Have GrTextureProducer return views instead of proxies.

Bug: skia:9556
Change-Id: Ieedb9c48914c637278203d4d462c19b2d85b27d4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268396
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gm/fpcoordinateoverride.cpp b/gm/fpcoordinateoverride.cpp
index 6202a61..879b487 100644
--- a/gm/fpcoordinateoverride.cpp
+++ b/gm/fpcoordinateoverride.cpp
@@ -83,9 +83,9 @@
     SkBitmap bmp;
     GetResourceAsBitmap("images/mandrill_512_q075.jpg", &bmp);
     GrBitmapTextureMaker maker(ctx, bmp);
-    auto [texture, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
+    auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
     std::unique_ptr<GrFragmentProcessor> imgFP =
-            GrTextureEffect::Make(texture, bmp.alphaType(), SkMatrix());
+            GrTextureEffect::Make(view.detachProxy(), bmp.alphaType(), SkMatrix());
     auto fp = std::unique_ptr<GrFragmentProcessor>(new SampleCoordEffect(std::move(imgFP)));
 
     GrPaint grPaint;
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index 7a1b007..4e052cd 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -176,22 +176,22 @@
             surface->getCanvas()->translate(-100, -100);
             surface->getCanvas()->drawPicture(pic);
             sk_sp<SkImage> image(surface->makeImageSnapshot());
-            fProxy = as_IB(image)->asTextureProxyRef(fCtx.get());
+            fView = as_IB(image)->asSurfaceProxyViewRef(fCtx.get());
         }
     }
 protected:
-    sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext* ctx, const SkImageInfo& info,
-                                            const SkIPoint& origin,
-                                            bool willBeMipped) override {
+    GrSurfaceProxyView onGenerateTexture(GrRecordingContext* ctx, const SkImageInfo& info,
+                                         const SkIPoint& origin,
+                                         bool willBeMipped) override {
         SkASSERT(ctx);
         SkASSERT(ctx == fCtx.get());
 
-        if (!fProxy) {
-            return nullptr;
+        if (!fView.proxy()) {
+            return {};
         }
 
-        if (origin.fX == 0 && origin.fY == 0 && info.dimensions() == fProxy->dimensions()) {
-            return fProxy;
+        if (origin.fX == 0 && origin.fY == 0 && info.dimensions() == fView.proxy()->dimensions()) {
+            return fView;
         }
 
         GrMipMapped mipMapped = willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo;
@@ -199,15 +199,15 @@
         // TODO: When we update this function to return a view instead of just a proxy then we can
         // remove the extra ref that happens when we call asTextureProxyRef.
         return GrSurfaceProxy::Copy(
-                fCtx.get(), fProxy.get(), kTopLeft_GrSurfaceOrigin,
+                fCtx.get(), fView.proxy(), fView.origin(),
                 SkColorTypeToGrColorType(info.colorType()), mipMapped,
                 SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
-                SkBackingFit::kExact, SkBudgeted::kYes).asTextureProxyRef();
+                SkBackingFit::kExact, SkBudgeted::kYes);
     }
 
 private:
-    sk_sp<GrContext>      fCtx;
-    sk_sp<GrTextureProxy> fProxy;
+    sk_sp<GrContext>   fCtx;
+    GrSurfaceProxyView fView;
 };
 
 static std::unique_ptr<SkImageGenerator> make_tex_generator(GrContext* ctx, sk_sp<SkPicture> pic) {
diff --git a/gm/texelsubset.cpp b/gm/texelsubset.cpp
index 215c5a7..46ae496 100644
--- a/gm/texelsubset.cpp
+++ b/gm/texelsubset.cpp
@@ -84,8 +84,8 @@
                                 context->priv().caps()->mipMapSupport()
                 ? GrMipMapped::kYes : GrMipMapped::kNo;
         GrBitmapTextureMaker maker(context, fBitmap);
-        auto [proxy, grCT] = maker.refTextureProxy(mipMapped);
-        if (!proxy) {
+        auto [view, grCT] = maker.refTextureProxyView(mipMapped);
+        if (!view.proxy()) {
             *errorMsg = "Failed to create proxy.";
             return DrawResult::kFail;
         }
@@ -114,12 +114,11 @@
         textureMatrices.back().preRotate(45.f, a.centerX(), a.centerY());
         textureMatrices.back().postSkew(.05f, -.05f);
 
-        sk_sp<GrTextureProxy> subsetProxy;
         SkBitmap subsetBmp;
         fBitmap.extractSubset(&subsetBmp, texelSubset);
         subsetBmp.setImmutable();
         GrBitmapTextureMaker subsetMaker(context, subsetBmp);
-        std::tie(subsetProxy, std::ignore) = subsetMaker.refTextureProxy(mipMapped);
+        auto[subsetView, subsetCT] = subsetMaker.refTextureProxyView(mipMapped);
 
         SkRect localRect = SkRect::Make(fBitmap.bounds()).makeOutset(kDrawPad, kDrawPad);
 
@@ -147,7 +146,7 @@
                     }
                     GrSamplerState sampler(wmx, wmy, fFilter);
                     const auto& caps = *context->priv().caps();
-                    auto fp1 = GrTextureEffect::MakeTexelSubset(proxy,
+                    auto fp1 = GrTextureEffect::MakeTexelSubset(view.proxyRef(),
                                                                 fBitmap.alphaType(),
                                                                 textureMatrices[tm],
                                                                 sampler,
@@ -175,8 +174,8 @@
                     // Now draw with a subsetted proxy using fixed function texture sampling rather
                     // than a texture subset as a comparison.
                     drawRect = localRect.makeOffset(x, y);
-                    auto fp2 = GrTextureEffect::Make(subsetProxy, fBitmap.alphaType(),
-                                                     subsetTextureMatrix,
+                    auto fp2 = GrTextureEffect::Make(subsetView.proxyRef(),
+                                                     fBitmap.alphaType(), subsetTextureMatrix,
                                                      GrSamplerState(wmx, wmy, fFilter), caps);
                     if (auto op = sk_gpu_test::test_ops::MakeRect(context, std::move(fp2), drawRect,
                                                                   localRect)) {
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index f2a471f1..43317af 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -99,11 +99,12 @@
 
         for (int i = 0; i < 3; ++i) {
             GrBitmapTextureMaker maker(context, fBitmaps[i]);
-            std::tie(proxies[i], std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
-            if (!proxies[i]) {
+            auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+            if (!view.proxy()) {
                 *errorMsg = "Failed to create proxy";
                 return DrawResult::kFail;
             }
+            proxies[i] = view.asTextureProxyRef();
         }
 
         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
@@ -215,11 +216,12 @@
 
         for (int i = 0; i < 2; ++i) {
             GrBitmapTextureMaker maker(context, fBitmaps[i]);
-            std::tie(proxies[i], std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
-            if (!proxies[i]) {
+            auto[view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+            if (!view.proxy()) {
                 *errorMsg = "Failed to create proxy";
                 return DrawResult::kFail;
             }
+            proxies[i] = view.asTextureProxyRef();
         }
 
         SkYUVAIndex yuvaIndices[4] = {
@@ -311,11 +313,12 @@
 
         for (int i = 0; i < 3; ++i) {
             GrBitmapTextureMaker maker(context, fBitmaps[i]);
-            std::tie(proxies[i], std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
-            if (!proxies[i]) {
+            auto[view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+            if (!view.proxy()) {
                 *errorMsg = "Failed to create proxy";
                 return DrawResult::kFail;
             }
+            proxies[i] = view.asTextureProxyRef();
         }
 
         // Draw a 2x2 grid of the YUV images.
diff --git a/include/core/SkImageGenerator.h b/include/core/SkImageGenerator.h
index 25e32b6..98ff37c 100644
--- a/include/core/SkImageGenerator.h
+++ b/include/core/SkImageGenerator.h
@@ -16,7 +16,7 @@
 #include "include/core/SkYUVASizeInfo.h"
 
 class GrRecordingContext;
-class GrTextureProxy;
+class GrSurfaceProxyView;
 class GrSamplerState;
 class SkBitmap;
 class SkData;
@@ -139,9 +139,8 @@
      *  the generator is allowed to return a non mipped proxy, but this will have some additional
      *  overhead in later allocating mips and copying of the base layer.
      */
-    sk_sp<GrTextureProxy> generateTexture(GrRecordingContext*, const SkImageInfo& info,
-                                          const SkIPoint& origin,
-                                          bool willNeedMipMaps);
+    GrSurfaceProxyView generateTexture(GrRecordingContext*, const SkImageInfo& info,
+                                       const SkIPoint& origin, bool willNeedMipMaps);
 
     bool texturesAreCacheable() const { return this->onTexturesAreCacheable(); }
 #endif
@@ -184,7 +183,7 @@
     };
 
     virtual TexGenType onCanGenerateTexture() const { return TexGenType::kNone; }
-    virtual sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+    virtual GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
                                                     const SkIPoint&,
                                                     bool willNeedMipMaps);  // returns nullptr
     virtual bool onTexturesAreCacheable() const { return true; }
diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp
index c51c1b0..42bc721 100644
--- a/src/core/SkImageGenerator.cpp
+++ b/src/core/SkImageGenerator.cpp
@@ -59,24 +59,24 @@
 }
 
 #if SK_SUPPORT_GPU
-#include "src/gpu/GrTextureProxy.h"
+#include "src/gpu/GrSurfaceProxyView.h"
 
-sk_sp<GrTextureProxy> SkImageGenerator::generateTexture(GrRecordingContext* ctx,
-                                                        const SkImageInfo& info,
-                                                        const SkIPoint& origin,
-                                                        bool willNeedMipMaps) {
+GrSurfaceProxyView SkImageGenerator::generateTexture(GrRecordingContext* ctx,
+                                                     const SkImageInfo& info,
+                                                     const SkIPoint& origin,
+                                                     bool willNeedMipMaps) {
     SkIRect srcRect = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height());
     if (!SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(srcRect)) {
-        return nullptr;
+        return {};
     }
     return this->onGenerateTexture(ctx, info, origin, willNeedMipMaps);
 }
 
-sk_sp<GrTextureProxy> SkImageGenerator::onGenerateTexture(GrRecordingContext*,
-                                                          const SkImageInfo&,
-                                                          const SkIPoint&,
-                                                          bool willNeedMipMaps) {
-    return nullptr;
+GrSurfaceProxyView SkImageGenerator::onGenerateTexture(GrRecordingContext*,
+                                                       const SkImageInfo&,
+                                                       const SkIPoint&,
+                                                       bool willNeedMipMaps) {
+    return {};
 }
 #endif
 
diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp
index b796e9a..c8ccfbc 100644
--- a/src/core/SkPictureImageGenerator.cpp
+++ b/src/core/SkPictureImageGenerator.cpp
@@ -25,8 +25,8 @@
 
 #if SK_SUPPORT_GPU
     TexGenType onCanGenerateTexture() const override { return TexGenType::kExpensive; }
-    sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
-                                            const SkIPoint&, bool willNeedMipMaps) override;
+    GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+                                         const SkIPoint&, bool willNeedMipMaps) override;
 #endif
 
 private:
@@ -94,7 +94,7 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 
-sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(
+GrSurfaceProxyView SkPictureImageGenerator::onGenerateTexture(
         GrRecordingContext* ctx, const SkImageInfo& info,
         const SkIPoint& origin, bool willNeedMipMaps) {
     SkASSERT(ctx);
@@ -107,7 +107,7 @@
                                                          kTopLeft_GrSurfaceOrigin, &props,
                                                          willNeedMipMaps));
     if (!surface) {
-        return nullptr;
+        return {};
     }
 
     SkMatrix matrix = fMatrix;
@@ -116,10 +116,10 @@
     surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
     sk_sp<SkImage> image(surface->makeImageSnapshot());
     if (!image) {
-        return nullptr;
+        return {};
     }
-    sk_sp<GrTextureProxy> proxy = as_IB(image)->asTextureProxyRef(ctx);
-    SkASSERT(!willNeedMipMaps || GrMipMapped::kYes == proxy->mipMapped());
-    return proxy;
+    GrSurfaceProxyView view = as_IB(image)->asSurfaceProxyViewRef(ctx);
+    SkASSERT(!willNeedMipMaps || GrMipMapped::kYes == view.asTextureProxy()->mipMapped());
+    return view;
 }
 #endif
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index 33e482a..78e1cfc 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -191,19 +191,20 @@
     return GrSurfaceProxyView(std::move(texProxy), fSurfaceOrigin, readSwizzle);
 }
 
-sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
+GrSurfaceProxyView GrAHardwareBufferImageGenerator::onGenerateTexture(
         GrRecordingContext* context, const SkImageInfo& info,
         const SkIPoint& origin, bool willNeedMipMaps) {
     GrSurfaceProxyView texProxyView = this->makeView(context);
     if (!texProxyView.proxy()) {
-        return nullptr;
+        return {};
     }
+    SkASSERT(texProxyView.asTextureProxy());
 
     if (0 == origin.fX && 0 == origin.fY &&
         info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
         // If the caller wants the full texture we're done. The caller will handle making a copy for
         // mip maps if that is required.
-        return texProxyView.asTextureProxyRef();
+        return texProxyView;
     }
     // Otherwise, make a copy for the requested subset.
     SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
@@ -213,7 +214,7 @@
     GrColorType grColorType = SkColorTypeToGrColorType(this->getInfo().colorType());
     return GrSurfaceProxy::Copy(context, texProxyView.proxy(), texProxyView.origin(), grColorType,
                                 mipMapped, subset, SkBackingFit::kExact,
-                                SkBudgeted::kYes).asTextureProxyRef();
+                                SkBudgeted::kYes);
 }
 
 bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.h b/src/gpu/GrAHardwareBufferImageGenerator.h
index 12ef6a8..c329447 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.h
+++ b/src/gpu/GrAHardwareBufferImageGenerator.h
@@ -43,8 +43,8 @@
     bool onIsValid(GrContext*) const override;
 
     TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; }
-    sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
-                                            const SkIPoint&, bool willNeedMipMaps) override;
+    GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+                                         const SkIPoint&, bool willNeedMipMaps) override;
 
 private:
     GrAHardwareBufferImageGenerator(const SkImageInfo&, AHardwareBuffer*, SkAlphaType,
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index 5bc3bdc..f2a10a5 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -93,16 +93,16 @@
     refHelper->unref();
 }
 
-sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
+GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(
         GrRecordingContext* context, const SkImageInfo& info,
         const SkIPoint& origin, bool willNeedMipMaps) {
     SkASSERT(context);
 
     if (context->backend() != fBackendTexture.backend()) {
-        return nullptr;
+        return {};
     }
     if (info.colorType() != this->getInfo().colorType()) {
-        return nullptr;
+        return {};
     }
 
     auto proxyProvider = context->priv().proxyProvider();
@@ -113,7 +113,7 @@
         if (fRefHelper->fBorrowingContextID != context->priv().contextID()) {
             fBorrowingMutex.release();
             SkDebugf("GrBackendTextureImageGenerator: Trying to use texture on two GrContexts!\n");
-            return nullptr;
+            return {};
         } else {
             SkASSERT(fRefHelper->fBorrowingContextReleaseProc);
             // Ref the release proc to be held by the proxy we make below
@@ -201,14 +201,14 @@
             mipMapsStatus, GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo,
             GrProtected::kNo, GrSurfaceProxy::UseAllocator::kYes);
     if (!proxy) {
-        return nullptr;
+        return {};
     }
 
     if (0 == origin.fX && 0 == origin.fY &&
         info.width() == fBackendTexture.width() && info.height() == fBackendTexture.height() &&
         (!willNeedMipMaps || GrMipMapped::kYes == proxy->mipMapped())) {
         // If the caller wants the entire texture and we have the correct mip support, we're done
-        return proxy;
+        return GrSurfaceProxyView(std::move(proxy), fSurfaceOrigin, readSwizzle);
     } else {
         // Otherwise, make a copy of the requested subset. Make sure our temporary is renderable,
         // because Vulkan will want to do the copy as a draw. All other copies would require a
@@ -216,10 +216,8 @@
         GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
 
-        // TODO: When we update this function to return a view instead of just a proxy then we can
-        // remove the extra ref that happens when we call asTextureProxyRef.
         return GrSurfaceProxy::Copy(
                 context, proxy.get(), fSurfaceOrigin, grColorType, mipMapped, subset,
-                SkBackingFit::kExact, SkBudgeted::kYes).asTextureProxyRef();
+                SkBackingFit::kExact, SkBudgeted::kYes);
     }
 }
diff --git a/src/gpu/GrBackendTextureImageGenerator.h b/src/gpu/GrBackendTextureImageGenerator.h
index d9980c5..eb547b1 100644
--- a/src/gpu/GrBackendTextureImageGenerator.h
+++ b/src/gpu/GrBackendTextureImageGenerator.h
@@ -40,8 +40,8 @@
     bool onIsValid(GrContext*) const override { return true; }
 
     TexGenType onCanGenerateTexture() const override { return TexGenType::kCheap; }
-    sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
-                                            const SkIPoint&, bool willNeedMipMaps) override;
+    GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+                                         const SkIPoint&, bool willNeedMipMaps) override;
     bool onTexturesAreCacheable() const override { return false; }
 
 private:
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index f518714..0fb2e05 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -39,21 +39,26 @@
     }
 }
 
