Replaced TextureCacheEntry with GrTexture* and a back pointer to GrResourceEntry (in GrTexture)

http://codereview.appspot.com/6460089/



git-svn-id: http://skia.googlecode.com/svn/trunk@5122 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 57f0aeb..0c4d73c 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -95,30 +95,8 @@
     // Textures
 
     /**
-     * Token that refers to an entry in the texture cache. Returned by
-     * functions that lock textures. Passed to unlockTexture.
-     */
-    class SK_API TextureCacheEntry {
-    public:
-        TextureCacheEntry() : fEntry(NULL) {}
-        TextureCacheEntry(const TextureCacheEntry& e) : fEntry(e.fEntry) {}
-        TextureCacheEntry& operator= (const TextureCacheEntry& e) {
-            fEntry = e.fEntry;
-            return *this;
-        }
-        GrTexture* texture() const;
-        void reset() { fEntry = NULL; }
-        GrResourceEntry* cacheEntry() { return fEntry; }
-    private:
-        explicit TextureCacheEntry(GrResourceEntry* entry) { fEntry = entry; }
-        void set(GrResourceEntry* entry) { fEntry = entry; }
-        GrResourceEntry* fEntry;
-        friend class GrContext;
-    };
-
-    /**
      *  Create a new entry, based on the specified key and texture, and return
-     *  its "locked" entry. Must call be balanced with an unlockTexture() call.
+     *  a "locked" texture. Must call be balanced with an unlockTexture() call.
      *
      * @param params    The tex params used to draw a texture may help determine
      *                  the cache entry used. (e.g. different versions may exist
@@ -130,14 +108,14 @@
      * @param rowBytes  The number of bytes between rows of the texture. Zero
      *                  implies tightly packed rows.
      */
-    TextureCacheEntry createAndLockTexture(const GrTextureParams* params,
-                                           const GrTextureDesc& desc,
-                                           const GrCacheData& cacheData,
-                                           void* srcData, size_t rowBytes);
+    GrTexture* createAndLockTexture(const GrTextureParams* params,
+                                    const GrTextureDesc& desc,
+                                    const GrCacheData& cacheData,
+                                    void* srcData, size_t rowBytes);
 
     /**
      *  Search for an entry based on key and dimensions. If found, "lock" it and
-     *  return it. The entry's texture() function will return NULL if not found.
+     *  return it. The return value will be NULL if not found.
      *  Must be balanced with an unlockTexture() call.
      *
      *  @param desc     Description of the texture properties.
@@ -147,9 +125,9 @@
      *                  for different wrap modes on GPUs with limited NPOT
      *                  texture support). NULL implies clamp wrap modes.
      */
-    TextureCacheEntry findAndLockTexture(const GrTextureDesc& desc,
-                                         const GrCacheData& cacheData,
-                                         const GrTextureParams* params);
+    GrTexture* findAndLockTexture(const GrTextureDesc& desc,
+                                  const GrCacheData& cacheData,
+                                  const GrTextureParams* params);
     /**
      * Determines whether a texture is in the cache. If the texture is found it
      * will not be locked or returned. This call does not affect the priority of
@@ -191,19 +169,25 @@
      * such an API will create gaps in the tiling pattern. This includes clamp
      * mode. (This may be addressed in a future update.)
      */
-    TextureCacheEntry lockScratchTexture(const GrTextureDesc& desc, 
-                                         ScratchTexMatch match);
+    GrTexture* lockScratchTexture(const GrTextureDesc& desc, 
+                                  ScratchTexMatch match);
 
     /**
      *  When done with an entry, call unlockTexture(entry) on it, which returns
      *  it to the cache, where it may be purged.
      */
-    void unlockTexture(TextureCacheEntry entry);
+    void unlockTexture(GrTexture* texture);
 
     /**
-     * Free any data associated with the provided entry in the texture cache
+     * Free any data associated with the provided entry in the texture cache.
+     * Currently this entry point is only used when a scratch texture is 
+     * detached from the cache. In this case the GrResourceEntry* associated
+     * with the texture needs to be freed since it will be re-allocated when
+     * the texture is re-added. This entry point will be removed soon since the
+     * texture can now carry around a pointer to its GrResourceEntry* (and
+     * will eventually take over its functionality).
      */
-    void freeEntry(TextureCacheEntry entry);
+    void freeEntry(GrTexture* texture);
 
     /**
      * Creates a texture that is outside the cache. Does not count against
@@ -753,8 +737,8 @@
      * a SB that matching an RT's criteria. If a match is found that has been
      * unlocked (its attachment count has reached 0) then it will be relocked.
      */
