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/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index b5f9259..cc64058 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -18,6 +18,8 @@
#include "GrDrawTarget.h"
#include "GrGpuVertex.h"
#include "GrTexture.h"
+#include "GrVertexBuffer.h"
+#include "GrIndexBuffer.h"
namespace {
@@ -282,17 +284,33 @@
////////////////////////////////////////////////////////////////////////////////
-GrDrawTarget::GrDrawTarget() {
+#define DEBUG_INVAL_BUFFER 0xdeadcafe
+#define DEBUG_INVAL_START_IDX -1
+
+GrDrawTarget::GrDrawTarget()
+: fGeoSrcStateStack(&fGeoSrcStateStackStorage) {
#if GR_DEBUG
VertexLayoutUnitTest();
#endif
- fReservedGeometry.fLocked = false;
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
#if GR_DEBUG
- fReservedGeometry.fVertexCount = ~0;
- fReservedGeometry.fIndexCount = ~0;
+ geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
+ geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
+ geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
+ geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
#endif
- fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
- fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
+ geoSrc.fVertexSrc = kNone_GeometrySrcType;
+ geoSrc.fIndexSrc = kNone_GeometrySrcType;
+}
+
+GrDrawTarget::~GrDrawTarget() {
+ int popCnt = fGeoSrcStateStack.count() - 1;
+ while (popCnt) {
+ this->popGeometrySource();
+ --popCnt;
+ }
+ this->releasePreviousVertexSource();
+ this->releasePreviousIndexSource();
}
void GrDrawTarget::setClip(const GrClip& clip) {
@@ -429,39 +447,54 @@
fCurrDrawState = srcTarget.fCurrDrawState;
}
+bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
+ int vertexCount,
+ void** vertices) {
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ bool acquired = false;
+ if (vertexCount > 0) {
+ GrAssert(NULL != vertices);
+ this->releasePreviousVertexSource();
+ geoSrc.fVertexSrc = kNone_GeometrySrcType;
-bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout,
- uint32_t vertexCount,
- uint32_t indexCount,
- void** vertices,
- void** indices) {
- GrAssert(!fReservedGeometry.fLocked);
- fReservedGeometry.fVertexCount = vertexCount;
- fReservedGeometry.fIndexCount = indexCount;
-
- fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout,
- vertices,
- indices);
- if (fReservedGeometry.fLocked) {
- if (vertexCount) {
- fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
- fGeometrySrc.fVertexLayout = vertexLayout;
- } else if (NULL != vertices) {
- *vertices = NULL;
- }
- if (indexCount) {
- fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
- } else if (NULL != indices) {
- *indices = NULL;
- }
+ acquired = this->onReserveVertexSpace(vertexLayout,
+ vertexCount,
+ vertices);
}
- return fReservedGeometry.fLocked;
+ if (acquired) {
+ geoSrc.fVertexSrc = kReserved_GeometrySrcType;
+ geoSrc.fVertexCount = vertexCount;
+ geoSrc.fVertexLayout = vertexLayout;
+ } else if (NULL != vertices) {
+ *vertices = NULL;
+ }
+ return acquired;
+}
+
+bool GrDrawTarget::reserveIndexSpace(int indexCount,
+ void** indices) {
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ bool acquired = false;
+ if (indexCount > 0) {
+ GrAssert(NULL != indices);
+ this->releasePreviousIndexSource();
+ geoSrc.fIndexSrc = kNone_GeometrySrcType;
+
+ acquired = this->onReserveIndexSpace(indexCount, indices);
+ }
+ if (acquired) {
+ geoSrc.fIndexSrc = kReserved_GeometrySrcType;
+ geoSrc.fIndexCount = indexCount;
+ } else if (NULL != indices) {
+ *indices = NULL;
+ }
+ return acquired;
+
}
bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
int32_t* vertexCount,
int32_t* indexCount) const {
- GrAssert(!fReservedGeometry.fLocked);
if (NULL != vertexCount) {
*vertexCount = -1;
}
@@ -471,39 +504,199 @@
return false;
}
-void GrDrawTarget::releaseReservedGeometry() {
- GrAssert(fReservedGeometry.fLocked);
- this->onReleaseGeometry();
- fReservedGeometry.fLocked = false;
+void GrDrawTarget::releasePreviousVertexSource() {
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ switch (geoSrc.fVertexSrc) {
+ case kNone_GeometrySrcType:
+ break;
+ case kArray_GeometrySrcType:
+ this->releaseVertexArray();
+ break;
+ case kReserved_GeometrySrcType:
+ this->releaseReservedVertexSpace();
+ break;
+ case kBuffer_GeometrySrcType:
+ geoSrc.fVertexBuffer->unref();
+#if GR_DEBUG
+ geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
+#endif
+ break;
+ default:
+ GrCrash("Unknown Vertex Source Type.");
+ break;
+ }
+}
+
+void GrDrawTarget::releasePreviousIndexSource() {
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ switch (geoSrc.fIndexSrc) {
+ case kNone_GeometrySrcType: // these two don't require
+ break;
+ case kArray_GeometrySrcType:
+ this->releaseIndexArray();
+ break;
+ case kReserved_GeometrySrcType:
+ this->releaseReservedIndexSpace();
+ break;
+ case kBuffer_GeometrySrcType:
+ geoSrc.fIndexBuffer->unref();
+#if GR_DEBUG
+ geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
+#endif
+ break;
+ default:
+ GrCrash("Unknown Index Source Type.");
+ break;
+ }
}
void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
const void* vertexArray,
int vertexCount) {
- fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
- fGeometrySrc.fVertexLayout = vertexLayout;
+ this->releasePreviousVertexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fVertexSrc = kArray_GeometrySrcType;
+ geoSrc.fVertexLayout = vertexLayout;
+ geoSrc.fVertexCount = vertexCount;
this->onSetVertexSourceToArray(vertexArray, vertexCount);
}
void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
int indexCount) {
- fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
+ this->releasePreviousIndexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fIndexSrc = kArray_GeometrySrcType;
+ geoSrc.fIndexCount = indexCount;
this->onSetIndexSourceToArray(indexArray, indexCount);
}
void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
const GrVertexBuffer* buffer) {
- fGeometrySrc.fVertexSrc = kBuffer_GeometrySrcType;
- fGeometrySrc.fVertexBuffer = buffer;
- fGeometrySrc.fVertexLayout = vertexLayout;
+ this->releasePreviousVertexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
+ geoSrc.fVertexBuffer = buffer;
+ buffer->ref();
+ geoSrc.fVertexLayout = vertexLayout;
}
void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
- fGeometrySrc.fIndexSrc = kBuffer_GeometrySrcType;
- fGeometrySrc.fIndexBuffer = buffer;
+ this->releasePreviousIndexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
+ geoSrc.fIndexBuffer = buffer;
+ buffer->ref();
}
-///////////////////////////////////////////////////////////////////////////////
+void GrDrawTarget::resetVertexSource() {
+ this->releasePreviousVertexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fVertexSrc = kNone_GeometrySrcType;
+}
+
+void GrDrawTarget::resetIndexSource() {
+ this->releasePreviousIndexSource();
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ geoSrc.fIndexSrc = kNone_GeometrySrcType;
+}
+
+void GrDrawTarget::pushGeometrySource() {
+ this->geometrySourceWillPush();
+ GeometrySrcState& newState = fGeoSrcStateStack.push_back();
+ newState.fIndexSrc = kNone_GeometrySrcType;
+ newState.fVertexSrc = kNone_GeometrySrcType;
+#if GR_DEBUG
+ newState.fVertexCount = ~0;
+ newState.fVertexBuffer = (GrVertexBuffer*)~0;
+ newState.fIndexCount = ~0;
+ newState.fIndexBuffer = (GrIndexBuffer*)~0;
+#endif
+}
+
+void GrDrawTarget::popGeometrySource() {
+ const GeometrySrcState& geoSrc = this->getGeomSrc();
+ // if popping last element then pops are unbalanced with pushes
+ GrAssert(fGeoSrcStateStack.count() > 1);
+
+ this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
+ this->releasePreviousVertexSource();
+ this->releasePreviousIndexSource();
+ fGeoSrcStateStack.pop_back();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
+ int startIndex, int vertexCount,
+ int indexCount) {
+#if GR_DEBUG
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ int maxVertex = startVertex + vertexCount;
+ int maxValidVertex;
+ switch (geoSrc.fVertexSrc) {
+ case kNone_GeometrySrcType:
+ GrCrash("Attempting to draw indexed geom without vertex src.");
+ case kReserved_GeometrySrcType: // fallthrough
+ case kArray_GeometrySrcType:
+ maxValidVertex = geoSrc.fVertexCount;
+ break;
+ case kBuffer_GeometrySrcType:
+ maxValidVertex = geoSrc.fVertexBuffer->size() /
+ VertexSize(geoSrc.fVertexLayout);
+ break;
+ }
+ if (maxVertex > maxValidVertex) {
+ GrCrash("Indexed drawing outside valid vertex range.");
+ }
+ int maxIndex = startIndex + indexCount;
+ int maxValidIndex;
+ switch (geoSrc.fIndexSrc) {
+ case kNone_GeometrySrcType:
+ GrCrash("Attempting to draw indexed geom without index src.");
+ case kReserved_GeometrySrcType: // fallthrough
+ case kArray_GeometrySrcType:
+ maxValidIndex = geoSrc.fIndexCount;
+ break;
+ case kBuffer_GeometrySrcType:
+ maxValidIndex = geoSrc.fIndexBuffer->size() / sizeof(uint16_t);
+ break;
+ }
+ if (maxIndex > maxValidIndex) {
+ GrCrash("Indexed drawing outside valid index range.");
+ }
+#endif
+ this->onDrawIndexed(type, startVertex, startIndex,
+ vertexCount, indexCount);
+}
+
+
+void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
+ int startVertex,
+ int vertexCount) {
+#if GR_DEBUG
+ GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
+ int maxVertex = startVertex + vertexCount;
+ int maxValidVertex;
+ switch (geoSrc.fVertexSrc) {
+ case kNone_GeometrySrcType:
+ GrCrash("Attempting to draw non-indexed geom without vertex src.");
+ case kReserved_GeometrySrcType: // fallthrough
+ case kArray_GeometrySrcType:
+ maxValidVertex = geoSrc.fVertexCount;
+ break;
+ case kBuffer_GeometrySrcType:
+ maxValidVertex = geoSrc.fVertexBuffer->size() /
+ VertexSize(geoSrc.fVertexLayout);
+ break;
+ }
+ if (maxVertex > maxValidVertex) {
+ GrCrash("Non-indexed drawing outside valid vertex range.");
+ }
+#endif
+ this->onDrawNonIndexed(type, startVertex, vertexCount);
+}
+
+////////////////////////////////////////////////////////////////////////////////
bool GrDrawTarget::canDisableBlend() const {
// If we compute a coverage value (using edge AA or a coverage stage) then
@@ -523,7 +716,7 @@
}
// If we have vertex color without alpha then we can't force blend off
- if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
+ if ((this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) ||
0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
return false;
}
@@ -572,7 +765,8 @@
}
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
void GrDrawTarget::drawRect(const GrRect& rect,
const GrMatrix* matrix,
StageBitfield stageEnableBitfield,
@@ -648,7 +842,7 @@
}
}
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
GrDrawTarget::AutoStateRestore::AutoStateRestore() {
fDrawTarget = NULL;
@@ -679,7 +873,7 @@
}
}
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target,
int stageMask) {
@@ -714,3 +908,62 @@
}
}
+////////////////////////////////////////////////////////////////////////////////
+
+GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
+ GrDrawTarget* target,
+ GrVertexLayout vertexLayout,
+ int vertexCount,
+ int indexCount) {
+ fTarget = NULL;
+ this->set(target, vertexLayout, vertexCount, indexCount);
+}
+
+GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
+ fTarget = NULL;
+}
+
+GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
+ this->reset();
+}
+
+bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
+ GrVertexLayout vertexLayout,
+ int vertexCount,
+ int indexCount) {
+ this->reset();
+ fTarget = 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();
+ }
+ }
+ }
+ GrAssert(success == (NULL != fTarget));
+ return success;
+}
+
+void GrDrawTarget::AutoReleaseGeometry::reset() {
+ if (NULL != fTarget) {
+ if (NULL != fVertices) {
+ fTarget->resetVertexSource();
+ }
+ if (NULL != fIndices) {
+ fTarget->resetIndexSource();
+ }
+ fTarget = NULL;
+ }
+}
+