Create GrCommandBuilder

BUG=skia:

Review URL: https://codereview.chromium.org/1113313003
diff --git a/src/gpu/GrCommandBuilder.cpp b/src/gpu/GrCommandBuilder.cpp
new file mode 100644
index 0000000..aafc345
--- /dev/null
+++ b/src/gpu/GrCommandBuilder.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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 "GrCommandBuilder.h"
+
+#include "GrColor.h"
+#include "GrInOrderDrawBuffer.h"
+#include "GrTemplates.h"
+#include "SkPoint.h"
+
+static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
+    static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
+    bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
+    if (isWinding) {
+        // Double check that it is in fact winding.
+        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
+        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
+        SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
+        SkASSERT(!pathStencilSettings.isTwoSided());
+    }
+    return isWinding;
+}
+
+GrTargetCommands::Cmd* GrCommandBuilder::recordDrawBatch(State* state, GrBatch* batch) {
+    // Check if there is a Batch Draw we can batch with
+    if (!this->cmdBuffer()->empty() &&
+        Cmd::kDrawBatch_CmdType == this->cmdBuffer()->back().type()) {
+        DrawBatch* previous = static_cast<DrawBatch*>(&this->cmdBuffer()->back());
+        if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
+            return NULL;
+        }
+    }
+
+    return GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawBatch, (state, batch,
+                                                                    this->batchTarget()));
+}
+
+GrTargetCommands::Cmd*
+GrCommandBuilder::recordStencilPath(const GrPipelineBuilder& pipelineBuilder,
+                                    const GrPathProcessor* pathProc,
+                                    const GrPath* path,
+                                    const GrScissorState& scissorState,
+                                    const GrStencilSettings& stencilSettings) {
+    StencilPath* sp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), StencilPath,
+                                               (path, pipelineBuilder.getRenderTarget()));
+
+    sp->fScissor = scissorState;
+    sp->fUseHWAA = pipelineBuilder.isHWAntialias();
+    sp->fViewMatrix = pathProc->viewMatrix();
+    sp->fStencil = stencilSettings;
+    return sp;
+}
+
+GrTargetCommands::Cmd*
+GrCommandBuilder::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*
+GrCommandBuilder::recordDrawPaths(State* state,
+                                  GrInOrderDrawBuffer* iodb,
+                                  const GrPathProcessor* pathProc,
+                                  const GrPathRange* pathRange,
+                                  const void* indexValues,
+                                  GrDrawTarget::PathIndexType indexType,
+                                  const float transformValues[],
+                                  GrDrawTarget::PathTransformType transformType,
+                                  int count,
+                                  const GrStencilSettings& stencilSettings,
+                                  const GrDrawTarget::PipelineInfo& pipelineInfo) {
+    SkASSERT(pathRange);
+    SkASSERT(indexValues);
+    SkASSERT(transformValues);
+
+    char* savedIndices;
+    float* savedTransforms;
+
+    iodb->appendIndicesAndTransforms(indexValues, indexType,
+                                     transformValues, transformType,
+                                     count, &savedIndices, &savedTransforms);
+
+    if (!this->cmdBuffer()->empty() &&
+        Cmd::kDrawPaths_CmdType == this->cmdBuffer()->back().type()) {
+        // The previous command was also DrawPaths. Try to collapse this call into the one
+        // before. Note that stenciling all the paths at once, then covering, may not be
+        // equivalent to two separate draw calls if there is overlap. Blending won't work,
+        // and the combined calls may also cancel each other's winding numbers in some
+        // places. For now the winding numbers are only an issue if the fill is even/odd,
+        // because DrawPaths is currently only used for glyphs, and glyphs in the same
+        // font tend to all wind in the same direction.
+        DrawPaths* previous = static_cast<DrawPaths*>(&this->cmdBuffer()->back());
+        if (pathRange == previous->pathRange() &&
+            indexType == previous->fIndexType &&
+            transformType == previous->fTransformType &&
+            stencilSettings == previous->fStencilSettings &&
+            path_fill_type_is_winding(stencilSettings) &&
+            !pipelineInfo.willBlendWithDst(pathProc) &&
+            previous->fState == state) {
+                const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
+                const int xformSize = GrPathRendering::PathTransformSize(transformType);
+                if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
+                    (0 == xformSize ||
+                     &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
+                    // Fold this DrawPaths call into the one previous.
+                    previous->fCount += count;
+                    return NULL;
+                }
+        }
+    }
+
+    DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPaths, (state, pathRange));
+    dp->fIndices = savedIndices;
+    dp->fIndexType = indexType;
+    dp->fTransforms = savedTransforms;
+    dp->fTransformType = transformType;
+    dp->fCount = count;
+    dp->fStencilSettings = stencilSettings;
+    return dp;
+}
+
+GrTargetCommands::Cmd* GrCommandBuilder::recordClear(const SkIRect* rect,
+                                                     GrColor color,
+                                                     bool canIgnoreRect,
+                                                     GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
+
+    SkIRect r;
+    if (NULL == rect) {
+        // We could do something smart and remove previous draws and clears to
+        // the current render target. If we get that smart we have to make sure
+        // those draws aren't read before this clear (render-to-texture).
+        r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
+        rect = &r;
+    }
+    Clear* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), Clear, (renderTarget));
+    GrColorIsPMAssert(color);
+    clr->fColor = color;
+    clr->fRect = *rect;
+    clr->fCanIgnoreRect = canIgnoreRect;
+    return clr;
+}
+
+GrTargetCommands::Cmd* GrCommandBuilder::recordClearStencilClip(const SkIRect& rect,
+                                                                bool insideClip,
+                                                                GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
+
+    ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(),
+                                                     ClearStencilClip,
+                                                     (renderTarget));
+    clr->fRect = rect;
+    clr->fInsideClip = insideClip;
+    return clr;
+}
+
+GrTargetCommands::Cmd* GrCommandBuilder::recordDiscard(GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
+
+    Clear* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), Clear, (renderTarget));
+    clr->fColor = GrColor_ILLEGAL;
+    return clr;
+}
+
+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;
+    return cs;
+}
+
+GrTargetCommands::Cmd*
+GrCommandBuilder::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
+                                               const GrDrawTargetCaps& caps) {
+    const GrXferProcessor& xp = *pipeline.getXferProcessor();
+    GrRenderTarget* rt = pipeline.getRenderTarget();
+
+    GrXferBarrierType barrierType;
+    if (!xp.willNeedXferBarrier(rt, caps, &barrierType)) {
+        return NULL;
+    }
+
+    XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), XferBarrier, ());
+    xb->fBarrierType = barrierType;
+    return xb;
+}
diff --git a/src/gpu/GrCommandBuilder.h b/src/gpu/GrCommandBuilder.h
new file mode 100644
index 0000000..165c2c2
--- /dev/null
+++ b/src/gpu/GrCommandBuilder.h
@@ -0,0 +1,85 @@
+/*
+ * 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 GrCommandBuilder_DEFINED
+#define GrCommandBuilder_DEFINED
+
+#include "GrTargetCommands.h"
+
+class GrInOrderDrawBuffer;
+class GrVertexBufferAllocPool;
+class GrIndexBufferAllocPool;
+
+class GrCommandBuilder : ::SkNoncopyable {
+public:
+    typedef GrTargetCommands::Cmd Cmd;
+    typedef GrTargetCommands::State State;
+
+    GrCommandBuilder(GrGpu* gpu,
+                     GrVertexBufferAllocPool* vertexPool,
+                     GrIndexBufferAllocPool* indexPool)
+        : fCommands(gpu, vertexPool, indexPool) {
+    }
+
+    virtual ~GrCommandBuilder() {}
+
+    void reset() { fCommands.reset(); }
+    void flush(GrInOrderDrawBuffer* iodb) { fCommands.flush(iodb); }
+
+    virtual Cmd* recordClearStencilClip(const SkIRect& rect,
+                                        bool insideClip,
+                                        GrRenderTarget* renderTarget);
+    virtual Cmd* recordDiscard(GrRenderTarget*);
+    virtual Cmd* recordDrawBatch(State*, GrBatch*);
+    virtual Cmd* recordStencilPath(const GrPipelineBuilder&,
+                                   const GrPathProcessor*,
+                                   const GrPath*,
+                                   const GrScissorState&,
+                                   const GrStencilSettings&);
+    virtual Cmd* recordDrawPath(State*,
+                                const GrPathProcessor*,
+                                const GrPath*,
+                                const GrStencilSettings&);
+    virtual Cmd* recordDrawPaths(State*,
+                                 GrInOrderDrawBuffer*,
+                                 const GrPathProcessor*,
+                                 const GrPathRange*,
+                                 const void*,
+                                 GrDrawTarget::PathIndexType,
+                                 const float transformValues[],
+                                 GrDrawTarget::PathTransformType ,
+                                 int,
+                                 const GrStencilSettings&,
+                                 const GrDrawTarget::PipelineInfo&);
+    virtual Cmd* recordClear(const SkIRect* rect,
+                             GrColor,
+                             bool canIgnoreRect,
+                             GrRenderTarget*);
+    virtual Cmd* recordCopySurface(GrSurface* dst,
+                                   GrSurface* src,
+                                   const SkIRect& srcRect,
+                                   const SkIPoint& dstPoint);
+    virtual Cmd* recordXferBarrierIfNecessary(const GrPipeline&, const GrDrawTargetCaps&);
+
+private:
+    typedef GrTargetCommands::DrawBatch DrawBatch;
+    typedef GrTargetCommands::StencilPath StencilPath;
+    typedef GrTargetCommands::DrawPath DrawPath;
+    typedef GrTargetCommands::DrawPaths DrawPaths;
+    typedef GrTargetCommands::Clear Clear;
+    typedef GrTargetCommands::ClearStencilClip ClearStencilClip;
+    typedef GrTargetCommands::CopySurface CopySurface;
+    typedef GrTargetCommands::XferBarrier XferBarrier;
+
+    GrTargetCommands::CmdBuffer* cmdBuffer() { return fCommands.cmdBuffer(); }
+    GrBatchTarget* batchTarget() { return fCommands.batchTarget(); }
+
+    GrTargetCommands fCommands;
+
+};
+
+#endif
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index c584181..458e6e1 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -373,6 +373,7 @@
     bool programUnitTest(int maxStages);
 
 protected:
+    friend class GrCommandBuilder; // for PipelineInfo
     friend class GrTargetCommands; // for PipelineInfo
 
     GrContext* getContext() { return fContext; }
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index a766af2..1e8f3ae 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -14,7 +14,7 @@
                                          GrVertexBufferAllocPool* vertexPool,
                                          GrIndexBufferAllocPool* indexPool)
     : INHERITED(context, vertexPool, indexPool)
-    , fCommands(context->getGpu(), vertexPool, indexPool)
+    , fCommands(SkNEW_ARGS(GrCommandBuilder, (context->getGpu(), vertexPool, indexPool)))
     , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4)
     , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4)
     , fPipelineBuffer(kPipelineBufferMinReserve)
@@ -272,7 +272,7 @@
         return;
     }
 
-    GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(state, batch);
+    GrTargetCommands::Cmd* cmd = fCommands->recordDrawBatch(state, batch);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
@@ -281,9 +281,9 @@
                                         const GrPath* path,
                                         const GrScissorState& scissorState,
                                         const GrStencilSettings& stencilSettings) {
-    GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(pipelineBuilder,
-                                                             pathProc, path, scissorState,
-                                                             stencilSettings);
+    GrTargetCommands::Cmd* cmd = fCommands->recordStencilPath(pipelineBuilder,
+                                                              pathProc, path, scissorState,
+                                                              stencilSettings);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
@@ -295,7 +295,7 @@
     if (!state) {
         return;
     }
-    GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(state, pathProc, path, stencilSettings);
+    GrTargetCommands::Cmd* cmd = fCommands->recordDrawPath(state, pathProc, path, stencilSettings);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
@@ -312,23 +312,23 @@
     if (!state) {
         return;
     }
-    GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(state, this, pathProc, pathRange,
-                                                           indices, indexType, transformValues,
-                                                           transformType, count,
-                                                           stencilSettings, pipelineInfo);
+    GrTargetCommands::Cmd* cmd = fCommands->recordDrawPaths(state, this, pathProc, pathRange,
+                                                            indices, indexType, transformValues,
+                                                            transformType, count,
+                                                            stencilSettings, pipelineInfo);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
                                   bool canIgnoreRect, GrRenderTarget* renderTarget) {
-    GrTargetCommands::Cmd* cmd = fCommands.recordClear(rect, color, canIgnoreRect, renderTarget);
+    GrTargetCommands::Cmd* cmd = fCommands->recordClear(rect, color, canIgnoreRect, renderTarget);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
                                            bool insideClip,
                                            GrRenderTarget* renderTarget) {
-    GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(rect, insideClip, renderTarget);
+    GrTargetCommands::Cmd* cmd = fCommands->recordClearStencilClip(rect, insideClip, renderTarget);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
@@ -337,12 +337,12 @@
         return;
     }
 
-    GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(renderTarget);
+    GrTargetCommands::Cmd* cmd = fCommands->recordDiscard(renderTarget);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
 void GrInOrderDrawBuffer::onReset() {
-    fCommands.reset();
+    fCommands->reset();
     fPathIndexBuffer.rewind();
     fPathTransformBuffer.rewind();
     fGpuCmdMarkers.reset();
@@ -358,7 +358,7 @@
 }
 
 void GrInOrderDrawBuffer::onFlush() {
-    fCommands.flush(this);
+    fCommands->flush(this);
     ++fDrawID;
 }
 
@@ -367,7 +367,7 @@
                                         const SkIRect& srcRect,
                                         const SkIPoint& dstPoint) {
     SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
-    GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(dst, src, srcRect, dstPoint);
+    GrTargetCommands::Cmd* cmd = fCommands->recordCopySurface(dst, src, srcRect, dstPoint);
     this->recordTraceMarkersIfNecessary(cmd);
 }
 
@@ -410,7 +410,8 @@
         fPrevState.reset(state);
     }
 
-    fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this);
+    this->recordTraceMarkersIfNecessary(
+            fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
     return fPrevState;
 }
 
@@ -434,6 +435,7 @@
         fPrevState.reset(state);
     }
 
-    fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this);
+    this->recordTraceMarkersIfNecessary(
+            fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
     return fPrevState;
 }
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index b253768..264d2a7 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -9,7 +9,7 @@
 #define GrInOrderDrawBuffer_DEFINED
 
 #include "GrDrawTarget.h"
-#include "GrTargetCommands.h"
+#include "GrCommandBuilder.h"
 #include "SkChunkAlloc.h"
 
 /**
@@ -71,6 +71,7 @@
     }
 
 private:
+    friend class GrCommandBuilder;
     friend class GrTargetCommands;
     typedef GrTargetCommands::State State;
 
@@ -148,7 +149,7 @@
     // highwater mark
     static const int kPipelineBufferHighWaterMark = 100;
 
-    GrTargetCommands                    fCommands;
+    SkAutoTDelete<GrCommandBuilder>     fCommands;
     SkTArray<GrTraceMarkerSet, false>   fGpuCmdMarkers;
     SkChunkAlloc                        fPathIndexBuffer;
     SkChunkAlloc                        fPathTransformBuffer;
diff --git a/src/gpu/GrTargetCommands.cpp b/src/gpu/GrTargetCommands.cpp
index d68a242..bf1a7af 100644
--- a/src/gpu/GrTargetCommands.cpp
+++ b/src/gpu/GrTargetCommands.cpp
@@ -7,164 +7,7 @@
 
 #include "GrTargetCommands.h"
 
-#include "GrColor.h"
-#include "GrDefaultGeoProcFactory.h"
 #include "GrInOrderDrawBuffer.h"
-#include "GrTemplates.h"
-#include "SkPoint.h"
-
-static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
-    static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
-    bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
-    if (isWinding) {
-        // Double check that it is in fact winding.
-        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
-        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
-        SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
-        SkASSERT(!pathStencilSettings.isTwoSided());
-    }
-    return isWinding;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch(State* state, GrBatch* batch) {
-    // Check if there is a Batch Draw we can batch with
-    if (!fCmdBuffer.empty() && Cmd::kDrawBatch_CmdType == fCmdBuffer.back().type()) {
-        DrawBatch* previous = static_cast<DrawBatch*>(&fCmdBuffer.back());
-        if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
-            return NULL;
-        }
-    }
-
-    return GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (state, batch, &fBatchTarget));
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath(
-                                                        const GrPipelineBuilder& pipelineBuilder,
-                                                        const GrPathProcessor* pathProc,
-                                                        const GrPath* path,
-                                                        const GrScissorState& scissorState,
-                                                        const GrStencilSettings& stencilSettings) {
-    StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
-                                               (path, pipelineBuilder.getRenderTarget()));
-
-    sp->fScissor = scissorState;
-    sp->fUseHWAA = pipelineBuilder.isHWAntialias();
-    sp->fViewMatrix = pathProc->viewMatrix();
-    sp->fStencil = stencilSettings;
-    return sp;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath(
-                                                  State* state,
-                                                  const GrPathProcessor* pathProc,
-                                                  const GrPath* path,
-                                                  const GrStencilSettings& stencilSettings) {
-    DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (state, path));
-    dp->fStencilSettings = stencilSettings;
-    return dp;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
-                                                  State* state,
-                                                  GrInOrderDrawBuffer* iodb,
-                                                  const GrPathProcessor* pathProc,
-                                                  const GrPathRange* pathRange,
-                                                  const void* indexValues,
-                                                  GrDrawTarget::PathIndexType indexType,
-                                                  const float transformValues[],
-                                                  GrDrawTarget::PathTransformType transformType,
-                                                  int count,
-                                                  const GrStencilSettings& stencilSettings,
-                                                  const GrDrawTarget::PipelineInfo& pipelineInfo) {
-    SkASSERT(pathRange);
-    SkASSERT(indexValues);
-    SkASSERT(transformValues);
-
-    char* savedIndices;
-    float* savedTransforms;
-    
-    iodb->appendIndicesAndTransforms(indexValues, indexType,
-                                     transformValues, transformType,
-                                     count, &savedIndices, &savedTransforms);
-
-    if (!fCmdBuffer.empty() && Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
-        // The previous command was also DrawPaths. Try to collapse this call into the one
-        // before. Note that stenciling all the paths at once, then covering, may not be
-        // equivalent to two separate draw calls if there is overlap. Blending won't work,
-        // and the combined calls may also cancel each other's winding numbers in some
-        // places. For now the winding numbers are only an issue if the fill is even/odd,
-        // because DrawPaths is currently only used for glyphs, and glyphs in the same
-        // font tend to all wind in the same direction.
-        DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
-        if (pathRange == previous->pathRange() &&
-            indexType == previous->fIndexType &&
-            transformType == previous->fTransformType &&
-            stencilSettings == previous->fStencilSettings &&
-            path_fill_type_is_winding(stencilSettings) &&
-            !pipelineInfo.willBlendWithDst(pathProc) &&
-            previous->fState == state) {
-                const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
-                const int xformSize = GrPathRendering::PathTransformSize(transformType);
-                if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
-                    (0 == xformSize ||
-                     &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
-                    // Fold this DrawPaths call into the one previous.
-                    previous->fCount += count;
-                    return NULL;
-                }
-        }
-    }
-
-    DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (state, pathRange));
-    dp->fIndices = savedIndices;
-    dp->fIndexType = indexType;
-    dp->fTransforms = savedTransforms;
-    dp->fTransformType = transformType;
-    dp->fCount = count;
-    dp->fStencilSettings = stencilSettings;
-    return dp;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordClear(const SkIRect* rect,
-                                                     GrColor color,
-                                                     bool canIgnoreRect,
-                                                     GrRenderTarget* renderTarget) {
-    SkASSERT(renderTarget);
-
-    SkIRect r;
-    if (NULL == rect) {
-        // We could do something smart and remove previous draws and clears to
-        // the current render target. If we get that smart we have to make sure
-        // those draws aren't read before this clear (render-to-texture).
-        r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
-        rect = &r;
-    }
-    Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
-    GrColorIsPMAssert(color);
-    clr->fColor = color;
-    clr->fRect = *rect;
-    clr->fCanIgnoreRect = canIgnoreRect;
-    return clr;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(const SkIRect& rect,
-                                                                bool insideClip,
-                                                                GrRenderTarget* renderTarget) {
-    SkASSERT(renderTarget);
-
-    ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
-    clr->fRect = rect;
-    clr->fInsideClip = insideClip;
-    return clr;
-}
-
-GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrRenderTarget* renderTarget) {
-    SkASSERT(renderTarget);
-
-    Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
-    clr->fColor = GrColor_ILLEGAL;
-    return clr;
-}
 
 void GrTargetCommands::reset() {
     fCmdBuffer.reset();
@@ -271,30 +114,3 @@
 void GrTargetCommands::XferBarrier::execute(GrGpu* gpu) {
     gpu->xferBarrier(fBarrierType);
 }
-
-GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrSurface* dst,
-                                                           GrSurface* src,
-                                                           const SkIRect& srcRect,
-                                                           const SkIPoint& dstPoint) {
-    CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
-    cs->fSrcRect = srcRect;
-    cs->fDstPoint = dstPoint;
-    return cs;
-}
-
-void GrTargetCommands::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
-                                                    GrInOrderDrawBuffer* iodb) {
-    const GrXferProcessor& xp = *pipeline.getXferProcessor();
-    GrRenderTarget* rt = pipeline.getRenderTarget();
-
-    GrXferBarrierType barrierType;
-    if (!xp.willNeedXferBarrier(rt, *iodb->caps(), &barrierType)) {
-        return;
-    }
-
-    XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, ());
-    xb->fBarrierType = barrierType;
-
-    iodb->recordTraceMarkersIfNecessary(xb);
-}
-
diff --git a/src/gpu/GrTargetCommands.h b/src/gpu/GrTargetCommands.h
index 4dfad2f..aaecac6 100644
--- a/src/gpu/GrTargetCommands.h
+++ b/src/gpu/GrTargetCommands.h
@@ -24,9 +24,6 @@
 class GrIndexBufferAllocPool;
 
 class GrTargetCommands : ::SkNoncopyable {
-    struct State;
-    struct SetState;
-
 public:
     GrTargetCommands(GrGpu* gpu,
                      GrVertexBufferAllocPool* vertexPool,
@@ -68,43 +65,9 @@
     void reset();
     void flush(GrInOrderDrawBuffer*);
 
-    Cmd* recordClearStencilClip(const SkIRect& rect,
-                                bool insideClip,
-                                GrRenderTarget* renderTarget);
-
-    Cmd* recordDiscard(GrRenderTarget*);
-    Cmd* recordDrawBatch(State*, GrBatch*);
-    Cmd* recordStencilPath(const GrPipelineBuilder&,
-                           const GrPathProcessor*,
-                           const GrPath*,
-                           const GrScissorState&,
-                           const GrStencilSettings&);
-    Cmd* recordDrawPath(State*,
-                        const GrPathProcessor*,
-                        const GrPath*,
-                        const GrStencilSettings&);
-    Cmd* recordDrawPaths(State*,
-                         GrInOrderDrawBuffer*,
-                         const GrPathProcessor*,
-                         const GrPathRange*,
-                         const void*,
-                         GrDrawTarget::PathIndexType,
-                         const float transformValues[],
-                         GrDrawTarget::PathTransformType ,
-                         int,
-                         const GrStencilSettings&,
-                         const GrDrawTarget::PipelineInfo&);
-    Cmd* recordClear(const SkIRect* rect,
-                     GrColor,
-                     bool canIgnoreRect,
-                     GrRenderTarget*);
-    Cmd* recordCopySurface(GrSurface* dst,
-                           GrSurface* src,
-                           const SkIRect& srcRect,
-                           const SkIPoint& dstPoint);
-
 private:
-    friend class GrInOrderDrawBuffer;
+    friend class GrCommandBuilder;
+    friend class GrInOrderDrawBuffer; // This goes away when State becomes just a pipeline
 
     typedef GrGpu::DrawArgs DrawArgs;
 
@@ -293,6 +256,9 @@
     typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
     typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
 
+    CmdBuffer* cmdBuffer() { return &fCmdBuffer; }
+    GrBatchTarget* batchTarget() { return &fBatchTarget; }
+
     CmdBuffer                           fCmdBuffer;
     GrBatchTarget                       fBatchTarget;
 };