GrCopySurfaceBatch

Review URL: https://codereview.chromium.org/1289673004
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index c0eae33..d227e91 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -228,6 +228,8 @@
       '<(skia_src_path)/gpu/batches/GrBatch.cpp',
       '<(skia_src_path)/gpu/batches/GrBatch.h',
       '<(skia_src_path)/gpu/batches/GrClearBatch.h',
+      '<(skia_src_path)/gpu/batches/GrCopySurfaceBatch.cpp',
+      '<(skia_src_path)/gpu/batches/GrCopySurfaceBatch.h',
       '<(skia_src_path)/gpu/batches/GrDiscardBatch.h',
       '<(skia_src_path)/gpu/batches/GrDrawBatch.cpp',
       '<(skia_src_path)/gpu/batches/GrDrawBatch.h',
diff --git a/src/gpu/GrBufferedDrawTarget.cpp b/src/gpu/GrBufferedDrawTarget.cpp
index 4959ddc..5e5d71e 100644
--- a/src/gpu/GrBufferedDrawTarget.cpp
+++ b/src/gpu/GrBufferedDrawTarget.cpp
@@ -89,13 +89,6 @@
     ++fDrawID;
 }
 
-void GrBufferedDrawTarget::onCopySurface(GrSurface* dst,
-                                         GrSurface* src,
-                                         const SkIRect& srcRect,
-                                         const SkIPoint& dstPoint) {
-    fCommands->recordCopySurface(dst, src, srcRect, dstPoint);
-}
-
 GrTargetCommands::StateForPathDraw*
 GrBufferedDrawTarget::createStateForPathDraw(const GrPrimitiveProcessor* primProc,
                                              const GrDrawTarget::PipelineInfo& pipelineInfo,
diff --git a/src/gpu/GrBufferedDrawTarget.h b/src/gpu/GrBufferedDrawTarget.h
index 962385e..dc409ef 100644
--- a/src/gpu/GrBufferedDrawTarget.h
+++ b/src/gpu/GrBufferedDrawTarget.h
@@ -91,10 +91,6 @@
                      int count,
                      const GrStencilSettings&,
                      const PipelineInfo&) override;
-    void onCopySurface(GrSurface* dst,
-                       GrSurface* src,
-                       const SkIRect& srcRect,
-                       const SkIPoint& dstPoint) override;
 
     bool isIssued(uint32_t drawID) override { return drawID != fDrawID; }
 
diff --git a/src/gpu/GrCommandBuilder.cpp b/src/gpu/GrCommandBuilder.cpp
index 2d86c1e..3a88ceb 100644
--- a/src/gpu/GrCommandBuilder.cpp
+++ b/src/gpu/GrCommandBuilder.cpp
@@ -17,14 +17,3 @@
         return SkNEW(GrInOrderCommandBuilder);
     }
 }
-
-GrTargetCommands::Cmd* GrCommandBuilder::recordCopySurface(GrSurface* dst,
-                                                           GrSurface* src,
-                                                           const SkIRect& srcRect,
-                                                           const SkIPoint& dstPoint) {
-    CopySurface* cs = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), CopySurface, (dst, src));
-    cs->fSrcRect = srcRect;
-    cs->fDstPoint = dstPoint;
-    GrBATCH_INFO("Recording copysurface %d\n", cs->uniqueID());
-    return cs;
-}
diff --git a/src/gpu/GrCommandBuilder.h b/src/gpu/GrCommandBuilder.h
index 473e0bf..ddf0ccf 100644
--- a/src/gpu/GrCommandBuilder.h
+++ b/src/gpu/GrCommandBuilder.h
@@ -47,17 +47,12 @@
                                  int,
                                  const GrStencilSettings&,
                                  const GrPipelineOptimizations&) = 0;
-    virtual Cmd* recordCopySurface(GrSurface* dst,
-                                   GrSurface* src,
-                                   const SkIRect& srcRect,
-                                   const SkIPoint& dstPoint);
 
 protected:
     typedef GrTargetCommands::DrawBatch DrawBatch;
     typedef GrTargetCommands::StencilPath StencilPath;
     typedef GrTargetCommands::DrawPath DrawPath;
     typedef GrTargetCommands::DrawPaths DrawPaths;
-    typedef GrTargetCommands::CopySurface CopySurface;
 
     GrCommandBuilder() {}
 
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 3926739..1102b18 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -21,6 +21,7 @@
 #include "GrVertexBuffer.h"
 
 #include "batches/GrClearBatch.h"
+#include "batches/GrCopySurfaceBatch.h"
 #include "batches/GrDiscardBatch.h"
 #include "batches/GrDrawBatch.h"
 #include "batches/GrRectBatchFactory.h"