-sk_sp<GrTextureProxy> GrBitmapTextureMaker::refOriginalTextureProxy(bool willBeMipped,
-                                                                    AllowedTexGenType onlyIfFast) {
+GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(bool willBeMipped,
+                                                                     AllowedTexGenType onlyIfFast) {
     if (AllowedTexGenType::kCheap == onlyIfFast) {
-        return nullptr;
+        return {};
     }
 
     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
     sk_sp<GrTextureProxy> proxy;
+    GrSwizzle swizzle;
 
     if (fOriginalKey.isValid()) {
         auto colorType = SkColorTypeToGrColorType(fBitmap.colorType());
         proxy = proxyProvider->findOrCreateProxyByUniqueKey(fOriginalKey, colorType,
                                                             kTopLeft_GrSurfaceOrigin);
-        if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
-            return proxy;
+        if (proxy) {
+            swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
+                                                                     this->colorType());
+            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
+                return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
+            }
         }
     }
 
@@ -63,7 +68,7 @@
             SkBitmap copy8888;
             if (!copy8888.tryAllocPixels(fBitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
                 !fBitmap.readPixels(copy8888.pixmap())) {
-                return nullptr;
+                return {};
             }
             copy8888.setImmutable();
             proxy = proxyProvider->createProxyFromBitmap(
@@ -73,51 +78,50 @@
                     fBitmap, willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo, fFit);
         }
         if (proxy) {
+            swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
+                                                                     this->colorType());
+            SkASSERT(!willBeMipped || GrMipMapped::kYes == proxy->mipMapped());
+            SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
             if (fOriginalKey.isValid()) {
                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
+                GrInstallBitmapUniqueKeyInvalidator(
+                        fOriginalKey, proxyProvider->contextID(), fBitmap.pixelRef());
             }
-            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
-                SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-                if (fOriginalKey.isValid()) {
-                    GrInstallBitmapUniqueKeyInvalidator(
-                            fOriginalKey, proxyProvider->contextID(), fBitmap.pixelRef());
-                }
-                return proxy;
-            }
+            return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
         }
     }
 
     if (proxy) {
         SkASSERT(willBeMipped);
         SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
-        // We need a mipped proxy, but we either found a proxy earlier that wasn't mipped or
-        // generated a non mipped proxy. Thus we generate a new mipped surface and copy the original
-        // proxy into the base layer. We will then let the gpu generate the rest of the mips.
+        SkASSERT(fOriginalKey.isValid());
+        // We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
+        // a new mipped surface and copy the original proxy into the base layer. We will then let
+        // the gpu generate the rest of the mips.
         GrColorType srcColorType = SkColorTypeToGrColorType(fBitmap.colorType());
-        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
-                                                              kTopLeft_GrSurfaceOrigin,
-                                                              srcColorType)) {
-            if (fOriginalKey.isValid()) {
-                // In this case we are stealing the key from the original proxy which should only
-                // happen when we have just generated mipmaps for an originally unmipped
-                // proxy/texture. This means that all future uses of the key will access the
-                // 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.
-                SkASSERT(proxy->getUniqueKey() == fOriginalKey);
-                proxyProvider->removeUniqueKeyFromProxy(proxy.get());
-                proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy.get());
-                GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextID(),
-                                                    fBitmap.pixelRef());
-            }
-            return mippedProxy;
+        auto mippedView = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
+                                                         kTopLeft_GrSurfaceOrigin, srcColorType);
+        if (auto mippedProxy = mippedView.asTextureProxy()) {
+            // In this case we are stealing the key from the original proxy which should only happen
+            // when we have just generated mipmaps for an originally unmipped proxy/texture. This
+            // means that all future uses of the key will access the 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.
+            SkASSERT(proxy->getUniqueKey() == fOriginalKey);
+            SkASSERT(mippedView.origin() == kTopLeft_GrSurfaceOrigin);
+            SkASSERT(mippedView.swizzle() == swizzle);
+            proxyProvider->removeUniqueKeyFromProxy(proxy.get());
+            proxyProvider->assignUniqueKeyToProxy(fOriginalKey, mippedProxy);
+            GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, proxyProvider->contextID(),
+                                                fBitmap.pixelRef());
+            return mippedView;
         }
         // We failed to make a mipped proxy with the base copied into it. This could have
         // been from failure to make the proxy or failure to do the copy. Thus we will fall
         // back to just using the non mipped proxy; See skbug.com/7094.
-        return proxy;
+        return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
     }
-    return nullptr;
+    return {};
 }
 
 void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) {
diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h
index 717a41c..1090a75 100644
--- a/src/gpu/GrBitmapTextureMaker.h
+++ b/src/gpu/GrBitmapTextureMaker.h
@@ -23,8 +23,8 @@
                          bool useDecal = false);
 
 private:
-    sk_sp<GrTextureProxy> refOriginalTextureProxy(bool willBeMipped,
-                                                  AllowedTexGenType onlyIfFast) override;
+    GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
+                                                   AllowedTexGenType onlyIfFast) override;
 
     void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 2bb1edf..62a27d4 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -154,23 +154,18 @@
 
         GrBitmapTextureMaker maker(context, bm, GrBitmapTextureMaker::Cached::kNo,
                                    SkBackingFit::kApprox);
-        auto [filteredMask, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!filteredMask) {
+        std::tie(filteredMaskView, std::ignore) = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!filteredMaskView.proxy()) {
             return false;
         }
 
-        // TODO: refTextureProxy should return a view instead of a proxy
-        SkASSERT(kTopLeft_GrSurfaceOrigin == filteredMask->origin());
+        SkASSERT(kTopLeft_GrSurfaceOrigin == filteredMaskView.origin());
 
         drawRect = dstM.fBounds;
 
         if (key.isValid()) {
-            proxyProvider->assignUniqueKeyToProxy(key, filteredMask.get());
+            proxyProvider->assignUniqueKeyToProxy(key, filteredMaskView.asTextureProxy());
         }
