aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-26 21:04:22 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-26 21:04:22 +0000
commita4f6b10818819a16bc94738e2eda42dfec332c43 (patch)
tree3b1ba2ae801c1c0f1827516a4520d25cf382a25f /src/gpu
parent69ffcf0d34878be7a1d2493785bf4df363199b10 (diff)
Make GrInOrderDrawBuffer playback command driven
Review URL: http://codereview.appspot.com/6341052/ git-svn-id: http://skia.googlecode.com/svn/trunk@4356 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp300
-rw-r--r--src/gpu/GrInOrderDrawBuffer.h33
2 files changed, 183 insertions, 150 deletions
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index f70b2eed2d..26be361085 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -25,7 +25,6 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
, fLastRectVertexLayout(0)
, fQuadIndexBuffer(NULL)
, fMaxQuads(0)
- , fCurrQuad(0)
, fFlushing(false) {
fCaps = gpu->getCaps();
@@ -42,7 +41,7 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0;
poolState.fPoolStartIndex = ~0;
#endif
- fInstancedDrawTracker.reset();
+ this->reset();
}
GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
@@ -149,8 +148,11 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
disabledClip = true;
}
}
- if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
- fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
+ if (!this->needsNewClip() &&
+ !this->needsNewState() &&
+ fCurrQuad > 0 &&
+ fCurrQuad < fMaxQuads &&
+ layout == fLastRectVertexLayout) {
int vsize = VertexSize(layout);
@@ -163,12 +165,9 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
GrAssert(0 == lastDraw.fStartIndex);
GeometryPoolState& poolState = fGeoPoolStateStack.back();
- bool clearSinceLastDraw =
- fClears.count() &&
- fClears.back().fBeforeDrawIdx == fDraws.count();
- appendToPreviousDraw =
- !clearSinceLastDraw &&
+ appendToPreviousDraw =
+ kDraw_Cmd != fCmds.back() &&
lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
(fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;
@@ -177,7 +176,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
lastDraw.fIndexCount += 6;
fCurrQuad += 1;
// we reserved above, so we should be the first
- // use of this vertex reserveation.
+ // use of this vertex reservation.
GrAssert(0 == poolState.fUsedPoolVertexBytes);
poolState.fUsedPoolVertexBytes = 4 * vsize;
}
@@ -212,39 +211,34 @@ void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type,
if (kReserved_GeometrySrcType == geomSrc.fVertexSrc &&
kBuffer_GeometrySrcType == geomSrc.fIndexSrc) {
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
+ if (this->needsNewState()) {
+ this->recordState();
+ }
+
Draw* draw = NULL;
// if the last draw used the same indices/vertices per shape then we
// may be able to append to it.
- if (verticesPerInstance == fInstancedDrawTracker.fVerticesPerInstance &&
+ if (kDraw_Cmd == fCmds.back() &&
+ verticesPerInstance == fInstancedDrawTracker.fVerticesPerInstance &&
indicesPerInstance == fInstancedDrawTracker.fIndicesPerInstance) {
GrAssert(fDraws.count());
draw = &fDraws.back();
}
- bool clipChanged = this->needsNewClip();
- bool stateChanged = this->needsNewState();
- if (clipChanged) {
- this->storeClip();
- }
- if (stateChanged) {
- this->pushState();
- }
-
GeometryPoolState& poolState = fGeoPoolStateStack.back();
const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
// Check whether the draw is compatible with this draw in order to
// append
if (NULL == draw ||
- clipChanged ||
- stateChanged ||
draw->fIndexBuffer != geomSrc.fIndexBuffer ||
draw->fPrimitiveType != type ||
draw->fVertexBuffer != vertexBuffer) {
- draw = &fDraws.push_back();
- draw->fClipChanged = clipChanged;
- draw->fStateChanged = stateChanged;
+ draw = this->recordDraw();
draw->fIndexBuffer = geomSrc.fIndexBuffer;
geomSrc.fIndexBuffer->ref();
draw->fVertexBuffer = vertexBuffer;
@@ -287,9 +281,7 @@ void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type,
while (instanceCount) {
if (!instancesToConcat) {
int startVertex = draw->fStartVertex + draw->fVertexCount;
- draw = &fDraws.push_back();
- draw->fClipChanged = false;
- draw->fStateChanged = false;
+ draw = this->recordDraw();
draw->fIndexBuffer = geomSrc.fIndexBuffer;
geomSrc.fIndexBuffer->ref();
draw->fVertexBuffer = vertexBuffer;
@@ -334,60 +326,58 @@ void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType,
GeometryPoolState& poolState = fGeoPoolStateStack.back();
- Draw& draw = fDraws.push_back();
- draw.fPrimitiveType = primitiveType;
- draw.fStartVertex = startVertex;
- draw.fStartIndex = startIndex;
- draw.fVertexCount = vertexCount;
- draw.fIndexCount = indexCount;
-
- draw.fClipChanged = this->needsNewClip();
- if (draw.fClipChanged) {
- this->storeClip();
+ if (this->needsNewClip()) {
+ this->recordClip();
}
-
- draw.fStateChanged = this->needsNewState();
- if (draw.fStateChanged) {
- this->pushState();
+ if (this->needsNewState()) {
+ this->recordState();
}
- draw.fVertexLayout = this->getVertexLayout();
+ Draw* draw = this->recordDraw();
+
+ draw->fPrimitiveType = primitiveType;
+ draw->fStartVertex = startVertex;
+ draw->fStartIndex = startIndex;
+ draw->fVertexCount = vertexCount;
+ draw->fIndexCount = indexCount;
+
+ draw->fVertexLayout = this->getVertexLayout();
switch (this->getGeomSrc().fVertexSrc) {
case kBuffer_GeometrySrcType:
- draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
+ draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
break;
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType: {
size_t vertexBytes = (vertexCount + startVertex) *
- VertexSize(draw.fVertexLayout);
+ VertexSize(draw->fVertexLayout);
poolState.fUsedPoolVertexBytes =
GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
- draw.fVertexBuffer = poolState.fPoolVertexBuffer;
- draw.fStartVertex += poolState.fPoolStartVertex;
+ draw->fVertexBuffer = poolState.fPoolVertexBuffer;
+ draw->fStartVertex += poolState.fPoolStartVertex;
break;
}
default:
GrCrash("unknown geom src type");
}
- draw.fVertexBuffer->ref();
+ draw->fVertexBuffer->ref();
switch (this->getGeomSrc().fIndexSrc) {
case kBuffer_GeometrySrcType:
- draw.fIndexBuffer = this->getGeomSrc().fIndexBuffer;
+ draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer;
break;
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType: {
size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
poolState.fUsedPoolIndexBytes =
GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
- draw.fIndexBuffer = poolState.fPoolIndexBuffer;
- draw.fStartIndex += poolState.fPoolStartIndex;
+ draw->fIndexBuffer = poolState.fPoolIndexBuffer;
+ draw->fStartIndex += poolState.fPoolStartIndex;
break;
}
default:
GrCrash("unknown geom src type");
}
- draw.fIndexBuffer->ref();
+ draw->fIndexBuffer->ref();
}
void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
@@ -400,44 +390,40 @@ void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
this->resetDrawTracking();
GeometryPoolState& poolState = fGeoPoolStateStack.back();
-
- Draw& draw = fDraws.push_back();
- draw.fPrimitiveType = primitiveType;
- draw.fStartVertex = startVertex;
- draw.fStartIndex = 0;
- draw.fVertexCount = vertexCount;
- draw.fIndexCount = 0;
-
- draw.fClipChanged = this->needsNewClip();
- if (draw.fClipChanged) {
- this->storeClip();
+ if (this->needsNewClip()) {
+ this->recordClip();
}
-
- draw.fStateChanged = this->needsNewState();
- if (draw.fStateChanged) {
- this->pushState();
+ if (this->needsNewState()) {
+ this->recordState();
}
- draw.fVertexLayout = this->getVertexLayout();
+ Draw* draw = this->recordDraw();
+ draw->fPrimitiveType = primitiveType;
+ draw->fStartVertex = startVertex;
+ draw->fStartIndex = 0;
+ draw->fVertexCount = vertexCount;
+ draw->fIndexCount = 0;
+
+ draw->fVertexLayout = this->getVertexLayout();
switch (this->getGeomSrc().fVertexSrc) {
case kBuffer_GeometrySrcType:
- draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
+ draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
break;
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType: {
size_t vertexBytes = (vertexCount + startVertex) *
- VertexSize(draw.fVertexLayout);
+ VertexSize(draw->fVertexLayout);
poolState.fUsedPoolVertexBytes =
GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
- draw.fVertexBuffer = poolState.fPoolVertexBuffer;
- draw.fStartVertex += poolState.fPoolStartVertex;
+ draw->fVertexBuffer = poolState.fPoolVertexBuffer;
+ draw->fStartVertex += poolState.fPoolStartVertex;
break;
}
default:
GrCrash("unknown geom src type");
}
- draw.fVertexBuffer->ref();
- draw.fIndexBuffer = NULL;
+ draw->fVertexBuffer->ref();
+ draw->fIndexBuffer = NULL;
}
void GrInOrderDrawBuffer::onStencilPath(const GrPath&, GrPathFill) {
@@ -457,12 +443,11 @@ void GrInOrderDrawBuffer::clear(const GrIRect* rect,
this->getDrawState().getRenderTarget()->height());
rect = &r;
}
- Clear& clr = fClears.push_back();
- clr.fColor = color;
- clr.fBeforeDrawIdx = fDraws.count();
- clr.fRect = *rect;
- clr.fRenderTarget = renderTarget;
- GrSafeRef(clr.fRenderTarget);
+ Clear* clr = this->recordClear();
+ clr->fColor = color;
+ clr->fRect = *rect;
+ clr->fRenderTarget = renderTarget;
+ GrSafeRef(clr->fRenderTarget);
}
void GrInOrderDrawBuffer::reset() {
@@ -476,29 +461,37 @@ void GrInOrderDrawBuffer::reset() {
fDraws[d].fVertexBuffer->unref();
GrSafeUnref(fDraws[d].fIndexBuffer);
}
+ fCmds.reset();
fDraws.reset();
fStates.reset();
-
fClears.reset();
-
fVertexPool.reset();
fIndexPool.reset();
-
fClips.reset();
+ fClipSet = true;
this->resetDrawTracking();
+
+ // we start off with a default clip and state so that we don't have
+ // to do count checks on fClips, fStates, or fCmds before checking their
+ // last entry.
+ this->recordDefaultState();
+ this->recordDefaultClip();
}
-void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
+bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
GrAssert(NULL != target);
GrAssert(target != this); // not considered and why?
- int numDraws = fDraws.count();
- if (!numDraws) {
- return;
+ int numCmds = fCmds.count();
+ GrAssert(numCmds >= 2);
+ if (2 == numCmds) {
+ GrAssert(kSetState_Cmd == fCmds[0]);
+ GrAssert(kSetClip_Cmd == fCmds[1]);
+ return false;
}
fVertexPool.unlock();
@@ -509,56 +502,59 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
GrDrawState* prevDrawState = target->drawState();
prevDrawState->ref();
- int currState = ~0;
- int currClip = ~0;
+ int currState = 0;
+ int currClip = 0;
int currClear = 0;
+ int currDraw = 0;
+
+ for (int c = 0; c < numCmds; ++c) {
+ switch (fCmds[c]) {
+ case kDraw_Cmd: {
+ const Draw& draw = fDraws[currDraw];
+ target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
+ if (draw.fIndexCount) {
+ target->setIndexSourceToBuffer(draw.fIndexBuffer);
+ }
- for (int i = 0; i < numDraws; ++i) {
- while (currClear < fClears.count() &&
- i == fClears[currClear].fBeforeDrawIdx) {
- target->clear(&fClears[currClear].fRect,
- fClears[currClear].fColor,
- fClears[currClear].fRenderTarget);
- ++currClear;
- }
-
- const Draw& draw = fDraws[i];
- if (draw.fStateChanged) {
- ++currState;
- target->setDrawState(&fStates[currState]);
- }
- if (draw.fClipChanged) {
- ++currClip;
- target->setClip(fClips[currClip]);
- }
-
- target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
-
- if (draw.fIndexCount) {
- target->setIndexSourceToBuffer(draw.fIndexBuffer);
- }
-
- if (draw.fIndexCount) {
- target->drawIndexed(draw.fPrimitiveType,
- draw.fStartVertex,
- draw.fStartIndex,
- draw.fVertexCount,
- draw.fIndexCount);
- } else {
- target->drawNonIndexed(draw.fPrimitiveType,
- draw.fStartVertex,
- draw.fVertexCount);
+ if (draw.fIndexCount) {
+ target->drawIndexed(draw.fPrimitiveType,
+ draw.fStartVertex,
+ draw.fStartIndex,
+ draw.fVertexCount,
+ draw.fIndexCount);
+ } else {
+ target->drawNonIndexed(draw.fPrimitiveType,
+ draw.fStartVertex,
+ draw.fVertexCount);
+ }
+ ++currDraw;
+ break;
+ }
+ case kSetState_Cmd:
+ target->setDrawState(&fStates[currState]);
+ ++currState;
+ break;
+ case kSetClip_Cmd:
+ target->setClip(fClips[currClip]);
+ ++currClip;
+ break;
+ case kClear_Cmd:
+ target->clear(&fClears[currClear].fRect,
+ fClears[currClear].fColor,
+ fClears[currClear].fRenderTarget);
+ ++currClear;
+ break;
}
}
- while (currClear < fClears.count()) {
- GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
- target->clear(&fClears[currClear].fRect,
- fClears[currClear].fColor,
- fClears[currClear].fRenderTarget);
- ++currClear;
- }
+ // we should have consumed all the states, clips, etc.
+ GrAssert(fStates.count() == currState);
+ GrAssert(fClips.count() == currClip);
+ GrAssert(fClears.count() == currClear);
+ GrAssert(fDraws.count() == currDraw);
+
target->setDrawState(prevDrawState);
prevDrawState->unref();
+ return true;
}
void GrInOrderDrawBuffer::setAutoFlushTarget(GrDrawTarget* target) {
@@ -774,29 +770,49 @@ void GrInOrderDrawBuffer::geometrySourceWillPop(
}
bool GrInOrderDrawBuffer::needsNewState() const {
- if (fStates.empty()) {
- return true;
- } else {
- return fStates.back() != this->getDrawState();
- }
+ // we should have recorded a default state in reset()
+ GrAssert(!fStates.empty());
+ return fStates.back() != this->getDrawState();
}
-void GrInOrderDrawBuffer::pushState() {
- fStates.push_back(this->getDrawState());
- }
-
bool GrInOrderDrawBuffer::needsNewClip() const {
if (this->getDrawState().isClipState()) {
- if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
+ if (fClipSet && fClips.back() != fClip) {
return true;
}
}
return false;
}
-void GrInOrderDrawBuffer::storeClip() {
+void GrInOrderDrawBuffer::recordClip() {
fClips.push_back() = fClip;
fClipSet = false;
+ fCmds.push_back(kSetClip_Cmd);
+}
+
+void GrInOrderDrawBuffer::recordDefaultClip() {
+ fClips.push_back() = GrClip();
+ fCmds.push_back(kSetClip_Cmd);
+}
+
+void GrInOrderDrawBuffer::recordState() {
+ fStates.push_back(this->getDrawState());
+ fCmds.push_back(kSetState_Cmd);
+}
+
+void GrInOrderDrawBuffer::recordDefaultState() {
+ fStates.push_back(GrDrawState());
+ fCmds.push_back(kSetState_Cmd);
+}
+
+GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw() {
+ fCmds.push_back(kDraw_Cmd);
+ return &fDraws.push_back();
+}
+
+GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() {
+ fCmds.push_back(kClear_Cmd);
+ return &fClears.push_back();
}
void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 9b5561a1ff..61fa9e2a86 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -72,9 +72,12 @@ public:
* the target will be finalized because it's geometry source will be pushed
* before playback and popped afterwards.
*
+ * @return false if the playback trivially drew nothing because nothing was
+ * recorded.
+ *
* @param target the target to receive the playback
*/
- void playback(GrDrawTarget* target);
+ bool playback(GrDrawTarget* target);
/**
* A convenience method to do a playback followed by a reset. All the
@@ -90,8 +93,9 @@ public:
}
fFlushing = true;
- this->playback(target);
- this->reset();
+ if (this->playback(target)) {
+ this->reset();
+ }
fFlushing = false;
}
@@ -131,14 +135,19 @@ protected:
int vertexCount,
int indexCount) SK_OVERRIDE;
private:
+ enum Cmd {
+ kDraw_Cmd = 1,
+ kSetState_Cmd = 2,
+ kSetClip_Cmd = 3,
+ kClear_Cmd = 4,
+ };
+
struct Draw {
GrPrimitiveType fPrimitiveType;
int fStartVertex;
int fStartIndex;
int fVertexCount;
int fIndexCount;
- bool fStateChanged;
- bool fClipChanged;
GrVertexLayout fVertexLayout;
const GrVertexBuffer* fVertexBuffer;
const GrIndexBuffer* fIndexBuffer;
@@ -148,7 +157,6 @@ private:
Clear() : fRenderTarget(NULL) {}
~Clear() { GrSafeUnref(fRenderTarget); }
- int fBeforeDrawIdx;
GrIRect fRect;
GrColor fColor;
GrRenderTarget* fRenderTarget;
@@ -182,17 +190,25 @@ private:
const GeometrySrcState& restoredState) SK_OVERRIDE;
virtual void clipWillBeSet(const GrClip& newClip) SK_OVERRIDE;
+ // we lazily record state and clip changes in order to skip clips and states
+ // that have no effect.
bool needsNewState() const;
bool needsNewClip() const;
- void pushState();
- void storeClip();
+ // these functions record a command
+ void recordState();
+ void recordDefaultState();
+ void recordClip();
+ void recordDefaultClip();
+ Draw* recordDraw();
+ Clear* recordClear();
// call this to invalidate the tracking data that is used to concatenate
// multiple draws into a single draw.
void resetDrawTracking();
enum {
+ kCmdPreallocCnt = 32,
kDrawPreallocCnt = 8,
kStatePreallocCnt = 8,
kClipPreallocCnt = 8,
@@ -200,6 +216,7 @@ private:
kGeoPoolStatePreAllocCnt = 4,
};
+ SkSTArray<kCmdPreallocCnt, uint8_t, true> fCmds;
GrSTAllocator<kDrawPreallocCnt, Draw> fDraws;
GrSTAllocator<kStatePreallocCnt, GrDrawState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;