This replaces the texture creation/caching functions on GrContext with a GrTextureProvider interface. The goal is to pass this narrowly focused object in places that currently take a GrContext but don't need and shouldn't use its other methods. It also has an extended private interface for interacting with non-texture resource types.

Review URL: https://codereview.chromium.org/1107973004
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
index 88dbce9..dff2944 100644
--- a/gm/texdata.cpp
+++ b/gm/texdata.cpp
@@ -84,7 +84,8 @@
                 desc.fConfig    = kSkia8888_GrPixelConfig;
                 desc.fWidth     = 2 * S;
                 desc.fHeight    = 2 * S;
-                GrTexture* texture = ctx->createTexture(desc, false, gTextureData.get(), 0);
+                GrTexture* texture = ctx->textureProvider()->createTexture(
+                    desc, false, gTextureData.get(), 0);
 
                 if (!texture) {
                     return;
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 5b7513c..4d2549e 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -33,6 +33,7 @@
       '<(skia_include_path)/gpu/GrSurface.h',
       '<(skia_include_path)/gpu/GrShaderVar.h',
       '<(skia_include_path)/gpu/GrTexture.h',
+      '<(skia_include_path)/gpu/GrTextureProvider.h',
       '<(skia_include_path)/gpu/GrTextureAccess.h',
       '<(skia_include_path)/gpu/GrTestUtils.h',
       '<(skia_include_path)/gpu/GrTypes.h',
@@ -197,6 +198,7 @@
       '<(skia_src_path)/gpu/GrTextContext.cpp',
       '<(skia_src_path)/gpu/GrTextContext.h',
       '<(skia_src_path)/gpu/GrTexture.cpp',
+      '<(skia_src_path)/gpu/GrTextureProvider.cpp',
       '<(skia_src_path)/gpu/GrTexturePriv.h',
       '<(skia_src_path)/gpu/GrTextureAccess.cpp',
       '<(skia_src_path)/gpu/GrTRecorder.h',
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 250fe45..dc824d5 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -13,7 +13,7 @@
 #include "GrPaint.h"
 #include "GrPathRendererChain.h"
 #include "GrRenderTarget.h"
-#include "GrTexture.h"
+#include "GrTextureProvider.h"
 #include "SkMatrix.h"
 #include "SkPathEffect.h"
 #include "SkTypes.h"
@@ -33,6 +33,7 @@
 class GrPipelineBuilder;
 class GrResourceEntry;
 class GrResourceCache;
+class GrResourceProvider;
 class GrTestTarget;
 class GrTextBlobCache;
 class GrTextContext;
@@ -111,7 +112,6 @@
      * GrGpuResources it created is to destroy them.
      */
     void abandonContext();
-    void contextDestroyed() { this->abandonContext(); }  //  legacy alias
 
     ///////////////////////////////////////////////////////////////////////////
     // Resource Cache
@@ -147,6 +147,9 @@
      */
     void setResourceCacheLimits(int maxResources, size_t maxResourceBytes);
 
+    GrTextureProvider* textureProvider() { return fTextureProvider; }
+    const GrTextureProvider* textureProvider() const { return fTextureProvider; }
+
     /**
      * Frees GPU created by the context. Can be called to reduce GPU memory
      * pressure.
@@ -154,121 +157,14 @@
     void freeGpuResources();
 
     /**
-     * This method should be called whenever a GrResource is unreffed or
-     * switched from exclusive to non-exclusive. This
-     * gives the resource cache a chance to discard unneeded resources.
-     * Note: this entry point will be removed once totally ref-driven
-     * cache maintenance is implemented.
-     */
-    void purgeCache();
-
-    /**
      * Purge all the unlocked resources from the cache.
      * This entry point is mainly meant for timing texture uploads
      * and is not defined in normal builds of Skia.
      */
     void purgeAllUnlockedResources();
 
-    /**
-     * Sets a unique key on the resource. Upon key collision this resource takes the place of the
-     * previous resource that had the key.
-     */
-    void addResourceToCache(const GrUniqueKey&, GrGpuResource*);
-
-    /**
-     * Finds a resource in the cache, based on the specified key. This is intended for use in
-     * conjunction with addResourceToCache(). The return value will be NULL if not found. The
-     * caller must balance with a call to unref().
-     */
-    GrGpuResource* findAndRefCachedResource(const GrUniqueKey&);
-
-    /** Helper for casting resource to a texture. Caller must be sure that the resource cached
-        with the key is either NULL or a texture and not another resource type. */
-    GrTexture* findAndRefCachedTexture(const GrUniqueKey& key) {
-        GrGpuResource* resource = this->findAndRefCachedResource(key);
-        if (resource) {
-            GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
-            SkASSERT(texture);
-            return texture;
-        }
-        return NULL;
-    }
-
-    /**
-     * Determines whether a resource is in the cache. If the resource is found it
-     * will not be locked or returned. This call does not affect the priority of
-     * the resource for deletion.
-     */
-    bool isResourceInCache(const GrUniqueKey& key) const;
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Textures
-
-    /**
-     * Creates a new texture in the resource cache and returns it. The caller owns a
-     * ref on the returned texture which must be balanced by a call to unref.
-     *
-     * @param desc      Description of the texture properties.
-     * @param budgeted  Does the texture count against the resource cache budget?
-     * @param srcData   Pointer to the pixel values (optional).
-     * @param rowBytes  The number of bytes between rows of the texture. Zero
-     *                  implies tightly packed rows. For compressed pixel configs, this
-     *                  field is ignored.
-     */
-    GrTexture* createTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData,
-                             size_t rowBytes);
-
-    GrTexture* createTexture(const GrSurfaceDesc& desc, bool budgeted) {
-        return this->createTexture(desc, budgeted, NULL, 0);
-    }
-
-    /**
-     * DEPRECATED: use createTexture().
-     */
-    GrTexture* createUncachedTexture(const GrSurfaceDesc& desc, void* srcData, size_t rowBytes) {
-        return this->createTexture(desc, false, srcData, rowBytes);
-    }
-
-    /**
-     * Enum that determines how closely a returned scratch texture must match
-     * a provided GrSurfaceDesc. TODO: Remove this. createTexture() should be used
-     * for exact match and refScratchTexture() should be replaced with createApproxTexture().
-     */
-    enum ScratchTexMatch {
-        /**
-         * Finds a texture that exactly matches the descriptor.
-         */
-        kExact_ScratchTexMatch,
-        /**
-         * Finds a texture that approximately matches the descriptor. Will be
-         * at least as large in width and height as desc specifies. If desc
-         * specifies that texture is a render target then result will be a
-         * render target. If desc specifies a render target and doesn't set the
-         * no stencil flag then result will have a stencil. Format and aa level
-         * will always match.
-         */
-        kApprox_ScratchTexMatch
-    };
-
-    /**
-     * Returns a texture matching the desc. It's contents are unknown. The caller
-     * owns a ref on the returned texture and must balance with a call to unref.
-     * It is guaranteed that the same texture will not be returned in subsequent
-     * calls until all refs to the texture are dropped.
-     *
-     * Textures created by createTexture() hide the complications of
-     * tiling non-power-of-two textures on APIs that don't support this (e.g.
-     * unextended GLES2). NPOT scratch textures are not tilable on such APIs.
-     *
-     * internalFlag is a temporary workaround until changes in the internal
-     * architecture are complete. Use the default value.
-     *
-     * TODO: Once internal flag can be removed, this should be replaced with
-     * createApproxTexture() and exact textures should be created with
-     * createTexture().
-     */
-    GrTexture* refScratchTexture(const GrSurfaceDesc&, ScratchTexMatch match,
-                                 bool internalFlag = false);
+    //////////////////////////////////////////////////////////////////////////
+    /// Texture and Render Target Queries
 
     /**
      * Can the provided configuration act as a texture?
@@ -325,33 +221,6 @@
     int getRecommendedSampleCount(GrPixelConfig config, SkScalar dpi) const;
 
     ///////////////////////////////////////////////////////////////////////////
-    // Backend Surfaces
-
-    /**
-     * Wraps an existing texture with a GrTexture object.
-     *
-     * OpenGL: if the object is a texture Gr may change its GL texture params
-     *         when it is drawn.
-     *
-     * @param  desc     description of the object to create.
-     *
-     * @return GrTexture object or NULL on failure.
-     */
-    GrTexture* wrapBackendTexture(const GrBackendTextureDesc& desc);
-
-    /**
-     * Wraps an existing render target with a GrRenderTarget object. It is
-     * similar to wrapBackendTexture but can be used to draw into surfaces
-     * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
-     * the client will resolve to a texture).
-     *
-     * @param  desc     description of the object to create.
-     *
-     * @return GrTexture object or NULL on failure.
-     */
-     GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc);
-
-    ///////////////////////////////////////////////////////////////////////////
     // Draws
 
     /**
@@ -646,6 +515,23 @@
     void discardRenderTarget(GrRenderTarget*);
 
     ///////////////////////////////////////////////////////////////////////////
+    // Legacy functions, to be removed once Chromium stops using them.
+
+    enum ScratchTexMatch {
+        kExact_ScratchTexMatch = GrTextureProvider::kExact_ScratchTexMatch,
+        kApprox_ScratchTexMatch = GrTextureProvider::kApprox_ScratchTexMatch
+    };
+
+    GrTexture* refScratchTexture(const GrSurfaceDesc& desc, ScratchTexMatch match) {
+        return this->textureProvider()->refScratchTexture(
+            desc, (GrTextureProvider::ScratchTexMatch) match);
+    }
+
+    GrTexture* wrapBackendTexture(const GrBackendTextureDesc& desc) {
+        return this->textureProvider()->wrapBackendTexture(desc);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
     // Functions intended for internal use only.
     GrGpu* getGpu() { return fGpu; }
     const GrGpu* getGpu() const { return fGpu; }
@@ -655,6 +541,8 @@
     GrDrawTarget* getTextTarget();
     const GrIndexBuffer* getQuadIndexBuffer() const;
     GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; }
+    GrResourceProvider* resourceProvider() { return fResourceProvider; }
+    const GrResourceProvider* resourceProvider() const { return fResourceProvider; }
     GrResourceCache* getResourceCache() { return fResourceCache; }
 
     // Called by tests that draw directly to the context via GrDrawTarget
@@ -689,8 +577,14 @@
 
 private:
     GrGpu*                          fGpu;
-
     GrResourceCache*                fResourceCache;
+    // this union exists because the inheritance of GrTextureProvider->GrResourceProvider
+    // is in a private header.
+    union { 
+        GrResourceProvider*         fResourceProvider;
+        GrTextureProvider*          fTextureProvider;
+    };
+
     GrBatchFontCache*               fBatchFontCache;
     SkAutoTDelete<GrLayerCache>     fLayerCache;
     SkAutoTDelete<GrTextBlobCache>  fTextBlobCache;
@@ -748,8 +642,6 @@
                           const SkPath&,
                           const GrStrokeInfo&);
 
-    GrTexture* internalRefScratchTexture(const GrSurfaceDesc&, uint32_t flags);
-
     /**
      * Creates a new text rendering context that is optimal for the
      * render target and the context. Caller assumes the ownership
diff --git a/include/gpu/GrTextureProvider.h b/include/gpu/GrTextureProvider.h
new file mode 100644
index 0000000..3e29dab
--- /dev/null
+++ b/include/gpu/GrTextureProvider.h
@@ -0,0 +1,167 @@
+/*
+ * 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 GrTextureProvider_DEFINED
+#define GrTextureProvider_DEFINED
+
+#include "GrTexture.h"
+
+class SK_API GrTextureProvider {
+public:
+    ///////////////////////////////////////////////////////////////////////////
+    // Textures
+
+    /**
+     * Creates a new texture in the resource cache and returns it. The caller owns a
+     * ref on the returned texture which must be balanced by a call to unref.
+     *
+     * @param desc      Description of the texture properties.
+     * @param budgeted  Does the texture count against the resource cache budget?
+     * @param srcData   Pointer to the pixel values (optional).
+     * @param rowBytes  The number of bytes between rows of the texture. Zero
+     *                  implies tightly packed rows. For compressed pixel configs, this
+     *                  field is ignored.
+     */
+    GrTexture* createTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData,
+                             size_t rowBytes);
+
+    /** Shortcut for creating a texture with no initial data to upload. */
+    GrTexture* createTexture(const GrSurfaceDesc& desc, bool budgeted) {
+        return this->createTexture(desc, budgeted, NULL, 0);
+    }
+
+    /** Assigns a unique key to the texture. The texture will be findable via this key using
+        findTextureByUniqueKey(). If an existing texture has this key, it's key will be removed. */
+    void assignUniqueKeyToTexture(const GrUniqueKey& key, GrTexture* texture) {
+        this->assignUniqueKeyToResource(key, texture);
+    }
+
+    /** Finds a texture by unique key. If the texture is found it is ref'ed and returned. */
+    GrTexture* findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
+        GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
+        if (resource) {
+            GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
+            SkASSERT(texture);
+            return texture;
+        }
+        return NULL;
+    }
+
+    /**
+     * Determines whether a texture is associated with the unique key. If the texture is found it
+     * will not be locked or returned. This call does not affect the priority of the resource for
+     * deletion.
+     */
+    bool existsTextureWithUniqueKey(const GrUniqueKey& key) const {
+        return this->existsResourceWithUniqueKey(key);
+    }
+
+    /**
+     * Enum that determines how closely a returned scratch texture must match
+     * a provided GrSurfaceDesc. TODO: Remove this. createTexture() should be used
+     * for exact match and refScratchTexture() should be replaced with createApproxTexture().
+     */
+    enum ScratchTexMatch {
+        /**
+         * Finds a texture that exactly matches the descriptor.
+         */
+        kExact_ScratchTexMatch,
+        /**
+         * Finds a texture that approximately matches the descriptor. Will be
+         * at least as large in width and height as desc specifies. If desc
+         * specifies that texture is a render target then result will be a
+         * render target. If desc specifies a render target and doesn't set the
+         * no stencil flag then result will have a stencil. Format and aa level
+         * will always match.
+         */
+        kApprox_ScratchTexMatch
+    };
+
+    /**
+     * Returns a texture matching the desc. It's contents are unknown. The caller
+     * owns a ref on the returned texture and must balance with a call to unref.
+     * It is guaranteed that the same texture will not be returned in subsequent
+     * calls until all refs to the texture are dropped.
+     *
+     * internalFlag is a temporary workaround until changes in the internal
+     * architecture are complete. Use the default value.
+     *
+     * TODO: Once internal flag can be removed, this should be replaced with
+     * createApproxTexture() and exact textures should be created with
+     * createTexture().
+     */
+    GrTexture* refScratchTexture(const GrSurfaceDesc&, ScratchTexMatch match,
+                                 bool internalFlag = false);
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Wrapped Backend Surfaces
+
+    /**
+     * Wraps an existing texture with a GrTexture object.
+     *
+     * OpenGL: if the object is a texture Gr may change its GL texture params
+     *         when it is drawn.
+     *
+     * @param  desc     description of the object to create.
+     *
+     * @return GrTexture object or NULL on failure.
+     */
+    GrTexture* wrapBackendTexture(const GrBackendTextureDesc& desc);
+
+    /**
+     * Wraps an existing render target with a GrRenderTarget object. It is
+     * similar to wrapBackendTexture but can be used to draw into surfaces
+     * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
+     * the client will resolve to a texture).
+     *
+     * @param  desc     description of the object to create.
+     *
+     * @return GrTexture object or NULL on failure.
+     */
+     GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc);
+
+protected:
+    GrTextureProvider(GrGpu* gpu, GrResourceCache* cache) : fCache(cache), fGpu(gpu) {}
+
+    /**
+     * Assigns a unique key to a resource. If the key is associated with another resource that
+     * association is removed and replaced by this resource.
+     */
+    void assignUniqueKeyToResource(const GrUniqueKey&, GrGpuResource*);
+
+    /**
+     * Finds a resource in the cache, based on the specified key. This is intended for use in
+     * conjunction with addResourceToCache(). The return value will be NULL if not found. The
+     * caller must balance with a call to unref().
+     */
+    GrGpuResource* findAndRefResourceByUniqueKey(const GrUniqueKey&);
+
+    /**
+     * Determines whether a resource is in the cache. If the resource is found it
+     * will not be locked or returned. This call does not affect the priority of
+     * the resource for deletion.
+     */
+    bool existsResourceWithUniqueKey(const GrUniqueKey& key) const;
+
+    GrTexture* internalRefScratchTexture(const GrSurfaceDesc&, uint32_t flags);
+
+    void abandon() {
+        fCache = NULL;
+        fGpu = NULL;
+    }
+
+private:
+    bool isAbandoned() const {
+        SkASSERT(SkToBool(fGpu) == SkToBool(fCache));
+        return !SkToBool(fCache);
+    }
+
+    GrResourceCache* fCache;
+    GrGpu* fGpu;
+};
+
+#endif
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index a930cfb..0a5aca8 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -257,8 +257,8 @@
     desc.fHeight = bounds.height();
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> dst(
-        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch));
     if (!dst) {
         return false;
     }
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index b699498..70d195b 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -278,8 +278,8 @@
         // the outside.
         maskDesc.fWidth = texture->width();
         maskDesc.fHeight = texture->height();