-        GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(filteredMask->backendFormat(),
-                                                                   grCT);
-        filteredMaskView = GrSurfaceProxyView(std::move(filteredMask), kTopLeft_GrSurfaceOrigin,
-                                              swizzle);
     }
 
     return draw_mask(renderTargetContext, clipData, viewMatrix, drawRect, std::move(paint),
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 6a644ac..af856b4 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -88,7 +88,9 @@
                                  GrSamplerState::Filter filter,
                                  GrTextureProducer::CopyParams* copyParams) {
     SkASSERT(texProxy);
-    bool willNeedMips = GrSamplerState::Filter::kMipMap == filter && caps->mipMapSupport();
+    int mipCount = SkMipMap::ComputeLevelCount(texProxy->width(), texProxy->height());
+    bool willNeedMips = GrSamplerState::Filter::kMipMap == filter && caps->mipMapSupport() &&
+            mipCount;
     // If the texture format itself doesn't support mipmapping (and those capabilities are required)
     // force a copy.
     if (willNeedMips && texProxy->mipMapped() == GrMipMapped::kNo) {
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index cc6f145..385e44a 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -33,10 +33,10 @@
     GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(), SkIRect::MakeSize(this->dimensions()));
 }
 
-sk_sp<GrTextureProxy> GrImageTextureMaker::refOriginalTextureProxy(bool willBeMipped,
-                                                                   AllowedTexGenType onlyIfFast) {
-    return fImage->lockTextureProxy(this->context(), fOriginalKey, fCachingHint,
-                                    willBeMipped, onlyIfFast);
+GrSurfaceProxyView GrImageTextureMaker::refOriginalTextureProxyView(bool willBeMipped,
+                                                                    AllowedTexGenType onlyIfFast) {
+    return fImage->lockTextureProxyView(this->context(), fOriginalKey, fCachingHint, willBeMipped,
+                                        onlyIfFast);
 }
 
 void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
@@ -58,16 +58,16 @@
     GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(), SkIRect::MakeSize(this->dimensions()));
 }
 
-sk_sp<GrTextureProxy> GrYUVAImageTextureMaker::refOriginalTextureProxy(bool willBeMipped,
-                                                                   AllowedTexGenType onlyIfFast) {
+GrSurfaceProxyView GrYUVAImageTextureMaker::refOriginalTextureProxyView(
+        bool willBeMipped, AllowedTexGenType onlyIfFast) {
     if (AllowedTexGenType::kCheap == onlyIfFast) {
-        return nullptr;
+        return {};
     }
 
     if (willBeMipped) {
-        return fImage->asMippedTextureProxyRef(this->context());
+        return fImage->asMippedTextureProxyViewRef(this->context());
     } else {
-        return fImage->asTextureProxyRef(this->context());
+        return fImage->asSurfaceProxyViewRef(this->context());
     }
 }
 
diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h
index c49e106..1bfea5a 100644
--- a/src/gpu/GrImageTextureMaker.h
+++ b/src/gpu/GrImageTextureMaker.h
@@ -25,8 +25,8 @@
     // TODO: consider overriding this, for the case where the underlying generator might be
     //       able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
     //          GrTexture* generateTextureForParams(const CopyParams&) override;
-    sk_sp<GrTextureProxy> refOriginalTextureProxy(bool willBeMipped,
-                                                  AllowedTexGenType onlyIfFast) override;
+    GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
+                                                   AllowedTexGenType onlyIfFast) override;
 
     void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
@@ -50,8 +50,8 @@
     // TODO: consider overriding this, for the case where the underlying generator might be
     //       able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
     //          GrTexture* generateTextureForParams(const CopyParams&) override;
-    sk_sp<GrTextureProxy> refOriginalTextureProxy(bool willBeMipped,
-                                                  AllowedTexGenType onlyIfFast) override;
+    GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
+                                                   AllowedTexGenType onlyIfFast) override;
 
     void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
@@ -70,5 +70,4 @@
     typedef GrTextureMaker INHERITED;
 };
 
-
 #endif
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 65db58d..98c69f7 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -105,6 +105,6 @@
     bitmap.setImmutable();
 
     GrBitmapTextureMaker maker(context, bitmap, GrBitmapTextureMaker::Cached::kNo, fit);
-    auto [texture, ct] = maker.refTextureProxy(GrMipMapped::kNo);
-    return texture;
+    auto [textureView, ct] = maker.refTextureProxyView(GrMipMapped::kNo);
+    return textureView.asTextureProxyRef();
 }
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index d15a5ea..2b1495d 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -14,11 +14,11 @@
 #include "src/gpu/SkGr.h"
 
 GrTextureAdjuster::GrTextureAdjuster(GrRecordingContext* context,
-                                     sk_sp<GrTextureProxy> original,
+                                     GrSurfaceProxyView original,
                                      const GrColorInfo& colorInfo,
                                      uint32_t uniqueID,
                                      bool useDecal)
-        : INHERITED(context, {colorInfo, original->dimensions()}, useDecal)
+        : INHERITED(context, {colorInfo, original.proxy()->dimensions()}, useDecal)
         , fOriginal(std::move(original))
         , fUniqueID(uniqueID) {}
 
@@ -33,37 +33,39 @@
     // We don't currently have a mechanism for notifications on Images!
 }
 
-sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
-                                                             bool willBeMipped,
-                                                             bool copyForMipsOnly) {
+GrSurfaceProxyView GrTextureAdjuster::refTextureProxyViewCopy(const CopyParams& copyParams,
+                                                              bool willBeMipped,
+                                                              bool copyForMipsOnly) {
     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
 
     GrUniqueKey key;
     this->makeCopyKey(copyParams, &key);
     sk_sp<GrTextureProxy> cachedCopy;
+    const GrSurfaceProxyView& originalView = this->originalProxyView();
     if (key.isValid()) {
         cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key, this->colorType(),
-                                                                 this->originalProxy()->origin());
+                                                                 originalView.origin());
         if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
-            return cachedCopy;
+            // TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
+            // colorTypes, we can use the swizzle of the originalView.
+            GrSwizzle swizzle = cachedCopy->textureSwizzle();
+            return GrSurfaceProxyView(std::move(cachedCopy), originalView.origin(), swizzle);
         }
     }
 
-    sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
-
-    sk_sp<GrTextureProxy> copy;
+    GrSurfaceProxyView copyView;
     if (copyForMipsOnly) {
-        copy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
-                                              this->originalProxy()->origin(), this->colorType());
+        copyView = GrCopyBaseMipMapToTextureProxy(this->context(), originalView.proxy(),
+                                                  originalView.origin(), this->colorType());
     } else {
-        copy = CopyOnGpu(this->context(), std::move(proxy), this->colorType(),
-                         copyParams, willBeMipped);
+        copyView = CopyOnGpu(this->context(), this->originalProxyViewRef(), this->colorType(),
+                             copyParams, willBeMipped);
     }
-    if (copy) {
+    if (copyView.proxy()) {
         if (key.isValid()) {
-            SkASSERT(copy->origin() == this->originalProxy()->origin());
+            SkASSERT(copyView.origin() == originalView.origin());
             if (cachedCopy) {
-                SkASSERT(GrMipMapped::kYes == copy->mipMapped() &&
+                SkASSERT(GrMipMapped::kYes == copyView.asTextureProxy()->mipMapped() &&
                          GrMipMapped::kNo == cachedCopy->mipMapped());
                 // 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
@@ -71,48 +73,51 @@
                 SkASSERT(cachedCopy->getUniqueKey() == key);
                 proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
             }
-            proxyProvider->assignUniqueKeyToProxy(key, copy.get());
+            proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
             this->didCacheCopy(key, proxyProvider->contextID());
         }
     }
-    return copy;
+    return copyView;
 }
 
-sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams(GrSamplerState params,
-                                                                    bool willBeMipped,
-                                                                    SkScalar scaleAdjust[2]) {
-    sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
-    CopyParams copyParams;
-
+GrSurfaceProxyView GrTextureAdjuster::onRefTextureProxyViewForParams(GrSamplerState params,
+                                                                     bool willBeMipped,
+                                                                     SkScalar scaleAdjust[2]) {
     if (this->context()->priv().abandoned()) {
         // The texture was abandoned.
-        return nullptr;
+        return {};
     }
 
     SkASSERT(this->width() <= this->context()->priv().caps()->maxTextureSize() &&
              this->height() <= this->context()->priv().caps()->maxTextureSize());
 
+    GrSurfaceProxyView view = this->originalProxyViewRef();
+    GrTextureProxy* texProxy = view.asTextureProxy();
+    SkASSERT(texProxy);
+    CopyParams copyParams;
+
     bool needsCopyForMipsOnly = false;
     if (!params.isRepeated() ||
-        !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), proxy.get(),
-                                               proxy->dimensions(), params.filter(), &copyParams,
+        !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
+                                               texProxy->dimensions(), params.filter(), &copyParams,
                                                scaleAdjust)) {
         needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
-                                                           proxy.get(), params.filter(),
+                                                           texProxy, params.filter(),
                                                            &copyParams);
         if (!needsCopyForMipsOnly) {
-            return proxy;
+            return view;
         }
     }
 
-    sk_sp<GrTextureProxy> result = this->refTextureProxyCopy(copyParams, willBeMipped,
-                                                             needsCopyForMipsOnly);
-    if (!result && needsCopyForMipsOnly) {
+    GrSurfaceProxyView result = this->refTextureProxyViewCopy(copyParams, willBeMipped,
+                                                              needsCopyForMipsOnly);
+    if (!result.proxy() && needsCopyForMipsOnly) {
         // If we were unable to make a copy and we only needed a copy for mips, then we will return
         // the source texture here and require that the GPU backend is able to fall back to using
         // bilerp if mips are required.
-        return this->originalProxyRef();
+        return view;
     }
+    SkASSERT(result.asTextureProxy());
     return result;
 }
 
@@ -125,21 +130,22 @@
     SkMatrix textureMatrix = origTextureMatrix;
 
     SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
-    sk_sp<GrTextureProxy> proxy(
-            this->refTextureProxyForParams(filterOrNullForBicubic, scaleAdjust));
-    if (!proxy) {
+    GrSurfaceProxyView view =
+            this->refTextureProxyViewForParams(filterOrNullForBicubic, scaleAdjust);
+    if (!view.proxy()) {
         return nullptr;
     }
+    SkASSERT(view.asTextureProxy());
     // If we made a copy then we only copied the contentArea, in which case the new texture is all
     // content.
-    if (proxy.get() != this->originalProxy()) {
+    if (view.proxy() != this->originalProxyView().proxy()) {
         textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
     }
 
     SkRect domain;
     DomainMode domainMode =
         DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
-                            proxy.get(), filterOrNullForBicubic, &domain);
+                            view.proxy(), filterOrNullForBicubic, &domain);
     if (kTightCopy_DomainMode == domainMode) {
         // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
         // non-int constraint rect)
@@ -151,11 +157,11 @@
         static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
         domainMode =
             DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
-                                proxy.get(), &kBilerp, &domain);
+                                view.proxy(), &kBilerp, &domain);
         SkASSERT(kTightCopy_DomainMode != domainMode);
     }
     SkASSERT(kNoDomain_DomainMode == domainMode ||
              (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
     return this->createFragmentProcessorForDomainAndFilter(
-            std::move(proxy), textureMatrix, domainMode, domain, filterOrNullForBicubic);
+            std::move(view), textureMatrix, domainMode, domain, filterOrNullForBicubic);
 }
diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h
index cc69325..665a5ef 100644
--- a/src/gpu/GrTextureAdjuster.h
+++ b/src/gpu/GrTextureAdjuster.h
@@ -29,25 +29,24 @@
             bool coordsLimitedToConstraintRect,
             const GrSamplerState::Filter* filterOrNullForBicubic) override;
 
-    GrTextureAdjuster(GrRecordingContext*, sk_sp<GrTextureProxy>, const GrColorInfo&,
+    GrTextureAdjuster(GrRecordingContext*, GrSurfaceProxyView, const GrColorInfo&,
                       uint32_t uniqueID, bool useDecal = false);
 
 protected:
     void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
 
-    GrTextureProxy* originalProxy() const { return fOriginal.get(); }
-    sk_sp<GrTextureProxy> originalProxyRef() const { return fOriginal; }
+    const GrSurfaceProxyView& originalProxyView() const { return fOriginal; }
+    GrSurfaceProxyView originalProxyViewRef() const { return fOriginal; }
 
 private:
-    sk_sp<GrTextureProxy> onRefTextureProxyForParams(GrSamplerState,
-                                                     bool willBeMipped,
-                                                     SkScalar scaleAdjust[2]) override;
+    GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
+                                                      SkScalar scaleAdjust[2]) override;
 
-    sk_sp<GrTextureProxy> refTextureProxyCopy(const CopyParams& copyParams, bool willBeMipped,
-                                              bool copyOnlyForMips);
+    GrSurfaceProxyView refTextureProxyViewCopy(const CopyParams& copyParams, bool willBeMipped,
+                                                bool copyOnlyForMips);
 
-    sk_sp<GrTextureProxy> fOriginal;
+    GrSurfaceProxyView fOriginal;
     uint32_t fUniqueID;
 
     typedef GrTextureProducer INHERITED;
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index 1feed59..2404046 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -13,26 +13,28 @@
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 
-sk_sp<GrTextureProxy> GrTextureMaker::onRefTextureProxyForParams(GrSamplerState params,
-                                                                 bool willBeMipped,
-                                                                 SkScalar scaleAdjust[2]) {
+GrSurfaceProxyView GrTextureMaker::onRefTextureProxyViewForParams(GrSamplerState params,
+                                                                  bool willBeMipped,
+                                                                  SkScalar scaleAdjust[2]) {
     if (this->width() > this->context()->priv().caps()->maxTextureSize() ||
         this->height() > this->context()->priv().caps()->maxTextureSize()) {
-        return nullptr;
+        return {};
     }
 
     CopyParams copyParams;
 
-    sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped,
-                                                                 AllowedTexGenType::kCheap));
+    GrSurfaceProxyView original = this->refOriginalTextureProxyView(willBeMipped,
+                                                                    AllowedTexGenType::kCheap);
     bool needsCopyForMipsOnly = false;
-    if (original) {
+    if (original.proxy()) {
+        GrTextureProxy* texProxy = original.asTextureProxy();
+        SkASSERT(texProxy);
         if (!params.isRepeated() ||
-            !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), original.get(),
-                                                   original->dimensions(), params.filter(),
+            !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
+                                                   texProxy->dimensions(), params.filter(),
                                                    &copyParams, scaleAdjust)) {
             needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
-                                                               original.get(), params.filter(),
+                                                               texProxy, params.filter(),
                                                                &copyParams);
             if (!needsCopyForMipsOnly) {
                 return original;
@@ -43,63 +45,71 @@
             !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), nullptr,
                                                    this->dimensions(), params.filter(), &copyParams,
                                                    scaleAdjust)) {
-            return this->refOriginalTextureProxy(willBeMipped, AllowedTexGenType::kAny);
+            return this->refOriginalTextureProxyView(willBeMipped, AllowedTexGenType::kAny);
         }
     }
 
     GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
 
-    GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
+    GrSurfaceOrigin origOrigin = original.proxy() ? original.origin() : kTopLeft_GrSurfaceOrigin;
     GrUniqueKey copyKey;
     this->makeCopyKey(copyParams, &copyKey);
-    sk_sp<GrTextureProxy> cachedProxy;
+    GrSurfaceProxyView cachedView;
     if (copyKey.isValid()) {
-        cachedProxy =
+        auto cachedProxy =
                 proxyProvider->findOrCreateProxyByUniqueKey(copyKey, this->colorType(), origOrigin);
-        if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
-            return cachedProxy;
+        if (cachedProxy) {
+            GrMipMapped mipped = cachedProxy->mipMapped();
+            // TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
+            // colorTypes, we can use the swizzle of the originalView.
+            GrSwizzle swizzle = cachedProxy->textureSwizzle();
+            cachedView = GrSurfaceProxyView(std::move(cachedProxy), origOrigin, swizzle);
+            if (!willBeMipped || GrMipMapped::kYes == mipped) {
+                return cachedView;
+            }
         }
     }
 
-    sk_sp<GrTextureProxy> source;
-    if (original) {
+    GrSurfaceProxyView source;
+    if (original.proxy()) {
         source = std::move(original);
-    } else if (cachedProxy) {
-        source = cachedProxy;
+    } else if (cachedView.proxy()) {
+        source = cachedView;
     } else {
         // Since we will be copying this texture there is no reason to make it mipped
-        source = this->refOriginalTextureProxy(false, AllowedTexGenType::kAny);
+        source = this->refOriginalTextureProxyView(false, AllowedTexGenType::kAny);
     }
 
-    if (!source) {
-        return nullptr;
+    if (!source.proxy()) {
+        return {};
     }
+    SkASSERT(source.asTextureProxy());
 
-    sk_sp<GrTextureProxy> result =
+    GrSurfaceProxyView result =
             CopyOnGpu(this->context(), source, this->colorType(), copyParams, willBeMipped);
 
-    if (!result) {
+    if (!result.proxy()) {
         // If we were unable to make a copy and we only needed a copy for mips, then we will return
         // the source texture here and require that the GPU backend is able to fall back to using
         // bilerp if mips are required.
         if (needsCopyForMipsOnly) {
             return source;
         }
-        return nullptr;
+        return {};
     }
 
     if (copyKey.isValid()) {
-        SkASSERT(result->origin() == origOrigin);
-        if (cachedProxy) {
-            SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
-                     GrMipMapped::kNo == cachedProxy->mipMapped());
+        SkASSERT(result.origin() == origOrigin);
+        if (cachedView.proxy()) {
+            SkASSERT(GrMipMapped::kYes == result.asTextureProxy()->mipMapped() &&
+                     GrMipMapped::kNo == cachedView.asTextureProxy()->mipMapped());
             // 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.
-            SkASSERT(cachedProxy->getUniqueKey() == copyKey);
-            proxyProvider->removeUniqueKeyFromProxy(cachedProxy.get());
+            SkASSERT(cachedView.asTextureProxy()->getUniqueKey() == copyKey);
+            proxyProvider->removeUniqueKeyFromProxy(cachedView.asTextureProxy());
         }
-        proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
+        proxyProvider->assignUniqueKeyToProxy(copyKey, result.asTextureProxy());
         this->didCacheCopy(copyKey, proxyProvider->contextID());
     }
     return result;
@@ -124,9 +134,9 @@
     }
 
     SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
-    sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(filterOrNullForBicubic,
-                                                               scaleAdjust));
-    if (!proxy) {
+    GrSurfaceProxyView view = this->refTextureProxyViewForParams(filterOrNullForBicubic,
+                                                                 scaleAdjust);
+    if (!view.proxy()) {
         return nullptr;
     }
     SkMatrix adjustedMatrix = textureMatrix;
@@ -135,8 +145,8 @@
     SkRect domain;
     DomainMode domainMode =
         DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
-                            proxy.get(), fmForDetermineDomain, &domain);
+                            view.proxy(), fmForDetermineDomain, &domain);
     SkASSERT(kTightCopy_DomainMode != domainMode);
     return this->createFragmentProcessorForDomainAndFilter(
-            std::move(proxy), adjustedMatrix, domainMode, domain, filterOrNullForBicubic);
+            std::move(view), adjustedMatrix, domainMode, domain, filterOrNullForBicubic);
 }
diff --git a/src/gpu/GrTextureMaker.h b/src/gpu/GrTextureMaker.h
index cd0942f..22aaced 100644
--- a/src/gpu/GrTextureMaker.h
+++ b/src/gpu/GrTextureMaker.h
@@ -36,13 +36,13 @@
      *  construct then refOriginalTextureProxy should return nullptr (for example if texture is made
      *  by drawing into a render target).
      */
-    virtual sk_sp<GrTextureProxy> refOriginalTextureProxy(bool willBeMipped,
-                                                          AllowedTexGenType genType) = 0;
+    virtual GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
+                                                           AllowedTexGenType genType) = 0;
 
 private:
-    sk_sp<GrTextureProxy> onRefTextureProxyForParams(GrSamplerState,
-                                                     bool willBeMipped,
-                                                     SkScalar scaleAdjust[2]) override;
+    GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState,
+                                                      bool willBeMipped,
+                                                      SkScalar scaleAdjust[2]) override;
 
     typedef GrTextureProducer INHERITED;
 };
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 4ec6ec1..e61f1e8 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -21,17 +21,19 @@
 #include "src/gpu/effects/GrTextureDomain.h"
 #include "src/gpu/effects/GrTextureEffect.h"
 
-sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrRecordingContext* context,
-                                                   sk_sp<GrTextureProxy> inputProxy,
-                                                   GrColorType colorType,
-                                                   const CopyParams& copyParams,
-                                                   bool dstWillRequireMipMaps) {
+GrSurfaceProxyView GrTextureProducer::CopyOnGpu(GrRecordingContext* context,
+                                                GrSurfaceProxyView inputView,
+                                                GrColorType colorType,
+                                                const CopyParams& copyParams,
+                                                bool dstWillRequireMipMaps) {
     SkASSERT(context);
+    SkASSERT(inputView.asTextureProxy());
 
     const SkRect dstRect = SkRect::Make(copyParams.fDimensions);
     GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
 
-    SkRect localRect = inputProxy->getBoundsRect();
+    GrSurfaceProxy* proxy = inputView.proxy();
+    SkRect localRect = proxy->getBoundsRect();
 
     bool resizing = false;
     if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
@@ -40,34 +42,33 @@
 
     if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !resizing &&
         dstWillRequireMipMaps) {
-        sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get(),
-                                                                     inputProxy->origin(),
-                                                                     colorType);
-        if (proxy) {
-            return proxy;
+        GrSurfaceProxyView view = GrCopyBaseMipMapToTextureProxy(context, proxy, inputView.origin(),
+                                                                 colorType);
+        if (view.proxy()) {
+            return view;
         }
     }
 
     auto copyRTC = GrRenderTargetContext::MakeWithFallback(
             context, colorType, nullptr, SkBackingFit::kExact, copyParams.fDimensions, 1,
-            mipMapped, inputProxy->isProtected(), inputProxy->origin());
+            mipMapped, proxy->isProtected(), inputView.origin());
     if (!copyRTC) {
-        return nullptr;
+        return {};
     }
 
     const auto& caps = *context->priv().caps();
     GrPaint paint;
 
     GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
-    auto boundsRect = SkIRect::MakeSize(inputProxy->dimensions());
-    auto fp = GrTextureEffect::MakeTexelSubset(std::move(inputProxy), kUnknown_SkAlphaType,
+    auto boundsRect = SkIRect::MakeSize(proxy->dimensions());
+    auto fp = GrTextureEffect::MakeTexelSubset(inputView.detachProxy(), kUnknown_SkAlphaType,
                                                SkMatrix::I(), sampler, boundsRect, localRect, caps);
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
     copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
                             localRect);
