Add GrDrawTarget::DrawInfo, combine API for performing indexed/non-indexed draws in subclasses.
Review URL: https://codereview.appspot.com/7237045

git-svn-id: http://skia.googlecode.com/svn/trunk@7466 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 3898426..d2d1d8d 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -341,20 +341,28 @@
 void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
                                int startIndex, int vertexCount,
                                int indexCount) {
-    if (indexCount > 0 &&
-        this->checkDraw(type, startVertex, startIndex,
-                        vertexCount, indexCount)) {
-        this->onDrawIndexed(type, startVertex, startIndex,
-                            vertexCount, indexCount);
+    if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
+        DrawInfo info;
+        info.fPrimitiveType = type;
+        info.fStartVertex   = startVertex;
+        info.fStartIndex    = startIndex;
+        info.fVertexCount   = vertexCount;
+        info.fIndexCount    = indexCount;
+        this->onDraw(info);
     }
 }
 
 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) {
-    if (vertexCount > 0 &&
-        this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
-        this->onDrawNonIndexed(type, startVertex, vertexCount);
+    if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
+        DrawInfo info;
+        info.fPrimitiveType = type;
+        info.fStartVertex   = startVertex;
+        info.fStartIndex    = 0;
+        info.fVertexCount   = vertexCount;
+        info.fIndexCount    = 0;
+        this->onDraw(info);
     }
 }
 
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 74d820b..2d1ca6c 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -727,6 +727,37 @@
 
     Caps fCaps;
 
+    class DrawInfo {
+    public:
+        DrawInfo(const DrawInfo& di) { (*this) = di; }
+        DrawInfo& operator =(const DrawInfo& di) {
+            fPrimitiveType  = di.fPrimitiveType;
+            fStartVertex    = di.fStartVertex;
+            fStartIndex     = di.fStartIndex;
+            fVertexCount    = di.fVertexCount;
+            fIndexCount     = di.fIndexCount;
+            return *this;
+        }
+
+        GrPrimitiveType primitiveType() const { return fPrimitiveType; }
+        int startVertex() const { return fStartVertex; }
+        int startIndex() const { return fStartIndex; }
+        int vertexCount() const { return fVertexCount; }
+        int indexCount() const { return fIndexCount; }
+
+        bool isIndexed() const { return fIndexCount > 0; }
+
+    private:
+        DrawInfo() {}
+        friend class GrDrawTarget;
+        GrPrimitiveType fPrimitiveType;
+
+        int             fStartVertex;
+        int             fStartIndex;
+        int             fVertexCount;
+        int             fIndexCount;
+    };
+
 private:
     // A subclass can optionally overload this function to be notified before
     // vertex and index space is reserved.
@@ -748,14 +779,7 @@
     virtual void geometrySourceWillPush() = 0;
     virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) = 0;
     // subclass called to perform drawing
-    virtual void onDrawIndexed(GrPrimitiveType type,
-                               int startVertex,
-                               int startIndex,
-                               int vertexCount,
-                               int indexCount) = 0;
-    virtual void onDrawNonIndexed(GrPrimitiveType type,
-                                  int startVertex,
-                                  int vertexCount) = 0;
+    virtual void onDraw(const DrawInfo&) = 0;
     virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType fill) = 0;
 
     // helpers for reserving vertex and index space.
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index b32c56a..b0ce7fe 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -371,45 +371,18 @@
     fGeomPoolStateStack.pop_back();
 }
 
