Replace bool purgeImmediately with enum GrWrapCacheable.

Store budgeted status as a tri-state enum on GrGpuResource:
kBudgeted
kUnbudgetedCacheable
kUnbudgetedUncacheable

Uncacheable vs. Cacheable captures the current distinction between
wrapped resources created with purgeImmediately or !purgeImmediately.

Non-wrapped and unbudgeted resources are all kUnbudgetedCacheable to
match current behavior.

This change just introduces the new types. No behavior is changed.

Bug: chromium:922851

Change-Id: Ic2387bf321cf9b56b4c9ffd9dbef8ade60f9cb98
Reviewed-on: https://skia-review.googlesource.com/c/185003
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index f191174..291f013 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -167,8 +167,10 @@
                     // informs us that the context is done with it. This is unfortunate - we'll have
                     // two texture objects referencing the same GPU object. However, no client can
                     // ever see the original texture, so this should be safe.
+                    // We make the texture uncacheable so that the release proc is called ASAP.
                     tex = resourceProvider->wrapBackendTexture(
-                            backendTexture, kBorrow_GrWrapOwnership, kRead_GrIOType, true);
+                            backendTexture, kBorrow_GrWrapOwnership, kRead_GrIOType,
+                            GrWrapCacheable::kNo);
                     if (!tex) {
                         return sk_sp<GrTexture>();
                     }
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 0e520d8..d291c04 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -148,9 +148,8 @@
 }
 
 sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
-                                           GrWrapOwnership ownership,
-                                           GrIOType ioType,
-                                           bool purgeImmediately) {
+                                           GrWrapOwnership ownership, GrWrapCacheable cacheable,
+                                           GrIOType ioType) {
     SkASSERT(ioType != kWrite_GrIOType);
     this->handleDirtyContext();
     SkASSERT(this->caps());
@@ -161,7 +160,7 @@
         backendTex.height() > this->caps()->maxTextureSize()) {
         return nullptr;
     }
-    return this->onWrapBackendTexture(backendTex, ownership, ioType, purgeImmediately);
+    return this->onWrapBackendTexture(backendTex, ownership, cacheable, ioType);
 }
 
 sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index c99733d..34e21c4 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -104,8 +104,8 @@
     /**
      * Implements GrResourceProvider::wrapBackendTexture
      */
-    sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrIOType,
-                                        bool purgeImmediately);
+    sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
+                                        GrIOType);
 
     /**
      * Implements GrResourceProvider::wrapRenderableBackendTexture
@@ -458,7 +458,7 @@
                                              const GrMipLevel texels[], int mipLevelCount) = 0;
 
     virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership,
-                                                  GrIOType, bool purgeImmediately) = 0;
+                                                  GrWrapCacheable, GrIOType) = 0;
     virtual sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
                                                             int sampleCnt,
                                                             GrWrapOwnership) = 0;
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index a4e0f54..b3d3b1d 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -21,28 +21,23 @@
     return gpu->getContext()->contextPriv().getResourceCache();
 }
 
-GrGpuResource::GrGpuResource(GrGpu* gpu)
-    : fGpu(gpu)
-    , fGpuMemorySize(kInvalidGpuMemorySize)
-    , fBudgeted(SkBudgeted::kNo)
-    , fShouldPurgeImmediately(false)
-    , fRefsWrappedObjects(false)
-    , fUniqueID(CreateUniqueID()) {
+GrGpuResource::GrGpuResource(GrGpu* gpu) : fGpu(gpu), fUniqueID(CreateUniqueID()) {
     SkDEBUGCODE(fCacheArrayIndex = -1);
 }
 
 void GrGpuResource::registerWithCache(SkBudgeted budgeted) {
-    SkASSERT(fBudgeted == SkBudgeted::kNo);
-    SkASSERT(!fShouldPurgeImmediately);
-    fBudgeted = budgeted;
+    SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedCacheable);
+    fBudgetedType = budgeted == SkBudgeted::kYes ? GrBudgetedType::kBudgeted
+                                                 : GrBudgetedType::kUnbudgetedCacheable;
     this->computeScratchKey(&fScratchKey);
     get_resource_cache(fGpu)->resourceAccess().insertResource(this);
 }
 
-void GrGpuResource::registerWithCacheWrapped(bool purgeImmediately) {
-    SkASSERT(fBudgeted == SkBudgeted::kNo);
-    // Currently resources referencing wrapped objects are not budgeted.
-    fShouldPurgeImmediately = purgeImmediately;
+void GrGpuResource::registerWithCacheWrapped(GrWrapCacheable wrapType) {
+    SkASSERT(fBudgetedType == GrBudgetedType::kUnbudgetedCacheable);
+    // Resources referencing wrapped objects are never budgeted. They may be cached or uncached.
+    fBudgetedType = wrapType == GrWrapCacheable::kNo ? GrBudgetedType::kUnbudgetedUncacheable
+                                                     : GrBudgetedType::kUnbudgetedCacheable;
     fRefsWrappedObjects = true;
     get_resource_cache(fGpu)->resourceAccess().insertResource(this);
 }
@@ -137,7 +132,8 @@
     // resources are a special case: the unique keys give us a weak ref so that we can reuse the
     // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
     // it will always be released - it is never converted to a scratch resource.
-    if (SkBudgeted::kNo == this->resourcePriv().isBudgeted() && !this->fRefsWrappedObjects) {
+    if (this->resourcePriv().budgetedType() != GrBudgetedType::kBudgeted &&
+        !this->fRefsWrappedObjects) {
         return;
     }
 
@@ -190,18 +186,21 @@
 }
 
 void GrGpuResource::makeBudgeted() {
-    if (!this->wasDestroyed() && SkBudgeted::kNo == fBudgeted) {
+    // We should never make a wrapped resource budgeted.
+    SkASSERT(!fRefsWrappedObjects);
+    // Only wrapped resources can be in the kUnbudgetedUncacheable state.
+    SkASSERT(fBudgetedType != GrBudgetedType::kUnbudgetedUncacheable);
+    if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kUnbudgetedCacheable) {
         // Currently resources referencing wrapped objects are not budgeted.
-        SkASSERT(!fRefsWrappedObjects);
-        fBudgeted = SkBudgeted::kYes;
+        fBudgetedType = GrBudgetedType::kBudgeted;
         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
     }
 }
 
 void GrGpuResource::makeUnbudgeted() {
-    if (!this->wasDestroyed() && SkBudgeted::kYes == fBudgeted &&
+    if (!this->wasDestroyed() && fBudgetedType == GrBudgetedType::kBudgeted &&
         !fUniqueKey.isValid()) {
-        fBudgeted = SkBudgeted::kNo;
+        fBudgetedType = GrBudgetedType::kUnbudgetedCacheable;
         get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
     }
 }
diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h
index ce3b597..3765c6e 100644
--- a/src/gpu/GrGpuResourceCacheAccess.h
+++ b/src/gpu/GrGpuResourceCacheAccess.h
@@ -26,15 +26,10 @@
      */
     bool isScratch() const {
         return !fResource->getUniqueKey().isValid() && fResource->fScratchKey.isValid() &&
-                SkBudgeted::kYes == fResource->resourcePriv().isBudgeted();
+               GrBudgetedType::kBudgeted == fResource->resourcePriv().budgetedType();
     }
 
     /**
-     * Even if the resource has a unique key should we still try to purge it as soon as possible.
-     */
-    bool shouldPurgeImmediately() const { return fResource->fShouldPurgeImmediately; }
-
-    /**
      * Called by GrResourceCache when a resource becomes purgeable regardless of whether the cache
      * has decided to keep the resource ot purge it immediately.
      */
