Split out methods in GrGpuResource::CacheAccess that can be called outside of the cache.

Review URL: https://codereview.chromium.org/923143002
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 6c6ec50..26b30a4 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -13,7 +13,7 @@
 #include "GrDefaultGeoProcFactory.h"
 #include "GrFontCache.h"
 #include "GrGpuResource.h"
-#include "GrGpuResourceCacheAccess.h"
+#include "GrGpuResourcePriv.h"
 #include "GrDistanceFieldTextContext.h"
 #include "GrDrawTargetCaps.h"
 #include "GrGpu.h"
@@ -249,7 +249,7 @@
             if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                                                  srcData, rowBytes)) {
                 if (!budgeted) {
-                    texture->cacheAccess().makeUnbudgeted();
+                    texture->resourcePriv().makeUnbudgeted();
                 }
                 return texture;
             }
@@ -335,15 +335,7 @@
     }
 
     if (!(kNoCreate_ScratchTextureFlag & flags)) {
-        GrTexture* texture = fGpu->createTexture(*desc, true, NULL, 0);
-    #ifdef SK_DEBUG
-        if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
-            GrScratchKey key;
-            GrTexturePriv::ComputeScratchKey(*desc, &key);
-            SkASSERT(NULL == texture || texture->cacheAccess().getScratchKey() == key);
-        }
-    #endif
-        return texture;
+        return fGpu->createTexture(*desc, true, NULL, 0);
     }
 
     return NULL;
@@ -1585,7 +1577,7 @@
     if (!resource || resource->wasDestroyed()) {
         return false;
     }