-void GrGpu::onDrawIndexed(GrPrimitiveType type,
-                          int startVertex,
-                          int startIndex,
-                          int vertexCount,
-                          int indexCount) {
-
+void GrGpu::onDraw(const DrawInfo& info) {
     this->handleDirtyContext();
-
-    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
+    if (!this->setupClipAndFlushState(PrimTypeToDrawType(info.primitiveType()))) {
         return;
     }
-
-    int sVertex = startVertex;
-    int sIndex = startIndex;
-    setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
-
-    this->onGpuDrawIndexed(type, sVertex, sIndex,
-                           vertexCount, indexCount);
-}
-
-void GrGpu::onDrawNonIndexed(GrPrimitiveType type,
-                             int startVertex,
-                             int vertexCount) {
-    this->handleDirtyContext();
-
-    if (!this->setupClipAndFlushState(PrimTypeToDrawType(type))) {
-        return;
-    }
-
-    int sVertex = startVertex;
-    setupGeometry(&sVertex, NULL, vertexCount, 0);
-
-    this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
+    this->onGpuDraw(info);
 }
 
 void GrGpu::onStencilPath(const GrPath* path, const SkStrokeRec&, SkPath::FillType fill) {
     this->handleDirtyContext();
 
-    // TODO: make this more effecient (don't copy and copy back)
+    // TODO: make this more efficient (don't copy and copy back)
     GrAutoTRestore<GrStencilSettings> asr(this->drawState()->stencil());
 
     this->setStencilPathSettings(*path, fill, this->drawState()->stencil());
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 573ef0a..ebfc60f 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -317,7 +317,7 @@
 
     /**
      * These methods are called by the clip manager's setupClipping function
-     * which (called as part of GrGpu's implementation of onDraw* and
+     * which (called as part of GrGpu's implementation of onDraw and
      * onStencilPath member functions.) The GrGpu subclass should flush the
      * stencil state to the 3D API in its implementation of flushGraphicsState.
      */
@@ -454,15 +454,7 @@
     virtual void onClear(const GrIRect* rect, GrColor color) = 0;
 
     // overridden by backend-specific derived class to perform the draw call.
-    virtual void onGpuDrawIndexed(GrPrimitiveType type,
-                                  uint32_t startVertex,
-                                  uint32_t startIndex,
-                                  uint32_t vertexCount,
-                                  uint32_t indexCount) = 0;
-
-    virtual void onGpuDrawNonIndexed(GrPrimitiveType type,
-                                     uint32_t vertexCount,
-                                     uint32_t numVertices) = 0;
+    virtual void onGpuDraw(const DrawInfo&) = 0;
     // when GrDrawTarget::stencilPath is called the draw state's current stencil
     // settings are ignored. Instead the GrGpu decides the stencil rules
     // necessary to stencil the path. These are still subject to filtering by
@@ -493,24 +485,13 @@
     // overridden by backend-specific derived class to perform the resolve
     virtual void onResolveRenderTarget(GrRenderTarget* target) = 0;
 
-    // called to program the vertex data, indexCount will be 0 if drawing non-
-    // indexed geometry. The subclass may adjust the startVertex and/or
-    // startIndex since it may have already accounted for these in the setup.
-    virtual void setupGeometry(int* startVertex,
-                               int* startIndex,
-                               int vertexCount,
-                               int indexCount) = 0;
-
     // width and height may be larger than rt (if underlying API allows it).
     // Should attach the SB to the RT. Returns false if compatible sb could
     // not be created.
-    virtual bool createStencilBufferForRenderTarget(GrRenderTarget* rt,
-                                                    int width,
-                                                    int height) = 0;
+    virtual bool createStencilBufferForRenderTarget(GrRenderTarget*, int width, int height) = 0;
 
     // attaches an existing SB to an existing RT.
-    virtual bool attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
-                                                   GrRenderTarget* rt) = 0;
+    virtual bool attachStencilBufferToRenderTarget(GrStencilBuffer*, GrRenderTarget*) = 0;
 
     // The GrGpu typically records the clients requested state and then flushes
     // deltas from previous state at draw time. This function does the
@@ -525,14 +506,7 @@
     bool attachStencilBufferToRenderTarget(GrRenderTarget* target);
 
     // GrDrawTarget overrides
-    virtual void onDrawIndexed(GrPrimitiveType type,
-                               int startVertex,
-                               int startIndex,
-                               int vertexCount,
-                               int indexCount) SK_OVERRIDE;
-    virtual void onDrawNonIndexed(GrPrimitiveType type,
-                                  int startVertex,
-                                  int vertexCount) SK_OVERRIDE;
+    virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
     virtual void onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
                                SkPath::FillType) SK_OVERRIDE;
 
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 7e83589..197cf0b 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -217,7 +217,7 @@
 
             int vsize = GrDrawState::VertexSize(layout);
 
