Move GrDrawOp pipeline/clip processing to GrRenderTargetContext

This is currently done in GrOpList. However, it can trigger resource creation, which in turn can trigger a flush. In the future flushing may destroy the op list.

Change-Id: I21cb1e10060bf31c95431c0511fcfff637cd6498
Reviewed-on: https://skia-review.googlesource.com/9304
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 7c1ad9d..4cab21f 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -27,7 +27,6 @@
   "$_include/gpu/GrProgramElement.h",
   "$_include/gpu/GrGpuResourceRef.h",
   "$_include/gpu/GrRenderTarget.h",
-  "$_include/gpu/GrRenderTargetContext.h",
   "$_include/gpu/GrResourceKey.h",
   "$_include/gpu/GrShaderCaps.h",
   "$_include/gpu/GrShaderVar.h",
@@ -162,6 +161,7 @@
   "$_src/gpu/GrReducedClip.cpp",
   "$_src/gpu/GrReducedClip.h",
   "$_src/gpu/GrRenderTargetContext.cpp",
+  "$_src/gpu/GrRenderTargetContext.h",
   "$_src/gpu/GrRenderTargetContextPriv.h",
   "$_src/gpu/GrPathRenderingRenderTargetContext.cpp",
   "$_src/gpu/GrPathRenderingRenderTargetContext.h",
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index 23f870d..239d4a4 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -17,7 +17,7 @@
 #include "SkString.h"
 
 struct GrContextOptions;
-
+class GrRenderTarget;
 
 /**
  * Represents the capabilities of a GrContext.
@@ -185,6 +185,14 @@
     bool fenceSyncSupport() const { return fFenceSyncSupport; }
     bool crossContextTextureSupport() const { return fCrossContextTextureSupport; }
 
+    /**
+     * This is can be called before allocating a texture to be a dst for copySurface. This is only
+     * used for doing dst copies needed in blends, thus the src is always a GrRenderTarget. It will
+     * populate the origin, config, and flags fields of the desc such that copySurface can
+     * efficiently succeed.
+     */
+    virtual bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const = 0;
+
 protected:
     /** Subclasses must call this at the end of their constructors in order to apply caps
         overrides requested by the client. Note that overrides will only reduce the caps never
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 5b69ead..ed77fcd 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -307,14 +307,6 @@
                         GrPixelConfig config, GrBuffer* transferBuffer,
                         size_t offset, size_t rowBytes, GrFence* fence);
 
-    /**
-     * This is can be called before allocating a texture to be a dst for copySurface. This is only
-     * used for doing dst copies needed in blends, thus the src is always a GrRenderTarget. It will
-     * populate the origin, config, and flags fields of the desc such that copySurface can
-     * efficiently succeed.
-     */
-    virtual bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const = 0;
-
     // After the client interacts directly with the 3D context state the GrGpu
     // must resync its internal state and assumptions about 3D context state.
     // Each time this occurs the GrGpu bumps a timestamp.
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1ddf8df..bae2ea6 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -6,8 +6,8 @@
  */
 
 #include "GrRenderTargetContext.h"
+#include "GrAppliedClip.h"
 #include "GrColor.h"
-#include "GrDrawOpTest.h"
 #include "GrDrawingManager.h"
 #include "GrFixedClip.h"
 #include "GrGpuResourcePriv.h"
@@ -17,9 +17,14 @@
 #include "GrRenderTargetContextPriv.h"
 #include "GrRenderTargetPriv.h"
 #include "GrResourceProvider.h"
+#include "GrStencilAttachment.h"
+#include "SkLatticeIter.h"
+#include "SkMatrixPriv.h"
 #include "SkSurfacePriv.h"
-
+#include "effects/GrRRectEffect.h"
+#include "instanced/InstancedRendering.h"
 #include "ops/GrClearOp.h"
+#include "ops/GrDrawOp.h"
 #include "ops/GrDrawAtlasOp.h"
 #include "ops/GrDrawVerticesOp.h"
 #include "ops/GrLatticeOp.h"
@@ -28,20 +33,11 @@
 #include "ops/GrRectOpFactory.h"
 #include "ops/GrRegionOp.h"
 #include "ops/GrShadowRRectOp.h"
