Add option to automatically flush GrInOrderDrawBuffer based on previewing vtx/idx request sizes
Review URL: http://codereview.appspot.com/5794079/
git-svn-id: http://skia.googlecode.com/svn/trunk@3372 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 7ea36da..e5f95e6 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1541,8 +1541,7 @@
void GrContext::flushDrawBuffer() {
#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
if (fDrawBuffer) {
- fDrawBuffer->playback(fGpu);
- fDrawBuffer->reset();
+ fDrawBuffer->flushTo(fGpu);
}
#endif
}
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index d180bcc..3dd86d2 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -573,6 +573,7 @@
int indexCount,
void** vertices,
void** indices) {
+ this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
if (vertexCount) {
if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
if (indexCount) {
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index cc0e875..488b5bb 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -332,11 +332,11 @@
* @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 @@
* 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 @@
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,
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 722ea42..b6581c0 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -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 @@
// 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::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 {
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 73746e9..b802f96 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -67,30 +67,60 @@
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 @@
GrSTAllocator<kStatePreallocCnt, SavedDrawState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;
GrSTAllocator<kClipPreallocCnt, GrClip> fClips;
-
+
+ GrDrawTarget* fAutoFlushTarget;
+
bool fClipSet;
GrVertexLayout fLastRectVertexLayout;