Put drawPath in GrBatch.

TODO: Implement path range version of this (and preserve combining consecutive ranges).

Review URL: https://codereview.chromium.org/1301823002
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 55d2273..3e08a50 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -235,6 +235,7 @@
       '<(skia_src_path)/gpu/batches/GrDrawBatch.h',
       '<(skia_src_path)/gpu/batches/GrDrawAtlasBatch.cpp',
       '<(skia_src_path)/gpu/batches/GrDrawAtlasBatch.h',
+      '<(skia_src_path)/gpu/batches/GrDrawPathBatch.h',
       '<(skia_src_path)/gpu/batches/GrDrawVerticesBatch.cpp',
       '<(skia_src_path)/gpu/batches/GrDrawVerticesBatch.h',
       '<(skia_src_path)/gpu/batches/GrRectBatchFactory.h',
diff --git a/src/gpu/GrBufferedDrawTarget.cpp b/src/gpu/GrBufferedDrawTarget.cpp
index dde57d3..c733f0c 100644
--- a/src/gpu/GrBufferedDrawTarget.cpp
+++ b/src/gpu/GrBufferedDrawTarget.cpp
@@ -30,18 +30,6 @@
     fCommands->recordDrawBatch(batch, *this->caps());
 }
 
-void GrBufferedDrawTarget::onDrawPath(const GrPathProcessor* pathProc,
-                                      const GrPath* path,
-                                      const GrStencilSettings& stencilSettings,
-                                      const PipelineInfo& pipelineInfo) {
-    GrPipelineOptimizations opts;
-    StateForPathDraw* state = this->createStateForPathDraw(pathProc, pipelineInfo, &opts);
-    if (!state) {
-        return;
-    }
-    fCommands->recordDrawPath(state, pathProc, path, stencilSettings);
-}
-
 void GrBufferedDrawTarget::onDrawPaths(const GrPathProcessor* pathProc,
                                        const GrPathRange* pathRange,
                                        const void* indices,
diff --git a/src/gpu/GrBufferedDrawTarget.h b/src/gpu/GrBufferedDrawTarget.h
index 2dc92a5..f11a9d8 100644
--- a/src/gpu/GrBufferedDrawTarget.h
+++ b/src/gpu/GrBufferedDrawTarget.h
@@ -73,10 +73,6 @@
     void onReset() override;
     void onFlush() override;
 
-    void onDrawPath(const GrPathProcessor*,
-                    const GrPath*,
-                    const GrStencilSettings&,
-                    const PipelineInfo&) override;
     void onDrawPaths(const GrPathProcessor*,
                      const GrPathRange*,
                      const void* indices,
diff --git a/src/gpu/GrCommandBuilder.h b/src/gpu/GrCommandBuilder.h
index e29677d..876e9b1 100644
--- a/src/gpu/GrCommandBuilder.h
+++ b/src/gpu/GrCommandBuilder.h
@@ -27,10 +27,6 @@
     void flush(GrGpu* gpu, GrResourceProvider* rp) { fCommands.flush(gpu, rp); }
 
     virtual Cmd* recordDrawBatch(GrBatch*, const GrCaps&) = 0;
-    virtual Cmd* recordDrawPath(State*,
-                                const GrPathProcessor*,
-                                const GrPath*,
-                                const GrStencilSettings&) = 0;
     virtual Cmd* recordDrawPaths(State*,
                                  GrBufferedDrawTarget*,
                                  const GrPathProcessor*,
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index fc5599e..fed97a9 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -24,6 +24,7 @@
 #include "batches/GrCopySurfaceBatch.h"
 #include "batches/GrDiscardBatch.h"
 #include "batches/GrDrawBatch.h"
+#include "batches/GrDrawPathBatch.h"
 #include "batches/GrRectBatchFactory.h"
 #include "batches/GrStencilPathBatch.h"
 
@@ -130,8 +131,6 @@
 }
 
 void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
-    // TODO some kind of checkdraw, but not at this level
-
     // Setup clip
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
@@ -147,6 +146,7 @@
 
     GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, batch, &bounds,
                                             this);
+
     if (!pipelineInfo.valid()) {
         return;
     }
@@ -226,34 +226,44 @@
                             const GrPathProcessor* pathProc,
                             const GrPath* path,
                             GrPathRendering::FillType fill) {
-    // TODO: extract portions of checkDraw that are relevant to path rendering.
     SkASSERT(path);
     SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
 
-    SkRect devBounds = path->getBounds();
-    pathProc->viewMatrix().mapRect(&devBounds);
+    GrDrawPathBatch* batch = GrDrawPathBatch::Create(pathProc, path);
 
-    // Setup clip
+    // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted
+    // after setupClip() but before onDrawBatch(). TODO: Figure out a better model for handling
+    // stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and batches.
+
     GrScissorState scissorState;
     GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
     GrPipelineBuilder::AutoRestoreStencil ars;
-    if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &devBounds)) {
-       return;
+    if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &batch->bounds())) {
+        return;
     }
 