-
-#include "effects/GrRRectEffect.h"
-
-#include "instanced/InstancedRendering.h"
-
+#include "ops/GrStencilPathOp.h"
 #include "text/GrAtlasTextContext.h"
 #include "text/GrStencilAndCoverTextContext.h"
-
 #include "../private/GrAuditTrail.h"
 
-#include "SkGr.h"
-#include "SkLatticeIter.h"
-#include "SkMatrixPriv.h"
-
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
 #define ASSERT_SINGLE_OWNER \
     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
@@ -523,7 +519,7 @@
             if (ss) {
                 pipelineBuilder.setUserStencil(ss);
             }
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return true;
         }
     }
@@ -540,7 +536,7 @@
                 if (ss) {
                     pipelineBuilder.setUserStencil(ss);
                 }
-                this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+                this->addDrawOp(pipelineBuilder, clip, std::move(op));
                 return true;
             }
         }
@@ -663,7 +659,7 @@
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
             pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -699,9 +695,55 @@
                                             GrAAType aaType,
                                             const SkMatrix& viewMatrix,
                                             const GrPath* path) {
+    ASSERT_SINGLE_OWNER_PRIV
+    RETURN_IF_ABANDONED_PRIV
+    SkDEBUGCODE(fRenderTargetContext->validate();)
+    GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
+                              "GrRenderTargetContext::stencilPath");
+
     SkASSERT(aaType != GrAAType::kCoverage);
-    fRenderTargetContext->getOpList()->stencilPath(fRenderTargetContext, clip, aaType, viewMatrix,
-                                                   path);
+
+    bool useHWAA = GrAATypeIsHW(aaType);
+    // TODO: extract portions of checkDraw that are relevant to path stenciling.
+    SkASSERT(path);
+    SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
+
+    // FIXME: Use path bounds instead of this WAR once
+    // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
+    SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
+
+    // Setup clip
+    GrAppliedClip appliedClip(bounds);
+    if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
+                    &appliedClip)) {
+        return;
+    }
+
+    // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
+    // attempt this in a situation that would require coverage AA.
+    SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
+
+    GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
+    if (!rt) {
+        return;
+    }
+    GrStencilAttachment* stencilAttachment =
+            fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
+    if (!stencilAttachment) {
+        SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
+        return;
+    }
+
+    std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
+                                                     useHWAA,
+                                                     path->getFillType(),
+                                                     appliedClip.hasStencilClip(),
+                                                     stencilAttachment->bits(),
+                                                     appliedClip.scissorState(),
+                                                     fRenderTargetContext->accessRenderTarget(),
+                                                     path);
+    op->setClippedBounds(appliedClip.clippedDrawBounds());
+    fRenderTargetContext->getOpList()->recordOp(std::move(op), fRenderTargetContext);
 }
 
 void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
@@ -779,7 +821,7 @@
                                                     &aaType));
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -838,7 +880,7 @@
                                                     &aaType));
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -854,7 +896,7 @@
         std::unique_ptr<GrDrawOp> op =
                 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
         GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-        this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+        this->addDrawOp(pipelineBuilder, clip, std::move(op));
         return;
     }
 
@@ -904,7 +946,7 @@
         return;
     }
     GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 void GrRenderTargetContext::drawVertices(const GrClip& clip,
@@ -926,7 +968,7 @@
         return;
     }
     GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -948,7 +990,7 @@
     std::unique_ptr<GrDrawOp> op =
             GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
     GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -993,7 +1035,7 @@
                                                      fInstancedPipelineInfo, &aaType));
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, *clip, std::move(op));
             return;
         }
     }
@@ -1009,7 +1051,7 @@
                                                                     shaderCaps);
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, *clip, std::move(op));
             return;
         }
     }
@@ -1047,7 +1089,7 @@
                                                          blurRadius, stroke, shaderCaps);
     if (op) {
         GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-        this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+        this->addDrawOp(pipelineBuilder, clip, std::move(op));
         return;
     }
 }
@@ -1071,7 +1113,7 @@
                                                       &aaType));
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return true;
         }
     }
@@ -1191,7 +1233,7 @@
 
     std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
     GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 void GrRenderTargetContext::drawOval(const GrClip& clip,
@@ -1222,7 +1264,7 @@
                                                     fInstancedPipelineInfo, &aaType));
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -1234,7 +1276,7 @@
                 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -1274,7 +1316,7 @@
                                                                   shaderCaps);
         if (op) {
             GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-            this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+            this->addDrawOp(pipelineBuilder, clip, std::move(op));
             return;
         }
     }
