Add GrProxyProvider

This pulls all the proxy tracking & creation functionality out of the GrResourceCache and GrResourceProvider and consolidates it in the GrProxyProvider.

Change-Id: I7256f7c544319a70c1bd93dd5a9ccbe5fa0a544f
Reviewed-on: https://skia-review.googlesource.com/91501
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/gm/flippity.cpp b/gm/flippity.cpp
index f435838..93813b9 100644
--- a/gm/flippity.cpp
+++ b/gm/flippity.cpp
@@ -12,6 +12,7 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrContextPriv.h"
 #include "SkImage_Gpu.h"
 
 static const int kNumMatrices = 6;
@@ -129,9 +130,10 @@
         }
     }
 
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                                               desc, SkBudgeted::kYes,
-                                                               bm.getPixels(), bm.rowBytes());
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(
+                                                            context->contextPriv().proxyProvider(),
+                                                            desc, SkBudgeted::kYes,
+                                                            bm.getPixels(), bm.rowBytes());
     if (!proxy) {
         return nullptr;
     }
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
index 4b63e2e..4e44bcc 100644
--- a/gm/texdata.cpp
+++ b/gm/texdata.cpp
@@ -91,9 +91,10 @@
         desc.fHeight    = 2 * S;
         desc.fConfig    = SkImageInfo2GrPixelConfig(ii, *context->caps());
 
-        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                                                   desc, SkBudgeted::kNo,
-                                                                   gTextureData.get(), 0);
+        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(
+                                                            context->contextPriv().proxyProvider(),
+                                                            desc, SkBudgeted::kNo,
+                                                            gTextureData.get(), 0);
         if (!proxy) {
             return;
         }
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index 3dd0847..7ee28b1 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -12,6 +12,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrRenderTargetContextPriv.h"
 #include "SkBitmap.h"
 #include "SkGr.h"
@@ -91,10 +92,11 @@
         desc.fHeight = fBmp.height();
         desc.fConfig = SkImageInfo2GrPixelConfig(fBmp.info(), *context->caps());
 
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                                                 desc, SkBudgeted::kYes,
-                                                                 fBmp.getPixels(),
-                                                                 fBmp.rowBytes()));
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(
+                                                            context->contextPriv().proxyProvider(),
+                                                            desc, SkBudgeted::kYes,
+                                                            fBmp.getPixels(),
+                                                            fBmp.rowBytes()));
         if (!proxy) {
             return;
         }
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index f5a905c..ba27719 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -12,6 +12,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrRenderTargetContextPriv.h"
 #include "GrTextureProxy.h"
 #include "SkBitmap.h"
@@ -92,7 +93,7 @@
                 desc.fHeight = fBmp[i].height();
                 desc.fConfig = SkImageInfo2GrPixelConfig(fBmp[i].info(), *context->caps());
 
-                proxy[i] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                proxy[i] = GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(),
                                                         desc, SkBudgeted::kYes,
                                                         fBmp[i].getPixels(), fBmp[i].rowBytes());
                 if (!proxy[i]) {
@@ -222,7 +223,7 @@
                 desc.fHeight = fBmp[index].height();
                 desc.fConfig = SkImageInfo2GrPixelConfig(fBmp[index].info(), *context->caps());
 
-                proxy[i] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                proxy[i] = GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(),
                                                         desc, SkBudgeted::kYes,
                                                         fBmp[index].getPixels(),
                                                         fBmp[index].rowBytes());
diff --git a/gn/gpu.gni b/gn/gpu.gni
index f41dc4a..a9e3ade 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -142,6 +142,8 @@
   "$_src/gpu/GrProcessorAnalysis.h",
   "$_src/gpu/GrProcessorUnitTest.cpp",
   "$_src/gpu/GrProcessorUnitTest.h",
+  "$_src/gpu/GrProxyProvider.cpp",
+  "$_src/gpu/GrProxyProvider.h",
   "$_src/gpu/GrGpuResourceRef.cpp",
   "$_src/gpu/GrQuad.h",
   "$_src/gpu/GrRect.h",
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index dd0ceff..84c71f8 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -30,6 +30,7 @@
 struct GrMockOptions;
 class GrOvalRenderer;
 class GrPath;
+class GrProxyProvider;
 class GrRenderTargetContext;
 class GrResourceEntry;
 class GrResourceCache;
@@ -356,6 +357,7 @@
     sk_sp<const GrCaps>                     fCaps;
     GrResourceCache*                        fResourceCache;
     GrResourceProvider*                     fResourceProvider;
+    GrProxyProvider*                        fProxyProvider;
 
     sk_sp<GrContextThreadSafeProxy>         fThreadSafeProxy;
 
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 493140b..b5ea486 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -16,6 +16,7 @@
 class GrBackendTexture;
 class GrCaps;
 class GrOpList;
+class GrProxyProvider;
 class GrRenderTargetOpList;
 class GrRenderTargetProxy;
 class GrResourceProvider;
@@ -184,7 +185,7 @@
     static sk_sp<GrSurfaceProxy> MakeWrapped(sk_sp<GrSurface>, GrSurfaceOrigin);
     static sk_sp<GrTextureProxy> MakeWrapped(sk_sp<GrTexture>, GrSurfaceOrigin);
 
-    static sk_sp<GrTextureProxy> MakeDeferred(GrResourceProvider*,
+    static sk_sp<GrTextureProxy> MakeDeferred(GrProxyProvider*,
                                               const GrSurfaceDesc&, SkBackingFit,
                                               SkBudgeted, uint32_t flags = 0);
 
@@ -196,7 +197,7 @@
      * @param texels        A contiguous array of mipmap levels
      * @param mipLevelCount The amount of elements in the texels array
      */
-    static sk_sp<GrTextureProxy> MakeDeferredMipMap(GrResourceProvider*,
+    static sk_sp<GrTextureProxy> MakeDeferredMipMap(GrProxyProvider*,
                                                     const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                                     const GrMipLevel texels[], int mipLevelCount,
                                                     SkDestinationSurfaceColorMode mipColorMode =
@@ -207,13 +208,13 @@
      * simply has space allocated for the mips. We will allocated the full amount of mip levels
      * based on the width and height in the GrSurfaceDesc.
      */
-    static sk_sp<GrTextureProxy> MakeDeferredMipMap(GrResourceProvider*,
+    static sk_sp<GrTextureProxy> MakeDeferredMipMap(GrProxyProvider*,
                                                     const GrSurfaceDesc& desc, SkBudgeted budgeted);
 
 
     // TODO: need to refine ownership semantics of 'srcData' if we're in completely
     // deferred mode
-    static sk_sp<GrTextureProxy> MakeDeferred(GrResourceProvider*,
+    static sk_sp<GrTextureProxy> MakeDeferred(GrProxyProvider*,
                                               const GrSurfaceDesc&, SkBudgeted,
                                               const void* srcData, size_t rowBytes);
 
diff --git a/include/private/GrTextureProxy.h b/include/private/GrTextureProxy.h
index a2f11d5..2e7c002 100644
--- a/include/private/GrTextureProxy.h
+++ b/include/private/GrTextureProxy.h
@@ -13,7 +13,7 @@
 
 class GrCaps;
 class GrDeferredProxyUploader;
-class GrResourceCache;
+class GrProxyProvider;
 class GrResourceProvider;
 class GrTextureOpList;
 class GrTextureProxyPriv;
@@ -84,8 +84,8 @@
     GrMipMapped fMipMapped;
     SkDestinationSurfaceColorMode fMipColorMode;
 
-    GrUniqueKey fUniqueKey;
-    GrResourceCache* fCache; // only set when fUniqueKey is valid
+    GrUniqueKey      fUniqueKey;
+    GrProxyProvider* fProxyProvider; // only set when fUniqueKey is valid
 
     // Only used for proxies whose contents are being prepared on a worker thread. This object
     // stores the texture data, allowing the proxy to remain uninstantiated until flush. At that
@@ -95,7 +95,7 @@
     size_t onUninstantiatedGpuMemorySize() const override;
 
     // Methods made available via GrTextureProxy::CacheAccess
-    void setUniqueKey(GrResourceCache*, const GrUniqueKey&);
+    void setUniqueKey(GrProxyProvider*, const GrUniqueKey&);
     void clearUniqueKey();
 
     SkDEBUGCODE(void validateLazyTexture(const GrTexture*) override;)
diff --git a/src/core/SkColorSpaceXformImageGenerator.cpp b/src/core/SkColorSpaceXformImageGenerator.cpp
index 8121cf9..d0c91a3 100644
--- a/src/core/SkColorSpaceXformImageGenerator.cpp
+++ b/src/core/SkColorSpaceXformImageGenerator.cpp
@@ -56,6 +56,7 @@
 
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrPaint.h"
 #include "GrRenderTargetContext.h"
 #include "GrTextureProxy.h"
@@ -71,7 +72,7 @@
 
     SkASSERT(ctx);
 
-    sk_sp<GrTextureProxy> proxy = GrUploadBitmapToTextureProxy(ctx->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy = GrUploadBitmapToTextureProxy(ctx->contextPriv().proxyProvider(),
                                                                fSrc, nullptr);
 
     if (!proxy) {
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index df56afd..771950a 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -18,7 +18,7 @@
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrContextPriv.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSurfaceContext.h"
 #include "GrTextureProxy.h"
 #include "SkImage_Gpu.h"
@@ -102,7 +102,8 @@
 
     // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
     // semantics). Since this is cached though we would have to bake the fit into the cache key.
-    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(context->resourceProvider(), bmp);
+    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(context->contextPriv().proxyProvider(),
+                                                          bmp);
     if (!proxy) {
         return nullptr;
     }
@@ -241,7 +242,7 @@
 #if SK_SUPPORT_GPU
     sk_sp<GrTextureProxy> onAsTextureProxyRef(GrContext* context) const override {
         if (context) {
-            return GrMakeCachedBitmapProxy(context->resourceProvider(), fBitmap);
+            return GrMakeCachedBitmapProxy(context->contextPriv().proxyProvider(), fBitmap);
         }
 
         return nullptr;
@@ -455,7 +456,7 @@
         if (subset) {
             // TODO: if this becomes a bottle neck we could base this logic on what the size
             // will be when it is finally instantiated - but that is more fraught.
-            if (GrResourceProvider::IsFunctionallyExact(fTextureProxy.get()) &&
+            if (GrProxyProvider::IsFunctionallyExact(fTextureProxy.get()) &&
                 0 == subset->fLeft && 0 == subset->fTop &&
                 fTextureProxy->width() == subset->width() &&
                 fTextureProxy->height() == subset->height()) {
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index 41ea482..55095e0 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -11,7 +11,7 @@
 #include "GrCircleBlurFragmentProcessor.h"
 #if SK_SUPPORT_GPU
 
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 
 // Computes an unnormalized half kernel (right side). Returns the summation of all the half
 // kernel values.
@@ -166,7 +166,7 @@
     return profile;
 }
 
-static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resourceProvider,
+static sk_sp<GrTextureProxy> create_profile_texture(GrProxyProvider* proxyProvider,
                                                     const SkRect& circle, float sigma,
                                                     float* solidRadius, float* textureRadius) {
     float circleR = circle.width() / 2.0f;
@@ -208,7 +208,7 @@
     builder.finish();
 
     sk_sp<GrTextureProxy> blurProfile =
-            resourceProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
+            proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
     if (!blurProfile) {
         static constexpr int kProfileTextureWidth = 512;
         GrSurfaceDesc texDesc;
@@ -227,30 +227,30 @@
                     create_circle_profile(sigma * scale, circleR * scale, kProfileTextureWidth));
         }
 
-        blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider, texDesc, SkBudgeted::kYes,
+        blurProfile = GrSurfaceProxy::MakeDeferred(proxyProvider, texDesc, SkBudgeted::kYes,
                                                    profile.get(), 0);
         if (!blurProfile) {
             return nullptr;
         }
 
         SkASSERT(blurProfile->origin() == kTopLeft_GrSurfaceOrigin);
-        resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get());
+        proxyProvider->assignUniqueKeyToProxy(key, blurProfile.get());
     }
 
     return blurProfile;
 }
 
 std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make(
-        GrResourceProvider* resourceProvider, const SkRect& circle, float sigma) {
+        GrProxyProvider* proxyProvider, const SkRect& circle, float sigma) {
     float solidRadius;
     float textureRadius;
     sk_sp<GrTextureProxy> profile(
-            create_profile_texture(resourceProvider, circle, sigma, &solidRadius, &textureRadius));
+            create_profile_texture(proxyProvider, circle, sigma, &solidRadius, &textureRadius));
     if (!profile) {
         return nullptr;
     }
     return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(
-            circle, textureRadius, solidRadius, std::move(profile), resourceProvider));
+            circle, textureRadius, solidRadius, std::move(profile)));
 }
 #include "glsl/GrGLSLFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -344,7 +344,7 @@
     SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f);
     SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f);
     SkRect circle = SkRect::MakeWH(wh, wh);
-    return GrCircleBlurFragmentProcessor::Make(testData->resourceProvider(), circle, sigma);
+    return GrCircleBlurFragmentProcessor::Make(testData->proxyProvider(), circle, sigma);
 }
 #endif
 #endif
diff --git a/src/effects/GrCircleBlurFragmentProcessor.fp b/src/effects/GrCircleBlurFragmentProcessor.fp
index a93d2ba..d09103e 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.fp
+++ b/src/effects/GrCircleBlurFragmentProcessor.fp
@@ -13,12 +13,8 @@
     kCompatibleWithCoverageAsAlpha_OptimizationFlag
 }
 
-@constructorParams {
-    GrResourceProvider* resourceProvider
-}
-
 @make {
-    static std::unique_ptr<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
+    static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider*,
                                                      const SkRect& circle, float sigma);
 }
 
@@ -28,7 +24,7 @@
 }
 
 @cpp {
-    #include "GrResourceProvider.h"
+    #include "GrProxyProvider.h"
 
     // Computes an unnormalized half kernel (right side). Returns the summation of all the half
     // kernel values.
@@ -184,11 +180,14 @@
         return profile;
     }
 
-    static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resourceProvider,
+    static sk_sp<GrTextureProxy> create_profile_texture(GrProxyProvider* proxyProvider,
                                                         const SkRect& circle,
                                                         float sigma,
                                                         float* solidRadius, float* textureRadius) {
         float circleR = circle.width() / 2.0f;
+        if (circleR < SK_ScalarNearlyZero) {
+            return nullptr;
+        }
         // Profile textures are cached by the ratio of sigma to circle radius and by the size of the
         // profile texture (binned by powers of 2).
         SkScalar sigmaToCircleRRatio = sigma / circleR;
@@ -224,7 +223,7 @@
         builder.finish();
 
         sk_sp<GrTextureProxy> blurProfile =
-                      resourceProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
+                      proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
         if (!blurProfile) {
             static constexpr int kProfileTextureWidth = 512;
             GrSurfaceDesc texDesc;
@@ -243,30 +242,30 @@
                                                     kProfileTextureWidth));
             }
 
-            blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider,
+            blurProfile = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                        texDesc, SkBudgeted::kYes, profile.get(), 0);
             if (!blurProfile) {
                 return nullptr;
             }
 
             SkASSERT(blurProfile->origin() == kTopLeft_GrSurfaceOrigin);
-            resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get());
+            proxyProvider->assignUniqueKeyToProxy(key, blurProfile.get());
         }
 
         return blurProfile;
     }
 
     std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make(
-            GrResourceProvider* resourceProvider, const SkRect& circle, float sigma) {
+            GrProxyProvider* proxyProvider, const SkRect& circle, float sigma) {
         float solidRadius;
         float textureRadius;
-        sk_sp<GrTextureProxy> profile(create_profile_texture(resourceProvider, circle, sigma,
+        sk_sp<GrTextureProxy> profile(create_profile_texture(proxyProvider, circle, sigma,
                                                              &solidRadius, &textureRadius));
         if (!profile) {
             return nullptr;
         }
         return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(
-                circle, textureRadius, solidRadius, std::move(profile), resourceProvider));
+                circle, textureRadius, solidRadius, std::move(profile)));
     }
 }
 
@@ -283,5 +282,5 @@
     SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f);
     SkScalar sigma = testData->fRandom->nextRangeF(1.f,10.f);
     SkRect circle = SkRect::MakeWH(wh, wh);
-    return GrCircleBlurFragmentProcessor::Make(testData->resourceProvider(), circle, sigma);
+    return GrCircleBlurFragmentProcessor::Make(testData->proxyProvider(), circle, sigma);
 }
diff --git a/src/effects/GrCircleBlurFragmentProcessor.h b/src/effects/GrCircleBlurFragmentProcessor.h
index 747c0ad..4b5c4b3 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.h
+++ b/src/effects/GrCircleBlurFragmentProcessor.h
@@ -20,16 +20,15 @@
     float textureRadius() const { return fTextureRadius; }
     float solidRadius() const { return fSolidRadius; }
 
-    static std::unique_ptr<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
-                                                     const SkRect& circle, float sigma);
+    static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider*, const SkRect& circle,
+                                                     float sigma);
     GrCircleBlurFragmentProcessor(const GrCircleBlurFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "CircleBlurFragmentProcessor"; }
 
 private:
     GrCircleBlurFragmentProcessor(SkRect circleRect, float textureRadius, float solidRadius,
-                                  sk_sp<GrTextureProxy> blurProfileSampler,
-                                  GrResourceProvider* resourceProvider)
+                                  sk_sp<GrTextureProxy> blurProfileSampler)
             : INHERITED(kGrCircleBlurFragmentProcessor_ClassID,
                         (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
             , fCircleRect(circleRect)
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index a7e0d24..396bed9 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -783,7 +783,7 @@
 
     SkScalar xformedSigma = this->computeXformedSigma(viewMatrix);
 
-    GrResourceProvider* resourceProvider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     std::unique_ptr<GrFragmentProcessor> fp;
 
     SkRect rect;
@@ -791,9 +791,9 @@
         SkScalar pad = 3.0f * xformedSigma;
         rect.outset(pad, pad);
 
-        fp = GrRectBlurEffect::Make(resourceProvider, rect, xformedSigma);
+        fp = GrRectBlurEffect::Make(proxyProvider, rect, xformedSigma);
     } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height())) {
-        fp = GrCircleBlurFragmentProcessor::Make(resourceProvider, rect, xformedSigma);
+        fp = GrCircleBlurFragmentProcessor::Make(proxyProvider, rect, xformedSigma);
 
         // expand the rect for the coverage geometry
         int pad = SkScalarCeilToInt(6*xformedSigma)/2;
@@ -835,7 +835,7 @@
         return false;
     }
 