-    GrResourceEntry* addAndLockStencilBuffer(GrStencilBuffer* sb);
-    void unlockStencilBuffer(GrResourceEntry* sbEntry);
+    void addAndLockStencilBuffer(GrStencilBuffer* sb);
+    void unlockStencilBuffer(GrStencilBuffer* sb);
     GrStencilBuffer* findStencilBuffer(int width, int height, int sampleCnt);
 
     GrPathRenderer* getPathRenderer(const SkPath& path,
@@ -861,14 +845,16 @@
 class GrAutoScratchTexture : ::GrNoncopyable {
 public:
     GrAutoScratchTexture()
-        : fContext(NULL) {
+        : fContext(NULL)
+        , fTexture(NULL) {
     }
 
     GrAutoScratchTexture(GrContext* context,
                          const GrTextureDesc& desc,
                          GrContext::ScratchTexMatch match =
                             GrContext::kApprox_ScratchTexMatch)
-      : fContext(NULL) {
+      : fContext(NULL)
+      , fTexture(NULL) {
       this->set(context, desc, match);
     }
     
@@ -877,9 +863,9 @@
     }
 
     void reset() {
-        if (NULL != fContext && NULL != fEntry.cacheEntry()) {
-            fContext->unlockTexture(fEntry);
-            fEntry.reset();
+        if (NULL != fContext && NULL != fTexture) {
+            fContext->unlockTexture(fTexture);
+            fTexture = NULL;
         }
     }
 
@@ -896,14 +882,14 @@
      * returned texture.
      */
     GrTexture* detach() {
-        GrTexture* temp = this->texture();
+        GrTexture* temp = fTexture;
 
         GrAssert(1 == temp->getRefCnt());
 
         // freeEntry will remove the texture cache's ref
         temp->ref();
-        fContext->freeEntry(fEntry);
-        fEntry.reset();
+        fContext->freeEntry(fTexture);
+        fTexture = NULL;
 
         temp->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
         GrAssert(1 == temp->getRefCnt());
@@ -918,21 +904,21 @@
 
         fContext = context;
         if (NULL != fContext) {
-            fEntry = fContext->lockScratchTexture(desc, match);
-            GrTexture* ret = fEntry.texture();
-            if (NULL == ret) {
+            fTexture = fContext->lockScratchTexture(desc, match);
+            if (NULL == fTexture) {
                 fContext = NULL;
             }
-            return ret;
+            return fTexture;
         } else {
             return NULL;
         }
     }
 
-    GrTexture* texture() { return fEntry.texture(); }
+    GrTexture* texture() { return fTexture; }
+
 private:
     GrContext*                    fContext;
-    GrContext::TextureCacheEntry  fEntry;
+    GrTexture*                    fTexture;
 };
 
 #endif
diff --git a/include/gpu/GrResource.h b/include/gpu/GrResource.h
index 94d2173..0f4b03d 100644
--- a/include/gpu/GrResource.h
+++ b/include/gpu/GrResource.h
@@ -14,6 +14,7 @@
 
 class GrGpu;
 class GrContext;
+class GrResourceEntry;
 
 /**
  * Base class for the GPU resources created by a GrContext.
@@ -52,7 +53,7 @@
      *
      * @return the size of the buffer in bytes
      */
-     virtual size_t sizeInBytes() const = 0;
+    virtual size_t sizeInBytes() const = 0;
 
      /**
       * Retrieves the context that owns the resource. Note that it is possible
@@ -60,8 +61,11 @@
       * abandon()ed they no longer have an owning context. Destroying a
       * GrContext automatically releases all its resources.
       */
-     const GrContext* getContext() const;
-     GrContext* getContext();
+    const GrContext* getContext() const;
+    GrContext* getContext();
+
+    void setCacheEntry(GrResourceEntry* cacheEntry) { fCacheEntry = cacheEntry; }
+    GrResourceEntry* getCacheEntry() { return fCacheEntry; }
 
 protected:
     explicit GrResource(GrGpu* gpu);
@@ -83,6 +87,8 @@
     GrResource* fNext;      // dl-list of resources per-GrGpu
     GrResource* fPrevious;
 
+    GrResourceEntry* fCacheEntry;  // NULL if not in cache
+
     typedef GrRefCnt INHERITED;
 };
 
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 539372a..c2fc186 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -116,7 +116,6 @@
     class SkAutoCachedTexture; // used internally
 
 protected:
-    typedef GrContext::TextureCacheEntry TexCache;
     bool isBitmapInTextureCache(const SkBitmap& bitmap,
                                 const GrTextureParams& params) const;
 
@@ -133,7 +132,8 @@
     GrClipData      fClipData;
 
     // state for our offscreen render-target
-    TexCache            fCache;
+    // TODO: remove 'fCached' and let fTexture automatically return to the cache
+    bool                fCached;        // is fTexture in the cache
     GrTexture*          fTexture;
     GrRenderTarget*     fRenderTarget;
     bool                fNeedClear;
@@ -143,7 +143,7 @@
     void initFromRenderTarget(GrContext*, GrRenderTarget*);
 
     // used by createCompatibleDevice
-    SkGpuDevice(GrContext*, GrTexture* texture, TexCache, bool needClear);
+    SkGpuDevice(GrContext*, GrTexture* texture, bool needClear);
 
     // override from SkDevice
     virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 35badfa..88ca08a 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -75,11 +75,11 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrContext::TextureCacheEntry GrLockCachedBitmapTexture(GrContext*,
-                                                       const SkBitmap&,
-                                                       const GrTextureParams*);
+GrTexture* GrLockCachedBitmapTexture(GrContext*,
+                                     const SkBitmap&,
+                                     const GrTextureParams*);
 
-void GrUnlockCachedBitmapTexture(GrContext*, GrContext::TextureCacheEntry);
+void GrUnlockCachedBitmapTexture(GrTexture*);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Classes
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index a07b388..0bdbe54 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -705,16 +705,15 @@
     SkBitmap bitmap;
     shader.getGradientTableBitmap(&bitmap);
 
-    GrContext::TextureCacheEntry entry = GrLockCachedBitmapTexture(ctx, bitmap,
-                                                                   sampler->textureParams());
-    fTexture = entry.texture();
+    fTexture = GrLockCachedBitmapTexture(ctx, bitmap,
+                                         sampler->textureParams());
     SkSafeRef(fTexture);
     fUseTexture = true;
 
     // Unlock immediately, this is not great, but we don't have a way of
     // knowing when else to unlock it currently, so it may get purged from
     // the cache, but it'll still be ref'd until it's no longer being used.
-    GrUnlockCachedBitmapTexture(ctx, entry);
+    GrUnlockCachedBitmapTexture(fTexture);
 }
 
 GrGradientEffect::~GrGradientEffect() {
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index e21383e..a8b6808 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -167,14 +167,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrTexture* GrContext::TextureCacheEntry::texture() const {
-    if (NULL == fEntry) {
-        return NULL; 
-    } else {
-        return (GrTexture*) fEntry->resource();
-    }
-}
-
 namespace {
 
 void scale_rect(SkRect* rect, float xScale, float yScale) {
@@ -237,12 +229,13 @@
 
 }
 
-GrContext::TextureCacheEntry GrContext::findAndLockTexture(const GrTextureDesc& desc,
-                                                           const GrCacheData& cacheData,
-                                                           const GrTextureParams* params) {
+GrTexture* GrContext::findAndLockTexture(const GrTextureDesc& desc,
+                                         const GrCacheData& cacheData,
+                                         const GrTextureParams* params) {
     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false);
-    return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
-                                            GrResourceCache::kNested_LockType));
+    GrResource* resource = fTextureCache->findAndLock(resourceKey,
+                                                      GrResourceCache::kNested_LockType);
+    return static_cast<GrTexture*>(resource);
 }
 
 bool GrContext::isTextureInCache(const GrTextureDesc& desc,
@@ -252,13 +245,13 @@
     return fTextureCache->hasKey(resourceKey);
 }
 
-GrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
+void GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
     ASSERT_OWNED_RESOURCE(sb);
 
     GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
                                                             sb->height(),
                                                             sb->numSamples());
-    return fTextureCache->createAndLock(resourceKey, sb);
+    fTextureCache->createAndLock(resourceKey, sb);
 }
 
 GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
@@ -266,19 +259,16 @@
     GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
                                                             height,
                                                             sampleCnt);
-    GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
+    GrResource* resource = fTextureCache->findAndLock(resourceKey,
                                             GrResourceCache::kSingle_LockType);
-    if (NULL != entry) {
-        GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
-        return sb;
-    } else {
-        return NULL;
-    }
+    return static_cast<GrStencilBuffer*>(resource);
 }
 
-void GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
-    ASSERT_OWNED_RESOURCE(sbEntry->resource());
-    fTextureCache->unlock(sbEntry);
+void GrContext::unlockStencilBuffer(GrStencilBuffer* sb) {
+    ASSERT_OWNED_RESOURCE(sb);
+    GrAssert(NULL != sb->getCacheEntry());
+
+    fTextureCache->unlock(sb->getCacheEntry());
 }
 
 static void stretchImage(void* dst,
@@ -315,12 +305,12 @@
                                            void* srcData,
                                            size_t rowBytes,
                                            bool needsFiltering) {
-    TextureCacheEntry clampEntry = this->findAndLockTexture(desc, cacheData, NULL);
+    GrTexture* clampedTexture = this->findAndLockTexture(desc, cacheData, NULL);
 
-    if (NULL == clampEntry.texture()) {
-        clampEntry = this->createAndLockTexture(NULL, desc, cacheData, srcData, rowBytes);
-        GrAssert(NULL != clampEntry.texture());
-        if (NULL == clampEntry.texture()) {
+    if (NULL == clampedTexture) {
+        clampedTexture = this->createAndLockTexture(NULL, desc, cacheData, srcData, rowBytes);
+        GrAssert(NULL != clampedTexture);
+        if (NULL == clampedTexture) {
             return NULL;
         }
     }
@@ -343,7 +333,7 @@
         // the original.
         drawState->sampler(0)->reset(SkShader::kClamp_TileMode,
                                      needsFiltering);
-        drawState->createTextureEffect(0, clampEntry.texture());
+        drawState->createTextureEffect(0, clampedTexture);
 
         static const GrVertexLayout layout =
                             GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
@@ -384,12 +374,12 @@
                                                     stretchedRowBytes);
         GrAssert(NULL != texture);
     }
-    fTextureCache->unlock(clampEntry.cacheEntry());
+    this->unlockTexture(clampedTexture);
 
     return texture;
 }
 