@@ -1302,7 +1344,7 @@
                                                           imageHeight, std::move(iter), dst);
 
     GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 void GrRenderTargetContext::prepareForExternalIO() {
@@ -1339,7 +1381,7 @@
     if (ss) {
         pipelineBuilder.setUserStencil(ss);
     }
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    this->addDrawOp(pipelineBuilder, clip, std::move(op));
 }
 
 // Can 'path' be drawn as a pair of filled nested rectangles?
@@ -1419,7 +1461,7 @@
                         GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
                 if (op) {
                     GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-                    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+                    this->addDrawOp(pipelineBuilder, clip, std::move(op));
                 }
                 return;
             }
@@ -1433,7 +1475,7 @@
                     paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
             if (op) {
                 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
-                this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+                this->addDrawOp(pipelineBuilder, clip, std::move(op));
                 return;
             }
         }
@@ -1605,6 +1647,32 @@
     pr->drawPath(args);
 }
 
+static void op_bounds(SkRect* bounds, const GrOp* op) {
+    *bounds = op->bounds();
+    if (op->hasZeroArea()) {
+        if (op->hasAABloat()) {
+            bounds->outset(0.5f, 0.5f);
+        } else {
+            // We don't know which way the particular GPU will snap lines or points at integer
+            // coords. So we ensure that the bounds is large enough for either snap.
+            SkRect before = *bounds;
+            bounds->roundOut(bounds);
+            if (bounds->fLeft == before.fLeft) {
+                bounds->fLeft -= 1;
+            }
+            if (bounds->fTop == before.fTop) {
+                bounds->fTop -= 1;
+            }
+            if (bounds->fRight == before.fRight) {
+                bounds->fRight += 1;
+            }
+            if (bounds->fBottom == before.fBottom) {
+                bounds->fBottom += 1;
+            }
+        }
+    }
+}
+
 void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
                                       std::unique_ptr<GrDrawOp> op) {
     ASSERT_SINGLE_OWNER
@@ -1612,5 +1680,99 @@
     SkDEBUGCODE(this->validate();)
     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
 
-    this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
+    // Setup clip
+    SkRect bounds;
+    op_bounds(&bounds, op.get());
+    GrAppliedClip appliedClip(bounds);
+    if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
+                    pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
+        return;
+    }
+
+    // This forces instantiation of the render target. Pipeline creation is moving to flush time
+    // by which point instantiation must have occurred anyway.
+    GrRenderTarget* rt = this->accessRenderTarget();
+    if (!rt) {
+        return;
+    }
+
+    GrResourceProvider* resourceProvider = fContext->resourceProvider();
+    if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
+        if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
+            SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
+            return;
+        }
+    }
+
+    GrProcessorSet::FragmentProcessorAnalysis analysis;
+    op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps());
+
+    GrPipeline::InitArgs args;
+    pipelineBuilder.getPipelineInitArgs(&args);
+    args.fAppliedClip = &appliedClip;
+    args.fRenderTarget = rt;
+    args.fCaps = this->caps();
+    args.fAnalysis = &analysis;
+
+    if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
+        this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
+        if (!args.fDstTexture.texture()) {
+            return;
+        }
+    }
+    op->initPipeline(args);
+    // TODO: We need to add pipeline dependencies on textures, etc before recording this op.
+    op->setClippedBounds(appliedClip.clippedDrawBounds());
+    this->getOpList()->addOp(std::move(op), this);
+}
+
+void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
+                                            const SkRect& opBounds,
+                                            GrXferProcessor::DstTexture* dstTexture) {
+    if (this->caps()->textureBarrierSupport()) {
+        if (GrTexture* rtTex = rt->asTexture()) {
+            // 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->setOffset(0, 0);
+            return;
+        }
+    }
+
+    SkIRect copyRect;
+    clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
+
+    SkIRect drawIBounds;
+    opBounds.roundOut(&drawIBounds);
+    if (!copyRect.intersect(drawIBounds)) {
+#ifdef SK_DEBUG
+        GrCapsDebugf(this->caps(), "Missed an early reject. "
+                                   "Bailing on draw from setupDstTexture.\n");
+#endif
+        return;
+    }
+
+    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
+    // have per-sample dst values by making the copy multisampled.
+    GrSurfaceDesc desc;
+    if (!this->caps()->initDescForDstCopy(rt, &desc)) {
+        desc.fOrigin = kDefault_GrSurfaceOrigin;
+        desc.fFlags = kRenderTarget_GrSurfaceFlag;
+        desc.fConfig = rt->config();
+    }
+
+    desc.fWidth = copyRect.width();
+    desc.fHeight = copyRect.height();
+
+    static const uint32_t kFlags = 0;
+    sk_sp<GrTexture> copy(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
+
+    if (!copy) {
+        SkDebugf("Failed to create temporary copy of destination texture.\n");
+        return;
+    }
+    SkIPoint dstPoint = {0, 0};
+    this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
+    dstTexture->setTexture(std::move(copy));
+    dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
 }
diff --git a/include/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
similarity index 97%
rename from include/gpu/GrRenderTargetContext.h
rename to src/gpu/GrRenderTargetContext.h
index f976e8e..d711c81 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -12,6 +12,7 @@
 #include "GrContext.h"
 #include "GrPaint.h"
 #include "GrSurfaceContext.h"
+#include "GrXferProcessor.h"
 #include "SkRefCnt.h"
 #include "SkSurfaceProps.h"
 #include "../private/GrInstancedPipelineInfo.h"
@@ -471,9 +472,17 @@
     bool onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
                        size_t srcRowBytes, int x, int y, uint32_t flags) override;
 