-    GrResourceProvider* resourceProvider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     SkScalar xformedSigma = this->computeXformedSigma(viewMatrix);
 
     if (devRRect.isRect() || devRRect.isCircle()) {
@@ -844,9 +844,9 @@
             SkScalar pad = 3.0f * xformedSigma;
             const SkRect dstCoverageRect = devRRect.rect().makeOutset(pad, pad);
 
-            fp = GrRectBlurEffect::Make(resourceProvider, dstCoverageRect, xformedSigma);
+            fp = GrRectBlurEffect::Make(proxyProvider, dstCoverageRect, xformedSigma);
         } else {
-            fp = GrCircleBlurFragmentProcessor::Make(resourceProvider,
+            fp = GrCircleBlurFragmentProcessor::Make(proxyProvider,
                                                      devRRect.rect(), xformedSigma);
         }
 
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 1d50625..d808c6f 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -315,6 +315,7 @@
 
 #include "GrColorSpaceInfo.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrFragmentProcessor.h"
 #include "GrTextureStripAtlas.h"
 #include "SkGr.h"
@@ -453,7 +454,7 @@
     if (-1 == row) {
         atlas = nullptr;
 
-        proxy = GrMakeCachedBitmapProxy(context->resourceProvider(), bitmap);
+        proxy = GrMakeCachedBitmapProxy(context->contextPriv().proxyProvider(), bitmap);
     } else {
         proxy = atlas->asTextureProxyRef();
     }
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 9b3ba36..064b1aa 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -10,7 +10,7 @@
 #include "GrContext.h"
 #include "GrContextPriv.h"
 #include "GrGpuResourcePriv.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSurfaceContext.h"
 #include "SkBitmap.h"
 #include "SkGr.h"
@@ -37,11 +37,11 @@
         return nullptr;
     }
 
+    GrProxyProvider* proxyProvider = this->context()->contextPriv().proxyProvider();
     sk_sp<GrTextureProxy> proxy;
 
     if (fOriginalKey.isValid()) {
-        proxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
-                                                            fOriginalKey, kTopLeft_GrSurfaceOrigin);
+        proxy = proxyProvider->findOrCreateProxyByUniqueKey(fOriginalKey, kTopLeft_GrSurfaceOrigin);
         if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             return proxy;
         }
@@ -53,13 +53,11 @@
                                                              dstColorSpace);
         }
         if (!proxy) {
-            proxy = GrUploadBitmapToTextureProxy(this->context()->resourceProvider(), fBitmap,
-                                                 dstColorSpace);
+            proxy = GrUploadBitmapToTextureProxy(proxyProvider, fBitmap, dstColorSpace);
         }
         if (proxy) {
             if (fOriginalKey.isValid()) {
-                this->context()->resourceProvider()->assignUniqueKeyToProxy(fOriginalKey,
-                                                                            proxy.get());
+                proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
             }
             if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
@@ -86,10 +84,8 @@
                 // mipmapped version. The texture backing the unmipped version will remain in the
                 // resource cache until the last texture proxy referencing it is deleted at which
                 // time it too will be deleted or recycled.
-                this->context()->resourceProvider()->removeUniqueKeyFromProxy(fOriginalKey,
-                                                                              proxy.get());
-                this->context()->resourceProvider()->assignUniqueKeyToProxy(fOriginalKey,
-                                                                            mippedProxy.get());
+                proxyProvider->removeUniqueKeyFromProxy(fOriginalKey, proxy.get());
+                proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy.get());
                 GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef());
             }
             return mippedProxy;
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 0f647e0..ce77369 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -14,7 +14,7 @@
 #include "GrFixedClip.h"
 #include "GrGpuResourcePriv.h"
 #include "GrRenderTargetContextPriv.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrStencilAttachment.h"
 #include "GrSWMaskHelper.h"
 #include "GrTextureProxy.h"
@@ -324,12 +324,12 @@
 
 sk_sp<GrTextureProxy> GrClipStackClip::createAlphaClipMask(GrContext* context,
                                                            const GrReducedClip& reducedClip) const {
-    GrResourceProvider* resourceProvider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrUniqueKey key;
     create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(),
                          reducedClip.numAnalyticFPs(), &key);
 
-    sk_sp<GrTextureProxy> proxy(resourceProvider->findOrCreateProxyByUniqueKey(
+    sk_sp<GrTextureProxy> proxy(proxyProvider->findOrCreateProxyByUniqueKey(
                                                                 key, kBottomLeft_GrSurfaceOrigin));
     if (proxy) {
         return proxy;
@@ -355,7 +355,7 @@
     }
 
     SkASSERT(result->origin() == kBottomLeft_GrSurfaceOrigin);
-    resourceProvider->assignUniqueKeyToProxy(key, result.get());
+    proxyProvider->assignUniqueKeyToProxy(key, result.get());
     add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key);
 
     return result;
@@ -442,7 +442,9 @@
     create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(),
                          reducedClip.numAnalyticFPs(), &key);
 
-    sk_sp<GrTextureProxy> proxy(context->resourceProvider()->findOrCreateProxyByUniqueKey(
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
+    sk_sp<GrTextureProxy> proxy(proxyProvider->findOrCreateProxyByUniqueKey(
                                                                   key, kTopLeft_GrSurfaceOrigin));
     if (proxy) {
         return proxy;
@@ -462,7 +464,7 @@
         desc.fConfig = kAlpha_8_GrPixelConfig;
         // MDB TODO: We're going to fill this proxy with an ASAP upload (which is out of order wrt
         // to ops), so it can't have any pending IO.
-        proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
+        proxy = GrSurfaceProxy::MakeDeferred(proxyProvider, desc,
                                              SkBackingFit::kApprox, SkBudgeted::kYes,
                                              GrResourceProvider::kNoPendingIO_Flag);
 
@@ -496,7 +498,7 @@
     }
 
     SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-    context->resourceProvider()->assignUniqueKeyToProxy(key, proxy.get());
+    proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
     add_invalidate_on_pop_message(*fStack, reducedClip.maskGenID(), key);
     return proxy;
 }
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 9240d63..131ac45 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -12,6 +12,7 @@
 #include "GrContextPriv.h"
 #include "GrDrawingManager.h"
 #include "GrGpu.h"
+#include "GrProxyProvider.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetProxy.h"
 #include "GrResourceCache.h"
@@ -198,6 +199,7 @@
         , fBackend(backend) {
     fResourceCache = nullptr;
     fResourceProvider = nullptr;
+    fProxyProvider = nullptr;
     fAtlasGlyphCache = nullptr;
 }
 
@@ -206,6 +208,7 @@
         , fBackend(proxy->fBackend) {
     fResourceCache = nullptr;
     fResourceProvider = nullptr;
+    fProxyProvider = nullptr;
     fAtlasGlyphCache = nullptr;
 }
 
@@ -214,6 +217,9 @@
     fCaps = fGpu->refCaps();
     fResourceCache = new GrResourceCache(fCaps.get(), fUniqueID);
     fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, &fSingleOwner);
+    fProxyProvider = new GrProxyProvider(fResourceProvider, fResourceCache, fCaps, &fSingleOwner);
+    fResourceCache->setProxyProvider(fProxyProvider);
+
     // DDL TODO: we need to think through how the task group & persistent cache
     // get passed on to/shared between all the DDLRecorders created with this context.
     fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->uniqueID(), fBackend,
@@ -293,6 +299,7 @@
 
     delete fResourceProvider;
     delete fResourceCache;
+    delete fProxyProvider;
     delete fAtlasGlyphCache;
 }
 
@@ -303,6 +310,7 @@
 void GrContext::abandonContext() {
     ASSERT_SINGLE_OWNER
 
+    fProxyProvider->abandon();
     fResourceProvider->abandon();
 
     // Need to abandon the drawing manager first so all the render targets
@@ -322,6 +330,7 @@
 void GrContext::releaseResourcesAndAbandonContext() {
     ASSERT_SINGLE_OWNER
 
+    fProxyProvider->abandon();
     fResourceProvider->abandon();
 
     // Need to abandon the drawing manager first so all the render targets
@@ -521,7 +530,7 @@
 
     sk_sp<GrTextureProxy> tempProxy;
     if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
-        tempProxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
+        tempProxy = GrSurfaceProxy::MakeDeferred(this->proxyProvider(),
                                                  tempDrawInfo.fTempSurfaceDesc,
                                                  SkBackingFit::kApprox,
                                                  SkBudgeted::kYes);
@@ -812,11 +821,11 @@
 
     sk_sp<GrTextureProxy> proxy;
     if (GrMipMapped::kNo == mipMapped) {
-        proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(), dstDesc, fit,
+        proxy = GrSurfaceProxy::MakeDeferred(this->proxyProvider(), dstDesc, fit,
                                              isDstBudgeted);
     } else {
         SkASSERT(SkBackingFit::kExact == fit);
-        proxy = GrSurfaceProxy::MakeDeferredMipMap(fContext->resourceProvider(), dstDesc,
+        proxy = GrSurfaceProxy::MakeDeferredMipMap(this->proxyProvider(), dstDesc,
                                                    isDstBudgeted);
     }
     if (!proxy) {
@@ -978,9 +987,9 @@
 
     sk_sp<GrTextureProxy> rtp;
     if (GrMipMapped::kNo == mipMapped) {
-        rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(), desc, fit, budgeted);
+        rtp = GrSurfaceProxy::MakeDeferred(fProxyProvider, desc, fit, budgeted);
     } else {
-        rtp = GrSurfaceProxy::MakeDeferredMipMap(this->resourceProvider(), desc, budgeted);
+        rtp = GrSurfaceProxy::MakeDeferredMipMap(fProxyProvider, desc, budgeted);
     }
     if (!rtp) {
         return nullptr;
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 2a286f2..2da8f34 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -167,6 +167,9 @@
 
     SkTaskGroup* getTaskGroup() { return fContext->fTaskGroup.get(); }
 
+    GrProxyProvider* proxyProvider() { return fContext->fProxyProvider; }
+    const GrProxyProvider* proxyProvider() const { return fContext->fProxyProvider; }
+
 private:
     explicit GrContextPriv(GrContext* context) : fContext(context) {}
     GrContextPriv(const GrContextPriv&); // unimpl
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 22afd03..420c43b 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -9,6 +9,7 @@
 
 #include "GrBackendSemaphore.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
 #include "GrOnFlushResourceProvider.h"
 #include "GrOpList.h"
@@ -377,7 +378,7 @@
     if (!pr && allowSW) {
         if (!fSoftwarePathRenderer) {
             fSoftwarePathRenderer =
-                    new GrSoftwarePathRenderer(fContext->resourceProvider(),
+                    new GrSoftwarePathRenderer(fContext->contextPriv().proxyProvider(),
                                                fOptionsForPathRendererChain.fAllowPathMaskCaching);
         }
         if (GrPathRenderer::CanDrawPath::kNo != fSoftwarePathRenderer->canDrawPath(args)) {
diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp
index e3b5eeb..a93c9eb 100644
--- a/src/gpu/GrOnFlushResourceProvider.cpp
+++ b/src/gpu/GrOnFlushResourceProvider.cpp
@@ -7,6 +7,7 @@
 
 #include "GrOnFlushResourceProvider.h"
 
+#include "GrContextPriv.h"
 #include "GrDrawingManager.h"
 #include "GrSurfaceProxy.h"
 
@@ -21,11 +22,11 @@
     // will, when instantiated, have no pending IO.
     // TODO: fold the kNoPendingIO_Flag into GrSurfaceFlags?
     sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(
-                                                    fDrawingMgr->getContext()->resourceProvider(),
-                                                    tmpDesc,
-                                                    SkBackingFit::kExact,
-                                                    SkBudgeted::kYes,
-                                                    GrResourceProvider::kNoPendingIO_Flag);
+                                        fDrawingMgr->getContext()->contextPriv().proxyProvider(),
+                                        tmpDesc,
+                                        SkBackingFit::kExact,
+                                        SkBudgeted::kYes,
+                                        GrResourceProvider::kNoPendingIO_Flag);
     if (!proxy->asRenderTargetProxy()) {
         return nullptr;
     }
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 8f8e797..96cbca4 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -7,6 +7,7 @@
 
 #include "GrProcessor.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGeometryProcessor.h"
 #include "GrMemoryPool.h"
 #include "GrSamplerState.h"
@@ -20,6 +21,10 @@
     return fContext->resourceProvider();
 }
 
+GrProxyProvider* GrProcessorTestData::proxyProvider() {
+    return fContext->contextPriv().proxyProvider();
+}
+
 const GrCaps* GrProcessorTestData::caps() {
     return fContext->caps();
 }
diff --git a/src/gpu/GrProcessorUnitTest.h b/src/gpu/GrProcessorUnitTest.h
index 739b2f0..731080e 100644
--- a/src/gpu/GrProcessorUnitTest.h
+++ b/src/gpu/GrProcessorUnitTest.h
@@ -19,6 +19,7 @@
 class SkMatrix;
 class GrCaps;
 class GrContext;
+class GrProxyProvider;
 class GrRenderTargetContext;
 struct GrProcessorTestData;
 class GrTexture;
@@ -63,6 +64,7 @@
 
     GrContext* context() { return fContext; }
     GrResourceProvider* resourceProvider();
+    GrProxyProvider* proxyProvider();
     const GrCaps* caps();
     sk_sp<GrTextureProxy> textureProxy(int index) { return fProxies[index]; }
 
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
new file mode 100644
index 0000000..d86f9bc
--- /dev/null
+++ b/src/gpu/GrProxyProvider.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrProxyProvider.h"
+
+#include "GrCaps.h"
+#include "GrResourceKey.h"
+#include "GrResourceProvider.h"
+#include "GrSurfaceProxy.h"
+#include "GrSurfaceProxyPriv.h"
+#include "GrTexture.h"
+#include "GrTextureProxyCacheAccess.h"
+#include "../private/GrSingleOwner.h"
+
+#define ASSERT_SINGLE_OWNER \
+    SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
+
+GrProxyProvider::GrProxyProvider(GrResourceProvider* resourceProvider,
+                                 GrResourceCache* resourceCache,
+                                 sk_sp<const GrCaps> caps,
+                                 GrSingleOwner* owner)
+        : fResourceProvider(resourceProvider)
+        , fResourceCache(resourceCache)
+        , fCaps(caps)
+#ifdef SK_DEBUG
+        , fSingleOwner(owner)
+#endif
+{
+
+}
+
+GrProxyProvider::~GrProxyProvider() {
+    SkASSERT(!fUniquelyKeyedProxies.count());
+}
+
+void GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
+    ASSERT_SINGLE_OWNER
+    SkASSERT(key.isValid());
+    if (this->isAbandoned() || !proxy) {
+        return;
+    }
+
+    // If there is already a GrResource with this key then the caller has violated the normal
+    // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
+    // if it already existed in the cache).
+    SkASSERT(!fResourceCache->findAndRefUniqueResource(key));
+
+    // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
+    // resources are a special case: the unique keys give us a weak ref so that we can reuse the
+    // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
+    // it will always be released - it is never converted to a scratch resource.
+    if (SkBudgeted::kNo == proxy->isBudgeted() &&
+                    (!proxy->priv().isInstantiated() ||
+                     !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
+        return;
+    }
+
+    SkASSERT(!fUniquelyKeyedProxies.find(key));     // multiple proxies can't get the same key
+
+    proxy->cacheAccess().setUniqueKey(this, key);
+    SkASSERT(proxy->getUniqueKey() == key);
+    fUniquelyKeyedProxies.add(proxy);
+}
+
+void GrProxyProvider::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
+    SkASSERT(surf->getUniqueKey().isValid());
+    proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
+    SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
+    // multiple proxies can't get the same key
+    SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
+    fUniquelyKeyedProxies.add(proxy);
+}
+
+void GrProxyProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
+    ASSERT_SINGLE_OWNER
+    if (this->isAbandoned() || !proxy) {
+        return;
+    }
+    this->processInvalidProxyUniqueKey(key, proxy, true);
+}
+
+sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& key,
+                                                            GrSurfaceOrigin origin) {
+    ASSERT_SINGLE_OWNER
+
+    if (this->isAbandoned()) {
+        return nullptr;
+    }
+
+    sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
+    if (result) {
+        SkASSERT(result->origin() == origin);
+    }
+    return result;
+}
+
+sk_sp<GrTextureProxy> GrProxyProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
+                                                                    GrSurfaceOrigin origin) {
+    ASSERT_SINGLE_OWNER
+
+    if (this->isAbandoned()) {
+        return nullptr;
+    }
+
+    sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
+    if (result) {
+        return result;
+    }
+
+    GrGpuResource* resource = fResourceCache->findAndRefUniqueResource(key);
+    if (!resource) {
+        return nullptr;
+    }
+
+    sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
+    SkASSERT(texture);
+
+    result = GrSurfaceProxy::MakeWrapped(std::move(texture), origin);
+    SkASSERT(result->getUniqueKey() == key);
+    // MakeWrapped should've added this for us
+    SkASSERT(fUniquelyKeyedProxies.find(key));
+    return result;
+}
+
+sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(const GrSurfaceDesc& desc,
+                                                          SkBudgeted budgeted,
+                                                          const GrMipLevel& mipLevel) {
+    ASSERT_SINGLE_OWNER
+
+    sk_sp<GrTexture> tex = fResourceProvider->createTexture(desc, budgeted, mipLevel);
+    if (!tex) {
+        return nullptr;
+    }
+
+    return GrSurfaceProxy::MakeWrapped(std::move(tex), desc.fOrigin);
+}
+
+sk_sp<GrTextureProxy> GrProxyProvider::createTextureProxy(
+                                                    const GrSurfaceDesc& desc, SkBudgeted budgeted,
+                                                    const GrMipLevel texels[], int mipLevelCount,
+                                                    SkDestinationSurfaceColorMode mipColorMode) {
+    sk_sp<GrTexture> tex(fResourceProvider->createTexture(desc, budgeted,
+                                                          texels, mipLevelCount,
+                                                          mipColorMode));
+    if (!tex) {
+        return nullptr;
+    }
+
+    return GrSurfaceProxy::MakeWrapped(std::move(tex), desc.fOrigin);
+}
+
+bool GrProxyProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
+    return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
+}
+
+void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
+    // Note: this method is called for the whole variety of GrGpuResources so often 'key'
+    // will not be in 'fUniquelyKeyedProxies'.
+    GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
+    if (proxy) {
+        this->processInvalidProxyUniqueKey(key, proxy, false);
+    }
+}
+
+void GrProxyProvider::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
+                                                   bool invalidateSurface) {
+    SkASSERT(proxy);
+    SkASSERT(proxy->getUniqueKey().isValid());
+    SkASSERT(proxy->getUniqueKey() == key);
+
+    fUniquelyKeyedProxies.remove(key);
+    proxy->cacheAccess().clearUniqueKey();
+
+    if (invalidateSurface && proxy->priv().isInstantiated()) {
+        GrSurface* surface = proxy->priv().peekSurface();
+        if (surface) {
+            surface->resourcePriv().removeUniqueKey();
+        }
+    }
+}
+
+void GrProxyProvider::removeAllUniqueKeys() {
+    UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
+    for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
+        GrTextureProxy& tmp = *iter;
+
+        this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
+    }
+    SkASSERT(!fUniquelyKeyedProxies.count());
+}
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
new file mode 100644
index 0000000..404e020
--- /dev/null
+++ b/src/gpu/GrProxyProvider.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrProxyProvider_DEFINED
+#define GrProxyProvider_DEFINED
+
+#include "GrResourceKey.h"
+#include "GrTextureProxy.h"
+#include "GrTypes.h"
+#include "SkRefCnt.h"
+#include "SkTDynamicHash.h"
+
+class GrCaps;
+class GrResourceProvider;
+class GrSingleOwner;
+
+/*
+ * A factory for creating GrSurfaceProxy-derived objects.
+ */
+class GrProxyProvider {
+public:
+    GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp<const GrCaps>, GrSingleOwner*);
+
+    ~GrProxyProvider();
+
+    /*
+     * Assigns a unique key to a proxy. The proxy will be findable via this key using
+     * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
+     */
+    void assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
+
+    /*
+     * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
+     * have a valid unique key.
+     */
+    void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);
+
+    /*
+     * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
+     * also remove the unique key from the target GrSurface.
+     */
+    void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
+
+    /*
+     * Finds a proxy by unique key.
+     */
+    sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
+
+    /*
+     * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
+     * key.
+     */
+    sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
+
+    /*
+     * Create an un-mipmapped texture proxy with data.
+     */
+    sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel&);
+
+    /*
+     * Create a mipmapped texture proxy with data.
+     */
+    sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted,
+                                             const GrMipLevel texels[], int mipLevelCount,
+                                             SkDestinationSurfaceColorMode mipColorMode);
+
+    // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
+    // determine if it is going to need a texture domain or a full clear.
+    static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
+
+    /**
+     * Either the proxy attached to the unique key is being deleted (in which case we
+     * don't want it cluttering up the hash table) or the client has indicated that
+     * it will never refer to the unique key again. In either case, remove the key
+     * from the hash table.
+     * Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
+     */
+    void processInvalidProxyUniqueKey(const GrUniqueKey&);
+
+    /**
+     * Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
+     * GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
+     * also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
+     */
+    void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);
+
+    const GrCaps* caps() const { return fCaps.get(); }
+
+    void abandon() {
+        fResourceCache = nullptr;
+        fResourceProvider = nullptr;
+    }
+
+    bool isAbandoned() const {
+        SkASSERT(SkToBool(fResourceCache) == SkToBool(fResourceProvider));
+        return !SkToBool(fResourceCache);
+    }
+
+    int numUniqueKeyProxies_TestOnly() const;
+
+    void removeAllUniqueKeys();
+
+private:
+    struct UniquelyKeyedProxyHashTraits {
+        static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
+
+        static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
+    };
+    typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
+
+    // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
+    // on these proxies but they must send a message to the resourceCache when they are deleted.
+    UniquelyKeyedProxyHash fUniquelyKeyedProxies;
+
+    GrResourceProvider*    fResourceProvider;
+    GrResourceCache*       fResourceCache;
+    sk_sp<const GrCaps>    fCaps;
+
+    // In debug builds we guard against improper thread handling
+    SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
+};
+
+#endif
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 20acf54..50b2e9a 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -10,6 +10,7 @@
 
 #include "GrCaps.h"
 #include "GrGpuResourceCacheAccess.h"
