Move CopyOps to CopyRenderTask.

This also means copies are no longer part of OpList or GpuCommandBuffer.

Change-Id: I234de2c93ca13e069d7e4423a3c8b292be2eb500
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235831
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrCopyRenderTask.cpp b/src/gpu/GrCopyRenderTask.cpp
new file mode 100644
index 0000000..6c41370
--- /dev/null
+++ b/src/gpu/GrCopyRenderTask.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrCopyRenderTask.h"
+
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/GrResourceAllocator.h"
+
+sk_sp<GrRenderTask> GrCopyRenderTask::Make(sk_sp<GrSurfaceProxy> srcProxy,
+                                           const SkIRect& srcRect,
+                                           sk_sp<GrSurfaceProxy> dstProxy,
+                                           const SkIPoint& dstPoint) {
+    SkASSERT(dstProxy);
+    SkASSERT(srcProxy);
+    SkIRect clippedSrcRect;
+    SkIPoint clippedDstPoint;
+    // If the rect is outside the srcProxy or dstProxy then we've already succeeded.
+    if (!GrClipSrcRectAndDstPoint(dstProxy->isize(), srcProxy->isize(), srcRect, dstPoint,
+                                  &clippedSrcRect, &clippedDstPoint)) {
+        return nullptr;
+    }
+    if (GrPixelConfigIsCompressed(dstProxy->config())) {
+        return nullptr;
+    }
+
+    SkASSERT(dstProxy->origin() == srcProxy->origin());
+    if (srcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+        int rectHeight = clippedSrcRect.height();
+        clippedSrcRect.fTop = srcProxy->height() - clippedSrcRect.fBottom;
+        clippedSrcRect.fBottom = clippedSrcRect.fTop + rectHeight;
+        clippedDstPoint.fY = dstProxy->height() - clippedDstPoint.fY - rectHeight;
+    }
+
+    sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask(
+            std::move(srcProxy), clippedSrcRect, std::move(dstProxy), clippedDstPoint));
+    return task;
+}
+
+GrCopyRenderTask::GrCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+                                   const SkIRect& srcRect,
+                                   sk_sp<GrSurfaceProxy> dstProxy,
+                                   const SkIPoint& dstPoint)
+        : GrRenderTask(std::move(dstProxy))
+        , fSrcProxy(std::move(srcProxy))
+        , fSrcRect(srcRect)
+        , fDstPoint(dstPoint) {
+    fTarget->setLastRenderTask(this);
+}
+
+void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+    // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
+    // fEndOfOpListOpIndices will remain in sync), so we create a fake op# to capture the fact that
+    // we read fSrcProxy and copy to fTarget.
+    alloc->addInterval(fSrcProxy.get(), alloc->curOp(), alloc->curOp(),
+                       GrResourceAllocator::ActualUse::kYes);
+    alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
+                       GrResourceAllocator::ActualUse::kYes);
+    alloc->incOps();
+}
+
+bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
+    if (!fSrcProxy->isInstantiated() || !fTarget->isInstantiated()) {
+        return false;
+    }
+    GrSurface* srcSurface = fSrcProxy->peekSurface();
+    GrSurface* dstSurface = fTarget->peekSurface();
+    if (fSrcProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+        if (fSrcProxy->height() != srcSurface->height()) {
+            fSrcRect.offset(0, srcSurface->height() - fSrcProxy->height());
+        }
+        if (fTarget->height() != dstSurface->height()) {
+            fDstPoint.fY = fDstPoint.fY + (dstSurface->height() - fTarget->height());
+        }
+    }
+    return flushState->gpu()->copySurface(dstSurface, srcSurface, fSrcRect, fDstPoint);
+}
+
diff --git a/src/gpu/GrCopyRenderTask.h b/src/gpu/GrCopyRenderTask.h
new file mode 100644
index 0000000..a04c89f
--- /dev/null
+++ b/src/gpu/GrCopyRenderTask.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrCopyRenderTask_DEFINED
+#define GrCopyRenderTask_DEFINED
+
+#include "src/gpu/GrRenderTask.h"
+
+class GrCopyRenderTask final : public GrRenderTask {
+public:
+    static sk_sp<GrRenderTask> Make(sk_sp<GrSurfaceProxy> srcProxy,
+                                    const SkIRect& srcRect,
+                                    sk_sp<GrSurfaceProxy> dstProxy,
+                                    const SkIPoint& dstPoint);
+
+private:
+    GrCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+                     const SkIRect& srcRect,
+                     sk_sp<GrSurfaceProxy> dstProxy,
+                     const SkIPoint& dstPoint);
+
+    void onPrepare(GrOpFlushState*) override {}
+    bool onIsUsed(GrSurfaceProxy* proxy) const override {
+        SkASSERT(proxy != fTarget.get());  // This case should be handled by GrRenderTask.
+        return proxy == fSrcProxy.get();
+    }
+    // If instantiation failed, at flush time we simply will skip doing the copy.
+    void handleInternalAllocationFailure() override {}
+    void gatherProxyIntervals(GrResourceAllocator*) const override;
+    ExpectedOutcome onMakeClosed(const GrCaps&) override {
+        return ExpectedOutcome::kTargetDirty;
+    }
+    bool onExecute(GrOpFlushState*) override;
+
+    sk_sp<GrSurfaceProxy> fSrcProxy;
+    SkIRect fSrcRect;
+    SkIPoint fDstPoint;
+};
+
+#endif
+
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 3017d4f..2437ee7 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -14,6 +14,7 @@
 #include "src/core/SkTTopoSort.h"
 #include "src/gpu/GrAuditTrail.h"
 #include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrCopyRenderTask.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrMemoryPool.h"
 #include "src/gpu/GrOnFlushResourceProvider.h"
