Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Unified Diff: src/gpu/GrInOrderDrawBuffer.cpp

Issue 712223002: Combine similar DrawPaths calls in GrInOrderDrawBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/gpu/GrInOrderDrawBuffer.h ('K') | « src/gpu/GrInOrderDrawBuffer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrInOrderDrawBuffer.cpp
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 9835200598d76ddadb1cd94661b8d299b24c961b..a85d1a0f60096c0dc2d229a1301de2840f9a6f04 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -23,6 +23,8 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
, fDstGpu(gpu)
, fVertexPool(*vertexPool)
, fIndexPool(*indexPool)
+ , fPathIndexBuffer(kPathIdxBufferMinAllocCnt)
+ , fPathTransformBuffer(kPathXformBufferMinAllocCnt)
, fFlushing(false)
, fDrawID(0) {
@@ -101,6 +103,25 @@ static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, G
}
}
+static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
+ static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
+ bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
+ if (isWinding) {
+ // Double check that it is in fact winding.
+ SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
+ SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
+ SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
+ SkASSERT(!pathStencilSettings.isTwoSided());
+ }
+ return isWinding;
+}
+
+static bool draw_state_is_opaque(const GrDrawState& drawState) {
egdaniel 2014/11/11 18:39:07 I don't believe this function fully captures what
Chris Dalton 2014/11/11 19:29:15 Ok, so while we wait for isUnblended can I capture
+ GrBlendCoeff dstBlendCoeff = drawState.getDstBlendCoeff();
+ return (kZero_GrBlendCoeff == dstBlendCoeff ||
+ (kISA_GrBlendCoeff == dstBlendCoeff && drawState.srcAlphaWillBeOne()));
+}
+
enum {
kTraceCmdBit = 0x80,
kCmdMask = 0x7f,
@@ -333,15 +354,36 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
this->recordStateIfNecessary();
- int sizeOfIndices = sizeof(uint32_t) * count;
- int sizeOfTransforms = sizeof(float) * count *
- GrPathRendering::PathTransformSize(transformsType);
+ int indicesLocation = fPathIndexBuffer.append(indices, count);
+ int transformsLocation = fPathTransformBuffer.append(transforms,
+ GrPathRendering::PathTransformSize(transformsType) * count);
+
+ if (kDrawPaths_Cmd == fCmdBuffer.back().fType) {
+ // The previous command was also DrawPaths. Try to collapse this call into the one
+ // before. Note that stencilling all the paths at once, then covering, may not be
+ // equivalent to two separate draw calls if there is overlap. Blending won't work,
+ // and the combined calls may also cancel each other's winding numbers in some
+ // places. For now the winding numbers are only an issue if the fill is even/odd,
+ // because DrawPaths is currently only used for glyphs, and glyphs in the same
+ // font tend to all wind in the same direction.
+ DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
+ if (pathRange == previous->pathRange() &&
+ transformsType == previous->fTransformsType &&
+ scissorState == previous->fScissorState &&
+ stencilSettings == previous->fStencilSettings &&
+ path_fill_type_is_winding(stencilSettings) &&
+ draw_state_is_opaque(this->getDrawState())) {
bsalomon 2014/11/11 14:41:25 Could/should you check that the b.boxes don't over
Chris Dalton 2014/11/11 17:49:07 In theory, yes. But right now there isn't a way of
+ // Fold this DrawPaths call into the one previous.
+ SkASSERT(!dstCopy || !dstCopy->texture());
+ previous->fCount += count;
+ return;
+ }
+ }
- DrawPaths* dp = GrNEW_APPEND_WITH_DATA_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange),
- sizeOfIndices + sizeOfTransforms);
- memcpy(dp->indices(), indices, sizeOfIndices);
+ DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
+ dp->fIndicesLocation = indicesLocation;
dp->fCount = count;
- memcpy(dp->transforms(), transforms, sizeOfTransforms);
+ dp->fTransformsLocation = transformsLocation;
dp->fTransformsType = transformsType;
dp->fScissorState = scissorState;
dp->fStencilSettings = stencilSettings;
@@ -403,6 +445,8 @@ void GrInOrderDrawBuffer::reset() {
this->resetIndexSource();
fCmdBuffer.reset();
+ fPathIndexBuffer.reset();
+ fPathTransformBuffer.reset();
fLastState = NULL;
fVertexPool.reset();
fIndexPool.reset();
@@ -452,7 +496,7 @@ void GrInOrderDrawBuffer::flush() {
kDrawPaths_Cmd == strip_trace_bit(iter->fType));
SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState);
- iter->execute(fDstGpu);
+ iter->execute(this);
if (cmd_has_trace_marker(iter->fType)) {
fDstGpu->removeGpuTraceMarker(&newMarker);
@@ -468,7 +512,8 @@ void GrInOrderDrawBuffer::flush() {
++fDrawID;
}
-void GrInOrderDrawBuffer::Draw::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
gpu->setVertexSourceToBuffer(this->vertexBuffer());
if (fInfo.isIndexed()) {
gpu->setIndexSourceToBuffer(this->indexBuffer());
@@ -476,26 +521,31 @@ void GrInOrderDrawBuffer::Draw::execute(GrGpu* gpu) {
gpu->draw(fInfo, fScissorState);
}
-void GrInOrderDrawBuffer::StencilPath::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
gpu->stencilPath(this->path(), fScissorState, fStencilSettings);
}
-void GrInOrderDrawBuffer::DrawPath::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
gpu->drawPath(this->path(), fScissorState, fStencilSettings,
- fDstCopy.texture() ? &fDstCopy : NULL);
+ fDstCopy.texture() ? &fDstCopy : NULL);
}
-void GrInOrderDrawBuffer::DrawPaths::execute(GrGpu* gpu) {
- gpu->drawPaths(this->pathRange(), this->indices(), fCount, this->transforms(),
- fTransformsType, fScissorState, fStencilSettings,
- fDstCopy.texture() ? &fDstCopy : NULL);
+void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
+ gpu->drawPaths(this->pathRange(), buf->pathIndexBuffer() + fIndicesLocation, fCount,
+ buf->pathTransformBuffer() + fTransformsLocation, fTransformsType,
+ fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
}
-void GrInOrderDrawBuffer::SetState::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
gpu->setDrawState(&fState);
}
-void GrInOrderDrawBuffer::Clear::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
if (GrColor_ILLEGAL == fColor) {
gpu->discard(this->renderTarget());
} else {
@@ -503,11 +553,13 @@ void GrInOrderDrawBuffer::Clear::execute(GrGpu* gpu) {
}
}
-void GrInOrderDrawBuffer::ClearStencilClip::execute(GrGpu* gpu) {
- gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
+void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
+ gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
}
-void GrInOrderDrawBuffer::CopySurface::execute(GrGpu* gpu) {
+void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf) {
+ GrGpu* gpu = buf->dstGpu();
gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
}
@@ -731,3 +783,25 @@ void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary() {
fGpuCmdMarkers.push_back(activeTraceMarkers);
}
}
+
+template<typename T> int GrInOrderDrawBuffer::DataBuffer<T>::append(const T* array, int count) {
+ if (fCount + count > fAllocCnt) {
+ fAllocCnt = SkTMax(2 * fAllocCnt, (fCount + count) * 3 / 2);
+ fBuffer.realloc(fAllocCnt);
+ }
+ int location = fCount;
+ memcpy(fBuffer + location, array, sizeof(T) * count);
+ fCount += count;
+ return location;
+}
+
+template<typename T> void GrInOrderDrawBuffer::DataBuffer<T>::reset() {
+ // Assume the next time this buffer fills up it will use approximately the same amount
+ // of space as last time. Only resize if we're using less than a third of the
+ // allocated space, and leave enough for 50% growth over last time.
+ if (3 * fCount < fAllocCnt && fAllocCnt > fMinAllocCnt) {
+ fAllocCnt = SkTMax(fMinAllocCnt, fCount * 3 / 2);
+ fBuffer.reset(fAllocCnt);
+ }
+ fCount = 0;
+}
« src/gpu/GrInOrderDrawBuffer.h ('K') | « src/gpu/GrInOrderDrawBuffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698