Make all GrContext members that return a texture also ref the texture for the caller.
Review URL: https://codereview.appspot.com/7198049

git-svn-id: http://skia.googlecode.com/svn/trunk@7362 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index c62e088..5568938 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -118,7 +118,8 @@
     // Textures
 
     /**
-     * Create a new entry, based on the specified key and texture and return it.
+     * Creates a new entry, based on the specified key and texture and returns it. The caller owns a
+     * ref on the returned texture which must be balanced by a call to unref.
      *
      * @param params    The texture params used to draw a texture may help determine
      *                  the cache entry used. (e.g. different versions may exist
@@ -136,8 +137,8 @@
                              void* srcData, size_t rowBytes);
 
     /**
-     *  Search for an entry based on key and dimensions. If found,
-     *  return it. The return value will be NULL if not found.
+     * Search for an entry based on key and dimensions. If found, ref it and return it. The return
+     * value will be NULL if not found. The caller must balance with a call to unref.
      *
      *  @param desc     Description of the texture properties.
      *  @param cacheID Cache-specific properties (e.g., texture gen ID)
@@ -146,9 +147,9 @@
      *                  for different wrap modes on GPUs with limited NPOT
      *                  texture support). NULL implies clamp wrap modes.
      */
-    GrTexture* findTexture(const GrTextureDesc& desc,
-                           const GrCacheID& cacheID,
-                           const GrTextureParams* params);
+    GrTexture* findAndRefTexture(const GrTextureDesc& desc,
+                                 const GrCacheID& cacheID,
+                                 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
@@ -182,7 +183,8 @@
      * Returns a texture matching the desc. It's contents are unknown. Subsequent
      * requests with the same descriptor are not guaranteed to return the same
      * texture. The same texture is guaranteed not be returned again until it is
-     * unlocked. Call must be balanced with an unlockTexture() call.
+     * unlocked. Call must be balanced with an unlockTexture() call. The caller
+     * owns a ref on the returned texture and must balance with a call to unref.
      *
      * Textures created by createAndLockTexture() hide the complications of
      * tiling non-power-of-two textures on APIs that don't support this (e.g.
@@ -190,11 +192,11 @@
      * such an API will create gaps in the tiling pattern. This includes clamp
      * mode. (This may be addressed in a future update.)
      */
-    GrTexture* lockScratchTexture(const GrTextureDesc&, ScratchTexMatch match);
+    GrTexture* lockAndRefScratchTexture(const GrTextureDesc&, ScratchTexMatch match);
 
     /**
      *  When done with an entry, call unlockScratchTexture(entry) on it, which returns
-     *  it to the cache, where it may be purged.
+     *  it to the cache, where it may be purged. This does not unref the texture.
      */
     void unlockScratchTexture(GrTexture* texture);
 
@@ -946,6 +948,7 @@
     void reset() {
         if (NULL != fContext && NULL != fTexture) {
             fContext->unlockScratchTexture(fTexture);
+            fTexture->unref();
             fTexture = NULL;
         }
     }
@@ -956,23 +959,26 @@
      * "locked" in the texture cache until it is freed and recycled in
      * GrTexture::internal_dispose. In reality, the texture has been removed
      * from the cache (because this is in AutoScratchTexture) and by not
-     * calling unlockTexture we simply don't re-add it. It will be reattached
-     * in GrTexture::internal_dispose.
+     * calling unlockScratchTexture we simply don't re-add it. It will be
+     * reattached in GrTexture::internal_dispose.
      *
      * Note that the caller is assumed to accept and manage the ref to the
      * returned texture.
      */
     GrTexture* detach() {
-        GrTexture* temp = fTexture;
-
-        // Conceptually the texture's cache entry loses its ref to the
-        // texture while the caller of this method gets a ref.
-        GrAssert(NULL != temp->getCacheEntry());
-
+        GrTexture* texture = fTexture;
         fTexture = NULL;
 
-        temp->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
-        return temp;
+        // This GrAutoScratchTexture has a ref from lockAndRefScratchTexture, which we give up now.
+        // The cache also has a ref which we are lending to the caller of detach(). When the caller
+        // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is
+        // set and re-ref the texture, thereby restoring the cache's ref.
+        GrAssert(texture->getRefCnt() > 1);
+        texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
+        texture->unref();
+        GrAssert(NULL != texture->getCacheEntry());
+
+        return texture;
     }
 
     GrTexture* set(GrContext* context,
@@ -982,7 +988,7 @@
 
         fContext = context;
         if (NULL != fContext) {
-            fTexture = fContext->lockScratchTexture(desc, match);
+            fTexture = fContext->lockAndRefScratchTexture(desc, match);
             if (NULL == fTexture) {
                 fContext = NULL;
             }
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index e7c2964..cf37f47 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -77,9 +77,9 @@
 
 bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
 
-GrTexture* GrLockCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
+GrTexture* GrLockAndRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
 
-void GrUnlockCachedBitmapTexture(GrTexture*);
+void GrUnlockAndUnrefCachedBitmapTexture(GrTexture*);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Classes
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index d91b978..96cfea6 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -353,7 +353,7 @@
 
     // Must set wrap and filter on the sampler before requesting a texture.
     GrTextureParams params(tm, paint.isFilterBitmap());
-    GrTexture* texture = GrLockCachedBitmapTexture(context, fRawBitmap, &params);
+    GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, &params);
 
     if (NULL == texture) {
         SkDebugf("Couldn't convert bitmap to texture.\n");
@@ -361,7 +361,7 @@
     }
 
     GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
-    GrUnlockCachedBitmapTexture(texture);
+    GrUnlockAndUnrefCachedBitmapTexture(texture);
     return effect;
 }
 #endif
diff --git a/src/effects/SkBlendImageFilter.cpp b/src/effects/SkBlendImageFilter.cpp
index bf1dbe4..846a1e9 100644
--- a/src/effects/SkBlendImageFilter.cpp
+++ b/src/effects/SkBlendImageFilter.cpp
@@ -191,9 +191,9 @@
             if (result.getTexture()) {
                 resultTex = (GrTexture*) result.getTexture();
             } else {
-                resultTex = GrLockCachedBitmapTexture(src->getContext(), result, NULL);
-                SkSafeRef(resultTex);
-                GrUnlockCachedBitmapTexture(resultTex);
+                resultTex = GrLockAndRefCachedBitmapTexture(src->getContext(), result, NULL);
+                SkSafeRef(resultTex); // for the caller
+                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
                 return resultTex;
             }
         } else {
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 527cc9e..0fef7c6 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -295,9 +295,9 @@
             if (result.getTexture()) {
                 resultTex = (GrTexture*) result.getTexture();
             } else {
-                resultTex = GrLockCachedBitmapTexture(src->getContext(), result, NULL);
-                SkSafeRef(resultTex);
-                GrUnlockCachedBitmapTexture(resultTex);
+                resultTex = GrLockAndRefCachedBitmapTexture(src->getContext(), result, NULL);
+                SkSafeRef(resultTex); // for the caller
+                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
                 return resultTex;
             }
         } else {
diff --git a/src/effects/SkSingleInputImageFilter.cpp b/src/effects/SkSingleInputImageFilter.cpp
index 08d039c..d9ec0ee 100644
--- a/src/effects/SkSingleInputImageFilter.cpp
+++ b/src/effects/SkSingleInputImageFilter.cpp
@@ -57,9 +57,9 @@
             if (result.getTexture()) {
                 resultTex = (GrTexture*) result.getTexture();
             } else {
-                resultTex = GrLockCachedBitmapTexture(src->getContext(), result, NULL);
-                SkSafeRef(resultTex);
-                GrUnlockCachedBitmapTexture(resultTex);
+                resultTex = GrLockAndRefCachedBitmapTexture(src->getContext(), result, NULL);
+                SkSafeRef(resultTex); // for the caller
+                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
                 return resultTex;
             }
         } else {
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index b703f99..5c00794 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -381,13 +381,13 @@
     SkBitmap bitmap;
     this->asComponentTable(&bitmap);
     // passing NULL because this effect does no tiling or filtering.
-    GrTexture* texture = GrLockCachedBitmapTexture(context, bitmap, NULL);
+    GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, bitmap, NULL);
     GrEffectRef* effect = ColorTableEffect::Create(texture, fFlags);
 
     // Unlock immediately, this is not great, but we don't have a way of
     // knowing when else to unlock it currently. TODO: Remove this when
     // unref becomes the unlock replacement for all types of textures.
