Make GrCopySurfaceOp friendlier to GrSurfaceProxy (take 2)

Reland of: https://skia-review.googlesource.com/c/11325/ (Make GrCopySurfaceOp friendlier to GrSurfaceProxy)

Change-Id: Ibe7312cebe7793af5803353a1499fbe7874c558f
Reviewed-on: https://skia-review.googlesource.com/11780
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 369e8e7..6ed53ff 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -23,19 +23,18 @@
     GrDrawingManager* drawingManager() { return fContext->fDrawingManager.get(); }
 
     // Create a renderTargetContext that wraps an existing renderTarget
-    sk_sp<GrRenderTargetContext> makeWrappedRenderTargetContext(sk_sp<GrRenderTarget> rt,
-                                                                sk_sp<SkColorSpace> colorSpace,
+    sk_sp<GrRenderTargetContext> makeWrappedRenderTargetContext(sk_sp<GrRenderTarget>,
+                                                                sk_sp<SkColorSpace>,
                                                                 const SkSurfaceProps* = nullptr);
 
     // Create a surfaceContext that wraps an existing texture or renderTarget
-    sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurface> tex);
+    sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurface>);
 
-    sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
-                                                      sk_sp<SkColorSpace>);
+    sk_sp<GrSurfaceContext> makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy>, sk_sp<SkColorSpace>);
 
-    sk_sp<GrSurfaceContext> makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
-                                                       SkBackingFit dstFit,
-                                                       SkBudgeted isDstBudgeted);
+    sk_sp<GrSurfaceContext> makeDeferredSurfaceContext(const GrSurfaceDesc&,
+                                                       SkBackingFit,
+                                                       SkBudgeted);
 
     // TODO: Maybe add a 'surfaceProps' param (that is ignored for non-RTs) and remove
     // makeBackendTextureRenderTargetContext & makeBackendTextureAsRenderTargetRenderTargetContext
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index e7a9022..a4b7731 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -135,22 +135,10 @@
     ASSERT_SINGLE_OWNER
     RETURN_FALSE_IF_ABANDONED
     SkDEBUGCODE(this->validate();)
-    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
+    GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::onCopy");
 
-    // TODO: defer instantiation until flush time
-    sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
-    if (!src) {
-        return false;
-    }
-
-    // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
-    sk_sp<GrRenderTarget> rt(
-                        sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
-    if (!rt) {
-        return false;
-    }
-
-    return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
+    return this->getOpList()->copySurface(fContext->resourceProvider(),
+                                          fRenderTargetProxy.get(), srcProxy, srcRect, dstPoint);
 }
 
 // TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
@@ -1664,8 +1652,7 @@
 
     GrXferProcessor::DstTexture dstTexture;
     if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
-        this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
-        if (!dstTexture.texture()) {
+        if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, op->bounds(), &dstTexture)) {
             return SK_InvalidUniqueID;
         }
     }
@@ -1720,8 +1707,7 @@
     args.fXPInputCoverage = analysis.outputCoverage();
 
     if (analysis.requiresDstTexture()) {
-        this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
-        if (!args.fDstTexture.texture()) {
+        if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
             return SK_InvalidUniqueID;
         }
     }
@@ -1731,33 +1717,39 @@
     return this->getOpList()->addOp(std::move(op), this);
 }
 