@@ -730,6 +731,34 @@
     SkDEBUGCODE(this->validate());
 }
 
+bool GrDrawingManager::newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+                                         const SkIRect& srcRect,
+                                         sk_sp<GrSurfaceProxy> dstProxy,
+                                         const SkIPoint& dstPoint) {
+    SkDEBUGCODE(this->validate());
+    SkASSERT(fContext);
+    this->closeRenderTasksForNewRenderTask(dstProxy.get());
+
+    sk_sp<GrRenderTask> task = GrCopyRenderTask::Make(srcProxy, srcRect, dstProxy, dstPoint);
+    if (!task) {
+        return false;
+    }
+
+    const GrCaps& caps = *fContext->priv().caps();
+
+    // We always say GrMipMapped::kNo here since we are always just copying from the base layer to
+    // another base layer. We don't need to make sure the whole mip map chain is valid.
+    task->addDependency(srcProxy.get(), GrMipMapped::kNo, GrTextureResolveManager(this), caps);
+    task->makeClosed(caps);
+
+    fDAG.add(std::move(task));
+    // We have closed the previous active oplist but since a new oplist isn't being added there
+    // shouldn't be an active one.
+    SkASSERT(!fActiveOpList);
+    SkDEBUGCODE(this->validate());
+    return true;
+}
+
 GrTextContext* GrDrawingManager::getTextContext() {
     if (!fTextContext) {
         fTextContext = GrTextContext::Make(fOptionsForTextContext);
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 5fd27bd..af833fc 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -68,6 +68,15 @@
                                    GrColorType surfaceColorType, GrColorType dstColorType,
                                    sk_sp<GrGpuBuffer> dstBuffer, size_t dstOffset);
 
+    // Creates a new render task which copies a pixel rectangle from srcProxy into dstProxy. The src
+    // pixels copied are specified by srcRect. They are copied to a rect of the same size in
+    // dstProxy with top left at dstPoint. If the src rect is clipped by the src bounds then  pixel
+    // values in the dst rect corresponding to the area clipped by the src rect are not overwritten.
+    // This method is not guaranteed to succeed depending on the type of surface, formats, etc, and
+    // the backend-specific limitations.
+    bool newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
+                           sk_sp<GrSurfaceProxy> dstProxy, const SkIPoint& dstPoint);
+
     GrRecordingContext* getContext() { return fContext; }
 
     GrTextContext* getTextContext();
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 91c7e41..3e7e735 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -355,7 +355,7 @@
 }
 
 bool GrGpu::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                        const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