-            Draw& lastDraw = fDraws.back();
+            DrawRecord& lastDraw = fDraws.back();
 
             GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
             GrAssert(kTriangles_GrPrimitiveType == lastDraw.fPrimitiveType);
@@ -227,10 +227,10 @@
 
             GeometryPoolState& poolState = fGeoPoolStateStack.back();
 
-            appendToPreviousDraw =
-                kDraw_Cmd == fCmds.back() &&
-                lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
-                (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
+            appendToPreviousDraw = kDraw_Cmd == fCmds.back() &&
+                                   lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
+                                   (fCurrQuad * 4 + lastDraw.fStartVertex) ==
+                                   poolState.fPoolStartVertex;
 
             if (appendToPreviousDraw) {
                 lastDraw.fVertexCount += 4;
@@ -279,7 +279,7 @@
             this->recordState();
         }
 
-        Draw* draw = NULL;
+        DrawRecord* draw = NULL;
         // if the last draw used the same indices/vertices per shape then we
         // may be able to append to it.
         if (kDraw_Cmd == fCmds.back() &&
@@ -371,18 +371,9 @@
                                               verticesPerInstance,
                                               indicesPerInstance);
     }
-
 }
 
-void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
-                                        int startVertex,
-                                        int startIndex,
-                                        int vertexCount,
-                                        int indexCount) {
-
-    if (!vertexCount || !indexCount) {
-        return;
-    }
+void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
 
     this->resetDrawTracking();
 
@@ -395,98 +386,49 @@
         this->recordState();
     }
 
-    Draw* draw = this->recordDraw();
-
-    draw->fPrimitiveType = primitiveType;
-    draw->fStartVertex   = startVertex;
-    draw->fStartIndex    = startIndex;
-    draw->fVertexCount   = vertexCount;
-    draw->fIndexCount    = indexCount;
-
+    DrawRecord* draw = this->recordDraw(info);
     draw->fVertexLayout = this->getVertexLayout();
+
     switch (this->getGeomSrc().fVertexSrc) {
-    case kBuffer_GeometrySrcType:
-        draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
-        break;
-    case kReserved_GeometrySrcType: // fallthrough
-    case kArray_GeometrySrcType: {
-        size_t vertexBytes = (vertexCount + startVertex) *
-                             GrDrawState::VertexSize(draw->fVertexLayout);
-        poolState.fUsedPoolVertexBytes =
-                            GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
-        draw->fVertexBuffer = poolState.fPoolVertexBuffer;
-        draw->fStartVertex += poolState.fPoolStartVertex;
-        break;
-    }
-    default:
-        GrCrash("unknown geom src type");
+        case kBuffer_GeometrySrcType:
+            draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
+            break;
+        case kReserved_GeometrySrcType: // fallthrough
+        case kArray_GeometrySrcType: {
+            size_t vertexBytes = (info.vertexCount() + info.startVertex()) *
+                                 GrDrawState::VertexSize(draw->fVertexLayout);
+            poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
+            draw->fVertexBuffer = poolState.fPoolVertexBuffer;
+            draw->fStartVertex += poolState.fPoolStartVertex;
+            break;
+        }
+        default:
+            GrCrash("unknown geom src type");
     }
     draw->fVertexBuffer->ref();
 
-    switch (this->getGeomSrc().fIndexSrc) {
-    case kBuffer_GeometrySrcType:
-        draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer;
-        break;
-    case kReserved_GeometrySrcType: // fallthrough
-    case kArray_GeometrySrcType: {
-        size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
-        poolState.fUsedPoolIndexBytes =
-                            GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
-        draw->fIndexBuffer = poolState.fPoolIndexBuffer;
-        draw->fStartIndex += poolState.fPoolStartIndex;
-        break;
+    if (info.isIndexed()) {
+        switch (this->getGeomSrc().fIndexSrc) {
+            case kBuffer_GeometrySrcType:
+                draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer;
+                break;
+            case kReserved_GeometrySrcType: // fallthrough
+            case kArray_GeometrySrcType: {
+                size_t indexBytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
+                poolState.fUsedPoolIndexBytes = GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
+                draw->fIndexBuffer = poolState.fPoolIndexBuffer;
+                draw->fStartIndex += poolState.fPoolStartIndex;
+                break;
+            }
+            default:
+                GrCrash("unknown geom src type");
+        }
+        draw->fIndexBuffer->ref();
+    } else {
+        draw->fIndexBuffer = NULL;
     }
-    default:
-        GrCrash("unknown geom src type");
-    }
-    draw->fIndexBuffer->ref();
 }
 