-    // This entry point allows the GrTextContext-derived classes to add their ops to the GrOpList.
+    // This performs processing specific to GrDrawOp-derived ops before recording them into the
+    // op list.
     void addDrawOp(const GrPipelineBuilder&, const GrClip&, std::unique_ptr<GrDrawOp>);
 
+    // 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*);
+
+
     GrRenderTargetOpList* getOpList();
 
     sk_sp<GrRenderTargetProxy>        fRenderTargetProxy;
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 2b05a16..2c28406 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -6,35 +6,17 @@
  */
 
 #include "GrRenderTargetOpList.h"
-
-#include "GrAppliedClip.h"
 #include "GrAuditTrail.h"
 #include "GrCaps.h"
-#include "GrRenderTargetContext.h"
 #include "GrGpu.h"
 #include "GrGpuCommandBuffer.h"
-#include "GrPath.h"
-#include "GrPipeline.h"
-#include "GrMemoryPool.h"
-#include "GrPipelineBuilder.h"
 #include "GrRenderTarget.h"
+#include "GrRenderTargetContext.h"
 #include "GrResourceProvider.h"
-#include "GrRenderTargetPriv.h"
-#include "GrStencilAttachment.h"
-#include "GrSurfacePriv.h"
-#include "GrTexture.h"
-
-#include "SkStrokeRec.h"
-
 #include "ops/GrClearOp.h"
 #include "ops/GrClearStencilClipOp.h"
 #include "ops/GrCopySurfaceOp.h"
 #include "ops/GrDiscardOp.h"
-#include "ops/GrDrawOp.h"
-#include "ops/GrDrawPathOp.h"
-#include "ops/GrRectOpFactory.h"
-#include "ops/GrStencilPathOp.h"
-
 #include "instanced/InstancedRendering.h"
 
 using gr_instanced::InstancedRendering;
@@ -52,8 +34,6 @@
     , fGpu(SkRef(gpu))
     , fResourceProvider(resourceProvider)
     , fLastClipStackGenID(SK_InvalidUniqueID) {
-    // TODO: Stop extracting the context (currently needed by GrClip)
-    fContext = fGpu->getContext();
 
     fMaxOpLookback = (options.fMaxOpCombineLookback < 0) ? kDefaultMaxOpLookback
                                                          : options.fMaxOpCombineLookback;
@@ -92,58 +72,6 @@
 }
 #endif
 