-    return copyRTC->asTextureProxyRef();
+    return copyRTC->readSurfaceView();
 }
 
 /** Determines whether a texture domain is necessary and if so what domain to use. There are two
@@ -86,7 +87,7 @@
         const SkRect& constraintRect,
         FilterConstraint filterConstraint,
         bool coordsLimitedToConstraintRect,
-        GrTextureProxy* proxy,
+        GrSurfaceProxy* proxy,
         const GrSamplerState::Filter* filterModeOrNullForBicubic,
         SkRect* domainRect) {
     const SkIRect proxyBounds = SkIRect::MakeSize(proxy->dimensions());
@@ -186,12 +187,13 @@
 }
 
 std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForDomainAndFilter(
-        sk_sp<GrTextureProxy> proxy,
+        GrSurfaceProxyView view,
         const SkMatrix& textureMatrix,
         DomainMode domainMode,
         const SkRect& domain,
         const GrSamplerState::Filter* filterOrNullForBicubic) {
     SkASSERT(kTightCopy_DomainMode != domainMode);
+    SkASSERT(view.asTextureProxy());
     const auto& caps = *fContext->priv().caps();
     SkAlphaType srcAlphaType = this->alphaType();
     if (filterOrNullForBicubic) {
@@ -200,10 +202,10 @@
                                                     : GrSamplerState::WrapMode::kClamp;
         GrSamplerState samplerState(wrapMode, *filterOrNullForBicubic);
         if (kNoDomain_DomainMode == domainMode) {
-            return GrTextureEffect::Make(std::move(proxy), srcAlphaType, textureMatrix,
+            return GrTextureEffect::Make(view.detachProxy(), srcAlphaType, textureMatrix,
                                          samplerState, caps);
         }
-        return GrTextureEffect::MakeSubset(std::move(proxy), srcAlphaType, textureMatrix,
+        return GrTextureEffect::MakeSubset(view.detachProxy(), srcAlphaType, textureMatrix,
                                            samplerState, domain, caps);
     } else {
         static const GrSamplerState::WrapMode kClampClamp[] = {
@@ -216,18 +218,18 @@
         if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
             GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
                                          : GrTextureDomain::kClamp_Mode;
-            return GrBicubicEffect::Make(std::move(proxy), textureMatrix, kClampClamp, wrapMode,
+            return GrBicubicEffect::Make(view.detachProxy(), textureMatrix, kClampClamp, wrapMode,
                                          wrapMode, kDir, srcAlphaType,
                                          kDomain_DomainMode == domainMode ? &domain : nullptr);
         } else {
-            return GrBicubicEffect::Make(std::move(proxy), textureMatrix,
+            return GrBicubicEffect::Make(view.detachProxy(), textureMatrix,
                                          fDomainNeedsDecal ? kDecalDecal : kClampClamp, kDir,
                                          srcAlphaType);
         }
     }
 }
 
-sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxyForParams(
+GrSurfaceProxyView GrTextureProducer::refTextureProxyViewForParams(
         const GrSamplerState::Filter* filterOrNullForBicubic,
         SkScalar scaleAdjust[2]) {
     GrSamplerState sampler; // Default is nearest + clamp
@@ -241,11 +243,11 @@
             sampler.setWrapModeY(GrSamplerState::WrapMode::kClampToBorder);
         }
     }
-    return this->refTextureProxyForParams(sampler, scaleAdjust);
+    return this->refTextureProxyViewForParams(sampler, scaleAdjust);
 }
 
-sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxyForParams(GrSamplerState sampler,
-                                                                  SkScalar scaleAdjust[2]) {
+GrSurfaceProxyView GrTextureProducer::refTextureProxyViewForParams(GrSamplerState sampler,
+                                                                   SkScalar scaleAdjust[2]) {
     // Check that the caller pre-initialized scaleAdjust
     SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1));
 
@@ -255,37 +257,42 @@
     bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
                         caps->mipMapSupport();
 
-    auto result = this->onRefTextureProxyForParams(sampler, willBeMipped, scaleAdjust);
+    auto result = this->onRefTextureProxyViewForParams(sampler, willBeMipped, scaleAdjust);
 
     // Check to make sure that if we say the texture willBeMipped that the returned texture has mip
     // maps, unless the config is not copyable.
-    SkASSERT(!result || !willBeMipped || result->mipMapped() == GrMipMapped::kYes ||
-             !caps->isFormatCopyable(result->backendFormat()));
+    SkASSERT(!result.proxy() || !willBeMipped ||
+             result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
+             !caps->isFormatCopyable(result.proxy()->backendFormat()));
+
+    SkASSERT(!result.proxy() || result.asTextureProxy());
 
     SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
                                       !sampler.isRepeated()));
     // Check that the "no scaling expected" case always returns a proxy of the same size as the
     // producer.
-    SkASSERT(!result || !expectNoScale || result->dimensions() == this->dimensions());
+    SkASSERT(!result.proxy() || !expectNoScale ||
+             result.proxy()->dimensions() == this->dimensions());
 
     return result;
 }
 
-std::pair<sk_sp<GrTextureProxy>, GrColorType> GrTextureProducer::refTextureProxy(
+std::pair<GrSurfaceProxyView, GrColorType> GrTextureProducer::refTextureProxyView(
         GrMipMapped willNeedMips) {
     GrSamplerState::Filter filter =
             GrMipMapped::kNo == willNeedMips ? GrSamplerState::Filter::kNearest
                                              : GrSamplerState::Filter::kMipMap;
     GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, filter);
 
-    auto result = this->refTextureProxyForParams(sampler, nullptr);
+    auto result = this->refTextureProxyViewForParams(sampler, nullptr);
 
 #ifdef SK_DEBUG
     const GrCaps* caps = this->context()->priv().caps();
     // Check that the resulting proxy format is compatible with the GrColorType of this producer
-    SkASSERT(!result ||
-             result->isFormatCompressed(caps) ||
-             caps->areColorTypeAndFormatCompatible(this->colorType(), result->backendFormat()));
+    SkASSERT(!result.proxy() ||
+             result.proxy()->isFormatCompressed(caps) ||
+             caps->areColorTypeAndFormatCompatible(this->colorType(),
+                                                   result.proxy()->backendFormat()));
 #endif
 
     return {result, this->colorType()};
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
index a75380a..e2d26c3 100644
--- a/src/gpu/GrTextureProducer.h
+++ b/src/gpu/GrTextureProducer.h
@@ -82,9 +82,9 @@
      * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling
      * this method. (TODO: Fix this and make this function always initialize scaleAdjust).
      */
-    sk_sp<GrTextureProxy> refTextureProxyForParams(GrSamplerState, SkScalar scaleAdjust[2]);
+    GrSurfaceProxyView refTextureProxyViewForParams(GrSamplerState, SkScalar scaleAdjust[2]);
 
-    sk_sp<GrTextureProxy> refTextureProxyForParams(
+    GrSurfaceProxyView refTextureProxyViewForParams(
             const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]);
 
     /**
@@ -96,7 +96,7 @@
     // wrap mode. To support that flag now would require us to support scaleAdjust array like in
     // refTextureProxyForParams, however the current public API that uses this call does not expose
     // that array.
-    std::pair<sk_sp<GrTextureProxy>, GrColorType> refTextureProxy(GrMipMapped willNeedMips);
+    std::pair<GrSurfaceProxyView, GrColorType> refTextureProxyView(GrMipMapped willNeedMips);
 
     virtual ~GrTextureProducer() {}
 
@@ -158,21 +158,21 @@
     };
 
     // This can draw to accomplish the copy, thus the recording context is needed
-    static sk_sp<GrTextureProxy> CopyOnGpu(GrRecordingContext*,
-                                           sk_sp<GrTextureProxy> inputProxy,
-                                           GrColorType,
-                                           const CopyParams& copyParams,
-                                           bool dstWillRequireMipMaps);
+    static GrSurfaceProxyView CopyOnGpu(GrRecordingContext*,
+                                        GrSurfaceProxyView inputView,
+                                        GrColorType,
+                                        const CopyParams& copyParams,
+                                        bool dstWillRequireMipMaps);
 
     static DomainMode DetermineDomainMode(const SkRect& constraintRect,
                                           FilterConstraint filterConstraint,
                                           bool coordsLimitedToConstraintRect,
-                                          GrTextureProxy*,
+                                          GrSurfaceProxy*,
                                           const GrSamplerState::Filter* filterModeOrNullForBicubic,
                                           SkRect* domainRect);
 
     std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForDomainAndFilter(
-            sk_sp<GrTextureProxy> proxy,
+            GrSurfaceProxyView view,
             const SkMatrix& textureMatrix,
             DomainMode,
             const SkRect& domain,
@@ -181,9 +181,8 @@
     GrRecordingContext* context() const { return fContext; }
 
 private:
-    virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(GrSamplerState,
-                                                             bool willBeMipped,
-                                                             SkScalar scaleAdjust[2]) = 0;
+    virtual GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
+                                                              SkScalar scaleAdjust[2]) = 0;
 
     GrRecordingContext* fContext;
     const GrImageInfo fImageInfo;
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 4cb2fe9..d40a87a 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -104,11 +104,11 @@
     cachedData->unref();
 }
 
-sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrRecordingContext* ctx,
-                                                       const GrSurfaceDesc& desc,
-                                                       GrColorType colorType,
-                                                       SkColorSpace* srcColorSpace,
-                                                       SkColorSpace* dstColorSpace) {
+GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx,
+                                                        const GrSurfaceDesc& desc,
+                                                        GrColorType colorType,
+                                                        SkColorSpace* srcColorSpace,
+                                                        SkColorSpace* dstColorSpace) {
     SkYUVASizeInfo yuvSizeInfo;
     SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount];
     SkYUVColorSpace yuvColorSpace;
@@ -117,7 +117,7 @@
     sk_sp<SkCachedData> dataStorage = this->getPlanes(&yuvSizeInfo, yuvaIndices,
                                                       &yuvColorSpace, planes);
     if (!dataStorage) {
-        return nullptr;
+        return {};
     }
 
     sk_sp<GrTextureProxy> yuvTextureProxies[SkYUVASizeInfo::kMaxCount];
@@ -153,10 +153,11 @@
         bitmap.setImmutable();
 
         GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kNo, fit);
-        std::tie(yuvTextureProxies[i], std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        yuvTextureProxies[i] = view.asTextureProxyRef();
 
         if (!yuvTextureProxies[i]) {
-            return nullptr;
+            return {};
         }
 
         SkASSERT(yuvTextureProxies[i]->dimensions() == yuvSizeInfo.fSizes[i]);
@@ -167,7 +168,7 @@
             ctx, colorType, nullptr, SkBackingFit::kExact, {desc.fWidth, desc.fHeight}, 1,
             GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
     if (!renderTargetContext) {
-        return nullptr;
+        return {};
     }
 
     GrPaint paint;
@@ -192,5 +193,6 @@
     SkMatrix m = SkEncodedOriginToMatrix(yuvSizeInfo.fOrigin, r.width(), r.height());
     renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, r);
 
-    return renderTargetContext->asTextureProxyRef();
+    SkASSERT(renderTargetContext->asTextureProxy());
+    return renderTargetContext->readSurfaceView();
 }
diff --git a/src/gpu/GrYUVProvider.h b/src/gpu/GrYUVProvider.h
index bfd1ddc..521ec48 100644
--- a/src/gpu/GrYUVProvider.h
+++ b/src/gpu/GrYUVProvider.h
@@ -17,8 +17,7 @@
 class GrBackendFormat;
 class GrRecordingContext;
 struct GrSurfaceDesc;
-class GrTexture;
-class GrTextureProxy;
+class GrSurfaceProxyView;
 class SkCachedData;
 
 /**
@@ -42,11 +41,11 @@
      *
      *  On failure (e.g. the provider had no data), this returns NULL.
      */