+#include "GrProxyProvider.h"
 #include "GrTexture.h"
 #include "GrTextureProxyCacheAccess.h"
 #include "GrTracing.h"
@@ -64,7 +65,8 @@
 
 
 GrResourceCache::GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID)
-    : fTimestamp(0)
+    : fProxyProvider(nullptr)
+    , fTimestamp(0)
     , fMaxCount(kDefaultMaxCount)
     , fMaxBytes(kDefaultMaxSize)
     , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes)
@@ -196,15 +198,10 @@
 
     this->processFreedGpuResources();
 
+    SkASSERT(fProxyProvider); // better have called setProxyProvider
     // We must remove the uniqueKeys from the proxies here. While they possess a uniqueKey
     // they also have a raw pointer back to this class (which is presumably going away)!
-    UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies);
-    for (UniquelyKeyedProxyHash::Iter iter(&fUniquelyKeyedProxies); !iter.done(); ++iter) {
-        GrTextureProxy& tmp = *iter;
-
-        this->processInvalidProxyUniqueKey(tmp.getUniqueKey(), &tmp, false);
-    }
-    SkASSERT(!fUniquelyKeyedProxies.count());
+    fProxyProvider->removeAllUniqueKeys();
 
     while(fNonpurgeableResources.count()) {
         GrGpuResource* back = *(fNonpurgeableResources.end() - 1);
@@ -588,9 +585,11 @@
 }
 
 void GrResourceCache::processInvalidUniqueKeys(
-    const SkTArray<GrUniqueKeyInvalidatedMessage>& msgs) {
+                                            const SkTArray<GrUniqueKeyInvalidatedMessage>& msgs) {
+    SkASSERT(fProxyProvider); // better have called setProxyProvider
+
     for (int i = 0; i < msgs.count(); ++i) {
-        this->processInvalidProxyUniqueKey(msgs[i].key());
+        fProxyProvider->processInvalidProxyUniqueKey(msgs[i].key());
 
         GrGpuResource* resource = this->findAndRefUniqueResource(msgs[i].key());
         if (resource) {
@@ -861,97 +860,3 @@
 }
 
 #endif
-
-void GrResourceCache::adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface* surf) {
-    SkASSERT(surf->getUniqueKey().isValid());
-    proxy->cacheAccess().setUniqueKey(this, surf->getUniqueKey());
-    SkASSERT(proxy->getUniqueKey() == surf->getUniqueKey());
-    // multiple proxies can't get the same key
-    SkASSERT(!fUniquelyKeyedProxies.find(surf->getUniqueKey()));
-    fUniquelyKeyedProxies.add(proxy);
-}
-
-void GrResourceCache::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
-    SkASSERT(key.isValid());
-    SkASSERT(proxy);
-
-    // If there is already a GrResource with this key then the caller has violated the normal
-    // usage pattern of uniquely keyed resources (e.g., they have created one w/o first seeing
-    // if it already existed in the cache).
-    SkASSERT(!this->findAndRefUniqueResource(key));
-
-    // Uncached resources can never have a unique key, unless they're wrapped resources. Wrapped
-    // resources are a special case: the unique keys give us a weak ref so that we can reuse the
-    // same resource (rather than re-wrapping). When a wrapped resource is no longer referenced,
-    // it will always be released - it is never converted to a scratch resource.
-    if (SkBudgeted::kNo == proxy->isBudgeted() &&
-                    (!proxy->priv().isInstantiated() ||
-                     !proxy->priv().peekSurface()->resourcePriv().refsWrappedObjects())) {
-        return;
-    }
-
-    SkASSERT(!fUniquelyKeyedProxies.find(key));     // multiple proxies can't get the same key
-
-    proxy->cacheAccess().setUniqueKey(this, key);
-    SkASSERT(proxy->getUniqueKey() == key);
-    fUniquelyKeyedProxies.add(proxy);
-}
-
-sk_sp<GrTextureProxy> GrResourceCache::findProxyByUniqueKey(const GrUniqueKey& key,
-                                                            GrSurfaceOrigin origin) {
-
-    sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
-    if (result) {
-        SkASSERT(result->origin() == origin);
-    }
-    return result;
-}
-
-sk_sp<GrTextureProxy> GrResourceCache::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
-                                                                    GrSurfaceOrigin origin) {
-    sk_sp<GrTextureProxy> result = this->findProxyByUniqueKey(key, origin);
-    if (result) {
-        return result;
-    }
-
-    GrGpuResource* resource = findAndRefUniqueResource(key);
-    if (!resource) {
-        return nullptr;
-    }
-
-    sk_sp<GrTexture> texture(static_cast<GrSurface*>(resource)->asTexture());
-    SkASSERT(texture);
-
-    result = GrSurfaceProxy::MakeWrapped(std::move(texture), origin);
-    SkASSERT(result->getUniqueKey() == key);
-    // MakeWrapped should've added this for us
-    SkASSERT(fUniquelyKeyedProxies.find(key));
-    return result;
-}
-
-void GrResourceCache::processInvalidProxyUniqueKey(const GrUniqueKey& key) {
-    // Note: this method is called for the whole variety of GrGpuResources so often 'key'
-    // will not be in 'fUniquelyKeyedProxies'.
-    GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
-    if (proxy) {
-        this->processInvalidProxyUniqueKey(key, proxy, false);
-    }
-}
-
-void GrResourceCache::processInvalidProxyUniqueKey(const GrUniqueKey& key, GrTextureProxy* proxy,
-                                                   bool invalidateSurface) {
-    SkASSERT(proxy);
-    SkASSERT(proxy->getUniqueKey().isValid());
-    SkASSERT(proxy->getUniqueKey() == key);
-
-    fUniquelyKeyedProxies.remove(key);
-    proxy->cacheAccess().clearUniqueKey();
-
-    if (invalidateSurface && proxy->priv().isInstantiated()) {
-        GrSurface* surface = proxy->priv().peekSurface();
-        if (surface) {
-            surface->resourcePriv().removeUniqueKey();
-        }
-    }
-}
-
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 54be56d..6869e4e 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -13,7 +13,6 @@
 #include "GrGpuResourcePriv.h"
 #include "GrResourceCache.h"
 #include "GrResourceKey.h"
-#include "GrTextureProxy.h"
 #include "SkMessageBus.h"
 #include "SkRefCnt.h"
 #include "SkTArray.h"
@@ -22,6 +21,7 @@
 #include "SkTMultiMap.h"
 
 class GrCaps;
+class GrProxyProvider;
 class SkString;
 class SkTraceMemoryDump;
 
@@ -49,7 +49,7 @@
  */
 class GrResourceCache {
 public:
-    GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID);
+    GrResourceCache(const GrCaps*, uint32_t contextUniqueID);
     ~GrResourceCache();
 
     // Default maximum number of budgeted resources in the cache.
@@ -157,78 +157,6 @@
         return resource;
     }
 
-    ///////////////////////////////////////////////////////////////////////////
-    // TextureProxies & GrUniqueKeys
-    //
-    // The four GrResourceCache methods assignUniqueKeyToProxy, adoptUniqueKeyFromSurface,
-    // findPorxyByUniqueKey, and findOrCreateProxyByUniqueKey drive the behavior of uniqueKeys on
-    // proxies.
-    //
-    // assignUniqueKeyToProxy does the following:
-    //    if the proxy is wrapped, it sets the texture & proxy keys & adds the proxy to the hash
-    //    if the proxy is deferred, it just set the unique key on the proxy & adds it to the hash
-    //
-    //    Note that when a deferred proxy with a unique key is instantiated, its unique key will be
-    //    pushed to the backing resource.
-    //
-    //    Futher note, a proxy can only receive a unique key once. It can be removed if Ganesh
-    //    determines that the key will never be used again but, in that case, the proxy should
-    //    never receive another key.
-    //
-    // adoptUniqueKeyFromSurface does the following:
-    //    takes in a GrSurface which must have a valid unique key. It sets the proxy's key to match
-    //    the surface and adds the proxy to the hash.
-    //
-    // findProxyByUniqueKey does the following:
-    //    looks in the UniqueKeyProxy hash table to see if there is already a proxy w/ the key and
-    //    returns the proxy. If it fails it will return null.
-    //
-    // findOrCreateProxyByUniqueKey does the following:
-    //    first calls findProxyByUniqueKey to see if a proxy already exists with the key
-    //    failing that it looks in the ResourceCache to see there is a texture with that key
-    //       if so, it will wrap the texture in a proxy, add the proxy to the hash and return it
-    //    failing that it will return null
-
-    /*
-     * Associate the provided proxy with the provided unique key.
-     */
-    void assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
-
-    /*
-     * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
-     * have a valid unique key.
-     */
-    void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);
-
-    /**
-     * Find a texture proxy that is associated with the provided unique key. It will not look for a
-     * GrSurface that has the unique key.
-     */
-    sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
-
-    /**
-     * Find a texture proxy that is associated with the provided unique key. If not proxy is found,
-     * try to find a resources that is associated with the unique key and create a proxy that wraps
-     * it.
-     */
-    sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
-
-    /**
-     * Either the proxy attached to the unique key is being deleted (in which case we
-     * don't want it cluttering up the hash table) or the client has indicated that
-     * it will never refer to the unique key again. In either case, remove the key
-     * from the hash table.
-     * Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
-     */
-    void processInvalidProxyUniqueKey(const GrUniqueKey&);
-
-    /**
-     * Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
-     * GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
-     * also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
-     */
-    void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);
-
     /**
      * Query whether a unique key exists in the cache.
      */
@@ -324,7 +252,7 @@
     // Enumerates all cached resources and dumps their details to traceMemoryDump.
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
 
-    int numUniqueKeyProxies_TestOnly() const;
+    void setProxyProvider(GrProxyProvider* proxyProvider) { fProxyProvider = proxyProvider; }
 
 private:
     ///////////////////////////////////////////////////////////////////////////
@@ -380,13 +308,6 @@
     };
     typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash;
 
-    struct UniquelyKeyedProxyHashTraits {
-        static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
-
-        static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
-    };
-    typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
-
     static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) {
         return a->cacheAccess().timestamp() < b->cacheAccess().timestamp();
     }
@@ -400,6 +321,7 @@
     typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
     typedef SkTDArray<GrGpuResource*> ResourceArray;
 
+    GrProxyProvider*                    fProxyProvider;
     // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is
     // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the
     // purgeable resources by this value, and thus is used to purge resources in LRU order.
@@ -411,9 +333,6 @@
     ScratchMap                          fScratchMap;
     // This holds all resources that have unique keys.
     UniqueHash                          fUniqueHash;
-    // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
-    // on these proxies but they must send a message to the resourceCache when they are deleted.
-    UniquelyKeyedProxyHash              fUniquelyKeyedProxies;
 
     // our budget, used in purgeAsNeeded()
     int                                 fMaxCount;
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 7fef350..0112b5c 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -20,7 +20,6 @@
 #include "GrResourceKey.h"
 #include "GrSemaphore.h"
 #include "GrStencilAttachment.h"
-#include "GrSurfaceProxyPriv.h"
 #include "GrTexturePriv.h"
 #include "../private/GrSingleOwner.h"
 #include "SkGr.h"
@@ -46,10 +45,6 @@
     fQuadIndexBufferKey = gQuadIndexBufferKey;
 }
 
-bool GrResourceProvider::IsFunctionallyExact(GrSurfaceProxy* proxy) {
-    return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height()));
-}
-
 bool validate_desc(const GrSurfaceDesc& desc, const GrCaps& caps, int levelCount = 0) {
     if (desc.fWidth <= 0 || desc.fHeight <= 0) {
         return false;
@@ -115,9 +110,9 @@
     return true;
 }
 
-sk_sp<GrTextureProxy> GrResourceProvider::createTextureProxy(const GrSurfaceDesc& desc,
-                                                             SkBudgeted budgeted,
-                                                             const GrMipLevel& mipLevel) {
+sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
+                                                   SkBudgeted budgeted,
+                                                   const GrMipLevel& mipLevel) {
     ASSERT_SINGLE_OWNER
 
     if (this->isAbandoned()) {
@@ -138,20 +133,20 @@
 
     if (make_info(desc.fWidth, desc.fHeight, desc.fConfig, &srcInfo)) {
         sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, 0);
-        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex), desc.fOrigin);
+        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(tex, desc.fOrigin);
         if (proxy) {
             sk_sp<GrSurfaceContext> sContext =
                        context->contextPriv().makeWrappedSurfaceContext(std::move(proxy), nullptr);
             if (sContext) {
                 if (sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, 0, 0)) {
-                    return sContext->asTextureProxyRef();
+                    SkASSERT(sContext->asTextureProxy()->priv().peekTexture() == tex.get());
+                    return tex;
                 }
             }
         }
     }
 