-        SkAutoTUnref<GrTexture> maskTexture(
-            context->refScratchTexture(maskDesc, GrContext::kApprox_ScratchTexMatch));
+        SkAutoTUnref<GrTexture> maskTexture(context->textureProvider()->refScratchTexture(
+            maskDesc, GrTextureProvider::kApprox_ScratchTexMatch));
         if (!maskTexture) {
             return false;
         }
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 41f0d8d..574a9af 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -617,7 +617,8 @@
     /**
      * Create a simple filter effect with custom bicubic coefficients.
      */
-    static GrFragmentProcessor* Create(GrContext *context, const SkRect& rect, float sigma) {
+    static GrFragmentProcessor* Create(GrTextureProvider *textureProvider, const SkRect& rect,
+                                       float sigma) {
         GrTexture *blurProfileTexture = NULL;
         int doubleProfileSize = SkScalarCeilToInt(12*sigma);
 
@@ -628,7 +629,8 @@
             return NULL;
         }
 
-        bool createdBlurProfileTexture = CreateBlurProfileTexture(context, sigma, &blurProfileTexture);
+        bool createdBlurProfileTexture = CreateBlurProfileTexture(
+            textureProvider, sigma, &blurProfileTexture);
         SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
         if (!createdBlurProfileTexture) {
            return NULL;
@@ -645,7 +647,7 @@
 
     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
 
-    static bool CreateBlurProfileTexture(GrContext *context, float sigma,
+    static bool CreateBlurProfileTexture(GrTextureProvider*, float sigma,
                                          GrTexture **blurProfileTexture);
 
     SkRect          fRect;
@@ -748,7 +750,7 @@
     pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
 }
 
-bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
+bool GrRectBlurEffect::CreateBlurProfileTexture(GrTextureProvider* textureProvider, float sigma,
                                                 GrTexture **blurProfileTexture) {
     GrSurfaceDesc texDesc;
 
@@ -767,19 +769,19 @@
     uint8_t *profile = NULL;
     SkAutoTDeleteArray<uint8_t> ada(NULL);
 
-    *blurProfileTexture = context->findAndRefCachedTexture(key);
+    *blurProfileTexture = textureProvider->findAndRefTextureByUniqueKey(key);
 
     if (NULL == *blurProfileTexture) {
 
         SkBlurMask::ComputeBlurProfile(sigma, &profile);
         ada.reset(profile);
 
-        *blurProfileTexture = context->createTexture(texDesc, true, profile, 0);
+        *blurProfileTexture = textureProvider->createTexture(texDesc, true, profile, 0);
 
         if (NULL == *blurProfileTexture) {
             return false;
         }
-        context->addResourceToCache(key, *blurProfileTexture);
+        textureProvider->assignUniqueKeyToTexture(key, *blurProfileTexture);
     }
 
     return true;
@@ -825,7 +827,8 @@
     float sigma = random->nextRangeF(3,8);
     float width = random->nextRangeF(200,300);
     float height = random->nextRangeF(200,300);
-    return GrRectBlurEffect::Create(context, SkRect::MakeWH(width, height), sigma);
+    return GrRectBlurEffect::Create(context->textureProvider(), SkRect::MakeWH(width, height),
+                                    sigma);
 }
 
 
@@ -855,7 +858,8 @@
     int pad=SkScalarCeilToInt(6*xformedSigma)/2;
     rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
 
-    SkAutoTUnref<GrFragmentProcessor> fp(GrRectBlurEffect::Create(context, rect, xformedSigma));
+    SkAutoTUnref<GrFragmentProcessor> fp(GrRectBlurEffect::Create(
+        context->textureProvider(), rect, xformedSigma));
     if (!fp) {
         return false;
     }
@@ -927,7 +931,8 @@
     builder[1] = cornerRadius;
     builder.finish();
 
-    SkAutoTUnref<GrTexture> blurNinePatchTexture(context->findAndRefCachedTexture(key));
+    SkAutoTUnref<GrTexture> blurNinePatchTexture(
+        context->textureProvider()->findAndRefTextureByUniqueKey(key));
 
     if (!blurNinePatchTexture) {
         SkMask mask;
@@ -964,12 +969,13 @@
         texDesc.fHeight = texSide;
         texDesc.fConfig = kAlpha_8_GrPixelConfig;
 
-        blurNinePatchTexture.reset(context->createTexture(texDesc, true, blurredMask.fImage, 0));
+        blurNinePatchTexture.reset(
+            context->textureProvider()->createTexture(texDesc, true, blurredMask.fImage, 0));
         SkMask::FreeImage(blurredMask.fImage);
         if (!blurNinePatchTexture) {
             return NULL;
         }
-        context->addResourceToCache(key, blurNinePatchTexture);
+        context->textureProvider()->assignUniqueKeyToTexture(key, blurNinePatchTexture);
     }
     return SkNEW_ARGS(GrRRectBlurEffect, (sigma, rrect, blurNinePatchTexture));
 }
diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp
index 3878e5f..253d287 100644
--- a/src/effects/SkColorCubeFilter.cpp
+++ b/src/effects/SkColorCubeFilter.cpp
@@ -351,11 +351,13 @@
     desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension();
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> textureCube(context->findAndRefCachedTexture(key));
+    SkAutoTUnref<GrTexture> textureCube(
+        context->textureProvider()->findAndRefTextureByUniqueKey(key));
     if (!textureCube) {
-        textureCube.reset(context->createTexture(desc, true, fCubeData->data(), 0));
+        textureCube.reset(context->textureProvider()->createTexture(
+            desc, true, fCubeData->data(), 0));
         if (textureCube) {
-            context->addResourceToCache(key, textureCube);
+            context->textureProvider()->assignUniqueKeyToTexture(key, textureCube);
         }
     }
 
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index a7fcbbe..6f0911c 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -429,8 +429,8 @@
     desc.fHeight = bounds.height();
     desc.fConfig = kSkia8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> dst(
-        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(desc,
+        GrTextureProvider::kApprox_ScratchTexMatch));
 
     if (!dst) {
         return false;
diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp
index 832e48a..6cb349e 100644
--- a/src/effects/SkGpuBlurUtils.cpp
+++ b/src/effects/SkGpuBlurUtils.cpp
@@ -180,12 +180,14 @@
     GrTexture* tempTexture;
     SkAutoTUnref<GrTexture> temp1, temp2;
 
-    temp1.reset(context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    temp1.reset(context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch));
     dstTexture = temp1.get();
     if (canClobberSrc) {
         tempTexture = srcTexture;
     } else {
-        temp2.reset(context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+        temp2.reset(context->textureProvider()->refScratchTexture(
+            desc, GrTextureProvider::kApprox_ScratchTexMatch));
         tempTexture = temp2.get();
     }
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index ed1e2d1..39bd6c8 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -365,8 +365,8 @@
     desc.fHeight = bounds.height();
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> dst(
-        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(desc,
+        GrTextureProvider::kApprox_ScratchTexMatch));
     if (!dst) {
         return false;
     }
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index a681c9d..9ecf0c2 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -667,7 +667,8 @@
     SkIRect srcRect = rect;
 
     if (radius.fWidth > 0) {
-        GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch);
+        GrTexture* texture = context->textureProvider()->refScratchTexture(
+            desc, GrTextureProvider::kApprox_ScratchTexMatch);
         if (NULL == texture) {
             return false;
         }
@@ -684,7 +685,8 @@
         srcRect = dstRect;
     }
     if (radius.fHeight > 0) {
-        GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch);
+        GrTexture* texture = context->textureProvider()->refScratchTexture(desc,
+            GrTextureProvider::kApprox_ScratchTexMatch);
         if (NULL == texture) {
             return false;
         }
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 6cd5437..76c4629 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -148,8 +148,8 @@
     desc.fWidth = src.width();
     desc.fHeight = src.height();
     desc.fConfig = kSkia8888_GrPixelConfig;
-    SkAutoTUnref<GrTexture> dst(
-        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch));
     if (!dst) {
         return false;
     }
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp
index ea338bb..f0b6c77 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp
@@ -590,8 +590,8 @@
 
         // We don't want to flush the context so we claim we're in the middle of flushing so as to
         // guarantee we do not recieve a texture with pending IO
-        GrTexture* texture = fContext->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch,
-                                                         true);
+        GrTexture* texture = fContext->textureProvider()->refScratchTexture(
+            desc, GrTextureProvider::kApprox_ScratchTexMatch, true);
         if (texture) {
             fAtlas = SkNEW_ARGS(GrBatchAtlas, (texture, NUM_PLOTS_X, NUM_PLOTS_Y));
         } else {
diff --git a/src/gpu/GrBatchFontCache.cpp b/src/gpu/GrBatchFontCache.cpp
index 4f27cfc..a1f87cb 100644
--- a/src/gpu/GrBatchFontCache.cpp
+++ b/src/gpu/GrBatchFontCache.cpp
@@ -27,7 +27,8 @@
 
     // We don't want to flush the context so we claim we're in the middle of flushing so as to
     // guarantee we do not recieve a texture with pending IO
-    GrTexture* texture = context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch, true);
+    GrTexture* texture = context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch, true);
     if (!texture) {
         return NULL;
     }
