Move transferFrom commands from GrOp and into GrRenderTask.

These Ops don't need to go through the GrGpuCommandBuffer.

Change-Id: Ifa9c7d801c97c225989d2542709c89f36ddfdc5e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235799
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 84fc97e..62dfe44 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -32,6 +32,7 @@
 #include "src/gpu/GrTextureProxyPriv.h"
 #include "src/gpu/GrTextureResolveRenderTask.h"
 #include "src/gpu/GrTracing.h"
+#include "src/gpu/GrTransferFromRenderTask.h"
 #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
 #include "src/gpu/text/GrTextContext.h"
 #include "src/image/SkSurface_Gpu.h"
@@ -613,8 +614,8 @@
 }
 #endif
 
-void GrDrawingManager::closeRenderTasksForNewOpList(GrSurfaceProxy* target) {
-    if (fDAG.sortingRenderTasks() && fReduceOpListSplitting) {
+void GrDrawingManager::closeRenderTasksForNewRenderTask(GrSurfaceProxy* target) {
+    if (target && fDAG.sortingRenderTasks() && fReduceOpListSplitting) {
         // In this case we need to close all the renderTasks that rely on the current contents of
         // 'target'. That is bc we're going to update the content of the proxy so they need to be
         // split in case they use both the old and new content. (This is a bit of an overkill: they
@@ -638,7 +639,7 @@
     SkDEBUGCODE(this->validate());
     SkASSERT(fContext);
 
-    this->closeRenderTasksForNewOpList(rtp.get());
+    this->closeRenderTasksForNewRenderTask(rtp.get());
 
     sk_sp<GrRenderTargetOpList> opList(new GrRenderTargetOpList(
                                                         fContext->priv().refOpMemoryPool(),
@@ -662,7 +663,7 @@
     SkDEBUGCODE(this->validate());
     SkASSERT(fContext);
 
-    this->closeRenderTasksForNewOpList(textureProxy.get());
+    this->closeRenderTasksForNewRenderTask(textureProxy.get());
 
     sk_sp<GrTextureOpList> opList(new GrTextureOpList(fContext->priv().refOpMemoryPool(),
                                                       textureProxy,
@@ -700,6 +701,35 @@
     return fDAG.addBeforeLast(std::move(textureResolveTask));
 }
 
+void GrDrawingManager::newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+                                                 const SkIRect& srcRect,
+                                                 GrColorType surfaceColorType,
+                                                 GrColorType dstColorType,
+                                                 sk_sp<GrGpuBuffer> dstBuffer,
+                                                 size_t dstOffset) {
+    SkDEBUGCODE(this->validate());
+    SkASSERT(fContext);
+    // This copies from srcProxy to dstBuffer so it doesn't have a real target.
+    this->closeRenderTasksForNewRenderTask(nullptr);
+
+    sk_sp<GrRenderTask> task(new GrTransferFromRenderTask(srcProxy, srcRect, surfaceColorType,
+                                                          dstColorType, std::move(dstBuffer),
+                                                          dstOffset));
+
+    const GrCaps& caps = *fContext->priv().caps();
+
+    // We always say GrMipMapped::kNo here since we are always just copying from the 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());
+}
+
 GrTextContext* GrDrawingManager::getTextContext() {
     if (!fTextContext) {
         fTextContext = GrTextContext::Make(fOptionsForTextContext);
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 80f006e..13e2f55 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -59,6 +59,15 @@
     GrRenderTask* newTextureResolveRenderTask(
             sk_sp<GrTextureProxy>, GrTextureResolveFlags, const GrCaps&);
 
+    // Create a new render task which copies the pixels from the srcProxy into the dstBuffer. This
+    // is used to support the asynchronous readback API. The srcRect is the region of the srcProxy
+    // to be copied. The surfaceColorType says how we should interpret the data when reading back
+    // from the source. DstColorType describes how the data should be stored in the dstBuffer.
+    // DstOffset is the offset into the dstBuffer where we will start writing data.
+    void newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
+                                   GrColorType surfaceColorType, GrColorType dstColorType,
+                                   sk_sp<GrGpuBuffer> dstBuffer, size_t dstOffset);
+
     GrRecordingContext* getContext() { return fContext; }
 
     GrTextContext* getTextContext();
@@ -162,7 +171,7 @@
     // Closes the target's dependent render tasks (or, if not in sorting/opList-splitting-reduction
     // mode, closes fActiveOpList) in preparation for us opening a new opList that will write to
     // 'target'.
-    void closeRenderTasksForNewOpList(GrSurfaceProxy* target);
+    void closeRenderTasksForNewRenderTask(GrSurfaceProxy* target);
 
     // return true if any opLists were actually executed; false otherwise
     bool executeRenderTasks(int startIndex, int stopIndex, GrOpFlushState*,
diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h
index 401bcc9..54531d3 100644
--- a/src/gpu/GrGpuCommandBuffer.h
+++ b/src/gpu/GrGpuCommandBuffer.h
@@ -33,10 +33,6 @@
     // 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;
-    // Initiates a transfer from the surface owned by the command buffer to the GrGpuBuffer.
-    virtual void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                              GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                              size_t offset) = 0;
 
     virtual void insertEventMarker(const char*) = 0;
 
diff --git a/src/gpu/GrOpList.h b/src/gpu/GrOpList.h
index 7da7b4d..4de0a21 100644
--- a/src/gpu/GrOpList.h
+++ b/src/gpu/GrOpList.h
@@ -37,13 +37,6 @@
                              const SkIRect& srcRect,
                              const SkIPoint& dstPoint) = 0;
 
-    virtual void transferFrom(GrRecordingContext*,
-                              const SkIRect& srcRect,
-                              GrColorType surfaceColorType,
-                              GrColorType dstColorType,
-                              sk_sp<GrGpuBuffer> dst,
-                              size_t dstOffset) = 0;
-
     void endFlush() override;
 
     /*
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 6837cbf..ae38228 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -66,7 +66,6 @@
 #include "src/gpu/ops/GrStencilPathOp.h"
 #include "src/gpu/ops/GrStrokeRectOp.h"
 #include "src/gpu/ops/GrTextureOp.h"
-#include "src/gpu/ops/GrTransferFromOp.h"
 #include "src/gpu/text/GrTextContext.h"
 #include "src/gpu/text/GrTextTarget.h"
 
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 77d42b9..932a818 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -23,7 +23,6 @@
 #include "src/gpu/geometry/GrRect.h"
 #include "src/gpu/ops/GrClearOp.h"
 #include "src/gpu/ops/GrCopySurfaceOp.h"
-#include "src/gpu/ops/GrTransferFromOp.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -605,18 +604,6 @@
     return true;
 }
 
-void GrRenderTargetOpList::transferFrom(GrRecordingContext* context,
-                                        const SkIRect& srcRect,
-                                        GrColorType surfaceColorType,
-                                        GrColorType dstColorType,
-                                        sk_sp<GrGpuBuffer> dst,
-                                        size_t dstOffset) {
-    auto op = GrTransferFromOp::Make(context, srcRect, surfaceColorType, dstColorType,
-                                     std::move(dst), dstOffset);
-    this->addOp(std::move(op), GrTextureResolveManager(context->priv().drawingManager()),
-                *context->priv().caps());
-}
-
 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 5d80cfa..a8119bb 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -104,13 +104,6 @@
                      const SkIRect& srcRect,
                      const SkIPoint& dstPoint) override;
 
-    void transferFrom(GrRecordingContext*,
-                      const SkIRect& srcRect,
-                      GrColorType surfaceColorType,
-                      GrColorType dstColorType,
-                      sk_sp<GrGpuBuffer> dst,
-                      size_t dstOffset) override;
-
     GrRenderTargetOpList* asRenderTargetOpList() override { return this; }
 
     SkDEBUGCODE(void dump(bool printDependencies) const override;)
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 46091f7..9909e6c 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -170,6 +170,11 @@
 }
 
 bool GrRenderTask::isInstantiated() const {
+    // Some renderTasks (e.g. GrTransferFromRenderTask) don't have a target.
+    if (!fTarget) {
+        return true;
+    }
+
     if (!fTarget->isInstantiated()) {
         return false;
     }
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index d9e499d..6d66634 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -630,8 +630,9 @@
         srcRect = SkIRect::MakeLTRB(rect.fLeft, this->height() - rect.fBottom, rect.fRight,
                                     this->height() - rect.fTop);
     }
-    this->getOpList()->transferFrom(fContext, srcRect, this->colorSpaceInfo().colorType(),
-                                    supportedRead.fColorType, buffer, 0);
+    this->drawingManager()->newTransferFromRenderTask(this->asSurfaceProxyRef(), srcRect,
+                                                      this->colorSpaceInfo().colorType(),
+                                                      supportedRead.fColorType, buffer, 0);
     PixelTransferResult result;
     result.fTransferBuffer = std::move(buffer);
     auto at = this->colorSpaceInfo().alphaType();
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 60c0883..5b346d4 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -19,7 +19,6 @@
 #include "src/gpu/GrTexturePriv.h"
 #include "src/gpu/GrTextureProxy.h"
 #include "src/gpu/ops/GrCopySurfaceOp.h"
-#include "src/gpu/ops/GrTransferFromOp.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -176,17 +175,6 @@
     return true;
 }
 
-void GrTextureOpList::transferFrom(GrRecordingContext* context,
-                                   const SkIRect& srcRect,
-                                   GrColorType surfaceColorType,
-                                   GrColorType dstColorType,
-                                   sk_sp<GrGpuBuffer> dst,
-                                   size_t dstOffset) {
-    auto op = GrTransferFromOp::Make(context, srcRect, surfaceColorType, dstColorType,
-                                     std::move(dst), dstOffset);
-    this->recordOp(std::move(op));
-}
-
 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 822bee8..756a390 100644
--- a/src/gpu/GrTextureOpList.h
+++ b/src/gpu/GrTextureOpList.h
@@ -43,13 +43,6 @@
                      const SkIRect& srcRect,
                      const SkIPoint& dstPoint) override;
 
-    void transferFrom(GrRecordingContext*,
-                      const SkIRect& srcRect,
-                      GrColorType surfaceColorType,
-                      GrColorType dstColorType,
-                      sk_sp<GrGpuBuffer> dst,
-                      size_t dstOffset) override;
-
     GrTextureOpList* asTextureOpList() override { return this; }
 
     SkDEBUGCODE(void dump(bool printDependencies) const override;)
diff --git a/src/gpu/GrTextureResolveRenderTask.cpp b/src/gpu/GrTextureResolveRenderTask.cpp
index eaae8db..613f6bd 100644
--- a/src/gpu/GrTextureResolveRenderTask.cpp
+++ b/src/gpu/GrTextureResolveRenderTask.cpp
@@ -14,26 +14,26 @@
 #include "src/gpu/GrTexturePriv.h"
 
 sk_sp<GrRenderTask> GrTextureResolveRenderTask::Make(
-        sk_sp<GrTextureProxy> textureProxyPtr, GrTextureResolveFlags flags, const GrCaps& caps) {
-    GrTextureProxy* textureProxy = textureProxyPtr.get();
+        sk_sp<GrTextureProxy> textureProxy, GrTextureResolveFlags flags, const GrCaps& caps) {
+    GrTextureProxy* textureProxyPtr = textureProxy.get();
     sk_sp<GrTextureResolveRenderTask> resolveTask(
-            new GrTextureResolveRenderTask(std::move(textureProxyPtr), flags));
+            new GrTextureResolveRenderTask(std::move(textureProxy), flags));
 
     // Add the target as a dependency: We will read the existing contents of this texture while
     // generating mipmap levels and/or resolving MSAA.
     //
     // NOTE: This must be called before makeClosed.
     resolveTask->addDependency(
-            textureProxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
-    textureProxy->setLastRenderTask(resolveTask.get());
+            textureProxyPtr, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
+    textureProxyPtr->setLastRenderTask(resolveTask.get());
 
     // We only resolve the texture; nobody should try to do anything else with this opList.
     resolveTask->makeClosed(caps);
 
     if (GrTextureResolveFlags::kMipMaps & flags) {
-        SkASSERT(GrMipMapped::kYes == textureProxy->mipMapped());
-        SkASSERT(textureProxy->mipMapsAreDirty());
-        textureProxy->markMipMapsClean();
+        SkASSERT(GrMipMapped::kYes == textureProxyPtr->mipMapped());
+        SkASSERT(textureProxyPtr->mipMapsAreDirty());
+        textureProxyPtr->markMipMapsClean();
     }
 
     return resolveTask;
diff --git a/src/gpu/GrTransferFromRenderTask.cpp b/src/gpu/GrTransferFromRenderTask.cpp
new file mode 100644
index 0000000..2b8cee4
--- /dev/null
+++ b/src/gpu/GrTransferFromRenderTask.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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/GrTransferFromRenderTask.h"
+
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/GrResourceAllocator.h"
+
+void GrTransferFromRenderTask::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.
+    alloc->addInterval(fSrcProxy.get(), alloc->curOp(), alloc->curOp(),
+                       GrResourceAllocator::ActualUse::kYes);
+    alloc->incOps();
+}
+
+bool GrTransferFromRenderTask::onExecute(GrOpFlushState* flushState) {
+    if (!fSrcProxy->isInstantiated()) {
+        return false;
+    }
+    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/GrTransferFromRenderTask.h b/src/gpu/GrTransferFromRenderTask.h
new file mode 100644
index 0000000..2ad02e8
--- /dev/null
+++ b/src/gpu/GrTransferFromRenderTask.h
@@ -0,0 +1,50 @@
+/*
+ * 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 GrTransferFromRenderTask_DEFINED
+#define GrTransferFromRenderTask_DEFINED
+
+#include "src/gpu/GrRenderTask.h"
+
+class GrTransferFromRenderTask final : public GrRenderTask {
+public:
+    GrTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
+                             const SkIRect& srcRect,
+                             GrColorType surfaceColorType,
+                             GrColorType dstColorType,
+                             sk_sp<GrGpuBuffer> dstBuffer,
+                             size_t dstOffset)
+            : GrRenderTask(nullptr)
+            , fSrcProxy(std::move(srcProxy))
+            , fSrcRect(srcRect)
+            , fSurfaceColorType(surfaceColorType)
+            , fDstColorType(dstColorType)
+            , fDstBuffer(std::move(dstBuffer))
+            , fDstOffset(dstOffset) {}
+
+private:
+    void onPrepare(GrOpFlushState*) override {}
+    bool onIsUsed(GrSurfaceProxy* proxy) const override {
+        SkASSERT(!fTarget);
+        return proxy == fSrcProxy.get();
+    }
+    // If fSrcProxy is uninstantiated at flush time we simply will skip doing the transfer.
+    void handleInternalAllocationFailure() override {}
+    void gatherProxyIntervals(GrResourceAllocator*) const override;
+    bool onExecute(GrOpFlushState*) override;
+
+    sk_sp<GrSurfaceProxy> fSrcProxy;
+    SkIRect fSrcRect;
+    GrColorType fSurfaceColorType;
+    GrColorType fDstColorType;
+    sk_sp<GrGpuBuffer> fDstBuffer;
+    size_t fDstOffset;
+
+};
+
+#endif
+
diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h
index 2a4d387..37b3061 100644
--- a/src/gpu/gl/GrGLGpuCommandBuffer.h
+++ b/src/gpu/gl/GrGLGpuCommandBuffer.h
@@ -25,14 +25,6 @@
         fGpu->copySurface(fTexture, src, srcRect, dstPoint);
     }
 
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override {
-        fGpu->transferPixelsFrom(fTexture, srcRect.fLeft, srcRect.fTop, srcRect.width(),
-                                 srcRect.height(), surfaceColorType, bufferColorType,
-                                 transferBuffer, offset);
-    }
-
     void insertEventMarker(const char* msg) override {
         fGpu->insertEventMarker(msg);
     }
@@ -71,14 +63,6 @@
         fGpu->copySurface(fRenderTarget, src,srcRect, dstPoint);
     }
 
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override {
-        fGpu->transferPixelsFrom(fRenderTarget, srcRect.fLeft, srcRect.fTop, srcRect.width(),
-                                 srcRect.height(), surfaceColorType, bufferColorType,
-                                 transferBuffer, offset);
-    }
-
     void set(GrRenderTarget*, GrSurfaceOrigin,
              const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
              const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&);
diff --git a/src/gpu/mock/GrMockGpuCommandBuffer.h b/src/gpu/mock/GrMockGpuCommandBuffer.h
index aa75378..bb5b3af 100644
--- a/src/gpu/mock/GrMockGpuCommandBuffer.h
+++ b/src/gpu/mock/GrMockGpuCommandBuffer.h
@@ -20,9 +20,6 @@
     ~GrMockGpuTextureCommandBuffer() override {}
 
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override {}
     void insertEventMarker(const char*) override {}
 
 private:
@@ -42,9 +39,6 @@
     void begin() override {}
     void end() override {}
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override {}
 
     int numDraws() const { return fNumDraws; }
 
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.h b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
index 723ac07..f614920 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.h
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
@@ -32,13 +32,6 @@
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
         fGpu->copySurface(fTexture, src, srcRect, dstPoint);
     }
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override {
-        fGpu->transferPixelsFrom(fTexture, srcRect.fLeft, srcRect.fTop, srcRect.width(),
-                                 srcRect.height(), surfaceColorType, bufferColorType,
-                                 transferBuffer, offset);
-    }
     void insertEventMarker(const char* msg) override {}
 
 private:
@@ -67,9 +60,6 @@
         // TODO: this could be more efficient
         state->doUpload(upload);
     }
-    void transferFrom(const SkIRect& srcRect, GrColorType textureColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override;
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
 
     void submit();
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
index a86d779..d404cb9 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.mm
@@ -65,17 +65,6 @@
     fGpu->copySurface(fRenderTarget, src, srcRect, dstPoint);
 }
 
-void GrMtlGpuRTCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                                           GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                                           size_t offset) {
-    // We cannot have an active encoder when we call transferFrom since it requires its own
-    // command encoder.
-    SkASSERT(nil == fActiveRenderCmdEncoder);
-    fGpu->transferPixelsFrom(fRenderTarget, srcRect.fLeft, srcRect.fTop, srcRect.width(),
-                             srcRect.height(), surfaceColorType, bufferColorType, transferBuffer,
-                             offset);
-}
-
 GrMtlPipelineState* GrMtlGpuRTCommandBuffer::prepareDrawState(
         const GrPrimitiveProcessor& primProc,
         const GrPipeline& pipeline,
diff --git a/src/gpu/ops/GrTransferFromOp.cpp b/src/gpu/ops/GrTransferFromOp.cpp
deleted file mode 100644
index be5490b..0000000
--- a/src/gpu/ops/GrTransferFromOp.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 "include/private/GrRecordingContext.h"
-#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrGpuCommandBuffer.h"
-#include "src/gpu/GrMemoryPool.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/ops/GrTransferFromOp.h"
-
-std::unique_ptr<GrOp> GrTransferFromOp::Make(GrRecordingContext* context,
-                                             const SkIRect& srcRect,
-                                             GrColorType surfaceColorType,
-                                             GrColorType dstColorType,
-                                             sk_sp<GrGpuBuffer> dstBuffer,
-                                             size_t dstOffset) {
-    GrOpMemoryPool* pool = context->priv().opMemoryPool();
-    return pool->allocate<GrTransferFromOp>(
-            srcRect, surfaceColorType, dstColorType, std::move(dstBuffer), dstOffset);
-}
-
-void GrTransferFromOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
-    state->commandBuffer()->transferFrom(
-            fSrcRect, fSurfaceColorType, fDstColorType, fDstBuffer.get(), fDstOffset);
-}
diff --git a/src/gpu/ops/GrTransferFromOp.h b/src/gpu/ops/GrTransferFromOp.h
deleted file mode 100644
index f611fc8..0000000
--- a/src/gpu/ops/GrTransferFromOp.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 GrTransferFromOp_DEFINED
-#define GrTransferFromOp_DEFINED
-
-#include "src/gpu/GrOpFlushState.h"
-#include "src/gpu/ops/GrOp.h"
-
-/**
- * Does a transfer from the surface context's surface to a transfer buffer. It is assumed
- * that the caller has checked the GrCaps to ensure this transfer is legal.
- */
-class GrTransferFromOp final : public GrOp {
-public:
-    DEFINE_OP_CLASS_ID
-
-    static std::unique_ptr<GrOp> Make(GrRecordingContext*,
-                                      const SkIRect& srcRect,
-                                      GrColorType surfaceColorType,
-                                      GrColorType dstColorType,
-                                      sk_sp<GrGpuBuffer> dstBuffer,
-                                      size_t dstOffset);
-
-    const char* name() const override { return "TransferFromOp"; }
-
-#ifdef SK_DEBUG
-    SkString dumpInfo() const override {
-        SkString string;
-        string = INHERITED::dumpInfo();
-        string.appendf(
-                "bufferID:: %d offset: %zu, surf color type: %d, dst color type: %d\n"
-                "srcRect: [ L: %d, T: %d, R: %d, B: %d ]\n",
-                fDstBuffer->uniqueID().asUInt(), fDstOffset, (int)fSurfaceColorType,
-                (int)fDstColorType, fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight,
-                fSrcRect.fBottom);
-        return string;
-    }
-#endif
-
-private:
-    friend class GrOpMemoryPool;  // for ctor
-
-    GrTransferFromOp(const SkIRect& srcRect,
-                     GrColorType surfaceColorType,
-                     GrColorType dstColorType,
-                     sk_sp<GrGpuBuffer> dstBuffer,
-                     size_t dstOffset)
-            : INHERITED(ClassID())
-            , fDstBuffer(std::move(dstBuffer))
-            , fDstOffset(dstOffset)
-            , fSrcRect(srcRect)
-            , fSurfaceColorType(surfaceColorType)
-            , fDstColorType(dstColorType) {
-        this->setBounds(SkRect::Make(srcRect), HasAABloat::kNo, IsZeroArea::kNo);
-    }
-
-    void onPrepare(GrOpFlushState*) override {}
-
-    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
-
-    sk_sp<GrGpuBuffer> fDstBuffer;
-    size_t fDstOffset;
-    SkIRect fSrcRect;
-    GrColorType fSurfaceColorType;
-    GrColorType fDstColorType;
-
-    typedef GrOp INHERITED;
-};
-
-#endif
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 5ded878..0376a0f 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -64,30 +64,6 @@
     bool fShouldDiscardDst;
 };
 
-class TransferFrom : public GrVkPrimaryCommandBufferTask {
-public:
-    TransferFrom(const SkIRect& srcRect, GrColorType surfaceColorType, GrColorType bufferColorType,
-                 GrGpuBuffer* transferBuffer, size_t offset)
-            : fTransferBuffer(sk_ref_sp(transferBuffer))
-            , fOffset(offset)
-            , fSrcRect(srcRect)
-            , fSurfaceColorType(surfaceColorType)
-            , fBufferColorType(bufferColorType) {}
-
-    void execute(const Args& args) override {
-        args.fGpu->transferPixelsFrom(args.fSurface, fSrcRect.fLeft, fSrcRect.fTop,
-                                      fSrcRect.width(), fSrcRect.height(), fSurfaceColorType,
-                                      fBufferColorType, fTransferBuffer.get(), fOffset);
-    }
-
-private:
-    sk_sp<GrGpuBuffer> fTransferBuffer;
-    size_t fOffset;
-    SkIRect fSrcRect;
-    GrColorType fSurfaceColorType;
-    GrColorType fBufferColorType;
-};
-
 }  // anonymous namespace
 
 /////////////////////////////////////////////////////////////////////////////
@@ -98,13 +74,6 @@
     fTasks.emplace<Copy>(src, srcRect, dstPoint, false);
 }
 
-void GrVkGpuTextureCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                                               GrColorType bufferColorType,
-                                               GrGpuBuffer* transferBuffer, size_t offset) {
-    fTasks.emplace<TransferFrom>(srcRect, surfaceColorType, bufferColorType, transferBuffer,
-                                 offset);
-}
-
 void GrVkGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
     // TODO: does Vulkan have a correlate?
 }
@@ -613,18 +582,6 @@
     }
 }
 
-void GrVkGpuRTCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                                          GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                                          size_t offset) {
-    CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
-    if (!cbInfo.fIsEmpty) {
-        this->addAdditionalRenderPass();
-    }
-    fPreCommandBufferTasks.emplace<TransferFrom>(srcRect, surfaceColorType, bufferColorType,
-                                                 transferBuffer, offset);
-    ++fCommandBufferInfos[fCurrentCmdInfo].fNumPreCmds;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrVkGpuRTCommandBuffer::bindGeometry(const GrGpuBuffer* indexBuffer,
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index eb0d8cb..8666591 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -46,9 +46,6 @@
     GrVkGpuTextureCommandBuffer(GrVkGpu* gpu) : fGpu(gpu) {}
 
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override;
 
     void insertEventMarker(const char*) override;
 
@@ -104,9 +101,6 @@
     void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override;
 
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
-                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
-                      size_t offset) override;
 
     void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override;