-void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
-                                           int startVertex,
-                                           int vertexCount) {
-    if (!vertexCount) {
-        return;
-    }
-
-    this->resetDrawTracking();
-
-    GeometryPoolState& poolState = fGeoPoolStateStack.back();
-    if (this->needsNewClip()) {
-        this->recordClip();
-    }
-    if (this->needsNewState()) {
-        this->recordState();
-    }
-
-    Draw* draw = this->recordDraw();
-    draw->fPrimitiveType = primitiveType;
-    draw->fStartVertex   = startVertex;
-    draw->fStartIndex    = 0;
-    draw->fVertexCount   = vertexCount;
-    draw->fIndexCount    = 0;
-
-    draw->fVertexLayout = this->getVertexLayout();
-    switch (this->getGeomSrc().fVertexSrc) {
-    case kBuffer_GeometrySrcType:
-        draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
-        break;
-    case kReserved_GeometrySrcType: // fallthrough
-    case kArray_GeometrySrcType: {
-        size_t vertexBytes = (vertexCount + startVertex) *
-                             GrDrawState::VertexSize(draw->fVertexLayout);
-        poolState.fUsedPoolVertexBytes =
-                            GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
-        draw->fVertexBuffer = poolState.fPoolVertexBuffer;
-        draw->fStartVertex += poolState.fPoolStartVertex;
-        break;
-    }
-    default:
-        GrCrash("unknown geom src type");
-    }
-    draw->fVertexBuffer->ref();
-    draw->fIndexBuffer = NULL;
-}
 
 GrInOrderDrawBuffer::StencilPath::StencilPath() : fStroke(SkStrokeRec::kFill_InitStyle) {}
 