-    // set stencil settings for path
+    // Ensure the render target has a stencil buffer and get the stencil settings.
     GrStencilSettings stencilSettings;
     GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
     GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
     this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
+    batch->setStencilSettings(stencilSettings);
 
-    GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, pathProc, &devBounds,
-                                            this);
+    // Don't compute a bounding box for dst copy texture, we'll opt
+    // instead for it to just copy the entire dst. Realistically this is a moot
+    // point, because any context that supports NV_path_rendering will also
+    // support NV_blend_equation_advanced.
+    GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, batch, NULL, this);
+
     if (!pipelineInfo.valid()) {
         return;
     }
+    if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) {
+        return;
+    }
 
-    this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo);
+    this->onDrawBatch(batch);
+    batch->unref();
 }
 
 void GrDrawTarget::drawPaths(const GrPipelineBuilder& pipelineBuilder,
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 6ab34ab..14c7ae9 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -243,10 +243,6 @@
 
     virtual void onFlush() = 0;
 
-    virtual void onDrawPath(const GrPathProcessor*,
-                            const GrPath*,
-                            const GrStencilSettings&,
-                            const PipelineInfo&) = 0;
     virtual void onDrawPaths(const GrPathProcessor*,
                              const GrPathRange*,
                              const void* indices,
diff --git a/src/gpu/GrImmediateDrawTarget.h b/src/gpu/GrImmediateDrawTarget.h
index c70b624..1fabce4 100644
--- a/src/gpu/GrImmediateDrawTarget.h
+++ b/src/gpu/GrImmediateDrawTarget.h
@@ -33,12 +33,6 @@
     void onReset() override;
     void onFlush() override;
 
-    void onDrawPath(const GrPathProcessor*,
-                    const GrPath*,
-                    const GrStencilSettings&,
-                    const PipelineInfo&) override {
-        SkFAIL("Only batch implemented\n");
-    }
     void onDrawPaths(const GrPathProcessor*,
                      const GrPathRange*,
                      const void* indices,
diff --git a/src/gpu/GrInOrderCommandBuilder.cpp b/src/gpu/GrInOrderCommandBuilder.cpp
index 9c0d1a9..f69dbb4 100644
--- a/src/gpu/GrInOrderCommandBuilder.cpp
+++ b/src/gpu/GrInOrderCommandBuilder.cpp
@@ -42,16 +42,6 @@
 }
 
 GrTargetCommands::Cmd*
-GrInOrderCommandBuilder::recordDrawPath(State* state,
-                                        const GrPathProcessor* pathProc,
-                                        const GrPath* path,
-                                        const GrStencilSettings& stencilSettings) {
-    DrawPath* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPath, (state, path));
-    dp->fStencilSettings = stencilSettings;
-    return dp;
-}
-
-GrTargetCommands::Cmd*
 GrInOrderCommandBuilder::recordDrawPaths(State* state,
                                          GrBufferedDrawTarget* bufferedDrawTarget,
                                          const GrPathProcessor* pathProc,
diff --git a/src/gpu/GrInOrderCommandBuilder.h b/src/gpu/GrInOrderCommandBuilder.h
index 9768218..dbc978d 100644
--- a/src/gpu/GrInOrderCommandBuilder.h
+++ b/src/gpu/GrInOrderCommandBuilder.h
@@ -18,10 +18,6 @@
     GrInOrderCommandBuilder() : INHERITED() { }
 
     Cmd* recordDrawBatch(GrBatch*, const GrCaps&) override;
-    Cmd* recordDrawPath(State*,
-                        const GrPathProcessor*,
-                        const GrPath*,
-                        const GrStencilSettings&) override;
     Cmd* recordDrawPaths(State*,
                          GrBufferedDrawTarget*,
                          const GrPathProcessor*,
diff --git a/src/gpu/GrReorderCommandBuilder.h b/src/gpu/GrReorderCommandBuilder.h
index dbb5c80..a1c7fae 100644
--- a/src/gpu/GrReorderCommandBuilder.h
+++ b/src/gpu/GrReorderCommandBuilder.h
@@ -19,14 +19,6 @@
 
     Cmd* recordDrawBatch(GrBatch*, const GrCaps&) override;
 
-    Cmd* recordDrawPath(State*,
-                        const GrPathProcessor*,
-                        const GrPath*,
-                        const GrStencilSettings&) override {
-        SkFAIL("Unsupported\n");
-        return NULL;
-    }
-
     Cmd* recordDrawPaths(State*,
                          GrBufferedDrawTarget*,
                          const GrPathProcessor*,
diff --git a/src/gpu/batches/GrDrawPathBatch.h b/src/gpu/batches/GrDrawPathBatch.h
new file mode 100644
index 0000000..e60a660
--- /dev/null
+++ b/src/gpu/batches/GrDrawPathBatch.h
@@ -0,0 +1,75 @@
+/*
+ * 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 GrDrawPathBatch_DEFINED
+#define GrDrawPathBatch_DEFINED
+
+#include "GrDrawBatch.h"
+#include "GrGpu.h"
+#include "GrPath.h"
+#include "GrPathRendering.h"
+#include "GrPathProcessor.h"
+
+class GrDrawPathBatch final : public GrDrawBatch {
+public:
+    // This must return the concrete type because we install the stencil settings late :(
+    static GrDrawPathBatch* Create(const GrPathProcessor* primProc, const GrPath* path) {
+        return SkNEW_ARGS(GrDrawPathBatch, (primProc, path));
+    }
+
+    const char* name() const override { return "DrawPath"; }
+
+    SkString dumpInfo() const override {
+        SkString string;
+        string.printf("PATH: 0x%p", fPath.get());
+        return string;
+    }
+
+    virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const {
+        fPrimitiveProcessor->getInvariantOutputColor(out);
+    }
+
+    virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
+        fPrimitiveProcessor->getInvariantOutputCoverage(out);
+    }
+
+    void setStencilSettings(const GrStencilSettings& stencil) { fStencilSettings = stencil; }
+
+private:
+    GrBatchTracker* tracker() { return reinterpret_cast<GrBatchTracker*>(&fWhatchamacallit); }
+    GrDrawPathBatch(const GrPathProcessor* primProc, const GrPath* path)
+    : fPrimitiveProcessor(primProc)
+    , fPath(path) {
+        fBounds = path->getBounds();
+        primProc->viewMatrix().mapRect(&fBounds);
+        this->initClassID<GrDrawPathBatch>();
+    }
+
+    virtual void initBatchTracker(const GrPipelineOptimizations& opts) {
+        fPrimitiveProcessor->initBatchTracker(this->tracker(), opts);
+    }
+
+    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { return false; }
+
+    void onPrepare(GrBatchFlushState*) override {}
+
+    void onDraw(GrBatchFlushState* state) override {
+        GrProgramDesc  desc;
+        state->gpu()->buildProgramDesc(&desc, *fPrimitiveProcessor.get(),
+                                       *this->pipeline(), *this->tracker());
+        GrPathRendering::DrawPathArgs args(fPrimitiveProcessor.get(), this->pipeline(),
+                                           &desc, this->tracker(), &fStencilSettings);
+        state->gpu()->pathRendering()->drawPath(args, fPath.get());
+    }
+
+    GrPendingProgramElement<const GrPathProcessor>      fPrimitiveProcessor;
+    PathBatchTracker                                    fWhatchamacallit; // TODO: delete this
+    GrStencilSettings                                   fStencilSettings;
+    GrPendingIOResource<const GrPath, kRead_GrIOType>   fPath;
+};
+
+#endif