Make drawIndexedInstances non-virtual and rewrite GrIODB's drawRect on top of drawIndexedInstances.

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/7221078

git-svn-id: http://skia.googlecode.com/svn/trunk@7508 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 04ffaa4..bb8b9ec 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -19,6 +19,66 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
+    fPrimitiveType  = di.fPrimitiveType;
+    fStartVertex    = di.fStartVertex;
+    fStartIndex     = di.fStartIndex;
+    fVertexCount    = di.fVertexCount;
+    fIndexCount     = di.fIndexCount;
+
+    fInstanceCount          = di.fInstanceCount;
+    fVerticesPerInstance    = di.fVerticesPerInstance;
+    fIndicesPerInstance     = di.fIndicesPerInstance;
+
+    if (NULL != di.fDevBounds) {
+        GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
+        fDevBoundsStorage = di.fDevBoundsStorage;
+        fDevBounds = &fDevBoundsStorage;
+    } else {
+        fDevBounds = NULL;
+    }
+    return *this;
+}
+
+#if GR_DEBUG
+bool GrDrawTarget::DrawInfo::isInstanced() const {
+    if (fInstanceCount > 0) {
+        GrAssert(0 == fIndexCount % fIndicesPerInstance);
+        GrAssert(0 == fVertexCount % fVerticesPerInstance);
+        GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
+        GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
+        // there is no way to specify a non-zero start index to drawIndexedInstances().
+        GrAssert(0 == fStartIndex);
+        return true;
+    } else {
+        GrAssert(!fVerticesPerInstance);
+        GrAssert(!fIndicesPerInstance);
+        return false;
+    }
+}
+#endif
+
+void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
+    GrAssert(this->isInstanced());
+    GrAssert(instanceOffset + fInstanceCount >= 0);
+    fInstanceCount += instanceOffset;
+    fVertexCount = fVerticesPerInstance * fInstanceCount;
+    fIndexCount = fIndicesPerInstance * fInstanceCount;
+}
+
+void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
+    fStartVertex += vertexOffset;
+    GrAssert(fStartVertex >= 0);
+}
+
+void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
+    GrAssert(this->isIndexed());
+    fStartIndex += indexOffset;
+    GrAssert(fStartIndex >= 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 #define DEBUG_INVAL_BUFFER 0xdeadcafe
 #define DEBUG_INVAL_START_IDX -1
 
@@ -338,9 +398,12 @@
     return true;
 }
 
-void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
-                               int startIndex, int vertexCount,
-                               int indexCount) {
+void GrDrawTarget::drawIndexed(GrPrimitiveType type,
+                               int startVertex,
+                               int startIndex,
+                               int vertexCount,
+                               int indexCount,
+                               const SkRect* devBounds) {
     if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
         DrawInfo info;
         info.fPrimitiveType = type;
@@ -348,13 +411,22 @@
         info.fStartIndex    = startIndex;
         info.fVertexCount   = vertexCount;
         info.fIndexCount    = indexCount;
+
+        info.fInstanceCount         = 0;
+        info.fVerticesPerInstance   = 0;
+        info.fIndicesPerInstance    = 0;
+
+        if (NULL != devBounds) {
+            info.setDevBounds(*devBounds);
+        }
         this->onDraw(info);
     }
 }
 
 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
-                                  int vertexCount) {
+                                  int vertexCount,
+                                  const SkRect* devBounds) {
     if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
         DrawInfo info;
         info.fPrimitiveType = type;
@@ -362,6 +434,14 @@
         info.fStartIndex    = 0;
         info.fVertexCount   = vertexCount;
         info.fIndexCount    = 0;
+
+        info.fInstanceCount         = 0;
+        info.fVerticesPerInstance   = 0;
+        info.fIndicesPerInstance    = 0;
+
+        if (NULL != devBounds) {
+            info.setDevBounds(*devBounds);
+        }
         this->onDraw(info);
     }
 }
@@ -546,27 +626,43 @@
 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
                                         int instanceCount,
                                         int verticesPerInstance,