-void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
+bool GrRenderTargetContext::setupDstTexture(GrRenderTargetProxy* rtProxy, const GrClip& clip,
                                             const SkRect& opBounds,
                                             GrXferProcessor::DstTexture* dstTexture) {
     if (this->caps()->textureBarrierSupport()) {
-        if (GrTexture* rtTex = rt->asTexture()) {
+        if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
+            // MDB TODO: remove this instantiation. Blocked on making DstTexture be proxy-based
+            sk_sp<GrTexture> tex(sk_ref_sp(texProxy->instantiate(fContext->resourceProvider())));
+            if (!tex) {
+                SkDebugf("setupDstTexture: instantiation of src texture failed.\n");
+                return false;  // We have bigger problems now
+            }
+
             // The render target is a texture, so we can read from it directly in the shader. The XP
             // will be responsible to detect this situation and request a texture barrier.
-            dstTexture->setTexture(sk_ref_sp(rtTex));
+            dstTexture->setTexture(std::move(tex));
             dstTexture->setOffset(0, 0);
-            return;
+            return true;
         }
     }
 
-    SkIRect copyRect = SkIRect::MakeWH(rt->width(), rt->height());
+    SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
 
     SkIRect clippedRect;
-    clip.getConservativeBounds(rt->width(), rt->height(), &clippedRect);
+    clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
     SkIRect drawIBounds;
     opBounds.roundOut(&drawIBounds);
     // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
     drawIBounds.outset(1, 1);
     if (!clippedRect.intersect(drawIBounds)) {
 #ifdef SK_DEBUG
-        GrCapsDebugf(this->caps(), "Missed an early reject. "
-                                   "Bailing on draw from setupDstTexture.\n");
+        GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
 #endif
-        return;
+        return false;
     }
 
     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
@@ -1765,41 +1757,56 @@
     GrSurfaceDesc desc;
     bool rectsMustMatch = false;
     bool disallowSubrect = false;
-    if (!this->caps()->initDescForDstCopy(rt, &desc, &rectsMustMatch, &disallowSubrect)) {
-        desc.fOrigin = kDefault_GrSurfaceOrigin;
+    if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch, &disallowSubrect)) {
+        desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
         desc.fFlags = kRenderTarget_GrSurfaceFlag;
-        desc.fConfig = rt->config();
+        desc.fConfig = rtProxy->config();
     }
 
     if (!disallowSubrect) {
         copyRect = clippedRect;
     }
 
-    SkIPoint dstPoint;
-    SkIPoint dstOffset;
-    static const uint32_t kFlags = 0;
-    sk_sp<GrTexture> copy;
+    SkIPoint dstPoint, dstOffset;
+    SkBackingFit fit;
     if (rectsMustMatch) {
-        SkASSERT(desc.fOrigin == rt->origin());
-        desc.fWidth = rt->width();
-        desc.fHeight = rt->height();
+        SkASSERT(desc.fOrigin == rtProxy->origin());
+        desc.fWidth = rtProxy->width();
+        desc.fHeight = rtProxy->height();
         dstPoint = {copyRect.fLeft, copyRect.fTop};
         dstOffset = {0, 0};
-        copy = fContext->resourceProvider()->createTexture(desc, SkBudgeted::kYes, kFlags);
+        fit = SkBackingFit::kExact;
     } else {
         desc.fWidth = copyRect.width();
         desc.fHeight = copyRect.height();
         dstPoint = {0, 0};
         dstOffset = {copyRect.fLeft, copyRect.fTop};
-        copy.reset(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
+        fit = SkBackingFit::kApprox;
     }
 
+    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
+                                                                                desc,
+                                                                                fit,
+                                                                                SkBudgeted::kYes);
+    if (!sContext) {
+        SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
+        return false;
+    }
+
+    if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
+        SkDebugf("setupDstTexture: copy failed.\n");
+        return false;
+    }
+
+    GrTextureProxy* copyProxy = sContext->asTextureProxy();
+    // MDB TODO: remove this instantiation once DstTexture is proxy-backed
+    sk_sp<GrTexture> copy(sk_ref_sp(copyProxy->instantiate(fContext->resourceProvider())));
     if (!copy) {
-        SkDebugf("Failed to create temporary copy of destination texture.\n");
-        return;
+        SkDebugf("setupDstTexture: instantiation of copied texture failed.\n");
+        return false;
     }
 
-    this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
     dstTexture->setTexture(std::move(copy));
     dstTexture->setOffset(dstOffset);
+    return true;
 }
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index fe32faf..8feec78 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -469,12 +469,13 @@
     uint32_t addLegacyMeshDrawOp(GrPipelineBuilder&&, const GrClip&,
                                  std::unique_ptr<GrLegacyMeshDrawOp>);
 
-    // Makes a copy of the dst if it is necessary for the draw and returns the texture that should
-    // be used by GrXferProcessor to access the destination color. If the texture is nullptr then
-    // a texture copy could not be made.
-    void setupDstTexture(GrRenderTarget*, const GrClip&, const SkRect& opBounds,
-                         GrXferProcessor::DstTexture*);
-
+    // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
+    // be used by GrXferProcessor to access the destination color in 'result'. If the return
+    // value is false then a texture copy could not be made.
+    bool SK_WARN_UNUSED_RESULT setupDstTexture(GrRenderTargetProxy*,
+                                               const GrClip&,
+                                               const SkRect& opBounds,
+                                               GrXferProcessor::DstTexture* result);
 
     GrRenderTargetOpList* getOpList();
 
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index daf0322..a003c12 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -236,11 +236,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrRenderTargetOpList::copySurface(GrSurface* dst,
-                                       GrSurface* src,
+bool GrRenderTargetOpList::copySurface(GrResourceProvider* resourceProvider,
+                                       GrSurfaceProxy* dst,
+                                       GrSurfaceProxy* src,
                                        const SkIRect& srcRect,
                                        const SkIPoint& dstPoint) {
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
+    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(resourceProvider, dst, src, srcRect, dstPoint);
     if (!op) {
         return false;
     }
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index 8e00df8..7e26490 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -98,8 +98,9 @@
      * depending on the type of surface, configs, etc, and the backend-specific
      * limitations.
      */
-    bool copySurface(GrSurface* dst,
-                     GrSurface* src,
+    bool copySurface(GrResourceProvider* resourceProvider,
+                     GrSurfaceProxy* dst,
+                     GrSurfaceProxy* src,
                      const SkIRect& srcRect,
                      const SkIPoint& dstPoint);
 
diff --git a/src/gpu/GrTextureContext.cpp b/src/gpu/GrTextureContext.cpp
index f946290..ca6f7a2 100644
--- a/src/gpu/GrTextureContext.cpp
+++ b/src/gpu/GrTextureContext.cpp
@@ -84,20 +84,9 @@
     fContext->contextPriv().flushSurfaceWrites(srcProxy);
 #endif
 
-    // TODO: defer instantiation until flush time
-    sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
-    if (!src) {
-        return false;
-    }
-
-    // TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
-    sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
-    if (!tex) {
-        return false;
-    }
-
     GrTextureOpList* opList = this->getOpList();
-    bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
+    bool result = opList->copySurface(fContext->resourceProvider(),
+                                      fTextureProxy.get(), srcProxy, srcRect, dstPoint);
 
 #ifndef ENABLE_MDB
     GrOpFlushState flushState(fContext->getGpu(), nullptr);
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 668e8a3..d2d9226 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -76,11 +76,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrTextureOpList::copySurface(GrSurface* dst,
-                                  GrSurface* src,
+bool GrTextureOpList::copySurface(GrResourceProvider* resourceProvider,
+                                  GrSurfaceProxy* dst,
+                                  GrSurfaceProxy* src,
                                   const SkIRect& srcRect,
                                   const SkIPoint& dstPoint) {
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(dst, src, srcRect, dstPoint);
+    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(resourceProvider, dst, src, srcRect, dstPoint);
     if (!op) {
         return false;
     }
diff --git a/src/gpu/GrTextureOpList.h b/src/gpu/GrTextureOpList.h
index 954289c..22828fd 100644
--- a/src/gpu/GrTextureOpList.h
+++ b/src/gpu/GrTextureOpList.h
@@ -52,8 +52,9 @@
      * depending on the type of surface, configs, etc, and the backend-specific
      * limitations.
      */
-    bool copySurface(GrSurface* dst,
-                     GrSurface* src,
+    bool copySurface(GrResourceProvider* resourceProvider,
+                     GrSurfaceProxy* dst,
+                     GrSurfaceProxy* src,
                      const SkIRect& srcRect,
                      const SkIPoint& dstPoint);
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 6b3e3a7..bc894c3 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -11,6 +11,7 @@
 #include "GrGLRenderTarget.h"
 #include "GrGLTexture.h"
 #include "GrShaderCaps.h"
+#include "GrSurfaceProxyPriv.h"
 #include "SkTSearch.h"
 #include "SkTSort.h"
 #include "instanced/GLInstancedRendering.h"
@@ -2071,7 +2072,7 @@
 #endif
 }
 
-bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc,
+bool GrGLCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
                                   bool* rectsMustMatch, bool* disallowSubrect) const {
     // By default, we don't require rects to match.
     *rectsMustMatch = false;
@@ -2081,17 +2082,22 @@
 
     // If the src is a texture, we can implement the blit as a draw assuming the config is
     // renderable.
-    if (src->asTexture() && this->isConfigRenderable(src->config(), false)) {
-        desc->fOrigin = kDefault_GrSurfaceOrigin;
+    if (src->asTextureProxy() && this->isConfigRenderable(src->config(), false)) {
+        desc->fOrigin = kBottomLeft_GrSurfaceOrigin;
         desc->fFlags = kRenderTarget_GrSurfaceFlag;
         desc->fConfig = src->config();
         return true;
     }
 
-    const GrGLTexture* srcTexture = static_cast<const GrGLTexture*>(src->asTexture());
-    if (srcTexture && srcTexture->target() != GR_GL_TEXTURE_2D) {
-        // Not supported for FBO blit or CopyTexSubImage
-        return false;
+    {
+        // The only way we could see a non-GR_GL_TEXTURE_2D texture would be if it were
+        // wrapped. In that case the proxy would already be instantiated.
+        const GrTexture* srcTexture = src->priv().peekTexture();
+        const GrGLTexture* glSrcTexture = static_cast<const GrGLTexture*>(srcTexture);
+        if (glSrcTexture && glSrcTexture->target() != GR_GL_TEXTURE_2D) {
+            // Not supported for FBO blit or CopyTexSubImage
+            return false;
+        }
     }
 
     // We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
@@ -2130,18 +2136,20 @@
         return false;
     }
 
-    const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src);
-    if (srcRT->renderFBOID() != srcRT->textureFBOID()) {
-        // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or
-        // fail.
-        if (this->canConfigBeFBOColorAttachment(src->config())) {
-            desc->fOrigin = originForBlitFramebuffer;
-            desc->fConfig = src->config();
-            *rectsMustMatch = rectsMustMatchForBlitFramebuffer;
-            *disallowSubrect = disallowSubrectForBlitFramebuffer;
-            return true;
+    {
+        bool srcIsMSAARenderbuffer = src->desc().fSampleCnt > 0 && this->usesMSAARenderBuffers();
+        if (srcIsMSAARenderbuffer) {
+            // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO
+            // blit or fail.
+            if (this->canConfigBeFBOColorAttachment(src->config())) {
+                desc->fOrigin = originForBlitFramebuffer;
+                desc->fConfig = src->config();
+                *rectsMustMatch = rectsMustMatchForBlitFramebuffer;
+                *disallowSubrect = disallowSubrectForBlitFramebuffer;
+                return true;
+            }
+            return false;
         }
-        return false;
     }
 
     // We'll do a CopyTexSubImage. Make the dst a plain old texture.
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index b8c4745..7439711 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -359,8 +359,8 @@
         return fRGBAToBGRAReadbackConversionsAreSlow;
     }
 
-    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch,
-                            bool* disallowSubrect) const override;
+    bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
+                            bool* rectsMustMatch, bool* disallowSubrect) const override;
 
 private:
     enum ExternalFormatUsage {
diff --git a/src/gpu/ops/GrCopySurfaceOp.cpp b/src/gpu/ops/GrCopySurfaceOp.cpp
index 87c490b..5feed18 100644
--- a/src/gpu/ops/GrCopySurfaceOp.cpp
+++ b/src/gpu/ops/GrCopySurfaceOp.cpp
@@ -8,12 +8,12 @@
 #include "GrCopySurfaceOp.h"
 
 // returns true if the read/written rect intersects the src/dst and false if not.
-bool GrCopySurfaceOp::ClipSrcRectAndDstPoint(const GrSurface* dst,
-                                             const GrSurface* src,
-                                             const SkIRect& srcRect,
-                                             const SkIPoint& dstPoint,
-                                             SkIRect* clippedSrcRect,
-                                             SkIPoint* clippedDstPoint) {
+static bool clip_src_rect_and_dst_point(const GrSurfaceProxy* dst,
+                                        const GrSurfaceProxy* src,
+                                        const SkIRect& srcRect,
+                                        const SkIPoint& dstPoint,
+                                        SkIRect* clippedSrcRect,
+                                        SkIPoint* clippedDstPoint) {
     *clippedSrcRect = srcRect;
     *clippedDstPoint = dstPoint;
 
@@ -58,21 +58,37 @@
     return !clippedSrcRect->isEmpty();
 }
 
-std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrResourceProvider* resourceProvider,
+                                            GrSurfaceProxy* dstProxy, GrSurfaceProxy* srcProxy,
+                                            const SkIRect& srcRect,
                                             const SkIPoint& dstPoint) {
-    SkASSERT(dst);
-    SkASSERT(src);
-    if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
+    SkASSERT(dstProxy);
+    SkASSERT(srcProxy);
+    if (GrPixelConfigIsSint(dstProxy->config()) != GrPixelConfigIsSint(srcProxy->config())) {
         return nullptr;
     }
-    if (GrPixelConfigIsCompressed(dst->config())) {
+    if (GrPixelConfigIsCompressed(dstProxy->config())) {
         return nullptr;
     }
     SkIRect clippedSrcRect;
     SkIPoint clippedDstPoint;
-    // If the rect is outside the src or dst then we've already succeeded.
-    if (!ClipSrcRectAndDstPoint(dst, src, srcRect, dstPoint, &clippedSrcRect, &clippedDstPoint)) {
+    // If the rect is outside the srcProxy or dstProxy then we've already succeeded.
+    if (!clip_src_rect_and_dst_point(dstProxy, srcProxy, srcRect, dstPoint,
+                                     &clippedSrcRect, &clippedDstPoint)) {
         return nullptr;
     }
-    return std::unique_ptr<GrOp>(new GrCopySurfaceOp(dst, src, clippedSrcRect, clippedDstPoint));
+
+    // MDB TODO: remove this instantiation
+    GrSurface* dstTex = dstProxy->instantiate(resourceProvider);
+    if (!dstTex) {
+        return nullptr;
+    }
+    GrSurface* srcTex = srcProxy->instantiate(resourceProvider);
+    if (!srcTex) {
+        return nullptr;
+    }
+
+    return std::unique_ptr<GrOp>(new GrCopySurfaceOp(dstTex, srcTex,
+                                                     dstProxy->uniqueID(), srcProxy->uniqueID(),
+                                                     clippedSrcRect, clippedDstPoint));
 }
diff --git a/src/gpu/ops/GrCopySurfaceOp.h b/src/gpu/ops/GrCopySurfaceOp.h
index 4c4500b..05ee8d0 100644
--- a/src/gpu/ops/GrCopySurfaceOp.h
+++ b/src/gpu/ops/GrCopySurfaceOp.h
@@ -8,45 +8,44 @@
 #ifndef GrCopySurfaceOp_DEFINED
 #define GrCopySurfaceOp_DEFINED
 
-#include "GrGpu.h"
 #include "GrOp.h"
 #include "GrOpFlushState.h"
-#include "GrRenderTarget.h"
 
 class GrCopySurfaceOp final : public GrOp {
 public:
     DEFINE_OP_CLASS_ID
 
-    /** This should not really be exposed as Create() will apply this clipping, but there is
-     *  currently a workaround in GrContext::copySurface() for non-render target dsts that relies
-     *  on it. */
-    static bool ClipSrcRectAndDstPoint(const GrSurface* dst,
-                                       const GrSurface* src,
-                                       const SkIRect& srcRect,
-                                       const SkIPoint& dstPoint,
-                                       SkIRect* clippedSrcRect,
-                                       SkIPoint* clippedDstPoint);
-
-    static std::unique_ptr<GrOp> Make(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+    // MDB TODO: remove the resourceProvider parameter
+    static std::unique_ptr<GrOp> Make(GrResourceProvider*,
+                                      GrSurfaceProxy* dst, GrSurfaceProxy* src,
+                                      const SkIRect& srcRect,
                                       const SkIPoint& dstPoint);
 
     const char* name() const override { return "CopySurface"; }
 
     SkString dumpInfo() const override {
         SkString string;
-        string.printf(
-                "SRC: 0x%p, DST: 0x%p, SRECT: [L: %d, T: %d, R: %d, B: %d], "
-                "DPT:[X: %d, Y: %d]",
-                fDst.get(), fSrc.get(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight,
-                fSrcRect.fBottom, fDstPoint.fX, fDstPoint.fY);
+        string.printf("src: (proxyID: %d, rtID: %d), dst: (proxyID: %d, rtID: %d), "
+                      "srcRect: [L: %d, T: %d, R: %d, B: %d], dstPt: [X: %d, Y: %d]",
+                      fSrcProxyID.asUInt(), fSrc.get()->uniqueID().asUInt(),
+                      fDstProxyID.asUInt(), fDst.get()->uniqueID().asUInt(),
+                      fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom,
+                      fDstPoint.fX, fDstPoint.fY);
         string.append(INHERITED::dumpInfo());
         return string;
     }
 
 private:
-    GrCopySurfaceOp(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                    const SkIPoint& dstPoint)
-            : INHERITED(ClassID()), fDst(dst), fSrc(src), fSrcRect(srcRect), fDstPoint(dstPoint) {
+    GrCopySurfaceOp(GrSurface* dst, GrSurface* src,
+                    GrSurfaceProxy::UniqueID dstID, GrSurfaceProxy::UniqueID srcID,
+                    const SkIRect& srcRect, const SkIPoint& dstPoint)
+            : INHERITED(ClassID())
+            , fDstProxyID(dstID)
+            , fSrcProxyID(srcID)
+            , fDst(dst)
+            , fSrc(src)
+            , fSrcRect(srcRect)
+            , fDstPoint(dstPoint) {
         SkRect bounds =
                 SkRect::MakeXYWH(SkIntToScalar(dstPoint.fX), SkIntToScalar(dstPoint.fY),
                                  SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
@@ -67,10 +66,14 @@
         }
     }
 
+    // MDB TODO: remove the proxy IDs once the GrSurfaceProxy carries the ref since they will
+    // be redundant
+    GrSurfaceProxy::UniqueID                        fDstProxyID;
+    GrSurfaceProxy::UniqueID                        fSrcProxyID;
     GrPendingIOResource<GrSurface, kWrite_GrIOType> fDst;
-    GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
-    SkIRect fSrcRect;
-    SkIPoint fDstPoint;
+    GrPendingIOResource<GrSurface, kRead_GrIOType>  fSrc;
+    SkIRect                                         fSrcRect;
+    SkIPoint                                        fDstPoint;
 
     typedef GrOp INHERITED;
 };
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index bf7e5ad..4f05b4f 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -6,7 +6,7 @@
  */
 
 #include "GrVkCaps.h"
-#include "GrRenderTarget.h"
+#include "GrRenderTargetProxy.h"
 #include "GrShaderCaps.h"
 #include "GrVkUtil.h"
 #include "vk/GrVkBackendContext.h"
@@ -53,7 +53,7 @@
     this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags);
 }
 
-bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc,
+bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
                                   bool* rectsMustMatch, bool* disallowSubrect) const {
     // Vk doesn't use rectsMustMatch or disallowSubrect. Always return false.
     *rectsMustMatch = false;
@@ -64,7 +64,7 @@
     // render target as well.
     desc->fOrigin = src->origin();
     desc->fConfig = src->config();
-    if (src->numColorSamples() > 1 || (src->asTexture() && this->supportsCopiesAsDraws())) {
+    if (src->numColorSamples() > 1 || (src->asTextureProxy() && this->supportsCopiesAsDraws())) {
         desc->fFlags = kRenderTarget_GrSurfaceFlag;
     } else {
         // Just going to use CopyImage here
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index dce9ce2..e7ffe05 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -104,8 +104,8 @@
         return fPreferedStencilFormat;
     }
 
-    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch,
-                            bool* disallowSubrect) const override;
+    bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
+                            bool* rectsMustMatch, bool* disallowSubrect) const override;
 
 private:
     enum VkVendor {