-    sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, &mipLevel, 1));
-    return GrSurfaceProxy::MakeWrapped(std::move(tex), desc.fOrigin);
+    return fGpu->createTexture(desc, budgeted, &mipLevel, 1);
 }
 
 sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
@@ -276,42 +271,12 @@
     resource->resourcePriv().setUniqueKey(key);
 }
 
-void GrResourceProvider::removeUniqueKeyFromProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
-    ASSERT_SINGLE_OWNER
-    if (this->isAbandoned() || !proxy) {
-        return;
-    }
-    fCache->processInvalidProxyUniqueKey(key, proxy, true);
-}
-
 sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
     ASSERT_SINGLE_OWNER
     return this->isAbandoned() ? nullptr
                                : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
 }
 
-void GrResourceProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) {
-    ASSERT_SINGLE_OWNER
-    SkASSERT(key.isValid());
-    if (this->isAbandoned() || !proxy) {
-        return;
-    }
-
-    fCache->assignUniqueKeyToProxy(key, proxy);
-}
-
-sk_sp<GrTextureProxy> GrResourceProvider::findProxyByUniqueKey(const GrUniqueKey& key,
-                                                               GrSurfaceOrigin origin) {
-    ASSERT_SINGLE_OWNER
-    return this->isAbandoned() ? nullptr : fCache->findProxyByUniqueKey(key, origin);
-}
-
-sk_sp<GrTextureProxy> GrResourceProvider::findOrCreateProxyByUniqueKey(const GrUniqueKey& key,
-                                                                       GrSurfaceOrigin origin) {
-    ASSERT_SINGLE_OWNER
-    return this->isAbandoned() ? nullptr : fCache->findOrCreateProxyByUniqueKey(key, origin);
-}
-
 sk_sp<const GrBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrBufferType intendedType,
                                                                  size_t size,
                                                                  const void* data,
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 64c9a8b..08da9ae 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -24,9 +24,7 @@
 class GrSemaphore;
 class GrSingleOwner;
 class GrStencilAttachment;
-class GrSurfaceProxy;
 class GrTexture;
-class GrTextureProxy;
 
 class GrStyle;
 class SkDescriptor;
@@ -53,29 +51,6 @@
         return sk_sp<T>(static_cast<T*>(this->findResourceByUniqueKey(key).release()));
     }
 
-    /*
-     * Assigns a unique key to a proxy. The proxy will be findable via this key using
-     * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
-     */
-    void assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
-
-    /*
-     * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
-     * also remove the unique key from the target GrSurface.
-     */
-    void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
-
-    /*
-     * Finds a proxy by unique key.
-     */
-    sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
-
-    /*
-     * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
-     * key.
-     */
-    sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
-
     ///////////////////////////////////////////////////////////////////////////
     // Textures
 
@@ -95,7 +70,8 @@
                                    const GrMipLevel texels[], int mipLevelCount,
                                    SkDestinationSurfaceColorMode mipColorMode);
 
-    sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel&);
+    // Create a potentially loose fit texture with the provided data
+    sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel&);
 
     ///////////////////////////////////////////////////////////////////////////
     // Wrapped Backend Surfaces
@@ -269,10 +245,6 @@
         fGpu = nullptr;
     }
 
-    // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
-    // determine if it is going to need a texture domain or a full clear.
-    static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
-
     const GrCaps* caps() const { return fCaps.get(); }
     bool overBudget() const { return fCache->overBudget(); }
 
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index ef7fa90..3fd5df4 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -13,7 +13,7 @@
 #include "GrGpuResourcePriv.h"
 #include "GrOpFlushState.h"
 #include "GrOpList.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSWMaskHelper.h"
 #include "SkMakeUnique.h"
 #include "SkSemaphore.h"
@@ -27,7 +27,7 @@
 GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     // Pass on any style that applies. The caller will apply the style if a suitable renderer is
     // not found and try again with the new GrShape.
-    if (!args.fShape->style().applies() && SkToBool(fResourceProvider) &&
+    if (!args.fShape->style().applies() && SkToBool(fProxyProvider) &&
         (args.fAAType == GrAAType::kCoverage || args.fAAType == GrAAType::kNone)) {
         // This is the fallback renderer for when a path is too complicated for the GPU ones.
         return CanDrawPath::kAsBackup;
@@ -176,8 +176,8 @@
     desc.fConfig = kAlpha_8_GrPixelConfig;
     // MDB TODO: We're going to fill this proxy with an ASAP upload (which is out of order wrt to
     // ops), so it can't have any pending IO.
-    return GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, fit, SkBudgeted::kYes,
-                                        GrResourceProvider::kNoPendingIO_Flag);
+    return GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(), desc, fit,
+                                        SkBudgeted::kYes, GrResourceProvider::kNoPendingIO_Flag);
 }
 
 namespace {
@@ -227,7 +227,7 @@
 bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
     GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                               "GrSoftwarePathRenderer::onDrawPath");
-    if (!fResourceProvider) {
+    if (!fProxyProvider) {
         return false;
     }
 
@@ -311,7 +311,7 @@
 
     sk_sp<GrTextureProxy> proxy;
     if (useCache) {
-        proxy = fResourceProvider->findOrCreateProxyByUniqueKey(maskKey, kTopLeft_GrSurfaceOrigin);
+        proxy = fProxyProvider->findOrCreateProxyByUniqueKey(maskKey, kTopLeft_GrSurfaceOrigin);
     }
     if (!proxy) {
         SkBackingFit fit = useCache ? SkBackingFit::kExact : SkBackingFit::kApprox;
@@ -358,7 +358,7 @@
         }
         if (useCache) {
             SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-            fResourceProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
+            fProxyProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
             args.fShape->addGenIDChangeListener(new PathInvalidator(maskKey));
         }
     }
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index d36b2f6..b399a18 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -10,7 +10,7 @@
 
 #include "GrPathRenderer.h"
 
-class GrResourceProvider;
+class GrProxyProvider;
 
 /**
  * This class uses the software side to render a path to an SkBitmap and
@@ -18,9 +18,11 @@
  */
 class GrSoftwarePathRenderer : public GrPathRenderer {
 public:
-    GrSoftwarePathRenderer(GrResourceProvider* resourceProvider, bool allowCaching)
-            : fResourceProvider(resourceProvider)
-            , fAllowCaching(allowCaching) {}
+    GrSoftwarePathRenderer(GrProxyProvider* proxyProvider, bool allowCaching)
+            : fProxyProvider(proxyProvider)
+            , fAllowCaching(allowCaching) {
+    }
+
 private:
     static void DrawNonAARect(GrRenderTargetContext* renderTargetContext,
                               GrPaint&& paint,
@@ -58,7 +60,7 @@
     bool onDrawPath(const DrawPathArgs&) override;
 
 private:
-    GrResourceProvider*    fResourceProvider;
+    GrProxyProvider*       fProxyProvider;
     bool                   fAllowCaching;
 
     typedef GrPathRenderer INHERITED;
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 8dd43de..1090d0d 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -13,7 +13,7 @@
 #include "GrContextPriv.h"
 #include "GrGpuResourcePriv.h"
 #include "GrOpList.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSurfaceContext.h"
 #include "GrTexturePriv.h"
 #include "GrTextureRenderTargetProxy.h"
@@ -202,7 +202,7 @@
     if (surf->getUniqueKey().isValid()) {
         // The proxy may already be in the hash. Thus we need to look for it first before creating
         // new one.
-        GrResourceProvider* provider = surf->getContext()->resourceProvider();
+        GrProxyProvider* provider = surf->getContext()->contextPriv().proxyProvider();
         sk_sp<GrSurfaceProxy> proxy = provider->findProxyByUniqueKey(surf->getUniqueKey(), origin);
         if (proxy) {
             return proxy;
@@ -231,7 +231,7 @@
     if (tex->getUniqueKey().isValid()) {
         // The proxy may already be in the hash. Thus we need to look for it first before creating
         // new one.
-        GrResourceProvider* provider = tex->getContext()->resourceProvider();
+        GrProxyProvider* provider = tex->getContext()->contextPriv().proxyProvider();
         sk_sp<GrTextureProxy> proxy = provider->findProxyByUniqueKey(tex->getUniqueKey(), origin);
         if (proxy) {
             return proxy;
@@ -245,14 +245,14 @@
     }
 }
 
-sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrProxyProvider* proxyProvider,
                                                    const GrSurfaceDesc& desc,
                                                    SkBackingFit fit,
                                                    SkBudgeted budgeted,
                                                    uint32_t flags) {
     SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
 
-    const GrCaps* caps = resourceProvider->caps();
+    const GrCaps* caps = proxyProvider->caps();
 
     // TODO: move this logic into GrResourceProvider!
     // TODO: share this testing code with check_texture_creation_params
@@ -311,7 +311,7 @@
 #endif
 }
 
-sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrProxyProvider* proxyProvider,
                                                    const GrSurfaceDesc& desc,
                                                    SkBudgeted budgeted,
                                                    const void* srcData,
@@ -319,13 +319,13 @@
     if (srcData) {
         GrMipLevel mipLevel = { srcData, rowBytes };
 
-        return resourceProvider->createTextureProxy(desc, budgeted, mipLevel);
+        return proxyProvider->createTextureProxy(desc, budgeted, mipLevel);
     }
 
-    return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
+    return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, SkBackingFit::kExact, budgeted);
 }
 
-sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(GrProxyProvider* proxyProvider,
                                                          const GrSurfaceDesc& desc,
                                                          SkBudgeted budgeted) {
     // SkMipMap doesn't include the base level in the level count so we have to add 1
@@ -339,11 +339,11 @@
         texels[i].fRowBytes = 0;
     }
 
-    return MakeDeferredMipMap(resourceProvider, desc, budgeted, texels.get(), mipCount);
+    return MakeDeferredMipMap(proxyProvider, desc, budgeted, texels.get(), mipCount);
 }
 
 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(
-                                                    GrResourceProvider* resourceProvider,
+                                                    GrProxyProvider* proxyProvider,
                                                     const GrSurfaceDesc& desc,
                                                     SkBudgeted budgeted,
                                                     const GrMipLevel texels[],
@@ -353,14 +353,14 @@
         if (texels) {
             return nullptr;
         }
-        return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, budgeted, nullptr, 0);
+        return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, budgeted, nullptr, 0);
     }
     if (!texels) {
         return nullptr;
     }
 
     if (1 == mipLevelCount) {
-        return resourceProvider->createTextureProxy(desc, budgeted, texels[0]);
+        return proxyProvider->createTextureProxy(desc, budgeted, texels[0]);
     }
 
 #ifdef SK_DEBUG
@@ -381,14 +381,7 @@
     SkASSERT((firstLevelHasData && allOtherLevelsHaveData) || allOtherLevelsLackData);
 #endif
 
-    sk_sp<GrTexture> tex(resourceProvider->createTexture(desc, budgeted,
-                                                         texels, mipLevelCount,
-                                                         mipColorMode));
-    if (!tex) {
-        return nullptr;
-    }
-
-    return GrSurfaceProxy::MakeWrapped(std::move(tex), desc.fOrigin);
+    return proxyProvider->createTextureProxy(desc, budgeted, texels, mipLevelCount, mipColorMode);
 }
 
 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index d8985fe..b307607 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -9,8 +9,9 @@
 
 #include "GrColorSpaceXform.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "SkGr.h"
 
 GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
@@ -39,12 +40,13 @@
 
 sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
                                                              bool willBeMipped) {
+    GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
+
     GrUniqueKey key;
     this->makeCopyKey(copyParams, &key, nullptr);
     if (key.isValid()) {
         sk_sp<GrTextureProxy> cachedCopy =
-                fContext->resourceProvider()->findOrCreateProxyByUniqueKey(
-                                                             key, this->originalProxy()->origin());
+                proxyProvider->findOrCreateProxyByUniqueKey(key, this->originalProxy()->origin());
         if (cachedCopy) {
             return cachedCopy;
         }
@@ -56,7 +58,7 @@
     if (copy) {
         if (key.isValid()) {
             SkASSERT(copy->origin() == this->originalProxy()->origin());
-            fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get());
+            proxyProvider->assignUniqueKeyToProxy(key, copy.get());
             this->didCacheCopy(key);
         }
     }
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index 6cb9832..1fc5f7a 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -9,8 +9,9 @@
 
 #include "GrColorSpaceXform.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 
 sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerState& params,
                                                                SkColorSpace* dstColorSpace,
@@ -42,14 +43,14 @@
         }
     }
 
-    GrSurfaceOrigin origOrigin = original ? original->origin()
-                                          : kTopLeft_GrSurfaceOrigin;
+    GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
+
+    GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
     GrUniqueKey copyKey;
     this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
     sk_sp<GrTextureProxy> cachedProxy;
     if (copyKey.isValid()) {
-        cachedProxy = fContext->resourceProvider()->findOrCreateProxyByUniqueKey(copyKey,
-                                                                                 origOrigin);
+        cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin);
         if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
             return cachedProxy;
         }
@@ -83,9 +84,9 @@
             // If we had a cachedProxy, that means there already is a proxy in the cache which
             // matches the key, but it does not have mip levels and we require them. Thus we must
             // remove the unique key from that proxy.
-            fContext->resourceProvider()->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
+            proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
         }
-        fContext->resourceProvider()->assignUniqueKeyToProxy(copyKey, result.get());
+        proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
         this->didCacheCopy(copyKey);
     }
     return result;
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 1be75f9..c99ee08 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -7,8 +7,8 @@
 
 #include "GrTextureProducer.h"
 #include "GrClip.h"
+#include "GrProxyProvider.h"
 #include "GrRenderTargetContext.h"
-#include "GrResourceProvider.h"
 #include "GrTextureProxy.h"
 #include "effects/GrBicubicEffect.h"
 #include "effects/GrSimpleTextureEffect.h"
@@ -39,7 +39,7 @@
     if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
         bool resizing = localRect.width()  != dstRect.width() ||
                         localRect.height() != dstRect.height();
-        needsDomain = resizing && !GrResourceProvider::IsFunctionallyExact(inputProxy.get());
+        needsDomain = resizing && !GrProxyProvider::IsFunctionallyExact(inputProxy.get());
     }
 
     if (needsDomain) {
@@ -84,7 +84,7 @@
 
     SkASSERT(proxyBounds.contains(constraintRect));
 
-    const bool proxyIsExact = GrResourceProvider::IsFunctionallyExact(proxy);
+    const bool proxyIsExact = GrProxyProvider::IsFunctionallyExact(proxy);
 
     // If the constraint rectangle contains the whole proxy then no need for a domain.
     if (constraintRect.contains(proxyBounds) && proxyIsExact) {
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index 9b3dc9c..c42df8b 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -9,8 +9,9 @@
 #include "GrTextureProxyPriv.h"
 
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrDeferredProxyUploader.h"
-#include "GrResourceCache.h"
+#include "GrProxyProvider.h"
 #include "GrTexturePriv.h"
 
 // Deferred version
@@ -19,7 +20,7 @@
         : INHERITED(srcDesc, fit, budgeted, flags)
         , fMipMapped(GrMipMapped::kNo)
         , fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
-        , fCache(nullptr)
+        , fProxyProvider(nullptr)
         , fDeferredUploader(nullptr) {
     SkASSERT(!srcData);  // currently handled in Make()
 }
@@ -29,7 +30,7 @@
         : INHERITED(std::move(callback), config)
         , fMipMapped(GrMipMapped::kNo)
         , fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
-        , fCache(nullptr)
+        , fProxyProvider(nullptr)
         , fDeferredUploader(nullptr) {
 }
 
@@ -38,11 +39,11 @@
         : INHERITED(std::move(surf), origin, SkBackingFit::kExact)
         , fMipMapped(fTarget->asTexture()->texturePriv().mipMapped())
         , fMipColorMode(fTarget->asTexture()->texturePriv().mipColorMode())
-        , fCache(nullptr)
+        , fProxyProvider(nullptr)
         , fDeferredUploader(nullptr) {
     if (fTarget->getUniqueKey().isValid()) {
-        fCache = fTarget->asTexture()->getContext()->getResourceCache();
-        fCache->adoptUniqueKeyFromSurface(this, fTarget);
+        fProxyProvider = fTarget->asTexture()->getContext()->contextPriv().proxyProvider();
+        fProxyProvider->adoptUniqueKeyFromSurface(this, fTarget);
     }
 }
 
@@ -51,9 +52,9 @@
     // at this point. Zero out the pointer so the cache invalidation code doesn't try to use it.
     fTarget = nullptr;
     if (fUniqueKey.isValid()) {
-        fCache->processInvalidProxyUniqueKey(fUniqueKey, this, false);
+        fProxyProvider->processInvalidProxyUniqueKey(fUniqueKey, this, false);
     } else {
-        SkASSERT(!fCache);
+        SkASSERT(!fProxyProvider);
     }
 }
 
@@ -124,7 +125,7 @@
                                   this->mipMapped(), !this->priv().isExact());
 }
 
-void GrTextureProxy::setUniqueKey(GrResourceCache* cache, const GrUniqueKey& key) {
+void GrTextureProxy::setUniqueKey(GrProxyProvider* proxyProvider, const GrUniqueKey& key) {
     SkASSERT(key.isValid());
     SkASSERT(!fUniqueKey.isValid()); // proxies can only ever get one uniqueKey
 
@@ -134,12 +135,12 @@
     }
 
     fUniqueKey = key;
-    fCache = cache;
+    fProxyProvider = proxyProvider;
 }
 
 void GrTextureProxy::clearUniqueKey() {
     fUniqueKey.reset();
-    fCache = nullptr;
+    fProxyProvider = nullptr;
 }
 
 #ifdef SK_DEBUG