@@ -398,79 +399,15 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-namespace {
-// returns true if the read/written rect intersects the src/dst and false if not.
-bool clip_srcrect_and_dstpoint(const GrSurface* dst,
-                               const GrSurface* src,
-                               const SkIRect& srcRect,
-                               const SkIPoint& dstPoint,
-                               SkIRect* clippedSrcRect,
-                               SkIPoint* clippedDstPoint) {
-    *clippedSrcRect = srcRect;
-    *clippedDstPoint = dstPoint;
-
-    // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
-    if (clippedSrcRect->fLeft < 0) {
-        clippedDstPoint->fX -= clippedSrcRect->fLeft;
-        clippedSrcRect->fLeft = 0;
-    }
-    if (clippedDstPoint->fX < 0) {
-        clippedSrcRect->fLeft -= clippedDstPoint->fX;
-        clippedDstPoint->fX = 0;
-    }
-
-    // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
-    if (clippedSrcRect->fTop < 0) {
-        clippedDstPoint->fY -= clippedSrcRect->fTop;
-        clippedSrcRect->fTop = 0;
-    }
-    if (clippedDstPoint->fY < 0) {
-        clippedSrcRect->fTop -= clippedDstPoint->fY;
-        clippedDstPoint->fY = 0;
-    }
-
-    // clip the right edge to the src and dst bounds.
-    if (clippedSrcRect->fRight > src->width()) {
-        clippedSrcRect->fRight = src->width();
-    }
-    if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
-        clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
-    }
-
-    // clip the bottom edge to the src and dst bounds.
-    if (clippedSrcRect->fBottom > src->height()) {
-        clippedSrcRect->fBottom = src->height();
-    }
-    if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
-        clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
-    }
-
-    // The above clipping steps may have inverted the rect if it didn't intersect either the src or
-    // dst bounds.
-    return !clippedSrcRect->isEmpty();
-}
-}
-
 void GrDrawTarget::copySurface(GrSurface* dst,
                                GrSurface* src,
                                const SkIRect& srcRect,
                                const SkIPoint& dstPoint) {
-    SkASSERT(dst);
-    SkASSERT(src);
-
-    SkIRect clippedSrcRect;
-    SkIPoint clippedDstPoint;
-    // If the rect is outside the src or dst then we've already succeeded.
-    if (!clip_srcrect_and_dstpoint(dst,
-                                   src,
-                                   srcRect,
-                                   dstPoint,
-                                   &clippedSrcRect,
-                                   &clippedDstPoint)) {
-        return;
+    GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
+    if (batch) {
+        this->onDrawBatch(batch);
+        batch->unref();
     }
-
-    this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index b2d4aa5..54531d2 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -262,13 +262,6 @@
                              const GrStencilSettings&,
                              const PipelineInfo&) = 0;
 
-    /** The subclass's copy surface implementation. It should assume that any clipping has already
-        been performed on the rect and point and that the GrGpu supports the copy. */
-    virtual void onCopySurface(GrSurface* dst,
-                               GrSurface* src,
-                               const SkIRect& srcRect,
-                               const SkIPoint& dstPoint) = 0;
-
     // Check to see if this set of draw commands has been sent out
     virtual bool       isIssued(uint32_t drawID) { return true; }
     void getPathStencilSettingsForFilltype(GrPathRendering::FillType,
diff --git a/src/gpu/GrImmediateDrawTarget.cpp b/src/gpu/GrImmediateDrawTarget.cpp
index dee30d2..66540e3 100644
--- a/src/gpu/GrImmediateDrawTarget.cpp
+++ b/src/gpu/GrImmediateDrawTarget.cpp
@@ -40,13 +40,6 @@
 #endif
 }
 
-void GrImmediateDrawTarget::onCopySurface(GrSurface* dst,
-                                          GrSurface* src,
-                                          const SkIRect& srcRect,
-                                          const SkIPoint& dstPoint) {
-    this->getGpu()->copySurface(dst, src, srcRect, dstPoint);
-}
-
 void GrImmediateDrawTarget::onReset() {}
 
 void GrImmediateDrawTarget::onFlush() {
diff --git a/src/gpu/GrImmediateDrawTarget.h b/src/gpu/GrImmediateDrawTarget.h
index e1baebe..440233f 100644
--- a/src/gpu/GrImmediateDrawTarget.h
+++ b/src/gpu/GrImmediateDrawTarget.h
@@ -57,10 +57,6 @@
                      const PipelineInfo&) override {
         SkFAIL("Only batch implemented\n");
     }
-    void onCopySurface(GrSurface* dst,
-                       GrSurface* src,
-                       const SkIRect& srcRect,
-                       const SkIPoint& dstPoint) override;
 
     bool isIssued(uint32_t drawID) override { return drawID != fDrawID; }
 
diff --git a/src/gpu/batches/GrCopySurfaceBatch.cpp b/src/gpu/batches/GrCopySurfaceBatch.cpp
new file mode 100644
index 0000000..2c859f8
--- /dev/null
+++ b/src/gpu/batches/GrCopySurfaceBatch.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 "GrCopySurfaceBatch.h"
+
+// returns true if the read/written rect intersects the src/dst and false if not.
+static bool clip_srcrect_and_dstpoint(const GrSurface* dst,
+                                      const GrSurface* src,
+                                      const SkIRect& srcRect,
+                                      const SkIPoint& dstPoint,
+                                      SkIRect* clippedSrcRect,
+                                      SkIPoint* clippedDstPoint) {
+    *clippedSrcRect = srcRect;
+    *clippedDstPoint = dstPoint;
+
+    // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
+    if (clippedSrcRect->fLeft < 0) {
+        clippedDstPoint->fX -= clippedSrcRect->fLeft;
+        clippedSrcRect->fLeft = 0;
+    }
+    if (clippedDstPoint->fX < 0) {
+        clippedSrcRect->fLeft -= clippedDstPoint->fX;
+        clippedDstPoint->fX = 0;
+    }
+
+    // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
+    if (clippedSrcRect->fTop < 0) {
+        clippedDstPoint->fY -= clippedSrcRect->fTop;
+        clippedSrcRect->fTop = 0;
+    }
+    if (clippedDstPoint->fY < 0) {
+        clippedSrcRect->fTop -= clippedDstPoint->fY;
+        clippedDstPoint->fY = 0;
+    }
+
+    // clip the right edge to the src and dst bounds.
+    if (clippedSrcRect->fRight > src->width()) {
+        clippedSrcRect->fRight = src->width();
+    }
+    if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
+        clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
+    }
+
+    // clip the bottom edge to the src and dst bounds.
+    if (clippedSrcRect->fBottom > src->height()) {
+        clippedSrcRect->fBottom = src->height();
+    }
+    if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
+        clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
+    }
+
+    // The above clipping steps may have inverted the rect if it didn't intersect either the src or
+    // dst bounds.
+    return !clippedSrcRect->isEmpty();
+}
+
+GrBatch* GrCopySurfaceBatch::Create(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+                                    const SkIPoint& dstPoint) {
+    SkASSERT(dst);
+    SkASSERT(src);
+
+    SkIRect clippedSrcRect;
+    SkIPoint clippedDstPoint;
+    // If the rect is outside the src or dst then we've already succeeded.
+    if (!clip_srcrect_and_dstpoint(dst,
+                                    src,
+                                    srcRect,
+                                    dstPoint,
+                                    &clippedSrcRect,
+                                    &clippedDstPoint)) {
+        return NULL;
+    }
+    return SkNEW_ARGS(GrCopySurfaceBatch, (dst, src, clippedSrcRect, clippedDstPoint));
+}
diff --git a/src/gpu/batches/GrCopySurfaceBatch.h b/src/gpu/batches/GrCopySurfaceBatch.h
new file mode 100644
index 0000000..584bbab
--- /dev/null
+++ b/src/gpu/batches/GrCopySurfaceBatch.h
@@ -0,0 +1,63 @@
+/*
+ * 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 GrCopySurfaceBatch_DEFINED
+#define GrCopySurfaceBatch_DEFINED
+
+#include "GrBatch.h"
+#include "GrBatchFlushState.h"
+#include "GrGpu.h"
+#include "GrRenderTarget.h"
+
+class GrCopySurfaceBatch final : public GrBatch {
+public:
+    static GrBatch* Create(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+                           const SkIPoint& dstPoint);
+
+    const char* name() const override { return "CopySurface"; }
+
+    uint32_t renderTargetUniqueID() const override {
+        GrRenderTarget* rt = fDst.get()->asRenderTarget();
+        return rt ? rt->getUniqueID() : 0;
+    }
+
+    SkString dumpInfo() const override {
+        SkString string;
+        string.printf("SRC: 0x%p, DST: 0x%p, SRECT: [L: %d, T: %d, R: %d, B: %d], "
+                      "DPT:[X: %d, Y: %d]",
+                      fDst.get(), fSrc.get(), fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight,
+                      fSrcRect.fBottom, fDstPoint.fX, fDstPoint.fY);
+        return string;
+    }
+
+private:
+    GrCopySurfaceBatch(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+                       const SkIPoint& dstPoint)
+        : fDst(dst)
+        , fSrc(src)
+        , fSrcRect(srcRect)
+        , fDstPoint(dstPoint) {
+        this->initClassID<GrCopySurfaceBatch>();        
+        fBounds = SkRect::MakeXYWH(SkIntToScalar(dstPoint.fX), SkIntToScalar(dstPoint.fY),
+                                   SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
+    }
+
+    bool onCombineIfPossible(GrBatch* that, const GrCaps& caps) override { return false; }
+
+    void onPrepare(GrBatchFlushState*) override {}
+
+    void onDraw(GrBatchFlushState* state) override {
+        state->gpu()->copySurface(fDst.get(), fSrc.get(), fSrcRect, fDstPoint);
+    }
+
+    GrPendingIOResource<GrSurface, kWrite_GrIOType> fDst;
+    GrPendingIOResource<GrSurface, kRead_GrIOType>  fSrc;
+    SkIRect                                         fSrcRect;
+    SkIPoint                                        fDstPoint;
+};
+
+#endif