-    sk_sp<GrTextureProxy> refAsTextureProxy(GrRecordingContext*,
-                                            const GrSurfaceDesc&,
-                                            GrColorType colorType,
-                                            SkColorSpace* srcColorSpace,
-                                            SkColorSpace* dstColorSpace);
+    GrSurfaceProxyView refAsTextureProxyView(GrRecordingContext*,
+                                             const GrSurfaceDesc&,
+                                             GrColorType colorType,
+                                             SkColorSpace* srcColorSpace,
+                                             SkColorSpace* dstColorSpace);
 
     sk_sp<SkCachedData> getPlanes(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
                                   SkYUVColorSpace*, const void* planes[SkYUVASizeInfo::kMaxCount]);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 35dd2de..9a77be7 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1318,7 +1318,10 @@
     auto iter = std::make_unique<SkLatticeIter>(image->width(), image->height(), center, dst);
     if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(this->context(),
                                                                           &pinnedUniqueID)) {
-        GrTextureAdjuster adjuster(this->context(), std::move(proxy),
+        GrSurfaceOrigin origin = proxy->origin();
+        GrSwizzle swizzle = proxy->textureSwizzle();
+        GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
+        GrTextureAdjuster adjuster(this->context(), std::move(view),
                                    image->imageInfo().colorInfo(), pinnedUniqueID);
         this->drawProducerLattice(&adjuster, std::move(iter), dst, paint);
     } else {
@@ -1358,17 +1361,13 @@
 
     auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
     const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
-    auto proxy = producer->refTextureProxyForParams(&filter, nullptr);
-    if (!proxy) {
+    auto view = producer->refTextureProxyViewForParams(&filter, nullptr);
+    if (!view.proxy()) {
         return;
     }
     auto csxf = GrColorSpaceXform::Make(producer->colorSpace(), producer->alphaType(),
                                         dstColorSpace,          kPremul_SkAlphaType);
 
-    GrSurfaceOrigin origin = proxy->origin();
-    const GrSwizzle& swizzle = proxy->textureSwizzle();
-    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
-
     fRenderTargetContext->drawImageLattice(this->clip(), std::move(grPaint), this->localToDevice(),
                                            std::move(view), producer->alphaType(), std::move(csxf),
                                            filter, std::move(iter), dst);
@@ -1382,7 +1381,10 @@
     auto iter = std::make_unique<SkLatticeIter>(lattice, dst);
     if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(this->context(),
                                                                           &pinnedUniqueID)) {
-        GrTextureAdjuster adjuster(this->context(), std::move(proxy),
+        GrSurfaceOrigin origin = proxy->origin();
+        GrSwizzle swizzle = proxy->textureSwizzle();
+        GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
+        GrTextureAdjuster adjuster(this->context(), std::move(view),
                                    image->imageInfo().colorInfo(), pinnedUniqueID);
         this->drawProducerLattice(&adjuster, std::move(iter), dst, paint);
     } else {
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index fa9b07c..38e4cbb 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -244,13 +244,13 @@
     if (attemptDrawTexture && can_use_draw_texture(paint)) {
         // We've done enough checks above to allow us to pass ClampNearest() and not check for
         // scaling adjustments.
-        auto [proxy, ct] = producer->refTextureProxy(GrMipMapped::kNo);
-        if (!proxy) {
+        auto [view, ct] = producer->refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy()) {
             return;
         }
 
         draw_texture(rtc, clip, ctm, paint, src, dst, dstClip, aa, aaFlags, constraint,
-                     std::move(proxy),
+                     view.asTextureProxyRef(),
                      {ct, producer->alphaType(), sk_ref_sp(producer->colorSpace())});
         return;
     }
@@ -421,7 +421,10 @@
                          dstClip, aa, aaFlags, constraint, std::move(proxy), colorInfo);
             return;
         }
-        GrTextureAdjuster adjuster(fContext.get(), std::move(proxy), colorInfo, pinnedUniqueID,
+        GrSurfaceOrigin origin = proxy->origin();
+        GrSwizzle swizzle = proxy->textureSwizzle();
+        GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
+        GrTextureAdjuster adjuster(fContext.get(), std::move(view), colorInfo, pinnedUniqueID,
                                    useDecal);
         draw_texture_producer(fContext.get(), fRenderTargetContext.get(), this->clip(), ctm,
                               paint, &adjuster, src, dst, dstClip, srcToDst, aa, aaFlags,
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index d2ec15a..1c2496e 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -124,19 +124,20 @@
     pixelRef->addGenIDChangeListener(new Invalidator(key, contextUniqueID));
 }
 
-sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
-                                                     GrSurfaceProxy* baseProxy,
-                                                     GrSurfaceOrigin origin,
-                                                     GrColorType srcColorType) {
+GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
+                                                  GrSurfaceProxy* baseProxy,
+                                                  GrSurfaceOrigin origin,
+                                                  GrColorType srcColorType) {
     SkASSERT(baseProxy);
 
     if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
-        return nullptr;
+        return {};
     }
     GrSurfaceProxyView view = GrSurfaceProxy::Copy(ctx, baseProxy, origin, srcColorType,
                                                    GrMipMapped::kYes, SkBackingFit::kExact,
                                                    SkBudgeted::kYes);
-    return view.asTextureProxyRef();
+    SkASSERT(!view.proxy() || view.asTextureProxy());
+    return view;
 }
 
 sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrRecordingContext* ctx,
@@ -144,7 +145,7 @@
                                                     GrSamplerState params,
                                                     SkScalar scaleAdjust[2]) {
     GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kYes);
-    return maker.refTextureProxyForParams(params, scaleAdjust);
+    return maker.refTextureProxyViewForParams(params, scaleAdjust).asTextureProxyRef();
 }
 
 GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext* context, const SkBitmap& bitmap,
@@ -154,14 +155,8 @@
     }
 
     GrBitmapTextureMaker maker(context, bitmap, GrBitmapTextureMaker::Cached::kYes, fit);
-    auto [proxy, ct] = maker.refTextureProxy(GrMipMapped::kNo);
-
-    if (!proxy) {
-        return {};
-    }
-    GrSurfaceOrigin origin = proxy->origin();
-    GrSwizzle swizzle = proxy->textureSwizzle();
-    return GrSurfaceProxyView(std::move(proxy), origin, swizzle);
+    auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+    return view;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 49109cf..840d36f 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -180,10 +180,10 @@
 /**
  * Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
  */
-sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
-                                                     GrSurfaceProxy* baseProxy,
-                                                     GrSurfaceOrigin origin,
-                                                     GrColorType srcColorType);
+GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
+                                                  GrSurfaceProxy* baseProxy,
+                                                  GrSurfaceOrigin origin,
+                                                  GrColorType srcColorType);
 
 /*
  * Create a texture proxy from the provided bitmap and add it to the texture cache
diff --git a/src/gpu/effects/GrCircleBlurFragmentProcessor.fp b/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
index d71e9d6..fcbea7c 100644
--- a/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
+++ b/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
@@ -253,7 +253,8 @@
             bm.setImmutable();
 
             GrBitmapTextureMaker maker(context, bm);
-            std::tie(blurProfile, std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
+            auto[blurView, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+            blurProfile = blurView.asTextureProxyRef();
             if (!blurProfile) {
                 return nullptr;
             }
diff --git a/src/gpu/effects/GrConfigConversionEffect.fp b/src/gpu/effects/GrConfigConversionEffect.fp
index ae4c26c..8268110 100644
--- a/src/gpu/effects/GrConfigConversionEffect.fp
+++ b/src/gpu/effects/GrConfigConversionEffect.fp
@@ -60,9 +60,9 @@
         bitmap.setImmutable();
 
         GrBitmapTextureMaker maker(context, bitmap);
-        auto [dataProxy, ct] = maker.refTextureProxy(GrMipMapped::kNo);
+        auto [dataView, ct] = maker.refTextureProxyView(GrMipMapped::kNo);
 
-        if (!dataProxy) {
+        if (!dataView.proxy()) {
             return false;
         }
 
@@ -80,7 +80,8 @@
         std::unique_ptr<GrFragmentProcessor> upmToPM(
                 new GrConfigConversionEffect(PMConversion::kToPremul));
 
-        paint1.addColorFragmentProcessor(GrTextureEffect::Make(dataProxy, kPremul_SkAlphaType));
+        paint1.addColorFragmentProcessor(GrTextureEffect::Make(dataView.detachProxy(),
+                                                               kPremul_SkAlphaType));
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp
index 34f7112..7735751 100644
--- a/src/gpu/effects/GrRectBlurEffect.fp
+++ b/src/gpu/effects/GrRectBlurEffect.fp
@@ -82,10 +82,11 @@
         bitmap.setImmutable();
 
         GrBitmapTextureMaker maker(context, bitmap);
-        std::tie(proxy, std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!proxy) {
+        auto[view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy()) {
             return nullptr;
         }
+        proxy = view.asTextureProxyRef();
         SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
         proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
     }
diff --git a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
index a9e477c..13b9507 100644
--- a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
@@ -230,7 +230,8 @@
         bm.setImmutable();
 
         GrBitmapTextureMaker maker(context, bm);
-        std::tie(blurProfile, std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
+        auto[blurView, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        blurProfile = blurView.asTextureProxyRef();
         if (!blurProfile) {
             return nullptr;
         }
diff --git a/src/gpu/effects/generated/GrConfigConversionEffect.h b/src/gpu/effects/generated/GrConfigConversionEffect.h
index 51045bc..80519da 100644
--- a/src/gpu/effects/generated/GrConfigConversionEffect.h
+++ b/src/gpu/effects/generated/GrConfigConversionEffect.h
@@ -69,9 +69,9 @@
         bitmap.setImmutable();
 
         GrBitmapTextureMaker maker(context, bitmap);
-        auto[dataProxy, ct] = maker.refTextureProxy(GrMipMapped::kNo);
+        auto[dataView, ct] = maker.refTextureProxyView(GrMipMapped::kNo);
 
-        if (!dataProxy) {
+        if (!dataView.proxy()) {
             return false;
         }
 
@@ -89,7 +89,8 @@
         std::unique_ptr<GrFragmentProcessor> upmToPM(
                 new GrConfigConversionEffect(PMConversion::kToPremul));
 
-        paint1.addColorFragmentProcessor(GrTextureEffect::Make(dataProxy, kPremul_SkAlphaType));
+        paint1.addColorFragmentProcessor(
+                GrTextureEffect::Make(dataView.detachProxy(), kPremul_SkAlphaType));
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.h b/src/gpu/effects/generated/GrRectBlurEffect.h
index 4ed6526..7ee6d7b 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRectBlurEffect.h
@@ -65,10 +65,11 @@
             bitmap.setImmutable();
 
             GrBitmapTextureMaker maker(context, bitmap);
-            std::tie(proxy, std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
-            if (!proxy) {
+            auto[view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+            if (!view.proxy()) {
                 return nullptr;
             }
+            proxy = view.asTextureProxyRef();
             SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
             proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
         }
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index e9fab08..f157547 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -664,13 +664,14 @@
         bitmap.setImmutable();
 
         GrBitmapTextureMaker maker(context, bitmap);
-        std::tie(falloffTexture, std::ignore) = maker.refTextureProxy(GrMipMapped::kNo);
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin);
 
+        falloffTexture = view.asTextureProxyRef();
         if (!falloffTexture) {
             return nullptr;
         }
 
-        SkASSERT(falloffTexture->origin() == kTopLeft_GrSurfaceOrigin);
         proxyProvider->assignUniqueKeyToProxy(key, falloffTexture.get());
     }
 
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 714cc47..d7c5f5a 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -415,14 +415,10 @@
 
 static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
                                                  uint32_t id, GrMipMapped mipMapped) {
-    // TODO: have texture producer return a GrSurfaceProxyView
-    auto [proxy, colorType] = producer->refTextureProxy(mipMapped);
-    if (!proxy) {
+    auto [view, colorType] = producer->refTextureProxyView(mipMapped);
+    if (!view.proxy()) {
         return nullptr;
     }
-    GrSurfaceOrigin origin = proxy->origin();
-    const GrSwizzle& swizzle = proxy->textureSwizzle();
-    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
     return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, std::move(view),
                                    GrColorTypeToSkColorType(colorType),
                                    producer->alphaType(), sk_ref_sp(producer->colorSpace()));
@@ -438,12 +434,12 @@
             return nullptr;
         }
 
-        sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
-        SkASSERT(proxy);
-        if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
+        GrSurfaceProxyView view = as_IB(this)->asSurfaceProxyViewRef(context);
+        SkASSERT(view.asTextureProxy());
+        if (GrMipMapped::kNo == mipMapped || view.asTextureProxy()->mipMapped() == mipMapped) {
             return sk_ref_sp(const_cast<SkImage*>(this));
         }
-        GrTextureAdjuster adjuster(context, std::move(proxy), this->imageInfo().colorInfo(),
+        GrTextureAdjuster adjuster(context, std::move(view), this->imageInfo().colorInfo(),
                                    this->uniqueID());
         return create_image_from_producer(context, &adjuster, this->uniqueID(), mipMapped);
     }
@@ -559,21 +555,21 @@
     bmp.installPixels(*pixmap);
     GrBitmapTextureMaker bitmapMaker(context, bmp);
     GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
-    auto [proxy, grCT] = bitmapMaker.refTextureProxy(mipMapped);
-    if (!proxy) {
+    auto [view, grCT] = bitmapMaker.refTextureProxyView(mipMapped);
+    if (!view.proxy()) {
         return SkImage::MakeRasterCopy(*pixmap);
     }
 
-    sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
+    sk_sp<GrTexture> texture = sk_ref_sp(view.proxy()->peekTexture());
 
     // Flush any writes or uploads
-    context->priv().flushSurface(proxy.get());
+    context->priv().flushSurface(view.proxy());
     GrGpu* gpu = context->priv().getGpu();
 
     std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
 
     SkColorType skCT = GrColorTypeToSkColorType(grCT);
-    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
+    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), view.origin(),
                                                     std::move(sema), skCT,
                                                     pixmap->alphaType(),
                                                     pixmap->info().refColorSpace());
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 61a8fd0..82a7603 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -195,9 +195,9 @@
         return nullptr;
     }
 
-    GrTextureAdjuster adjuster(fContext.get(), this->asTextureProxyRef(context),
+    GrTextureAdjuster adjuster(fContext.get(), this->asSurfaceProxyViewRef(context),
                                this->imageInfo().colorInfo(), this->uniqueID());
-    return adjuster.refTextureProxyForParams(params, scaleAdjust);
+    return adjuster.refTextureProxyViewForParams(params, scaleAdjust).asTextureProxyRef();
 }
 
 GrBackendTexture SkImage_GpuBase::onGetBackendTexture(bool flushPendingGrContextIO,
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index 0860cf3..30cbb58 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -98,12 +98,12 @@
                                                     fProxies[i].get(),
                                                     GrSamplerState::Filter::kMipMap,
                                                     &copyParams)) {
-            auto mippedProxy = GrCopyBaseMipMapToTextureProxy(context, fProxies[i].get(), fOrigin,
-                                                              fProxyColorTypes[i]);
-            if (!mippedProxy) {
+            auto mippedView = GrCopyBaseMipMapToTextureProxy(context, fProxies[i].get(), fOrigin,
+                                                             fProxyColorTypes[i]);
+            if (!mippedView.proxy()) {
                 return false;
             }
-            fProxies[i] = mippedProxy;
+            fProxies[i] = mippedView.asTextureProxyRef();
         }
     }
     return true;
@@ -174,24 +174,24 @@
     return fRGBView.asTextureProxyRef();
 }
 
-sk_sp<GrTextureProxy> SkImage_GpuYUVA::asMippedTextureProxyRef(GrRecordingContext* context) const {
+GrSurfaceProxyView SkImage_GpuYUVA::asMippedTextureProxyViewRef(GrRecordingContext* context) const {
     // if invalid or already has miplevels
     this->flattenToRGB(context);
     if (!fRGBView.proxy() || GrMipMapped::kYes == fRGBView.asTextureProxy()->mipMapped()) {
-        return fRGBView.asTextureProxyRef();
+        return fRGBView;
     }
 
     // need to generate mips for the proxy
     GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
-    if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(
-            context, fRGBView.proxy(), fRGBView.origin(), srcColorType)) {
-        SkASSERT(mippedProxy->textureSwizzle() == GrSwizzle());
-        fRGBView = GrSurfaceProxyView(mippedProxy, fOrigin, GrSwizzle());
-        return mippedProxy;
+    GrSurfaceProxyView mippedView = GrCopyBaseMipMapToTextureProxy(
+            context, fRGBView.proxy(), fRGBView.origin(), srcColorType);
+    if (mippedView.proxy()) {
+        fRGBView = std::move(mippedView);
+        return fRGBView;
     }
 
     // failed to generate mips
-    return nullptr;
+    return {};
 }
 
 GrSurfaceProxyView SkImage_GpuYUVA::asSurfaceProxyViewRef(GrRecordingContext* context) const {
@@ -298,11 +298,12 @@
         bmp.installPixels(*pixmap);
         GrBitmapTextureMaker bitmapMaker(context, bmp);
         GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
-        std::tie(tempTextureProxies[i], proxyColorTypes[i]) =
-                bitmapMaker.refTextureProxy(mipMapped);
-        if (!tempTextureProxies[i]) {
+        GrSurfaceProxyView view;
+        std::tie(view, proxyColorTypes[i]) = bitmapMaker.refTextureProxyView(mipMapped);
+        if (!view.proxy()) {
             return nullptr;
         }
+        tempTextureProxies[i] = view.asTextureProxyRef();
     }
 
     return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageSize, kNeedNewImageUniqueID,
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index 65a4e0f..27ad48c 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -55,8 +55,8 @@
 
     bool setupMipmapsForPlanes(GrRecordingContext*) const;
 
-    // Returns a ref-ed texture proxy with miplevels
-    sk_sp<GrTextureProxy> asMippedTextureProxyRef(GrRecordingContext*) const;
+    // Returns a ref-ed texture proxy view with miplevels
+    GrSurfaceProxyView asMippedTextureProxyViewRef(GrRecordingContext*) const;
 
 #if GR_TEST_UTILS
     bool testingOnly_IsFlattened() const {
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 0b8233f..f6cc530 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -246,7 +246,7 @@
     }
 
     GrImageTextureMaker textureMaker(context, this, kAllow_CachingHint);
-    return textureMaker.refTextureProxyForParams(params, scaleAdjust);
+    return textureMaker.refTextureProxyViewForParams(params, scaleAdjust).asTextureProxyRef();
 }
 #endif
 
@@ -421,7 +421,7 @@
  *  3. Ask the generator to return YUV planes, which the GPU can convert
  *  4. Ask the generator to return RGB(A) data, which the GPU can convert
  */
-sk_sp<GrTextureProxy> SkImage_Lazy::lockTextureProxy(
+GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(
         GrRecordingContext* ctx,
         const GrUniqueKey& origKey,
         SkImage::CachingHint chint,
@@ -448,46 +448,53 @@
     GrUniqueKey key;
     this->makeCacheKeyFromOrigKey(origKey, &key);
 
+    const GrCaps* caps = ctx->priv().caps();
     GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
-    sk_sp<GrTextureProxy> proxy;
+    GrSurfaceProxyView view;
+
+    auto ct = this->colorTypeOfLockTextureProxy(caps);
 
     // 1. Check the cache for a pre-existing one
     if (key.isValid()) {
-        auto ct = SkColorTypeToGrColorType(this->colorType());
-        proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, ct, kTopLeft_GrSurfaceOrigin);
+        auto proxy = proxyProvider->findOrCreateProxyByUniqueKey(key, ct, kTopLeft_GrSurfaceOrigin);
         if (proxy) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kPreExisting_LockTexturePath,
                                      kLockTexturePathCount);
-            if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
-                return proxy;
+            GrSwizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
+            view = GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
+            if (!willBeMipped || GrMipMapped::kYes == view.asTextureProxy()->mipMapped()) {
+                return view;
             }
         }
     }
 
     // 2. Ask the generator to natively create one
