Change interface on GrDrawTarget to reserve vtx/idx space at same time
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 13 Mar 2012 12:40:53 +0000 (12:40 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 13 Mar 2012 12:40:53 +0000 (12:40 +0000)
Review URL: https://codereview.appspot.com/5796066/

git-svn-id: http://skia.googlecode.com/svn/trunk@3371 2bbb7eff-a529-9590-31e7-b0007b416f81

src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrTextContext.cpp

index d68aa39..d180bcc 100644 (file)
@@ -568,6 +568,30 @@ bool GrDrawTarget::reserveIndexSpace(int indexCount,
     
 }
 
+bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
+                                              int vertexCount,
+                                              int indexCount,
+                                              void** vertices,
+                                              void** indices) {
+    if (vertexCount) {
+        if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
+            if (indexCount) {
+                this->resetIndexSource();
+            }
+            return false;
+        }
+    }
+    if (indexCount) {
+        if (!this->reserveIndexSpace(indexCount, indices)) {
+            if (vertexCount) {
+                this->resetVertexSource();
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
 bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
                                  int32_t* vertexCount,
                                  int32_t* indexCount) const {
@@ -1168,19 +1192,14 @@ bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
     bool success = true;
     if (NULL != fTarget) {
         fTarget = target;
-        if (vertexCount > 0) {
-            success = target->reserveVertexSpace(vertexLayout, 
-                                                 vertexCount,
-                                                 &fVertices);
-            if (!success) {
-                this->reset();
-            }
-        }
-        if (success && indexCount > 0) {
-            success = target->reserveIndexSpace(indexCount, &fIndices);
-            if (!success) {
-                this->reset();
-            }
+        success = target->reserveVertexAndIndexSpace(vertexLayout,
+                                                     vertexCount,
+                                                     indexCount,
+                                                     &fVertices,
+                                                     &fIndices);
+        if (!success) {
+            fTarget = NULL;
+            this->reset();
         }
     }
     GrAssert(success == (NULL != fTarget));
index 6962a18..cc0e875 100644 (file)
@@ -260,21 +260,30 @@ public:
     GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
 
     /**
-     * There are three methods for specifying geometry (vertices and optionally
-     * indices) to the draw target. When indexed drawing the indices and vertices
-     * can use a different method. Once geometry is specified it can be used for
-     * multiple drawIndexed and drawNonIndexed calls.
+     * There are three types of "sources" of geometry (vertices and indices) for
+     * draw calls made on the target. When performing an indexed draw, the
+     * indices and vertices can use different source types. Once a source is
+     * specified it can be used for multiple drawIndexed and drawNonIndexed
+     * calls. However, the time at which the geometry data is no longer editable
+     * depends on the source type.
      *
      * Sometimes it is necessary to perform a draw while upstack code has
-     * already specified geometry that it isn't finished with. There are push
-     * pop methods
+     * already specified geometry that it isn't finished with. So there are push
+     * and pop methods. This allows the client to push the sources, draw
+     * something using alternate sources, and then pop to restore the original
+     * sources.
+     *
+     * Aside from pushes and pops, a source remains valid until another source
+     * is set or resetVertexSource / resetIndexSource is called. Drawing from
+     * a reset source is an error.
+     *
+     * The three types of sources are:
      *
-     * 1. Provide a cpu array (set*SourceToArray). This is useful when the
-     *    caller's client has already provided vertex data in a format
-     *    the time compatible with a GrVertexLayout. The array must contain the
-     *    data at set*SourceToArray is called. The source stays in effect for
-     *    drawIndexed & drawNonIndexed calls until set*SourceToArray is called
-     *    again or one of the other two paths is chosen.
+     * 1. A cpu array (set*SourceToArray). This is useful when the caller
+     *    already provided vertex data in a format compatible with a
+     *    GrVertexLayout. The data in the array is consumed at the time that
+     *    set*SourceToArray is called and subsequent edits to the array will not
+     *    be reflected in draws.
      *
      * 2. Reserve. This is most useful when the caller has data it must
      *    transform before drawing and is not long-lived. The caller requests
@@ -282,70 +291,53 @@ public:
      *    data. The target provides ptrs to hold the vertex and/or index data.
      *
      *    The data is writable up until the next drawIndexed, drawNonIndexed, 
-     *    or pushGeometrySource At this point the data is frozen and the ptrs
+     *    or pushGeometrySource. At this point the data is frozen and the ptrs
      *    are no longer valid.
      *
+     *    Where the space is allocated and how it is uploaded to the GPU is
+     *    subclass-dependent.
+     *
      * 3. Vertex and Index Buffers. This is most useful for geometry that will
-     *    is long-lived. SetVertexSourceToBuffer and SetIndexSourceToBuffer are
-     *    used to set the buffer and subsequent drawIndexed and drawNonIndexed 
-     *    calls use this source until another source is set.
+     *    is long-lived. When the data in the buffer is consumed depends on the
+     *    GrDrawTarget subclass. For deferred subclasses the caller has to 
+     *    guarantee that the data is still available in the buffers at playback.
+     *    (TODO: Make this more automatic as we have done for read/write pixels)
      */
 
     /**
-     * Reserves space for vertices. Draw target will use reserved vertices at
-     * at the next draw.
+     * Reserves space for vertices and/or indices. Zero can be specifed as
+     * either the vertex or index count if the caller desires to only reserve
+     * space for only indices or only vertices. If zero is specifed for 
+     * vertexCount then the vertex source will be unmodified and likewise for
+     * indexCount.
      *
-     * If succeeds:
-     *          if vertexCount > 0, *vertices will be the array
-     *          of vertices to be filled by caller. The next draw will read
-     *          these vertices.
+     * If the function returns true then the reserve suceeded and the vertices
+     * and indices pointers will point to the space created.
      *
-     * If a client does not already have a vertex buffer then this is the
-     * preferred way to allocate vertex data. It allows the subclass of
-     * GrDrawTarget to decide whether to put data in buffers, to group vertex
-     * data that uses the same state (e.g. for deferred rendering), etc.
+     * If the target cannot make space for the request then this function will
+     * return false. If vertexCount was non-zero then upon failure the vertex
+     * source is reset and likewise for indexCount.
      *
-     * After the next draw or pushGeometrySource the vertices ptr is no longer
-     * valid and the geometry data cannot be further modified. The contents
-     * that were put in the reserved space can be drawn by multiple draws,
-     * however.
+     * The pointers to the space allocated for vertices and indices remain valid
+     * until a drawIndexed, drawNonIndexed, or push/popGeomtrySource is called.
+     * At that point logically a snapshot of the data is made and the pointers
+     * are invalid.
      *
      * @param vertexLayout the format of vertices (ignored if vertexCount == 0).
-     * @param vertexCount  the number of vertices to reserve space for. Can be 0.
-     * @param vertices     will point to reserved vertex space if vertexCount is
-     *                     non-zero. Illegal to pass NULL if vertexCount > 0.
-     *
-     * @return  true if succeeded in allocating space for the vertices and false
-     *               if not.
-     */
-    bool reserveVertexSpace(GrVertexLayout vertexLayout,
-                            int vertexCount,
-                            void** vertices);
-    /**
-     * Reserves space for indices. Draw target will use the reserved indices at
-     * the next indexed draw.
-     *
-     * If succeeds:
-     *          if indexCount > 0, *indices will be the array
-     *          of indices to be filled by caller. The next draw will read
-     *          these indices.
-     *
-     * If a client does not already have a index buffer then this is the
-     * preferred way to allocate index data. It allows the subclass of
-     * GrDrawTarget to decide whether to put data in buffers, to group index
-     * data that uses the same state (e.g. for deferred rendering), etc.
-     *
-     * After the next indexed draw or pushGeometrySource the indices ptr is no
-     * longer valid and the geometry data cannot be further modified. The
-     * contents that were put in the reserved space can be drawn by multiple
-     * draws, however.
-     *
+     * @param vertexCount  the number of vertices to reserve space for. Can be
+     *                     0.
      * @param indexCount   the number of indices to reserve space for. Can be 0.
+     * @param vertices     will point to reserved vertex space if vertexCount is
+     *                     non-zero. Illegal to pass NULL if vertexCount > 0.    
      * @param indices      will point to reserved index space if indexCount is
      *                     non-zero. Illegal to pass NULL if indexCount > 0.
      */
+    virtual bool reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
+                                            int vertexCount,
+                                            int indexCount,
+                                            void** vertices,
+                                            void** indices);
 
-    bool reserveIndexSpace(int indexCount, void** indices);
     /**
      * Provides hints to caller about the number of vertices and indices
      * that can be allocated cheaply. This can be useful if caller is reserving
@@ -994,7 +986,14 @@ protected:
     // and index sources have been released (including those held by 
     // pushGeometrySource())
     void releaseGeometry();
+
 private:
+    // helpers for reserving vertex and index space.
+    bool reserveVertexSpace(GrVertexLayout vertexLayout,
+                            int vertexCount,
+                            void** vertices);
+    bool reserveIndexSpace(int indexCount, void** indices);
+    
     // called by drawIndexed and drawNonIndexed. Use a negative indexCount to
     // indicate non-indexed drawing.
     bool checkDraw(GrPrimitiveType type, int startVertex,
index c22b203..62c894e 100644 (file)
@@ -255,8 +255,8 @@ HAS_ATLAS:
         // a number of verts to reserve and whether to perform a flush.
         fMaxVertices = kMinRequestedVerts;
         bool flush = fDrawTarget->geometryHints(fVertexLayout,
-                                               &fMaxVertices,
-                                               NULL);
+                                                &fMaxVertices,
+                                                NULL);
         if (flush) {
             this->flushGlyphs();
             fContext->flushText();
@@ -275,9 +275,12 @@ HAS_ATLAS:
             // don't exceed the limit of the index buffer
             fMaxVertices = maxQuadVertices;
         }
-        bool success = fDrawTarget->reserveVertexSpace(fVertexLayout, 
+        bool success = fDrawTarget->reserveVertexAndIndexSpace(
+                                                   fVertexLayout, 
                                                    fMaxVertices,
-                                                   GrTCast<void**>(&fVertices));
+                                                   0,
+                                                   GrTCast<void**>(&fVertices),
+                                                   NULL);
         GrAlwaysAssert(success);
     }