1 /*
2  * Copyright 2018 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 "src/gpu/GrProxyProvider.h"
9 
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkImage.h"
12 #include "include/gpu/GrContext.h"
13 #include "include/gpu/GrTexture.h"
14 #include "include/private/GrImageContext.h"
15 #include "include/private/GrResourceKey.h"
16 #include "include/private/GrSingleOwner.h"
17 #include "include/private/SkImageInfoPriv.h"
18 #include "src/core/SkAutoPixmapStorage.h"
19 #include "src/core/SkImagePriv.h"
20 #include "src/core/SkMipMap.h"
21 #include "src/core/SkTraceEvent.h"
22 #include "src/gpu/GrCaps.h"
23 #include "src/gpu/GrContextPriv.h"
24 #include "src/gpu/GrImageContextPriv.h"
25 #include "src/gpu/GrRenderTarget.h"
26 #include "src/gpu/GrResourceProvider.h"
27 #include "src/gpu/GrSurfaceProxy.h"
28 #include "src/gpu/GrSurfaceProxyPriv.h"
29 #include "src/gpu/GrTextureProxyCacheAccess.h"
30 #include "src/gpu/GrTextureRenderTargetProxy.h"
31 #include "src/gpu/SkGr.h"
32 #include "src/image/SkImage_Base.h"
33 
34 #define ASSERT_SINGLE_OWNER \
35     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());)
36 
GrProxyProvider(GrImageContext * imageContext)37 GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
38 
~GrProxyProvider()39 GrProxyProvider::~GrProxyProvider() {
40     if (this->renderingDirectly()) {
41         // In DDL-mode a proxy provider can still have extant uniquely keyed proxies (since
42         // they need their unique keys to, potentially, find a cached resource when the
43         // DDL is played) but, in non-DDL-mode they should all have been cleaned up by this point.
44         SkASSERT(!fUniquelyKeyedProxies.count());
45     }
46 }
47 
assignUniqueKeyToProxy(const GrUniqueKey & key,GrTextureProxy * proxy)48 bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
49     ASSERT_SINGLE_OWNER
50     SkASSERT(key.isValid());
51     if (this->isAbandoned() || !proxy) {
52         return false;
53     }
54 
55 #ifdef SK_DEBUG
56     {
57         GrContext* direct = fImageContext->priv().asDirectContext();
58         if (direct) {
59             GrResourceCache* resourceCache = direct->priv().getResourceCache();
60             // If there is already a GrResource with this key then the caller has violated the
61             // normal usage pattern of uniquely keyed resources (e.g., they have created one w/o
62             // first seeing if it already existed in the cache).
63             SkASSERT(!resourceCache->findAndRefUniqueResource(key));
64         }
65     }
66 #endif
67 
68     SkASSERT(!fUniquelyKeyedProxies.find(key));     // multiple proxies can't get the same key
69 
70     proxy->cacheAccess().setUniqueKey(this, key);
71     SkASSERT(proxy->getUniqueKey() == key);
72     fUniquelyKeyedProxies.add(proxy);
73     return true;
74 }
75 
adoptUniqueKeyFromSurface(GrTextureProxy * proxy,const GrSurface * surf)76 void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
77     SkASSERT(surf->getUniqueKey().isValid());
78     proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
79     SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
80     // multiple proxies can't get the same key
81     SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
82     fUniquelyKeyedProxies.add(proxy);
83 }
84 
removeUniqueKeyFromProxy(GrTextureProxy * proxy)85 void GrProxyProvider::removeUniqueKeyFromProxy(GrTextureProxy* proxy) {
86     ASSERT_SINGLE_OWNER
87     SkASSERT(proxy);
88     SkASSERT(proxy->getUniqueKey().isValid());
89 
90     if (this->isAbandoned()) {
91         return;
92     }
93 
94     this->processInvalidUniqueKey(proxy->getUniqueKey(), proxy, InvalidateGPUResource::kYes);
95 }
96 
findProxyByUniqueKey(const GrUniqueKey & key,GrSurfaceOrigin origin)97 sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
98                                                             GrSurfaceOrigin origin) {
99     ASSERT_SINGLE_OWNER
100 
101     if (this->isAbandoned()) {
102         return nullptr;
103     }
104 
105     GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
106     if (proxy) {
107         SkASSERT(proxy->refCnt() >= 1);
108         SkASSERT(proxy->origin() == origin);
109         return sk_ref_sp(proxy);
110     }
111     return nullptr;
112 }
113 
114 ///////////////////////////////////////////////////////////////////////////////
115 
116 #if GR_TEST_UTILS
testingOnly_createInstantiatedProxy(const SkISize & size,GrColorType colorType,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)117 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
118         const SkISize& size,
119         GrColorType colorType,
120         const GrBackendFormat& format,
121         GrRenderable renderable,
122         int renderTargetSampleCnt,
123         GrSurfaceOrigin origin,
124         SkBackingFit fit,
125         SkBudgeted budgeted,
126         GrProtected isProtected) {
127     GrContext* direct = fImageContext->priv().asDirectContext();
128     if (!direct) {
129         return nullptr;
130     }
131 
132     if (this->caps()->isFormatCompressed(format)) {
133         // TODO: Allow this to go to GrResourceProvider::createCompressedTexture() once we no longer
134         // rely on GrColorType to get to GrPixelConfig. Currently this will cause
135         // makeConfigSpecific() to assert because GrColorTypeToPixelConfig() never returns a
136         // compressed GrPixelConfig.
137         return nullptr;
138     }
139     GrSurfaceDesc desc;
140     desc.fConfig = GrColorTypeToPixelConfig(colorType);
141     desc.fConfig = this->caps()->makeConfigSpecific(desc.fConfig, format);
142     desc.fWidth = size.width();
143     desc.fHeight = size.height();
144 
145     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
146     sk_sp<GrTexture> tex;
147 
148     if (SkBackingFit::kApprox == fit) {
149         tex = resourceProvider->createApproxTexture(desc, format, renderable, renderTargetSampleCnt,
150                                                     isProtected);
151     } else {
152         tex = resourceProvider->createTexture(desc, format, renderable, renderTargetSampleCnt,
153                                               GrMipMapped::kNo, budgeted, isProtected);
154     }
155     if (!tex) {
156         return nullptr;
157     }
158 
159     return this->createWrapped(std::move(tex), colorType, origin, UseAllocator::kYes);
160 }
161 
testingOnly_createInstantiatedProxy(const SkISize & size,GrColorType colorType,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected)162 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
163         const SkISize& size,
164         GrColorType colorType,
165         GrRenderable renderable,
166         int renderTargetSampleCnt,
167         GrSurfaceOrigin origin,
168         SkBackingFit fit,
169         SkBudgeted budgeted,
170         GrProtected isProtected) {
171     auto format = this->caps()->getDefaultBackendFormat(colorType, renderable);
172     return this->testingOnly_createInstantiatedProxy(size,
173                                                      colorType,
174                                                      format,
175                                                      renderable,
176                                                      renderTargetSampleCnt,
177                                                      origin,
178                                                      fit,
179                                                      budgeted,
180                                                      isProtected);
181 }
182 
testingOnly_createWrapped(sk_sp<GrTexture> tex,GrColorType colorType,GrSurfaceOrigin origin)183 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex,
184                                                                  GrColorType colorType,
185                                                                  GrSurfaceOrigin origin) {
186     return this->createWrapped(std::move(tex), colorType, origin, UseAllocator::kYes);
187 }
188 #endif
189 
createWrapped(sk_sp<GrTexture> tex,GrColorType colorType,GrSurfaceOrigin origin,UseAllocator useAllocator)190 sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex,
191                                                      GrColorType colorType,
192                                                      GrSurfaceOrigin origin,
193                                                      UseAllocator useAllocator) {
194 #ifdef SK_DEBUG
195     if (tex->getUniqueKey().isValid()) {
196         SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
197     }
198 #endif
199     GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(tex->backendFormat(), colorType);
200 
201     if (tex->asRenderTarget()) {
202         GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(tex->backendFormat(), colorType);
203         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
204                 std::move(tex), origin, texSwizzle, outSwizzle, useAllocator));
205     } else {
206         return sk_sp<GrTextureProxy>(
207                 new GrTextureProxy(std::move(tex), origin, texSwizzle, useAllocator));
208     }
209 }
210 
findOrCreateProxyByUniqueKey(const GrUniqueKey & key,GrColorType colorType,GrSurfaceOrigin origin,UseAllocator useAllocator)211 sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
212                                                                     GrColorType colorType,
213                                                                     GrSurfaceOrigin origin,
214                                                                     UseAllocator useAllocator) {
215     ASSERT_SINGLE_OWNER
216 
217     if (this->isAbandoned()) {
218         return nullptr;
219     }
220 
221     sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
222     if (result) {
223         return result;
224     }
225 
226     GrContext* direct = fImageContext->priv().asDirectContext();
227     if (!direct) {
228         return nullptr;
229     }
230 
231     GrResourceCache* resourceCache = direct->priv().getResourceCache();
232 
233     GrGpuResource* resource = resourceCache->findAndRefUniqueResource(key);
234     if (!resource) {
235         return nullptr;
236     }
237 
238     sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
239     SkASSERT(texture);
240 
241     result = this->createWrapped(std::move(texture), colorType, origin, useAllocator);
242     SkASSERT(result->getUniqueKey() == key);
243     // createWrapped should've added this for us
244     SkASSERT(fUniquelyKeyedProxies.find(key));
245     SkASSERT(result->textureSwizzle() ==
246              this->caps()->getTextureSwizzle(result->backendFormat(), colorType));
247     return result;
248 }
249 
createTextureProxy(sk_sp<SkImage> srcImage,int sampleCnt,SkBudgeted budgeted,SkBackingFit fit,GrInternalSurfaceFlags surfaceFlags)250 sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
251                                                           int sampleCnt,
252                                                           SkBudgeted budgeted,
253                                                           SkBackingFit fit,
254                                                           GrInternalSurfaceFlags surfaceFlags) {
255     ASSERT_SINGLE_OWNER
256     SkASSERT(srcImage);
257 
258     if (this->isAbandoned()) {
259         return nullptr;
260     }
261 
262     const SkImageInfo& info = srcImage->imageInfo();
263     GrColorType ct = SkColorTypeToGrColorType(info.colorType());
264 
265     GrBackendFormat format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
266 
267     if (!format.isValid()) {
268         SkBitmap copy8888;
269         if (!copy8888.tryAllocPixels(info.makeColorType(kRGBA_8888_SkColorType)) ||
270             !srcImage->readPixels(copy8888.pixmap(), 0, 0)) {
271             return nullptr;
272         }
273         copy8888.setImmutable();
274         srcImage = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
275         ct = GrColorType::kRGBA_8888;
276         format = this->caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
277         if (!format.isValid()) {
278             return nullptr;
279         }
280     }
281 
282     GrPixelConfig config = GrColorTypeToPixelConfig(ct);
283     if (kUnknown_GrPixelConfig == config) {
284         return nullptr;
285     }
286 
287     GrSurfaceDesc desc;
288     desc.fWidth = srcImage->width();
289     desc.fHeight = srcImage->height();
290     desc.fConfig = config;
291 
292     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
293             [desc, format, sampleCnt, budgeted, srcImage, fit,
294              ct](GrResourceProvider* resourceProvider) {
295                 SkPixmap pixMap;
296                 SkAssertResult(srcImage->peekPixels(&pixMap));
297                 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
298 
299                 return LazyCallbackResult(resourceProvider->createTexture(
300                         desc, format, ct, GrRenderable::kNo, sampleCnt, budgeted, fit,
301                         GrProtected::kNo, mipLevel));
302             },
303             format, desc, GrRenderable::kNo, sampleCnt, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
304             GrMipMapsStatus::kNotAllocated, surfaceFlags, fit, budgeted, GrProtected::kNo,
305             UseAllocator::kYes);
306 
307     if (!proxy) {
308         return nullptr;
309     }
310 
311     GrContext* direct = fImageContext->priv().asDirectContext();
312     if (direct) {
313         GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
314 
315         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
316         // we're better off instantiating the proxy immediately here.
317         if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
318             return nullptr;
319         }
320     }
321 
322     SkASSERT(proxy->width() == desc.fWidth);
323     SkASSERT(proxy->height() == desc.fHeight);
324     return proxy;
325 }
326 
createProxyFromBitmap(const SkBitmap & bitmap,GrMipMapped mipMapped)327 sk_sp<GrTextureProxy> GrProxyProvider::createProxyFromBitmap(const SkBitmap& bitmap,
328                                                              GrMipMapped mipMapped) {
329     ASSERT_SINGLE_OWNER
330     SkASSERT(GrMipMapped::kNo == mipMapped || this->caps()->mipMapSupport());
331 
332     if (this->isAbandoned()) {
333         return nullptr;
334     }
335 
336     if (!SkImageInfoIsValid(bitmap.info())) {
337         return nullptr;
338     }
339 
340     ATRACE_ANDROID_FRAMEWORK("Upload %sTexture [%ux%u]",
341                              GrMipMapped::kYes == mipMapped ? "MipMap " : "",
342                              bitmap.width(), bitmap.height());
343 
344     // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
345     // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
346     // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
347     SkCopyPixelsMode copyMode = this->renderingDirectly() ? kNever_SkCopyPixelsMode
348                                                           : kIfMutable_SkCopyPixelsMode;
349     sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
350     if (!baseLevel) {
351         return nullptr;
352     }
353 
354     // If mips weren't requested (or this was too small to have any), then take the fast path
355     if (GrMipMapped::kNo == mipMapped ||
356         0 == SkMipMap::ComputeLevelCount(baseLevel->width(), baseLevel->height())) {
357         return this->createTextureProxy(std::move(baseLevel), 1, SkBudgeted::kYes,
358                                         SkBackingFit::kExact);
359     }
360 
361     GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info());
362 
363     GrBackendFormat format = this->caps()->getDefaultBackendFormat(
364             SkColorTypeToGrColorType(bitmap.info().colorType()), GrRenderable::kNo);
365     if (!format.isValid()) {
366         SkBitmap copy8888;
367         if (!copy8888.tryAllocPixels(bitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
368             !bitmap.readPixels(copy8888.pixmap())) {
369             return nullptr;
370         }
371         copy8888.setImmutable();
372         baseLevel = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
373         desc.fConfig = kRGBA_8888_GrPixelConfig;
374         format = this->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kNo);
375         if (!format.isValid()) {
376             return nullptr;
377         }
378     }
379 
380     SkPixmap pixmap;
381     SkAssertResult(baseLevel->peekPixels(&pixmap));
382     sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, nullptr));
383     if (!mipmaps) {
384         return nullptr;
385     }
386 
387     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
388             [desc, format, baseLevel, mipmaps](GrResourceProvider* resourceProvider) {
389                 const int mipLevelCount = mipmaps->countLevels() + 1;
390                 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
391 
392                 SkPixmap pixmap;
393                 SkAssertResult(baseLevel->peekPixels(&pixmap));
394 
395                 texels[0].fPixels = pixmap.addr();
396                 texels[0].fRowBytes = pixmap.rowBytes();
397 
398                 auto colorType = SkColorTypeToGrColorType(pixmap.colorType());
399                 for (int i = 1; i < mipLevelCount; ++i) {
400                     SkMipMap::Level generatedMipLevel;
401                     mipmaps->getLevel(i - 1, &generatedMipLevel);
402                     texels[i].fPixels = generatedMipLevel.fPixmap.addr();
403                     texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
404                     SkASSERT(texels[i].fPixels);
405                     SkASSERT(generatedMipLevel.fPixmap.colorType() == pixmap.colorType());
406                 }
407                 return LazyCallbackResult(resourceProvider->createTexture(
408                         desc, format, colorType, GrRenderable::kNo, 1, SkBudgeted::kYes,
409                         GrProtected::kNo, texels.get(), mipLevelCount));
410             },
411             format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kYes,
412             GrMipMapsStatus::kValid, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact,
413             SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes);
414 
415     if (!proxy) {
416         return nullptr;
417     }
418 
419     GrContext* direct = fImageContext->priv().asDirectContext();
420     if (direct) {
421         GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
422         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
423         // we're better off instantiating the proxy immediately here.
424         if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
425             return nullptr;
426         }
427     }
428     return proxy;
429 }
430 
createProxy(const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrInternalSurfaceFlags surfaceFlags,GrSurfaceProxy::UseAllocator useAllocator)431 sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format,
432                                                    const GrSurfaceDesc& desc,
433                                                    GrRenderable renderable,
434                                                    int renderTargetSampleCnt,
435                                                    GrSurfaceOrigin origin,
436                                                    GrMipMapped mipMapped,
437                                                    SkBackingFit fit,
438                                                    SkBudgeted budgeted,
439                                                    GrProtected isProtected,
440                                                    GrInternalSurfaceFlags surfaceFlags,
441                                                    GrSurfaceProxy::UseAllocator useAllocator) {
442     const GrCaps* caps = this->caps();
443 
444     if (caps->isFormatCompressed(format)) {
445         // Deferred proxies for compressed textures are not supported.
446         return nullptr;
447     }
448 
449     GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
450 
451     SkASSERT(GrCaps::AreConfigsCompatible(desc.fConfig,
452                                           caps->getConfigFromBackendFormat(format, colorType)));
453 
454     if (GrMipMapped::kYes == mipMapped) {
455         // SkMipMap doesn't include the base level in the level count so we have to add 1
456         int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
457         if (1 == mipCount) {
458             mipMapped = GrMipMapped::kNo;
459         }
460     }
461 
462     if (!caps->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig, renderable,
463                                      renderTargetSampleCnt, mipMapped)) {
464         return nullptr;
465     }
466     GrSurfaceDesc copyDesc = desc;
467     GrMipMapsStatus mipMapsStatus = (GrMipMapped::kYes == mipMapped)
468             ? GrMipMapsStatus::kDirty
469             : GrMipMapsStatus::kNotAllocated;
470     GrSwizzle texSwizzle = caps->getTextureSwizzle(format, colorType);
471     if (renderable == GrRenderable::kYes) {
472         renderTargetSampleCnt =
473                 caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
474         SkASSERT(renderTargetSampleCnt);
475         // We know anything we instantiate later from this deferred path will be
476         // both texturable and renderable
477         GrSwizzle outSwizzle = caps->getOutputSwizzle(format, colorType);
478         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
479                 *caps, format, copyDesc, renderTargetSampleCnt, origin, mipMapped, mipMapsStatus,
480                 texSwizzle, outSwizzle, fit, budgeted, isProtected, surfaceFlags, useAllocator));
481     }
482 
483     return sk_sp<GrTextureProxy>(new GrTextureProxy(format, copyDesc, origin, mipMapped,
484                                                     mipMapsStatus, texSwizzle, fit, budgeted,
485                                                     isProtected, surfaceFlags, useAllocator));
486 }
487 
createCompressedTextureProxy(int width,int height,SkBudgeted budgeted,SkImage::CompressionType compressionType,sk_sp<SkData> data)488 sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
489         int width, int height, SkBudgeted budgeted, SkImage::CompressionType compressionType,
490         sk_sp<SkData> data) {
491 
492     GrSurfaceDesc desc;
493     desc.fConfig = GrCompressionTypePixelConfig(compressionType);
494     desc.fWidth = width;
495     desc.fHeight = height;
496 
497     GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
498 
499     if (!this->caps()->isFormatTexturable(format)) {
500         return nullptr;
501     }
502 
503     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
504             [width, height, format, compressionType, budgeted,
505              data](GrResourceProvider* resourceProvider) {
506                 return LazyCallbackResult(resourceProvider->createCompressedTexture(
507                         width, height, format, compressionType, budgeted, data.get()));
508             },
509             format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
510             GrMipMapsStatus::kNotAllocated, GrInternalSurfaceFlags::kNone, SkBackingFit::kExact,
511             SkBudgeted::kYes, GrProtected::kNo, UseAllocator::kYes);
512 
513     if (!proxy) {
514         return nullptr;
515     }
516 
517     GrContext* direct = fImageContext->priv().asDirectContext();
518     if (direct) {
519         GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
520         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
521         // we're better off instantiating the proxy immediately here.
522         if (!proxy->priv().doLazyInstantiation(resourceProvider)) {
523             return nullptr;
524         }
525     }
526     return proxy;
527 }
528 
wrapBackendTexture(const GrBackendTexture & backendTex,GrColorType grColorType,GrSurfaceOrigin origin,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType,ReleaseProc releaseProc,ReleaseContext releaseCtx)529 sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture& backendTex,
530                                                           GrColorType grColorType,
531                                                           GrSurfaceOrigin origin,
532                                                           GrWrapOwnership ownership,
533                                                           GrWrapCacheable cacheable,
534                                                           GrIOType ioType,
535                                                           ReleaseProc releaseProc,
536                                                           ReleaseContext releaseCtx) {
537     SkASSERT(ioType != kWrite_GrIOType);
538     if (this->isAbandoned()) {
539         return nullptr;
540     }
541 
542     // This is only supported on a direct GrContext.
543     GrContext* direct = fImageContext->priv().asDirectContext();
544     if (!direct) {
545         return nullptr;
546     }
547 
548     const GrCaps* caps = this->caps();
549 
550     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
551 
552     sk_sp<GrTexture> tex =
553             resourceProvider->wrapBackendTexture(backendTex, grColorType,
554                                                  ownership, cacheable, ioType);
555     if (!tex) {
556         return nullptr;
557     }
558 
559     if (releaseProc) {
560         tex->setRelease(releaseProc, releaseCtx);
561     }
562 
563     SkASSERT(!tex->asRenderTarget());  // Strictly a GrTexture
564     // Make sure we match how we created the proxy with SkBudgeted::kNo
565     SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
566 
567     GrSwizzle texSwizzle = caps->getTextureSwizzle(tex->backendFormat(), grColorType);
568 
569     return sk_sp<GrTextureProxy>(
570             new GrTextureProxy(std::move(tex), origin, texSwizzle, UseAllocator::kNo));
571 }
572 
wrapRenderableBackendTexture(const GrBackendTexture & backendTex,GrSurfaceOrigin origin,int sampleCnt,GrColorType colorType,GrWrapOwnership ownership,GrWrapCacheable cacheable,ReleaseProc releaseProc,ReleaseContext releaseCtx)573 sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
574         const GrBackendTexture& backendTex, GrSurfaceOrigin origin, int sampleCnt,
575         GrColorType colorType, GrWrapOwnership ownership, GrWrapCacheable cacheable,
576         ReleaseProc releaseProc, ReleaseContext releaseCtx) {
577     if (this->isAbandoned()) {
578         return nullptr;
579     }
580 
581     // This is only supported on a direct GrContext.
582     GrContext* direct = fImageContext->priv().asDirectContext();
583     if (!direct) {
584         return nullptr;
585     }
586 
587     const GrCaps* caps = this->caps();
588 
589     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
590 
591     // TODO: This should have been checked and validated before getting into GrProxyProvider.
592     if (!caps->isFormatAsColorTypeRenderable(colorType, backendTex.getBackendFormat(), sampleCnt)) {
593         return nullptr;
594     }
595 
596     sampleCnt = caps->getRenderTargetSampleCount(sampleCnt, backendTex.getBackendFormat());
597     SkASSERT(sampleCnt);
598 
599     sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture(backendTex, sampleCnt,
600                                                                           colorType, ownership,
601                                                                           cacheable);
602     if (!tex) {
603         return nullptr;
604     }
605 
606     if (releaseProc) {
607         tex->setRelease(releaseProc, releaseCtx);
608     }
609 
610     SkASSERT(tex->asRenderTarget());  // A GrTextureRenderTarget
611     // Make sure we match how we created the proxy with SkBudgeted::kNo
612     SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
613 
614     GrSwizzle texSwizzle = caps->getTextureSwizzle(tex->backendFormat(), colorType);
615     GrSwizzle outSwizzle = caps->getOutputSwizzle(tex->backendFormat(), colorType);
616 
617     return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin, texSwizzle,
618                                                                 outSwizzle, UseAllocator::kNo));
619 }
620 
wrapBackendRenderTarget(const GrBackendRenderTarget & backendRT,GrColorType grColorType,GrSurfaceOrigin origin,ReleaseProc releaseProc,ReleaseContext releaseCtx)621 sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
622         const GrBackendRenderTarget& backendRT, GrColorType grColorType,
623         GrSurfaceOrigin origin, ReleaseProc releaseProc, ReleaseContext releaseCtx) {
624     if (this->isAbandoned()) {
625         return nullptr;
626     }
627 
628     // This is only supported on a direct GrContext.
629     GrContext* direct = fImageContext->priv().asDirectContext();
630     if (!direct) {
631         return nullptr;
632     }
633 
634     const GrCaps* caps = this->caps();
635 
636     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
637 
638     sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT, grColorType);
639     if (!rt) {
640         return nullptr;
641     }
642 
643     if (releaseProc) {
644         rt->setRelease(releaseProc, releaseCtx);
645     }
646 
647     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
648     SkASSERT(!rt->getUniqueKey().isValid());
649     // Make sure we match how we created the proxy with SkBudgeted::kNo
650     SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
651 
652     GrSwizzle texSwizzle = caps->getTextureSwizzle(rt->backendFormat(), grColorType);
653     GrSwizzle outSwizzle = caps->getOutputSwizzle(rt->backendFormat(), grColorType);
654 
655     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), origin, texSwizzle,
656                                                               outSwizzle, UseAllocator::kNo));
657 }
658 
wrapBackendTextureAsRenderTarget(const GrBackendTexture & backendTex,GrColorType grColorType,GrSurfaceOrigin origin,int sampleCnt)659 sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendTextureAsRenderTarget(
660         const GrBackendTexture& backendTex, GrColorType grColorType,
661         GrSurfaceOrigin origin, int sampleCnt) {
662     if (this->isAbandoned()) {
663         return nullptr;
664     }
665 
666     // This is only supported on a direct GrContext.
667     GrContext* direct = fImageContext->priv().asDirectContext();
668     if (!direct) {
669         return nullptr;
670     }
671 
672     const GrCaps* caps = this->caps();
673 
674     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
675 
676     sk_sp<GrRenderTarget> rt =
677             resourceProvider->wrapBackendTextureAsRenderTarget(backendTex, sampleCnt, grColorType);
678     if (!rt) {
679         return nullptr;
680     }
681     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
682     SkASSERT(!rt->getUniqueKey().isValid());
683     // This proxy should be unbudgeted because we're just wrapping an external resource
684     SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
685 
686     GrSwizzle texSwizzle = caps->getTextureSwizzle(rt->backendFormat(), grColorType);
687     GrSwizzle outSwizzle = caps->getOutputSwizzle(rt->backendFormat(), grColorType);
688 
689     return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin, texSwizzle,
690                                                          outSwizzle, UseAllocator::kNo));
691 }
692 
wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)693 sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
694         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
695     if (this->isAbandoned()) {
696         return nullptr;
697     }
698 
699     // This is only supported on a direct GrContext.
700     GrContext* direct = fImageContext->priv().asDirectContext();
701     if (!direct) {
702         return nullptr;
703     }
704 
705     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
706 
707     sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
708                                                                                      vkInfo);
709     if (!rt) {
710         return nullptr;
711     }
712 
713     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
714     SkASSERT(!rt->getUniqueKey().isValid());
715     // This proxy should be unbudgeted because we're just wrapping an external resource
716     SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
717 
718     GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType());
719     GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(rt->backendFormat(), colorType);
720     GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(rt->backendFormat(), colorType);
721 
722     if (!this->caps()->isFormatAsColorTypeRenderable(colorType, rt->backendFormat(),
723                                                      rt->numSamples())) {
724         return nullptr;
725     }
726 
727     // All Vulkan surfaces uses top left origins.
728     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
729             std::move(rt), kTopLeft_GrSurfaceOrigin, texSwizzle, outSwizzle, UseAllocator::kNo,
730             GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
731 }
732 
createLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,GrRenderable renderable,int renderTargetSampleCnt,GrSurfaceOrigin origin,GrMipMapped mipMapped,GrMipMapsStatus mipMapsStatus,GrInternalSurfaceFlags surfaceFlags,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,GrSurfaceProxy::UseAllocator useAllocator)733 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
734                                                        const GrBackendFormat& format,
735                                                        const GrSurfaceDesc& desc,
736                                                        GrRenderable renderable,
737                                                        int renderTargetSampleCnt,
738                                                        GrSurfaceOrigin origin,
739                                                        GrMipMapped mipMapped,
740                                                        GrMipMapsStatus mipMapsStatus,
741                                                        GrInternalSurfaceFlags surfaceFlags,
742                                                        SkBackingFit fit,
743                                                        SkBudgeted budgeted,
744                                                        GrProtected isProtected,
745                                                        GrSurfaceProxy::UseAllocator useAllocator) {
746     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
747              (desc.fWidth > 0 && desc.fHeight > 0));
748 
749     if (!format.isValid()) {
750         return nullptr;
751     }
752 
753     if (desc.fWidth > this->caps()->maxTextureSize() ||
754         desc.fHeight > this->caps()->maxTextureSize()) {
755         return nullptr;
756     }
757 
758     GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
759     GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(format, colorType);
760     GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(format, colorType);
761 
762     if (renderable == GrRenderable::kYes) {
763         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*this->caps(),
764                                                                     std::move(callback),
765                                                                     format,
766                                                                     desc,
767                                                                     renderTargetSampleCnt,
768                                                                     origin,
769                                                                     mipMapped,
770                                                                     mipMapsStatus,
771                                                                     texSwizzle,
772                                                                     outSwizzle,
773                                                                     fit,
774                                                                     budgeted,
775                                                                     isProtected,
776                                                                     surfaceFlags,
777                                                                     useAllocator));
778     } else {
779         return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
780                                                         format,
781                                                         desc,
782                                                         origin,
783                                                         mipMapped,
784                                                         mipMapsStatus,
785                                                         texSwizzle,
786                                                         fit,
787                                                         budgeted,
788                                                         isProtected,
789                                                         surfaceFlags,
790                                                         useAllocator));
791     }
792 }
793 
createLazyRenderTargetProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,const GrSurfaceDesc & desc,int sampleCnt,GrSurfaceOrigin origin,GrInternalSurfaceFlags surfaceFlags,const TextureInfo * textureInfo,GrMipMapsStatus mipMapsStatus,SkBackingFit fit,SkBudgeted budgeted,GrProtected isProtected,bool wrapsVkSecondaryCB,UseAllocator useAllocator)794 sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
795         LazyInstantiateCallback&& callback,
796         const GrBackendFormat& format,
797         const GrSurfaceDesc& desc,
798         int sampleCnt,
799         GrSurfaceOrigin origin,
800         GrInternalSurfaceFlags surfaceFlags,
801         const TextureInfo* textureInfo,
802         GrMipMapsStatus mipMapsStatus,
803         SkBackingFit fit,
804         SkBudgeted budgeted,
805         GrProtected isProtected,
806         bool wrapsVkSecondaryCB,
807         UseAllocator useAllocator) {
808     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
809              (desc.fWidth > 0 && desc.fHeight > 0));
810 
811     if (desc.fWidth > this->caps()->maxRenderTargetSize() ||
812         desc.fHeight > this->caps()->maxRenderTargetSize()) {
813         return nullptr;
814     }
815 
816     GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
817     GrSwizzle texSwizzle = this->caps()->getTextureSwizzle(format, colorType);
818     GrSwizzle outSwizzle = this->caps()->getOutputSwizzle(format, colorType);
819 
820     if (textureInfo) {
821         // Wrapped vulkan secondary command buffers don't support texturing since we won't have an
822         // actual VkImage to texture from.
823         SkASSERT(!wrapsVkSecondaryCB);
824         return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
825                 *this->caps(), std::move(callback), format, desc, sampleCnt, origin,
826                 textureInfo->fMipMapped, mipMapsStatus, texSwizzle, outSwizzle, fit, budgeted,
827                 isProtected, surfaceFlags, useAllocator));
828     }
829 
830     GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
831             wrapsVkSecondaryCB ? GrRenderTargetProxy::WrapsVkSecondaryCB::kYes
832                                : GrRenderTargetProxy::WrapsVkSecondaryCB::kNo;
833 
834     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(
835             std::move(callback), format, desc, sampleCnt, origin, texSwizzle, outSwizzle, fit,
836             budgeted, isProtected, surfaceFlags, useAllocator, vkSCB));
837 }
838 
MakeFullyLazyProxy(LazyInstantiateCallback && callback,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,GrProtected isProtected,GrSurfaceOrigin origin,GrPixelConfig config,const GrCaps & caps,UseAllocator useAllocator)839 sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallback&& callback,
840                                                           const GrBackendFormat& format,
841                                                           GrRenderable renderable,
842                                                           int renderTargetSampleCnt,
843                                                           GrProtected isProtected,
844                                                           GrSurfaceOrigin origin,
845                                                           GrPixelConfig config,
846                                                           const GrCaps& caps,
847                                                           UseAllocator useAllocator) {
848     if (!format.isValid()) {
849         return nullptr;
850     }
851 
852     SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes);
853     GrSurfaceDesc desc;
854     GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
855     desc.fWidth = -1;
856     desc.fHeight = -1;
857     desc.fConfig = config;
858 
859     GrColorType colorType = GrPixelConfigToColorType(desc.fConfig);
860     GrSwizzle texSwizzle = caps.getTextureSwizzle(format, colorType);
861     GrSwizzle outSwizzle = caps.getOutputSwizzle(format, colorType);
862 
863     if (GrRenderable::kYes == renderable) {
864         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
865                 caps, std::move(callback), format, desc, renderTargetSampleCnt, origin,
866                 GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, texSwizzle, outSwizzle,
867                 SkBackingFit::kApprox, SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator));
868     } else {
869         return sk_sp<GrTextureProxy>(new GrTextureProxy(
870                 std::move(callback), format, desc, origin, GrMipMapped::kNo,
871                 GrMipMapsStatus::kNotAllocated, texSwizzle, SkBackingFit::kApprox, SkBudgeted::kYes,
872                 isProtected, surfaceFlags, useAllocator));
873     }
874 }
875 
IsFunctionallyExact(GrSurfaceProxy * proxy)876 bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
877     const bool isInstantiated = proxy->isInstantiated();
878     // A proxy is functionally exact if:
879     //   it is exact (obvs)
880     //   when it is instantiated it will be exact (i.e., power of two dimensions)
881     //   it is already instantiated and the proxy covers the entire backing surface
882     return proxy->priv().isExact() ||
883            (!isInstantiated && SkIsPow2(proxy->width()) && SkIsPow2(proxy->height())) ||
884            (isInstantiated && proxy->worstCaseWidth() == proxy->width() &&
885                               proxy->worstCaseHeight() == proxy->height());
886 }
887 
processInvalidUniqueKey(const GrUniqueKey & key,GrTextureProxy * proxy,InvalidateGPUResource invalidateGPUResource)888 void GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
889                                               InvalidateGPUResource invalidateGPUResource) {
890     SkASSERT(key.isValid());
891 
892     if (!proxy) {
893         proxy = fUniquelyKeyedProxies.find(key);
894     }
895     SkASSERT(!proxy || proxy->getUniqueKey() == key);
896 
897     // Locate the corresponding GrGpuResource (if it needs to be invalidated) before clearing the
898     // proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
899     sk_sp<GrGpuResource> invalidGpuResource;
900     if (InvalidateGPUResource::kYes == invalidateGPUResource) {
901         GrContext* direct = fImageContext->priv().asDirectContext();
902         if (direct) {
903             GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
904             invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
905         }
906         SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
907     }
908 
909     // Note: this method is called for the whole variety of GrGpuResources so often 'key'
910     // will not be in 'fUniquelyKeyedProxies'.
911     if (proxy) {
912         fUniquelyKeyedProxies.remove(key);
913         proxy->cacheAccess().clearUniqueKey();
914     }
915 
916     if (invalidGpuResource) {
917         invalidGpuResource->resourcePriv().removeUniqueKey();
918     }
919 }
920 
contextID() const921 uint32_t GrProxyProvider::contextID() const {
922     return fImageContext->priv().contextID();
923 }
924 
caps() const925 const GrCaps* GrProxyProvider::caps() const {
926     return fImageContext->priv().caps();
927 }
928 
refCaps() const929 sk_sp<const GrCaps> GrProxyProvider::refCaps() const {
930     return fImageContext->priv().refCaps();
931 }
932 
isAbandoned() const933 bool GrProxyProvider::isAbandoned() const {
934     return fImageContext->priv().abandoned();
935 }
936 
orphanAllUniqueKeys()937 void GrProxyProvider::orphanAllUniqueKeys() {
938     UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
939     for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
940         GrTextureProxy& tmp = *iter;
941 
942         tmp.fProxyProvider = nullptr;
943     }
944 }
945 
removeAllUniqueKeys()946 void GrProxyProvider::removeAllUniqueKeys() {
947     UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
948     for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
949         GrTextureProxy& tmp = *iter;
950 
951         this->processInvalidUniqueKey(tmp.getUniqueKey(), &tmp, InvalidateGPUResource::kNo);
952     }
953     SkASSERT(!fUniquelyKeyedProxies.count());
954 }
955 
renderingDirectly() const956 bool GrProxyProvider::renderingDirectly() const {
957     return fImageContext->priv().asDirectContext();
958 }
959