Refactor GrDrawTarget vertex/index api
Review URL: http://codereview.appspot.com/4631056/



git-svn-id: http://skia.googlecode.com/svn/trunk@1662 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 4f260c7..db7de2c 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -33,27 +33,36 @@
 
 extern void gr_run_unittests();
 
+#define DEBUG_INVAL_BUFFER    0xdeadcafe
+#define DEBUG_INVAL_START_IDX -1
+
 GrGpu::GrGpu()
     : f8bitPaletteSupport(false)
-    , fCurrPoolVertexBuffer(NULL)
-    , fCurrPoolStartVertex(0)
-    , fCurrPoolIndexBuffer(NULL)
-    , fCurrPoolStartIndex(0)
     , fContext(NULL)
     , fVertexPool(NULL)
     , fIndexPool(NULL)
+    , fVertexPoolUseCnt(0)
+    , fIndexPoolUseCnt(0)
+    , fGeomPoolStateStack(&fGeoSrcStateStackStorage)
     , fQuadIndexBuffer(NULL)
     , fUnitSquareVertexBuffer(NULL)
     , fDefaultPathRenderer(NULL)
     , fClientPathRenderer(NULL)
     , fContextIsDirty(true)
-    , fVertexPoolInUse(false)
-    , fIndexPoolInUse(false)
     , fResourceHead(NULL) {
 
 #if GR_DEBUG
     //gr_run_unittests();
 #endif
+        
+    fGeomPoolStateStack.push_back();
+#if GR_DEBUG
+    GeometryPoolState& poolState = fGeomPoolStateStack.back();
+    poolState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
+    poolState.fPoolStartVertex = DEBUG_INVAL_START_IDX;
+    poolState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
+    poolState.fPoolStartIndex = DEBUG_INVAL_START_IDX;
+#endif
     resetStats();
 }
 
@@ -417,7 +426,7 @@
             fClip.setFromRect(bounds);
 
             AutoStateRestore asr(this);
-            AutoInternalDrawGeomRestore aidgr(this);
+            AutoGeometryPush agp(this);
 
             this->setViewMatrix(GrMatrix::I());
             this->clearStencilClip(clipRect);
@@ -566,15 +575,36 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void GrGpu::drawIndexed(GrPrimitiveType type,
-                        int startVertex,
-                        int startIndex,
-                        int vertexCount,
-                        int indexCount) {
-    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
-             fReservedGeometry.fLocked);
-    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
-             fReservedGeometry.fLocked);
+void GrGpu::geometrySourceWillPush() {
+    const GeometrySrcState& geoSrc = this->getGeomSrc();
+    if (kArray_GeometrySrcType == geoSrc.fVertexSrc ||
+        kReserved_GeometrySrcType == geoSrc.fVertexSrc) {
+        this->finalizeReservedVertices();
+    }
+    if (kArray_GeometrySrcType == geoSrc.fIndexSrc ||
+        kReserved_GeometrySrcType == geoSrc.fIndexSrc) {
+        this->finalizeReservedIndices();
+    }
+    GeometryPoolState& newState = fGeomPoolStateStack.push_back();
+#if GR_DEBUG
+    newState.fPoolVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
+    newState.fPoolStartVertex = DEBUG_INVAL_START_IDX;
+    newState.fPoolIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
+    newState.fPoolStartIndex = DEBUG_INVAL_START_IDX;
+#endif
+}
+
+void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) {
+    // if popping last entry then pops are unbalanced with pushes
+    GrAssert(fGeomPoolStateStack.count() > 1);
+    fGeomPoolStateStack.pop_back();
+}
+
+void GrGpu::onDrawIndexed(GrPrimitiveType type,
+                          int startVertex,
+                          int startIndex,
+                          int vertexCount,
+                          int indexCount) {
 
     this->handleDirtyContext();
 
@@ -592,16 +622,13 @@
     int sIndex = startIndex;
     setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
 
-    this->onDrawIndexed(type, sVertex, sIndex,
-                        vertexCount, indexCount);
+    this->onGpuDrawIndexed(type, sVertex, sIndex,
+                           vertexCount, indexCount);
 }
 