-    GrUnlockCachedBitmapTexture(texture);
+    GrUnlockAndUnrefCachedBitmapTexture(texture);
     return effect;
 }
 
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index cdbfd7c..81a6659 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -811,14 +811,14 @@
                   fAtlas->getVerticalScaleFactor();
         fTextureAccess.reset(fAtlas->getTexture(), params);
     } else {
-        GrTexture* texture = GrLockCachedBitmapTexture(ctx, bitmap, &params);
+        GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &params);
         fTextureAccess.reset(texture, params);
         fYCoord = SK_ScalarHalf;
 
         // 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(texture);
+        GrUnlockAndUnrefCachedBitmapTexture(texture);
     }
     this->addTextureAccess(&fTextureAccess);
 }
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
index 491f6cf..48a4f39 100644
--- a/src/gpu/GrAtlas.cpp
+++ b/src/gpu/GrAtlas.cpp
@@ -177,6 +177,7 @@
     GrAssert(0 == kA8_GrMaskFormat);
     GrAssert(1 == kA565_GrMaskFormat);
     if (NULL == fTexture[format]) {
+        // TODO: Update this to use the cache rather than directly creating a texture.
         GrTextureDesc desc;
         desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
         desc.fWidth = GR_ATLAS_TEXTURE_WIDTH;
@@ -203,5 +204,3 @@
     GrAssert(fPlotMgr->isBusy(x, y));
     fPlotMgr->freePlot(x, y);
 }
