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/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index d576d80..e0b66a4 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -202,6 +202,7 @@
///////////////////////////////////////////////////////////////////////////
GrDrawTarget();
+ virtual ~GrDrawTarget();
/**
* Sets the current clip to the region specified by clip. All draws will be
@@ -607,9 +608,14 @@
GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
/**
- * There are three paths for specifying geometry (vertices and optionally
+ * There are three methods for specifying geometry (vertices and optionally
* indices) to the draw target. When indexed drawing the indices and vertices
- * can be each use a different path.
+ * can use a different method. Once geometry is specified it can be used for
+ * multiple drawIndexed and drawNonIndexed calls.
+ *
+ * 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
*
* 1. Provide a cpu array (set*SourceToArray). This is useful when the
* caller's client has already provided vertex data in a format
@@ -618,69 +624,76 @@
* drawIndexed & drawNonIndexed calls until set*SourceToArray is called
* again or one of the other two paths is chosen.
*
- * 2. Reserve and Lock. This is most useful when the caller has data it must
- * transform before drawing and will not likely render it again. The
- * caller requests that the draw target make room for some amount of
- * vertex and/or index data. The target provides ptrs to hold the data
- * data. The caller can write the data into the pts up until the first
- * drawIndexed or drawNonIndexed call. At this point the data is frozen
- * and the ptrs are no longer guaranteed to be valid. All subsequent
- * drawIndexed & drawNonIndexed calls will use this data until
- * releaseReserved geometry is called. This must be called before another
- * source is set.
+ * 2. Reserve. This is most useful when the caller has data it must
+ * transform before drawing and is not long-lived. The caller requests
+ * that the draw target make room for some amount of vertex and/or index
+ * 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
+ * are no longer valid.
*
* 3. Vertex and Index Buffers. This is most useful for geometry that will
- * be rendered multiple times. SetVertexSourceToBuffer &
- * SetIndexSourceToBuffer are used to set the buffer and subsequent
- * drawIndexed and drawNonIndexed calls use this source until another
- * source is set.
+ * 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.
*/
/**
- * Reserves space for vertices and/or indices. Draw target will use
- * reserved vertices / indices at next draw.
+ * Reserves space for vertices. Draw target will use reserved vertices at
+ * at the next draw.
*
* If succeeds:
- * if vertexCount is nonzero, *vertices will be the array
+ * if vertexCount > 0, *vertices will be the array
* of vertices to be filled by caller. The next draw will read
* these vertices.
*
- * if indexCount is nonzero, *indices will be the array of indices
- * to be filled by caller. The next indexed draw will read from
- * these indices.
- *
* If a client does not already have a vertex buffer then this is the
- * preferred way to allocate vertex/index array. It allows the subclass of
+ * 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.
*
- * Following the first draw after reserveAndLockGeometry the ptrs returned
- * by releaseReservedGeometry are 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.
+ * 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.
*
- * reserveAndLockGeometry must be matched with a releaseReservedGeometry
- * call after all draws that reference the reserved geometry data have
- * been called.
- *
- * AutoGeometryRelease can be used to automatically call the release.
- *
- * @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 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.
- * @param indices will point to reserved index space if indexCount is
- * non-zero. Illegal to pass NULL if indexCount > 0.
*
* @return true if succeeded in allocating space for the vertices and false
* if not.
*/
- bool reserveAndLockGeometry(GrVertexLayout vertexLayout,
- uint32_t vertexCount,
- uint32_t indexCount,
- void** vertices,
- void** indices);
+ 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 indexCount the number of indices to reserve space for. Can be 0.
+ * @param indices will point to reserved index space if indexCount is
+ * non-zero. Illegal to pass NULL if indexCount > 0.
+ */
+
+ 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
@@ -708,11 +721,6 @@
int* indexCount) const;
/**
- * Releases reserved vertex/index data from reserveAndLockGeometry().
- */
- void releaseReservedGeometry();
-
- /**
* Sets source of vertex data for the next draw. Array must contain
* the vertex data when this is called.
*
@@ -752,8 +760,36 @@
* before indexed draw call.
*/
void setIndexSourceToBuffer(const GrIndexBuffer* buffer);
+
+ /**
+ * Resets vertex source. Drawing from reset vertices is illegal. Set vertex
+ * source to reserved, array, or buffer before next draw. May be able to free
+ * up temporary storage allocated by setVertexSourceToArray or
+ * reserveVertexSpace.
+ */
+ void resetVertexSource();
+
+ /**
+ * Resets index source. Indexed Drawing from reset indices is illegal. Set
+ * index source to reserved, array, or buffer before next indexed draw. May
+ * be able to free up temporary storage allocated by setIndexSourceToArray
+ * or reserveIndexSpace.
+ */
+ void resetIndexSource();
/**
+ * Pushes and resets the vertex/index sources. Any reserved vertex / index
+ * data is finalized (i.e. cannot be updated after the matching pop but can
+ * be drawn from). Must be balanced by a pop.
+ */
+ void pushGeometrySource();
+
+ /**
+ * Pops the vertex / index sources from the matching push.
+ */
+ void popGeometrySource();
+
+ /**
* Draws indexed geometry using the current state and current vertex / index
* sources.
*
@@ -766,11 +802,11 @@
* is effectively trimmed to the last completely
* specified primitive.
*/
- virtual void drawIndexed(GrPrimitiveType type,
- int startVertex,
- int startIndex,
- int vertexCount,
- int indexCount) = 0;
+ void drawIndexed(GrPrimitiveType type,
+ int startVertex,
+ int startIndex,
+ int vertexCount,
+ int indexCount);
/**
* Draws non-indexed geometry using the current state and current vertex
@@ -781,9 +817,9 @@
* to index 0
* @param vertexCount one greater than the max index.
*/
- virtual void drawNonIndexed(GrPrimitiveType type,
- int startVertex,
- int vertexCount) = 0;
+ void drawNonIndexed(GrPrimitiveType type,
+ int startVertex,
+ int vertexCount);
/**
* Helper function for drawing rects. This does not use the current index
@@ -840,7 +876,7 @@
*/
virtual int getMaxEdges() const { return 6; }
- ///////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
class AutoStateRestore : ::GrNoncopyable {
public:
@@ -860,7 +896,7 @@
SavedDrawState fDrawState;
};
- ///////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
class AutoViewMatrixRestore : ::GrNoncopyable {
public:
@@ -893,7 +929,7 @@
GrMatrix fMatrix;
};
- ///////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
/**
* Sets the view matrix to I and preconcats all stage matrices enabled in
@@ -910,63 +946,36 @@
int fStageMask;
};
- ///////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
class AutoReleaseGeometry : ::GrNoncopyable {
public:
AutoReleaseGeometry(GrDrawTarget* target,
GrVertexLayout vertexLayout,
- uint32_t vertexCount,
- uint32_t indexCount) {
- fTarget = NULL;
- this->set(target, vertexLayout, vertexCount, indexCount);
- }
-
- AutoReleaseGeometry() {
- fTarget = NULL;
- }
-
- ~AutoReleaseGeometry() {
- if (NULL != fTarget) {
- fTarget->releaseReservedGeometry();
- }
- }
-
+ int vertexCount,
+ int indexCount);
+ AutoReleaseGeometry();
+ ~AutoReleaseGeometry();
bool set(GrDrawTarget* target,
GrVertexLayout vertexLayout,
- uint32_t vertexCount,
- uint32_t indexCount) {
- if (NULL != fTarget) {
- fTarget->releaseReservedGeometry();
- }
- fTarget = target;
- if (NULL != fTarget) {
- if (!fTarget->reserveAndLockGeometry(vertexLayout,
- vertexCount,
- indexCount,
- &fVertices,
- &fIndices)) {
- fTarget = NULL;
- }
- }
- return NULL != fTarget;
- }
-
+ int vertexCount,
+ int indexCount);
bool succeeded() const { return NULL != fTarget; }
void* vertices() const { return fVertices; }
void* indices() const { return fIndices; }
-
GrPoint* positions() const {
return static_cast<GrPoint*>(fVertices);
}
private:
+ void reset();
+
GrDrawTarget* fTarget;
void* fVertices;
void* fIndices;
};
- ///////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
class AutoClipRestore : ::GrNoncopyable {
public:
@@ -982,6 +991,22 @@
GrDrawTarget* fTarget;
GrClip fClip;
};
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ class AutoGeometryPush : ::GrNoncopyable {
+ public:
+ AutoGeometryPush(GrDrawTarget* target) {
+ GrAssert(NULL != target);
+ fTarget = target;
+ target->pushGeometrySource();
+ }
+ ~AutoGeometryPush() {
+ fTarget->popGeometrySource();
+ }
+ private:
+ GrDrawTarget* fTarget;
+ };
////////////////////////////////////////////////////////////////////////////
// Helpers for picking apart vertex layouts
@@ -1140,6 +1165,34 @@
static void VertexLayoutUnitTest();
protected:
+
+ enum GeometrySrcType {
+ kNone_GeometrySrcType, //<! src has not been specified
+ kReserved_GeometrySrcType, //<! src was set using reserve*Space
+ kArray_GeometrySrcType, //<! src was set using set*SourceToArray
+ kBuffer_GeometrySrcType //<! src was set using set*SourceToBuffer
+ };
+
+ struct GeometrySrcState {
+ GeometrySrcType fVertexSrc;
+ union {
+ // valid if src type is buffer
+ const GrVertexBuffer* fVertexBuffer;
+ // valid if src type is reserved or array
+ int fVertexCount;
+ };
+
+ GeometrySrcType fIndexSrc;
+ union {
+ // valid if src type is buffer
+ const GrIndexBuffer* fIndexBuffer;
+ // valid if src type is reserved or array
+ int fIndexCount;
+ };
+
+ GrVertexLayout fVertexLayout;
+ };
+
// given a vertex layout and a draw state, will a stage be used?
static bool StageWillBeUsed(int stage, GrVertexLayout layout,
const DrState& state) {
@@ -1147,7 +1200,8 @@
}
bool isStageEnabled(int stage) const {
- return StageWillBeUsed(stage, fGeometrySrc.fVertexLayout, fCurrDrawState);
+ return StageWillBeUsed(stage, this->getGeomSrc().fVertexLayout,
+ fCurrDrawState);
}
// Helpers for GrDrawTarget subclasses that won't have private access to
@@ -1157,21 +1211,38 @@
static const DrState& accessSavedDrawState(const SavedDrawState& sds)
{ return sds.fState; }
- // implemented by subclass
- virtual bool onAcquireGeometry(GrVertexLayout vertexLayout,
- void** vertices,
- void** indices) = 0;
-
- virtual void onReleaseGeometry() = 0;
-
+ // implemented by subclass to allocate space for reserved geom
+ virtual bool onReserveVertexSpace(GrVertexLayout vertexLayout,
+ int vertexCount,
+ void** vertices) = 0;
+ virtual bool onReserveIndexSpace(int indexCount, void** indices) = 0;
+ // implemented by subclass to handle release of reserved geom space
+ virtual void releaseReservedVertexSpace() = 0;
+ virtual void releaseReservedIndexSpace() = 0;
+ // subclass must consume array contents when set
+ virtual void onSetVertexSourceToArray(const void* vertexArray,
+ int vertexCount) = 0;
+ virtual void onSetIndexSourceToArray(const void* indexArray,
+ int indexCount) = 0;
+ // subclass is notified that geom source will be set away from an array
+ virtual void releaseVertexArray() = 0;
+ virtual void releaseIndexArray() = 0;
+ // subclass overrides to be notified just before geo src state
+ // is pushed/popped.
+ virtual void geometrySourceWillPush() = 0;
+ virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) = 0;
+ // subclass called to perform drawing
+ virtual void onDrawIndexed(GrPrimitiveType type,
+ int startVertex,
+ int startIndex,
+ int vertexCount,
+ int indexCount) = 0;
+ virtual void onDrawNonIndexed(GrPrimitiveType type,
+ int startVertex,
+ int vertexCount) = 0;
// subclass overrides to be notified when clip is set.
virtual void clipWillBeSet(const GrClip& clip) = 0;
- virtual void onSetVertexSourceToArray(const void* vertexArray,
- int vertexCount) = 0;
-
- virtual void onSetIndexSourceToArray(const void* indexArray,
- int indexCount) = 0;
// Helpers for drawRect, protected so subclasses that override drawRect
// can use them.
@@ -1185,51 +1256,28 @@
GrVertexLayout layout,
void* vertices);
- enum GeometrySrcType {
- kReserved_GeometrySrcType, // src was set using reserveAndLockGeometry
- kArray_GeometrySrcType, // src was set using set*SourceToArray
- kBuffer_GeometrySrcType // src was set using set*SourceToBuffer
- };
-
- struct ReservedGeometry {
- bool fLocked;
- uint32_t fVertexCount;
- uint32_t fIndexCount;
- } fReservedGeometry;
-
- struct GeometrySrc {
- GeometrySrcType fVertexSrc;
- const GrVertexBuffer* fVertexBuffer; // valid if src type is buffer
- GeometrySrcType fIndexSrc;
- const GrIndexBuffer* fIndexBuffer; // valid if src type is buffer
- GrVertexLayout fVertexLayout;
- } fGeometrySrc;
+ // accessor for derived classes
+ const GeometrySrcState& getGeomSrc() const {
+ return fGeoSrcStateStack.back();
+ }
GrClip fClip;
DrState fCurrDrawState;
- // Not meant for external use. Only setVertexSourceToBuffer and
- // setIndexSourceToBuffer will work since GrDrawTarget subclasses don't
- // support nested reserveAndLockGeometry (and cpu arrays internally use the
- // same path).
- class AutoGeometrySrcRestore {
- public:
- AutoGeometrySrcRestore(GrDrawTarget* target) {
- fTarget = target;
- fGeometrySrc = fTarget->fGeometrySrc;
- }
- ~AutoGeometrySrcRestore() {
- fTarget->fGeometrySrc = fGeometrySrc;
- }
- private:
- GrDrawTarget *fTarget;
- GeometrySrc fGeometrySrc;
-
- AutoGeometrySrcRestore();
- AutoGeometrySrcRestore(const AutoGeometrySrcRestore&);
- AutoGeometrySrcRestore& operator =(AutoGeometrySrcRestore&);
+private:
+ // called when setting a new vert/idx source to unref prev vb/ib
+ void releasePreviousVertexSource();
+ void releasePreviousIndexSource();
+
+ enum {
+ kPreallocGeoSrcStateStackCnt = 4,
};
+ GrAlignedSTStorage<kPreallocGeoSrcStateStackCnt,
+ GeometrySrcState>
+ fGeoSrcStateStackStorage;
+ GrTArray<GeometrySrcState, true> fGeoSrcStateStack;
+
};
#endif