+                        const SkIPoint& dstPoint) {
     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
     SkASSERT(dst && src);
 
@@ -365,7 +365,7 @@
 
     this->handleDirtyContext();
 
-    return this->onCopySurface(dst, src, srcRect, dstPoint, canDiscardOutsideDstRect);
+    return this->onCopySurface(dst, src, srcRect, dstPoint);
 }
 
 bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int height,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 34be996..84d9c41 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -295,7 +295,7 @@
     // already being transformed for origin if need be. If canDiscardOutsideDstRect is set to true
     // then we don't need to preserve any data on the dst surface outside of the copy.
     bool copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                     const SkIPoint& dstPoint, bool canDiscardOutsideDstRect = false);
+                     const SkIPoint& dstPoint);
 
     // Queries the per-pixel HW sample locations for the given render target, and then finds or
     // assigns a key that uniquely identifies the sample pattern. The actual sample locations can be
@@ -597,7 +597,7 @@
 
     // overridden by backend specific derived class to perform the copy surface
     virtual bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                               const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) = 0;
+                               const SkIPoint& dstPoint) = 0;
 
     virtual void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
                                const GrFlushInfo&, const GrPrepareForExternalIORequests&) = 0;
diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h
index 54531d3..b242c06 100644
--- a/src/gpu/GrGpuCommandBuffer.h
+++ b/src/gpu/GrGpuCommandBuffer.h
@@ -29,11 +29,6 @@
 public:
     virtual ~GrGpuCommandBuffer() {}
 
-    // Copy src into current surface owned by either a GrGpuTextureCommandBuffer or
-    // GrGpuRenderTargetCommandBuffer. The srcRect and dstPoint must be in dst coords and have
-    // already been adjusted for any origin flips.
-    virtual void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
-
     virtual void insertEventMarker(const char*) = 0;
 
     virtual GrGpuRTCommandBuffer* asRTCommandBuffer() { return nullptr; }
diff --git a/src/gpu/GrOpList.h b/src/gpu/GrOpList.h
index f77e0a2..a4ee09e 100644
--- a/src/gpu/GrOpList.h
+++ b/src/gpu/GrOpList.h
@@ -23,20 +23,6 @@
     GrOpList(sk_sp<GrOpMemoryPool>, sk_sp<GrSurfaceProxy>, GrAuditTrail*);
     ~GrOpList() override;
 
-    /**
-     * Copies a pixel rectangle from a proxy into this opLists's target. This call may finalize
-     * reserved vertex/index data (as though a draw call was made). The src pixels copied are
-     * specified by srcRect. They are copied to a rect of the same size in this opList's target with
-     * top left at dstPoint. If the src rect is clipped by the src bounds then  pixel values in the
-     * dst rect corresponding to area clipped by the src rect are not overwritten. This method is
-     * not guaranteed to succeed depending on the type of surface, configs, etc, and the
-     * backend-specific limitations.
-     */
-    virtual bool copySurface(GrRecordingContext*,
-                             GrSurfaceProxy* src,
-                             const SkIRect& srcRect,
-                             const SkIPoint& dstPoint) = 0;
-
     void endFlush() override;
 
 protected:
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index ca39aa0..4c8bf05 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -16,13 +16,13 @@
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrGpuCommandBuffer.h"
 #include "src/gpu/GrMemoryPool.h"
+#include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrResourceAllocator.h"
 #include "src/gpu/GrTexturePriv.h"
 #include "src/gpu/geometry/GrRect.h"
 #include "src/gpu/ops/GrClearOp.h"