-
-
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index be057fc..4bd4893 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -212,11 +212,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-GrTexture* GrContext::findTexture(const GrTextureDesc& desc,
-                                  const GrCacheID& cacheID,
-                                  const GrTextureParams* params) {
+GrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
+                                        const GrCacheID& cacheID,
+                                        const GrTextureParams* params) {
     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
     GrResource* resource = fTextureCache->find(resourceKey);
+    SkSafeRef(resource);
     return static_cast<GrTexture*>(resource);
 }
 
@@ -279,17 +280,15 @@
                                            void* srcData,
                                            size_t rowBytes,
                                            bool needsFiltering) {
-    GrTexture* clampedTexture = this->findTexture(desc, cacheID, NULL);
+    SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
     if (NULL == clampedTexture) {
-        clampedTexture = this->createTexture(NULL, desc, cacheID, srcData, rowBytes);
+        clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
 
         if (NULL == clampedTexture) {
             return NULL;
         }
     }
 
-    clampedTexture->ref();
-
     GrTextureDesc rtDesc = desc;
     rtDesc.fFlags =  rtDesc.fFlags |
                      kRenderTarget_GrTextureFlagBit |
@@ -310,19 +309,14 @@
         GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
         drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
 
-        static const GrVertexLayout layout =
-                            GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+        static const GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
         GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
 
         if (arg.succeeded()) {
             GrPoint* verts = (GrPoint*) arg.vertices();
-            verts[0].setIRectFan(0, 0,
-                                    texture->width(),
-                                    texture->height(),
-                                    2*sizeof(GrPoint));
-            verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
-            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType,
-                                    0, 4);
+            verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
+            verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
+            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
         }
         texture->releaseRenderTarget();
     } else {
@@ -346,16 +340,14 @@
         GrAssert(NULL != texture);
     }
 
-    clampedTexture->unref();
     return texture;
 }
 