-    return resource->cacheAccess().setContentKey(key);
+    return resource->resourcePriv().setContentKey(key);
 }
 
 bool GrContext::isResourceInCache(const GrContentKey& key) const {
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index d23d452..eef965e 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -12,6 +12,7 @@
 #include "GrBufferAllocPool.h"
 #include "GrContext.h"
 #include "GrDrawTargetCaps.h"
+#include "GrGpuResourcePriv.h"
 #include "GrIndexBuffer.h"
 #include "GrResourceCache.h"
 #include "GrStencilBuffer.h"
@@ -72,7 +73,7 @@
         }
     }
     if (!this->caps()->reuseScratchTextures() && !isRT) {
-        tex->cacheAccess().removeScratchKey();
+        tex->resourcePriv().removeScratchKey();
     }
     if (tex) {
         fStats.incTextureCreates();
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index 7f65af2..dbf5d8c 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -9,6 +9,7 @@
 #include "GrGpuResource.h"
 #include "GrResourceCache.h"
 #include "GrGpu.h"
+#include "GrGpuResourcePriv.h"
 
 static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
     SkASSERT(gpu);
@@ -94,7 +95,7 @@
     SkASSERT(key.isValid());
 
     // Wrapped and uncached resources can never have a content key.
-    if (!this->cacheAccess().isBudgeted()) {
+    if (!this->resourcePriv().isBudgeted()) {
         return false;
     }
 
diff --git a/src/gpu/GrGpuResourceCacheAccess.h b/src/gpu/GrGpuResourceCacheAccess.h
index 6c99d08..922e3b3 100644
--- a/src/gpu/GrGpuResourceCacheAccess.h
+++ b/src/gpu/GrGpuResourceCacheAccess.h
@@ -10,74 +10,31 @@
 #define GrGpuResourceCacheAccess_DEFINED
 
 #include "GrGpuResource.h"
+#include "GrGpuResourcePriv.h"
+
+namespace skiatest {
+    class Reporter;
+}
 
 /**
- * This class allows code internal to Skia privileged access to manage the cache keys of a
- * GrGpuResource object.
+ * This class allows GrResourceCache increased privileged access to GrGpuResource objects.
  */
 class GrGpuResource::CacheAccess {
-public:
-    /**
-     * Sets a content key for the resource. If the resource was previously cached as scratch it will
-     * be converted to a content resource. Currently this may only be called once per resource. It
-     * fails if there is already a resource with the same content key. TODO: make this supplant the
-     * resource that currently is using the content key, allow resources' content keys to change,
-     * and allow removal of a content key to convert a resource back to scratch.
-     */
-    bool setContentKey(const GrContentKey& contentKey) {
-        return fResource->setContentKey(contentKey);
-    }
-
-    void removeContentKey() { return fResource->removeContentKey(); }
-
+private:
     /**
      * Is the resource currently cached as scratch? This means it is cached, has a valid scratch
      * key, and does not have a content key.
      */
     bool isScratch() const {
         return !fResource->getContentKey().isValid() && fResource->fScratchKey.isValid() &&
-                this->isBudgeted();
+                fResource->resourcePriv().isBudgeted();
     }
 
-    /** 
-     * If this resource can be used as a scratch resource this returns a valid scratch key.
-     * Otherwise it returns a key for which isNullScratch is true. The resource may currently be
-     * used as a content resource rather than scratch. Check isScratch().
-     */
-    const GrScratchKey& getScratchKey() const { return fResource->fScratchKey; }
-
-    /**
-     * If the resource has a scratch key, the key will be removed. Since scratch keys are installed
-     * at resource creation time, this means the resource will never again be used as scratch.
-     */
-    void removeScratchKey() const { fResource->removeScratchKey();  }
-
     /**
      * Is the resource object wrapping an externally allocated GPU resource?
      */
     bool isWrapped() const { return GrGpuResource::kWrapped_LifeCycle == fResource->fLifeCycle; }
-
-    /**
-     * Does the resource count against the resource budget?
-     */
-    bool isBudgeted() const {
-        bool ret = GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle;
-        SkASSERT(ret || !fResource->getContentKey().isValid());
-        return ret;
-    }
-
-    /**
-     * If the resource is uncached make it cached. Has no effect on resources that are wrapped or
-     * already cached.
-     */
-    void makeBudgeted() { fResource->makeBudgeted(); }
-
-    /**
-     * If the resource is cached make it uncached. Has no effect on resources that are wrapped or
-     * already uncached. Furthermore, resources with content keys cannot be made unbudgeted.
-     */
-    void makeUnbudgeted() { fResource->makeUnbudgeted(); }
-
+ 
     /**
      * Called by the cache to delete the resource under normal circumstances.
      */
@@ -98,9 +55,8 @@
         }
     }
 
-private:
-    CacheAccess(GrGpuResource* resource) : fResource(resource) { }
-    CacheAccess(const CacheAccess& that) : fResource(that.fResource) { }
+    CacheAccess(GrGpuResource* resource) : fResource(resource) {}
+    CacheAccess(const CacheAccess& that) : fResource(that.fResource) {}
     CacheAccess& operator=(const CacheAccess&); // unimpl
 
     // No taking addresses of this type.
@@ -110,6 +66,8 @@
     GrGpuResource* fResource;
 
     friend class GrGpuResource; // to construct/copy this type.
+    friend class GrResourceCache; // to use this type
+    friend void test_unbudgeted_to_scratch(skiatest::Reporter* reporter); // for unit testing
 };
 
 inline GrGpuResource::CacheAccess GrGpuResource::cacheAccess() { return CacheAccess(this); }
