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