-GrContext::TextureCacheEntry GrContext::createAndLockTexture(
+GrTexture* GrContext::createAndLockTexture(
         const GrTextureParams* params,
         const GrTextureDesc& desc,
         const GrCacheData& cacheData,
@@ -401,8 +391,6 @@
     GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
 #endif
 
-    TextureCacheEntry entry;
-
     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false);
 
     GrTexture* texture = NULL;
@@ -415,15 +403,14 @@
     }
 
     if (NULL != texture) {
-        entry.set(fTextureCache->createAndLock(resourceKey, texture));
+        fTextureCache->createAndLock(resourceKey, texture);
     }
 
-    return entry;
+    return texture;
 }
 
-GrContext::TextureCacheEntry GrContext::lockScratchTexture(
-                                                const GrTextureDesc& inDesc,
-                                                ScratchTexMatch match) {
+GrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc,
+                                         ScratchTexMatch match) {
     GrTextureDesc desc = inDesc;
     GrCacheData cacheData(GrCacheData::kScratch_CacheID);
 
@@ -434,7 +421,7 @@
         desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
     }
 
-    GrResourceEntry* entry;
+    GrResource* resource = NULL;
     int origWidth = desc.fWidth;
     int origHeight = desc.fHeight;
     bool doubledW = false;
@@ -442,11 +429,11 @@
 
     do {
         GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, cacheData, true);
-        entry = fTextureCache->findAndLock(key,
-                                           GrResourceCache::kNested_LockType);
+        resource = fTextureCache->findAndLock(key,
+                                              GrResourceCache::kNested_LockType);
         // if we miss, relax the fit of the flags...
         // then try doubling width... then height.
-        if (NULL != entry || kExact_ScratchTexMatch == match) {
+        if (NULL != resource || kExact_ScratchTexMatch == match) {
             break;
         }
         if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
@@ -468,7 +455,7 @@
         
     } while (true);
 
-    if (NULL == entry) {
+    if (NULL == resource) {
         desc.fFlags = inDesc.fFlags;
         desc.fWidth = origWidth;
         desc.fHeight = origHeight;
@@ -478,17 +465,18 @@
                                                       texture->desc(),
                                                       cacheData,
                                                       true);
-            entry = fTextureCache->createAndLock(key, texture);
+            fTextureCache->createAndLock(key, texture);
+            resource = texture;
         }
     }
 
     // If the caller gives us the same desc/sampler twice we don't want
     // to return the same texture the second time (unless it was previously
     // released). So we detach the entry from the cache and reattach at release.
-    if (NULL != entry) {
-        fTextureCache->detach(entry);
+    if (NULL != resource) {
+        fTextureCache->detach(resource->getCacheEntry());
     }
-    return TextureCacheEntry(entry);
+    return static_cast<GrTexture*>(resource);
 }
 
 void GrContext::addExistingTextureToCache(GrTexture* texture) {
@@ -507,22 +495,26 @@
     fTextureCache->attach(key, texture);
 }
 