diff --git a/src/gpu/GrGpuResourcePriv.h b/src/gpu/GrGpuResourcePriv.h
new file mode 100644
index 0000000..520e217
--- /dev/null
+++ b/src/gpu/GrGpuResourcePriv.h
@@ -0,0 +1,88 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGpuResourcePriv_DEFINED
+#define GrGpuResourcePriv_DEFINED
+
+#include "GrGpuResource.h"
+
+/**
+ * This class allows code internal to Skia privileged access to manage the cache keys and budget
+ * status of a GrGpuResource object.
+ */
+class GrGpuResource::ResourcePriv {
+public:
+    /**
+     * Sets a content key for the resource. If the resource was previously cached as scratch it will
+     * be converted to a content resource. Currently this may only be called once per resource. It
+     * fails if there is already a resource with the same content key. TODO: make this supplant the
+     * resource that currently is using the content key, allow resources' content keys to change,
+     * and allow removal of a content key to convert a resource back to scratch.
+     */
+    bool setContentKey(const GrContentKey& contentKey) {
+        return fResource->setContentKey(contentKey);
+    }
+
+    /** Removes the content key from a resource */
+    void removeContentKey() { return fResource->removeContentKey(); }
+
+    /**
+     * If the resource is uncached make it cached. Has no effect on resources that are wrapped or
+     * already cached.
+     */
+    void makeBudgeted() { fResource->makeBudgeted(); }
+
+    /**
+     * If the resource is cached make it uncached. Has no effect on resources that are wrapped or
+     * already uncached. Furthermore, resources with content keys cannot be made unbudgeted.
+     */
+    void makeUnbudgeted() { fResource->makeUnbudgeted(); }
+
+    /**
+     * Does the resource count against the resource budget?
+     */
+    bool isBudgeted() const {
+        bool ret = GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle;
+        SkASSERT(ret || !fResource->getContentKey().isValid());
+        return ret;
+    }
+
+    /** 
+     * If this resource can be used as a scratch resource this returns a valid scratch key.
+     * Otherwise it returns a key for which isNullScratch is true. The resource may currently be
+     * used as a content resource rather than scratch. Check isScratch().
+     */
+    const GrScratchKey& getScratchKey() const { return fResource->fScratchKey; }
+
+    /**
+     * If the resource has a scratch key, the key will be removed. Since scratch keys are installed
+     * at resource creation time, this means the resource will never again be used as scratch.
+     */
+    void removeScratchKey() const { fResource->removeScratchKey();  }
+
+protected:
+    ResourcePriv(GrGpuResource* resource) : fResource(resource) {   }
+    ResourcePriv(const ResourcePriv& that) : fResource(that.fResource) {}
+    ResourcePriv& operator=(const CacheAccess&); // unimpl
+
+    // No taking addresses of this type.
+    const ResourcePriv* operator&() const;
+    ResourcePriv* operator&();
+
+    GrGpuResource* fResource;
+
+    friend class GrGpuResource; // to construct/copy this type.
+};
+
+inline GrGpuResource::ResourcePriv GrGpuResource::resourcePriv() { return ResourcePriv(this); }
+
+inline const GrGpuResource::ResourcePriv GrGpuResource::resourcePriv() const {
+    return ResourcePriv(const_cast<GrGpuResource*>(this));
+}
+
+#endif
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 2b842a8..5cb1dd2 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -8,8 +8,7 @@
 
 
 #include "GrResourceCache.h"
-#include "GrGpuResource.h"  
-
+#include "GrGpuResourceCacheAccess.h"
 #include "SkChecksum.h"
 #include "SkGr.h"
 #include "SkMessageBus.h"
@@ -101,7 +100,7 @@
     fHighWaterCount = SkTMax(fCount, fHighWaterCount);
     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
 #endif
