| Index: src/gpu/GrInOrderDrawBuffer.cpp
|
| diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
|
| index 1789c49aca35dcedebcfe6770296862c48ee1630..38994f1d35eec84b4a784227fba6614c56cda2af 100644
|
| --- a/src/gpu/GrInOrderDrawBuffer.cpp
|
| +++ b/src/gpu/GrInOrderDrawBuffer.cpp
|
| @@ -33,6 +33,9 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrGpu* gpu,
|
| SkASSERT(vertexPool);
|
| SkASSERT(indexPool);
|
|
|
| + fPathIndexBuffer.setReserve(kPathIdxBufferMinReserve);
|
| + fPathTransformBuffer.setReserve(kPathXformBufferMinReserve);
|
| +
|
| GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
|
| poolState.fUsedPoolVertexBytes = 0;
|
| poolState.fUsedPoolIndexBytes = 0;
|
| @@ -102,6 +105,32 @@ 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;
|
| +}
|
| +
|
| +template<typename T> static void reset_data_buffer(SkTDArray<T>* buffer, int minReserve) {
|
| + // 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 * buffer->count() < buffer->reserved() && buffer->reserved() > minReserve) {
|
| + int reserve = SkTMax(minReserve, buffer->count() * 3 / 2);
|
| + buffer->reset();
|
| + buffer->setReserve(reserve);
|
| + } else {
|
| + buffer->rewind();
|
| + }
|
| +}
|
| +
|
| enum {
|
| kTraceCmdBit = 0x80,
|
| kCmdMask = 0x7f,
|
| @@ -335,15 +364,35 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathRange* pathRange,
|
|
|
| this->recordStateIfNecessary(GrGpu::kDrawPaths_DrawType, dstCopy);
|
|
|
| - int sizeOfIndices = sizeof(uint32_t) * count;
|
| - int sizeOfTransforms = sizeof(float) * count *
|
| - GrPathRendering::PathTransformSize(transformsType);
|
| + uint32_t* savedIndices = fPathIndexBuffer.append(count, indices);
|
| + float* savedTransforms = fPathTransformBuffer.append(count *
|
| + GrPathRendering::PathTransformSize(transformsType), transforms);
|
| +
|
| + if (kDrawPaths_Cmd == strip_trace_bit(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) &&
|
| + !this->getDrawState().willBlendWithDst()) {
|
| + // Fold this DrawPaths call into the one previous.
|
| + 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 = savedIndices - fPathIndexBuffer.begin();
|
| dp->fCount = count;
|
| - memcpy(dp->transforms(), transforms, sizeOfTransforms);
|
| + dp->fTransformsLocation = savedTransforms - fPathTransformBuffer.begin();
|
| dp->fTransformsType = transformsType;
|
| dp->fScissorState = scissorState;
|
| dp->fStencilSettings = stencilSettings;
|
| @@ -408,6 +457,8 @@ void GrInOrderDrawBuffer::reset() {
|
| fLastState = NULL;
|
| fVertexPool.reset();
|
| fIndexPool.reset();
|
| + reset_data_buffer(&fPathIndexBuffer, kPathIdxBufferMinReserve);
|
| + reset_data_buffer(&fPathTransformBuffer, kPathXformBufferMinReserve);
|
| fGpuCmdMarkers.reset();
|
| }
|
|
|
| @@ -457,7 +508,7 @@ void GrInOrderDrawBuffer::flush() {
|
| &ss->fDstCopy,
|
| ss->fDrawType));
|
| } else {
|
| - iter->execute(fDstGpu, currentOptState.get());
|
| + iter->execute(this, currentOptState.get());
|
| }
|
|
|
| if (cmd_has_trace_marker(iter->fType)) {
|
| @@ -472,58 +523,64 @@ void GrInOrderDrawBuffer::flush() {
|
| ++fDrawID;
|
| }
|
|
|
| -void GrInOrderDrawBuffer::Draw::execute(GrGpu* gpu, const GrOptDrawState* optState) {
|
| +void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState* optState) {
|
| if (!optState) {
|
| return;
|
| }
|
| - gpu->setVertexSourceToBuffer(this->vertexBuffer(), optState->getVertexStride());
|
| + GrGpu* dstGpu = buf->fDstGpu;
|
| + dstGpu->setVertexSourceToBuffer(this->vertexBuffer(), optState->getVertexStride());
|
| if (fInfo.isIndexed()) {
|
| - gpu->setIndexSourceToBuffer(this->indexBuffer());
|
| + dstGpu->setIndexSourceToBuffer(this->indexBuffer());
|
| }
|
| - gpu->draw(*optState, fInfo, fScissorState);
|
| + dstGpu->draw(*optState, fInfo, fScissorState);
|
| }
|
|
|
| -void GrInOrderDrawBuffer::StencilPath::execute(GrGpu* gpu, const GrOptDrawState* optState) {
|
| +void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf,
|
| + const GrOptDrawState* optState) {
|
| if (!optState) {
|
| return;
|
| }
|
| - gpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
|
| + buf->fDstGpu->stencilPath(*optState, this->path(), fScissorState, fStencilSettings);
|
| }
|
|
|
| -void GrInOrderDrawBuffer::DrawPath::execute(GrGpu* gpu, const GrOptDrawState* optState) {
|
| +void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf,
|
| + const GrOptDrawState* optState) {
|
| if (!optState) {
|
| return;
|
| }
|
| - gpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
|
| - fDstCopy.texture() ? &fDstCopy : NULL);
|
| + buf->fDstGpu->drawPath(*optState, this->path(), fScissorState, fStencilSettings,
|
| + fDstCopy.texture() ? &fDstCopy : NULL);
|
| }
|
|
|
| -void GrInOrderDrawBuffer::DrawPaths::execute(GrGpu* gpu, const GrOptDrawState* optState) {
|
| +void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf,
|
| + const GrOptDrawState* optState) {
|
| if (!optState) {
|
| return;
|
| }
|
| - gpu->drawPaths(*optState, this->pathRange(), this->indices(), fCount, this->transforms(),
|
| - fTransformsType, fScissorState, fStencilSettings,
|
| - fDstCopy.texture() ? &fDstCopy : NULL);
|
| + buf->fDstGpu->drawPaths(*optState, this->pathRange(),
|
| + &buf->fPathIndexBuffer[fIndicesLocation], fCount,
|
| + &buf->fPathTransformBuffer[fTransformsLocation], fTransformsType,
|
| + fScissorState, fStencilSettings, fDstCopy.texture() ? &fDstCopy : NULL);
|
| }
|
|
|
| -void GrInOrderDrawBuffer::SetState::execute(GrGpu* gpu, const GrOptDrawState*) {
|
| +void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const GrOptDrawState*) {
|
| }
|
|
|
| -void GrInOrderDrawBuffer::Clear::execute(GrGpu* gpu, const GrOptDrawState*) {
|
| +void GrInOrderDrawBuffer::Clear::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
|
| if (GrColor_ILLEGAL == fColor) {
|
| - gpu->discard(this->renderTarget());
|
| + buf->fDstGpu->discard(this->renderTarget());
|
| } else {
|
| - gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
|
| + buf->fDstGpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
|
| }
|
| }
|
|
|
| -void GrInOrderDrawBuffer::ClearStencilClip::execute(GrGpu* gpu, const GrOptDrawState*) {
|
| - gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
|
| +void GrInOrderDrawBuffer::ClearStencilClip::execute(GrInOrderDrawBuffer* buf,
|
| + const GrOptDrawState*) {
|
| + buf->fDstGpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
|
| }
|
|
|
| -void GrInOrderDrawBuffer::CopySurface::execute(GrGpu* gpu, const GrOptDrawState*){
|
| - gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
|
| +void GrInOrderDrawBuffer::CopySurface::execute(GrInOrderDrawBuffer* buf, const GrOptDrawState*) {
|
| + buf->fDstGpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
|
| }
|
|
|
| bool GrInOrderDrawBuffer::copySurface(GrSurface* dst,
|
|
|