diff --git a/src/gpu/GrTextureProxyCacheAccess.h b/src/gpu/GrTextureProxyCacheAccess.h
index 79cf845..7db7150 100644
--- a/src/gpu/GrTextureProxyCacheAccess.h
+++ b/src/gpu/GrTextureProxyCacheAccess.h
@@ -15,8 +15,8 @@
  */
 class GrTextureProxy::CacheAccess {
 private:
-    void setUniqueKey(GrResourceCache* cache, const GrUniqueKey& key) {
-        fTextureProxy->setUniqueKey(cache, key);
+    void setUniqueKey(GrProxyProvider* proxyProvider, const GrUniqueKey& key) {
+        fTextureProxy->setUniqueKey(proxyProvider, key);
     }
 
     void clearUniqueKey() {
@@ -34,7 +34,7 @@
     GrTextureProxy* fTextureProxy;
 
     friend class GrTextureProxy;  // to construct/copy this type.
-    friend class GrResourceCache; // to use this type
+    friend class GrProxyProvider; // to use this type
 };
 
 inline GrTextureProxy::CacheAccess GrTextureProxy::cacheAccess() { return CacheAccess(this); }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 47d67e1..a781e53 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -10,6 +10,7 @@
 #include "GrBlurUtils.h"
 #include "GrColorSpaceXform.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
 #include "GrImageTextureMaker.h"
 #include "GrRenderTargetContextPriv.h"
@@ -1190,7 +1191,8 @@
 sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkBitmap& bitmap) {
     // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's
     // semantics). Since this is cached we would have to bake the fit into the cache key though.
-    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(fContext->resourceProvider(), bitmap);
+    sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(fContext->contextPriv().proxyProvider(),
+                                                          bitmap);
     if (!proxy) {
         return nullptr;
     }
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 89deb98..da57a04 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -13,7 +13,7 @@
 #include "GrContextPriv.h"
 #include "GrGpuResourcePriv.h"
 #include "GrPaint.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrTextureProxy.h"
 #include "GrTypes.h"
 #include "GrXferProcessor.h"
@@ -65,7 +65,7 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////
-sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrProxyProvider* proxyProvider,
                                                    const SkBitmap& bitmap,
                                                    SkColorSpace* dstColorSpace) {
     if (!bitmap.readyToDraw()) {
@@ -75,10 +75,10 @@
     if (!bitmap.peekPixels(&pixmap)) {
         return nullptr;
     }
-    return GrUploadPixmapToTextureProxy(resourceProvider, pixmap, SkBudgeted::kYes, dstColorSpace);
+    return GrUploadPixmapToTextureProxy(proxyProvider, pixmap, SkBudgeted::kYes, dstColorSpace);
 }
 
-sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrProxyProvider* proxyProvider,
                                                    const SkPixmap& pixmap,
                                                    SkBudgeted budgeted,
                                                    SkColorSpace* dstColorSpace) {
@@ -91,8 +91,8 @@
     }
 
     ATRACE_ANDROID_FRAMEWORK("Upload Texture [%ux%u]", pixmap.width(), pixmap.height());
-    GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *resourceProvider->caps());
-    return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, budgeted, pixmap.addr(),
+    GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *proxyProvider->caps());
+    return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, budgeted, pixmap.addr(),
                                         pixmap.rowBytes());
 }
 
@@ -151,7 +151,7 @@
         texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
     }
 
-    return GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
+    return GrSurfaceProxy::MakeDeferredMipMap(ctx->contextPriv().proxyProvider(),
                                               desc,
                                               SkBudgeted::kYes,
                                               texels.get(),
@@ -175,7 +175,7 @@
     desc.fConfig = baseProxy->config();
     desc.fSampleCnt = 0;
 
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(ctx->contextPriv().proxyProvider(),
                                                                      desc,
                                                                      SkBudgeted::kYes);
     if (!proxy) {
@@ -199,7 +199,7 @@
         return nullptr;
     }
 
-    return GrSurfaceProxy::MakeDeferredMipMap(ctx->resourceProvider(),
+    return GrSurfaceProxy::MakeDeferredMipMap(ctx->contextPriv().proxyProvider(),
                                               GrImageInfoToSurfaceDesc(info, *ctx->caps()),
                                               SkBudgeted::kYes, texels,
                                               mipLevelCount, colorMode);
@@ -214,7 +214,7 @@
                                                                       nullptr, scaleAdjust);
 }
 
-sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrResourceProvider* resourceProvider,
+sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrProxyProvider* proxyProvider,
                                               const SkBitmap& bitmap) {
     GrUniqueKey originalKey;
 
@@ -227,17 +227,16 @@
     sk_sp<GrTextureProxy> proxy;
 
     if (originalKey.isValid()) {
-        proxy = resourceProvider->findOrCreateProxyByUniqueKey(originalKey,
-                                                               kTopLeft_GrSurfaceOrigin);
+        proxy = proxyProvider->findOrCreateProxyByUniqueKey(originalKey, kTopLeft_GrSurfaceOrigin);
     }
     if (!proxy) {
         // Pass nullptr for |dstColorSpace|.  This is lenient - we allow a wider range of
         // color spaces in legacy mode.  Unfortunately, we have to be lenient here, since
         // we can't necessarily know the |dstColorSpace| at this time.
-        proxy = GrUploadBitmapToTextureProxy(resourceProvider, bitmap, nullptr);
+        proxy = GrUploadBitmapToTextureProxy(proxyProvider, bitmap, nullptr);
         if (proxy && originalKey.isValid()) {
             SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-            resourceProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
+            proxyProvider->assignUniqueKeyToProxy(originalKey, proxy.get());
             GrInstallBitmapUniqueKeyInvalidator(originalKey, bitmap.pixelRef());
         }
     }
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 0b972b4..87b602e 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -205,7 +205,7 @@
  * The bitmap must have CPU-accessible pixels. Attempts to take advantage of faster paths for
  * yuv planes.
  */
-sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrResourceProvider*, const SkBitmap&,
+sk_sp<GrTextureProxy> GrUploadBitmapToTextureProxy(GrProxyProvider*, const SkBitmap&,
                                                    SkColorSpace* dstColorSpace);
 
 sk_sp<GrTextureProxy> GrGenerateMipMapsAndUploadToTextureProxy(GrContext*, const SkBitmap&,
@@ -214,7 +214,7 @@
 /**
  * Creates a new texture for the pixmap.
  */
-sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrResourceProvider*,
+sk_sp<GrTextureProxy> GrUploadPixmapToTextureProxy(GrProxyProvider*,
                                                    const SkPixmap&, SkBudgeted, SkColorSpace*);
 
 /**
@@ -242,7 +242,7 @@
 //    if (!texture) {
 //        return nullptr;
 //    }
-sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrResourceProvider*, const SkBitmap& bitmap);
+sk_sp<GrTextureProxy> GrMakeCachedBitmapProxy(GrProxyProvider*, const SkBitmap& bitmap);
 
 
 /**
diff --git a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.h b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.h
index ff9f047..4a8f215 100644
--- a/src/gpu/effects/GrBlurredEdgeFragmentProcessor.h
+++ b/src/gpu/effects/GrBlurredEdgeFragmentProcessor.h
@@ -16,7 +16,7 @@
 #include "GrCoordTransform.h"
 class GrBlurredEdgeFragmentProcessor : public GrFragmentProcessor {
 public:
-    enum class Mode { kSmoothStep = 1, kGaussian = 0 };
+    enum class Mode { kGaussian = 0, kSmoothStep = 1 };
     Mode mode() const { return fMode; }
     static std::unique_ptr<GrFragmentProcessor> Make(Mode mode) {
         return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(mode));
diff --git a/src/gpu/effects/GrConfigConversionEffect.fp b/src/gpu/effects/GrConfigConversionEffect.fp
index 62b998d..a64ac43 100644
--- a/src/gpu/effects/GrConfigConversionEffect.fp
+++ b/src/gpu/effects/GrConfigConversionEffect.fp
@@ -46,7 +46,7 @@
         desc.fHeight = kSize;
         desc.fConfig = kConfig;
 
-        sk_sp<GrTextureProxy> dataProxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+        sk_sp<GrTextureProxy> dataProxy = GrSurfaceProxy::MakeDeferred(context->proxyProvider(),
                                                                        desc,
                                                                        SkBudgeted::kYes, data, 0);
         if (!dataProxy) {
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index cc02473..66e8db6 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -15,6 +15,7 @@
 
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrRenderTargetContext.h"
 #include "GrFragmentProcessor.h"
 #include "GrCoordTransform.h"
@@ -58,7 +59,7 @@
         desc.fConfig = kConfig;
 
         sk_sp<GrTextureProxy> dataProxy = GrSurfaceProxy::MakeDeferred(
-                context->resourceProvider(), desc, SkBudgeted::kYes, data, 0);
+                context->contextPriv().proxyProvider(), desc, SkBudgeted::kYes, data, 0);
         if (!dataProxy) {
             return false;
         }
diff --git a/src/gpu/effects/GrConstColorProcessor.h b/src/gpu/effects/GrConstColorProcessor.h
index 62a9a0c..830240b 100644
--- a/src/gpu/effects/GrConstColorProcessor.h
+++ b/src/gpu/effects/GrConstColorProcessor.h
@@ -16,7 +16,7 @@
 #include "GrCoordTransform.h"
 class GrConstColorProcessor : public GrFragmentProcessor {
 public:
-    enum class InputMode { kLast = 2, kModulateA = 2, kModulateRGBA = 1, kIgnore = 0 };
+    enum class InputMode { kLast = 2, kModulateA = 2, kIgnore = 0, kModulateRGBA = 1 };
 
     static const int kInputModeCnt = (int)InputMode::kLast + 1;
 
diff --git a/src/gpu/effects/GrRRectBlurEffect.fp b/src/gpu/effects/GrRRectBlurEffect.fp
index c920efd..c21c4f0 100644
--- a/src/gpu/effects/GrRRectBlurEffect.fp
+++ b/src/gpu/effects/GrRRectBlurEffect.fp
@@ -9,6 +9,7 @@
     #include "GrClip.h"
     #include "GrContext.h"
     #include "GrPaint.h"
+    #include "GrProxyProvider.h"
     #include "GrRenderTargetContext.h"
     #include "GrStyle.h"
     #include "SkBlurMaskFilter.h"
@@ -35,7 +36,7 @@
         }
         builder.finish();
 
-        sk_sp<GrTextureProxy> mask(context->resourceProvider()->findOrCreateProxyByUniqueKey(
+        sk_sp<GrTextureProxy> mask(context->proxyProvider()->findOrCreateProxyByUniqueKey(
                                                                  key, kBottomLeft_GrSurfaceOrigin));
         if (!mask) {
             // TODO: this could be approx but the texture coords will need to be updated
@@ -74,7 +75,7 @@
                 return nullptr;
             }
             SkASSERT(mask->origin() == kBottomLeft_GrSurfaceOrigin);
-            context->resourceProvider()->assignUniqueKeyToProxy(key, mask.get());
+            context->proxyProvider()->assignUniqueKeyToProxy(key, mask.get());
         }
 
         return mask;
diff --git a/src/gpu/effects/GrRRectBlurEffect.h b/src/gpu/effects/GrRRectBlurEffect.h
index def7244..b95f7b0 100644
--- a/src/gpu/effects/GrRRectBlurEffect.h
+++ b/src/gpu/effects/GrRRectBlurEffect.h
@@ -15,7 +15,9 @@
 
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrPaint.h"
+#include "GrProxyProvider.h"
 #include "GrRenderTargetContext.h"
 #include "GrStyle.h"
 #include "SkBlurMaskFilter.h"
@@ -43,7 +45,9 @@
         }
         builder.finish();
 
-        sk_sp<GrTextureProxy> mask(context->resourceProvider()->findOrCreateProxyByUniqueKey(
+        GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
+        sk_sp<GrTextureProxy> mask(proxyProvider->findOrCreateProxyByUniqueKey(
                 key, kBottomLeft_GrSurfaceOrigin));
         if (!mask) {
             // TODO: this could be approx but the texture coords will need to be updated
@@ -83,7 +87,7 @@
                 return nullptr;
             }
             SkASSERT(mask->origin() == kBottomLeft_GrSurfaceOrigin);
-            context->resourceProvider()->assignUniqueKeyToProxy(key, mask.get());
+            proxyProvider->assignUniqueKeyToProxy(key, mask.get());
         }
 
         return mask;
diff --git a/src/gpu/effects/GrRectBlurEffect.cpp b/src/gpu/effects/GrRectBlurEffect.cpp
index e018761..f886ae3 100644
--- a/src/gpu/effects/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/GrRectBlurEffect.cpp
@@ -161,7 +161,7 @@
     float sigma = data->fRandom->nextRangeF(3, 8);
     float width = data->fRandom->nextRangeF(200, 300);
     float height = data->fRandom->nextRangeF(200, 300);
-    return GrRectBlurEffect::Make(data->resourceProvider(), SkRect::MakeWH(width, height), sigma);
+    return GrRectBlurEffect::Make(data->proxyProvider(), SkRect::MakeWH(width, height), sigma);
 }
 #endif
 #endif
diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp
index d20f52b..29767e6 100644
--- a/src/gpu/effects/GrRectBlurEffect.fp
+++ b/src/gpu/effects/GrRectBlurEffect.fp
@@ -1,5 +1,5 @@
 @header {
-    #include "GrResourceProvider.h"
+    #include "GrProxyProvider.h"
     #include "../effects/SkBlurMask.h"
 }
 
@@ -32,7 +32,7 @@
 
 
 @class {
-    static sk_sp<GrTextureProxy> CreateBlurProfileTexture(GrResourceProvider* resourceProvider,
+    static sk_sp<GrTextureProxy> CreateBlurProfileTexture(GrProxyProvider* proxyProvider,
                                                           float sigma) {
         unsigned int profileSize = SkScalarCeilToInt(6 * sigma);
 
@@ -42,7 +42,7 @@
         builder[0] = profileSize;
         builder.finish();
 
-        sk_sp<GrTextureProxy> blurProfile(resourceProvider->findOrCreateProxyByUniqueKey(
+        sk_sp<GrTextureProxy> blurProfile(proxyProvider->findOrCreateProxyByUniqueKey(
                                                                     key, kTopLeft_GrSurfaceOrigin));
         if (!blurProfile) {
             GrSurfaceDesc texDesc;
@@ -53,14 +53,14 @@
 
             std::unique_ptr<uint8_t[]> profile(SkBlurMask::ComputeBlurProfile(sigma));
 
-            blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider,
+            blurProfile = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                        texDesc, SkBudgeted::kYes, profile.get(), 0);
             if (!blurProfile) {
                 return nullptr;
             }
 
             SkASSERT(blurProfile->origin() == kTopLeft_GrSurfaceOrigin);
-            resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get());
+            proxyProvider->assignUniqueKeyToProxy(key, blurProfile.get());
         }
 
         return blurProfile;
@@ -68,7 +68,7 @@
 }
 
 @make {
-     static std::unique_ptr<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
+     static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider* proxyProvider,
                                                       const SkRect& rect, float sigma) {
          int doubleProfileSize = SkScalarCeilToInt(12*sigma);
 
@@ -78,7 +78,7 @@
              return nullptr;
          }
 
-         sk_sp<GrTextureProxy> blurProfile(CreateBlurProfileTexture(resourceProvider, sigma));
+         sk_sp<GrTextureProxy> blurProfile(CreateBlurProfileTexture(proxyProvider, sigma));
          if (!blurProfile) {
             return nullptr;
          }
@@ -127,6 +127,5 @@
     float sigma = data->fRandom->nextRangeF(3,8);
     float width = data->fRandom->nextRangeF(200,300);
     float height = data->fRandom->nextRangeF(200,300);
-    return GrRectBlurEffect::Make(data->resourceProvider(),
-                                  SkRect::MakeWH(width, height), sigma);
+    return GrRectBlurEffect::Make(data->proxyProvider(), SkRect::MakeWH(width, height), sigma);
 }
diff --git a/src/gpu/effects/GrRectBlurEffect.h b/src/gpu/effects/GrRectBlurEffect.h
index 8c43eaf..4f9b971 100644
--- a/src/gpu/effects/GrRectBlurEffect.h
+++ b/src/gpu/effects/GrRectBlurEffect.h
@@ -13,13 +13,13 @@
 #include "SkTypes.h"
 #if SK_SUPPORT_GPU
 
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "../effects/SkBlurMask.h"
 #include "GrFragmentProcessor.h"
 #include "GrCoordTransform.h"
 class GrRectBlurEffect : public GrFragmentProcessor {
 public:
-    static sk_sp<GrTextureProxy> CreateBlurProfileTexture(GrResourceProvider* resourceProvider,
+    static sk_sp<GrTextureProxy> CreateBlurProfileTexture(GrProxyProvider* proxyProvider,
                                                           float sigma) {
         unsigned int profileSize = SkScalarCeilToInt(6 * sigma);
 
@@ -30,7 +30,7 @@
         builder.finish();
 
         sk_sp<GrTextureProxy> blurProfile(
-                resourceProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin));
+                proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin));
         if (!blurProfile) {
             GrSurfaceDesc texDesc;
             texDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
@@ -40,14 +40,14 @@
 
             std::unique_ptr<uint8_t[]> profile(SkBlurMask::ComputeBlurProfile(sigma));
 
-            blurProfile = GrSurfaceProxy::MakeDeferred(resourceProvider, texDesc, SkBudgeted::kYes,
+            blurProfile = GrSurfaceProxy::MakeDeferred(proxyProvider, texDesc, SkBudgeted::kYes,
                                                        profile.get(), 0);
             if (!blurProfile) {
                 return nullptr;
             }
 
             SkASSERT(blurProfile->origin() == kTopLeft_GrSurfaceOrigin);
-            resourceProvider->assignUniqueKeyToProxy(key, blurProfile.get());
+            proxyProvider->assignUniqueKeyToProxy(key, blurProfile.get());
         }
 
         return blurProfile;
@@ -55,7 +55,7 @@
     SkRect rect() const { return fRect; }
     float sigma() const { return fSigma; }
 
-    static std::unique_ptr<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
+    static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider* proxyProvider,
                                                      const SkRect& rect, float sigma) {
         int doubleProfileSize = SkScalarCeilToInt(12 * sigma);
 
@@ -65,7 +65,7 @@
             return nullptr;
         }
 
-        sk_sp<GrTextureProxy> blurProfile(CreateBlurProfileTexture(resourceProvider, sigma));
+        sk_sp<GrTextureProxy> blurProfile(CreateBlurProfileTexture(proxyProvider, sigma));
         if (!blurProfile) {
             return nullptr;
         }
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 02746cf..81e8da1 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -7,7 +7,7 @@
 
 #include "GrTextureDomain.h"
 
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrShaderCaps.h"
 #include "GrSimpleTextureEffect.h"
 #include "GrSurfaceProxyPriv.h"
@@ -20,7 +20,7 @@
 #include "glsl/GrGLSLUniformHandler.h"
 
 static bool can_ignore_rect(GrTextureProxy* proxy, const SkRect& domain) {
-    if (GrResourceProvider::IsFunctionallyExact(proxy)) {
+    if (GrProxyProvider::IsFunctionallyExact(proxy)) {
         const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
 
         return domain.contains(kFullRect);
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index a459b32..f39da2a 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -8,7 +8,7 @@
 #include "GrTextureStripAtlas.h"
 #include "GrContext.h"
 #include "GrContextPriv.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSurfaceContext.h"
 #include "SkGr.h"
 #include "SkPixelRef.h"
@@ -207,7 +207,9 @@
     builder[0] = static_cast<uint32_t>(fCacheKey);
     builder.finish();
 
-    sk_sp<GrTextureProxy> proxy = fDesc.fContext->resourceProvider()->findOrCreateProxyByUniqueKey(
+    GrProxyProvider* proxyProvider = fDesc.fContext->contextPriv().proxyProvider();
+
+    sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(
                                                                 key, kTopLeft_GrSurfaceOrigin);
     if (!proxy) {
         GrSurfaceDesc texDesc;
@@ -216,7 +218,7 @@
         texDesc.fHeight = fDesc.fHeight;
         texDesc.fConfig = fDesc.fConfig;
 
-        proxy = GrSurfaceProxy::MakeDeferred(fDesc.fContext->resourceProvider(),
+        proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                              texDesc, SkBackingFit::kExact,
                                              SkBudgeted::kYes,
                                              GrResourceProvider::kNoPendingIO_Flag);
@@ -225,7 +227,7 @@
         }
 
         SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-        fDesc.fContext->resourceProvider()->assignUniqueKeyToProxy(key, proxy.get());
+        proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
         // This is a new texture, so all of our cache info is now invalid
         this->initLRU();
         fKeyTable.rewind();
diff --git a/src/gpu/ops/GrClearOp.cpp b/src/gpu/ops/GrClearOp.cpp
index 702edcc..e54ca6e 100644
--- a/src/gpu/ops/GrClearOp.cpp
+++ b/src/gpu/ops/GrClearOp.cpp
@@ -9,7 +9,7 @@
 
 #include "GrGpuCommandBuffer.h"
 #include "GrOpFlushState.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 
 GrClearOp::GrClearOp(const GrFixedClip& clip, GrColor color, GrSurfaceProxy* proxy)
         : INHERITED(ClassID())
@@ -23,7 +23,7 @@
             fClip = GrFixedClip(SkIRect::MakeEmpty());
         }
 
-        if (GrResourceProvider::IsFunctionallyExact(proxy) && fClip.scissorRect() == rtRect) {
+        if (GrProxyProvider::IsFunctionallyExact(proxy) && fClip.scissorRect() == rtRect) {
             fClip.disableScissor();
         }
     }
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 79a22d8..5ed02cc 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -615,6 +615,7 @@
 
 #if GR_TEST_UTILS
 #include "GrContext.h"
+#include "GrContextPriv.h"
 
 GR_DRAW_OP_TEST_DEFINE(TextureOp) {
     GrSurfaceDesc desc;
@@ -623,8 +624,9 @@
     desc.fWidth = random->nextULessThan(90) + 10;
     desc.fOrigin = random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
     SkBackingFit fit = random->nextBool() ? SkBackingFit::kApprox : SkBackingFit::kExact;
-    auto proxy =
-            GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, fit, SkBudgeted::kNo);
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(
+                                              context->contextPriv().proxyProvider(),
+                                              desc, fit, SkBudgeted::kNo);
     SkRect rect = GrTest::TestRect(random);
     SkRect srcRect;
     srcRect.fLeft = random->nextRangeScalar(0.f, proxy->width() / 2.f);
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 87ee213..a47587f 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -608,8 +608,8 @@
         bmp.installPixels(pixmap);
         proxy = GrGenerateMipMapsAndUploadToTextureProxy(context, bmp, dstColorSpace);
     } else {
-        proxy = GrUploadPixmapToTextureProxy(context->resourceProvider(), pixmap, SkBudgeted::kYes,
-                                             dstColorSpace);
+        proxy = GrUploadPixmapToTextureProxy(context->contextPriv().proxyProvider(),
+                                             pixmap, SkBudgeted::kYes, dstColorSpace);
     }
 
     if (!proxy) {
@@ -997,7 +997,7 @@
         // verification.  This is ok because we've already verified the color space in
         // getDeferredTextureImageData().
         sk_sp<GrTextureProxy> proxy(GrUploadPixmapToTextureProxy(
-                context->resourceProvider(), pixmap, budgeted, nullptr));
+                context->contextPriv().proxyProvider(), pixmap, budgeted, nullptr));
         if (!proxy) {
             return nullptr;
         }
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 3c9c461..ae4dfd6 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -23,7 +23,7 @@
 #include "GrGpuResourcePriv.h"
 #include "GrImageTextureMaker.h"
 #include "GrResourceKey.h"
-#include "GrResourceProvider.h"
+#include "GrProxyProvider.h"
 #include "GrSamplerState.h"
 #include "GrYUVProvider.h"
 #include "SkGr.h"
@@ -695,7 +695,7 @@
     }
 };
 
-static void set_key_on_proxy(GrResourceProvider* resourceProvider,
+static void set_key_on_proxy(GrProxyProvider* proxyProvider,
                              GrTextureProxy* proxy, GrTextureProxy* originalProxy,
                              const GrUniqueKey& key) {
     if (key.isValid()) {
@@ -706,9 +706,9 @@
             // If we had an originalProxy, that means there already is a proxy in the cache which
             // matches the key, but it does not have mip levels and we require them. Thus we must
             // remove the unique key from that proxy.
-            resourceProvider->removeUniqueKeyFromProxy(key, originalProxy);
+            proxyProvider->removeUniqueKeyFromProxy(key, originalProxy);
         }
-        resourceProvider->assignUniqueKeyToProxy(key, proxy);
+        proxyProvider->assignUniqueKeyToProxy(key, proxy);
     }
 }
 
@@ -760,12 +760,12 @@
     GrUniqueKey key;
     this->makeCacheKeyFromOrigKey(origKey, format, &key);
 
+    GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider();
     sk_sp<GrTextureProxy> proxy;
 
     // 1. Check the cache for a pre-existing one
     if (key.isValid()) {
-        proxy = ctx->resourceProvider()->findOrCreateProxyByUniqueKey(key,
-                                                                      kTopLeft_GrSurfaceOrigin);
+        proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
         if (proxy) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kPreExisting_LockTexturePath,
                                      kLockTexturePathCount);
@@ -793,7 +793,7 @@
                                                 willBeMipped))) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(ctx->resourceProvider(), proxy.get(), nullptr, key);
+            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
             if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 return proxy;
             }
@@ -820,7 +820,7 @@
         if (proxy) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kYUV_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(ctx->resourceProvider(), proxy.get(), nullptr, key);
+            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
             return proxy;
         }
     }
@@ -832,12 +832,12 @@
             proxy = GrGenerateMipMapsAndUploadToTextureProxy(ctx, bitmap, dstColorSpace);
         }
         if (!proxy) {
-            proxy = GrUploadBitmapToTextureProxy(ctx->resourceProvider(), bitmap, dstColorSpace);
+            proxy = GrUploadBitmapToTextureProxy(proxyProvider, bitmap, dstColorSpace);
         }
         if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kRGBA_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(ctx->resourceProvider(), proxy.get(), nullptr, key);
+            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
             return proxy;
         }
     }
@@ -850,7 +850,7 @@
         SkASSERT(willBeMipped);
         SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
         if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(ctx, proxy.get())) {
-            set_key_on_proxy(ctx->resourceProvider(), mippedProxy.get(), proxy.get(), key);
+            set_key_on_proxy(proxyProvider, mippedProxy.get(), proxy.get(), key);
             return mippedProxy;
         }
         // We failed to make a mipped proxy with the base copied into it. This could have
diff --git a/src/shaders/SkPerlinNoiseShader.cpp b/src/shaders/SkPerlinNoiseShader.cpp
index 6c53401..6577a12 100644
--- a/src/shaders/SkPerlinNoiseShader.cpp
+++ b/src/shaders/SkPerlinNoiseShader.cpp
@@ -19,6 +19,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrCoordTransform.h"
 #include "SkGr.h"
 #include "effects/GrConstColorProcessor.h"
@@ -1435,10 +1436,11 @@
     }
 
     sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy(
-                                                         args.fContext->resourceProvider(),
-                                                         paintingData->getPermutationsBitmap());
-    sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(args.fContext->resourceProvider(),
-                                                               paintingData->getNoiseBitmap());
+                                                    args.fContext->contextPriv().proxyProvider(),
+                                                    paintingData->getPermutationsBitmap());
+    sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(
+                                                    args.fContext->contextPriv().proxyProvider(),
+                                                    paintingData->getNoiseBitmap());
 
     if (permutationsProxy && noiseProxy) {
         auto inner = GrPerlinNoise2Effect::Make(fType,
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 1a3e749..3367d9e 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -939,6 +939,7 @@
 
 #include "GrColorSpaceXform.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrShaderCaps.h"
 #include "GrTextureStripAtlas.h"
 #include "gl/GrGLContext.h"
@@ -1299,8 +1300,8 @@
             // that GrMakeCachedBitmapProxy is sufficient (i.e., it won't need to be
             // extracted to a subset or mipmapped).
             sk_sp<GrTextureProxy> proxy = GrMakeCachedBitmapProxy(
-                                                            args.fContext->resourceProvider(),
-                                                            bitmap);
+                                                     args.fContext->contextPriv().proxyProvider(),
+                                                     bitmap);
             if (!proxy) {
                 SkDebugf("Gradient won't draw. Could not create texture.");
                 return;
diff --git a/src/sksl/sksl_enums.include b/src/sksl/sksl_enums.include
index eb60b3b..2eced87 100644
--- a/src/sksl/sksl_enums.include
+++ b/src/sksl/sksl_enums.include
@@ -1,35 +1,35 @@
-R"(/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-/*************************************************************************************************/
-/* This file is used from both C++ and SkSL, so we need to stick to syntax compatible with both. */
-/*************************************************************************************************/
-
-/**
- * We have coverage effects that clip rendering to the edge of some geometric primitive.
- * This enum specifies how that clipping is performed. Not all factories that take a
- * GrProcessorEdgeType will succeed with all values and it is up to the caller to check for
- * a NULL return.
- */
-enum class GrClipEdgeType {
-    kFillBW,
-    kFillAA,
-    kInverseFillBW,
-    kInverseFillAA,
-    kHairlineAA,
-
-    kLast = kHairlineAA
-};
-
-enum class PMConversion {
-    kToPremul        = 0,
-    kToUnpremul      = 1,
-    kPMConversionCnt = 2
-};
-
-)"
+R"(/*

+ * Copyright 2017 Google Inc.

+ *

+ * Use of this source code is governed by a BSD-style license that can be

+ * found in the LICENSE file.

+ */

+

+

+/*************************************************************************************************/

+/* This file is used from both C++ and SkSL, so we need to stick to syntax compatible with both. */

+/*************************************************************************************************/

+

+/**

+ * We have coverage effects that clip rendering to the edge of some geometric primitive.

+ * This enum specifies how that clipping is performed. Not all factories that take a

+ * GrProcessorEdgeType will succeed with all values and it is up to the caller to check for

+ * a NULL return.

+ */

+enum class GrClipEdgeType {

+    kFillBW,

+    kFillAA,

+    kInverseFillBW,

+    kInverseFillAA,

+    kHairlineAA,

+

+    kLast = kHairlineAA

+};

+

+enum class PMConversion {

+    kToPremul        = 0,

+    kToUnpremul      = 1,

+    kPMConversionCnt = 2

+};

+

+)"