-void GrContext::unlockTexture(TextureCacheEntry entry) {
-    ASSERT_OWNED_RESOURCE(entry.texture());
+void GrContext::unlockTexture(GrTexture* texture) {
+    ASSERT_OWNED_RESOURCE(texture);
+    GrAssert(NULL != texture->getCacheEntry());
+
     // If this is a scratch texture we detached it from the cache
     // while it was locked (to avoid two callers simultaneously getting
     // the same texture).
-    if (GrTexture::IsScratchTexture(entry.cacheEntry()->key())) {
-        fTextureCache->reattachAndUnlock(entry.cacheEntry());
+    if (GrTexture::IsScratchTexture(texture->getCacheEntry()->key())) {
+        fTextureCache->reattachAndUnlock(texture->getCacheEntry());
     } else {
-        fTextureCache->unlock(entry.cacheEntry());
+        fTextureCache->unlock(texture->getCacheEntry());
     }
 }
 
-void GrContext::freeEntry(TextureCacheEntry entry) {
-    ASSERT_OWNED_RESOURCE(entry.texture());
+void GrContext::freeEntry(GrTexture* texture) {
+    ASSERT_OWNED_RESOURCE(texture);
+    GrAssert(NULL != texture->getCacheEntry());
 
-    fTextureCache->freeEntry(entry.cacheEntry());
+    fTextureCache->freeEntry(texture->getCacheEntry());
+    texture->setCacheEntry(NULL);
 }
 
 GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
diff --git a/src/gpu/GrResource.cpp b/src/gpu/GrResource.cpp
index 7e2d4a8..74fc63d4 100644
--- a/src/gpu/GrResource.cpp
+++ b/src/gpu/GrResource.cpp
@@ -16,6 +16,7 @@
     fGpu        = gpu;
     fNext       = NULL;
     fPrevious   = NULL;
+    fCacheEntry = NULL;
     fGpu->insertResource(this);
 }
 
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index b82cdb2..982d45e 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -28,6 +28,7 @@
 void GrResourceEntry::validate() const {
     GrAssert(fLockCount >= 0);
     GrAssert(fResource);
+    GrAssert(fResource->getCacheEntry() == this);
     fResource->validate();
 }
 #endif
@@ -158,21 +159,24 @@
 #endif
 };
 
-GrResourceEntry* GrResourceCache::findAndLock(const GrResourceKey& key,
-                                              LockType type) {
+GrResource* GrResourceCache::findAndLock(const GrResourceKey& key,
+                                         LockType type) {
     GrAutoResourceCacheValidate atcv(this);
 
     GrResourceEntry* entry = fCache.find(key);
-    if (entry) {
-        this->internalDetach(entry, false);
-        // mark the entry as "busy" so it doesn't get purged
-        // do this between detach and attach for locked count tracking
-        if (kNested_LockType == type || !entry->isLocked()) {
-            entry->lock();
-        }
-        this->attachToHead(entry, false);
+    if (NULL == entry) {
+        return NULL;
     }
-    return entry;
+
+    this->internalDetach(entry, false);
+    // mark the entry as "busy" so it doesn't get purged
+    // do this between detach and attach for locked count tracking
+    if (kNested_LockType == type || !entry->isLocked()) {
+        entry->lock();
+    }
+    this->attachToHead(entry, false);
+
+    return entry->fResource;
 }
 
 bool GrResourceCache::hasKey(const GrResourceKey& key) const {
@@ -192,6 +196,8 @@
 
     GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
 
+    resource->setCacheEntry(entry);
+
     if (lock) {
         // mark the entry as "busy" so it doesn't get purged
         // do this before attach for locked count tracking
@@ -210,13 +216,15 @@
     return entry;
 }
 
-GrResourceEntry* GrResourceCache::createAndLock(const GrResourceKey& key,
-                                                GrResource* resource) {
-    return this->create(key, resource, true, false);
+void GrResourceCache::createAndLock(const GrResourceKey& key,
+                                    GrResource* resource) {
+    GrAssert(NULL == resource->getCacheEntry());
+    this->create(key, resource, true, false);
 }
 
 void GrResourceCache::attach(const GrResourceKey& key,
                              GrResource* resource) {
+    GrAssert(NULL == resource->getCacheEntry());
     this->create(key, resource, false, true);
 }
 
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 076097d..d708e0a 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -225,7 +225,7 @@
      *  Search for an entry with the same Key. If found, "lock" it and return it.
      *  If not found, return null.
      */
-    GrResourceEntry* findAndLock(const GrResourceKey&, LockType style);
+    GrResource* findAndLock(const GrResourceKey&, LockType style);
 
     /**
      *  Create a new cache entry, based on the provided key and resource, and 
@@ -234,7 +234,7 @@
      *  Ownership of the resource is transferred to the resource cache, 
      *  which will unref() it when it is purged or deleted.
      */
-    GrResourceEntry* createAndLock(const GrResourceKey&, GrResource*);
+    void createAndLock(const GrResourceKey&, GrResource*);
 
     /**
      *  Create a new cache entry, based on the provided key and resource.
diff --git a/src/gpu/GrStencilBuffer.cpp b/src/gpu/GrStencilBuffer.cpp
index 53a4a65..7f733f4 100644
--- a/src/gpu/GrStencilBuffer.cpp
+++ b/src/gpu/GrStencilBuffer.cpp
@@ -23,9 +23,11 @@
 }
 
 void GrStencilBuffer::transferToCacheAndLock() {
-    GrAssert(NULL == fCacheEntry);
-    fCacheEntry = 
-        this->getGpu()->getContext()->addAndLockStencilBuffer(this);
+    GrAssert(NULL == this->getCacheEntry());
+    GrAssert(!fHoldingLock);
+
+    this->getGpu()->getContext()->addAndLockStencilBuffer(this);
+    fHoldingLock = true;
 }
 
 void GrStencilBuffer::onRelease() {
@@ -39,7 +41,7 @@
         this->unlockInCache();
         // we shouldn't be deleted here because some RT still has a ref on us.
     }
-    fCacheEntry = NULL;
+    fHoldingLock = false;
 }
 
 void GrStencilBuffer::onAbandon() {
@@ -48,11 +50,11 @@
 }
 
 void GrStencilBuffer::unlockInCache() {
-    if (NULL != fCacheEntry) {
+    if (fHoldingLock) {
         GrGpu* gpu = this->getGpu();
         if (NULL != gpu) {
             GrAssert(NULL != gpu->getContext());
-            gpu->getContext()->unlockStencilBuffer(fCacheEntry);
+            gpu->getContext()->unlockStencilBuffer(this);
         }
     }
 }
diff --git a/src/gpu/GrStencilBuffer.h b/src/gpu/GrStencilBuffer.h
index 649e130..f83590a 100644
--- a/src/gpu/GrStencilBuffer.h
+++ b/src/gpu/GrStencilBuffer.h
@@ -84,7 +84,7 @@
         , fLastClipData()
         , fLastClipWidth(-1)
         , fLastClipHeight(-1)
-        , fCacheEntry(NULL)
+        , fHoldingLock(false)
         , fRTAttachmentCnt(0) {
     }
 
@@ -109,7 +109,7 @@
     int         fLastClipWidth;
     int         fLastClipHeight;
 
-    GrResourceEntry* fCacheEntry;
+    bool             fHoldingLock;
     int              fRTAttachmentCnt;
 
     typedef GrResource INHERITED;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 496c096..e3ce2dc 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -81,43 +81,47 @@
 
 class SkGpuDevice::SkAutoCachedTexture : public ::SkNoncopyable {
 public:
-    SkAutoCachedTexture() { }    
+    SkAutoCachedTexture()
+        : fDevice(NULL)
+        , fTexture(NULL) {
+    }    
+
     SkAutoCachedTexture(SkGpuDevice* device,
                         const SkBitmap& bitmap,
                         const GrTextureParams* params,
-                        GrTexture** texture) {
-        GrAssert(texture);
+                        GrTexture** texture)
+        : fDevice(NULL)
+        , fTexture(NULL) {
+        GrAssert(NULL != texture);
         *texture = this->set(device, bitmap, params);
     }
 
     ~SkAutoCachedTexture() {
-        if (fTex.texture()) {
-            GrUnlockCachedBitmapTexture(fDevice->context(), fTex);
+        if (NULL != fTexture) {
+            GrUnlockCachedBitmapTexture(fTexture);
         }
     }
 
     GrTexture* set(SkGpuDevice* device,
                    const SkBitmap& bitmap,
                    const GrTextureParams* params) {
-        if (fTex.texture()) {
-            GrUnlockCachedBitmapTexture(fDevice->context(), fTex);
+        if (NULL != fTexture) {
+            GrUnlockCachedBitmapTexture(fTexture);
+            fTexture = NULL;
         }
         fDevice = device;
-        GrTexture* texture = (GrTexture*)bitmap.getTexture();
-        if (texture) {
-            // return the native texture
-            fTex.reset();
-        } else {
-            // look it up in our cache
-            fTex = GrLockCachedBitmapTexture(device->context(), bitmap, params);
-            texture = fTex.texture();
+        GrTexture* result = (GrTexture*)bitmap.getTexture();
+        if (NULL == result) {
+            // Cannot return the native texture so look it up in our cache
+            fTexture = GrLockCachedBitmapTexture(device->context(), bitmap, params);
+            result = fTexture;
         }
-        return texture;
+        return result;
     }
     
 private:
     SkGpuDevice* fDevice;
-    GrContext::TextureCacheEntry fTex;
+    GrTexture*   fTexture;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -184,6 +188,7 @@
     fContext = context;
     fContext->ref();
 
+    fCached = false;
     fTexture = NULL;
     fRenderTarget = NULL;
     fNeedClear = false;
@@ -221,6 +226,7 @@
     fContext = context;
     fContext->ref();
 
+    fCached = false;
     fTexture = NULL;
     fRenderTarget = NULL;
     fNeedClear = false;
@@ -266,10 +272,9 @@
 
     SkSafeUnref(fTexture);
     SkSafeUnref(fRenderTarget);
-    if (fCache.texture()) {
-        GrAssert(NULL != fTexture);
+    if (NULL != fTexture && fCached) {
         GrAssert(fRenderTarget == fTexture->asRenderTarget());
-        fContext->unlockTexture(fCache);
+        fContext->unlockTexture(fTexture);
     }
     fContext->unref();
 }
@@ -1925,7 +1930,6 @@
     desc.fHeight = height;
     desc.fSampleCnt = fRenderTarget->numSamples();
 
-    GrContext::TextureCacheEntry cacheEntry;
     GrTexture* texture;
     SkAutoTUnref<GrTexture> tunref;
     // Skia's convention is to only clear a device if it is non-opaque.
@@ -1937,8 +1941,7 @@
     GrContext::ScratchTexMatch matchType = (kSaveLayer_Usage == usage) ?
                                     GrContext::kApprox_ScratchTexMatch :
                                     GrContext::kExact_ScratchTexMatch;
-    cacheEntry = fContext->lockScratchTexture(desc, matchType);
-    texture = cacheEntry.texture();
+    texture = fContext->lockScratchTexture(desc, matchType);
 #else
     tunref.reset(fContext->createUncachedTexture(desc, NULL, 0));
     texture = tunref.get();
@@ -1946,7 +1949,6 @@
     if (texture) {
         return SkNEW_ARGS(SkGpuDevice,(fContext,
                                        texture,
-                                       cacheEntry,
                                        needClear));
     } else {
         GrPrintf("---- failed to create compatible device texture [%d %d]\n",
@@ -1957,13 +1959,11 @@
 
 SkGpuDevice::SkGpuDevice(GrContext* context,
                          GrTexture* texture,
-                         TexCache cacheEntry,
                          bool needClear)
     : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
 
     GrAssert(texture && texture->asRenderTarget());
-    GrAssert(NULL == cacheEntry.texture() || texture == cacheEntry.texture());
     this->initFromRenderTarget(context, texture->asRenderTarget());
-    fCache = cacheEntry;
+    fCached = true;
     fNeedClear = needClear;
 }
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 8240eb1..a98b8fd 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -56,15 +56,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
-                                                uint64_t key,
-                                                const GrTextureParams* params,
-                                                const SkBitmap& origBitmap) {
+static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
+                                              uint64_t key,
+                                              const GrTextureParams* params,
+                                              const SkBitmap& origBitmap) {
     SkAutoLockPixels alp(origBitmap);
-    GrContext::TextureCacheEntry entry;
 
     if (!origBitmap.readyToDraw()) {
-        return entry;
+        return NULL;
     }
 
     SkBitmap tmpBitmap;
@@ -97,12 +96,12 @@
                                                  storage.get(),
                                                  bitmap->width());
             } else {
-                entry = ctx->lockScratchTexture(desc,
-                                        GrContext::kExact_ScratchTexMatch);
-                entry.texture()->writePixels(0, 0, bitmap->width(), 
-                                             bitmap->height(), desc.fConfig,
-                                             storage.get(), 0);
-                return entry;
+                GrTexture* result = ctx->lockScratchTexture(desc,
+                                          GrContext::kExact_ScratchTexMatch);
+                result->writePixels(0, 0, bitmap->width(), 
+                                    bitmap->height(), desc.fConfig,
+                                    storage.get(), 0);
+                return result;
             }
 
         } else {
@@ -125,23 +124,23 @@
         // cache so no one else can find it. Additionally, once unlocked, the 
         // scratch texture will go to the end of the list for purging so will 
         // likely be available for this volatile bitmap the next time around.
-        entry = ctx->lockScratchTexture(desc,
-                                        GrContext::kExact_ScratchTexMatch);
-        entry.texture()->writePixels(0, 0,
-                                     bitmap->width(), bitmap->height(),
-                                     desc.fConfig,
-                                     bitmap->getPixels(),
-                                     bitmap->rowBytes());
-        return entry;
+        GrTexture* result = ctx->lockScratchTexture(desc,
+                                         GrContext::kExact_ScratchTexMatch);
+        result->writePixels(0, 0,
+                            bitmap->width(), bitmap->height(),
+                            desc.fConfig,
+                            bitmap->getPixels(),
+                            bitmap->rowBytes());
+        return result;
     }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrContext::TextureCacheEntry GrLockCachedBitmapTexture(GrContext* ctx, 
-                                                       const SkBitmap& bitmap,
-                                                       const GrTextureParams* params) {
-    GrContext::TextureCacheEntry entry;
+GrTexture* GrLockCachedBitmapTexture(GrContext* ctx, 
+                                     const SkBitmap& bitmap,
+                                     const GrTextureParams* params) {
+    GrTexture* result = NULL;
 
     if (!bitmap.isVolatile()) {
         // If the bitmap isn't changing try to find a cached copy first
@@ -155,22 +154,24 @@
 
         GrCacheData cacheData(key);
 
-        entry = ctx->findAndLockTexture(desc, cacheData, params);
-        if (NULL == entry.texture()) {
-            entry = sk_gr_create_bitmap_texture(ctx, key, params, bitmap);
+        result = ctx->findAndLockTexture(desc, cacheData, params);
+        if (NULL == result) {
+            result = sk_gr_create_bitmap_texture(ctx, key, params, bitmap);
         }
     } else {
-        entry = sk_gr_create_bitmap_texture(ctx, GrCacheData::kScratch_CacheID, params, bitmap);
+        result = sk_gr_create_bitmap_texture(ctx, GrCacheData::kScratch_CacheID, params, bitmap);
     }
-    if (NULL == entry.texture()) {
+    if (NULL == result) {
         GrPrintf("---- failed to create texture for cache [%d %d]\n",
                     bitmap.width(), bitmap.height());
     }
-    return entry;
+    return result;
 }
 
-void GrUnlockCachedBitmapTexture(GrContext* ctx, GrContext::TextureCacheEntry cache) {
-    ctx->unlockTexture(cache);
+void GrUnlockCachedBitmapTexture(GrTexture* texture) {
+    GrAssert(NULL != texture->getContext());
+
+    texture->getContext()->unlockTexture(texture);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index 1a8a93b..a1a9d03 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -63,6 +63,7 @@
     , fLockedRows(0)
     , fDesc(desc)
     , fNumRows(desc.fHeight / desc.fRowHeight)
+    , fTexture(NULL)
     , fRows(SkNEW_ARRAY(AtlasRow, fNumRows))
     , fLRUFront(NULL)
     , fLRUBack(NULL) {
@@ -139,7 +140,7 @@
 
         // Pass in the kDontFlush flag, since we know we're writing to a part of this texture
         // that is not currently in use
-        fDesc.fContext->internalWriteTexturePixels(fEntry.texture(), 0, 
+        fDesc.fContext->internalWriteTexturePixels(fTexture, 0, 
                                                    rowNumber * fDesc.fRowHeight, 
                                                    fDesc.fWidth,
                                                    fDesc.fRowHeight, 
@@ -182,20 +183,20 @@
     texDesc.fConfig = fDesc.fConfig;
     GrCacheData cacheData(fCacheID);
     cacheData.fResourceDomain = GetTextureStripAtlasDomain();
-    fEntry = fDesc.fContext->findAndLockTexture(texDesc, cacheData, &params);
-    if (NULL == fEntry.texture()) {
-        fEntry = fDesc.fContext->createAndLockTexture(&params, texDesc, cacheData, NULL, 0);
+    fTexture = fDesc.fContext->findAndLockTexture(texDesc, cacheData, &params);
+    if (NULL == fTexture) {
+        fTexture = fDesc.fContext->createAndLockTexture(&params, texDesc, cacheData, NULL, 0);
         // This is a new texture, so all of our cache info is now invalid
         this->initLRU();
         fKeyTable.rewind();
     }
-    GrAssert(NULL != fEntry.texture());
+    GrAssert(NULL != fTexture);
 }
 
 void GrTextureStripAtlas::unlockTexture() {
-    GrAssert(NULL != fEntry.texture() && 0 == fLockedRows);
-    fDesc.fContext->unlockTexture(fEntry);
-    fEntry.reset();
+    GrAssert(NULL != fTexture && 0 == fLockedRows);
+    fDesc.fContext->unlockTexture(fTexture);
+    fTexture = NULL;
 }
 
 void GrTextureStripAtlas::initLRU() {
@@ -311,9 +312,9 @@
     // If we have locked rows, we should have a locked texture, otherwise
     // it should be unlocked
     if (fLockedRows == 0) {
-        GrAssert(NULL == fEntry.texture());
+        GrAssert(NULL == fTexture);
     } else {
-        GrAssert(NULL != fEntry.texture());
+        GrAssert(NULL != fTexture);
     }
 }
 #endif
diff --git a/src/gpu/effects/GrTextureStripAtlas.h b/src/gpu/effects/GrTextureStripAtlas.h
index 22e2e47..c763599 100644
--- a/src/gpu/effects/GrTextureStripAtlas.h
+++ b/src/gpu/effects/GrTextureStripAtlas.h
@@ -69,7 +69,7 @@
     GrScalar getVerticalScaleFactor() const { return SkIntToScalar(fDesc.fRowHeight) / fDesc.fHeight; }
 
     GrContext* getContext() const { return fDesc.fContext; }
-    GrTexture* getTexture() const { return fEntry.texture(); }
+    GrTexture* getTexture() const { return fTexture; }
 
 private:
 
@@ -141,7 +141,7 @@
 
     const Desc fDesc;
     const uint16_t fNumRows;
-    GrContext::TextureCacheEntry fEntry;
+    GrTexture* fTexture;
 
     // Array of AtlasRows which store the state of all our rows. Stored in a contiguous array, in
     // order that they appear in our texture, this means we can subtract this pointer from a row 
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index c13bade..8089d10 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1143,7 +1143,7 @@
                                                  int width, int height) {
 
     // All internally created RTs are also textures. We don't create
-    // SBs for a client's standalone RT (that is RT that isnt also a texture).
+    // SBs for a client's standalone RT (that is a RT that isn't also a texture).
     GrAssert(rt->asTexture());
     GrAssert(width >= rt->width());
     GrAssert(height >= rt->height());