diff --git a/src/gpu/GrClipMaskCache.h b/src/gpu/GrClipMaskCache.h
index 0329c84..3aa80df 100644
--- a/src/gpu/GrClipMaskCache.h
+++ b/src/gpu/GrClipMaskCache.h
@@ -206,8 +206,8 @@
 
             // HACK: set the last param to true to indicate that this request is at
             // flush time and therefore we require a scratch texture with no pending IO operations.
-            fLastMask.reset(context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch,
-                                                       /*flushing=*/true));
+            fLastMask.reset(context->textureProvider()->refScratchTexture(
+                desc, GrTextureProvider::kApprox_ScratchTexMatch, /*flushing=*/true));
 
             fLastBound = bound;
         }
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 945d6be..15677fc 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -496,7 +496,8 @@
         desc.fConfig = kRGBA_8888_GrPixelConfig;
     }
 
-    return this->getContext()->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch);
+    return this->getContext()->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 11bced9..301c676 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -27,6 +27,7 @@
 #include "GrPathUtils.h"
 #include "GrRenderTargetPriv.h"
 #include "GrResourceCache.h"
+#include "GrResourceProvider.h"
 #include "GrSoftwarePathRenderer.h"
 #include "GrStencilAndCoverTextContext.h"
 #include "GrStrokeInfo.h"
