aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@google.com>2014-10-13 14:00:42 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-13 14:00:42 -0700
commit07894c4d7dbd539583d7f51f05616e295eef2578 (patch)
tree7d6cd877bbcdaab334460ce784a5612abe5a5e09
parentbe23418776414ccc6d534ba4dcbe1361b94f4356 (diff)
Revert of Create a single command buffer for GrInOrderDrawBuffer (patchset #14 id:1050001 of https://codereview.chromium.org/628453002/)
Reason for revert: New test failing on Android: http://build.chromium.org/p/client.skia.android/builders/Test-Android-Nexus7-Tegra3-Arm7-Release/builds/89/steps/dm/logs/stdio Original issue's description: > Adds a GrTBaseList class that GrInOrderDrawBuffer uses to allocate > all its commands interleaved in contiguous memory. GrTBaseList also > supports extra data associated with objects, so we can store arrays > inline without having to call malloc(). > > Committed: https://skia.googlesource.com/skia/+/47c844aaba81e5a29c773b660e1d6062c766d253 TBR=bsalomon@google.com,reed@google.com,cdalton@nvidia.com NOTREECHECKS=true NOTRY=true Review URL: https://codereview.chromium.org/652843002
-rw-r--r--gyp/gpu.gypi1
-rw-r--r--gyp/tests.gypi1
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp353
-rw-r--r--src/gpu/GrInOrderDrawBuffer.h152
-rw-r--r--src/gpu/GrTRecorder.h251
-rw-r--r--tests/GrTRecorderTest.cpp244
6 files changed, 289 insertions, 713 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index e8d2f63345..a853cf5675 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -162,7 +162,6 @@
'<(skia_src_path)/gpu/GrTexture.cpp',
'<(skia_src_path)/gpu/GrTexturePriv.h',
'<(skia_src_path)/gpu/GrTextureAccess.cpp',
- '<(skia_src_path)/gpu/GrTRecorder.h',
'<(skia_src_path)/gpu/GrVertexBuffer.h',
'<(skia_src_path)/gpu/effects/Gr1DKernelEffect.h',
diff --git a/gyp/tests.gypi b/gyp/tests.gypi
index 6a2032646b..fc0d69d0bf 100644
--- a/gyp/tests.gypi
+++ b/gyp/tests.gypi
@@ -115,7 +115,6 @@
'../tests/GrRedBlackTreeTest.cpp',
'../tests/GrSurfaceTest.cpp',
'../tests/GrTBSearchTest.cpp',
- '../tests/GrTRecorderTest.cpp',
'../tests/GradientTest.cpp',
'../tests/ImageCacheTest.cpp',
'../tests/ImageDecodingTest.cpp',
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 753a379ff8..b9e84c0a99 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -18,9 +18,6 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
GrVertexBufferAllocPool* vertexPool,
GrIndexBufferAllocPool* indexPool)
: GrDrawTarget(gpu->getContext())
- , fCmdBuffer(kCmdBufferInitialSizeInBytes)
- , fLastState(NULL)
- , fLastClip(NULL)
, fDstGpu(gpu)
, fClipSet(true)
, fClipProxyState(kUnknown_ClipProxyState)
@@ -219,7 +216,6 @@ bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) {
}
int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
- SkASSERT(!fCmdBuffer.empty());
SkASSERT(info.isInstanced());
const GeometrySrcState& geomSrc = this->getGeomSrc();
@@ -234,17 +230,17 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
}
// Check if there is a draw info that is compatible that uses the same VB from the pool and
// the same IB
- if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) {
+ if (kDraw_Cmd != strip_trace_bit(fCmds.back())) {
return 0;
}
- Draw* draw = static_cast<Draw*>(&fCmdBuffer.back());
+ Draw* draw = &fDraws.back();
GeometryPoolState& poolState = fGeoPoolStateStack.back();
const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;
- if (!draw->fInfo.isInstanced() ||
- draw->fInfo.verticesPerInstance() != info.verticesPerInstance() ||
- draw->fInfo.indicesPerInstance() != info.indicesPerInstance() ||
+ if (!draw->isInstanced() ||
+ draw->verticesPerInstance() != info.verticesPerInstance() ||
+ draw->indicesPerInstance() != info.indicesPerInstance() ||
draw->vertexBuffer() != vertexBuffer ||
draw->indexBuffer() != geomSrc.fIndexBuffer) {
return 0;
@@ -252,15 +248,15 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
// info does not yet account for the offset from the start of the pool's VB while the previous
// draw record does.
int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex();
- if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) {
+ if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) {
return 0;
}
- SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount());
+ SkASSERT(poolState.fPoolStartVertex == draw->startVertex() + draw->vertexCount());
// how many instances can be concat'ed onto draw given the size of the index buffer
int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
- instancesToConcat -= draw->fInfo.instanceCount();
+ instancesToConcat -= draw->instanceCount();
instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
// update the amount of reserved vertex data actually referenced in draws
@@ -268,15 +264,15 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
drawState.getVertexStride();
poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
- draw->fInfo.adjustInstanceCount(instancesToConcat);
+ draw->adjustInstanceCount(instancesToConcat);
// update last fGpuCmdMarkers to include any additional trace markers that have been added
if (this->getActiveTraceMarkers().count() > 0) {
- if (cmd_has_trace_marker(draw->fType)) {
+ if (cmd_has_trace_marker(fCmds.back())) {
fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
} else {
fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
- draw->fType = add_trace_bit(draw->fType);
+ fCmds.back() = add_trace_bit(fCmds.back());
}
}
@@ -313,7 +309,9 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
acr.set(this->drawState());
}
- this->recordClipIfNecessary();
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
this->recordStateIfNecessary();
const GrVertexBuffer* vb;
@@ -336,51 +334,52 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
if (info.isInstanced()) {
int instancesConcated = this->concatInstancedDraw(info);
if (info.instanceCount() > instancesConcated) {
- draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib));
- draw->fInfo.adjustInstanceCount(-instancesConcated);
+ draw = this->recordDraw(info, vb, ib);
+ draw->adjustInstanceCount(-instancesConcated);
} else {
return;
}
} else {
- draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib));
+ draw = this->recordDraw(info, vb, ib);
}
- this->recordTraceMarkersIfNecessary();
// Adjust the starting vertex and index when we are using reserved or array sources to
// compensate for the fact that the data was inserted into a larger vb/ib owned by the pool.
if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) {
size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride();
poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes);
- draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex);
+ draw->adjustStartVertex(poolState.fPoolStartVertex);
}
if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) {
size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes);
- draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex);
+ draw->adjustStartIndex(poolState.fPoolStartIndex);
}
}
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
- this->recordClipIfNecessary();
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
// Only compare the subset of GrDrawState relevant to path stenciling?
this->recordStateIfNecessary();
- StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath, (path));
+ StencilPath* sp = this->recordStencilPath(path);
sp->fFill = fill;
- this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
SkPath::FillType fill, const GrDeviceCoordTexture* dstCopy) {
- this->recordClipIfNecessary();
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
// TODO: Only compare the subset of GrDrawState relevant to path covering?
this->recordStateIfNecessary();
- DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
- dp->fFill = fill;
+ DrawPath* cp = this->recordDrawPath(path);
+ cp->fFill = fill;
if (dstCopy) {
- dp->fDstCopy = *dstCopy;
+ cp->fDstCopy = *dstCopy;
}
- this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
@@ -391,25 +390,25 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
SkASSERT(indices);
SkASSERT(transforms);
- this->recordClipIfNecessary();
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
this->recordStateIfNecessary();
-
- int sizeOfIndices = sizeof(uint32_t) * count;
- int sizeOfTransforms = sizeof(float) * count *
- GrPathRendering::PathTransformSize(transformsType);
-
- DrawPaths* dp = GrNEW_APPEND_WITH_DATA_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange),
- sizeOfIndices + sizeOfTransforms);
- memcpy(dp->indices(), indices, sizeOfIndices);
+ DrawPaths* dp = this->recordDrawPaths(pathRange);
+ dp->fIndices = SkNEW_ARRAY(uint32_t, count); // TODO: Accomplish this without a malloc
+ memcpy(dp->fIndices, indices, sizeof(uint32_t) * count);
dp->fCount = count;
- memcpy(dp->transforms(), transforms, sizeOfTransforms);
+
+ const int transformsLength = GrPathRendering::PathTransformSize(transformsType) * count;
+ dp->fTransforms = SkNEW_ARRAY(float, transformsLength);
+ memcpy(dp->fTransforms, transforms, sizeof(float) * transformsLength);
dp->fTransformsType = transformsType;
+
dp->fFill = fill;
+
if (dstCopy) {
dp->fDstCopy = *dstCopy;
}
-
- this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
@@ -426,12 +425,11 @@ void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
rect = &r;
}
- Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
+ Clear* clr = this->recordClear(renderTarget);
GrColorIsPMAssert(color);
clr->fColor = color;
clr->fRect = *rect;
clr->fCanIgnoreRect = canIgnoreRect;
- this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
@@ -442,21 +440,26 @@ void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
renderTarget = this->drawState()->getRenderTarget();
SkASSERT(renderTarget);
}
- Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
+ Clear* clr = this->recordClear(renderTarget);
clr->fColor = GrColor_ILLEGAL;
- this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::reset() {
SkASSERT(1 == fGeoPoolStateStack.count());
this->resetVertexSource();
this->resetIndexSource();
-
- fCmdBuffer.reset();
- fLastState = NULL;
- fLastClip = NULL;
+
+ fCmds.reset();
+ fDraws.reset();
+ fStencilPaths.reset();
+ fDrawPath.reset();
+ fDrawPaths.reset();
+ fStates.reset();
+ fClears.reset();
fVertexPool.reset();
fIndexPool.reset();
+ fClips.reset();
+ fCopySurfaces.reset();
fGpuCmdMarkers.reset();
fClipSet = true;
}
@@ -471,7 +474,8 @@ void GrInOrderDrawBuffer::flush() {
SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
- if (fCmdBuffer.empty()) {
+ int numCmds = fCmds.count();
+ if (0 == numCmds) {
return;
}
@@ -486,35 +490,113 @@ void GrInOrderDrawBuffer::flush() {
GrDrawState* prevDrawState = SkRef(fDstGpu->drawState());
- CmdBuffer::Iter iter(fCmdBuffer);
+ GrClipData clipData;
- int currCmdMarker = 0;
- fDstGpu->saveActiveTraceMarkers();
+ StateAllocator::Iter stateIter(&fStates);
+ ClipAllocator::Iter clipIter(&fClips);
+ ClearAllocator::Iter clearIter(&fClears);
+ DrawAllocator::Iter drawIter(&fDraws);
+ StencilPathAllocator::Iter stencilPathIter(&fStencilPaths);
+ DrawPathAllocator::Iter drawPathIter(&fDrawPath);
+ DrawPathsAllocator::Iter drawPathsIter(&fDrawPaths);
+ CopySurfaceAllocator::Iter copySurfaceIter(&fCopySurfaces);
+
+ int currCmdMarker = 0;
- while (iter.next()) {
+ fDstGpu->saveActiveTraceMarkers();
+ for (int c = 0; c < numCmds; ++c) {
GrGpuTraceMarker newMarker("", -1);
SkString traceString;
- if (cmd_has_trace_marker(iter->fType)) {
+ if (cmd_has_trace_marker(fCmds[c])) {
traceString = fGpuCmdMarkers[currCmdMarker].toString();
newMarker.fMarker = traceString.c_str();
fDstGpu->addGpuTraceMarker(&newMarker);
++currCmdMarker;
}
-
- SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) ||
- kStencilPath_Cmd == strip_trace_bit(iter->fType) ||
- kDrawPath_Cmd == strip_trace_bit(iter->fType) ||
- kDrawPaths_Cmd == strip_trace_bit(iter->fType));
- SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState);
-
- iter->execute(fDstGpu);
-
- if (cmd_has_trace_marker(iter->fType)) {
+ switch (strip_trace_bit(fCmds[c])) {
+ case kDraw_Cmd: {
+ SkASSERT(fDstGpu->drawState() != prevDrawState);
+ SkAssertResult(drawIter.next());
+ fDstGpu->setVertexSourceToBuffer(drawIter->vertexBuffer());
+ if (drawIter->isIndexed()) {
+ fDstGpu->setIndexSourceToBuffer(drawIter->indexBuffer());
+ }
+ fDstGpu->executeDraw(*drawIter);
+ break;
+ }
+ case kStencilPath_Cmd: {
+ SkASSERT(fDstGpu->drawState() != prevDrawState);
+ SkAssertResult(stencilPathIter.next());
+ fDstGpu->stencilPath(stencilPathIter->path(), stencilPathIter->fFill);
+ break;
+ }
+ case kDrawPath_Cmd: {
+ SkASSERT(fDstGpu->drawState() != prevDrawState);
+ SkAssertResult(drawPathIter.next());
+ fDstGpu->executeDrawPath(drawPathIter->path(), drawPathIter->fFill,
+ drawPathIter->fDstCopy.texture() ?
+ &drawPathIter->fDstCopy :
+ NULL);
+ break;
+ }
+ case kDrawPaths_Cmd: {
+ SkASSERT(fDstGpu->drawState() != prevDrawState);
+ SkAssertResult(drawPathsIter.next());
+ const GrDeviceCoordTexture* dstCopy =
+ drawPathsIter->fDstCopy.texture() ? &drawPathsIter->fDstCopy : NULL;
+ fDstGpu->executeDrawPaths(drawPathsIter->pathRange(),
+ drawPathsIter->fIndices,
+ drawPathsIter->fCount,
+ drawPathsIter->fTransforms,
+ drawPathsIter->fTransformsType,
+ drawPathsIter->fFill,
+ dstCopy);
+ break;
+ }
+ case kSetState_Cmd:
+ SkAssertResult(stateIter.next());
+ fDstGpu->setDrawState(stateIter.get());
+ break;
+ case kSetClip_Cmd:
+ SkAssertResult(clipIter.next());
+ clipData.fClipStack = &clipIter->fStack;
+ clipData.fOrigin = clipIter->fOrigin;
+ fDstGpu->setClip(&clipData);
+ break;
+ case kClear_Cmd:
+ SkAssertResult(clearIter.next());
+ if (GrColor_ILLEGAL == clearIter->fColor) {
+ fDstGpu->discard(clearIter->renderTarget());
+ } else {
+ fDstGpu->clear(&clearIter->fRect,
+ clearIter->fColor,
+ clearIter->fCanIgnoreRect,
+ clearIter->renderTarget());
+ }
+ break;
+ case kCopySurface_Cmd:
+ SkAssertResult(copySurfaceIter.next());
+ fDstGpu->copySurface(copySurfaceIter->dst(),
+ copySurfaceIter->src(),
+ copySurfaceIter->fSrcRect,
+ copySurfaceIter->fDstPoint);
+ break;
+ }
+ if (cmd_has_trace_marker(fCmds[c])) {
fDstGpu->removeGpuTraceMarker(&newMarker);
}
}
-
fDstGpu->restoreActiveTraceMarkers();
+ // we should have consumed all the states, clips, etc.
+ SkASSERT(!stateIter.next());
+ SkASSERT(!clipIter.next());
+ SkASSERT(!clearIter.next());
+ SkASSERT(!drawIter.next());
+ SkASSERT(!copySurfaceIter.next());
+ SkASSERT(!stencilPathIter.next());
+ SkASSERT(!drawPathIter.next());
+ SkASSERT(!drawPathsIter.next());
+
SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
fDstGpu->setDrawState(prevDrawState);
@@ -523,58 +605,14 @@ void GrInOrderDrawBuffer::flush() {
++fDrawID;
}
-void GrInOrderDrawBuffer::Draw::execute(GrDrawTarget* gpu) {
- gpu->setVertexSourceToBuffer(this->vertexBuffer());
- if (fInfo.isIndexed()) {
- gpu->setIndexSourceToBuffer(this->indexBuffer());
- }
- gpu->executeDraw(fInfo);
-}
-
-void GrInOrderDrawBuffer::StencilPath::execute(GrDrawTarget* gpu) {
- gpu->stencilPath(this->path(), fFill);
-}
-
-void GrInOrderDrawBuffer::DrawPath::execute(GrDrawTarget* gpu) {
- gpu->executeDrawPath(this->path(), fFill, fDstCopy.texture() ? &fDstCopy : NULL);
-}
-
-void GrInOrderDrawBuffer::DrawPaths::execute(GrDrawTarget* gpu) {
- gpu->executeDrawPaths(this->pathRange(), this->indices(), fCount, this->transforms(),
- fTransformsType, fFill, fDstCopy.texture() ? &fDstCopy : NULL);
-}
-
-void GrInOrderDrawBuffer::SetState::execute(GrDrawTarget* gpu) {
- gpu->setDrawState(&fState);
-}
-
-void GrInOrderDrawBuffer::SetClip::execute(GrDrawTarget* gpu) {
- // Our fClipData is referenced directly, so we must remain alive for the entire
- // duration of the flush (after which the gpu's previous clip is restored).
- gpu->setClip(&fClipData);
-}
-
-void GrInOrderDrawBuffer::Clear::execute(GrDrawTarget* gpu) {
- if (GrColor_ILLEGAL == fColor) {
- gpu->discard(this->renderTarget());
- } else {
- gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
- }
-}
-
-void GrInOrderDrawBuffer::CopySurface::execute(GrDrawTarget* gpu) {
- gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
-}
-
bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) {
- CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
+ CopySurface* cs = this->recordCopySurface(dst, src);
cs->fSrcRect = srcRect;
cs->fDstPoint = dstPoint;
- this->recordTraceMarkersIfNecessary();
return true;
} else {
return false;
@@ -794,55 +832,94 @@ void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restored
}
void GrInOrderDrawBuffer::recordStateIfNecessary() {
- if (!fLastState) {
- SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (this->getDrawState()));
- fLastState = &ss->fState;
- this->convertDrawStateToPendingExec(fLastState);
- this->recordTraceMarkersIfNecessary();
+ if (fStates.empty()) {
+ this->convertDrawStateToPendingExec(&fStates.push_back(this->getDrawState()));
+ this->addToCmdBuffer(kSetState_Cmd);
return;
}
const GrDrawState& curr = this->getDrawState();
- switch (GrDrawState::CombineIfPossible(*fLastState, curr, *this->caps())) {
+ GrDrawState& prev = fStates.back();
+ switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) {
case GrDrawState::kIncompatible_CombinedState:
- fLastState = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (curr))->fState;
- this->convertDrawStateToPendingExec(fLastState);
- this->recordTraceMarkersIfNecessary();
+ this->convertDrawStateToPendingExec(&fStates.push_back(curr));
+ this->addToCmdBuffer(kSetState_Cmd);
break;
case GrDrawState::kA_CombinedState:
case GrDrawState::kAOrB_CombinedState: // Treat the same as kA.
break;
case GrDrawState::kB_CombinedState:
// prev has already been converted to pending execution. That is a one-way ticket.
- // So here we just destruct the previous state and reinit with a new copy of curr.
- // Note that this goes away when we move GrIODB over to taking optimized snapshots
- // of draw states.
- fLastState->~GrDrawState();
- SkNEW_PLACEMENT_ARGS(fLastState, GrDrawState, (curr));
- this->convertDrawStateToPendingExec(fLastState);
+ // So here we just delete prev and push back a new copy of curr. Note that this
+ // goes away when we move GrIODB over to taking optimized snapshots of draw states.
+ fStates.pop_back();
+ this->convertDrawStateToPendingExec(&fStates.push_back(curr));
break;
}
}
-void GrInOrderDrawBuffer::recordClipIfNecessary() {
- if (this->getDrawState().isClipState() &&
- fClipSet &&
- (!fLastClip || *fLastClip != *this->getClip())) {
- fLastClip = &GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetClip, (this->getClip()))->fClipData;
- this->recordTraceMarkersIfNecessary();
- fClipSet = false;
+bool GrInOrderDrawBuffer::needsNewClip() const {
+ if (this->getDrawState().isClipState()) {
+ if (fClipSet &&
+ (fClips.empty() ||
+ fClips.back().fStack != *this->getClip()->fClipStack ||
+ fClips.back().fOrigin != this->getClip()->fOrigin)) {
+ return true;
+ }
}
+ return false;
}
-void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
- SkASSERT(!fCmdBuffer.empty());
- SkASSERT(!cmd_has_trace_marker(fCmdBuffer.back().fType));
+void GrInOrderDrawBuffer::addToCmdBuffer(uint8_t cmd) {
+ SkASSERT(!cmd_has_trace_marker(cmd));
const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
if (activeTraceMarkers.count() > 0) {
- fCmdBuffer.back().fType = add_trace_bit(fCmdBuffer.back().fType);
+ fCmds.push_back(add_trace_bit(cmd));
fGpuCmdMarkers.push_back(activeTraceMarkers);
+ } else {
+ fCmds.push_back(cmd);
}
}
+void GrInOrderDrawBuffer::recordClip() {
+ fClips.push_back().fStack = *this->getClip()->fClipStack;
+ fClips.back().fOrigin = this->getClip()->fOrigin;
+ fClipSet = false;
+ this->addToCmdBuffer(kSetClip_Cmd);
+}
+
+GrInOrderDrawBuffer::Draw* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info,
+ const GrVertexBuffer* vb,
+ const GrIndexBuffer* ib) {
+ this->addToCmdBuffer(kDraw_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fDraws, Draw, (info, vb, ib));
+}
+
+GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath(const GrPath* path) {
+ this->addToCmdBuffer(kStencilPath_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fStencilPaths, StencilPath, (path));
+}
+
+GrInOrderDrawBuffer::DrawPath* GrInOrderDrawBuffer::recordDrawPath(const GrPath* path) {
+ this->addToCmdBuffer(kDrawPath_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPath, DrawPath, (path));
+}
+
+GrInOrderDrawBuffer::DrawPaths* GrInOrderDrawBuffer::recordDrawPaths(const GrPathRange* pathRange) {
+ this->addToCmdBuffer(kDrawPaths_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fDrawPaths, DrawPaths, (pathRange));
+}
+
+GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear(GrRenderTarget* rt) {
+ this->addToCmdBuffer(kClear_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fClears, Clear, (rt));
+}
+
+GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface(GrSurface* dst,
+ GrSurface* src) {
+ this->addToCmdBuffer(kCopySurface_Cmd);
+ return GrNEW_APPEND_TO_ALLOCATOR(&fCopySurfaces, CopySurface, (dst, src));
+}
+
void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
INHERITED::clipWillBeSet(newClipData);
fClipSet = true;
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 5d0fc0440d..485de07db5 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -16,7 +16,6 @@
#include "GrPath.h"
#include "GrPathRange.h"
#include "GrSurface.h"
-#include "GrTRecorder.h"
#include "GrVertexBuffer.h"
#include "SkClipStack.h"
@@ -88,7 +87,7 @@ protected:
virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
private:
- enum {
+ enum Cmd {
kDraw_Cmd = 1,
kStencilPath_Cmd = 2,
kSetState_Cmd = 3,
@@ -99,54 +98,37 @@ private:
kDrawPaths_Cmd = 8,
};
- struct Cmd : ::SkNoncopyable {
- Cmd(uint8_t type) : fType(type) {}
- virtual ~Cmd() {}
-
- virtual void execute(GrDrawTarget*) = 0;
-
- uint8_t fType;
- };
-
- struct Draw : public Cmd {
+ class Draw : public DrawInfo {
+ public:
Draw(const DrawInfo& info, const GrVertexBuffer* vb, const GrIndexBuffer* ib)
- : Cmd(kDraw_Cmd)
- , fInfo(info)
+ : DrawInfo(info)
, fVertexBuffer(vb)
, fIndexBuffer(ib) {}
const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
- virtual void execute(GrDrawTarget*);
-
- DrawInfo fInfo;
-
private:
GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer;
GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer;
};
- struct StencilPath : public Cmd {
- StencilPath(const GrPath* path) : Cmd(kStencilPath_Cmd), fPath(path) {}
+ struct StencilPath : public ::SkNoncopyable {
+ StencilPath(const GrPath* path) : fPath(path) {}
const GrPath* path() const { return fPath.get(); }
- virtual void execute(GrDrawTarget*);
-
SkPath::FillType fFill;
private:
GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
};
- struct DrawPath : public Cmd {
- DrawPath(const GrPath* path) : Cmd(kDrawPath_Cmd), fPath(path) {}
+ struct DrawPath : public ::SkNoncopyable {
+ DrawPath(const GrPath* path) : fPath(path) {}
const GrPath* path() const { return fPath.get(); }
- virtual void execute(GrDrawTarget*);
-
SkPath::FillType fFill;
GrDeviceCoordTexture fDstCopy;
@@ -154,16 +136,24 @@ private:
GrPendingIOResource<const GrPath, kRead_GrIOType> fPath;
};
- struct DrawPaths : public Cmd {
- DrawPaths(const GrPathRange* pathRange) : Cmd(kDrawPaths_Cmd), fPathRange(pathRange) {}
+ struct DrawPaths : public ::SkNoncopyable {
+ DrawPaths(const GrPathRange* pathRange)
+ : fPathRange(pathRange) {}
+
+ ~DrawPaths() {
+ if (fTransforms) {
+ SkDELETE_ARRAY(fTransforms);
+ }
+ if (fIndices) {
+ SkDELETE_ARRAY(fIndices);
+ }
+ }
const GrPathRange* pathRange() const { return fPathRange.get(); }
- uint32_t* indices() { return reinterpret_cast<uint32_t*>(CmdBuffer::GetDataForItem(this)); }
- float* transforms() { return reinterpret_cast<float*>(&this->indices()[fCount]); }
-
- virtual void execute(GrDrawTarget*);
+ uint32_t* fIndices;
size_t fCount;
+ float* fTransforms;
PathTransformType fTransformsType;
SkPath::FillType fFill;
GrDeviceCoordTexture fDstCopy;
@@ -173,13 +163,11 @@ private:
};
// This is also used to record a discard by setting the color to GrColor_ILLEGAL
- struct Clear : public Cmd {
- Clear(GrRenderTarget* rt) : Cmd(kClear_Cmd), fRenderTarget(rt) {}
-
+ struct Clear : public ::SkNoncopyable {
+ Clear(GrRenderTarget* rt) : fRenderTarget(rt) {}
+ ~Clear() { }
GrRenderTarget* renderTarget() const { return fRenderTarget.get(); }
- virtual void execute(GrDrawTarget*);
-
SkIRect fRect;
GrColor fColor;
bool fCanIgnoreRect;
@@ -188,14 +176,12 @@ private:
GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
};
- struct CopySurface : public Cmd {
- CopySurface(GrSurface* dst, GrSurface* src) : Cmd(kCopySurface_Cmd), fDst(dst), fSrc(src) {}
+ struct CopySurface : public ::SkNoncopyable {
+ CopySurface(GrSurface* dst, GrSurface* src) : fDst(dst), fSrc(src) {}
GrSurface* dst() const { return fDst.get(); }
GrSurface* src() const { return fSrc.get(); }
- virtual void execute(GrDrawTarget*);
-
SkIPoint fDstPoint;
SkIRect fSrcRect;
@@ -204,33 +190,11 @@ private:
GrPendingIOResource<GrSurface, kRead_GrIOType> fSrc;
};
- struct SetState : public Cmd {
- SetState(const GrDrawState& state) : Cmd(kSetState_Cmd), fState(state) {}
-
- virtual void execute(GrDrawTarget*);
-
- GrDrawState fState;
- };
-
- struct SetClip : public Cmd {
- SetClip(const GrClipData* clipData)
- : Cmd(kSetClip_Cmd),
- fStackStorage(*clipData->fClipStack) {
- fClipData.fClipStack = &fStackStorage;
- fClipData.fOrigin = clipData->fOrigin;
- }
-
- virtual void execute(GrDrawTarget*);
-
- GrClipData fClipData;
-
- private:
- SkClipStack fStackStorage;
+ struct Clip : public ::SkNoncopyable {
+ SkClipStack fStack;
+ SkIPoint fOrigin;
};
- typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
- typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
-
// overrides from GrDrawTarget
virtual void onDraw(const DrawInfo&) SK_OVERRIDE;
virtual void onDrawRect(const SkRect& rect,
@@ -283,25 +247,57 @@ private:
// Determines whether the current draw operation requieres a new drawstate and if so records it.
void recordStateIfNecessary();
// We lazily record clip changes in order to skip clips that have no effect.
- void recordClipIfNecessary();
- // Records any trace markers for a command after adding it to the buffer.
- void recordTraceMarkersIfNecessary();
+ bool needsNewClip() const;
+
+ // these functions record a command
+ void recordState();
+ void recordClip();
+ Draw* recordDraw(const DrawInfo&, const GrVertexBuffer*, const GrIndexBuffer*);
+ StencilPath* recordStencilPath(const GrPath*);
+ DrawPath* recordDrawPath(const GrPath*);
+ DrawPaths* recordDrawPaths(const GrPathRange*);
+ Clear* recordClear(GrRenderTarget*);
+ CopySurface* recordCopySurface(GrSurface* dst, GrSurface* src);
virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
+ void addToCmdBuffer(uint8_t cmd);
// TODO: Use a single allocator for commands and records
enum {
- kCmdBufferInitialSizeInBytes = 64 * 1024,
- kGeoPoolStatePreAllocCnt = 4,
+ kCmdPreallocCnt = 32,
+ kDrawPreallocCnt = 16,
+ kStencilPathPreallocCnt = 8,
+ kDrawPathPreallocCnt = 8,
+ kDrawPathsPreallocCnt = 8,
+ kStatePreallocCnt = 8,
+ kClipPreallocCnt = 8,
+ kClearPreallocCnt = 8,
+ kGeoPoolStatePreAllocCnt = 4,
+ kCopySurfacePreallocCnt = 4,
};
- CmdBuffer fCmdBuffer;
- GrDrawState* fLastState;
- GrClipData* fLastClip;
-
- SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
- GrDrawTarget* fDstGpu;
- bool fClipSet;
+ typedef GrTAllocator<Draw> DrawAllocator;
+ typedef GrTAllocator<StencilPath> StencilPathAllocator;
+ typedef GrTAllocator<DrawPath> DrawPathAllocator;
+ typedef GrTAllocator<DrawPaths> DrawPathsAllocator;
+ typedef GrTAllocator<GrDrawState> StateAllocator;
+ typedef GrTAllocator<Clear> ClearAllocator;
+ typedef GrTAllocator<CopySurface> CopySurfaceAllocator;
+ typedef GrTAllocator<Clip> ClipAllocator;
+
+ GrSTAllocator<kDrawPreallocCnt, Draw> fDraws;
+ GrSTAllocator<kStencilPathPreallocCnt, StencilPath> fStencilPaths;
+ GrSTAllocator<kDrawPathPreallocCnt, DrawPath> fDrawPath;
+ GrSTAllocator<kDrawPathsPreallocCnt, DrawPaths> fDrawPaths;
+ GrSTAllocator<kStatePreallocCnt, GrDrawState> fStates;
+ GrSTAllocator<kClearPreallocCnt, Clear> fClears;
+ GrSTAllocator<kCopySurfacePreallocCnt, CopySurface> fCopySurfaces;
+ GrSTAllocator<kClipPreallocCnt, Clip> fClips;
+
+ SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
+ SkSTArray<kCmdPreallocCnt, uint8_t, true> fCmds;
+ GrDrawTarget* fDstGpu;
+ bool fClipSet;
enum ClipProxyState {
kUnknown_ClipProxyState,
diff --git a/src/gpu/GrTRecorder.h b/src/gpu/GrTRecorder.h
deleted file mode 100644
index c8f7644f4f..0000000000
--- a/src/gpu/GrTRecorder.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrTRecorder_DEFINED
-#define GrTRecorder_DEFINED
-
-#include "SkTemplates.h"
-#include "SkTypes.h"
-
-template<typename TBase, typename TAlign> class GrTRecorder;
-template<typename TItem> struct GrTRecorderAllocWrapper;
-
-/**
- * Records a list of items with a common base type, optional associated data, and
- * permanent memory addresses.
- *
- * This class preallocates its own chunks of memory for hosting objects, so new items can
- * be created without excessive calls to malloc().
- *
- * To create a new item and append it to the back of the list, use the following macros:
- *
- * GrNEW_APPEND_TO_RECORDER(recorder, SubclassName, (args))
- * GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassName, (args), sizeOfData)
- *
- * Upon reset or delete, the items are destructed in the same order they were received,
- * not reverse (stack) order.
- *
- * @param TBase Common base type of items in the list. If TBase is not a class with a
- * virtual destructor, the client is responsible for invoking any necessary
- * destructors.
- *
- * For now, any subclass used in the list must have the same start address
- * as TBase (or in other words, the types must be convertible via
- * reinterpret_cast<>). Classes with multiple inheritance (or any subclass
- * on an obscure compiler) may not be compatible. This is runtime asserted
- * in debug builds.
- *
- * @param TAlign A type whose size is the desired memory alignment for object allocations.
- * This should be the largest known alignment requirement for all objects
- * that may be stored in the list.
- */
-template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable {
-public:
- class Iter;
-
- /**
- * Create a recorder.
- *
- * @param initialSizeInBytes The amount of memory reserved by the recorder initially,
- and after calls to reset().
- */
- GrTRecorder(int initialSizeInBytes)
- : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes))),
- fTailBlock(fHeadBlock),
- fLastItem(NULL) {}
-
- ~GrTRecorder() {
- this->reset();
- sk_free(fHeadBlock);
- }
-
- bool empty() { return !fLastItem; }
-
- TBase& back() {
- SkASSERT(!this->empty());
- return *fLastItem;
- }
-
- /**
- * Destruct all items in the list and reset to empty.
- */
- void reset();
-
- /**
- * Retrieve the extra data associated with an item that was allocated using
- * GrNEW_APPEND_WITH_DATA_TO_RECORDER().
- *
- * @param item The item whose data to retrieve. The pointer must be of the same type
- * that was allocated initally; it can't be a pointer to a base class.
- *
- * @return The item's associated data.
- */
- template<typename TItem> static const void* GetDataForItem(const TItem* item) {
- const TAlign* ptr = reinterpret_cast<const TAlign*>(item);
- return &ptr[length_of<TItem>::kValue];
- }
- template<typename TItem> static void* GetDataForItem(TItem* item) {
- TAlign* ptr = reinterpret_cast<TAlign*>(item);
- return &ptr[length_of<TItem>::kValue];
- }
-
-private:
- template<typename TItem> struct length_of {
- enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) };
- };
- static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeof(TAlign); }
-
- struct Header {
- int fTotalLength;
- };
- template<typename TItem> TItem* alloc_back(int dataLength);
-
- struct MemBlock {
- static MemBlock* Alloc(int length) {
- void* ptr = sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::kValue + length));
- return SkNEW_PLACEMENT_ARGS(ptr, MemBlock, (length));
- }
- TAlign& operator [](int i) {
- return reinterpret_cast<TAlign*>(this)[length_of<MemBlock>::kValue + i];
- }
- ~MemBlock() { sk_free(fNext); }
-
- const int fLength;
- int fBack;
- MemBlock* fNext;
-
- private:
- MemBlock(int length) : fLength(length), fBack(0), fNext(NULL) {}
- };
- MemBlock* const fHeadBlock;
- MemBlock* fTailBlock;
-
- TBase* fLastItem;
-
- template<typename TItem> friend struct GrTRecorderAllocWrapper;
-
- template <typename UBase, typename UAlign, typename UAlloc>
- friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&,
- const GrTRecorderAllocWrapper<UAlloc>&);
-
- friend class Iter;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-template<typename TBase, typename TAlign>
-template<typename TItem>
-TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) {
- const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength;
-
- if (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
- SkASSERT(!fTailBlock->fNext);
- fTailBlock->fNext = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLength));
- fTailBlock = fTailBlock->fNext;
- }
-
- Header* header = reinterpret_cast<Header*>(&(*fTailBlock)[fTailBlock->fBack]);
- TItem* rawPtr = reinterpret_cast<TItem*>(
- &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kValue]);
-
- header->fTotalLength = totalLength;
- fLastItem = rawPtr;
- fTailBlock->fBack += totalLength;
-
- // FIXME: We currently require that the base and subclass share the same start address.
- // This is not required by the C++ spec, and is likely to not be true in the case of
- // multiple inheritance or a base class that doesn't have virtual methods (when the
- // subclass does). It would be ideal to find a more robust solution that comes at no
- // extra cost to performance or code generality.
- SkDEBUGCODE(void* baseAddr = fLastItem;
- void* subclassAddr = rawPtr);
- SkASSERT(baseAddr == subclassAddr);
-
- return rawPtr;
-}
-
-template<typename TBase, typename TAlign>
-class GrTRecorder<TBase, TAlign>::Iter {
-public:
- Iter(GrTRecorder& recorder) : fBlock(recorder.fHeadBlock), fPosition(0), fItem(NULL) {}
-
- bool next() {
- if (fPosition >= fBlock->fBack) {
- SkASSERT(fPosition == fBlock->fBack);
- if (!fBlock->fNext) {
- return false;
- }
- SkASSERT(0 != fBlock->fNext->fBack);
- fBlock = fBlock->fNext;
- fPosition = 0;
- }
-
- Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]);
- fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header>::kValue]);
- fPosition += header->fTotalLength;
- return true;
- }
-
- TBase* get() const {
- SkASSERT(fItem);
- return fItem;
- }
-
- TBase* operator->() const { return this->get(); }
-
-private:
- MemBlock* fBlock;
- int fPosition;
- TBase* fItem;
-};
-
-template<typename TBase, typename TAlign>
-void GrTRecorder<TBase, TAlign>::reset() {
- Iter iter(*this);
- while (iter.next()) {
- iter->~TBase();
- }
- fHeadBlock->fBack = 0;
- sk_free(fHeadBlock->fNext);
- fHeadBlock->fNext = NULL;
- fTailBlock = fHeadBlock;
- fLastItem = NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-template<typename TItem> struct GrTRecorderAllocWrapper {
- GrTRecorderAllocWrapper() : fDataLength(0) {}
-
- template <typename TBase, typename TAlign>
- GrTRecorderAllocWrapper(const GrTRecorder<TBase, TAlign>&, int sizeOfData)
- : fDataLength(GrTRecorder<TBase, TAlign>::LengthOf(sizeOfData)) {}
-
- const int fDataLength;
-};
-
-template <typename TBase, typename TAlign, typename TItem>
-void* operator new(size_t size, GrTRecorder<TBase, TAlign>& recorder,
- const GrTRecorderAllocWrapper<TItem>& wrapper) {
- SkASSERT(size == sizeof(TItem));
- return recorder.template alloc_back<TItem>(wrapper.fDataLength);
-}
-
-template <typename TBase, typename TAlign, typename TItem>
-void operator delete(void*, GrTRecorder<TBase, TAlign>&, const GrTRecorderAllocWrapper<TItem>&) {
- // We only provide an operator delete to work around compiler warnings that can come
- // up for an unmatched operator new when compiling with exceptions.
- SK_CRASH();
-}
-
-#define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \
- (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args)
-
-#define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_data) \
- (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args)
-
-#endif
diff --git a/tests/GrTRecorderTest.cpp b/tests/GrTRecorderTest.cpp
deleted file mode 100644
index ef9a2aa4fa..0000000000
--- a/tests/GrTRecorderTest.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#if SK_SUPPORT_GPU
-
-#include "SkMatrix.h"
-#include "SkString.h"
-#include "GrTRecorder.h"
-#include "Test.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-static int activeRecorderItems = 0;
-
-class IntWrapper {
-public:
- IntWrapper() {}
- IntWrapper(int value) : fValue(value) {}
- operator int() { return fValue; }
-private:
- int fValue;
-};
-
-static void test_empty_back(skiatest::Reporter* reporter) {
- GrTRecorder<IntWrapper, int> recorder(0);
-
- REPORTER_ASSERT(reporter, recorder.empty());
-
- for (int i = 0; i < 100; ++i) {
- REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder, IntWrapper, (i)));
- REPORTER_ASSERT(reporter, !recorder.empty());
- REPORTER_ASSERT(reporter, i == recorder.back());
- }
-
- REPORTER_ASSERT(reporter, !recorder.empty());
-
- recorder.reset();
-
- REPORTER_ASSERT(reporter, recorder.empty());
-}
-
-struct ExtraData {
- typedef GrTRecorder<ExtraData, int> Recorder;
-
- ExtraData(int i) : fData(i) {
- int* extraData = this->extraData();
- for (int j = 0; j < i; j++) {
- extraData[j] = i;
- }
- ++activeRecorderItems;
- }
- ~ExtraData() {
- --activeRecorderItems;
- }
- int* extraData() {
- return reinterpret_cast<int*>(Recorder::GetDataForItem(this));
- }
- int fData;
-};
-
-static void test_extra_data(skiatest::Reporter* reporter) {
- ExtraData::Recorder recorder(0);
- for (int i = 0; i < 100; ++i) {
- GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int));
- }
- REPORTER_ASSERT(reporter, 100 == activeRecorderItems);
-
- ExtraData::Recorder::Iter iter(recorder);
- for (int i = 0; i < 100; ++i) {
- REPORTER_ASSERT(reporter, iter.next());
- REPORTER_ASSERT(reporter, i == iter->fData);
- for (int j = 0; j < i; j++) {
- REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
- }
- }
- REPORTER_ASSERT(reporter, !iter.next());
-
- recorder.reset();
- REPORTER_ASSERT(reporter, 0 == activeRecorderItems);
-}
-
-enum ClassType {
- kBase_ClassType,
- kSubclass_ClassType,
- kSubSubclass_ClassType,
- kSubclassExtraData_ClassType,
- kSubclassEmpty_ClassType,
-
- kNumClassTypes
-};
-
-class Base {
-public:
- typedef GrTRecorder<Base, void*> Recorder;
-
- Base() {
- fMatrix.reset();
- ++activeRecorderItems;
- }
-
- virtual ~Base() { --activeRecorderItems; }
-
- virtual ClassType getType() { return kBase_ClassType; }
-
- virtual void validate(skiatest::Reporter* reporter) const {
- REPORTER_ASSERT(reporter, fMatrix.isIdentity());
- }
-
-private:
- SkMatrix fMatrix;
-};
-
-class Subclass : public Base {
-public:
- Subclass() : fString("Lorem ipsum dolor sit amet") {}
-
- virtual ClassType getType() { return kSubclass_ClassType; }
-
- virtual void validate(skiatest::Reporter* reporter) const {
- Base::validate(reporter);
- REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str()));
- }
-
-private:
- SkString fString;
-};
-
-class SubSubclass : public Subclass {
-public:
- SubSubclass() : fInt(1234), fFloat(1.234f) {}
-
- virtual ClassType getType() { return kSubSubclass_ClassType; }
-
- virtual void validate(skiatest::Reporter* reporter) const {
- Subclass::validate(reporter);
- REPORTER_ASSERT(reporter, 1234 == fInt);
- REPORTER_ASSERT(reporter, 1.234f == fFloat);
- }
-
-private:
- int fInt;
- float fFloat;
-};
-
-class SubclassExtraData : public Base {
-public:
- SubclassExtraData(int length) : fLength(length) {
- int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this));
- for (int i = 0; i < fLength; ++i) {
- data[i] = 123456789 + 987654321 * i;
- }
- }
-
- virtual ClassType getType() { return kSubclassExtraData_ClassType; }
-
- virtual void validate(skiatest::Reporter* reporter) const {
- Base::validate(reporter);
- const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this));
- for (int i = 0; i < fLength; ++i) {
- REPORTER_ASSERT(reporter, 123456789 + 987654321 * i == data[i]);
- }
- }
-
-private:
- int fLength;
-};
-
-class SubclassEmpty : public Base {
-public:
- virtual ClassType getType() { return kSubclassEmpty_ClassType; }
-};
-
-static void test_subclasses(skiatest::Reporter* reporter) {
- class Order {
- public:
- Order() { this->reset(); }
- void reset() { fCurrent = 0; }
- ClassType next() {
- fCurrent = 1664525 * fCurrent + 1013904223;
- return static_cast<ClassType>(fCurrent % kNumClassTypes);
- }
- private:
- uint32_t fCurrent;
- };
-
- Base::Recorder recorder(1024);
-
- Order order;
- for (int i = 0; i < 1000; i++) {
- switch (order.next()) {
- case kBase_ClassType:
- GrNEW_APPEND_TO_RECORDER(recorder, Base, ());
- break;
-
- case kSubclass_ClassType:
- GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ());
- break;
-
- case kSubSubclass_ClassType:
- GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ());
- break;
-
- case kSubclassExtraData_ClassType:
- GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i);
- break;
-
- case kSubclassEmpty_ClassType:
- GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ());
- break;
-
- default:
- reporter->reportFailed(SkString("Invalid class type"));
- break;
- }
- }
- REPORTER_ASSERT(reporter, 1000 == activeRecorderItems);
-
- order.reset();
- Base::Recorder::Iter iter(recorder);
- for (int i = 0; i < 1000; ++i) {
- REPORTER_ASSERT(reporter, iter.next());
- REPORTER_ASSERT(reporter, order.next() == iter->getType());
- iter->validate(reporter);
- }
- REPORTER_ASSERT(reporter, !iter.next());
-
- // Don't reset the recorder. It should automatically destruct all its items.
-}
-
-DEF_GPUTEST(GrTRecorder, reporter, factory) {
- test_empty_back(reporter);
-
- test_extra_data(reporter);
- REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset().
-
- test_subclasses(reporter);
- REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors.
-}
-
-#endif