diff --git a/tests/CopySurfaceTest.cpp b/tests/CopySurfaceTest.cpp
index 8dfca0c..0d9fc86 100644
--- a/tests/CopySurfaceTest.cpp
+++ b/tests/CopySurfaceTest.cpp
@@ -20,6 +20,7 @@
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     static const int kW = 10;
     static const int kH = 10;
     static const size_t kRowBytes = sizeof(uint32_t) * kW;
@@ -74,13 +75,13 @@
                             dstDesc.fFlags = dFlags;
 
                             sk_sp<GrTextureProxy> src(GrSurfaceProxy::MakeDeferred(
-                                                                    context->resourceProvider(),
+                                                                    proxyProvider,
                                                                     srcDesc, SkBudgeted::kNo,
                                                                     srcPixels.get(),
                                                                     kRowBytes));
 
                             sk_sp<GrTextureProxy> dst(GrSurfaceProxy::MakeDeferred(
-                                                                    context->resourceProvider(),
+                                                                    proxyProvider,
                                                                     dstDesc, SkBudgeted::kNo,
                                                                     dstPixels.get(),
                                                                     kRowBytes));
diff --git a/tests/DetermineDomainModeTest.cpp b/tests/DetermineDomainModeTest.cpp
index 9c584d8..5848ca8 100644
--- a/tests/DetermineDomainModeTest.cpp
+++ b/tests/DetermineDomainModeTest.cpp
@@ -9,6 +9,7 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrContextPriv.h"
 #include "GrSurfaceProxy.h"
 #include "GrTextureProducer.h"
 #include "GrTextureProxy.h"
@@ -109,7 +110,7 @@
 
 };
 
-static sk_sp<GrTextureProxy> create_proxy(GrResourceProvider* resourceProvider,
+static sk_sp<GrTextureProxy> create_proxy(GrProxyProvider* proxyProvider,
                                           bool isPowerOfTwo,
                                           bool isExact,
                                           RectInfo* rect) {
@@ -132,10 +133,7 @@
               (isPowerOfTwo || isExact) ? RectInfo::kHard : RectInfo::kBad,
               name);
 
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(resourceProvider,
-                                                               desc, fit,
-                                                               SkBudgeted::kYes);
-    return proxy;
+    return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, fit, SkBudgeted::kYes);
 }
 
 static RectInfo::EdgeType compute_inset_edgetype(RectInfo::EdgeType previous,
@@ -308,7 +306,7 @@
                          insetAmount, halfFilterWidth, 0, name);
 }
 
-static void proxy_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider) {
+static void proxy_test(skiatest::Reporter* reporter, GrProxyProvider* proxyProvider) {
     GrTextureProducer_TestAccess::DomainMode actualMode, expectedMode;
     SkRect actualDomainRect;
 
@@ -327,7 +325,7 @@
         for (auto isExact : { true, false }) {
             RectInfo outermost;
 
-            sk_sp<GrTextureProxy> proxy = create_proxy(resourceProvider, isPowerOfTwoSized,
+            sk_sp<GrTextureProxy> proxy = create_proxy(proxyProvider, isPowerOfTwoSized,
                                                        isExact, &outermost);
             SkASSERT(outermost.isHardOrBadAllAround());
 
@@ -381,7 +379,7 @@
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DetermineDomainModeTest, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
 
-    proxy_test(reporter, context->resourceProvider());
+    proxy_test(reporter, context->contextPriv().proxyProvider());
 }
 
 #endif
diff --git a/tests/FloatingPointTextureTest.cpp b/tests/FloatingPointTextureTest.cpp
index d1718f8..95c27f2 100644
--- a/tests/FloatingPointTextureTest.cpp
+++ b/tests/FloatingPointTextureTest.cpp
@@ -33,6 +33,7 @@
         return;
     }
 
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     SkTDArray<T> controlPixelData, readBuffer;
     controlPixelData.setCount(arraySize);
     readBuffer.setCount(arraySize);
@@ -51,7 +52,7 @@
         desc.fWidth = DEV_W;
         desc.fHeight = DEV_H;
         desc.fConfig = config;
-        sk_sp<GrTextureProxy> fpProxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+        sk_sp<GrTextureProxy> fpProxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                      desc, SkBudgeted::kNo,
                                                                      controlPixelData.begin(), 0);
         // Floating point textures are NOT supported everywhere
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 5c97b6b..202e085 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -261,6 +261,7 @@
 #else
 bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages, int maxLevels) {
     GrDrawingManager* drawingManager = context->contextPriv().drawingManager();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
 
     sk_sp<GrTextureProxy> proxies[2];
 
@@ -271,15 +272,13 @@
     dummyDesc.fWidth = 34;
     dummyDesc.fHeight = 18;
     dummyDesc.fConfig = kRGBA_8888_GrPixelConfig;
-    proxies[0] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                              dummyDesc, SkBudgeted::kNo, nullptr, 0);
+    proxies[0] = GrSurfaceProxy::MakeDeferred(proxyProvider, dummyDesc, SkBudgeted::kNo, nullptr, 0);
     dummyDesc.fFlags = kNone_GrSurfaceFlags;
     dummyDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
     dummyDesc.fWidth = 16;
     dummyDesc.fHeight = 22;
     dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