-GrTexture* GrContext::createTexture(
-        const GrTextureParams* params,
-        const GrTextureDesc& desc,
-        const GrCacheID& cacheID,
-        void* srcData,
-        size_t rowBytes) {
+GrTexture* GrContext::createTexture(const GrTextureParams* params,
+                                    const GrTextureDesc& desc,
+                                    const GrCacheID& cacheID,
+                                    void* srcData,
+                                    size_t rowBytes) {
     SK_TRACE_EVENT0("GrContext::createTexture");
 
 #if GR_DUMP_TEXTURE_UPLOAD
@@ -364,13 +356,13 @@
 
     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
 
-    SkAutoTUnref<GrTexture> texture;
+    GrTexture* texture;
     if (GrTexture::NeedsResizing(resourceKey)) {
-        texture.reset(this->createResizedTexture(desc, cacheID,
-                                                 srcData, rowBytes,
-                                                 GrTexture::NeedsFiltering(resourceKey)));
+        texture = this->createResizedTexture(desc, cacheID,
+                                             srcData, rowBytes,
+                                             GrTexture::NeedsFiltering(resourceKey));
     } else {
-        texture.reset(fGpu->createTexture(desc, srcData, rowBytes));
+        texture= fGpu->createTexture(desc, srcData, rowBytes);
     }
 
     if (NULL != texture) {
@@ -380,7 +372,7 @@
     return texture;
 }
 
-GrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
+GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
     GrTextureDesc desc = inDesc;
 
     GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
@@ -403,11 +395,16 @@
         GrResourceKey key = GrTexture::ComputeScratchKey(desc);
         // Ensure we have exclusive access to the texture so future 'find' calls don't return it
         resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
-        // if we miss, relax the fit of the flags...
-        // then try doubling width... then height.
-        if (NULL != resource || kExact_ScratchTexMatch == match) {
+        if (NULL != resource) {
+            resource->ref();
             break;
         }
+        if (kExact_ScratchTexMatch == match) {
+            break;
+        }
+        // We had a cache miss and we are in approx mode, relax the fit of the flags... then try
+        // doubling width... then the height.
+
         // We no longer try to reuse textures that were previously used as render targets in
         // situations where no RT is needed; doing otherwise can confuse the video driver and
         // cause significant performance problems in some cases.
@@ -432,7 +429,7 @@
         desc.fFlags = inDesc.fFlags;
         desc.fWidth = origWidth;
         desc.fHeight = origHeight;
-        SkAutoTUnref<GrTexture> texture(fGpu->createTexture(desc, NULL, 0));
+        GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
         if (NULL != texture) {
             GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
             // Make the resource exclusive so future 'find' calls don't return it
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 7ceefe8..827fc52 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -96,7 +96,7 @@
 
     ~SkAutoCachedTexture() {
         if (NULL != fTexture) {
-            GrUnlockCachedBitmapTexture(fTexture);
+            GrUnlockAndUnrefCachedBitmapTexture(fTexture);
         }
     }
 
@@ -104,14 +104,14 @@
                    const SkBitmap& bitmap,
                    const GrTextureParams* params) {
         if (NULL != fTexture) {
-            GrUnlockCachedBitmapTexture(fTexture);
+            GrUnlockAndUnrefCachedBitmapTexture(fTexture);
             fTexture = NULL;
         }
         fDevice = device;
         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);
+            fTexture = GrLockAndRefCachedBitmapTexture(device->context(), bitmap, params);
             result = fTexture;
         }
         return result;
@@ -1801,8 +1801,7 @@
     desc.fHeight = height;
     desc.fSampleCnt = fRenderTarget->numSamples();
 
-    GrTexture* texture;
-    SkAutoTUnref<GrTexture> tunref;
+    SkAutoTUnref<GrTexture> texture;
     // Skia's convention is to only clear a device if it is non-opaque.
     bool needClear = !isOpaque;
 
@@ -1812,18 +1811,14 @@
     const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == usage) ?
                                                 GrContext::kApprox_ScratchTexMatch :
                                                 GrContext::kExact_ScratchTexMatch;
-    texture = fContext->lockScratchTexture(desc, match);
+    texture.reset(fContext->lockAndRefScratchTexture(desc, match));
 #else
-    tunref.reset(fContext->createUncachedTexture(desc, NULL, 0));
-    texture = tunref.get();
+    texture.reset(fContext->createUncachedTexture(desc, NULL, 0));
 #endif
-    if (texture) {
-        return SkNEW_ARGS(SkGpuDevice,(fContext,
-                                       texture,
-                                       needClear));
+    if (NULL != texture.get()) {
+        return SkNEW_ARGS(SkGpuDevice,(fContext, texture, needClear));
     } else {
-        GrPrintf("---- failed to create compatible device texture [%d %d]\n",
-                    width, height);
+        GrPrintf("---- failed to create compatible device texture [%d %d]\n", width, height);
         return NULL;
     }
 }
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index fac18e9..2eb3800 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -118,11 +118,9 @@
             if (cache) {
                 GrCacheID cacheID;
                 generate_bitmap_cache_id(origBitmap, &cacheID);
-                return ctx->createTexture(params, desc, cacheID,
-                                          storage.get(),
-                                          bitmap->width());
+                return ctx->createTexture(params, desc, cacheID, storage.get(), bitmap->width());
             } else {
-                GrTexture* result = ctx->lockScratchTexture(desc,
+                GrTexture* result = ctx->lockAndRefScratchTexture(desc,
                                                             GrContext::kExact_ScratchTexMatch);
                 result->writePixels(0, 0, bitmap->width(),
                                     bitmap->height(), desc.fConfig,
@@ -141,16 +139,14 @@
         // This texture is likely to be used again so leave it in the cache
         GrCacheID cacheID;
         generate_bitmap_cache_id(origBitmap, &cacheID);
-        return ctx->createTexture(params, desc, cacheID,
-                                  bitmap->getPixels(),
-                                  bitmap->rowBytes());
+        return ctx->createTexture(params, desc, cacheID, bitmap->getPixels(), bitmap->rowBytes());
     } else {
         // This texture is unlikely to be used again (in its present form) so
         // just use a scratch texture. This will remove the texture from the
         // 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.
-        GrTexture* result = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
+        GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
         result->writePixels(0, 0,
                             bitmap->width(), bitmap->height(),
                             desc.fConfig,
@@ -171,9 +167,9 @@
     return ctx->isTextureInCache(desc, cacheID, params);
 }
 
-GrTexture* GrLockCachedBitmapTexture(GrContext* ctx,
-                                     const SkBitmap& bitmap,
-                                     const GrTextureParams* params) {
+GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx,
+                                           const SkBitmap& bitmap,
+                                           const GrTextureParams* params) {
     GrTexture* result = NULL;
 
     bool cache = !bitmap.isVolatile();
@@ -187,7 +183,7 @@
         GrTextureDesc desc;
         generate_bitmap_texture_desc(bitmap, &desc);
 
-        result = ctx->findTexture(desc, cacheID, params);
+        result = ctx->findAndRefTexture(desc, cacheID, params);
     }
     if (NULL == result) {
         result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
@@ -199,10 +195,11 @@
     return result;
 }
 
-void GrUnlockCachedBitmapTexture(GrTexture* texture) {
+void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
     GrAssert(NULL != texture->getContext());
 
     texture->getContext()->unlockScratchTexture(texture);
+    texture->unref();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -224,4 +221,3 @@
             return kUnknown_GrPixelConfig;
     }
 }
-
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index bd256c5..9081fb6 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -202,7 +202,7 @@
     memset(key.fData32 + 1, 0, sizeof(key) - sizeof(uint32_t));
     GrCacheID cacheID(gTextureStripAtlasDomain, key);
 
-    fTexture = fDesc.fContext->findTexture(texDesc, cacheID, &params);
+    fTexture = fDesc.fContext->findAndRefTexture(texDesc, cacheID, &params);
     if (NULL == fTexture) {
         fTexture = fDesc.fContext->createTexture(&params, texDesc, cacheID, NULL, 0);
         // This is a new texture, so all of our cache info is now invalid
@@ -210,7 +210,6 @@
         fKeyTable.rewind();
     }
     GrAssert(NULL != fTexture);
-    fTexture->ref();
 }
 
 void GrTextureStripAtlas::unlockTexture() {
@@ -345,4 +344,3 @@
     }
 }
 #endif
-
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index 1aeebb8..c80ba63 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -155,14 +155,14 @@
 
     // check that the set took
     check_state(reporter, cache, clip1, texture1, bound1);
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
 
     // push the state
     cache.push();
 
     // verify that the pushed state is initially empty
     check_state(reporter, cache, emptyClip, NULL, emptyBound);
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
 
     // modify the new state
     GrIRect bound2;
@@ -180,8 +180,8 @@
 
     // check that the changes took
     check_state(reporter, cache, clip2, texture2, bound2);
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
-    REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture2->getRefCnt());
 
     // check to make sure canReuse works
     REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
@@ -192,16 +192,16 @@
 
     // verify that the old state is restored
     check_state(reporter, cache, clip1, texture1, bound1);
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
-    REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture2->getRefCnt());
 
     // manually clear the state
     cache.reset();
 
     // verify it is now empty
     check_state(reporter, cache, emptyClip, NULL, emptyBound);
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
-    REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture2->getRefCnt());
 
     // pop again - so there is no state
     cache.pop();
@@ -211,8 +211,8 @@
     // only do in release since it generates asserts in debug
     check_state(reporter, cache, emptyClip, NULL, emptyBound);
 #endif
-    REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
-    REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
+    REPORTER_ASSERT(reporter, texture1->getRefCnt());
+    REPORTER_ASSERT(reporter, texture2->getRefCnt());
 }
 
 ////////////////////////////////////////////////////////////////////////////////