@@ -588,7 +530,7 @@
     for (int c = 0; c < numCmds; ++c) {
         switch (fCmds[c]) {
             case kDraw_Cmd: {
-                const Draw& draw = fDraws[currDraw];
+                const DrawRecord& draw = fDraws[currDraw];
                 target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
                 if (draw.fIndexCount) {
                     target->setIndexSourceToBuffer(draw.fIndexBuffer);
@@ -892,11 +834,21 @@
     fCmds.push_back(kSetState_Cmd);
 }
 
-GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw() {
+GrInOrderDrawBuffer::DrawRecord* GrInOrderDrawBuffer::recordDraw() {
     fCmds.push_back(kDraw_Cmd);
     return &fDraws.push_back();
 }
 
+GrInOrderDrawBuffer::DrawRecord* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info) {
+    DrawRecord* record = this->recordDraw();
+    record->fPrimitiveType  = info.primitiveType();
+    record->fStartVertex    = info.startVertex();
+    record->fVertexCount    = info.vertexCount();
+    record->fStartIndex     = info.startIndex();
+    record->fIndexCount     = info.indexCount();
+    return record;
+}
+
 GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath() {
     fCmds.push_back(kStencilPath_Cmd);
     return &fStencilPaths.push_back();
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 38cc890..353d5bf 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -120,7 +120,8 @@
         kClear_Cmd          = 5,
     };
 
-    struct Draw {
+    // TODO: Make this derive from DrawInfo
+    struct DrawRecord {
         GrPrimitiveType         fPrimitiveType;
         int                     fStartVertex;
         int                     fStartIndex;
@@ -149,14 +150,7 @@
     };
 
     // overrides from GrDrawTarget
-    virtual void onDrawIndexed(GrPrimitiveType primitiveType,
-                               int startVertex,
-                               int startIndex,
-                               int vertexCount,
-                               int indexCount) SK_OVERRIDE;
-    virtual void onDrawNonIndexed(GrPrimitiveType primitiveType,
-                                  int startVertex,
-                                  int vertexCount) SK_OVERRIDE;
+    virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
     virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType) SK_OVERRIDE;
     virtual bool onReserveVertexSpace(GrVertexLayout layout,
                                       int vertexCount,
@@ -186,7 +180,8 @@
     // these functions record a command
     void            recordState();
     void            recordClip();
-    Draw*           recordDraw();
+    DrawRecord*     recordDraw();
+    DrawRecord*     recordDraw(const DrawInfo&);
     StencilPath*    recordStencilPath();
     Clear*          recordClear();
 
@@ -205,7 +200,7 @@
     };
 
     SkSTArray<kCmdPreallocCnt, uint8_t, true>                          fCmds;
-    GrSTAllocator<kDrawPreallocCnt, Draw>                              fDraws;
+    GrSTAllocator<kDrawPreallocCnt, DrawRecord>                        fDraws;
     GrSTAllocator<kStatePreallocCnt, StencilPath>                      fStencilPaths;
     GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState>       fStates;
     GrSTAllocator<kClearPreallocCnt, Clear>                            fClears;
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a1a5bee..7ca07a0 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1606,53 +1606,28 @@
     #endif
 #endif
 
-void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
-                               uint32_t startVertex,
-                               uint32_t startIndex,
-                               uint32_t vertexCount,
-                               uint32_t indexCount) {
-    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
+void GrGpuGL::onGpuDraw(const DrawInfo& info) {
+    int extraStartIndexOffset;
+    this->setupGeometry(info, &extraStartIndexOffset);
 
-    GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
-
-    GrAssert(NULL != fHWGeometryState.fIndexBuffer);
+    GrAssert((size_t)info.primitiveType() < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
     GrAssert(NULL != fHWGeometryState.fVertexBuffer);
 
-    // our setupGeometry better have adjusted this to zero since
-    // DrawElements always draws from the begining of the arrays for idx 0.
-    GrAssert(0 == startVertex);
-
-    GL_CALL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
-                         GR_GL_UNSIGNED_SHORT, indices));
-#if SWAP_PER_DRAW
-    glFlush();
-    #if GR_MAC_BUILD
-        aglSwapBuffers(aglGetCurrentContext());
-        int set_a_break_pt_here = 9;
-        aglSwapBuffers(aglGetCurrentContext());
-    #elif GR_WIN32_BUILD
-        SwapBuf();
-        int set_a_break_pt_here = 9;
-        SwapBuf();
-    #endif
-#endif
-}
-
-void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
-                                  uint32_t startVertex,
-                                  uint32_t vertexCount) {
-    GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
-
-    GrAssert(NULL != fHWGeometryState.fVertexBuffer);
-
-    // our setupGeometry better have adjusted this to zero.
-    // DrawElements doesn't take an offset so we always adjus the startVertex.
-    GrAssert(0 == startVertex);
-
-    // pass 0 for parameter first. We have to adjust gl*Pointer() to
-    // account for startVertex in the DrawElements case. So we always
-    // rely on setupGeometry to have accounted for startVertex.
-    GL_CALL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
+    if (info.isIndexed()) {
+        GrAssert(NULL != fHWGeometryState.fIndexBuffer);
+        GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * (info.startIndex() +
+                                                            extraStartIndexOffset));
+        // info.startVertex() was accounted for by setupGeometry.
+        GL_CALL(DrawElements(gPrimitiveType2GLMode[info.primitiveType()],
+                             info.indexCount(),
+                             GR_GL_UNSIGNED_SHORT,
+                             indices));
+    } else {
+        // Pass 0 for parameter first. We have to adjust glVertexAttribPointer() to account for
+        // startVertex in the DrawElements case. So we always rely on setupGeometry to have
+        // accounted for startVertex.
+        GL_CALL(DrawArrays(gPrimitiveType2GLMode[info.primitiveType()], 0, info.vertexCount()));
+    }
 #if SWAP_PER_DRAW
     glFlush();
     #if GR_MAC_BUILD
@@ -1688,7 +1663,6 @@
 }
 }
 