-    proxies[1] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                              dummyDesc, SkBudgeted::kNo, nullptr, 0);
+    proxies[1] = GrSurfaceProxy::MakeDeferred(proxyProvider, dummyDesc, SkBudgeted::kNo, nullptr, 0);
 
     if (!proxies[0] || !proxies[1]) {
         SkDebugf("Could not allocate dummy textures");
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 0cd97f1..ecfd9f2 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -70,6 +70,7 @@
 // consistent with createTexture's result.
 DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrResourceProvider* resourceProvider = context->resourceProvider();
     const GrCaps* caps = context->caps();
 
@@ -125,7 +126,7 @@
                 texels[i].fPixels = pixelData.get();
                 texels[i].fRowBytes = rowBytes >> i;
             }
-            sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(resourceProvider,
+            sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferredMipMap(proxyProvider,
                                                                              desc, SkBudgeted::kNo,
                                                                              texels.get(),
                                                                              levelCount);
diff --git a/tests/ImageFilterCacheTest.cpp b/tests/ImageFilterCacheTest.cpp
index fb9d04b..a722df0 100644
--- a/tests/ImageFilterCacheTest.cpp
+++ b/tests/ImageFilterCacheTest.cpp
@@ -186,7 +186,7 @@
 #include "GrTexture.h"
 #include "GrTextureProxy.h"
 
-static sk_sp<GrTextureProxy> create_proxy(GrResourceProvider* resourceProvider) {
+static sk_sp<GrTextureProxy> create_proxy(GrProxyProvider* proxyProvider) {
     SkBitmap srcBM = create_bm();
 
     GrSurfaceDesc desc;
@@ -196,16 +196,15 @@
     desc.fHeight = kFullSize;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    return GrSurfaceProxy::MakeDeferred(resourceProvider,
+    return GrSurfaceProxy::MakeDeferred(proxyProvider,
                                         desc, SkBudgeted::kYes,
-                                        srcBM.getPixels(),
-                                        srcBM.rowBytes());
+                                        srcBM.getPixels(), srcBM.rowBytes());
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
 
-    sk_sp<GrTextureProxy> srcProxy(create_proxy(context->resourceProvider()));
+    sk_sp<GrTextureProxy> srcProxy(create_proxy(context->contextPriv().proxyProvider()));
     if (!srcProxy) {
         return;
     }
@@ -251,7 +250,7 @@
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_GPUBacked, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
 
-    sk_sp<GrTextureProxy> srcProxy(create_proxy(context->resourceProvider()));
+    sk_sp<GrTextureProxy> srcProxy(create_proxy(context->contextPriv().proxyProvider()));
     if (!srcProxy) {
         return;
     }
diff --git a/tests/IntTextureTest.cpp b/tests/IntTextureTest.cpp
index 4e46785..74fbc59 100644
--- a/tests/IntTextureTest.cpp
+++ b/tests/IntTextureTest.cpp
@@ -38,6 +38,8 @@
     if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
         return;
     }
+
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     static const int kS = UINT8_MAX + 1;
     static const size_t kRowBytes = kS * sizeof(int32_t);
 
@@ -66,18 +68,16 @@
         levels[1].fPixels = testData.get();
         levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
 
-        sk_sp<GrTextureProxy> temp(GrSurfaceProxy::MakeDeferredMipMap(context->resourceProvider(),
-                                                                      desc,
-                                                                      SkBudgeted::kYes,
+        sk_sp<GrTextureProxy> temp(GrSurfaceProxy::MakeDeferredMipMap(proxyProvider,
+                                                                      desc, SkBudgeted::kYes,
                                                                       levels, 2));
         REPORTER_ASSERT(reporter, !temp);
     }
 
     // Test that we can create an integer texture.
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                desc, SkBudgeted::kYes,
-                                                               testData.get(),
-                                                               kRowBytes);
+                                                               testData.get(), kRowBytes);
     REPORTER_ASSERT(reporter, proxy);
     if (!proxy) {
         return;
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index 8d290da..77ceb89 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -481,7 +481,7 @@
     desc.fWidth = 32;
     desc.fHeight = 16;
     desc.fConfig = kSkia8888_GrPixelConfig;
-    return GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+    return GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(),
                                         desc, SkBackingFit::kExact,
                                         SkBudgeted::kYes,
                                         GrResourceProvider::kNoPendingIO_Flag);
diff --git a/tests/PackedConfigsTextureTest.cpp b/tests/PackedConfigsTextureTest.cpp
index 5d54861..1f51d65 100644
--- a/tests/PackedConfigsTextureTest.cpp
+++ b/tests/PackedConfigsTextureTest.cpp
@@ -97,6 +97,7 @@
 
 static void run_test(skiatest::Reporter* reporter, GrContext* context,
                      int arraySize, GrPixelConfig config) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     SkTDArray<uint16_t> controlPixelData;
     // We will read back into an 8888 buffer since 565/4444 read backs aren't supported
     SkTDArray<GrColor> readBuffer;
@@ -119,7 +120,7 @@
         desc.fConfig = config;
         desc.fOrigin = origin;
 
-        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+        sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                    desc, SkBudgeted::kNo,
                                                                    controlPixelData.begin(), 0);
         SkASSERT(proxy);
diff --git a/tests/PathRendererCacheTests.cpp b/tests/PathRendererCacheTests.cpp
index 8c3ba2a..a3e272c 100644
--- a/tests/PathRendererCacheTests.cpp
+++ b/tests/PathRendererCacheTests.cpp
@@ -132,7 +132,7 @@
 // Test that deleting the original path invalidates the textures cached by the SW path renderer
 DEF_GPUTEST(SoftwarePathRendererCacheTest, reporter, /* options */) {
     auto createPR = [](GrContext* ctx) {
-        return new GrSoftwarePathRenderer(ctx->resourceProvider(), true);
+        return new GrSoftwarePathRenderer(ctx->contextPriv().proxyProvider(), true);
     };
 
     // Software path renderer creates a mask texture, but also renders with a non-AA rect, which
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 1d393d6..d6d3635 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -12,6 +12,7 @@
 #include <random>
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpuResource.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
@@ -155,6 +156,7 @@
 
 DEF_GPUTEST_FOR_ALL_CONTEXTS(ProcessorRefTest, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
 
     GrSurfaceDesc desc;
     desc.fOrigin = kTopLeft_GrSurfaceOrigin;
@@ -170,19 +172,19 @@
             {
                 bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport();
                 sk_sp<GrTextureProxy> proxy1(
-                        GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                        GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                      desc, SkBackingFit::kExact,
                                                      SkBudgeted::kYes));
                 sk_sp<GrTextureProxy> proxy2
-                        (GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                        (GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                       desc, SkBackingFit::kExact,
                                                       SkBudgeted::kYes));
                 sk_sp<GrTextureProxy> proxy3(
-                        GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                        GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                      desc, SkBackingFit::kExact,
                                                      SkBudgeted::kYes));
                 sk_sp<GrTextureProxy> proxy4(
-                        GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+                        GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                      desc, SkBackingFit::kExact,
                                                      SkBudgeted::kYes));
                 sk_sp<GrBuffer> buffer(texelBufferSupport
@@ -295,6 +297,8 @@
 
 /** Initializes the two test texture proxies that are available to the FP test factories. */
 bool init_test_textures(GrContext* context, SkRandom* random, sk_sp<GrTextureProxy> proxies[2]) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
     static const int kTestTextureSize = 256;
     GrSurfaceDesc desc;
     desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
@@ -310,7 +314,7 @@
                     input_texel_color(random->nextULessThan(256), random->nextULessThan(256));
         }
     }
-    proxies[0] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, SkBudgeted::kYes,
+    proxies[0] = GrSurfaceProxy::MakeDeferred(proxyProvider, desc, SkBudgeted::kYes,
                                               rgbaData.get(), kTestTextureSize * sizeof(GrColor));
 
     // Put random values into the alpha texture that the test FPs can optionally use.
@@ -321,7 +325,7 @@
             alphaData[kTestTextureSize * y + x] = random->nextULessThan(256);
         }
     }
-    proxies[1] = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, SkBudgeted::kYes,
+    proxies[1] = GrSurfaceProxy::MakeDeferred(proxyProvider, desc, SkBudgeted::kYes,
                                               alphaData.get(), kTestTextureSize);
 
     return proxies[0] && proxies[1];
@@ -330,6 +334,8 @@
 // Creates a texture of premul colors used as the output of the fragment processor that precedes
 // the fragment processor under test. Color values are those provided by input_texel_color().
 sk_sp<GrTextureProxy> make_input_texture(GrContext* context, int width, int height) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
     std::unique_ptr<GrColor[]> data(new GrColor[width * height]);
     for (int y = 0; y < width; ++y) {
         for (int x = 0; x < height; ++x) {
@@ -341,7 +347,7 @@
     desc.fWidth = width;
     desc.fHeight = height;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
-    return GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, SkBudgeted::kYes,
+    return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, SkBudgeted::kYes,
                                         data.get(), width * sizeof(GrColor));
 }
 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ProcessorOptimizationValidationTest, reporter, ctxInfo) {
diff --git a/tests/ProxyConversionTest.cpp b/tests/ProxyConversionTest.cpp
index 2a6222c..fda71d7 100644
--- a/tests/ProxyConversionTest.cpp
+++ b/tests/ProxyConversionTest.cpp
@@ -11,6 +11,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrBackendSurface.h"
+#include "GrContextPriv.h"
 #include "GrRenderTarget.h"
 #include "GrRenderTargetProxy.h"
 #include "GrResourceProvider.h"
@@ -118,7 +119,7 @@
 // Test converting between RenderTargetProxies and TextureProxies for deferred
 // Proxies
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DefferredProxyConversionTest, reporter, ctxInfo) {
-    GrResourceProvider* resourceProvider = ctxInfo.grContext()->resourceProvider();
+    GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
 
     GrSurfaceDesc desc;
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
@@ -128,7 +129,7 @@
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
     {
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(proxyProvider, desc,
                                                                  SkBackingFit::kApprox,
                                                                  SkBudgeted::kYes));
 
@@ -142,7 +143,7 @@
     }
 
     {
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(proxyProvider, desc,
                                                                  SkBackingFit::kApprox,
                                                                  SkBudgeted::kYes));
 
@@ -159,7 +160,7 @@
         desc.fFlags = kNone_GrSurfaceFlags; // force no-RT
         desc.fOrigin = kTopLeft_GrSurfaceOrigin;
 
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(resourceProvider, desc,
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(proxyProvider, desc,
                                                                  SkBackingFit::kApprox,
                                                                  SkBudgeted::kYes));
 
diff --git a/tests/ProxyRefTest.cpp b/tests/ProxyRefTest.cpp
index 16f4f42..5bf3a57 100644
--- a/tests/ProxyRefTest.cpp
+++ b/tests/ProxyRefTest.cpp
@@ -73,7 +73,7 @@
     desc.fHeight = kWidthHeight;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    return GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
+    return GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(), desc,
                                         SkBackingFit::kApprox, SkBudgeted::kYes,
                                         GrResourceProvider::kNoPendingIO_Flag);
 }
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
index edf54f6..01c881c 100644
--- a/tests/ProxyTest.cpp
+++ b/tests/ProxyTest.cpp
@@ -12,6 +12,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrBackendSurface.h"
+#include "GrContextPriv.h"
 #include "GrRenderTargetPriv.h"
 #include "GrRenderTargetProxy.h"
 #include "GrResourceProvider.h"
@@ -109,7 +110,8 @@
 
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) {
-    GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider();
+    GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
+    GrResourceProvider* resourceProvider = ctxInfo.grContext()->resourceProvider();
     const GrCaps& caps = *ctxInfo.grContext()->caps();
 
     const GrGpuResource::UniqueID kInvalidResourceID = GrGpuResource::UniqueID::InvalidID();
@@ -134,13 +136,13 @@
                             {
                                 sk_sp<GrTexture> tex;
                                 if (SkBackingFit::kApprox == fit) {
-                                    tex = provider->createApproxTexture(desc, 0);
+                                    tex = resourceProvider->createApproxTexture(desc, 0);
                                 } else {
-                                    tex = provider->createTexture(desc, budgeted);
+                                    tex = resourceProvider->createTexture(desc, budgeted);
                                 }
 
                                 sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(
-                                                                                provider, desc,
+                                                                                proxyProvider, desc,
                                                                                 fit, budgeted));
                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
                                 if (proxy) {
@@ -156,7 +158,7 @@
                                                   widthHeight, widthHeight, config,
                                                   kInvalidResourceID, budgeted);
                                     int supportedSamples = caps.getSampleCount(numSamples, config);
-                                    check_rendertarget(reporter, caps, provider,
+                                    check_rendertarget(reporter, caps, resourceProvider,
                                                        proxy->asRenderTargetProxy(),
                                                        supportedSamples,
                                                        fit, caps.maxWindowRectangles(), false);
@@ -168,29 +170,30 @@
                             {
                                 sk_sp<GrTexture> tex;
                                 if (SkBackingFit::kApprox == fit) {
-                                    tex = provider->createApproxTexture(desc, 0);
+                                    tex = resourceProvider->createApproxTexture(desc, 0);
                                 } else {
-                                    tex = provider->createTexture(desc, budgeted);
+                                    tex = resourceProvider->createTexture(desc, budgeted);
                                 }
 
-                                sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(provider,
-                                                                                         desc,
-                                                                                         fit,
-                                                                                         budgeted));
+                                sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(
+                                                                                    proxyProvider,
+                                                                                    desc,
+                                                                                    fit,
+                                                                                    budgeted));
                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
                                 if (proxy) {
-                                    // This forces the proxy to compute and cache its pre-instantiation
-                                    // size guess. Later, when it is actually instantiated, it checks
-                                    // that the instantiated size is <= to the pre-computation.
-                                    // If the proxy never computed its pre-instantiation size then the
-                                    // check is skipped.
+                                    // This forces the proxy to compute and cache its
+                                    // pre-instantiation size guess. Later, when it is actually
+                                    // instantiated, it checks that the instantiated size is <= to
+                                    // the pre-computation. If the proxy never computed its
+                                    // pre-instantiation size then the check is skipped.
                                     proxy->gpuMemorySize();
 
                                     check_surface(reporter, proxy.get(), origin,
                                                   widthHeight, widthHeight, config,
                                                   kInvalidResourceID, budgeted);
-                                    check_texture(reporter, provider, proxy->asTextureProxy(),
-                                                  fit, false);
+                                    check_texture(reporter, resourceProvider,
+                                                  proxy->asTextureProxy(), fit, false);
                                 }
                             }
 
@@ -281,7 +284,7 @@
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest, reporter, ctxInfo) {
-    GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider();
+    GrProxyProvider* provider = ctxInfo.grContext()->contextPriv().proxyProvider();
 
     for (auto flags : { kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags }) {
         for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index 9dda8e8..ec3e464 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -449,6 +449,7 @@
     }
 
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
 
     SkBitmap bmp = make_src_bitmap();
 
@@ -462,7 +463,7 @@
             desc.fConfig = kSkia8888_GrPixelConfig;
             desc.fOrigin = origin;
 
-            sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+            sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                        desc, SkBudgeted::kNo,
                                                                        bmp.getPixels(),
                                                                        bmp.rowBytes());
diff --git a/tests/ReadWriteAlphaTest.cpp b/tests/ReadWriteAlphaTest.cpp
index 2e5a1dc..ee3588f 100644
--- a/tests/ReadWriteAlphaTest.cpp
+++ b/tests/ReadWriteAlphaTest.cpp
@@ -41,6 +41,8 @@
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
     unsigned char alphaData[X_SIZE * Y_SIZE];
 
     static const int kClearValue = 0x2;
@@ -58,9 +60,8 @@
         // We are initializing the texture with zeros here
         memset(alphaData, 0, X_SIZE * Y_SIZE);
 
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                                                 desc,
-                                                                 SkBudgeted::kNo,
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(proxyProvider,
+                                                                 desc, SkBudgeted::kNo,
                                                                  alphaData, 0));
         if (!proxy) {
             ERRORF(reporter, "Could not create alpha texture.");
@@ -166,9 +167,9 @@
                     rgbaData[y * X_SIZE + x] = GrColorPackRGBA(6, 7, 8, alphaData[y * X_SIZE + x]);
                 }
             }
-            sk_sp<GrTextureProxy> proxy =
-                GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, SkBudgeted::kNo,
-                                             rgbaData, 0);
+            sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(proxyProvider,
+                                                                     desc, SkBudgeted::kNo,
+                                                                     rgbaData, 0));
             if (!proxy) {
                 // We always expect to be able to create a RGBA texture
                 if (!rt  && kRGBA_8888_GrPixelConfig == desc.fConfig) {
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
index 8a5cca0..f5453bd 100644
--- a/tests/RectangleTextureTest.cpp
+++ b/tests/RectangleTextureTest.cpp
@@ -146,7 +146,7 @@
 
         test_read_pixels(reporter, rectContext.get(), refPixels, "RectangleTexture-read");
 
-        test_copy_to_surface(reporter, context->resourceProvider(),
+        test_copy_to_surface(reporter, context->contextPriv().proxyProvider(),
                               rectContext.get(), "RectangleTexture-copy-to");
 
         test_write_pixels(reporter, rectContext.get(), true, "RectangleTexture-write");
diff --git a/tests/ResourceAllocatorTest.cpp b/tests/ResourceAllocatorTest.cpp
index c74a8bd..8d196f6 100644
--- a/tests/ResourceAllocatorTest.cpp
+++ b/tests/ResourceAllocatorTest.cpp
@@ -31,8 +31,7 @@
     // TODO: do we care about mipmapping
 };
 
-static sk_sp<GrSurfaceProxy> make_deferred(GrResourceProvider* resourceProvider,
-                                           const ProxyParams& p) {
+static sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const ProxyParams& p) {
     GrSurfaceDesc desc;
     desc.fFlags = p.fIsRT ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
     desc.fOrigin = p.fOrigin;
@@ -41,7 +40,7 @@
     desc.fConfig = p.fConfig;
     desc.fSampleCnt = p.fSampleCnt;
 
-    return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, p.fFit, SkBudgeted::kNo);
+    return GrSurfaceProxy::MakeDeferred(proxyProvider, desc, p.fFit, SkBudgeted::kNo);
 }
 
 static sk_sp<GrSurfaceProxy> make_backend(GrContext* context, const ProxyParams& p,
@@ -100,6 +99,7 @@
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) {
+    GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
     GrResourceProvider* resourceProvider = ctxInfo.grContext()->resourceProvider();
 
     struct TestCase {
@@ -136,8 +136,8 @@
     };
 
     for (auto test : gOverlappingTests) {
-        sk_sp<GrSurfaceProxy> p1 = make_deferred(resourceProvider, test.fP1);
-        sk_sp<GrSurfaceProxy> p2 = make_deferred(resourceProvider, test.fP2);
+        sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1);
+        sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2);
         overlap_test(reporter, resourceProvider,
                      std::move(p1), std::move(p2), test.fExpectation);
     }
@@ -175,8 +175,8 @@
     };
 
     for (auto test : gNonOverlappingTests) {
-        sk_sp<GrSurfaceProxy> p1 = make_deferred(resourceProvider, test.fP1);
-        sk_sp<GrSurfaceProxy> p2 = make_deferred(resourceProvider, test.fP2);
+        sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1);
+        sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2);
         if (!p1 || !p2) {
             continue; // creation can fail (i.e., for msaa4 on iOS)
         }
@@ -192,7 +192,7 @@
 
         GrBackendTexture backEndTex;
         sk_sp<GrSurfaceProxy> p1 = make_backend(ctxInfo.grContext(), t[0].fP1, &backEndTex);
-        sk_sp<GrSurfaceProxy> p2 = make_deferred(resourceProvider, t[0].fP2);
+        sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, t[0].fP2);
         non_overlap_test(reporter, resourceProvider,
                          std::move(p1), std::move(p2), t[0].fExpectation);
         cleanup_backend(ctxInfo.grContext(), &backEndTex);
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index d0666d5..7b2d835 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -1627,7 +1627,7 @@
     return provider->createTexture(desc, SkBudgeted::kYes);
 }
 
-static sk_sp<GrTextureProxy> make_mipmap_proxy(GrResourceProvider* provider,
+static sk_sp<GrTextureProxy> make_mipmap_proxy(GrProxyProvider* provider,
                                                GrSurfaceFlags flags,
                                                int width, int height,
                                                int sampleCnt) {
@@ -1671,7 +1671,8 @@
 // Texture-only, both-RT-and-Texture and MIPmapped
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
-    GrResourceProvider* provider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+    GrResourceProvider* resourceProvider = context->resourceProvider();
 
     static const int kSize = 64;
 
@@ -1679,13 +1680,13 @@
     {
         sk_sp<GrTexture> tex;
 
-        tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
+        tex = make_normal_texture(resourceProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
         size_t size = tex->gpuMemorySize();
         REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
 
         size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
         if (sampleCount >= 4) {
-            tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
+            tex = make_normal_texture(resourceProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
                                       sampleCount);
             size = tex->gpuMemorySize();
             REPORTER_ASSERT(reporter,
@@ -1694,7 +1695,7 @@
                             kSize*kSize*4*(sampleCount+1) == size);   // explicit resolve buffer
         }
 
-        tex = make_normal_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
+        tex = make_normal_texture(resourceProvider, kNone_GrSurfaceFlags, kSize, kSize, 0);
         size = tex->gpuMemorySize();
         REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
     }
@@ -1704,13 +1705,13 @@
     if (context->caps()->mipMapSupport()) {
         sk_sp<GrTextureProxy> proxy;
 
-        proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
+        proxy = make_mipmap_proxy(proxyProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
         size_t size = proxy->gpuMemorySize();
         REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
 
         size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
         if (sampleCount >= 4) {
-            proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
+            proxy = make_mipmap_proxy(proxyProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
                                       sampleCount);
             size = proxy->gpuMemorySize();
             REPORTER_ASSERT(reporter,
@@ -1719,7 +1720,7 @@
                kSize*kSize*4*(sampleCount+1)+(kSize*kSize*4)/3 == size);  // explicit resolve buffer
         }
 
-        proxy = make_mipmap_proxy(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
+        proxy = make_mipmap_proxy(proxyProvider, kNone_GrSurfaceFlags, kSize, kSize, 0);
         size = proxy->gpuMemorySize();
         REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
     }
diff --git a/tests/SRGBMipMapTest.cpp b/tests/SRGBMipMapTest.cpp
index 857ca58..b74663d 100644
--- a/tests/SRGBMipMapTest.cpp
+++ b/tests/SRGBMipMapTest.cpp
@@ -10,6 +10,7 @@
 #include "GrCaps.h"
 #include "GrClip.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrRenderTargetContext.h"
 #include "SkCanvas.h"
 #include "SkGr.h"
@@ -129,8 +130,8 @@
     desc.fHeight = texS;
     desc.fConfig = kSRGBA_8888_GrPixelConfig;
 
-    GrResourceProvider* resourceProvider = context->resourceProvider();
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(resourceProvider,
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                desc, SkBudgeted::kNo,
                                                                texData, 0);
 
diff --git a/tests/SpecialImageTest.cpp b/tests/SpecialImageTest.cpp
index 2ac80d6..6dfcfc4 100644
--- a/tests/SpecialImageTest.cpp
+++ b/tests/SpecialImageTest.cpp
@@ -17,6 +17,7 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrSurfaceProxy.h"
 #include "GrTextureProxy.h"
 #include "SkGr.h"
@@ -234,9 +235,10 @@
         // gpu
         const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bm.info(), *context->caps());
 
-        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                                                 desc, SkBudgeted::kNo,
-                                                                 bm.getPixels(), bm.rowBytes()));
+        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(
+                                                            context->contextPriv().proxyProvider(),
+                                                            desc, SkBudgeted::kNo,
+                                                            bm.getPixels(), bm.rowBytes()));
         if (!proxy) {
             return;
         }
@@ -267,7 +269,7 @@
 
     const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bm.info(), *context->caps());
 
-    sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(),
                                                              desc, SkBudgeted::kNo,
                                                              bm.getPixels(), bm.rowBytes()));
     if (!proxy) {
@@ -307,7 +309,7 @@
     desc.fHeight = kFullSize;
     desc.fConfig = kSkia8888_GrPixelConfig;
 
-    sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->contextPriv().proxyProvider(),
                                                              desc, SkBudgeted::kNo,
                                                              bm.getPixels(), 0));
     if (!proxy) {
diff --git a/tests/TestUtils.cpp b/tests/TestUtils.cpp
index f608413..588d479 100644
--- a/tests/TestUtils.cpp
+++ b/tests/TestUtils.cpp
@@ -89,7 +89,7 @@
     }
 }
 
-void test_copy_to_surface(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
+void test_copy_to_surface(skiatest::Reporter* reporter, GrProxyProvider* proxyProvider,
                           GrSurfaceContext* dstContext, const char* testName) {
 
     int pixelCnt = dstContext->width() * dstContext->height();
@@ -111,7 +111,7 @@
         copySrcDesc.fOrigin = (kNone_GrSurfaceFlags == flags) ? kTopLeft_GrSurfaceOrigin
                                                               : kBottomLeft_GrSurfaceOrigin;
 
-        sk_sp<GrTextureProxy> src(GrSurfaceProxy::MakeDeferred(resourceProvider,
+        sk_sp<GrTextureProxy> src(GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                copySrcDesc,
                                                                SkBudgeted::kYes, pixels.get(), 0));
         dstContext->copy(src.get());
diff --git a/tests/TestUtils.h b/tests/TestUtils.h
index 6f878bf..fc310be 100644
--- a/tests/TestUtils.h
+++ b/tests/TestUtils.h
@@ -29,6 +29,6 @@
                             bool onlyTestRTConfig, const char* testName);
 
 // Ensure that RGBA 8888 pixels can be copied into 'dstContext'
-void test_copy_to_surface(skiatest::Reporter*, GrResourceProvider*,
+void test_copy_to_surface(skiatest::Reporter*, GrProxyProvider*,
                           GrSurfaceContext* dstContext, const char* testName);
 #endif
diff --git a/tests/TextureProxyTest.cpp b/tests/TextureProxyTest.cpp
index 393e8c6..425fab2 100644
--- a/tests/TextureProxyTest.cpp
+++ b/tests/TextureProxyTest.cpp
@@ -14,6 +14,7 @@
 #include "GrBackendSurface.h"
 #include "GrContextPriv.h"
 #include "GrResourceCache.h"
+#include "GrProxyProvider.h"
 #include "GrResourceProvider.h"
 #include "GrTest.h"
 #include "GrTexture.h"
@@ -22,7 +23,7 @@
 #include "SkGr.h"
 #include "SkImage.h"
 
-int GrResourceCache::numUniqueKeyProxies_TestOnly() const {
+int GrProxyProvider::numUniqueKeyProxies_TestOnly() const {
     return fUniquelyKeyedProxies.count();
 }
 
@@ -42,37 +43,41 @@
 // Basic test
 
 static sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter,
-                                          GrResourceProvider* provider, SkBackingFit fit) {
+                                          GrContext* context, SkBackingFit fit) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
 
     // Only budgeted & wrapped external proxies get to carry uniqueKeys
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider, desc, fit,
                                                                SkBudgeted::kYes);
     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
     return proxy;
 }
 
 static sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter,
-                                            GrResourceProvider* provider, SkBackingFit fit) {
+                                            GrContext* context, SkBackingFit fit) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrSurfaceDesc desc = make_desc(kRenderTarget_GrSurfaceFlag);
 
     // Only budgeted & wrapped external proxies get to carry uniqueKeys
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider, desc, fit,
                                                                SkBudgeted::kYes);
     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
     return proxy;
 }
 
 static sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter,
-                                     GrResourceProvider* provider, SkBackingFit fit) {
+                                     GrContext* context, SkBackingFit fit) {
+    GrResourceProvider* resourceProvider = context->resourceProvider();
+
     GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
 
     sk_sp<GrTexture> tex;
     if (SkBackingFit::kApprox == fit) {
-        tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0));
+        tex = sk_sp<GrTexture>(resourceProvider->createApproxTexture(desc, 0));
     } else {
         // Only budgeted & wrapped external proxies get to carry uniqueKeys
-        tex = provider->createTexture(desc, SkBudgeted::kYes);
+        tex = resourceProvider->createTexture(desc, SkBudgeted::kYes);
     }
 
     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex),
@@ -82,7 +87,9 @@
 }
 
 static sk_sp<GrTextureProxy> wrapped_with_key(skiatest::Reporter* reporter,
-                                              GrResourceProvider* provider, SkBackingFit fit) {
+                                              GrContext* context, SkBackingFit fit) {
+    GrResourceProvider* resourceProvider = context->resourceProvider();
+
     static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
     static int kUniqueKeyData = 0;
 
@@ -96,10 +103,10 @@
 
     sk_sp<GrTexture> tex;
     if (SkBackingFit::kApprox == fit) {
-        tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0));
+        tex = sk_sp<GrTexture>(resourceProvider->createApproxTexture(desc, 0));
     } else {
         // Only budgeted & wrapped external proxies get to carry uniqueKeys
-        tex = provider->createTexture(desc, SkBudgeted::kYes);
+        tex = resourceProvider->createTexture(desc, SkBudgeted::kYes);
     }
 
     tex->resourcePriv().setUniqueKey(key);
@@ -134,7 +141,8 @@
                        sk_sp<GrTextureProxy> proxy, bool proxyIsCached) {
     static int id = 1;
 
-    GrResourceProvider* provider = context->resourceProvider();
+    GrResourceProvider* resourceProvider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrResourceCache* cache = context->getResourceCache();
 
     int startCacheCount = cache->getResourceCount();
@@ -147,23 +155,23 @@
         ++id;
 
         // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
-        REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
-        provider->assignUniqueKeyToProxy(key, proxy.get());
+        REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
+        proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
     }
 
-    REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
 
     // setUniqueKey had better stick
     REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
 
     // We just added it, surely we can find it
-    REPORTER_ASSERT(reporter, provider->findOrCreateProxyByUniqueKey(key,
-                                                                     kBottomLeft_GrSurfaceOrigin));
-    REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, proxyProvider->findOrCreateProxyByUniqueKey(
+                                                                key, kBottomLeft_GrSurfaceOrigin));
+    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
 
     // Once instantiated, the backing resource should have the same key
-    SkAssertResult(proxy->instantiate(provider));
+    SkAssertResult(proxy->instantiate(resourceProvider));
     const GrUniqueKey& texKey = proxy->priv().peekSurface()->getUniqueKey();
     REPORTER_ASSERT(reporter, texKey.isValid());
     REPORTER_ASSERT(reporter, key == texKey);
@@ -173,17 +181,17 @@
 
     // deleting the proxy should delete it from the hash but not the cache
     proxy = nullptr;
-    REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
 
     // If the proxy was cached refinding it should bring it back to life
-    proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
+    proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
     if (proxyIsCached) {
         REPORTER_ASSERT(reporter, proxy);
-        REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
+        REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
     } else {
         REPORTER_ASSERT(reporter, !proxy);
-        REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+        REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     }
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
 
@@ -197,7 +205,7 @@
     }
 
     // We can bring neither the texture nor proxy back from perma-death
-    proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
+    proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
     REPORTER_ASSERT(reporter, !proxy);
     if (proxyIsCached) {
         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
@@ -212,6 +220,7 @@
 // Test if invalidating unique ids operates as expected for texture proxies.
 static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) {
 
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrResourceCache* cache = context->getResourceCache();
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 
@@ -224,12 +233,12 @@
         bm.allocPixels(ii);
 
         rasterImg = SkImage::MakeFromBitmap(bm);
-        REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+        REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
     }
 
     sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr);
-    REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
 
     rasterImg = nullptr;        // this invalidates the uniqueKey
@@ -240,20 +249,21 @@
     context->getResourceCacheLimits(&maxNum, &maxBytes);
     context->setResourceCacheLimits(maxNum-1, maxBytes);
 
-    REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
 
     textureImg = nullptr;
     context->purgeAllUnlockedResources();
 
-    REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 }
 
 #ifndef SK_DISABLE_DEFERRED_PROXIES
 // Test if invalidating unique ids prior to instantiating operates as expected
 static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) {
-    GrResourceProvider* provider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+    GrResourceProvider* resourceProvider = context->resourceProvider();
     GrResourceCache* cache = context->getResourceCache();
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 
@@ -264,44 +274,44 @@
     builder.finish();
 
     // Create proxy, assign unique key
-    sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, provider, SkBackingFit::kExact);
-    provider->assignUniqueKeyToProxy(key, proxy.get());
+    sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, context, SkBackingFit::kExact);
+    proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
 
     // Send an invalidation message, which will be sitting in the cache's inbox
     SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(GrUniqueKeyInvalidatedMessage(key));
 
-    REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 
     // Instantiate the proxy. This will trigger the message to be processed, so the resulting
     // texture should *not* have the unique key on it!
-    SkAssertResult(proxy->instantiate(provider));
+    SkAssertResult(proxy->instantiate(resourceProvider));
 
     REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
     REPORTER_ASSERT(reporter, !proxy->priv().peekTexture()->getUniqueKey().isValid());
-    REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
 
     proxy = nullptr;
     context->purgeAllUnlockedResources();
 
-    REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 }
 #endif
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
-    GrResourceProvider* provider = context->resourceProvider();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     GrResourceCache* cache = context->getResourceCache();
 
-    REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
+    REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
     REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
 
     for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
         for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
             REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
-            basic_test(context, reporter, create(reporter, provider, fit), true);
+            basic_test(context, reporter, create(reporter, context, fit), true);
         }
 
         REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
diff --git a/tests/VkUploadPixelsTests.cpp b/tests/VkUploadPixelsTests.cpp
index 3fa9419..d05ca77 100644
--- a/tests/VkUploadPixelsTests.cpp
+++ b/tests/VkUploadPixelsTests.cpp
@@ -53,6 +53,8 @@
 
 void basic_texture_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
                         bool renderTarget) {
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
+
     const int kWidth = 16;
     const int kHeight = 16;
     SkAutoTMalloc<GrColor> srcBuffer(kWidth*kHeight);
@@ -71,7 +73,7 @@
     SkColorType ct;
     SkAssertResult(GrPixelConfigToColorType(config, &ct));
 
-    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+    sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(proxyProvider,
                                                                surfDesc, SkBudgeted::kNo,
                                                                srcBuffer, 0);
     REPORTER_ASSERT(reporter, proxy);
@@ -105,9 +107,7 @@
 
     surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
 
-    proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
-                                         surfDesc, SkBudgeted::kNo,
-                                         srcBuffer, 0);
+    proxy = GrSurfaceProxy::MakeDeferred(proxyProvider, surfDesc, SkBudgeted::kNo, srcBuffer, 0);
     REPORTER_ASSERT(reporter, proxy);
     if (proxy) {
         sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeWrappedSurfaceContext(
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index f909190..9a76dcf 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -15,6 +15,7 @@
 #if SK_SUPPORT_GPU
 #include "GrBackendSurface.h"
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpu.h"
 #include "GrTest.h"
 #endif
@@ -476,6 +477,7 @@
 // in between uses of the shared backing resource).
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WritePixelsPendingIO, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
+    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
 
     static const int kFullSize = 62;
     static const int kHalfSize = 31;
@@ -499,7 +501,7 @@
         desc.fHeight = 64;
         desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-        sk_sp<GrTextureProxy> temp = GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc,
+        sk_sp<GrTextureProxy> temp = GrSurfaceProxy::MakeDeferred(proxyProvider, desc,
                                                                   SkBackingFit::kApprox,
                                                                   SkBudgeted::kYes);
         temp->instantiate(context->resourceProvider());