-#include "src/gpu/ops/GrCopySurfaceOp.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -575,23 +575,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-// This closely parallels GrTextureOpList::copySurface but renderTargetOpLists
-// also store the applied clip and dest proxy with the op
-bool GrRenderTargetOpList::copySurface(GrRecordingContext* context,
-                                       GrSurfaceProxy* src,
-                                       const SkIRect& srcRect,
-                                       const SkIPoint& dstPoint) {
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(
-            context, fTarget.get(), src, srcRect, dstPoint);
-    if (!op) {
-        return false;
-    }
-
-    this->addOp(std::move(op), GrTextureResolveManager(context->priv().drawingManager()),
-                *context->priv().caps());
-    return true;
-}
-
 void GrRenderTargetOpList::handleInternalAllocationFailure() {
     bool hasUninstantiatedProxy = false;
     auto checkInstantiation = [&hasUninstantiatedProxy](GrSurfaceProxy* p, GrMipMapped) {
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index efacbd0..fc675e3 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -89,11 +89,6 @@
 
     void discard();
 
-    bool copySurface(GrRecordingContext*,
-                     GrSurfaceProxy* src,
-                     const SkIRect& srcRect,
-                     const SkIPoint& dstPoint) override;
-
     GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
 
     SkDEBUGCODE(void dump(bool printDependencies) const override;)
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 3ab7a1f..dff02b0 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -425,7 +425,8 @@
         return false;
     }
 
-    return this->getOpList()->copySurface(fContext, src, srcRect, dstPoint);
+    return this->drawingManager()->newCopyRenderTask(sk_ref_sp(src), srcRect,
+                                                     this->asSurfaceProxyRef(), dstPoint);
 }
 
 std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 5a9e02c..2498af5 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -18,7 +18,6 @@
 #include "src/gpu/GrResourceAllocator.h"
 #include "src/gpu/GrTexturePriv.h"
 #include "src/gpu/GrTextureProxy.h"
-#include "src/gpu/ops/GrCopySurfaceOp.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -139,30 +138,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-// This closely parallels GrRenderTargetOpList::copySurface but renderTargetOpList
-// stores extra data with the op
-bool GrTextureOpList::copySurface(GrRecordingContext* context,
-                                  GrSurfaceProxy* src,
-                                  const SkIRect& srcRect,
-                                  const SkIPoint& dstPoint) {
-    std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(
-            context, fTarget.get(), src, srcRect, dstPoint);
-    if (!op) {
-        return false;
-    }
-
-    GrTextureResolveManager textureResolveManager(context->priv().drawingManager());
-    const GrCaps* caps = context->priv().caps();
-    auto addDependency = [ textureResolveManager, caps, this ] (
-            GrSurfaceProxy* p, GrMipMapped mipmapped) {
-        this->addDependency(p, mipmapped, textureResolveManager, *caps);
-    };
-    op->visitProxies(addDependency);
-
-    this->recordOp(std::move(op));
-    return true;
-}
-
 void GrTextureOpList::handleInternalAllocationFailure() {
     bool hasUninstantiatedProxy = false;
     auto checkInstantiation = [&hasUninstantiatedProxy](GrSurfaceProxy* p, GrMipMapped) {
diff --git a/src/gpu/GrTextureOpList.h b/src/gpu/GrTextureOpList.h
index 7029b75..4b578b6 100644
--- a/src/gpu/GrTextureOpList.h
+++ b/src/gpu/GrTextureOpList.h
@@ -38,11 +38,6 @@
     void onPrepare(GrOpFlushState* flushState) override;
     bool onExecute(GrOpFlushState* flushState) override;
 
-    bool copySurface(GrRecordingContext*,
-                     GrSurfaceProxy* src,
-                     const SkIRect& srcRect,
-                     const SkIPoint& dstPoint) override;
-
     GrTextureOpList* asTextureOpList() override { return this; }
 
     SkDEBUGCODE(void dump(bool printDependencies) const override;)
diff --git a/src/gpu/GrTransferFromRenderTask.cpp b/src/gpu/GrTransferFromRenderTask.cpp
index 2b8cee4..3e6dfc5 100644
--- a/src/gpu/GrTransferFromRenderTask.cpp
+++ b/src/gpu/GrTransferFromRenderTask.cpp
@@ -24,8 +24,7 @@
     if (!fSrcProxy->isInstantiated()) {
         return false;
     }
-    flushState->gpu()->transferPixelsFrom(
+    return flushState->gpu()->transferPixelsFrom(
             fSrcProxy->peekSurface(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.width(),
             fSrcRect.height(), fSurfaceColorType, fDstColorType, fDstBuffer.get(), fDstOffset);
-    return true;
 }
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 16a286b..0cbef8b 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3178,7 +3178,7 @@
 }
 
 bool GrGLGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                            const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
+                            const SkIPoint& dstPoint) {
     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
     // This implicitly handles this->glCaps().useDrawInsteadOfAllRenderTargetWrites().
     bool preferCopy = SkToBool(dst->asRenderTarget());
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 7959216..5787096 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -268,7 +268,7 @@
     bool onRegenerateMipMapLevels(GrTexture*) override;
 
     bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                       const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
+                       const SkIPoint& dstPoint) override;
 
     // binds texture unit in GL
     void setTextureUnit(int unitIdx);
diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h
index 37b3061..7d61a19 100644
--- a/src/gpu/gl/GrGLGpuCommandBuffer.h
+++ b/src/gpu/gl/GrGLGpuCommandBuffer.h
@@ -21,10 +21,6 @@
 public:
     GrGLGpuTextureCommandBuffer(GrGLGpu* gpu) : fGpu(gpu) {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fTexture, src, srcRect, dstPoint);
-    }
-
     void insertEventMarker(const char* msg) override {
         fGpu->insertEventMarker(msg);
     }