-
 void GrGpuGL::setStencilPathSettings(const GrPath&,
                                      SkPath::FillType fill,
                                      GrStencilSettings* settings) {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 0210c65..3b8c16f 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -96,14 +96,7 @@
 
     virtual void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE;
 
-    virtual void onGpuDrawIndexed(GrPrimitiveType type,
-                                  uint32_t startVertex,
-                                  uint32_t startIndex,
-                                  uint32_t vertexCount,
-                                  uint32_t indexCount) SK_OVERRIDE;
-    virtual void onGpuDrawNonIndexed(GrPrimitiveType type,
-                                     uint32_t vertexCount,
-                                     uint32_t numVertices) SK_OVERRIDE;
+    virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE;
 
     virtual void setStencilPathSettings(const GrPath&,
                                         SkPath::FillType,
@@ -115,22 +108,23 @@
     virtual void clearStencilClip(const GrIRect& rect,
                                   bool insideClip) SK_OVERRIDE;
     virtual bool flushGraphicsState(DrawType) SK_OVERRIDE;
-    virtual void setupGeometry(int* startVertex,
-                               int* startIndex,
-                               int vertexCount,
-                               int indexCount) SK_OVERRIDE;
 
     const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); }
 
     // binds texture unit in GL
     void setTextureUnit(int unitIdx);
 
-    // binds appropriate vertex and index buffers, also returns any extra
-    // extra verts or indices to offset by.
+    // Sets up vertex attribute pointers and strides. On return startIndexOffset specifies an
+    // offset into the index buffer to the first index to be read (in addition to
+    // info.startIndex()). It accounts for the fact that index buffer pool may have provided space
+    // in the middle of a larger index buffer.
+    void setupGeometry(const DrawInfo& info, int* startIndexOffset);
+    // binds appropriate vertex and index buffers, also returns any extra verts or indices to
+    // offset by based on how space was allocated in pool VB/IBs.
     void setBuffers(bool indexed, int* extraVertexOffset, int* extraIndexOffset);
 
     // Subclasses should call this to flush the blend state.
-    // The params should be the final coeffecients to apply
+    // The params should be the final coefficients to apply
     // (after any blending optimizations or dual source blending considerations
     // have been accounted for).
     void flushBlend(bool isLines, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index d1a60fa..d5e8fbd 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -340,10 +340,7 @@
     #error "unknown GR_TEXT_SCALAR type"
 #endif
 
-void GrGpuGL::setupGeometry(int* startVertex,
-                            int* startIndex,
-                            int vertexCount,
-                            int indexCount) {
+void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
 
     int newColorOffset;
     int newCoverageOffset;
@@ -352,28 +349,24 @@
 
     GrVertexLayout currLayout = this->getVertexLayout();
 
-    GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(
-                                            currLayout,
-                                            newTexCoordOffsets,
-                                            &newColorOffset,
-                                            &newCoverageOffset,
-                                            &newEdgeOffset);
+    GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout,
+                                                                 newTexCoordOffsets,
+                                                                 &newColorOffset,
+                                                                 &newCoverageOffset,
+                                                                 &newEdgeOffset);
     int oldColorOffset;
     int oldCoverageOffset;
     int oldTexCoordOffsets[GrDrawState::kMaxTexCoords];
     int oldEdgeOffset;
 
-    GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(
-                                            fHWGeometryState.fVertexLayout,
-                                            oldTexCoordOffsets,
-                                            &oldColorOffset,
-                                            &oldCoverageOffset,
-                                            &oldEdgeOffset);
-    bool indexed = NULL != startIndex;
+    GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
+                                                                 oldTexCoordOffsets,
+                                                                 &oldColorOffset,
+                                                                 &oldCoverageOffset,
+                                                                 &oldEdgeOffset);
 
     int extraVertexOffset;
-    int extraIndexOffset;
-    this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
+    this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
 
     GrGLenum scalarType;
     bool texCoordNorm;
@@ -381,16 +374,11 @@
         scalarType = TEXT_COORDS_GL_TYPE;
         texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED);
     } else {
-//        GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
         scalarType = GR_GL_FLOAT;
         texCoordNorm = false;
     }
 
-    size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
-    *startVertex = 0;
-    if (indexed) {
-        *startIndex += extraIndexOffset;
-    }
+    size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride;
 
     // all the Pointers must be set if any of these are true
     bool allOffsetsChange =  fHWGeometryState.fArrayPtrsDirty ||