-                                        int indicesPerInstance) {
+                                        int indicesPerInstance,
+                                        const SkRect* devBounds) {
     if (!verticesPerInstance || !indicesPerInstance) {
         return;
     }
 
-    int instancesPerDraw = this->indexCountInCurrentSource() /
-                           indicesPerInstance;
-    if (!instancesPerDraw) {
+    int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
+    if (!maxInstancesPerDraw) {
         return;
     }
 
-    instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
-    int startVertex = 0;
+    DrawInfo info;
+    info.fPrimitiveType = type;
+    info.fStartIndex = 0;
+    info.fStartVertex = 0;
+    info.fIndicesPerInstance = indicesPerInstance;
+    info.fVerticesPerInstance = verticesPerInstance;
+
+    // Set the same bounds for all the draws.
+    if (NULL != devBounds) {
+        info.setDevBounds(*devBounds);
+    }
+
     while (instanceCount) {
-        this->drawIndexed(type,
-                          startVertex,
-                          0,
-                          verticesPerInstance * instancesPerDraw,
-                          indicesPerInstance * instancesPerDraw);
-        startVertex += verticesPerInstance;
-        instanceCount -= instancesPerDraw;
+        info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
+        info.fVertexCount = info.fInstanceCount * verticesPerInstance;
+        info.fIndexCount = info.fInstanceCount * indicesPerInstance;
+
+        if (this->checkDraw(type,
+                            info.fStartVertex,
+                            info.fStartIndex,
+                            info.fVertexCount,
+                            info.fIndexCount)) {
+            this->onDraw(info);
+        }
+        info.fStartVertex += info.fVertexCount;
+        instanceCount -= info.fInstanceCount;
     }
 }
 
@@ -576,7 +672,24 @@
                             const SkMatrix* matrix,
                             const GrRect* srcRects[],
                             const SkMatrix* srcMatrices[]) {
-    GrVertexLayout layout = GetRectVertexLayout(srcRects);
+    GrVertexLayout layout = 0;
+    uint32_t explicitCoordMask = 0;
+
+    if (NULL != srcRects) {
+        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+            int numTC = 0;
+            if (NULL != srcRects[s]) {
+                layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
+                explicitCoordMask |= (1 << s);
+                ++numTC;
+            }
+        }
+    }
+
+    GrDrawState::AutoViewMatrixRestore avmr;
+    if (NULL != matrix) {
+        avmr.set(this->drawState(), *matrix, explicitCoordMask);
+    }
 
     AutoReleaseGeometry geo(this, layout, 4, 0);
     if (!geo.succeeded()) {
@@ -584,69 +697,14 @@
         return;
     }
 
-    SetRectVertices(rect, matrix, srcRects,
-                    srcMatrices, SK_ColorBLACK, layout, geo.vertices());
-
-    drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
-}
-
-GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
-    if (NULL == srcRects) {
-        return 0;
-    }
-
-    GrVertexLayout layout = 0;
-    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
-        int numTC = 0;
-        if (NULL != srcRects[i]) {
-            layout |= GrDrawState::StageTexCoordVertexLayoutBit(i, numTC);
-            ++numTC;
-        }
-    }
-    return layout;
-}
-
-// This method fills int the four vertices for drawing 'rect'.
-//      matrix - is applied to each vertex
-//      srcRects - provide the uvs for each vertex
-//      srcMatrices - are applied to the corresponding 'srcRect'
-//      color - vertex color (replicated in each vertex)
-//      layout - specifies which uvs and/or color are present
-//      vertices - storage for the resulting vertices
-// Note: the color parameter will only be used when kColor_VertexLayoutBit
-// is present in 'layout'
-void GrDrawTarget::SetRectVertices(const GrRect& rect,
-                                   const SkMatrix* matrix,
-                                   const GrRect* srcRects[],
-                                   const SkMatrix* srcMatrices[],
-                                   GrColor color,
-                                   GrVertexLayout layout,
-                                   void* vertices) {
-#if GR_DEBUG
-    // check that the layout and srcRects agree
-    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
-        if (GrDrawState::VertexTexCoordsForStage(i, layout) >= 0) {
-            GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
-        } else {
-            GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
-        }
-    }
-#endif
-
-    int stageOffsets[GrDrawState::kNumStages], colorOffset;
-    int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,
-                                                         &colorOffset, NULL, NULL);
-
-    GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
-                                            rect.fRight, rect.fBottom,
-                                            vsize);
-    if (NULL != matrix) {
-        matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
-    }
+    int stageOffsets[GrDrawState::kNumStages];
+    int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,  NULL, NULL, NULL);
+    geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
 
     for (int i = 0; i < GrDrawState::kNumStages; ++i) {
-        if (stageOffsets[i] > 0) {
-            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
+        if (explicitCoordMask & (1 << i)) {
+            GrAssert(NULL != stageOffsets[i]);
+            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
                                                 stageOffsets[i]);
             coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
                                srcRects[i]->fRight, srcRects[i]->fBottom,
@@ -654,18 +712,12 @@
             if (NULL != srcMatrices && NULL != srcMatrices[i]) {
                 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
             }
+        } else {
+            GrAssert(NULL == stageOffsets[i]);
         }
     }
 
-    if (colorOffset >= 0) {
-
-        GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
-
-        for (int i = 0; i < 4; ++i) {
-            *vertCol = color;
-            vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
-        }
-    }
+    this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
 }
 
 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {