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