-void GrRenderTargetOpList::setupDstTexture(GrRenderTarget* rt,
-                                           const GrClip& clip,
-                                           const SkRect& opBounds,
-                                           GrXferProcessor::DstTexture* dstTexture) {
-    if (this->caps()->textureBarrierSupport()) {
-        if (GrTexture* rtTex = rt->asTexture()) {
-            // 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->setOffset(0, 0);
-            return;
-        }
-    }
-
-    SkIRect copyRect;
-    clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
-
-    SkIRect drawIBounds;
-    opBounds.roundOut(&drawIBounds);
-    if (!copyRect.intersect(drawIBounds)) {
-#ifdef SK_DEBUG
-        GrCapsDebugf(this->caps(), "Missed an early reject. "
-                                   "Bailing on draw from setupDstTexture.\n");
-#endif
-        return;
-    }
-
-    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
-    // have per-sample dst values by making the copy multisampled.
-    GrSurfaceDesc desc;
-    if (!fGpu->initDescForDstCopy(rt, &desc)) {
-        desc.fOrigin = kDefault_GrSurfaceOrigin;
-        desc.fFlags = kRenderTarget_GrSurfaceFlag;
-        desc.fConfig = rt->config();
-    }
-
-    desc.fWidth = copyRect.width();
-    desc.fHeight = copyRect.height();
-
-    static const uint32_t kFlags = 0;
-    sk_sp<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
-
-    if (!copy) {
-        SkDebugf("Failed to create temporary copy of destination texture.\n");
-        return;
-    }
-    SkIPoint dstPoint = {0, 0};
-    this->copySurface(copy.get(), rt, copyRect, dstPoint);
-    dstTexture->setTexture(std::move(copy));
-    dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
-}
-
 void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
     // Semi-usually the GrOpLists are already closed at this point, but sometimes Ganesh
     // needs to flush mid-draw. In that case, the SkGpuDevice's GrOpLists won't be closed
@@ -216,152 +144,19 @@
 }
 
 void GrRenderTargetOpList::abandonGpuResources() {
-    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+    if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
         InstancedRendering* ir = this->instancedRendering();
         ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
     }
 }
 
 void GrRenderTargetOpList::freeGpuResources() {
-    if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
+    if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
         InstancedRendering* ir = this->instancedRendering();
         ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
     }
 }
 