-void GrGpu::drawNonIndexed(GrPrimitiveType type,
+void GrGpu::onDrawNonIndexed(GrPrimitiveType type,
                            int startVertex,
                            int vertexCount) {
-    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
-             fReservedGeometry.fLocked);
-
     this->handleDirtyContext();
 
     if (!this->setupClipAndFlushState(type)) {
@@ -615,7 +642,7 @@
     int sVertex = startVertex;
     setupGeometry(&sVertex, NULL, vertexCount, 0);
 
-    this->onDrawNonIndexed(type, sVertex, vertexCount);
+    this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
 }
 
 void GrGpu::finalizeReservedVertices() {
@@ -630,11 +657,12 @@
 
 void GrGpu::prepareVertexPool() {
     if (NULL == fVertexPool) {
+        GrAssert(0 == fVertexPoolUseCnt);
         fVertexPool = new GrVertexBufferAllocPool(this, true,
                                                   VERTEX_POOL_VB_SIZE,
                                                   VERTEX_POOL_VB_COUNT);
         fVertexPool->releaseGpuRef();
-    } else if (!fVertexPoolInUse) {
+    } else if (!fVertexPoolUseCnt) {
         // the client doesn't have valid data in the pool
         fVertexPool->reset();
     }
@@ -642,81 +670,117 @@
 
 void GrGpu::prepareIndexPool() {
     if (NULL == fIndexPool) {
+        GrAssert(0 == fIndexPoolUseCnt);
         fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
         fIndexPool->releaseGpuRef();
-    } else if (!fIndexPoolInUse) {
+    } else if (!fIndexPoolUseCnt) {
         // the client doesn't have valid data in the pool
         fIndexPool->reset();
     }
 }
 
-bool GrGpu::onAcquireGeometry(GrVertexLayout vertexLayout,
-                              void**         vertices,
-                              void**         indices) {
-    GrAssert(!fReservedGeometry.fLocked);
-    size_t reservedVertexSpace = 0;
-
-    if (fReservedGeometry.fVertexCount) {
-        GrAssert(NULL != vertices);
-
-        this->prepareVertexPool();
-
-        *vertices = fVertexPool->makeSpace(vertexLayout,
-                                           fReservedGeometry.fVertexCount,
-                                           &fCurrPoolVertexBuffer,
-                                           &fCurrPoolStartVertex);
-        if (NULL == *vertices) {
-            return false;
-        }
-        reservedVertexSpace = VertexSize(vertexLayout) *
-                              fReservedGeometry.fVertexCount;
+bool GrGpu::onReserveVertexSpace(GrVertexLayout vertexLayout,
+                                 int vertexCount,
+                                 void** vertices) {
+    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
+    
+    GrAssert(vertexCount > 0);
+    GrAssert(NULL != vertices);
+    
+    this->prepareVertexPool();
+    
+    *vertices = fVertexPool->makeSpace(vertexLayout,
+                                       vertexCount,
+                                       &geomPoolState.fPoolVertexBuffer,
+                                       &geomPoolState.fPoolStartVertex);
+    if (NULL == *vertices) {
+        return false;
     }
-    if (fReservedGeometry.fIndexCount) {
-        GrAssert(NULL != indices);
-
-        this->prepareIndexPool();
-
-        *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
-                                         &fCurrPoolIndexBuffer,
-                                         &fCurrPoolStartIndex);
-        if (NULL == *indices) {
-            fVertexPool->putBack(reservedVertexSpace);
-            fCurrPoolVertexBuffer = NULL;
-            return false;
-        }
-    }
+    ++fVertexPoolUseCnt;
     return true;
 }
 
-void GrGpu::onReleaseGeometry() {}
+bool GrGpu::onReserveIndexSpace(int indexCount, void** indices) {
+    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
+    
+    GrAssert(indexCount > 0);
+    GrAssert(NULL != indices);
+
+    this->prepareIndexPool();
+
+    *indices = fIndexPool->makeSpace(indexCount,
+                                     &geomPoolState.fPoolIndexBuffer,
+                                     &geomPoolState.fPoolStartIndex);
+    if (NULL == *indices) {
+        return false;
+    }
+    ++fIndexPoolUseCnt;
+    return true;
+}
+
+void GrGpu::releaseReservedVertexSpace() {
+    const GeometrySrcState& geoSrc = this->getGeomSrc();
+    GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
+    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
+    fVertexPool->putBack(bytes);
+    --fVertexPoolUseCnt;
+}
+
+void GrGpu::releaseReservedIndexSpace() {
+    const GeometrySrcState& geoSrc = this->getGeomSrc();
+    GrAssert(kReserved_GeometrySrcType == geoSrc.fIndexSrc);
+    size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t);
+    fIndexPool->putBack(bytes);
+    --fIndexPoolUseCnt;
+}
 
 void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
-    GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
     this->prepareVertexPool();
+    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
 #if GR_DEBUG
     bool success =
 #endif
-    fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
+    fVertexPool->appendVertices(this->getGeomSrc().fVertexLayout,
                                 vertexCount,
                                 vertexArray,
-                                &fCurrPoolVertexBuffer,
-                                &fCurrPoolStartVertex);
+                                &geomPoolState.fPoolVertexBuffer,
+                                &geomPoolState.fPoolStartVertex);
+    ++fVertexPoolUseCnt;
     GR_DEBUGASSERT(success);
 }
 
 void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) {
-    GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
     this->prepareIndexPool();
+    GeometryPoolState& geomPoolState = fGeomPoolStateStack.back();
 #if GR_DEBUG
     bool success =
 #endif
     fIndexPool->appendIndices(indexCount,
                               indexArray,
-                              &fCurrPoolIndexBuffer,
-                              &fCurrPoolStartIndex);
+                              &geomPoolState.fPoolIndexBuffer,
+                              &geomPoolState.fPoolStartIndex);
+    ++fIndexPoolUseCnt;
     GR_DEBUGASSERT(success);
 }
 
+void GrGpu::releaseVertexArray() {
+    // if vertex source was array, we stowed data in the pool
+    const GeometrySrcState& geoSrc = this->getGeomSrc();
+    GrAssert(kArray_GeometrySrcType == geoSrc.fVertexSrc);
+    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
+    fVertexPool->putBack(bytes);
+    --fVertexPoolUseCnt;
+}
+
+void GrGpu::releaseIndexArray() {
+    // if index source was array, we stowed data in the pool
+    const GeometrySrcState& geoSrc = this->getGeomSrc();
+    GrAssert(kArray_GeometrySrcType == geoSrc.fIndexSrc);
+    size_t bytes = geoSrc.fIndexCount * sizeof(uint16_t);
+    fIndexPool->putBack(bytes);
+    --fIndexPoolUseCnt;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 const GrGpuStats& GrGpu::getStats() const {