@@ -92,9 +93,10 @@
 
 GrContext::GrContext(const Options& opts) : fOptions(opts) {
     fGpu = NULL;
+    fResourceCache = NULL;
+    fResourceProvider = NULL;
     fPathRendererChain = NULL;
     fSoftwarePathRenderer = NULL;
-    fResourceCache = NULL;
     fBatchFontCache = NULL;
     fDrawBuffer = NULL;
     fDrawBufferVBAllocPool = NULL;
@@ -119,6 +121,7 @@
 void GrContext::initCommon() {
     fResourceCache = SkNEW(GrResourceCache);
     fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
+    fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache));
 
     fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
 
@@ -146,6 +149,7 @@
         (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
     }
 
+    SkDELETE(fResourceProvider);
     SkDELETE(fResourceCache);
     SkDELETE(fBatchFontCache);
     SkDELETE(fDrawBuffer);
@@ -161,6 +165,7 @@
 }
 
 void GrContext::abandonContext() {
+    fResourceProvider->abandon();
     // abandon first to so destructors
     // don't try to free the resources in the API.
     fResourceCache->abandonAll();
@@ -237,11 +242,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-enum ScratchTextureFlags {
-    kExact_ScratchTextureFlag           = 0x1,
-    kNoPendingIO_ScratchTextureFlag     = 0x2,
-    kNoCreate_ScratchTextureFlag        = 0x4,
-};
 
 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
     return fGpu->caps()->isConfigTexturable(config);
@@ -251,90 +251,6 @@
     return fGpu->caps()->npotTextureTileSupport();
 }
 
-GrTexture* GrContext::createTexture(const GrSurfaceDesc& desc, bool budgeted, const void* srcData,
-                                    size_t rowBytes) {
-    RETURN_NULL_IF_ABANDONED
-    if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
-        !this->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
-        return NULL;
-    }
-    if (!GrPixelConfigIsCompressed(desc.fConfig)) {
-        static const uint32_t kFlags = kExact_ScratchTextureFlag |
-                                       kNoCreate_ScratchTextureFlag;
-        if (GrTexture* texture = this->internalRefScratchTexture(desc, kFlags)) {
-            if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
-                                                 srcData, rowBytes)) {
-                if (!budgeted) {
-                    texture->resourcePriv().makeUnbudgeted();
-                }
-                return texture;
-            }
-            texture->unref();
-        }
-    }
-    return fGpu->createTexture(desc, budgeted, srcData, rowBytes);
-}
-
-GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& desc, ScratchTexMatch match,
-                                        bool calledDuringFlush) {
-    RETURN_NULL_IF_ABANDONED
-    // Currently we don't recycle compressed textures as scratch.
-    if (GrPixelConfigIsCompressed(desc.fConfig)) {
-        return NULL;
-    } else {
-        uint32_t flags = 0;
-        if (kExact_ScratchTexMatch == match) {
-            flags |= kExact_ScratchTextureFlag;
-        }
-        if (calledDuringFlush) {
-            flags |= kNoPendingIO_ScratchTextureFlag;
-        }
-        return this->internalRefScratchTexture(desc, flags);
-    }
-}
-
-GrTexture* GrContext::internalRefScratchTexture(const GrSurfaceDesc& inDesc, uint32_t flags) {
-    SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
-
-    SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
-
-    if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
-        if (!(kExact_ScratchTextureFlag & flags)) {
-            // bin by pow2 with a reasonable min
-            static const int MIN_SIZE = 16;
-            GrSurfaceDesc* wdesc = desc.writable();
-            wdesc->fWidth  = SkTMax(MIN_SIZE, GrNextPow2(desc->fWidth));
-            wdesc->fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc->fHeight));
-        }
-
-        GrScratchKey key;
-        GrTexturePriv::ComputeScratchKey(*desc, &key);
-        uint32_t scratchFlags = 0;
-        if (kNoPendingIO_ScratchTextureFlag & flags) {
-            scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
-        } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
-            // If it is not a render target then it will most likely be populated by
-            // writePixels() which will trigger a flush if the texture has pending IO.
-            scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
-        }
-        GrGpuResource* resource = fResourceCache->findAndRefScratchResource(key, scratchFlags);
-        if (resource) {
-            GrSurface* surface = static_cast<GrSurface*>(resource);
-            GrRenderTarget* rt = surface->asRenderTarget();
-            if (rt && fGpu->caps()->discardRenderTargetSupport()) {
-                rt->discard();
-            }
-            return surface->asTexture();
-        }
-    }
-
-    if (!(kNoCreate_ScratchTextureFlag & flags)) {
-        return fGpu->createTexture(*desc, true, NULL, 0);
-    }
-
-    return NULL;
-}
-
 void GrContext::OverBudgetCB(void* data) {
     SkASSERT(data);
 
@@ -369,18 +285,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
-    RETURN_NULL_IF_ABANDONED
-    return fGpu->wrapBackendTexture(desc);
-}
-
-GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
-    RETURN_NULL_IF_ABANDONED
-    return fGpu->wrapBackendRenderTarget(desc);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 void GrContext::clear(const SkIRect* rect,
                       const GrColor color,
                       bool canIgnoreRect,
@@ -1543,7 +1447,8 @@
     desc.fWidth = width;
     desc.fHeight = height;
     desc.fConfig = writeConfig;
-    SkAutoTUnref<GrTexture> texture(this->refScratchTexture(desc, kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc,
+        GrTextureProvider::kApprox_ScratchTexMatch));
     if (!texture) {
         return false;
     }
@@ -1688,15 +1593,15 @@
         // match the passed rect. However, if we see many different size rectangles we will trash
         // our texture cache and pay the cost of creating and destroying many textures. So, we only
         // request an exact match when the caller is reading an entire RT.
-        ScratchTexMatch match = kApprox_ScratchTexMatch;
+        GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
         if (0 == left &&
             0 == top &&
             target->width() == width &&
             target->height() == height &&
             fGpu->fullReadPixelsIsFasterThanPartial()) {
-            match = kExact_ScratchTexMatch;
+            match = GrTextureProvider::kExact_ScratchTexMatch;
         }
-        tempTexture.reset(this->refScratchTexture(desc, match));
+        tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match));
         if (tempTexture) {
             // compute a matrix to perform the draw
             SkMatrix textureMatrix;
@@ -1990,22 +1895,6 @@
     fResourceCache->setLimits(maxTextures, maxTextureBytes);
 }
 
-void GrContext::addResourceToCache(const GrUniqueKey& key, GrGpuResource* resource) {
-    ASSERT_OWNED_RESOURCE(resource);
-    if (!resource) {
-        return;
-    }
-    resource->resourcePriv().setUniqueKey(key);
-}
-
-bool GrContext::isResourceInCache(const GrUniqueKey& key) const {
-    return fResourceCache->hasUniqueKey(key);
-}
-
-GrGpuResource* GrContext::findAndRefCachedResource(const GrUniqueKey& key) {
-    return fResourceCache->findAndRefUniqueResource(key);
-}
-
 //////////////////////////////////////////////////////////////////////////////
 
 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
@@ -2021,4 +1910,3 @@
         fDrawBuffer->removeGpuTraceMarker(marker);
     }
 }
-
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index d868bcb..1521a9b 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -122,8 +122,8 @@
     desc.fWidth = copyRect.width();
     desc.fHeight = copyRect.height();
 
-    SkAutoTUnref<GrTexture> copy(
-        fContext->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> copy(fContext->textureProvider()->refScratchTexture(desc,
+        GrTextureProvider::kApprox_ScratchTexMatch));
 
     if (!copy) {
         SkDebugf("Failed to create temporary copy of destination texture.\n");
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp
index 1e09d0e..aea1c9b 100644
--- a/src/gpu/GrLayerCache.cpp
+++ b/src/gpu/GrLayerCache.cpp
@@ -248,12 +248,12 @@
     }
 
     // TODO: make the test for exact match depend on the image filters themselves
-    GrContext::ScratchTexMatch usage = GrContext::kApprox_ScratchTexMatch;
+    GrTextureProvider::ScratchTexMatch usage = GrTextureProvider::kApprox_ScratchTexMatch;
     if (layer->fFilter) {
-        usage = GrContext::kExact_ScratchTexMatch;
+        usage = GrTextureProvider::kExact_ScratchTexMatch;
     }
 
-    SkAutoTUnref<GrTexture> tex(fContext->refScratchTexture(desc, usage));
+    SkAutoTUnref<GrTexture> tex(fContext->textureProvider()->refScratchTexture(desc, usage));
     if (!tex) {
         return false;
     }
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
new file mode 100644
index 0000000..f560afa
--- /dev/null
+++ b/src/gpu/GrResourceProvider.h
@@ -0,0 +1,30 @@
+/*
+ * 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 GrResourceProvider_DEFINED
+#define GrResourceProvider_DEFINED
+
+#include "GrTextureProvider.h"
+
+/**
+ * An extension of the texture provider for arbitrary resource types. This class is intended for
+ * use within the Gr code base, not by clients or extensions (e.g. third party GrProcessor
+ * derivatives).
+ */
+class GrResourceProvider : public GrTextureProvider {
+public:
+
+    GrResourceProvider(GrGpu* gpu, GrResourceCache* cache) : INHERITED(gpu, cache) {}
+
+    using GrTextureProvider::assignUniqueKeyToResource;
+    using GrTextureProvider::findAndRefResourceByUniqueKey;
+    using GrTextureProvider::abandon;
+
+    typedef GrTextureProvider INHERITED;
+};
+
+#endif
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index ff52912..510b85a 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -248,7 +248,8 @@
         SkASSERT(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig));
     }
 
-    return fContext->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch);
+    return fContext->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch);
 }
 
 void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrSurfaceDesc& desc,
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 4c9fdea..33b988e 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -14,6 +14,7 @@
 #include "GrPath.h"
 #include "GrRenderTarget.h"
 #include "GrRenderTargetPriv.h"
+#include "GrResourceProvider.h"
 #include "GrStrokeInfo.h"
 
 /*
@@ -76,10 +77,11 @@
     GrContext* ctx = gpu->getContext();
     GrUniqueKey key;
     GrPath::ComputeKey(skPath, stroke, &key);
-    SkAutoTUnref<GrPath> path(static_cast<GrPath*>(ctx->findAndRefCachedResource(key)));
+    SkAutoTUnref<GrPath> path(
+        static_cast<GrPath*>(ctx->resourceProvider()->findAndRefResourceByUniqueKey(key)));
     if (NULL == path || !path->isEqualTo(skPath, stroke)) {
         path.reset(gpu->pathRendering()->createPath(skPath, stroke));
-        ctx->addResourceToCache(key, path);
+        ctx->resourceProvider()->assignUniqueKeyToResource(key, path);
     }
     return path.detach();
 }
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 0d64915..a2abfa7 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -11,6 +11,7 @@
 #include "GrGpu.h"
 #include "GrPath.h"
 #include "GrPathRange.h"
+#include "GrResourceProvider.h"
 #include "SkAutoKern.h"
 #include "SkDraw.h"
 #include "SkDrawProcs.h"
@@ -235,10 +236,10 @@
     builder.finish();
 
     SkAutoTUnref<GrPathRange> glyphs(
-        static_cast<GrPathRange*>(ctx->findAndRefCachedResource(key)));
+        static_cast<GrPathRange*>(ctx->resourceProvider()->findAndRefResourceByUniqueKey(key)));
     if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) {
         glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc, stroke));
-        ctx->addResourceToCache(key, glyphs);
+        ctx->resourceProvider()->assignUniqueKeyToResource(key, glyphs);
     }
 
     return glyphs.detach();
diff --git a/src/gpu/GrTextureProvider.cpp b/src/gpu/GrTextureProvider.cpp
new file mode 100644
index 0000000..c195398
--- /dev/null
+++ b/src/gpu/GrTextureProvider.cpp
@@ -0,0 +1,134 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTextureProvider.h"
+#include "GrTexturePriv.h"
+#include "GrResourceCache.h"
+#include "GrGpu.h"
+
+enum ScratchTextureFlags {
+    kExact_ScratchTextureFlag           = 0x1,
+    kNoPendingIO_ScratchTextureFlag     = 0x2,
+    kNoCreate_ScratchTextureFlag        = 0x4,
+};
+
+GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, bool budgeted,
+                                            const void* srcData, size_t rowBytes) {
+    if (this->isAbandoned()) {
+        return NULL;
+    }
+    if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
+        !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
+        return NULL;
+    }
+    if (!GrPixelConfigIsCompressed(desc.fConfig)) {
+        static const uint32_t kFlags = kExact_ScratchTextureFlag |
+                                       kNoCreate_ScratchTextureFlag;
+        if (GrTexture* texture = this->internalRefScratchTexture(desc, kFlags)) {
+            if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
+                                                 srcData, rowBytes)) {
+                if (!budgeted) {
+                    texture->resourcePriv().makeUnbudgeted();
+                }
+                return texture;
+            }
+            texture->unref();
+        }
+    }
+    return fGpu->createTexture(desc, budgeted, srcData, rowBytes);
+}
+
+GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& desc, ScratchTexMatch match,
+                                                bool calledDuringFlush) {
+    if (this->isAbandoned()) {
+        return NULL;
+    }
+    // Currently we don't recycle compressed textures as scratch.
+    if (GrPixelConfigIsCompressed(desc.fConfig)) {
+        return NULL;
+    } else {
+        uint32_t flags = 0;
+        if (kExact_ScratchTexMatch == match) {
+            flags |= kExact_ScratchTextureFlag;
+        }
+        if (calledDuringFlush) {
+            flags |= kNoPendingIO_ScratchTextureFlag;
+        }
+        return this->internalRefScratchTexture(desc, flags);
+    }
+}
+
+GrTexture* GrTextureProvider::internalRefScratchTexture(const GrSurfaceDesc& inDesc,
+                                                        uint32_t flags) {
+    SkASSERT(!this->isAbandoned());
+    SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
+
+    SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
+
+    if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
+        if (!(kExact_ScratchTextureFlag & flags)) {
+            // bin by pow2 with a reasonable min
+            static const int MIN_SIZE = 16;
+            GrSurfaceDesc* wdesc = desc.writable();
+            wdesc->fWidth  = SkTMax(MIN_SIZE, GrNextPow2(desc->fWidth));
+            wdesc->fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc->fHeight));
+        }
+
+        GrScratchKey key;
+        GrTexturePriv::ComputeScratchKey(*desc, &key);
+        uint32_t scratchFlags = 0;
+        if (kNoPendingIO_ScratchTextureFlag & flags) {
+            scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
+        } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
+            // If it is not a render target then it will most likely be populated by
+            // writePixels() which will trigger a flush if the texture has pending IO.
+            scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
+        }
+        GrGpuResource* resource = fCache->findAndRefScratchResource(key, scratchFlags);
+        if (resource) {
+            GrSurface* surface = static_cast<GrSurface*>(resource);
+            GrRenderTarget* rt = surface->asRenderTarget();
+            if (rt && fGpu->caps()->discardRenderTargetSupport()) {
+                rt->discard();
+            }
+            return surface->asTexture();
+        }
+    }
+
+    if (!(kNoCreate_ScratchTextureFlag & flags)) {
+        return fGpu->createTexture(*desc, true, NULL, 0);
+    }
+
+    return NULL;
+}
+
+GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc) {
+    if (this->isAbandoned()) {
+        return NULL;
+    }
+    return fGpu->wrapBackendTexture(desc);
+}
+
+GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
+    return this->isAbandoned() ? NULL : fGpu->wrapBackendRenderTarget(desc);
+}
+
+void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
+    if (this->isAbandoned() || !resource) {
+        return;
+    }
+    resource->resourcePriv().setUniqueKey(key);
+}
+
+bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
+    return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
+}
+
+GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
+    return this->isAbandoned() ? NULL : fCache->findAndRefUniqueResource(key);
+}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3ff2f20..13b00de 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -199,7 +199,8 @@
     desc.fHeight = info.height();
     desc.fConfig = SkImageInfo2GrPixelConfig(info);
     desc.fSampleCnt = sampleCount;
-    GrTexture* texture = context->createTexture(desc, SkToBool(budgeted), NULL, 0);
+    GrTexture* texture = context->textureProvider()->createTexture(
+        desc, SkToBool(budgeted), NULL, 0);
     if (NULL == texture) {
         return NULL;
     }
@@ -699,8 +700,8 @@
     desc.fHeight = dstM.fBounds.height();
     desc.fConfig = kAlpha_8_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> texture(
-        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
+    SkAutoTUnref<GrTexture> texture(context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch));
     if (!texture) {
         return false;
     }
@@ -734,7 +735,8 @@
         desc.fConfig = kAlpha_8_GrPixelConfig;
     }
 
-    GrTexture* mask = context->refScratchTexture(desc,GrContext::kApprox_ScratchTexMatch);
+    GrTexture* mask = context->textureProvider()->refScratchTexture(
+        desc, GrTextureProvider::kApprox_ScratchTexMatch);
     if (NULL == mask) {
         return NULL;
     }
@@ -1951,10 +1953,10 @@
 
     // layers are never draw in repeat modes, so we can request an approx
     // match and ignore any padding.
-    const GrContext::ScratchTexMatch match = (kNever_TileUsage == cinfo.fTileUsage) ?
-                                                GrContext::kApprox_ScratchTexMatch :
-                                                GrContext::kExact_ScratchTexMatch;
-    texture.reset(fContext->refScratchTexture(desc, match));
+    const GrTextureProvider::ScratchTexMatch match = (kNever_TileUsage == cinfo.fTileUsage) ?
+                                                  GrTextureProvider::kApprox_ScratchTexMatch :
+                                                  GrTextureProvider::kExact_ScratchTexMatch;
+    texture.reset(fContext->textureProvider()->refScratchTexture(desc, match));
 
     if (texture) {
         SkSurfaceProps props(fSurfaceProps.flags(), cinfo.fPixelGeometry);
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 3161c81..5df8c53 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -177,11 +177,11 @@
                                          SkPixelRef* pixelRefForInvalidationNotification,
                                          const void* pixels,
                                          size_t rowBytes) {
-    GrTexture* result = ctx->createTexture(desc, true, pixels, rowBytes);
+    GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes);
     if (result && optionalKey.isValid()) {
         BitmapInvalidator* listener = SkNEW_ARGS(BitmapInvalidator, (optionalKey));
         pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
-        ctx->addResourceToCache(optionalKey, result);
+        ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result);
     }
     return result;
 }
@@ -368,9 +368,9 @@
         bool needsExactTexture =
             (yuvDesc.fWidth  != yuvInfo.fSize[0].fWidth) ||
             (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight);
-        yuvTextures[i].reset(ctx->refScratchTexture(yuvDesc,
-            needsExactTexture ? GrContext::kExact_ScratchTexMatch :
-                                GrContext::kApprox_ScratchTexMatch));
+        yuvTextures[i].reset(ctx->textureProvider()->refScratchTexture(yuvDesc,
+            needsExactTexture ? GrTextureProvider::kExact_ScratchTexMatch :
+                                GrTextureProvider::kApprox_ScratchTexMatch));
         if (!yuvTextures[i] ||
             !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
                                          yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) {
@@ -471,7 +471,7 @@
         SkAutoTUnref<GrTexture> unstretched;
         // Check if we have the unstretched version in the cache, if not create it.
         if (unstretchedKey.isValid()) {
-            unstretched.reset(ctx->findAndRefCachedTexture(unstretchedKey));
+            unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey));
         }
         if (!unstretched) {
             unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey));
@@ -509,7 +509,7 @@
         }
         GrUniqueKey stretchedKey;
         make_stretched_key(key, stretch, &stretchedKey);
-        return ctx->isResourceInCache(stretchedKey);
+        return ctx->textureProvider()->existsTextureWithUniqueKey(stretchedKey);
     }
 
     // We don't cache volatile bitmaps
@@ -519,7 +519,8 @@
 
     GrUniqueKey key, stretchedKey;
     make_bitmap_keys(bitmap, stretch, &key, &stretchedKey);
-    return ctx->isResourceInCache((kNo_Stretch == stretch) ? key : stretchedKey);
+    return ctx->textureProvider()->existsTextureWithUniqueKey(
+        (kNo_Stretch == stretch) ? key : stretchedKey);
 }
 
 GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
@@ -539,7 +540,8 @@
             const GrUniqueKey& key = result->getUniqueKey();
             if (key.isValid()) {
                 make_stretched_key(key, stretch, &stretchedKey);
-                GrTexture* stretched = ctx->findAndRefCachedTexture(stretchedKey);
+                GrTexture* stretched =
+                    ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
                 if (stretched) {
                     return stretched;
                 }
@@ -554,7 +556,8 @@
         // If the bitmap isn't changing try to find a cached copy first.
         make_bitmap_keys(bitmap, stretch, &key, &resizedKey);
 
-        result = ctx->findAndRefCachedTexture(resizedKey.isValid() ? resizedKey : key);
+        result = ctx->textureProvider()->findAndRefTextureByUniqueKey(
+            resizedKey.isValid() ? resizedKey : key);
         if (result) {
             return result;
         }
diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp
index 01444af..3fa0491 100644
--- a/src/gpu/SkGrPixelRef.cpp
+++ b/src/gpu/SkGrPixelRef.cpp
@@ -80,7 +80,7 @@
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
     desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT);
 
-    GrTexture* dst = context->createTexture(desc, false, NULL, 0);
+    GrTexture* dst = context->textureProvider()->createTexture(desc, false, NULL, 0);
     if (NULL == dst) {
         return NULL;
     }
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 8cf9bb6..8b75a88 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -186,16 +186,16 @@
     desc.fHeight = 256;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> readTex(context->createTexture(desc, true, NULL, 0));
+    SkAutoTUnref<GrTexture> readTex(context->textureProvider()->createTexture(desc, true, NULL, 0));
     if (!readTex.get()) {
         return;
     }
-    SkAutoTUnref<GrTexture> tempTex(context->createTexture(desc, true, NULL, 0));
+    SkAutoTUnref<GrTexture> tempTex(context->textureProvider()->createTexture(desc, true, NULL, 0));
     if (!tempTex.get()) {
         return;
     }
     desc.fFlags = kNone_GrSurfaceFlags;
-    SkAutoTUnref<GrTexture> dataTex(context->createTexture(desc, true, data, 0));
+    SkAutoTUnref<GrTexture> dataTex(context->textureProvider()->createTexture(desc, true, data, 0));
     if (!dataTex.get()) {
         return;
     }
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index 65096bf..8610691 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -204,13 +204,13 @@
     builder[0] = static_cast<uint32_t>(fCacheKey);
     builder.finish();
 
-    fTexture = fDesc.fContext->findAndRefCachedTexture(key);
+    fTexture = fDesc.fContext->textureProvider()->findAndRefTextureByUniqueKey(key);
     if (NULL == fTexture) {
-        fTexture = fDesc.fContext->createTexture(texDesc, true, NULL, 0);
+        fTexture = fDesc.fContext->textureProvider()->createTexture(texDesc, true, NULL, 0);
         if (!fTexture) {
             return;
         }
-        fDesc.fContext->addResourceToCache(key, fTexture);
+        fDesc.fContext->textureProvider()->assignUniqueKeyToTexture(key, fTexture);
         // This is a new texture, so all of our cache info is now invalid
         this->initLRU();
         fKeyTable.rewind();
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index ac2f7fe..8788e08 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -107,7 +107,7 @@
     if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
         return NULL;
     }
-    SkAutoTUnref<GrSurface> surface(context->wrapBackendTexture(desc));
+    SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc));
     if (!surface) {
         return NULL;
     }
diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp
index 61eaa97..f222715 100644
--- a/src/views/SkWindow.cpp
+++ b/src/views/SkWindow.cpp
@@ -360,7 +360,7 @@
     GrGLint buffer;
     GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
     desc.fRenderTargetHandle = buffer;
-    return grContext->wrapBackendRenderTarget(desc);
+    return grContext->textureProvider()->wrapBackendRenderTarget(desc);
 }
 
 #endif
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index 3d3fa95..71d0380 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -31,7 +31,7 @@
     desc.fHeight    = Y_SIZE;
 
     // We are initializing the texture with zeros here
-    GrTexture* texture = context->createTexture(desc, false, textureData, 0);
+    GrTexture* texture = context->textureProvider()->createTexture(desc, false, textureData, 0);
     if (!texture) {
         return NULL;
     }
@@ -52,7 +52,7 @@
     desc.fWidth     = kXSize;
     desc.fHeight    = kYSize;
 
-    GrTexture* texture = context->createTexture(desc, false, NULL, 0);
+    GrTexture* texture = context->textureProvider()->createTexture(desc, false, NULL, 0);
     if (!texture) {
         return;
     }
diff --git a/tests/FloatingPointTextureTest.cpp b/tests/FloatingPointTextureTest.cpp
index 7ac27cb..69495b4 100644
--- a/tests/FloatingPointTextureTest.cpp
+++ b/tests/FloatingPointTextureTest.cpp
@@ -11,9 +11,10 @@
  * 32 bit floating point textures, and indeed floating point test values
  * have been selected to require 32 bits of precision and full IEEE conformance
  */
-#if SK_SUPPORT_GPU
+
 #include <float.h>
 #include "Test.h"
+#if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrTexture.h"
 #include "GrContextFactory.h"
@@ -59,8 +60,8 @@
                 continue;
             }
 
-            SkAutoTUnref<GrTexture> fpTexture(context->createTexture(desc, false,
-                                                                     controlPixelData.begin(), 0));
+            SkAutoTUnref<GrTexture> fpTexture(context->textureProvider()->createTexture(
+                desc, false, controlPixelData.begin(), 0));
             // Floating point textures are NOT supported everywhere
             if (NULL == fpTexture) {
                 continue;
@@ -106,8 +107,8 @@
                 continue;
             }
 
-            SkAutoTUnref<GrTexture> fpTexture(context->createTexture(desc, false,
-                                                                     controlPixelData.begin(), 0));
+            SkAutoTUnref<GrTexture> fpTexture(context->textureProvider()->createTexture(
+                desc, false, controlPixelData.begin(), 0));
             // 16-bit floating point textures are NOT supported everywhere
             if (NULL == fpTexture) {
                 continue;
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index c12e5e8..1d7beec 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -115,11 +115,11 @@
     builder[0] = texDesc.fOrigin;
     builder.finish();
 
-    GrTexture* texture = context->findAndRefCachedTexture(key);
+    GrTexture* texture = context->textureProvider()->findAndRefTextureByUniqueKey(key);
     if (!texture) {
-        texture = context->createTexture(texDesc, true);
+        texture = context->textureProvider()->createTexture(texDesc, true);
         if (texture) {
-            context->addResourceToCache(key, texture);
+            context->textureProvider()->assignUniqueKeyToTexture(key, texture);
         }
     }
     return texture ? texture->asRenderTarget() : NULL;
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 094ca78..685bf41 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -27,7 +27,7 @@
         desc.fWidth = 256;
         desc.fHeight = 256;
         desc.fSampleCnt = 0;
-        GrSurface* texRT1 = context->createTexture(desc, false, NULL, 0);
+        GrSurface* texRT1 = context->textureProvider()->createTexture(desc, false, NULL, 0);
 
         REPORTER_ASSERT(reporter, texRT1 == texRT1->asRenderTarget());
         REPORTER_ASSERT(reporter, texRT1 == texRT1->asTexture());
@@ -39,7 +39,7 @@
                                   static_cast<GrSurface*>(texRT1->asTexture()));
 
         desc.fFlags = kNone_GrSurfaceFlags;
-        GrSurface* tex1 = context->createTexture(desc, false, NULL, 0);
+        GrSurface* tex1 = context->textureProvider()->createTexture(desc, false, NULL, 0);
         REPORTER_ASSERT(reporter, NULL == tex1->asRenderTarget());
         REPORTER_ASSERT(reporter, tex1 == tex1->asTexture());
         REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1) == tex1->asTexture());
@@ -51,7 +51,7 @@
         backendDesc.fHeight = 256;
         backendDesc.fSampleCnt = 0;
         backendDesc.fTextureHandle = 5;
-        GrSurface* texRT2 = context->wrapBackendTexture(backendDesc);
+        GrSurface* texRT2 = context->textureProvider()->wrapBackendTexture(backendDesc);
         REPORTER_ASSERT(reporter, texRT2 == texRT2->asRenderTarget());
         REPORTER_ASSERT(reporter, texRT2 == texRT2->asTexture());
         REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index cead36f..a45e9ee 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -318,7 +318,8 @@
                 desc.fHeight = DEV_H;
                 desc.fConfig = kSkia8888_GrPixelConfig;
                 desc.fOrigin = 1 == dtype ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
-                SkAutoTUnref<GrTexture> texture(context->createTexture(desc, false));
+                SkAutoTUnref<GrTexture> texture(
+                    context->textureProvider()->createTexture(desc, false));
                 surface.reset(SkSurface::NewRenderTargetDirect(texture->asRenderTarget()));
 #else
                 continue;
diff --git a/tests/ReadWriteAlphaTest.cpp b/tests/ReadWriteAlphaTest.cpp
index 3f9ff1b..6ae77d0 100644
--- a/tests/ReadWriteAlphaTest.cpp
+++ b/tests/ReadWriteAlphaTest.cpp
@@ -41,7 +41,7 @@
         desc.fHeight    = Y_SIZE;
 
         // We are initializing the texture with zeros here
-        GrTexture* texture = context->createTexture(desc, false, textureData, 0);
+        GrTexture* texture = context->textureProvider()->createTexture(desc, false, textureData, 0);
         if (!texture) {
             return;
         }
diff --git a/tests/RecordReplaceDrawTest.cpp b/tests/RecordReplaceDrawTest.cpp
index 41da9a1..473683b 100644
--- a/tests/RecordReplaceDrawTest.cpp
+++ b/tests/RecordReplaceDrawTest.cpp
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#if SK_SUPPORT_GPU
-
 #include "Test.h"
 
+#if SK_SUPPORT_GPU
+
 #include "GrContextFactory.h"
 #include "GrLayerCache.h"
 #include "GrRecordReplaceDraw.h"
@@ -124,7 +124,8 @@
     desc.fHeight = kHeight;
     desc.fSampleCnt = 0;
 
-    SkAutoTUnref<GrTexture> texture(context->createTexture(desc, false, NULL, 0));
+    SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc,
+        false, NULL, 0));
     layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight));
 
     SkAutoTUnref<SkBBoxHierarchy> bbh;
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index cd58905..71fb4e3 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -76,13 +76,14 @@
     smallDesc.fHeight = 4;
     smallDesc.fSampleCnt = 0;
 
+    GrTextureProvider* cache = context->textureProvider();
     // Test that two budgeted RTs with the same desc share a stencil buffer.
-    SkAutoTUnref<GrTexture> smallRT0(context->createTexture(smallDesc, true));
+    SkAutoTUnref<GrTexture> smallRT0(cache->createTexture(smallDesc, true));
     if (smallRT0 && smallRT0->asRenderTarget()) {
         smallRT0->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
     }
 
-    SkAutoTUnref<GrTexture> smallRT1(context->createTexture(smallDesc, true));
+    SkAutoTUnref<GrTexture> smallRT1(cache->createTexture(smallDesc, true));
     if (smallRT1 && smallRT1->asRenderTarget()) {
         smallRT1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
     }
@@ -94,7 +95,7 @@
                     smallRT1->asRenderTarget()->renderTargetPriv().getStencilAttachment());
 
     // An unbudgeted RT with the same desc should also share.
-    SkAutoTUnref<GrTexture> smallRT2(context->createTexture(smallDesc, false));
+    SkAutoTUnref<GrTexture> smallRT2(cache->createTexture(smallDesc, false));
     if (smallRT2 && smallRT2->asRenderTarget()) {
         smallRT2->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
     }
@@ -111,7 +112,7 @@
     bigDesc.fWidth = 400;
     bigDesc.fHeight = 200;
     bigDesc.fSampleCnt = 0;
-    SkAutoTUnref<GrTexture> bigRT(context->createTexture(bigDesc, false));
+    SkAutoTUnref<GrTexture> bigRT(cache->createTexture(bigDesc, false));
     if (bigRT && bigRT->asRenderTarget()) {
         bigRT->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
     }
@@ -125,7 +126,7 @@
         // An RT with a different sample count should not share. 
         GrSurfaceDesc smallMSAADesc = smallDesc;
         smallMSAADesc.fSampleCnt = 4;
-        SkAutoTUnref<GrTexture> smallMSAART0(context->createTexture(smallMSAADesc, false));
+        SkAutoTUnref<GrTexture> smallMSAART0(cache->createTexture(smallMSAADesc, false));
         if (smallMSAART0 && smallMSAART0->asRenderTarget()) {
             smallMSAART0->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
         }
@@ -141,7 +142,7 @@
                         smallRT0->asRenderTarget()->renderTargetPriv().getStencilAttachment() !=
                         smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilAttachment());
         // A second MSAA RT should share with the first MSAA RT.
-        SkAutoTUnref<GrTexture> smallMSAART1(context->createTexture(smallMSAADesc, false));
+        SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
         if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
             smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
         }
@@ -156,8 +157,8 @@
         if (context->getMaxSampleCount() >= 8 && smallMSAART0 && smallMSAART0->asRenderTarget() &&
             smallMSAART0->asRenderTarget()->numSamples() < 8) {
             smallMSAADesc.fSampleCnt = 8;
-            smallMSAART1.reset(context->createTexture(smallMSAADesc, false));
-            SkAutoTUnref<GrTexture> smallMSAART1(context->createTexture(smallMSAADesc, false));
+            smallMSAART1.reset(cache->createTexture(smallMSAADesc, false));
+            SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
             if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
                 smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilAttachment();
             }
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index a7c6460..23a7f94 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -104,7 +104,7 @@
     texDesc.fWidth = texDesc.fHeight = 100;
     texDesc.fSampleCnt = 0;
     texDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
-    SkAutoTUnref<GrSurface> dummySurface(ctx->createTexture(texDesc, false));
+    SkAutoTUnref<GrSurface> dummySurface(ctx->textureProvider()->createTexture(texDesc, false));
 
     REPORTER_ASSERT(reporter, dummySurface && dummySurface->asTexture() &&
                               dummySurface->asRenderTarget());
diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp
index 5c7619c..bc2d0d1 100644
--- a/tests/TessellatingPathRendererTests.cpp
+++ b/tests/TessellatingPathRendererTests.cpp
@@ -251,9 +251,8 @@
     desc.fHeight = 800;
     desc.fConfig = kSkia8888_GrPixelConfig;
     desc.fOrigin = kTopLeft_GrSurfaceOrigin;
-    SkAutoTUnref<GrTexture> texture(
-        context->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch)
-    );
+    SkAutoTUnref<GrTexture> texture(context->textureProvider()->refScratchTexture(desc,
+        GrTextureProvider::kExact_ScratchTexMatch));
     GrTestTarget tt;
     context->getTestTarget(&tt);
     GrRenderTarget* rt = texture->asRenderTarget();
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index 2d24a77..d1c328e 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -319,7 +319,7 @@
             desc.fConfig = kSkia8888_GrPixelConfig;
             desc.fOrigin = kGpu_TopLeft_DevType == c.fDevType ?
                 kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
-            SkAutoTUnref<GrTexture> texture(grCtx->createTexture(desc, false));
+            SkAutoTUnref<GrTexture> texture(grCtx->textureProvider()->createTexture(desc, false));
             return SkSurface::NewRenderTargetDirect(texture->asRenderTarget());
 #endif
     }
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index aec153d..559413f 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -156,7 +156,7 @@
                 desc.fWidth = width;
                 desc.fHeight = height;
                 desc.fSampleCnt = fSampleCount;
-                target.reset(fGrContext->createTexture(desc, false, NULL, 0));
+                target.reset(fGrContext->textureProvider()->createTexture(desc, false, NULL, 0));
             }
 
             uint32_t flags = fUseDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;