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