• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrVkTexture.h"
9 #include "GrVkGpu.h"
10 #include "GrVkImageView.h"
11 #include "GrTexturePriv.h"
12 #include "GrVkTextureRenderTarget.h"
13 #include "GrVkUtil.h"
14 
15 #include "vk/GrVkTypes.h"
16 
17 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
18 
19 // This method parallels GrTextureProxy::highestFilterMode
highest_filter_mode(GrPixelConfig config)20 static inline GrSamplerParams::FilterMode highest_filter_mode(GrPixelConfig config) {
21     if (GrPixelConfigIsSint(config)) {
22         // We only ever want to nearest-neighbor sample signed int textures.
23         return GrSamplerParams::kNone_FilterMode;
24     }
25     return GrSamplerParams::kMipMap_FilterMode;
26 }
27 
28 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrVkTexture(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * view)29 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
30                          SkBudgeted budgeted,
31                          const GrSurfaceDesc& desc,
32                          const GrVkImageInfo& info,
33                          const GrVkImageView* view)
34     : GrSurface(gpu, desc)
35     , GrVkImage(info, GrVkImage::kNot_Wrapped)
36     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
37                 info.fLevelCount > 1)
38     , fTextureView(view)
39     , fLinearTextureView(nullptr) {
40     this->registerWithCache(budgeted);
41 }
42 
GrVkTexture(GrVkGpu * gpu,Wrapped,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * view,GrVkImage::Wrapped wrapped)43 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
44                          Wrapped,
45                          const GrSurfaceDesc& desc,
46                          const GrVkImageInfo& info,
47                          const GrVkImageView* view,
48                          GrVkImage::Wrapped wrapped)
49     : GrSurface(gpu, desc)
50     , GrVkImage(info, wrapped)
51     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
52                 info.fLevelCount > 1)
53     , fTextureView(view)
54     , fLinearTextureView(nullptr) {
55     this->registerWithCacheWrapped();
56 }
57 
58 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrVkTexture(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * view,GrVkImage::Wrapped wrapped)59 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
60                          const GrSurfaceDesc& desc,
61                          const GrVkImageInfo& info,
62                          const GrVkImageView* view,
63                          GrVkImage::Wrapped wrapped)
64     : GrSurface(gpu, desc)
65     , GrVkImage(info, wrapped)
66     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
67                 info.fLevelCount > 1)
68     , fTextureView(view)
69     , fLinearTextureView(nullptr) {
70 }
71 
CreateNewTexture(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImage::ImageDesc & imageDesc)72 sk_sp<GrVkTexture> GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
73                                                  const GrSurfaceDesc& desc,
74                                                  const GrVkImage::ImageDesc& imageDesc) {
75     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
76 
77     GrVkImageInfo info;
78     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
79         return nullptr;
80     }
81 
82     const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
83                                                            GrVkImageView::kColor_Type,
84                                                            info.fLevelCount);
85     if (!imageView) {
86         GrVkImage::DestroyImageInfo(gpu, &info);
87         return nullptr;
88     }
89 
90     return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, imageView));
91 }
92 
MakeWrappedTexture(GrVkGpu * gpu,const GrSurfaceDesc & desc,GrWrapOwnership ownership,const GrVkImageInfo * info)93 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
94                                                    const GrSurfaceDesc& desc,
95                                                    GrWrapOwnership ownership,
96                                                    const GrVkImageInfo* info) {
97     SkASSERT(info);
98     // Wrapped textures require both image and allocation (because they can be mapped)
99     SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
100 
101     const GrVkImageView* imageView = GrVkImageView::Create(gpu, info->fImage, info->fFormat,
102                                                            GrVkImageView::kColor_Type,
103                                                            info->fLevelCount);
104     if (!imageView) {
105         return nullptr;
106     }
107 
108     GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership
109             ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped;
110     return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped));
111 }
112 
~GrVkTexture()113 GrVkTexture::~GrVkTexture() {
114     // either release or abandon should have been called by the owner of this object.
115     SkASSERT(!fTextureView);
116     SkASSERT(!fLinearTextureView);
117 }
118 
onRelease()119 void GrVkTexture::onRelease() {
120     // we create this and don't hand it off, so we should always destroy it
121     if (fTextureView) {
122         fTextureView->unref(this->getVkGpu());
123         fTextureView = nullptr;
124     }
125 
126     if (fLinearTextureView) {
127         fLinearTextureView->unref(this->getVkGpu());
128         fLinearTextureView = nullptr;
129     }
130 
131     this->releaseImage(this->getVkGpu());
132 
133     INHERITED::onRelease();
134 }
135 
onAbandon()136 void GrVkTexture::onAbandon() {
137     if (fTextureView) {
138         fTextureView->unrefAndAbandon();
139         fTextureView = nullptr;
140     }
141 
142     if (fLinearTextureView) {
143         fLinearTextureView->unrefAndAbandon();
144         fLinearTextureView = nullptr;
145     }
146 
147     this->abandonImage();
148     INHERITED::onAbandon();
149 }
150 
getTextureHandle() const151 GrBackendObject GrVkTexture::getTextureHandle() const {
152     return (GrBackendObject)&fInfo;
153 }
154 
getVkGpu() const155 GrVkGpu* GrVkTexture::getVkGpu() const {
156     SkASSERT(!this->wasDestroyed());
157     return static_cast<GrVkGpu*>(this->getGpu());
158 }
159 
textureView(bool allowSRGB)160 const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
161     VkFormat linearFormat;
162     if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
163         return fTextureView;
164     }
165 
166     if (!fLinearTextureView) {
167         fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
168                                                    linearFormat, GrVkImageView::kColor_Type,
169                                                    fInfo.fLevelCount);
170         SkASSERT(fLinearTextureView);
171     }
172 
173     return fLinearTextureView;
174 }
175 
reallocForMipmap(GrVkGpu * gpu,uint32_t mipLevels)176 bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
177     if (mipLevels == 1) {
178         // don't need to do anything for a 1x1 texture
179         return false;
180     }
181 
182     const GrVkResource* oldResource = this->resource();
183 
184     // We shouldn't realloc something that doesn't belong to us
185     if (fIsBorrowed) {
186         return false;
187     }
188 
189     bool renderTarget = SkToBool(this->asRenderTarget());
190 
191     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
192     if (renderTarget) {
193         usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
194     }
195     usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
196 
197     GrVkImage::ImageDesc imageDesc;
198     imageDesc.fImageType = VK_IMAGE_TYPE_2D;
199     imageDesc.fFormat = fInfo.fFormat;
200     imageDesc.fWidth = this->width();
201     imageDesc.fHeight = this->height();
202     imageDesc.fLevels = mipLevels;
203     imageDesc.fSamples = 1;
204     imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
205     imageDesc.fUsageFlags = usageFlags;
206     imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
207 
208     GrVkImageInfo info;
209     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
210         return false;
211     }
212 
213     // have to create a new image view for new resource
214     const GrVkImageView* oldView = fTextureView;
215     VkImage image = info.fImage;
216     const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
217                                                              GrVkImageView::kColor_Type, mipLevels);
218     if (!textureView) {
219         GrVkImage::DestroyImageInfo(gpu, &info);
220         return false;
221     }
222 
223     if (renderTarget) {
224         GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
225         if (!texRT->updateForMipmap(gpu, info)) {
226             GrVkImage::DestroyImageInfo(gpu, &info);
227             return false;
228         }
229     }
230 
231     oldResource->unref(gpu);
232     oldView->unref(gpu);
233     if (fLinearTextureView) {
234         fLinearTextureView->unref(gpu);
235         fLinearTextureView = nullptr;
236     }
237 
238     this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
239     fTextureView = textureView;
240     fInfo = info;
241     this->texturePriv().setMaxMipMapLevel(mipLevels);
242 
243     return true;
244 }
245