@@ -59,10 +55,6 @@
         state->doUpload(upload);
     }
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fRenderTarget, src,srcRect, dstPoint);
-    }
-
     void set(GrRenderTarget*, GrSurfaceOrigin,
              const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
              const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&);
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 89aa278..26edf8a 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -114,7 +114,7 @@
         return true;
     }
     bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                       const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override {
+                       const SkIPoint& dstPoint) override {
         return true;
     }
 
diff --git a/src/gpu/mock/GrMockGpuCommandBuffer.h b/src/gpu/mock/GrMockGpuCommandBuffer.h
index fff810e..7cc4ea1 100644
--- a/src/gpu/mock/GrMockGpuCommandBuffer.h
+++ b/src/gpu/mock/GrMockGpuCommandBuffer.h
@@ -21,7 +21,6 @@
 
     ~GrMockGpuTextureCommandBuffer() override {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
     void insertEventMarker(const char*) override {}
 
 private:
@@ -46,9 +45,6 @@
         }
     }
     void end() override {}
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        this->markRenderTargetDirty();
-    }
 
     int numDraws() const { return fNumDraws; }
 
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 6715797..420264b 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -78,7 +78,7 @@
                            const SkIPoint& dstPoint);
 
     bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                       const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
+                       const SkIPoint& dstPoint) override;
 
     GrGpuRTCommandBuffer* getCommandBuffer(
                                     GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 39282c4..364e72a 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -149,7 +149,7 @@
 
 GrGpuTextureCommandBuffer* GrMtlGpu::getCommandBuffer(GrTexture* texture,
                                                       GrSurfaceOrigin origin) {
-    return new GrMtlGpuTextureCommandBuffer(this, texture, origin);
+    return new GrMtlGpuTextureCommandBuffer(texture, origin);
 }
 
 void GrMtlGpu::submit(GrGpuCommandBuffer* buffer) {
@@ -918,7 +918,7 @@
 }
 
 bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                             const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
+                             const SkIPoint& dstPoint) {
     SkASSERT(!src->isProtected() && !dst->isProtected());
 
     MTLPixelFormat dstFormat = GrBackendFormatAsMTLPixelFormat(dst->backendFormat());
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.h b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
index f614920..eb60f4e 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.h
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
@@ -22,21 +22,15 @@
 
 class GrMtlGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
 public:
-    GrMtlGpuTextureCommandBuffer(GrMtlGpu* gpu, GrTexture* texture, GrSurfaceOrigin origin)
-            : INHERITED(texture, origin)
-            , fGpu(gpu) {
+    GrMtlGpuTextureCommandBuffer(GrTexture* texture, GrSurfaceOrigin origin)
+            : INHERITED(texture, origin) {
     }
 
     ~GrMtlGpuTextureCommandBuffer() override {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fTexture, src, srcRect, dstPoint);
-    }
     void insertEventMarker(const char* msg) override {}
 
 private:
-    GrMtlGpu* fGpu;
-
     typedef GrGpuTextureCommandBuffer INHERITED;
 };
 