-    if (!proxy) {
+    if (!view.proxy()) {
         ScopedGenerator generator(fSharedGenerator);
         if (GrTextureMaker::AllowedTexGenType::kCheap == genType &&
                 SkImageGenerator::TexGenType::kCheap != generator->onCanGenerateTexture()) {
-            return nullptr;
+            return {};
         }
-        if ((proxy = generator->generateTexture(ctx, this->imageInfo(), fOrigin, willBeMipped))) {
+        view = generator->generateTexture(ctx, this->imageInfo(), fOrigin, willBeMipped);
+        if (view.proxy()) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
+            GrTextureProxy* proxy = view.asTextureProxy();
+            SkASSERT(proxy);
+            set_key_on_proxy(proxyProvider, proxy, nullptr, key);
             if (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped()) {
                 if (generator->texturesAreCacheable()) {
                     *fUniqueKeyInvalidatedMessages.append() =
                         new GrUniqueKeyInvalidatedMessage(key, ctx->priv().contextID());
                 }
-                return proxy;
+                return view;
             }
         }
     }
 
     // 3. Ask the generator to return YUV planes, which the GPU can convert. If we will be mipping
     //    the texture we fall through here and have the CPU generate the mip maps for us.
-    if (!proxy && !willBeMipped && !ctx->priv().options().fDisableGpuYUVConversion) {
+    if (!view.proxy() && !willBeMipped && !ctx->priv().options().fDisableGpuYUVConversion) {
         const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(this->imageInfo());
 
         SkColorType colorType = this->colorType();
@@ -504,58 +511,65 @@
 
         // TODO: Update to create the mipped surface in the YUV generator and draw the base
         // layer directly into the mipped surface.
-        proxy = provider.refAsTextureProxy(ctx, desc, SkColorTypeToGrColorType(colorType),
-                                           generatorColorSpace, thisColorSpace);
-        if (proxy) {
+        view = provider.refAsTextureProxyView(ctx, desc, SkColorTypeToGrColorType(colorType),
+                                               generatorColorSpace, thisColorSpace);
+        if (view.proxy()) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kYUV_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
+            GrTextureProxy* proxy = view.asTextureProxy();
+            SkASSERT(proxy);
+            set_key_on_proxy(proxyProvider, proxy, nullptr, key);
             *fUniqueKeyInvalidatedMessages.append() =
                     new GrUniqueKeyInvalidatedMessage(key, ctx->priv().contextID());
-            return proxy;
+            return view;
         }
     }
 
     // 4. Ask the generator to return RGB(A) data, which the GPU can convert
     SkBitmap bitmap;
-    if (!proxy && this->getROPixels(&bitmap, chint)) {
+    if (!view.proxy() && this->getROPixels(&bitmap, chint)) {
         GrBitmapTextureMaker bitmapMaker(ctx, bitmap);
-        std::tie(proxy, std::ignore) = bitmapMaker.refTextureProxy(willBeMipped ? GrMipMapped::kYes
-                                                                                : GrMipMapped::kNo);
+        std::tie(view, std::ignore) =
+                bitmapMaker.refTextureProxyView(willBeMipped ? GrMipMapped::kYes
+                                                             : GrMipMapped::kNo);
+        GrTextureProxy* proxy = view.asTextureProxy();
         if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kRGBA_LockTexturePath,
                                      kLockTexturePathCount);
-            set_key_on_proxy(proxyProvider, proxy.get(), nullptr, key);
+            SkASSERT(proxy);
+            set_key_on_proxy(proxyProvider, proxy, nullptr, key);
             *fUniqueKeyInvalidatedMessages.append() =
                     new GrUniqueKeyInvalidatedMessage(key, ctx->priv().contextID());
-            return proxy;
+            return view;
         }
     }
 
-    if (proxy) {
+    if (view.proxy()) {
         // We need a mipped proxy, but we either found a proxy earlier that wasn't mipped, generated
         // a native non mipped proxy, or generated a non-mipped yuv proxy. Thus we generate a new
         // mipped surface and copy the original proxy into the base layer. We will then let the gpu
         // generate the rest of the mips.
         SkASSERT(willBeMipped);
-        SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
+        SkASSERT(GrMipMapped::kNo == view.asTextureProxy()->mipMapped());
         *fUniqueKeyInvalidatedMessages.append() =
                 new GrUniqueKeyInvalidatedMessage(key, ctx->priv().contextID());
         GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
-        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(
-                ctx, proxy.get(), kTopLeft_GrSurfaceOrigin, srcColorType)) {
-            set_key_on_proxy(proxyProvider, mippedProxy.get(), proxy.get(), key);
-            return mippedProxy;
+        GrSurfaceProxyView mippedView = GrCopyBaseMipMapToTextureProxy(
+                ctx, view.proxy(), kTopLeft_GrSurfaceOrigin, srcColorType);
+        auto mippedProxy = mippedView.asTextureProxy();
+        if (mippedProxy) {
+            set_key_on_proxy(proxyProvider, mippedProxy, view.asTextureProxy(), key);
+            return mippedView;
         }
         // We failed to make a mipped proxy with the base copied into it. This could have
         // been from failure to make the proxy or failure to do the copy. Thus we will fall
         // back to just using the non mipped proxy; See skbug.com/7094.
-        return proxy;
+        return view;
     }
 
     SK_HISTOGRAM_ENUMERATION("LockTexturePath", kFailure_LockTexturePath,
                              kLockTexturePathCount);
-    return nullptr;
+    return {};
 }
 
 GrColorType SkImage_Lazy::colorTypeOfLockTextureProxy(const GrCaps* caps) const {
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index 42d0f94..afbd28c 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -62,11 +62,11 @@
     // Returns the texture proxy. If we're going to generate and cache the texture, we should use
     // the passed in key (if the key is valid). If genType is AllowedTexGenType::kCheap and the
     // texture is not trivial to construct, returns nullptr.
-    sk_sp<GrTextureProxy> lockTextureProxy(GrRecordingContext*,
-                                           const GrUniqueKey& key,
-                                           SkImage::CachingHint,
-                                           bool willBeMipped,
-                                           GrTextureMaker::AllowedTexGenType genType) const;
+    GrSurfaceProxyView lockTextureProxyView(GrRecordingContext*,
+                                            const GrUniqueKey& key,
+                                            SkImage::CachingHint,
+                                            bool willBeMipped,
+                                            GrTextureMaker::AllowedTexGenType genType) const;
 
     // Returns the GrColorType to use with the GrTextureProxy returned from lockTextureProxy. This
     // may be different from the color type on the image in the case where we need up upload CPU
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index b725de0..15fe77e 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -177,9 +177,12 @@
     uint32_t uniqueID;
     sk_sp<GrTextureProxy> tex = this->refPinnedTextureProxy(context, &uniqueID);
     if (tex) {
-        GrTextureAdjuster adjuster(context, fPinnedProxy, fBitmap.info().colorInfo(),
+        GrSurfaceOrigin origin = tex->origin();
+        GrSwizzle swizzle = tex->textureSwizzle();
+        GrSurfaceProxyView view(std::move(tex), origin, swizzle);
+        GrTextureAdjuster adjuster(context, std::move(view), fBitmap.info().colorInfo(),
                                    fPinnedUniqueID);
-        return adjuster.refTextureProxyForParams(params, scaleAdjust);
+        return adjuster.refTextureProxyViewForParams(params, scaleAdjust).asTextureProxyRef();
     }
 
     return GrRefCachedBitmapTextureProxy(context, fBitmap, params, scaleAdjust);
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index 7a24853..a7b8fd8 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -146,8 +146,9 @@
             SkIPoint origin = SkIPoint::Make(0,0);
             SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
                                                       kPremul_SkAlphaType);
-            sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
-                                                                       origin, willUseMips);
+            GrSurfaceProxyView genView = imageGen->generateTexture(context, imageInfo, origin,
+                                                                   willUseMips);
+            GrSurfaceProxy* genProxy = genView.proxy();
 
             REPORTER_ASSERT(reporter, genProxy);
             if (!genProxy) {
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index dc92dbc..b7c6fd0 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -426,15 +426,15 @@
         copySrcBitmap.setImmutable();
 
         GrBitmapTextureMaker maker(context, copySrcBitmap);
-        auto [copySrc, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
+        auto [copySrc, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
 
-        REPORTER_ASSERT(reporter, copySrc);
-        auto copyResult = surfContext->testCopy(copySrc.get());
+        REPORTER_ASSERT(reporter, copySrc.proxy());
+        auto copyResult = surfContext->testCopy(copySrc.proxy());
         REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType));
         // Try the low level copy.
         context->flush();
         auto gpuCopyResult = context->priv().getGpu()->copySurface(
-                proxy->peekTexture(), copySrc->peekTexture(), SkIRect::MakeWH(kSize, kSize),
+                proxy->peekSurface(), copySrc.proxy()->peekSurface(), SkIRect::MakeWH(kSize, kSize),
                 {0, 0});
         REPORTER_ASSERT(reporter, gpuCopyResult == (ioType == kRW_GrIOType));
 
diff --git a/tests/ImageFilterCacheTest.cpp b/tests/ImageFilterCacheTest.cpp
index 199f828..7ff7e5e 100644
--- a/tests/ImageFilterCacheTest.cpp
+++ b/tests/ImageFilterCacheTest.cpp
@@ -210,14 +210,8 @@
 static GrSurfaceProxyView create_proxy_view(GrRecordingContext* context) {
     SkBitmap srcBM = create_bm();
     GrBitmapTextureMaker maker(context, srcBM);
-    auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-
-    if (!proxy) {
-        return {};
-    }
-    GrSurfaceOrigin origin = proxy->origin();
-    GrSwizzle swizzle = proxy->textureSwizzle();
-    return {std::move(proxy), origin, swizzle};
+    auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+    return view;
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, ctxInfo) {
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 96e076d..891cb20 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -282,11 +282,11 @@
                              [](void* addr, void* context) { delete[] (GrColor*)addr; }, nullptr);
         bitmap.setImmutable();
         GrBitmapTextureMaker maker(context, bitmap);
-        auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!proxy || !proxy->instantiate(resourceProvider)) {
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy() || !view.proxy()->instantiate(resourceProvider)) {
             return false;
         }
-        proxies[0] = {std::move(proxy), GrColorType::kRGBA_8888, kPremul_SkAlphaType};
+        proxies[0] = {view.asTextureProxyRef(), GrColorType::kRGBA_8888, kPremul_SkAlphaType};
     }
 
     {
@@ -305,11 +305,11 @@
                              [](void* addr, void* context) { delete[] (uint8_t*)addr; }, nullptr);
         bitmap.setImmutable();
         GrBitmapTextureMaker maker(context, bitmap);
-        auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!proxy || !proxy->instantiate(resourceProvider)) {
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy() || !view.proxy()->instantiate(resourceProvider)) {
             return false;
         }
-        proxies[1] = {std::move(proxy), GrColorType::kAlpha_8, kPremul_SkAlphaType};
+        proxies[1] = {view.asTextureProxyRef(), GrColorType::kAlpha_8, kPremul_SkAlphaType};
     }
 
     return true;
@@ -332,8 +332,8 @@
                          [](void* addr, void* context) { delete[] (GrColor*)addr; }, nullptr);
     bitmap.setImmutable();
     GrBitmapTextureMaker maker(context, bitmap);
-    auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-    return proxy;
+    auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+    return view.asTextureProxyRef();
 }
 
 // We tag logged  data as unpremul to avoid conversion when encoding as  PNG. The input texture
diff --git a/tests/ReadWriteAlphaTest.cpp b/tests/ReadWriteAlphaTest.cpp
index 8e3904b..c24d16d 100644
--- a/tests/ReadWriteAlphaTest.cpp
+++ b/tests/ReadWriteAlphaTest.cpp
@@ -71,16 +71,12 @@
         bitmap.installPixels(ii, alphaDataCopy, ii.minRowBytes());
         bitmap.setImmutable();
         GrBitmapTextureMaker maker(context, bitmap);
-        auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!proxy) {
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy()) {
             ERRORF(reporter, "Could not create alpha texture.");
             return;
         }
 
-        SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
-        GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(),
-                                                                   grCT);
-        GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle);
         auto sContext = GrSurfaceContext::Make(context, std::move(view), grCT, kPremul_SkAlphaType,
                                                nullptr);
 
diff --git a/tests/SpecialImageTest.cpp b/tests/SpecialImageTest.cpp
index 73db823..98d9720 100644
--- a/tests/SpecialImageTest.cpp
+++ b/tests/SpecialImageTest.cpp
@@ -224,15 +224,11 @@
     {
         // gpu
         GrBitmapTextureMaker maker(context, bm);
-        auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-        if (!proxy) {
+        auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+        if (!view.proxy()) {
             return;
         }
 
-        GrSurfaceOrigin origin = proxy->origin();
-        GrSwizzle swizzle = proxy->textureSwizzle();
-        GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
-
         sk_sp<SkSpecialImage> gpuImage(SkSpecialImage::MakeDeferredFromGpu(
                                                             context,
                                                             SkIRect::MakeWH(kFullSize, kFullSize),
@@ -259,15 +255,11 @@
     GrContext* context = ctxInfo.grContext();
     SkBitmap bm = create_bm();
     GrBitmapTextureMaker maker(context, bm);
-    auto [proxy, grCT] = maker.refTextureProxy(GrMipMapped::kNo);
-    if (!proxy) {
+    auto [view, grCT] = maker.refTextureProxyView(GrMipMapped::kNo);
+    if (!view.proxy()) {
         return;
     }
 
-    GrSurfaceOrigin origin = proxy->origin();
-    GrSwizzle swizzle = proxy->textureSwizzle();
-    GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
-
     sk_sp<SkSpecialImage> fullSImg(SkSpecialImage::MakeDeferredFromGpu(
                                                             context,
                                                             SkIRect::MakeWH(kFullSize, kFullSize),