diff --git a/src/gpu/GrGpuResourcePriv.h b/src/gpu/GrGpuResourcePriv.h
index 9537ffb..75b3531 100644
--- a/src/gpu/GrGpuResourcePriv.h
+++ b/src/gpu/GrGpuResourcePriv.h
@@ -43,12 +43,13 @@
     void makeUnbudgeted() { fResource->makeUnbudgeted(); }
 
     /**
-     * Does the resource count against the resource budget?
+     * Get the resource's budgeted-type which indicates whether it counts against the resource cache
+     * budget and if not whether it is allowed to be cached.
      */
-    SkBudgeted isBudgeted() const {
-        bool ret = SkBudgeted::kYes == fResource->fBudgeted;
-        SkASSERT(ret || !fResource->getUniqueKey().isValid() || fResource->fRefsWrappedObjects);
-        return SkBudgeted(ret);
+    GrBudgetedType budgetedType() const {
+        SkASSERT(GrBudgetedType::kBudgeted == fResource->fBudgetedType ||
+                 !fResource->getUniqueKey().isValid() || fResource->fRefsWrappedObjects);
+        return fResource->fBudgetedType;
     }
 
     /**
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index 3aa6262..978da53 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -464,7 +464,8 @@
         return nullptr;
     }
 
-    sk_sp<GrTexture> tex = fResourceProvider->wrapBackendTexture(backendTex, ownership, ioType);
+    sk_sp<GrTexture> tex = fResourceProvider->wrapBackendTexture(backendTex, ownership, ioType,
+                                                                 GrWrapCacheable::kYes);
     if (!tex) {
         return nullptr;
     }
@@ -478,7 +479,7 @@
 
     SkASSERT(!tex->asRenderTarget());  // Strictly a GrTexture
     // Make sure we match how we created the proxy with SkBudgeted::kNo
-    SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
+    SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
 
     return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), origin));
 }
@@ -508,7 +509,7 @@
 
     SkASSERT(tex->asRenderTarget());  // A GrTextureRenderTarget
     // Make sure we match how we created the proxy with SkBudgeted::kNo
-    SkASSERT(SkBudgeted::kNo == tex->resourcePriv().isBudgeted());
+    SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
 
     return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), origin));
 }
@@ -531,7 +532,7 @@
     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
     SkASSERT(!rt->getUniqueKey().isValid());
     // Make sure we match how we created the proxy with SkBudgeted::kNo
-    SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
+    SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
 
     return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(rt), origin));
 }
@@ -555,7 +556,7 @@
     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
     SkASSERT(!rt->getUniqueKey().isValid());
     // This proxy should be unbudgeted because we're just wrapping an external resource
-    SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
+    SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
 
     return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(rt), origin));
 }
@@ -580,7 +581,7 @@
     SkASSERT(!rt->asTexture());  // A GrRenderTarget that's not textureable
     SkASSERT(!rt->getUniqueKey().isValid());
     // This proxy should be unbudgeted because we're just wrapping an external resource
-    SkASSERT(SkBudgeted::kNo == rt->resourcePriv().isBudgeted());
+    SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
 
     // All Vulkan surfaces uses top left origins.
     return sk_sp<GrRenderTargetProxy>(
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 0f70894..0d3c34e 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -266,9 +266,9 @@
     sk_sp<GrSurface> surface(fFreePool.findAndRemove(key, filter));
     if (surface) {
         if (SkBudgeted::kYes == proxy->isBudgeted() &&
-            SkBudgeted::kNo == surface->resourcePriv().isBudgeted()) {
+            GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
             // This gets the job done but isn't quite correct. It would be better to try to
-            // match budgeted proxies w/ budgeted surface and unbudgeted w/ unbudgeted.
+            // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
             surface->resourcePriv().makeBudgeted();
         }
 
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 53dfe9b..634dac7 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -125,7 +125,7 @@
     fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount);
     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
 #endif
-    if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) {
+    if (GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType()) {
         ++fBudgetedCount;
         fBudgetedBytes += size;
         TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used",
@@ -159,7 +159,7 @@
 
     SkDEBUGCODE(--fCount;)
     fBytes -= size;
-    if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) {
+    if (GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType()) {
         --fBudgetedCount;
         fBudgetedBytes -= size;
         TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used",
@@ -423,10 +423,18 @@
     {
         SkScopeExit notifyPurgeable([resource] { resource->cacheAccess().becamePurgeable(); });
 
-        if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) {
+        auto budgetedType = resource->resourcePriv().budgetedType();
+        if (budgetedType == GrBudgetedType::kBudgeted) {
+            // Purge the resource immediately if we're over budget
+            // Also purge if the resource has neither a valid scratch key nor a unique key.
+            bool hasKey = resource->resourcePriv().getScratchKey().isValid() || hasUniqueKey;
+            if (!this->overBudget() && hasKey) {
+                return;
+            }
+        } else {
             // We keep unbudgeted resources with a unique key in the purgable queue of the cache so
             // they can be reused again by the image connected to the unique key.
-            if (hasUniqueKey && !resource->cacheAccess().shouldPurgeImmediately()) {
+            if (hasUniqueKey && budgetedType == GrBudgetedType::kUnbudgetedCacheable) {
                 return;
             }
             // Check whether this resource could still be used as a scratch resource.
@@ -439,13 +447,6 @@
                     return;
                 }
             }
-        } else {
-            // Purge the resource immediately if we're over budget
-            // Also purge if the resource has neither a valid scratch key nor a unique key.
-            bool hasKey = resource->resourcePriv().getScratchKey().isValid() || hasUniqueKey;
-            if (!this->overBudget() && hasKey) {
-                return;
-            }
         }
     }
     SkDEBUGCODE(int beforeCount = this->getResourceCount();)
@@ -462,7 +463,7 @@
 
     size_t size = resource->gpuMemorySize();
 
-    if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) {
+    if (GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType()) {
         ++fBudgetedCount;
         fBudgetedBytes += size;
 #if GR_CACHE_STATS
@@ -752,7 +753,7 @@
                 SkASSERT(fScratchMap->countForKey(scratchKey));
                 SkASSERT(!resource->resourcePriv().refsWrappedObjects());
             } else if (scratchKey.isValid()) {
-                SkASSERT(SkBudgeted::kNo == resource->resourcePriv().isBudgeted() ||
+                SkASSERT(GrBudgetedType::kBudgeted != resource->resourcePriv().budgetedType() ||
                          uniqueKey.isValid());
                 if (!uniqueKey.isValid()) {
                     ++fCouldBeScratch;
@@ -763,7 +764,7 @@
             if (uniqueKey.isValid()) {
                 ++fContent;
                 SkASSERT(fUniqueHash->find(uniqueKey) == resource);
-                SkASSERT(SkBudgeted::kYes == resource->resourcePriv().isBudgeted() ||
+                SkASSERT(GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType() ||
                          resource->resourcePriv().refsWrappedObjects());
 
                 if (scratchKey.isValid()) {
@@ -771,7 +772,7 @@
                 }
             }
 
-            if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) {
+            if (GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType()) {
                 ++fBudgetedCount;
                 fBudgetedBytes += resource->gpuMemorySize();
             }
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 7730ebd..59141ad 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -225,7 +225,7 @@
             if (resource->resourcePriv().refsWrappedObjects()) {
                 ++fWrapped;
             }
-            if (SkBudgeted::kNo  == resource->resourcePriv().isBudgeted()) {
+            if (GrBudgetedType::kBudgeted != resource->resourcePriv().budgetedType()) {
                 fUnbudgetedSize += resource->gpuMemorySize();
             }
         }
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 6b5ff4f..c996494 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -236,12 +236,12 @@
 sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
                                                         GrWrapOwnership ownership,
                                                         GrIOType ioType,
-                                                        bool purgeImmediately) {
+                                                        GrWrapCacheable cacheable) {
     ASSERT_SINGLE_OWNER
     if (this->isAbandoned()) {
         return nullptr;
     }
-    return fGpu->wrapBackendTexture(tex, ownership, ioType, purgeImmediately);
+    return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
 }
 
 sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 84a97a1..8364049 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -109,7 +109,7 @@
     sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture& tex,
                                         GrWrapOwnership /* = kBorrow_GrWrapOwnership*/,
                                         GrIOType,
-                                        bool purgeImmediately = false);
+                                        GrWrapCacheable = GrWrapCacheable::kYes);
 
     /**
      * This makes the backend texture be renderable. If sampleCnt is > 1 and the underlying API
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 3da6aaa..8b1bce4 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -89,7 +89,9 @@
         , fHeight(fTarget->height())
         , fOrigin(origin)
         , fFit(fit)
-        , fBudgeted(fTarget->resourcePriv().isBudgeted())
+        , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
+                            ? SkBudgeted::kYes
+                            : SkBudgeted::kNo)
         , fUniqueID(fTarget->uniqueID())  // Note: converting from unique resource ID to a proxy ID!
         , fNeedsClear(false)
         , fGpuMemorySize(kInvalidGpuMemorySize)
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 2c8b602..5cca23a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -653,8 +653,8 @@
 }
 
 sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
-                                               GrWrapOwnership ownership, GrIOType ioType,
-                                               bool purgeImmediately) {
+                                               GrWrapOwnership ownership, GrWrapCacheable cacheable,
+                                               GrIOType ioType) {
     GrGLTexture::IDDesc idDesc;
     if (!check_backend_texture(backendTex, this->glCaps(), &idDesc)) {
         return nullptr;
@@ -678,8 +678,8 @@
     GrMipMapsStatus mipMapsStatus = backendTex.hasMipMaps() ? GrMipMapsStatus::kValid
                                                             : GrMipMapsStatus::kNotAllocated;
 
-    auto texture = GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc, ioType,
-                                            purgeImmediately);
+    auto texture =
+            GrGLTexture::MakeWrapped(this, surfDesc, mipMapsStatus, idDesc, cacheable, ioType);
     // We don't know what parameters are already set on wrapped textures.
     texture->textureParamsModified();
     return std::move(texture);
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 75466cf..1987a28 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -189,8 +189,8 @@
     GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
                              const void* data) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrIOType,
-                                          bool purgeImmediately) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
+                                          GrIOType) override;
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override;
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index cbb6b5a..a94c87b 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -53,13 +53,12 @@
     }
 }
 
-GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc,
-                         GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc, GrIOType ioType,
-                         bool purgeImmediately)
+GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
+                         const IDDesc& idDesc, GrWrapCacheable cacheable, GrIOType ioType)
         : GrSurface(gpu, desc)
         , INHERITED(gpu, desc, TextureTypeFromTarget(idDesc.fInfo.fTarget), mipMapsStatus) {
     this->init(desc, idDesc);
-    this->registerWithCacheWrapped(purgeImmediately);
+    this->registerWithCacheWrapped(cacheable);
     if (ioType == kRead_GrIOType) {
         this->setReadOnly();
     }
@@ -117,9 +116,8 @@
 
 sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
                                             GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc,
-                                            GrIOType ioType, bool purgeImmediately) {
-    return sk_sp<GrGLTexture>(
-            new GrGLTexture(gpu, kWrapped, desc, mipMapsStatus, idDesc, ioType, purgeImmediately));
+                                            GrWrapCacheable cacheable, GrIOType ioType) {
+    return sk_sp<GrGLTexture>(new GrGLTexture(gpu, desc, mipMapsStatus, idDesc, cacheable, ioType));
 }
 
 bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index f9d4acd..e8ca83c 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -111,7 +111,7 @@
     void baseLevelWasBoundToFBO() { fBaseLevelHasBeenBoundToFBO = true; }
 
     static sk_sp<GrGLTexture> MakeWrapped(GrGLGpu*, const GrSurfaceDesc&, GrMipMapsStatus,
-                                          const IDDesc&, GrIOType, bool purgeImmediately);
+                                          const IDDesc&, GrWrapCacheable, GrIOType);
 
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
 
@@ -119,10 +119,9 @@
     // Constructor for subclasses.
     GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrMipMapsStatus);
 
-    enum Wrapped { kWrapped };
     // Constructor for instances wrapping backend objects.
-    GrGLTexture(GrGLGpu*, Wrapped, const GrSurfaceDesc&, GrMipMapsStatus, const IDDesc&, GrIOType,
-                bool purgeImmediately);
+    GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, GrMipMapsStatus, const IDDesc&, GrWrapCacheable,
+                GrIOType);
 
     void init(const GrSurfaceDesc&, const IDDesc&);
 
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index b98af80..a2955f5 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -107,8 +107,8 @@
 }
 
 sk_sp<GrTexture> GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex,
-                                                 GrWrapOwnership ownership, GrIOType ioType,
-                                                 bool purgeImmediately) {
+                                                 GrWrapOwnership ownership,
+                                                 GrWrapCacheable wrapType, GrIOType ioType) {
     GrSurfaceDesc desc;
     desc.fWidth = tex.width();
     desc.fHeight = tex.height();
@@ -120,8 +120,7 @@
     GrMipMapsStatus mipMapsStatus = tex.hasMipMaps() ? GrMipMapsStatus::kValid
                                                      : GrMipMapsStatus::kNotAllocated;
 
-    return sk_sp<GrTexture>(new GrMockTexture(this, GrMockTexture::kWrapped, desc, mipMapsStatus,
-                                              info, ioType, purgeImmediately));
+    return sk_sp<GrTexture>(new GrMockTexture(this, desc, mipMapsStatus, info, wrapType, ioType));
 }
 
 sk_sp<GrTexture> GrMockGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index d3584b5..77090ea 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -59,8 +59,8 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel[],
                                      int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrIOType,
-                                          bool purgeImmediately) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
+                                          GrIOType) override;
 
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
                                                     int sampleCnt,
diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h
index 3674de6..e9e35af 100644
--- a/src/gpu/mock/GrMockTexture.h
+++ b/src/gpu/mock/GrMockTexture.h
@@ -22,14 +22,13 @@
         this->registerWithCache(budgeted);
     }
 
-    enum Wrapped { kWrapped };
-    GrMockTexture(GrMockGpu* gpu, Wrapped, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
-                  const GrMockTextureInfo& info, GrIOType ioType, bool purgeImmediately)
+    GrMockTexture(GrMockGpu* gpu, const GrSurfaceDesc& desc, GrMipMapsStatus mipMapsStatus,
+                  const GrMockTextureInfo& info, GrWrapCacheable cacheable, GrIOType ioType)
             : GrMockTexture(gpu, desc, mipMapsStatus, info) {
         if (ioType == kRead_GrIOType) {
             this->setReadOnly();
         }
-        this->registerWithCacheWrapped(purgeImmediately);
+        this->registerWithCacheWrapped(cacheable);
     }
 
     ~GrMockTexture() override {}
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index cc13645..bab666c 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -132,8 +132,8 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                      const GrMipLevel texels[], int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrIOType,
-                                          bool purgeImmediately) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
+                                          GrIOType) override;
 
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
                                                     int sampleCnt,
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 68693b1..a74ac52 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -342,8 +342,8 @@
 }
 
 sk_sp<GrTexture> GrMtlGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
-                                                GrWrapOwnership ownership, GrIOType ioType,
-                                                bool purgeImmediately) {
+                                                GrWrapOwnership ownership,
+                                                GrWrapCacheable cacheable, GrIOType ioType) {
     id<MTLTexture> mtlTexture = get_texture_from_backend(backendTex, ownership);
     if (!mtlTexture) {
         return nullptr;
@@ -352,7 +352,7 @@
     GrSurfaceDesc surfDesc;
     init_surface_desc(&surfDesc, mtlTexture, false, backendTex.config());
 
-    return GrMtlTexture::MakeWrappedTexture(this, surfDesc, mtlTexture, ioType, purgeImmediately);
+    return GrMtlTexture::MakeWrappedTexture(this, surfDesc, mtlTexture, cacheable, ioType);
 }
 
 sk_sp<GrTexture> GrMtlGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
diff --git a/src/gpu/mtl/GrMtlTexture.h b/src/gpu/mtl/GrMtlTexture.h
index 2cdb92b..87599ea 100644
--- a/src/gpu/mtl/GrMtlTexture.h
+++ b/src/gpu/mtl/GrMtlTexture.h
@@ -22,7 +22,7 @@
                                                 GrMipMapsStatus);
 
     static sk_sp<GrMtlTexture> MakeWrappedTexture(GrMtlGpu*, const GrSurfaceDesc&, id<MTLTexture>,
-                                                  GrIOType, bool purgeImmediately);
+                                                  GrWrapCacheable, GrIOType);
 
     ~GrMtlTexture() override;
 
@@ -88,7 +88,7 @@
                  GrMipMapsStatus);
 
     GrMtlTexture(GrMtlGpu*, Wrapped, const GrSurfaceDesc&, id<MTLTexture>, GrMipMapsStatus,
-                 GrIOType, bool purgeImmediately);
+                 GrWrapCacheable, GrIOType);
 
     id<MTLTexture> fTexture;
     sk_sp<GrReleaseProcHelper> fReleaseHelper;
diff --git a/src/gpu/mtl/GrMtlTexture.mm b/src/gpu/mtl/GrMtlTexture.mm
index 5e91746..87829a3 100644
--- a/src/gpu/mtl/GrMtlTexture.mm
+++ b/src/gpu/mtl/GrMtlTexture.mm
@@ -28,8 +28,8 @@
                            const GrSurfaceDesc& desc,
                            id<MTLTexture> texture,
                            GrMipMapsStatus mipMapsStatus,
-                           GrIOType ioType,
-                           bool purgeImmediately)
+                           GrWrapCacheable cacheable,
+                           GrIOType ioType)
         : GrSurface(gpu, desc)
         , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
         , fTexture(texture) {
@@ -37,7 +37,7 @@
     if (ioType == kRead_GrIOType) {
         this->setReadOnly();
     }
-    this->registerWithCacheWrapped(purgeImmediately);
+    this->registerWithCacheWrapped(cacheable);
 }
 
 GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu,
@@ -67,8 +67,8 @@
 sk_sp<GrMtlTexture> GrMtlTexture::MakeWrappedTexture(GrMtlGpu* gpu,
                                                      const GrSurfaceDesc& desc,
                                                      id<MTLTexture> texture,
-                                                     GrIOType ioType,
-                                                     bool purgeImmediately) {
+                                                     GrWrapCacheable cacheable,
+                                                     GrIOType ioType) {
     if (desc.fSampleCnt > 1) {
         SkASSERT(false); // Currently we don't support msaa
         return nullptr;
@@ -77,8 +77,8 @@
     SkASSERT(MTLTextureUsageShaderRead & texture.usage);
     GrMipMapsStatus mipMapsStatus = texture.mipmapLevelCount > 1 ? GrMipMapsStatus::kValid
                                                                  : GrMipMapsStatus::kNotAllocated;
-    return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, kWrapped, desc, texture, mipMapsStatus, ioType,
-                                                purgeImmediately));
+    return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, kWrapped, desc, texture, mipMapsStatus,
+                                                cacheable, ioType));
 }
 
 GrMtlTexture::~GrMtlTexture() {
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 619394d..b85d603 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1022,8 +1022,8 @@
 }
 
 sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
-                                               GrWrapOwnership ownership, GrIOType ioType,
-                                               bool purgeImmediately) {
+                                               GrWrapOwnership ownership, GrWrapCacheable cacheable,
+                                               GrIOType ioType) {
     GrVkImageInfo imageInfo;
     if (!backendTex.getVkImageInfo(&imageInfo)) {
         return nullptr;
@@ -1042,8 +1042,8 @@
 
     sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout();
     SkASSERT(layout);
-    return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, ioType, purgeImmediately,
-                                           imageInfo, std::move(layout));
+    return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, cacheable, ioType, imageInfo,
+                                           std::move(layout));
 }
 
 sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 6358560..8200b6f 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -184,8 +184,8 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel[],
                                      int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrIOType,
-                                          bool purgeImmediately) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
+                                          GrIOType) override;
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override;
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 802bbcd..bdd8db4 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -36,16 +36,10 @@
     }
 }
 
-GrVkTexture::GrVkTexture(GrVkGpu* gpu,
-                         Wrapped,
-                         const GrSurfaceDesc& desc,
-                         const GrVkImageInfo& info,
-                         sk_sp<GrVkImageLayout> layout,
-                         const GrVkImageView* view,
-                         GrMipMapsStatus mipMapsStatus,
-                         GrBackendObjectOwnership ownership,
-                         GrIOType ioType,
-                         bool purgeImmediately)
+GrVkTexture::GrVkTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
+                         sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
+                         GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
+                         GrWrapCacheable cacheable, GrIOType ioType)
         : GrSurface(gpu, desc)
         , GrVkImage(info, std::move(layout), ownership)
         , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
@@ -54,7 +48,7 @@
     if (ioType == kRead_GrIOType) {
         this->setReadOnly();
     }
-    this->registerWithCacheWrapped(purgeImmediately);
+    this->registerWithCacheWrapped(cacheable);
 }
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
@@ -96,11 +90,9 @@
                                               imageView, mipMapsStatus));
 }
 
-sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
-                                                   const GrSurfaceDesc& desc,
+sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
                                                    GrWrapOwnership wrapOwnership,
-                                                   GrIOType ioType,
-                                                   bool purgeImmediately,
+                                                   GrWrapCacheable cacheable, GrIOType ioType,
                                                    const GrVkImageInfo& info,
                                                    sk_sp<GrVkImageLayout> layout) {
     // Wrapped textures require both image and allocation (because they can be mapped)
@@ -118,9 +110,8 @@
 
     GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
             ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
-    return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, info, std::move(layout),
-                                              imageView, mipMapsStatus, ownership, ioType,
-                                              purgeImmediately));
+    return sk_sp<GrVkTexture>(new GrVkTexture(gpu, desc, info, std::move(layout), imageView,
+                                              mipMapsStatus, ownership, cacheable, ioType));
 }
 
 GrVkTexture::~GrVkTexture() {
diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h
index 0592fc8..9005b42 100644
--- a/src/gpu/vk/GrVkTexture.h
+++ b/src/gpu/vk/GrVkTexture.h
@@ -25,8 +25,8 @@
                                              GrMipMapsStatus);
 
     static sk_sp<GrVkTexture> MakeWrappedTexture(GrVkGpu*, const GrSurfaceDesc&, GrWrapOwnership,
-                                                 GrIOType, bool purgeImmediately,
-                                                 const GrVkImageInfo&, sk_sp<GrVkImageLayout>);
+                                                 GrWrapCacheable, GrIOType, const GrVkImageInfo&,
+                                                 sk_sp<GrVkImageLayout>);
 
     ~GrVkTexture() override;
 
@@ -62,13 +62,12 @@
     }
 
 private:
-    enum Wrapped { kWrapped };
     GrVkTexture(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&, const GrVkImageInfo&,
                 sk_sp<GrVkImageLayout> layout, const GrVkImageView* imageView,
                 GrMipMapsStatus);
-    GrVkTexture(GrVkGpu*, Wrapped, const GrSurfaceDesc&, const GrVkImageInfo&,
-                sk_sp<GrVkImageLayout> layout, const GrVkImageView* imageView, GrMipMapsStatus,
-                GrBackendObjectOwnership, GrIOType ioType, bool purgeImmediately);
+    GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, const GrVkImageInfo&, sk_sp<GrVkImageLayout>,
+                const GrVkImageView*, GrMipMapsStatus, GrBackendObjectOwnership, GrWrapCacheable,
+                GrIOType);
 
     void becamePurgeable() override;