-static void op_bounds(SkRect* bounds, const GrOp* op) {
-    *bounds = op->bounds();
-    if (op->hasZeroArea()) {
-        if (op->hasAABloat()) {
-            bounds->outset(0.5f, 0.5f);
-        } else {
-            // We don't know which way the particular GPU will snap lines or points at integer
-            // coords. So we ensure that the bounds is large enough for either snap.
-            SkRect before = *bounds;
-            bounds->roundOut(bounds);
-            if (bounds->fLeft == before.fLeft) {
-                bounds->fLeft -= 1;
-            }
-            if (bounds->fTop == before.fTop) {
-                bounds->fTop -= 1;
-            }
-            if (bounds->fRight == before.fRight) {
-                bounds->fRight += 1;
-            }
-            if (bounds->fBottom == before.fBottom) {
-                bounds->fBottom += 1;
-            }
-        }
-    }
-}
-
-void GrRenderTargetOpList::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
-                                     GrRenderTargetContext* renderTargetContext,
-                                     const GrClip& clip,
-                                     std::unique_ptr<GrDrawOp> op) {
-    // Setup clip
-    SkRect bounds;
-    op_bounds(&bounds, op.get());
-    GrAppliedClip appliedClip(bounds);
-    if (!clip.apply(fContext, renderTargetContext, pipelineBuilder.isHWAntialias(),
-                    pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
-        return;
-    }
-
-    if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
-        if (!renderTargetContext->accessRenderTarget()) {
-            return;
-        }
-
-        if (!fResourceProvider->attachStencilAttachment(
-                renderTargetContext->accessRenderTarget())) {
-            SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
-            return;
-        }
-    }
-
-    GrProcessorSet::FragmentProcessorAnalysis analysis;
-    op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps());
-
-    GrPipeline::InitArgs args;
-    pipelineBuilder.getPipelineInitArgs(&args);
-    args.fAppliedClip = &appliedClip;
-    // This forces instantiation of the render target. Pipeline creation is moving to flush time
-    // by which point instantiation must have occurred anyway.
-    args.fRenderTarget = renderTargetContext->accessRenderTarget();
-    if (!args.fRenderTarget) {
-        return;
-    }
-    args.fCaps = this->caps();
-    args.fAnalysis = &analysis;
-
-    if (!renderTargetContext->accessRenderTarget()) {
-        return;
-    }
-
-    if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
-        this->setupDstTexture(renderTargetContext->accessRenderTarget(), clip, bounds,
-                              &args.fDstTexture);
-        if (!args.fDstTexture.texture()) {
-            return;
-        }
-    }
-    op->initPipeline(args);
-
-#ifdef ENABLE_MDB
-    SkASSERT(fSurface);
-    op->pipeline()->addDependenciesTo(fSurface);
-#endif
-    op->setClippedBounds(appliedClip.clippedDrawBounds());
-    this->recordOp(std::move(op), renderTargetContext);
-}
-
-void GrRenderTargetOpList::stencilPath(GrRenderTargetContext* renderTargetContext,
-                                       const GrClip& clip,
-                                       GrAAType aaType,
-                                       const SkMatrix& viewMatrix,
-                                       const GrPath* path) {
-    bool useHWAA = GrAATypeIsHW(aaType);
-    // TODO: extract portions of checkDraw that are relevant to path stenciling.
-    SkASSERT(path);
-    SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
-
-    // FIXME: Use path bounds instead of this WAR once
-    // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
-    SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
-
-    // Setup clip
-    GrAppliedClip appliedClip(bounds);
-    if (!clip.apply(fContext, renderTargetContext, useHWAA, true, &appliedClip)) {
-        return;
-    }
-
-    // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
-    // attempt this in a situation that would require coverage AA.
-    SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
-
-    if (!renderTargetContext->accessRenderTarget()) {
-        return;
-    }
-    GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(
-                                                renderTargetContext->accessRenderTarget());
-    if (!stencilAttachment) {
-        SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
-        return;
-    }
-
-    std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
-                                                     useHWAA,
-                                                     path->getFillType(),
-                                                     appliedClip.hasStencilClip(),
-                                                     stencilAttachment->bits(),
-                                                     appliedClip.scissorState(),
-                                                     renderTargetContext->accessRenderTarget(),
-                                                     path);
-    op->setClippedBounds(appliedClip.clippedDrawBounds());
-    this->recordOp(std::move(op), renderTargetContext);
-}
-
 void GrRenderTargetOpList::fullClear(GrRenderTargetContext* renderTargetContext, GrColor color) {
     GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
     // Currently this just inserts or updates the last clear op. However, once in MDB this can
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index 36bdc6b..e232547 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -8,19 +8,11 @@
 #ifndef GrRenderTargetOpList_DEFINED
 #define GrRenderTargetOpList_DEFINED
 
-#include "GrClip.h"
-#include "GrContext.h"
 #include "GrOpList.h"
-#include "GrPathProcessor.h"
 #include "GrPrimitiveProcessor.h"
 #include "GrPathRendering.h"
-#include "GrXferProcessor.h"
-
-#include "ops/GrDrawOp.h"
-
 #include "SkClipStack.h"
 #include "SkMatrix.h"
-#include "SkPath.h"
 #include "SkStringUtils.h"
 #include "SkStrokeRec.h"
 #include "SkTArray.h"
@@ -29,10 +21,8 @@
 
 class GrAuditTrail;
 class GrClearOp;
-class GrClip;
 class GrCaps;
-class GrPath;
-class GrDrawPathOpBase;
+class GrClip;
 class GrOp;
 class GrPipelineBuilder;
 class GrRenderTargetProxy;
@@ -77,26 +67,10 @@
      */
     const GrCaps* caps() const { return fGpu->caps(); }
 
-    void addDrawOp(const GrPipelineBuilder&, GrRenderTargetContext*, const GrClip&,
-                   std::unique_ptr<GrDrawOp>);
-
     void addOp(std::unique_ptr<GrOp> op, GrRenderTargetContext* renderTargetContext) {
         this->recordOp(std::move(op), renderTargetContext);
     }
 
-    /**
-     * Draws the path into user stencil bits. Upon return, all user stencil values
-     * inside the path will be nonzero. The path's fill must be either even/odd or
-     * winding (notnverse or hairline).It will respect the HW antialias boolean (if
-     * possible in the 3D API).  Note, we will never have an inverse fill with
-     * stencil path.
-     */
-    void stencilPath(GrRenderTargetContext*,
-                     const GrClip&,
-                     GrAAType aa,
-                     const SkMatrix& viewMatrix,
-                     const GrPath*);
-
     /** Clears the entire render target */
     void fullClear(GrRenderTargetContext*, GrColor color);
 
@@ -136,14 +110,6 @@
 
     void forwardCombine();
 
-    // 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*);
-
     // Used only via GrRenderTargetContextPriv.
     void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTargetContext*);
 
@@ -159,8 +125,6 @@
     GrClearOp* fLastFullClearOp = nullptr;
     GrGpuResource::UniqueID fLastFullClearRenderTargetID = GrGpuResource::UniqueID::InvalidID();
 
-    // The context is only in service of the GrClip, remove once it doesn't need this.
-    GrContext* fContext;
     GrGpu* fGpu;
     GrResourceProvider* fResourceProvider;
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d2e1899..cb0d789 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -5,16 +5,15 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrGLCaps.h"
-
 #include "GrContextOptions.h"
 #include "GrGLContext.h"
 #include "GrGLRenderTarget.h"
+#include "GrGLTexture.h"
 #include "GrShaderCaps.h"
-#include "instanced/GLInstancedRendering.h"
 #include "SkTSearch.h"
 #include "SkTSort.h"
+#include "instanced/GLInstancedRendering.h"
 
 GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
                    const GrGLContextInfo& ctxInfo,
@@ -2068,6 +2067,62 @@
 #endif
 }
 
+bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
+    // 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;
+        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;
+    }
+
+    // We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
+    // possible and we return false to fallback to creating a render target dst for render-to-
+    // texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
+    // creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
+    GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin;
+    if (this->blitFramebufferSupportFlags() & kNoScalingOrMirroring_BlitFramebufferFlag) {
+        originForBlitFramebuffer = src->origin();
+    }
+
+    // Check for format issues with glCopyTexSubImage2D
+    if (this->bgraIsInternalFormat() && kBGRA_8888_GrPixelConfig == src->config()) {
+        // glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit
+        // then we set up for that, otherwise fail.
+        if (this->canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) {
+            desc->fOrigin = originForBlitFramebuffer;
+            desc->fConfig = kBGRA_8888_GrPixelConfig;
+            return true;
+        }
+        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();
+            return true;
+        }
+        return false;
+    }
+
+    // We'll do a CopyTexSubImage. Make the dst a plain old texture.
+    desc->fConfig = src->config();
+    desc->fOrigin = src->origin();
+    desc->fFlags = kNone_GrSurfaceFlags;
+    return true;
+}
+
 void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
     if (options.fEnableInstancedRendering) {
         fInstancedSupport = gr_instanced::GLInstancedRendering::CheckSupport(*this);
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 8a83e02..a659435 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -359,6 +359,8 @@
         return fRGBAToBGRAReadbackConversionsAreSlow;
     }
 
+    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
+
 private:
     enum ExternalFormatUsage {
         kTexImage_ExternalFormatUsage,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index bda1c16..7a811d1 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3464,65 +3464,6 @@
     }
 }
 
-bool GrGLGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
-    // If the src is a texture, we can implement the blit as a draw assuming the config is
-    // renderable.
-    if (src->asTexture() && this->caps()->isConfigRenderable(src->config(), false)) {
-        desc->fOrigin = kDefault_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;
-    }
-
-    // We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
-    // possible and we return false to fallback to creating a render target dst for render-to-
-    // texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
-    // creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
-
-    GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin;
-    if (this->glCaps().blitFramebufferSupportFlags() &
-        GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag) {
-        originForBlitFramebuffer = src->origin();
-    }
-
-    // Check for format issues with glCopyTexSubImage2D
-    if (kGLES_GrGLStandard == this->glStandard() && this->glCaps().bgraIsInternalFormat() &&
-        kBGRA_8888_GrPixelConfig == src->config()) {
-        // glCopyTexSubImage2D doesn't work with this config. If the bgra can be used with fbo blit
-        // then we set up for that, otherwise fail.
-        if (this->glCaps().canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) {
-            desc->fOrigin = originForBlitFramebuffer;
-            desc->fConfig = kBGRA_8888_GrPixelConfig;
-            return true;
-        }
-        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->glCaps().canConfigBeFBOColorAttachment(src->config())) {
-            desc->fOrigin = originForBlitFramebuffer;
-            desc->fConfig = src->config();
-            return true;
-        }
-        return false;
-    }
-
-    // We'll do a CopyTexSubImage. Make the dst a plain old texture.
-    desc->fConfig = src->config();
-    desc->fOrigin = src->origin();
-    desc->fFlags = kNone_GrSurfaceFlags;
-    return true;
-}
-
 bool GrGLGpu::onCopySurface(GrSurface* dst,
                             GrSurface* src,
                             const SkIRect& srcRect,
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 564ed76..6a175d5 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -75,8 +75,6 @@
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override;
 
-    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
-
     // These functions should be used to bind GL objects. They track the GL state and skip redundant
     // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
     void bindVertexArray(GrGLuint id) {
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index fd454ad..16a91c1 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -6,11 +6,11 @@
  */
 
 #include "GrVkCaps.h"
-
+#include "GrRenderTarget.h"
 #include "GrShaderCaps.h"
 #include "GrVkUtil.h"
-#include "vk/GrVkInterface.h"
 #include "vk/GrVkBackendContext.h"
+#include "vk/GrVkInterface.h"
 
 GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
                    VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags)
@@ -52,6 +52,22 @@
     this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags);
 }
 
+bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
+    // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
+    // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
+    // render target as well.
+    desc->fOrigin = src->origin();
+    desc->fConfig = src->config();
+    if (src->numColorSamples() > 1 || (src->asTexture() && this->supportsCopiesAsDraws())) {
+        desc->fFlags = kRenderTarget_GrSurfaceFlag;
+    } else {
+        // Just going to use CopyImage here
+        desc->fFlags = kNone_GrSurfaceFlags;
+    }
+
+    return true;
+}
+
 void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
                     VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) {
 
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 6d030f6..6ef0796 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -87,6 +87,8 @@
         return fPreferedStencilFormat;
     }
 
+    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
+
 private:
     enum VkVendor {
         kQualcomm_VkVendor = 20803,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index b85aa2d..4008c7c 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1590,23 +1590,6 @@
     return false;
 }
 
-bool GrVkGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
-    // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
-    // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
-    // render target as well.
-    desc->fOrigin = src->origin();
-    desc->fConfig = src->config();
-    if (src->numColorSamples() > 1 ||
-        (src->asTexture() && this->vkCaps().supportsCopiesAsDraws())) {
-        desc->fFlags = kRenderTarget_GrSurfaceFlag;
-    } else {
-        // Just going to use CopyImage here
-        desc->fFlags = kNone_GrSurfaceFlags;
-    }
-
-    return true;
-}
-
 void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
                                       int* effectiveSampleCnt, SamplePattern*) {
     // TODO: stub.
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 7203bf1..9556d85 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -79,8 +79,6 @@
     void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
                                  int* effectiveSampleCnt, SamplePattern*) override;
 
-    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override;
-
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
 
     GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index ef3cc48..55529d8 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -237,8 +237,7 @@
 
 void GrRenderTargetContextPriv::testingOnly_addDrawOp(GrPaint&& paint,
                                                       GrAAType aaType,
-                                                      std::unique_ptr<GrDrawOp>
-                                                              op,
+                                                      std::unique_ptr<GrDrawOp> op,
                                                       const GrUserStencilSettings* uss,
                                                       bool snapToCenters) {
     ASSERT_SINGLE_OWNER
@@ -253,8 +252,7 @@
     }
     pipelineBuilder.setSnapVerticesToPixelCenters(snapToCenters);
 
-    fRenderTargetContext->getOpList()->addDrawOp(pipelineBuilder, fRenderTargetContext, GrNoClip(),
-                                                 std::move(op));
+    fRenderTargetContext->addDrawOp(pipelineBuilder, GrNoClip(), std::move(op));
 }
 
 #undef ASSERT_SINGLE_OWNER
@@ -280,6 +278,9 @@
     bool isConfigTexturable(GrPixelConfig config) const override { return false; }
     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { return false; }
     bool canConfigBeImageStorage(GrPixelConfig) const override { return false; }
+    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override {
+        return false;
+    }
 
 private:
     typedef GrCaps INHERITED;
@@ -310,10 +311,6 @@
         *effectiveSampleCnt = rt->desc().fSampleCnt;
     }
 
-    bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override {
-        return false;
-    }
-
     GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&,
                                             const GrGpuCommandBuffer::LoadAndStoreInfo&) override {
         return nullptr;