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