Home | History | Annotate | Download | only in gpu
      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 "GrProxyProvider.h"
      9 
     10 #include "GrCaps.h"
     11 #include "GrRenderTarget.h"
     12 #include "GrResourceKey.h"
     13 #include "GrResourceProvider.h"
     14 #include "GrSurfaceProxy.h"
     15 #include "GrSurfaceProxyPriv.h"
     16 #include "GrTexture.h"
     17 #include "GrTextureProxyCacheAccess.h"
     18 #include "GrTextureRenderTargetProxy.h"
     19 #include "../private/GrSingleOwner.h"
     20 #include "SkBitmap.h"
     21 #include "SkGr.h"
     22 #include "SkImage.h"
     23 #include "SkImage_Base.h"
     24 #include "SkImageInfoPriv.h"
     25 #include "SkImagePriv.h"
     26 #include "SkMipMap.h"
     27 #include "SkTraceEvent.h"
     28 
     29 #define ASSERT_SINGLE_OWNER \
     30     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
     31 
     32 GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider,
     33                                  GrResourceCache* resourceCache,
     34                                  sk_sp<const GrCaps> caps,
     35                                  GrSingleOwner* owner)
     36         : fResourceProvider(resourceProvider)
     37         , fResourceCache(resourceCache)
     38         , fAbandoned(false)
     39         , fCaps(caps)
     40 #ifdef SK_DEBUG
     41         , fSingleOwner(owner)
     42 #endif
     43 {
     44 
     45 }
     46 
     47 GrProxyProvider::~GrProxyProvider() {
     48     SkASSERT(!fUniquelyKeyedProxies.count());
     49 }
     50 
     51 bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
     52     ASSERT_SINGLE_OWNER
     53     SkASSERT(key.isValid());
     54     if (this->isAbandoned() || !proxy) {
     55         return false;
     56     }
     57 
     58     // If there is already a GrResource with this key then the caller has violated the normal
     59     // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
     60     // if it already existed in the cache).
     61     SkASSERT(!fResourceCache || !fResourceCache->findAndRefUniqueResource(key));
     62 
     63     // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
     64     // resources are a special case: the unique keys give us a weak ref so that we can reuse the
     65     // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
     66     // it will always be released - it is never converted to a scratch resource.
     67     if (SkBudgeted::kNo == proxy->isBudgeted() &&
     68                     (!proxy->priv().isInstantiated() ||
     69                      !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
     70         return false;
     71     }
     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 
     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 
     90 void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
     91     ASSERT_SINGLE_OWNER
     92     if (this->isAbandoned() || !proxy) {
     93         return;
     94     }
     95     this->processInvalidProxyUniqueKey(key, proxy, true);
     96 }
     97 
     98 sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
     99                                                             GrSurfaceOrigin origin) {
    100     ASSERT_SINGLE_OWNER
    101 
    102     if (this->isAbandoned()) {
    103         return nullptr;
    104     }
    105 
    106     sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
    107     if (result) {
    108         SkASSERT(result->origin() == origin);
    109     }
    110     return result;
    111 }
    112 
    113 sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin) {
    114 #ifdef SK_DEBUG
    115     if (tex->getUniqueKey().isValid()) {
    116         SkASSERT(!this->findProxyByUniqueKey(tex->getUniqueKey(), origin));
    117     }
    118 #endif
    119 
    120     if (tex->asRenderTarget()) {
    121         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin));
    122     } else {
    123         return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin));
    124     }
    125 }
    126 
    127 sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
    128                                                                     GrSurfaceOrigin origin) {
    129     ASSERT_SINGLE_OWNER
    130 
    131     if (this->isAbandoned()) {
    132         return nullptr;
    133     }
    134 
    135     sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
    136     if (result) {
    137         return result;
    138     }
    139 
    140     if (!fResourceCache) {
    141         return nullptr;
    142     }
    143 
    144     GrGpuResource* resource = fResourceCache->findAndRefUniqueResource(key);
    145     if (!resource) {
    146         return nullptr;
    147     }
    148 
    149     sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
    150     SkASSERT(texture);
    151 
    152     result = this->createWrapped(std::move(texture), origin);
    153     SkASSERT(result->getUniqueKey() == key);
    154     // createWrapped should've added this for us
    155     SkASSERT(fUniquelyKeyedProxies.find(key));
    156     return result;
    157 }
    158 
    159 sk_sp<GrTextureProxy> GrProxyProvider::createInstantiatedProxy(const GrSurfaceDesc& desc,
    160                                                                SkBackingFit fit,
    161                                                                SkBudgeted budgeted,
    162                                                                uint32_t flags) {
    163     sk_sp<GrTexture> tex;
    164 
    165     if (SkBackingFit::kApprox == fit) {
    166         tex = fResourceProvider->createApproxTexture(desc, flags);
    167     } else {
    168         tex = fResourceProvider->createTexture(desc, budgeted, flags);
    169     }
    170     if (!tex) {
    171         return nullptr;
    172     }
    173 
    174     return this->createWrapped(std::move(tex), desc.fOrigin);
    175 }
    176 
    177 sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(const GrSurfaceDesc& desc,
    178                                                           SkBudgeted budgeted,
    179                                                           const void* srcData, size_t rowBytes) {
    180     ASSERT_SINGLE_OWNER
    181 
    182     if (this->isAbandoned()) {
    183         return nullptr;
    184     }
    185 
    186     if (srcData) {
    187         GrMipLevel mipLevel = { srcData, rowBytes };
    188 
    189         sk_sp<GrTexture> tex = fResourceProvider->createTexture(desc, budgeted,
    190                                                                 SkBackingFit::kExact, mipLevel);
    191         if (!tex) {
    192             return nullptr;
    193         }
    194 
    195         return this->createWrapped(std::move(tex), desc.fOrigin);
    196     }
    197 
    198     return this->createProxy(desc, SkBackingFit::kExact, budgeted);
    199 }
    200 
    201 sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(sk_sp<SkImage> srcImage,
    202                                                           GrSurfaceFlags flags,
    203                                                           GrSurfaceOrigin origin,
    204                                                           int sampleCnt,
    205                                                           SkBudgeted budgeted,
    206                                                           SkBackingFit fit) {
    207     ASSERT_SINGLE_OWNER
    208     SkASSERT(srcImage);
    209 
    210     if (this->isAbandoned()) {
    211         return nullptr;
    212     }
    213 
    214     GrPixelConfig config = SkImageInfo2GrPixelConfig(as_IB(srcImage)->onImageInfo(),
    215                                                      *this->caps());
    216 
    217     if (kUnknown_GrPixelConfig == config) {
    218         return nullptr;
    219     }
    220 
    221     if (SkToBool(flags & kRenderTarget_GrSurfaceFlag)) {
    222         sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, config);
    223         if (!sampleCnt) {
    224             return nullptr;
    225         }
    226     }
    227 
    228     GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
    229     if (SkToBool(flags & kRenderTarget_GrSurfaceFlag)) {
    230         if (fCaps->usesMixedSamples() && sampleCnt > 1) {
    231             renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
    232         }
    233         if (fCaps->maxWindowRectangles() > 0) {
    234             renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
    235         }
    236     }
    237 
    238     GrSurfaceDesc desc;
    239     desc.fWidth = srcImage->width();
    240     desc.fHeight = srcImage->height();
    241     desc.fFlags = flags;
    242     desc.fOrigin = origin;
    243     desc.fSampleCnt = sampleCnt;
    244     desc.fConfig = config;
    245 
    246     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
    247             [desc, budgeted, srcImage, fit]
    248             (GrResourceProvider* resourceProvider) {
    249                 if (!resourceProvider) {
    250                     // Nothing to clean up here. Once the proxy (and thus lambda) is deleted the ref
    251                     // on srcImage will be released.
    252                     return sk_sp<GrTexture>();
    253                 }
    254                 SkPixmap pixMap;
    255                 SkAssertResult(srcImage->peekPixels(&pixMap));
    256                 GrMipLevel mipLevel = { pixMap.addr(), pixMap.rowBytes() };
    257 
    258                 return resourceProvider->createTexture(desc, budgeted, fit, mipLevel);
    259             }, desc, GrMipMapped::kNo, renderTargetFlags, fit, budgeted);
    260 
    261     if (fResourceProvider) {
    262         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
    263         // we're better off instantiating the proxy immediately here.
    264         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    265             return nullptr;
    266         }
    267     }
    268     return proxy;
    269 }
    270 
    271 sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxy(const GrSurfaceDesc& desc,
    272                                                          SkBudgeted budgeted) {
    273     ASSERT_SINGLE_OWNER
    274 
    275     if (this->isAbandoned()) {
    276         return nullptr;
    277     }
    278 
    279     return this->createProxy(desc, GrMipMapped::kYes, SkBackingFit::kExact, budgeted, 0);
    280 }
    281 
    282 sk_sp<GrTextureProxy> GrProxyProvider::createMipMapProxyFromBitmap(const SkBitmap& bitmap,
    283                                                                    SkColorSpace* dstColorSpace) {
    284     SkDestinationSurfaceColorMode mipColorMode = dstColorSpace
    285         ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
    286         : SkDestinationSurfaceColorMode::kLegacy;
    287 
    288     if (!SkImageInfoIsValid(bitmap.info(), mipColorMode)) {
    289         return nullptr;
    290     }
    291 
    292     SkPixmap pixmap;
    293     if (!bitmap.peekPixels(&pixmap)) {
    294         return nullptr;
    295     }
    296 
    297     ATRACE_ANDROID_FRAMEWORK("Upload MipMap Texture [%ux%u]", pixmap.width(), pixmap.height());
    298     sk_sp<SkMipMap> mipmaps(SkMipMap::Build(pixmap, mipColorMode, nullptr));
    299     if (!mipmaps) {
    300         return nullptr;
    301     }
    302 
    303     if (mipmaps->countLevels() < 0) {
    304         return nullptr;
    305     }
    306 
    307     // In non-ddl we will always instantiate right away. Thus we never want to copy the SkBitmap
    308     // even if its mutable. In ddl, if the bitmap is mutable then we must make a copy since the
    309     // upload of the data to the gpu can happen at anytime and the bitmap may change by then.
    310     SkCopyPixelsMode copyMode = this->mutableBitmapsNeedCopy() ? kIfMutable_SkCopyPixelsMode
    311                                                                : kNever_SkCopyPixelsMode;
    312     sk_sp<SkImage> baseLevel = SkMakeImageFromRasterBitmap(bitmap, copyMode);
    313 
    314     if (!baseLevel) {
    315         return nullptr;
    316     }
    317 
    318     GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *this->caps());
    319 
    320     if (0 == mipmaps->countLevels()) {
    321         return this->createTextureProxy(baseLevel, kNone_GrSurfaceFlags, kTopLeft_GrSurfaceOrigin,
    322                                         1, SkBudgeted::kYes, SkBackingFit::kExact);
    323 
    324     }
    325 
    326     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
    327             [desc, baseLevel, mipmaps, mipColorMode]
    328             (GrResourceProvider* resourceProvider) {
    329                 if (!resourceProvider) {
    330                     return sk_sp<GrTexture>();
    331                 }
    332 
    333                 const int mipLevelCount = mipmaps->countLevels() + 1;
    334                 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
    335 
    336                 SkPixmap pixmap;
    337                 SkAssertResult(baseLevel->peekPixels(&pixmap));
    338 
    339                 // DDL TODO: Instead of copying all this info into GrMipLevels we should just plumb
    340                 // the use of SkMipMap down through Ganesh.
    341                 texels[0].fPixels = pixmap.addr();
    342                 texels[0].fRowBytes = pixmap.rowBytes();
    343 
    344                 for (int i = 1; i < mipLevelCount; ++i) {
    345                     SkMipMap::Level generatedMipLevel;
    346                     mipmaps->getLevel(i - 1, &generatedMipLevel);
    347                     texels[i].fPixels = generatedMipLevel.fPixmap.addr();
    348                     texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
    349                     SkASSERT(texels[i].fPixels);
    350                 }
    351 
    352                 return resourceProvider->createTexture(desc, SkBudgeted::kYes, texels.get(),
    353                                                        mipLevelCount, mipColorMode);
    354             }, desc, GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes);
    355 
    356     if (fResourceProvider) {
    357         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however
    358         // we're better off instantiating the proxy immediately here.
    359         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    360             return nullptr;
    361         }
    362     }
    363     return proxy;
    364 }
    365 
    366 sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrSurfaceDesc& desc,
    367                                                    GrMipMapped mipMapped,
    368                                                    SkBackingFit fit,
    369                                                    SkBudgeted budgeted,
    370                                                    uint32_t flags) {
    371     SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
    372 
    373     if (GrMipMapped::kYes == mipMapped) {
    374         // SkMipMap doesn't include the base level in the level count so we have to add 1
    375         int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
    376         if (1 == mipCount) {
    377             mipMapped = GrMipMapped::kNo;
    378         }
    379     }
    380 
    381     if (!this->caps()->validateSurfaceDesc(desc, mipMapped)) {
    382         return nullptr;
    383     }
    384     GrSurfaceDesc copyDesc = desc;
    385     if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
    386         copyDesc.fSampleCnt =
    387                 this->caps()->getRenderTargetSampleCount(desc.fSampleCnt, desc.fConfig);
    388     }
    389 
    390     if (copyDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
    391         // We know anything we instantiate later from this deferred path will be
    392         // both texturable and renderable
    393         return sk_sp<GrTextureProxy>(
    394                 new GrTextureRenderTargetProxy(*this->caps(), copyDesc, mipMapped, fit, budgeted,
    395                                                flags));
    396     }
    397 
    398     return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, mipMapped, fit, budgeted, nullptr, 0,
    399                                                     flags));
    400 }
    401 
    402 sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(
    403                                                          const GrBackendTexture& backendTex,
    404                                                          GrSurfaceOrigin origin,
    405                                                          GrWrapOwnership ownership,
    406                                                          ReleaseProc releaseProc,
    407                                                          ReleaseContext releaseCtx) {
    408     if (this->isAbandoned()) {
    409         return nullptr;
    410     }
    411 
    412     GrSurfaceDesc desc;
    413     desc.fOrigin = origin;
    414     desc.fWidth = backendTex.width();
    415     desc.fHeight = backendTex.height();
    416     desc.fConfig = backendTex.config();
    417     GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
    418 
    419     sk_sp<GrReleaseProcHelper> releaseHelper;
    420     if (releaseProc) {
    421         releaseHelper.reset(new GrReleaseProcHelper(releaseProc, releaseCtx));
    422     }
    423 
    424     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
    425             [backendTex, ownership, releaseHelper]
    426             (GrResourceProvider* resourceProvider) {
    427                 if (!resourceProvider) {
    428                     // If this had a releaseHelper it will get unrefed when we delete this lambda
    429                     // and will call the release proc so that the client knows they can free the
    430                     // underlying backend object.
    431                     return sk_sp<GrTexture>();
    432                 }
    433 
    434                 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(backendTex,
    435                                                                             ownership);
    436                 if (!tex) {
    437                     return sk_sp<GrTexture>();
    438                 }
    439                 if (releaseHelper) {
    440                     // This gives the texture a ref on the releaseHelper
    441                     tex->setRelease(releaseHelper);
    442                 }
    443                 SkASSERT(!tex->asRenderTarget());   // Strictly a GrTexture
    444                 // Make sure we match how we created the proxy with SkBudgeted::kNo
    445                 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
    446 
    447                 return tex;
    448             }, desc, mipMapped, SkBackingFit::kExact, SkBudgeted::kNo);
    449 
    450     if (fResourceProvider) {
    451         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
    452         // we're better off instantiating the proxy immediately here.
    453         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    454             return nullptr;
    455         }
    456     }
    457     return proxy;
    458 }
    459 
    460 sk_sp<GrTextureProxy> GrProxyProvider::createWrappedTextureProxy(const GrBackendTexture& backendTex,
    461                                                                  GrSurfaceOrigin origin,
    462                                                                  int sampleCnt) {
    463     if (this->isAbandoned()) {
    464         return nullptr;
    465     }
    466 
    467     sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config());
    468     if (!sampleCnt) {
    469         return nullptr;
    470     }
    471 
    472     GrSurfaceDesc desc;
    473     desc.fOrigin = origin;
    474     desc.fWidth = backendTex.width();
    475     desc.fHeight = backendTex.height();
    476     desc.fConfig = backendTex.config();
    477     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    478     desc.fSampleCnt = sampleCnt;
    479     GrMipMapped mipMapped = backendTex.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
    480 
    481     GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
    482     if (fCaps->usesMixedSamples() && sampleCnt > 1) {
    483         renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
    484     }
    485     if (fCaps->maxWindowRectangles() > 0) {
    486         renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
    487     }
    488 
    489     sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
    490             [backendTex, sampleCnt] (GrResourceProvider* resourceProvider) {
    491                 if (!resourceProvider) {
    492                     return sk_sp<GrTexture>();
    493                 }
    494 
    495                 sk_sp<GrTexture> tex = resourceProvider->wrapRenderableBackendTexture(backendTex,
    496                                                                                       sampleCnt);
    497                 if (!tex) {
    498                     return sk_sp<GrTexture>();
    499                 }
    500                 SkASSERT(tex->asRenderTarget());   // A GrTextureRenderTarget
    501                 // Make sure we match how we created the proxy with SkBudgeted::kNo
    502                 SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
    503 
    504                 return tex;
    505             }, desc, mipMapped, renderTargetFlags, SkBackingFit::kExact, SkBudgeted::kNo);
    506 
    507     if (fResourceProvider) {
    508         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
    509         // we're better off instantiating the proxy immediately here.
    510         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    511             return nullptr;
    512         }
    513     }
    514     return proxy;
    515 }
    516 
    517 sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(
    518                                                              const GrBackendRenderTarget& backendRT,
    519                                                              GrSurfaceOrigin origin) {
    520     if (this->isAbandoned()) {
    521         return nullptr;
    522     }
    523 
    524     GrSurfaceDesc desc;
    525     desc.fOrigin = origin;
    526     desc.fWidth = backendRT.width();
    527     desc.fHeight = backendRT.height();
    528     desc.fConfig = backendRT.config();
    529     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    530     desc.fSampleCnt = backendRT.sampleCnt();
    531 
    532     GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
    533     if (fCaps->isMixedSamplesSupportedForRT(backendRT) && backendRT.sampleCnt() > 1) {
    534         renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
    535     }
    536     if (fCaps->isWindowRectanglesSupportedForRT(backendRT)) {
    537         renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
    538     }
    539 
    540     sk_sp<GrRenderTargetProxy> proxy = this->createLazyRenderTargetProxy(
    541             [backendRT] (GrResourceProvider* resourceProvider) {
    542                 if (!resourceProvider) {
    543                     return sk_sp<GrRenderTarget>();
    544                 }
    545 
    546                 sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendRenderTarget(backendRT);
    547                 if (!rt) {
    548                     return sk_sp<GrRenderTarget>();
    549                 }
    550                 SkASSERT(!rt->asTexture());   // A GrRenderTarget that's not textureable
    551                 SkASSERT(!rt->getUniqueKey().isValid());
    552                 // Make sure we match how we created the proxy with SkBudgeted::kNo
    553                 SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
    554 
    555                 return rt;
    556             }, desc, renderTargetFlags, Textureable::kNo, GrMipMapped::kNo, SkBackingFit::kExact,
    557                SkBudgeted::kNo);
    558 
    559     if (fResourceProvider) {
    560         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
    561         // we're better off instantiating the proxy immediately here.
    562         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    563             return nullptr;
    564         }
    565     }
    566     return proxy;
    567 }
    568 
    569 sk_sp<GrSurfaceProxy> GrProxyProvider::createWrappedRenderTargetProxy(
    570                                                                  const GrBackendTexture& backendTex,
    571                                                                  GrSurfaceOrigin origin,
    572                                                                  int sampleCnt) {
    573     if (this->isAbandoned()) {
    574         return nullptr;
    575     }
    576 
    577     sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendTex.config());
    578     if (!sampleCnt) {
    579         return nullptr;
    580     }
    581 
    582     GrSurfaceDesc desc;
    583     desc.fOrigin = origin;
    584     desc.fWidth = backendTex.width();
    585     desc.fHeight = backendTex.height();
    586     desc.fConfig = backendTex.config();
    587     desc.fFlags = kRenderTarget_GrSurfaceFlag;
    588     desc.fSampleCnt = sampleCnt;
    589 
    590     GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
    591     if (fCaps->usesMixedSamples() && sampleCnt > 1) {
    592         renderTargetFlags |= GrRenderTargetFlags::kMixedSampled;
    593     }
    594     if (fCaps->maxWindowRectangles() > 0) {
    595         renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
    596     }
    597 
    598     sk_sp<GrRenderTargetProxy> proxy = this->createLazyRenderTargetProxy(
    599             [backendTex, sampleCnt] (GrResourceProvider* resourceProvider) {
    600                 if (!resourceProvider) {
    601                     return sk_sp<GrRenderTarget>();
    602                 }
    603 
    604                 sk_sp<GrRenderTarget> rt = resourceProvider->wrapBackendTextureAsRenderTarget(
    605                         backendTex, sampleCnt);
    606                 if (!rt) {
    607                     return sk_sp<GrRenderTarget>();
    608                 }
    609                 SkASSERT(!rt->asTexture());   // A GrRenderTarget that's not textureable
    610                 SkASSERT(!rt->getUniqueKey().isValid());
    611                 // Make sure we match how we created the proxy with SkBudgeted::kNo
    612                 SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
    613 
    614                 return rt;
    615             }, desc, renderTargetFlags, Textureable::kNo, GrMipMapped::kNo, SkBackingFit::kExact,
    616                SkBudgeted::kNo);
    617 
    618     if (fResourceProvider) {
    619         // In order to reuse code we always create a lazy proxy. When we aren't in DDL mode however,
    620         // we're better off instantiating the proxy immediately here.
    621         if (!proxy->priv().doLazyInstantiation(fResourceProvider)) {
    622             return nullptr;
    623         }
    624     }
    625     return proxy;
    626 }
    627 
    628 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
    629                                                        const GrSurfaceDesc& desc,
    630                                                        GrMipMapped mipMapped,
    631                                                        SkBackingFit fit, SkBudgeted budgeted) {
    632     return this->createLazyProxy(std::move(callback), desc, mipMapped, GrRenderTargetFlags::kNone,
    633                                  fit, budgeted);
    634 }
    635 
    636 sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
    637                                                        const GrSurfaceDesc& desc,
    638                                                        GrMipMapped mipMapped,
    639                                                        GrRenderTargetFlags renderTargetFlags,
    640                                                        SkBackingFit fit, SkBudgeted budgeted) {
    641     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
    642              (desc.fWidth > 0 && desc.fHeight > 0));
    643     uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
    644 
    645 #ifdef SK_DEBUG
    646     if (SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags)) {
    647         if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kMixedSampled)) {
    648             SkASSERT(fCaps->usesMixedSamples() && desc.fSampleCnt > 1);
    649         }
    650         if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kWindowRectsSupport)) {
    651             SkASSERT(fCaps->maxWindowRectangles() > 0);
    652         }
    653     }
    654 #endif
    655 
    656     using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
    657     // For non-ddl draws always make lazy proxy's single use.
    658     LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
    659                                                        : LazyInstantiationType::kMultipleUse;
    660 
    661     return sk_sp<GrTextureProxy>(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags) ?
    662                                  new GrTextureRenderTargetProxy(std::move(callback), lazyType, desc,
    663                                                                 mipMapped, fit, budgeted, flags,
    664                                                                 renderTargetFlags) :
    665                                  new GrTextureProxy(std::move(callback), lazyType, desc, mipMapped,
    666                                                     fit, budgeted, flags));
    667 }
    668 
    669 sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
    670                                                 LazyInstantiateCallback&& callback,
    671                                                 const GrSurfaceDesc& desc,
    672                                                 GrRenderTargetFlags renderTargetFlags,
    673                                                 Textureable textureable,
    674                                                 GrMipMapped mipMapped,
    675                                                 SkBackingFit fit, SkBudgeted budgeted) {
    676     SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
    677              (desc.fWidth > 0 && desc.fHeight > 0));
    678     SkASSERT(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags));
    679     uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
    680 
    681 #ifdef SK_DEBUG
    682     if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kMixedSampled)) {
    683         SkASSERT(fCaps->usesMixedSamples() && desc.fSampleCnt > 1);
    684     }
    685     if (SkToBool(renderTargetFlags & GrRenderTargetFlags::kWindowRectsSupport)) {
    686         SkASSERT(fCaps->maxWindowRectangles() > 0);
    687     }
    688 #endif
    689 
    690     using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
    691     // For non-ddl draws always make lazy proxy's single use.
    692     LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
    693                                                        : LazyInstantiationType::kMultipleUse;
    694 
    695     if (Textureable::kYes == textureable) {
    696         return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(std::move(callback),
    697                                                                          lazyType, desc, mipMapped,
    698                                                                          fit, budgeted, flags,
    699                                                                          renderTargetFlags));
    700     }
    701 
    702     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(callback), lazyType, desc,
    703                                                               fit, budgeted, flags,
    704                                                               renderTargetFlags));
    705 }
    706 
    707 sk_sp<GrTextureProxy> GrProxyProvider::createFullyLazyProxy(LazyInstantiateCallback&& callback,
    708                                                             Renderable renderable,
    709                                                             GrSurfaceOrigin origin,
    710                                                             GrPixelConfig config) {
    711     GrSurfaceDesc desc;
    712     GrRenderTargetFlags renderTargetFlags = GrRenderTargetFlags::kNone;
    713     if (Renderable::kYes == renderable) {
    714         desc.fFlags = kRenderTarget_GrSurfaceFlag;
    715         if (fCaps->maxWindowRectangles() > 0) {
    716             renderTargetFlags |= GrRenderTargetFlags::kWindowRectsSupport;
    717         }
    718     }
    719     desc.fOrigin = origin;
    720     desc.fWidth = -1;
    721     desc.fHeight = -1;
    722     desc.fConfig = config;
    723     desc.fSampleCnt = 1;
    724 
    725     return this->createLazyProxy(std::move(callback), desc, GrMipMapped::kNo, renderTargetFlags,
    726                                  SkBackingFit::kApprox, SkBudgeted::kYes);
    727 
    728 }
    729 
    730 bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
    731     return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
    732 }
    733 
    734 void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
    735     // Note: this method is called for the whole variety of GrGpuResources so often 'key'
    736     // will not be in 'fUniquelyKeyedProxies'.
    737     GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
    738     if (proxy) {
    739         this->processInvalidProxyUniqueKey(key, proxy, false);
    740     }
    741 }
    742 
    743 void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
    744                                                    bool invalidateSurface) {
    745     SkASSERT(proxy);
    746     SkASSERT(proxy->getUniqueKey().isValid());
    747     SkASSERT(proxy->getUniqueKey() == key);
    748 
    749     fUniquelyKeyedProxies.remove(key);
    750     proxy->cacheAccess().clearUniqueKey();
    751 
    752     if (invalidateSurface && proxy->priv().isInstantiated()) {
    753         GrSurface* surface = proxy->priv().peekSurface();
    754         if (surface) {
    755             surface->resourcePriv().removeUniqueKey();
    756         }
    757     }
    758 }
    759 
    760 void GrProxyProvider::removeAllUniqueKeys() {
    761     UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
    762     for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
    763         GrTextureProxy& tmp = *iter;
    764 
    765         this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
    766     }
    767     SkASSERT(!fUniquelyKeyedProxies.count());
    768 }
    769