Adds a GrTRecorder class that GrInOrderDrawBuffer uses to allocate
all its commands interleaved in contiguous memory. GrTRecorder also
supports extra data associated with objects, so we can store arrays
inline without having to call malloc().

Committed: https://skia.googlesource.com/skia/+/360b6801cfd90485891d709e44cf395d527ba69e

Review URL: https://codereview.chromium.org/628453002
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 485de07..5d0fc04 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -16,6 +16,7 @@
 #include "GrPath.h"
 #include "GrPathRange.h"
 #include "GrSurface.h"
+#include "GrTRecorder.h"
 #include "GrVertexBuffer.h"
 
 #include "SkClipStack.h"
@@ -87,7 +88,7 @@
     virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
 
 private:
-    enum Cmd {
+    enum {
         kDraw_Cmd           = 1,
         kStencilPath_Cmd    = 2,
         kSetState_Cmd       = 3,
@@ -98,37 +99,54 @@
         kDrawPaths_Cmd      = 8,
     };
 
-    class Draw : public DrawInfo {
-    public:
+    struct Cmd : ::SkNoncopyable {
+        Cmd(uint8_t type) : fType(type) {}
+        virtual ~Cmd() {}
+
+        virtual void execute(GrDrawTarget*) = 0;
+
+        uint8_t fType;
+    };
+
+    struct Draw : public Cmd {
         Draw(const DrawInfo& info, const GrVertexBuffer* vb, const GrIndexBuffer* ib)
-            : DrawInfo(info)
+            : Cmd(kDraw_Cmd)
+            , fInfo(info)
             , fVertexBuffer(vb)
             , fIndexBuffer(ib) {}
 
         const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
         const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
 
+        virtual void execute(GrDrawTarget*);
+
+        DrawInfo fInfo;
+
     private:
         GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType>    fVertexBuffer;
         GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType>     fIndexBuffer;
     };
 
-    struct StencilPath : public ::SkNoncopyable {
-        StencilPath(const GrPath* path) : fPath(path) {}
+    struct StencilPath : public Cmd {
+        StencilPath(const GrPath* path) : Cmd(kStencilPath_Cmd), fPath(path) {}
 
         const GrPath* path() const { return fPath.get(); }
 
+        virtual void execute(GrDrawTarget*);
+
         SkPath::FillType fFill;
 
     private:
         GrPendingIOResource<const GrPath, kRead_GrIOType>   fPath;
     };
 
-    struct DrawPath : public ::SkNoncopyable {
-        DrawPath(const GrPath* path) : fPath(path) {}
+    struct DrawPath : public Cmd {
+        DrawPath(const GrPath* path) : Cmd(kDrawPath_Cmd), fPath(path) {}
 
         const GrPath* path() const { return fPath.get(); }
 
+        virtual void execute(GrDrawTarget*);
+
         SkPath::FillType        fFill;
         GrDeviceCoordTexture    fDstCopy;
 
@@ -136,24 +154,16 @@
         GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
     };
 
-    struct DrawPaths : public ::SkNoncopyable {
-        DrawPaths(const GrPathRange* pathRange)
-            : fPathRange(pathRange) {}
-
-        ~DrawPaths() {
-            if (fTransforms) {
-                SkDELETE_ARRAY(fTransforms);
-            }
-            if (fIndices) {
-                SkDELETE_ARRAY(fIndices);
-            }
-        }
+    struct DrawPaths : public Cmd {
+        DrawPaths(const GrPathRange* pathRange) : Cmd(kDrawPaths_Cmd), fPathRange(pathRange) {}
 
         const GrPathRange* pathRange() const { return fPathRange.get();  }
+        uint32_t* indices() { return reinterpret_cast<uint32_t*>(CmdBuffer::GetDataForItem(this)); }
+        float* transforms() { return reinterpret_cast<float*>(&this->indices()[fCount]); }
 
-        uint32_t*               fIndices;
+        virtual void execute(GrDrawTarget*);
+
         size_t                  fCount;
-        float*                  fTransforms;
         PathTransformType       fTransformsType;
         SkPath::FillType        fFill;
         GrDeviceCoordTexture    fDstCopy;
@@ -163,11 +173,13 @@
     };
 
     // This is also used to record a discard by setting the color to GrColor_ILLEGAL
-    struct Clear : public ::SkNoncopyable {
-        Clear(GrRenderTarget* rt) : fRenderTarget(rt) {}
-        ~Clear() { }
+    struct Clear : public Cmd {
+        Clear(GrRenderTarget* rt) : Cmd(kClear_Cmd), fRenderTarget(rt) {}
+
         GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
 
+        virtual void execute(GrDrawTarget*);
+
         SkIRect fRect;
         GrColor fColor;
         bool    fCanIgnoreRect;
@@ -176,12 +188,14 @@
         GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
     };
 
-    struct CopySurface : public ::SkNoncopyable {
-        CopySurface(GrSurface* dst, GrSurface* src) : fDst(dst), fSrc(src) {}
+    struct CopySurface : public Cmd {
+        CopySurface(GrSurface* dst, GrSurface* src) : Cmd(kCopySurface_Cmd), fDst(dst), fSrc(src) {}
 
         GrSurface* dst() const { return fDst.get(); }
         GrSurface* src() const { return fSrc.get(); }
 
+        virtual void execute(GrDrawTarget*);
+
         SkIPoint    fDstPoint;
         SkIRect     fSrcRect;
 
@@ -190,11 +204,33 @@
         GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
     };
 
-    struct Clip : public ::SkNoncopyable {
-        SkClipStack fStack;
-        SkIPoint    fOrigin;
+    struct SetState : public Cmd {
+        SetState(const GrDrawState& state) : Cmd(kSetState_Cmd), fState(state) {}
+
+        virtual void execute(GrDrawTarget*);
+
+        GrDrawState fState;
     };
 
+    struct SetClip : public Cmd {
+        SetClip(const GrClipData* clipData)
+            : Cmd(kSetClip_Cmd),
+              fStackStorage(*clipData->fClipStack) {
+            fClipData.fClipStack = &fStackStorage;
+            fClipData.fOrigin = clipData->fOrigin;
+        }
+
+        virtual void execute(GrDrawTarget*);
+
+        GrClipData fClipData;
+
+    private:
+        SkClipStack fStackStorage;
+    };
+
+    typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
+    typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
+
     // overrides from GrDrawTarget
     virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
     virtual void onDrawRect(const SkRect& rect,
@@ -247,57 +283,25 @@
     // Determines whether the current draw operation requieres a new drawstate and if so records it.
     void recordStateIfNecessary();
     // We lazily record clip changes in order to skip clips that have no effect.
-    bool needsNewClip() const;
-
-    // these functions record a command
-    void            recordState();
-    void            recordClip();
-    Draw*           recordDraw(const DrawInfo&, const GrVertexBuffer*, const GrIndexBuffer*);
-    StencilPath*    recordStencilPath(const GrPath*);
-    DrawPath*       recordDrawPath(const GrPath*);
-    DrawPaths*      recordDrawPaths(const GrPathRange*);
-    Clear*          recordClear(GrRenderTarget*);
-    CopySurface*    recordCopySurface(GrSurface* dst, GrSurface* src);
+    void recordClipIfNecessary();
+    // Records any trace markers for a command after adding it to the buffer.
+    void recordTraceMarkersIfNecessary();
 
     virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
-    void addToCmdBuffer(uint8_t cmd);
 
     // TODO: Use a single allocator for commands and records
     enum {
-        kCmdPreallocCnt          = 32,
-        kDrawPreallocCnt         = 16,
-        kStencilPathPreallocCnt  = 8,
-        kDrawPathPreallocCnt     = 8,
-        kDrawPathsPreallocCnt    = 8,
-        kStatePreallocCnt        = 8,
-        kClipPreallocCnt         = 8,
-        kClearPreallocCnt        = 8,
-        kGeoPoolStatePreAllocCnt = 4,
-        kCopySurfacePreallocCnt  = 4,
+        kCmdBufferInitialSizeInBytes = 64 * 1024,
+        kGeoPoolStatePreAllocCnt     = 4,
     };
 
-    typedef GrTAllocator<Draw>          DrawAllocator;
-    typedef GrTAllocator<StencilPath>   StencilPathAllocator;
-    typedef GrTAllocator<DrawPath>      DrawPathAllocator;
-    typedef GrTAllocator<DrawPaths>     DrawPathsAllocator;
-    typedef GrTAllocator<GrDrawState>   StateAllocator;
-    typedef GrTAllocator<Clear>         ClearAllocator;
-    typedef GrTAllocator<CopySurface>   CopySurfaceAllocator;
-    typedef GrTAllocator<Clip>          ClipAllocator;
+    CmdBuffer                         fCmdBuffer;
+    GrDrawState*                      fLastState;
+    GrClipData*                       fLastClip;
 
-    GrSTAllocator<kDrawPreallocCnt, Draw>               fDraws;
-    GrSTAllocator<kStencilPathPreallocCnt, StencilPath> fStencilPaths;
-    GrSTAllocator<kDrawPathPreallocCnt, DrawPath>       fDrawPath;
-    GrSTAllocator<kDrawPathsPreallocCnt, DrawPaths>     fDrawPaths;
-    GrSTAllocator<kStatePreallocCnt, GrDrawState>       fStates;
-    GrSTAllocator<kClearPreallocCnt, Clear>             fClears;
-    GrSTAllocator<kCopySurfacePreallocCnt, CopySurface> fCopySurfaces;
-    GrSTAllocator<kClipPreallocCnt, Clip>               fClips;
-
-    SkTArray<GrTraceMarkerSet, false>                   fGpuCmdMarkers;
-    SkSTArray<kCmdPreallocCnt, uint8_t, true>           fCmds;
-    GrDrawTarget*                                       fDstGpu;
-    bool                                                fClipSet;
+    SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
+    GrDrawTarget*                     fDstGpu;
+    bool                              fClipSet;
 
     enum ClipProxyState {
         kUnknown_ClipProxyState,