@@ -60,8 +54,6 @@
         // TODO: this could be more efficient
         state->doUpload(upload);
     }
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
     void submit();
 
 private:
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
index d404cb9..049485d 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
@@ -57,14 +57,6 @@
     fGpu->submitIndirectCommandBuffer(fRenderTarget, fOrigin, &iBounds);
 }
 
-void GrMtlGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
-const SkIPoint& dstPoint) {
-    // We cannot have an active encoder when we call copy since it requires its own
-    // command encoder.
-    SkASSERT(nil == fActiveRenderCmdEncoder);
-    fGpu->copySurface(fRenderTarget, src, srcRect, dstPoint);
-}
-
 GrMtlPipelineState* GrMtlGpuRTCommandBuffer::prepareDrawState(
         const GrPrimitiveProcessor& primProc,
         const GrPipeline& pipeline,
diff --git a/src/gpu/ops/GrCopySurfaceOp.cpp b/src/gpu/ops/GrCopySurfaceOp.cpp
deleted file mode 100644
index aef1828..0000000
--- a/src/gpu/ops/GrCopySurfaceOp.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/ops/GrCopySurfaceOp.h"
-
-#include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrGpu.h"
-#include "src/gpu/GrMemoryPool.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/geometry/GrRect.h"
-
-std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrRecordingContext* context,
-                                            GrSurfaceProxy* dstProxy,
-                                            GrSurfaceProxy* srcProxy,
-                                            const SkIRect& srcRect,
-                                            const SkIPoint& dstPoint) {
-    SkASSERT(dstProxy);
-    SkASSERT(srcProxy);
-    SkIRect clippedSrcRect;
-    SkIPoint clippedDstPoint;
-    // If the rect is outside the srcProxy or dstProxy then we've already succeeded.
-    if (!GrClipSrcRectAndDstPoint(dstProxy->isize(), srcProxy->isize(), srcRect, dstPoint,
-                                  &clippedSrcRect, &clippedDstPoint)) {
-        return nullptr;
-    }
-    if (GrPixelConfigIsCompressed(dstProxy->config())) {
-        return nullptr;
-    }
-
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
-    return pool->allocate<GrCopySurfaceOp>(srcProxy, dstProxy, clippedSrcRect, clippedDstPoint);
-}
-
-void GrCopySurfaceOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
-    SkASSERT(fSrc.get()->isInstantiated());
-
-    // If we are using approx surfaces we may need to adjust our srcRect or dstPoint if the origin
-    // is bottom left.
-    GrSurfaceProxy* src = fSrc.get();
-    if (src->origin() == kBottomLeft_GrSurfaceOrigin) {
-        GrSurfaceProxy* dst = fDst.get();
-        SkASSERT(dst->isInstantiated());
-        if (src->height() != src->peekSurface()->height()) {
-            fSrcRect.offset(0, src->peekSurface()->height() - src->height());
-        }
-        if (dst->height() != dst->peekSurface()->height()) {
-            fDstPoint.fY = fDstPoint.fY + (dst->peekSurface()->height() - dst->height());
-        }
-    }
-
-    state->commandBuffer()->copy(fSrc.get()->peekSurface(), fSrcRect, fDstPoint);
-}
diff --git a/src/gpu/ops/GrCopySurfaceOp.h b/src/gpu/ops/GrCopySurfaceOp.h
deleted file mode 100644
index f5d41dd..0000000
--- a/src/gpu/ops/GrCopySurfaceOp.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrCopySurfaceOp_DEFINED
-#define GrCopySurfaceOp_DEFINED
-
-#include "src/gpu/GrOpFlushState.h"
-#include "src/gpu/ops/GrOp.h"
-
-class GrRecordingContext;
-
-class GrCopySurfaceOp final : public GrOp {
-public:
-    DEFINE_OP_CLASS_ID
-
-    static std::unique_ptr<GrOp> Make(GrRecordingContext*,
-                                      GrSurfaceProxy* dst,
-                                      GrSurfaceProxy* src,
-                                      const SkIRect& srcRect,
-                                      const SkIPoint& dstPoint);
-
-    const char* name() const override { return "CopySurface"; }
-
-    void visitProxies(const VisitProxyFunc& func) const override {
-        func(fSrc.get(), GrMipMapped::kNo);
-        func(fDst.get(), GrMipMapped::kNo);
-    }
-
-#ifdef SK_DEBUG
-    SkString dumpInfo() const override {
-        SkString string;
-        string = INHERITED::dumpInfo();
-        string.appendf(
-                "srcProxyID: %d,\n"
-                "srcRect: [ L: %d, T: %d, R: %d, B: %d ], dstPt: [ X: %d, Y: %d ]\n",
-                fSrc.get()->uniqueID().asUInt(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight,
-                fSrcRect.fBottom, fDstPoint.fX, fDstPoint.fY);
-        return string;
-    }
-#endif
-
-private:
-    friend class GrOpMemoryPool; // for ctor
-
-    GrCopySurfaceOp(GrSurfaceProxy* src, GrSurfaceProxy* dst, const SkIRect& srcRect,
-                    const SkIPoint& dstPoint)
-            : INHERITED(ClassID())
-            , fSrc(sk_ref_sp(src))
-            , fDst(sk_ref_sp(dst))
-            , fSrcRect(srcRect)
-            , fDstPoint(dstPoint) {
-        SkRect bounds =
-                SkRect::MakeXYWH(SkIntToScalar(dstPoint.fX), SkIntToScalar(dstPoint.fY),
-                                 SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
-        this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
-
-        SkASSERT(dst->origin() == src->origin());
-        if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
-            int rectHeight = fSrcRect.height();
-            fSrcRect.fTop = src->height() - fSrcRect.fBottom;
-            fSrcRect.fBottom = fSrcRect.fTop + rectHeight;
-            fDstPoint.fY = dst->height() - fDstPoint.fY - rectHeight;
-        }
-
-    }
-
-    void onPrepare(GrOpFlushState*) override {}
-
-    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
-
-    sk_sp<GrSurfaceProxy> fSrc;
-    sk_sp<GrSurfaceProxy> fDst;
-    SkIRect               fSrcRect;
-    SkIPoint              fDstPoint;
-
-    typedef GrOp INHERITED;
-};
-
-#endif
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index a5b451a..13f603a 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -869,7 +869,7 @@
     if (copyTexture.get()) {
         SkASSERT(dataColorType == GrColorType::kRGB_888x);
         SkAssertResult(this->copySurface(tex, copyTexture.get(), SkIRect::MakeWH(width, height),
-                                         SkIPoint::Make(left, top), false));
+                                         SkIPoint::Make(left, top)));
     }
     if (1 == mipLevelCount) {
         tex->texturePriv().markMipMapsDirty();
@@ -2204,7 +2204,7 @@
 }
 
 bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                            const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) {
+                            const SkIPoint& dstPoint) {
 #ifdef SK_DEBUG
     if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) {
         SkASSERT(!srcRT->wrapsSecondaryCommandBuffer());
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index ca175e5..b0252cd 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -238,7 +238,7 @@
                               GrGpuBuffer* transferBuffer, size_t offset) override;
 
     bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
