Add option to automatically flush GrInOrderDrawBuffer based on previewing vtx/idx...
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 13 Mar 2012 14:32:07 +0000 (14:32 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 13 Mar 2012 14:32:07 +0000 (14:32 +0000)
Review URL: http://codereview.appspot.com/5794079/

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

src/gpu/GrContext.cpp
src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/GrInOrderDrawBuffer.h

index 7ea36da..e5f95e6 100644 (file)
@@ -1541,8 +1541,7 @@ void GrContext::flushText() {
 void GrContext::flushDrawBuffer() {
 #if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
     if (fDrawBuffer) {
-        fDrawBuffer->playback(fGpu);
-        fDrawBuffer->reset();
+        fDrawBuffer->flushTo(fGpu);
     }
 #endif
 }
index d180bcc..3dd86d2 100644 (file)
@@ -573,6 +573,7 @@ bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
                                               int indexCount,
                                               void** vertices,
                                               void** indices) {
+    this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
     if (vertexCount) {
         if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
             if (indexCount) {
index cc0e875..488b5bb 100644 (file)
@@ -332,11 +332,11 @@ public:
      * @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 reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
+                                     int vertexCount,
+                                     int indexCount,
+                                     void** vertices,
+                                     void** indices);
 
     /**
      * Provides hints to caller about the number of vertices and indices
@@ -419,7 +419,15 @@ public:
      * be able to free up temporary storage allocated by setIndexSourceToArray
      * or reserveIndexSpace.
      */
-    void resetIndexSource(); 
+    void resetIndexSource();
+    
+    /**
+     * Query to find out if the vertex or index source is reserved.
+     */
+    bool hasReservedVerticesOrIndices() const {
+        kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc ||
+        kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
+    }
 
     /**
      * Pushes and resets the vertex/index sources. Any reserved vertex / index
@@ -926,6 +934,13 @@ protected:
         return *sds.fState.get();
     }
 
+    // A sublcass can optionally overload this function to be notified before
+    // vertex and index space is reserved.
+    virtual void willReserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
+                                                int vertexCount,
+                                                int indexCount) {}
+    
+
     // implemented by subclass to allocate space for reserved geom
     virtual bool onReserveVertexSpace(GrVertexLayout vertexLayout,
                                       int vertexCount,
index 722ea42..b6581c0 100644 (file)
@@ -19,7 +19,8 @@
 GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
                                          GrVertexBufferAllocPool* vertexPool,
                                          GrIndexBufferAllocPool* indexPool)
-    : fClipSet(true)
+    : fAutoFlushTarget(NULL)
+    , fClipSet(true)
     , fLastRectVertexLayout(0)
     , fQuadIndexBuffer(NULL)
     , fMaxQuads(0)
@@ -48,6 +49,7 @@ GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
     // This must be called by before the GrDrawTarget destructor
     this->releaseGeometry();
     GrSafeUnref(fQuadIndexBuffer);
+    GrSafeUnref(fAutoFlushTarget);
 }
 
 void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
@@ -425,6 +427,50 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
     }
 }
 
+void GrInOrderDrawBuffer::setAutoFlushTarget(GrDrawTarget* target) {
+    GrSafeAssign(fAutoFlushTarget, target);
+}
+
+void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace(
+                                GrVertexLayout vertexLayout,
+                                int vertexCount,
+                                int indexCount) {
+    if (NULL != fAutoFlushTarget) {
+        // We use geometryHints() to know whether to flush the draw buffer. We
+        // can't flush if we are inside an unbalanced pushGeometrySource.
+        // Moreover, flushing blows away vertex and index data that was
+        // previously reserved. So if the vertex or index data is pulled from
+        // reserved space and won't be released by this request then we can't
+        // flush.
+        bool insideGeoPush = fGeoPoolStateStack.count() > 1;
+
+        bool unreleasedVertexSpace =
+            !vertexCount &&
+            kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc;
+
+        bool unreleasedIndexSpace =
+            !indexCount &&
+            kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc;
+
+        // we don't want to finalize any reserved geom on the target since
+        // we don't know that the client has finished writing to it.
+        bool targetHasReservedGeom =
+            fAutoFlushTarget->hasReservedVerticesOrIndices();
+        
+        int vcount = vertexCount;
+        int icount = indexCount;
+        
+        if (!insideGeoPush &&
+            !unreleasedVertexSpace &&
+            !unreleasedIndexSpace &&
+            !targetHasReservedGeom &&
+            this->geometryHints(vertexLayout, &vcount, &icount)) {
+
+            this->flushTo(fAutoFlushTarget);
+        }
+    }
+}
+
 bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
                                         int* vertexCount,
                                         int* indexCount) const {
index 73746e9..b802f96 100644 (file)
@@ -67,30 +67,60 @@ public:
     void setQuadIndexBuffer(const GrIndexBuffer* indexBuffer);
 
     /**
-     * Empties the draw buffer of any queued up draws.
+     * Empties the draw buffer of any queued up draws. This must not be called
+     * while inside an unbalanced pushGeometrySource().
      */
     void reset();
 
     /**
-     * plays the queued up draws to another target. Does not empty this buffer so
-     * that it can be played back multiple times.
+     * plays the queued up draws to another target. Does not empty this buffer
+     * so that it can be played back multiple times. This buffer must not have
+     * an active reserved vertex or index source. Any reserved geometry on
+     * the target will be finalized because it's geometry source will be pushed
+     * before playback and popped afterwards.
+     *
      * @param target    the target to receive the playback
      */
     void playback(GrDrawTarget* target);
-    
+
+    /**
+     * A convenience method to do a playback followed by a reset. All the
+     * constraints and side-effects or playback() and reset apply().
+     */
+    void flushTo(GrDrawTarget* target) {
+        this->playback(target);
+        this->reset();
+    }
+
+    /**
+     * This function allows the draw buffer to automatically flush itself to
+     * another target. This means the buffer may internally call 
+     * this->flushTo(target) when it is safe to do so.
+     * 
+     * When the auto flush target is set to NULL (as it initially is) the draw
+     * buffer will never automatically flush itself.
+     */
+    void setAutoFlushTarget(GrDrawTarget* target);
+
     // overrides from GrDrawTarget
     virtual void drawRect(const GrRect& rect, 
                           const GrMatrix* matrix = NULL,
                           StageMask stageEnableMask = 0,
                           const GrRect* srcRects[] = NULL,
-                          const GrMatrix* srcMatrices[] = NULL);
+                          const GrMatrix* srcMatrices[] = NULL) SK_OVERRIDE;
 
     virtual bool geometryHints(GrVertexLayout vertexLayout,
                                int* vertexCount,
-                               int* indexCount) const;
+                               int* indexCount) const SK_OVERRIDE;
 
-    virtual void clear(const GrIRect* rect, GrColor color);
+    virtual void clear(const GrIRect* rect, GrColor color) SK_OVERRIDE;
 
+protected:
+
+    virtual void willReserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
+                                                int vertexCount,
+                                                int indexCount) SK_OVERRIDE;
+    
 private:
 
     struct Draw {
@@ -155,7 +185,9 @@ private:
     GrSTAllocator<kStatePreallocCnt, SavedDrawState>    fStates;
     GrSTAllocator<kClearPreallocCnt, Clear>             fClears;
     GrSTAllocator<kClipPreallocCnt, GrClip>             fClips;
-    
+
+    GrDrawTarget*                   fAutoFlushTarget;
+
     bool                            fClipSet;
 
     GrVertexLayout                  fLastRectVertexLayout;