-    if (resource->cacheAccess().isBudgeted()) {
+    if (resource->resourcePriv().isBudgeted()) {
         ++fBudgetedCount;
         fBudgetedBytes += size;
 #if GR_CACHE_STATS
@@ -109,9 +108,9 @@
         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
 #endif
     }
-    if (resource->cacheAccess().getScratchKey().isValid()) {
+    if (resource->resourcePriv().getScratchKey().isValid()) {
         SkASSERT(!resource->cacheAccess().isWrapped());
-        fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
+        fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
     }
     
     this->purgeAsNeeded();
@@ -123,14 +122,14 @@
     size_t size = resource->gpuMemorySize();
     --fCount;
     fBytes -= size;
-    if (resource->cacheAccess().isBudgeted()) {
+    if (resource->resourcePriv().isBudgeted()) {
         --fBudgetedCount;
         fBudgetedBytes -= size;
     }
 
     fResources.remove(resource);
-    if (resource->cacheAccess().getScratchKey().isValid()) {
-        fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
+    if (resource->resourcePriv().getScratchKey().isValid()) {
+        fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource);
     }
     if (resource->getContentKey().isValid()) {
         fContentHash.remove(resource->getContentKey());
@@ -217,8 +216,8 @@
 }
 
 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) {
-    SkASSERT(resource->cacheAccess().getScratchKey().isValid());
-    fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
+    SkASSERT(resource->resourcePriv().getScratchKey().isValid());
+    fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource);
 }
 
 void GrResourceCache::willRemoveContentKey(const GrGpuResource* resource) {
@@ -268,14 +267,14 @@
 
     if (resource->cacheAccess().isWrapped()) {
         release = true;
-    } else if (!resource->cacheAccess().isBudgeted()) {
+    } else if (!resource->resourcePriv().isBudgeted()) {
         // Check whether this resource could still be used as a scratch resource.
-        if (resource->cacheAccess().getScratchKey().isValid()) {
+        if (resource->resourcePriv().getScratchKey().isValid()) {
             // We won't purge an existing resource to make room for this one.
             bool underBudget = fBudgetedCount < fMaxCount &&
                                fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes;
             if (underBudget) {
-                resource->cacheAccess().makeBudgeted();
+                resource->resourcePriv().makeBudgeted();
             } else {
                 release = true;
             }
@@ -287,7 +286,7 @@
         bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
 
         // Also purge if the resource has neither a valid scratch key nor a content key.
-        bool noKey = !resource->cacheAccess().getScratchKey().isValid() &&
+        bool noKey = !resource->resourcePriv().getScratchKey().isValid() &&
                      !resource->getContentKey().isValid();
         if (overBudget || noKey) {
             release = true;
@@ -314,7 +313,7 @@
 #if GR_CACHE_STATS
     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
 #endif
-    if (resource->cacheAccess().isBudgeted()) {
+    if (resource->resourcePriv().isBudgeted()) {
         fBudgetedBytes += delta;
 #if GR_CACHE_STATS
         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
@@ -332,7 +331,7 @@
 
     size_t size = resource->gpuMemorySize();
 
-    if (resource->cacheAccess().isBudgeted()) {
+    if (resource->resourcePriv().isBudgeted()) {
         ++fBudgetedCount;
         fBudgetedBytes += size;
 #if GR_CACHE_STATS
@@ -418,7 +417,7 @@
     for (int i = 0; i < msgs.count(); ++i) {
         GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key());
         if (resource) {
-            resource->cacheAccess().removeContentKey();
+            resource->resourcePriv().removeContentKey();
             resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable.
         }
     }
@@ -455,13 +454,13 @@
         if (resource->cacheAccess().isScratch()) {
             SkASSERT(!resource->getContentKey().isValid());
             ++scratch;
-            SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
+            SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratchKey()));
             SkASSERT(!resource->cacheAccess().isWrapped());
-        } else if (resource->cacheAccess().getScratchKey().isValid()) {
-            SkASSERT(!resource->cacheAccess().isBudgeted() ||
+        } else if (resource->resourcePriv().getScratchKey().isValid()) {
+            SkASSERT(!resource->resourcePriv().isBudgeted() ||
                      resource->getContentKey().isValid());
             ++couldBeScratch;
-            SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
+            SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratchKey()));
             SkASSERT(!resource->cacheAccess().isWrapped());
         }
         const GrContentKey& contentKey = resource->getContentKey();
@@ -469,10 +468,10 @@
             ++content;
             SkASSERT(fContentHash.find(contentKey) == resource);
             SkASSERT(!resource->cacheAccess().isWrapped());
-            SkASSERT(resource->cacheAccess().isBudgeted());
+            SkASSERT(resource->resourcePriv().isBudgeted());
         }
 
-        if (resource->cacheAccess().isBudgeted()) {
+        if (resource->resourcePriv().isBudgeted()) {
             ++budgetedCount;
             budgetedBytes += resource->gpuMemorySize();
         }
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 522641b..3e4eded 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -10,7 +10,7 @@
 #define GrResourceCache_DEFINED
 
 #include "GrGpuResource.h"
-#include "GrGpuResourceCacheAccess.h"
+#include "GrGpuResourcePriv.h"
 #include "GrResourceKey.h"
 #include "SkMessageBus.h"
 #include "SkRefCnt.h"
@@ -198,7 +198,7 @@
 
     struct ScratchMapTraits {
         static const GrScratchKey& GetKey(const GrGpuResource& r) {
-            return r.cacheAccess().getScratchKey();
+            return r.resourcePriv().getScratchKey();
         }
 
         static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 14259e6..72fde04 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -8,6 +8,7 @@
 
 #include "GrTest.h"
 
+#include "GrGpuResourceCacheAccess.h"
 #include "GrInOrderDrawBuffer.h"
 #include "GrResourceCache.h"
 #include "SkString.h"
@@ -96,7 +97,7 @@
         if (resource->cacheAccess().isWrapped()) {
             ++wrapped;
         }
-        if (!resource->cacheAccess().isBudgeted()) {
+        if (!resource->resourcePriv().isBudgeted()) {
             unbudgetedSize += resource->gpuMemorySize();
         }
     }
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 21d2f63..5813d5d 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -9,7 +9,7 @@
 #include "GrGLGpu.h"
 #include "GrGLStencilBuffer.h"
 #include "GrGLTextureRenderTarget.h"
-#include "GrGpuResourceCacheAccess.h"
+#include "GrGpuResourcePriv.h"
 #include "GrPipeline.h"
 #include "GrSurfacePriv.h"
 #include "GrTemplates.h"
@@ -1186,7 +1186,7 @@
             }
             // Remove the scratch key from this resource so we don't grab it from the cache ever
             // again.
-            sb->cacheAccess().removeScratchKey();
+            sb->resourcePriv().removeScratchKey();
             // Set this to 0 since we handed the valid ID off to the failed stencil buffer resource.
             sbDesc.fRenderbufferID = 0;
         }
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index f20625a..f4ca064 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -9,7 +9,7 @@
 #define SkImage_Gpu_DEFINED
 
 #include "GrTexture.h"
-#include "GrGpuResourceCacheAccess.h"
+#include "GrGpuResourcePriv.h"
 #include "SkBitmap.h"
 #include "SkImage_Base.h"
 #include "SkImagePriv.h"
@@ -38,9 +38,9 @@
 
     void applyBudgetDecision() const {
         if (fBudgeted) {
-            fBitmap.getTexture()->cacheAccess().makeBudgeted();
+            fBitmap.getTexture()->resourcePriv().makeBudgeted();
         } else {
-            fBitmap.getTexture()->cacheAccess().makeUnbudgeted();
+            fBitmap.getTexture()->resourcePriv().makeUnbudgeted();
         }
     }
 
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 34aec2b..a1c31f3 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -7,7 +7,7 @@
 
 #include "SkSurface_Gpu.h"
 
-#include "GrGpuResourceCacheAccess.h"
+#include "GrGpuResourcePriv.h"
 #include "SkCanvas.h"
 #include "SkGpuDevice.h"
 #include "SkImage_Base.h"
@@ -70,8 +70,8 @@
     SkASSERT(image);
     if (rt->asTexture() == SkTextureImageGetTexture(image)) {
         GrRenderTarget* oldRT = this->fDevice->accessRenderTarget();
-        SkSurface::Budgeted budgeted = oldRT->cacheAccess().isBudgeted() ? kYes_Budgeted :
-                                                                           kNo_Budgeted;
+        SkSurface::Budgeted budgeted = oldRT->resourcePriv().isBudgeted() ? kYes_Budgeted :
+                                                                            kNo_Budgeted;
         SkAutoTUnref<SkGpuDevice> newDevice(
             SkGpuDevice::Create(oldRT->getContext(), budgeted, fDevice->imageInfo(),
                                 oldRT->numSamples(), &this->props(), 0));