-                       const SkIPoint& dstPoint, bool canDiscardOutsideDstRect) override;
+                       const SkIPoint& dstPoint) override;
 
     void onFinishFlush(GrSurfaceProxy*[], int, SkSurface::BackendSurfaceAccess access,
                        const GrFlushInfo&, const GrPrepareForExternalIORequests&) override;
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 331728a..80e4340 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -44,36 +44,10 @@
     GrDeferredTextureUploadFn fUpload;
 };
 
-class Copy : public GrVkPrimaryCommandBufferTask {
-public:
-    Copy(sk_sp<GrSurface> src, const SkIRect& srcRect, const SkIPoint& dstPoint,
-         bool shouldDiscardDst)
-            : fSrc(std::move(src))
-            , fSrcRect(srcRect)
-            , fDstPoint(dstPoint)
-            , fShouldDiscardDst(shouldDiscardDst) {}
-
-    void execute(const Args& args) override {
-        args.fGpu->copySurface(args.fSurface, fSrc.get(), fSrcRect, fDstPoint, fShouldDiscardDst);
-    }
-
-private:
-    sk_sp<GrSurface> fSrc;
-    SkIRect          fSrcRect;
-    SkIPoint         fDstPoint;
-    bool             fShouldDiscardDst;
-};
-
 }  // anonymous namespace
 
 /////////////////////////////////////////////////////////////////////////////
 
-void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
-                                       const SkIPoint& dstPoint) {
-    SkASSERT(!src->isProtected() || (fTexture->isProtected() && fGpu->protectedContext()));
-    fTasks.emplace<Copy>(sk_ref_sp(src), srcRect, dstPoint, false);
-}
-
 void GrVkGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
     // TODO: does Vulkan have a correlate?
 }
@@ -541,48 +515,6 @@
     ++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds;
 }
 
-void GrVkGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
-                                  const SkIPoint& dstPoint) {
-    CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
-    if (!cbInfo.fIsEmpty || LoadStoreState::kStartsWithClear == cbInfo.fLoadStoreState) {
-        this->addAdditionalRenderPass();
-    }
-
-    fPreCommandBufferTasks.emplace<Copy>(
-            sk_ref_sp(src), srcRect, dstPoint,
-            LoadStoreState::kStartsWithDiscard == cbInfo.fLoadStoreState);
-    ++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds;
-
-    if (LoadStoreState::kLoadAndStore != cbInfo.fLoadStoreState) {
-        // Change the render pass to do a load and store so we don't lose the results of our copy
-        GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
-                                                VK_ATTACHMENT_STORE_OP_STORE);
-        GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
-                                                  VK_ATTACHMENT_STORE_OP_STORE);
-
-        const GrVkRenderPass* oldRP = cbInfo.fRenderPass;
-
-        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(fRenderTarget);
-        SkASSERT(!src->isProtected() || (fRenderTarget->isProtected() && fGpu->protectedContext()));
-        const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
-                vkRT->compatibleRenderPassHandle();
-        if (rpHandle.isValid()) {
-            cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
-                                                                         vkColorOps,
-                                                                         vkStencilOps);
-        } else {
-            cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
-                                                                         vkColorOps,
-                                                                         vkStencilOps);
-        }
-        SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
-        oldRP->unref(fGpu);
-
-        cbInfo.fLoadStoreState = LoadStoreState::kLoadAndStore;
-
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrVkGpuRTCommandBuffer::bindGeometry(const GrGpuBuffer* indexBuffer,
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index a9283f4..c24eebd 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -45,8 +45,6 @@
 public:
     GrVkGpuTextureCommandBuffer(GrVkGpu* gpu) : fGpu(gpu) {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
     void insertEventMarker(const char*) override;
 
     void reset() {
@@ -100,8 +98,6 @@
 
     void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override;
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
     void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override;
 
     void set(GrRenderTarget*, GrSurfaceOrigin,