| Index: src/gpu/GrTargetCommands.cpp
|
| diff --git a/src/gpu/GrTargetCommands.cpp b/src/gpu/GrTargetCommands.cpp
|
| index d68a24292e54e9150382e8e30a561f29096b5fa5..a6d31481413b0d29005013b1a975ad3f13a69459 100644
|
| --- a/src/gpu/GrTargetCommands.cpp
|
| +++ b/src/gpu/GrTargetCommands.cpp
|
| @@ -26,19 +26,27 @@
|
| return isWinding;
|
| }
|
|
|
| -GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch(State* state, GrBatch* batch) {
|
| +GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch(
|
| + GrInOrderDrawBuffer* iodb,
|
| + GrBatch* batch,
|
| + const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
| + if (!this->setupPipelineAndShouldDraw(iodb, batch, pipelineInfo)) {
|
| + return NULL;
|
| + }
|
| +
|
| // Check if there is a Batch Draw we can batch with
|
| - if (!fCmdBuffer.empty() && Cmd::kDrawBatch_CmdType == fCmdBuffer.back().type()) {
|
| + if (Cmd::kDrawBatch_CmdType == fCmdBuffer.back().type()) {
|
| DrawBatch* previous = static_cast<DrawBatch*>(&fCmdBuffer.back());
|
| - if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
|
| + if (previous->fBatch->combineIfPossible(batch)) {
|
| return NULL;
|
| }
|
| }
|
|
|
| - return GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (state, batch, &fBatchTarget));
|
| + return GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (batch, &fBatchTarget));
|
| }
|
|
|
| GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath(
|
| + GrInOrderDrawBuffer* iodb,
|
| const GrPipelineBuilder& pipelineBuilder,
|
| const GrPathProcessor* pathProc,
|
| const GrPath* path,
|
| @@ -55,17 +63,21 @@
|
| }
|
|
|
| GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath(
|
| - State* state,
|
| + GrInOrderDrawBuffer* iodb,
|
| const GrPathProcessor* pathProc,
|
| const GrPath* path,
|
| - const GrStencilSettings& stencilSettings) {
|
| - DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (state, path));
|
| + const GrStencilSettings& stencilSettings,
|
| + const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
| + // TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
|
| + if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) {
|
| + return NULL;
|
| + }
|
| + DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
|
| dp->fStencilSettings = stencilSettings;
|
| return dp;
|
| }
|
|
|
| GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
|
| - State* state,
|
| GrInOrderDrawBuffer* iodb,
|
| const GrPathProcessor* pathProc,
|
| const GrPathRange* pathRange,
|
| @@ -80,6 +92,10 @@
|
| SkASSERT(indexValues);
|
| SkASSERT(transformValues);
|
|
|
| + if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) {
|
| + return NULL;
|
| + }
|
| +
|
| char* savedIndices;
|
| float* savedTransforms;
|
|
|
| @@ -87,7 +103,7 @@
|
| transformValues, transformType,
|
| count, &savedIndices, &savedTransforms);
|
|
|
| - if (!fCmdBuffer.empty() && Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
|
| + if (Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
|
| // The previous command was also DrawPaths. Try to collapse this call into the one
|
| // before. Note that stenciling all the paths at once, then covering, may not be
|
| // equivalent to two separate draw calls if there is overlap. Blending won't work,
|
| @@ -101,8 +117,7 @@
|
| transformType == previous->fTransformType &&
|
| stencilSettings == previous->fStencilSettings &&
|
| path_fill_type_is_winding(stencilSettings) &&
|
| - !pipelineInfo.willBlendWithDst(pathProc) &&
|
| - previous->fState == state) {
|
| + !pipelineInfo.willBlendWithDst(pathProc)) {
|
| const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
|
| const int xformSize = GrPathRendering::PathTransformSize(transformType);
|
| if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
|
| @@ -115,7 +130,7 @@
|
| }
|
| }
|
|
|
| - DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (state, pathRange));
|
| + DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (pathRange));
|
| dp->fIndices = savedIndices;
|
| dp->fIndexType = indexType;
|
| dp->fTransforms = savedTransforms;
|
| @@ -125,7 +140,8 @@
|
| return dp;
|
| }
|
|
|
| -GrTargetCommands::Cmd* GrTargetCommands::recordClear(const SkIRect* rect,
|
| +GrTargetCommands::Cmd* GrTargetCommands::recordClear(GrInOrderDrawBuffer* iodb,
|
| + const SkIRect* rect,
|
| GrColor color,
|
| bool canIgnoreRect,
|
| GrRenderTarget* renderTarget) {
|
| @@ -147,7 +163,8 @@
|
| return clr;
|
| }
|
|
|
| -GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(const SkIRect& rect,
|
| +GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(GrInOrderDrawBuffer* iodb,
|
| + const SkIRect& rect,
|
| bool insideClip,
|
| GrRenderTarget* renderTarget) {
|
| SkASSERT(renderTarget);
|
| @@ -158,7 +175,8 @@
|
| return clr;
|
| }
|
|
|
| -GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrRenderTarget* renderTarget) {
|
| +GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrInOrderDrawBuffer* iodb,
|
| + GrRenderTarget* renderTarget) {
|
| SkASSERT(renderTarget);
|
|
|
| Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
|
| @@ -168,12 +186,17 @@
|
|
|
| void GrTargetCommands::reset() {
|
| fCmdBuffer.reset();
|
| + fPrevState = NULL;
|
| }
|
|
|
| void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
|
| if (fCmdBuffer.empty()) {
|
| return;
|
| }
|
| +
|
| + // Updated every time we find a set state cmd to reflect the current state in the playback
|
| + // stream.
|
| + SetState* currentState = NULL;
|
|
|
| GrGpu* gpu = iodb->getGpu();
|
|
|
| @@ -183,8 +206,13 @@
|
| if (Cmd::kDrawBatch_CmdType == genIter->type()) {
|
| DrawBatch* db = reinterpret_cast<DrawBatch*>(genIter.get());
|
| fBatchTarget.resetNumberOfDraws();
|
| - db->fBatch->generateGeometry(&fBatchTarget, db->fState->getPipeline());
|
| + db->execute(NULL, currentState);
|
| db->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws());
|
| + } else if (Cmd::kSetState_CmdType == genIter->type()) {
|
| + SetState* ss = reinterpret_cast<SetState*>(genIter.get());
|
| +
|
| + ss->execute(gpu, currentState);
|
| + currentState = ss;
|
| }
|
| }
|
|
|
| @@ -203,7 +231,29 @@
|
| gpu->addGpuTraceMarker(&newMarker);
|
| }
|
|
|
| - iter->execute(gpu);
|
| + if (Cmd::kDrawBatch_CmdType == iter->type()) {
|
| + DrawBatch* db = reinterpret_cast<DrawBatch*>(iter.get());
|
| + fBatchTarget.flushNext(db->fBatch->numberOfDraws());
|
| +
|
| + if (iter->isTraced()) {
|
| + gpu->removeGpuTraceMarker(&newMarker);
|
| + }
|
| + continue;
|
| + }
|
| +
|
| + if (Cmd::kSetState_CmdType == iter->type()) {
|
| + // TODO this is just until NVPR is in batch
|
| + SetState* ss = reinterpret_cast<SetState*>(iter.get());
|
| +
|
| + if (ss->fPrimitiveProcessor) {
|
| + ss->execute(gpu, currentState);
|
| + }
|
| + currentState = ss;
|
| +
|
| + } else {
|
| + iter->execute(gpu, currentState);
|
| + }
|
| +
|
| if (iter->isTraced()) {
|
| gpu->removeGpuTraceMarker(&newMarker);
|
| }
|
| @@ -212,7 +262,7 @@
|
| fBatchTarget.postFlush();
|
| }
|
|
|
| -void GrTargetCommands::StencilPath::execute(GrGpu* gpu) {
|
| +void GrTargetCommands::StencilPath::execute(GrGpu* gpu, const SetState*) {
|
| GrGpu::StencilPathState state;
|
| state.fRenderTarget = fRenderTarget.get();
|
| state.fScissor = &fScissor;
|
| @@ -223,36 +273,37 @@
|
| gpu->stencilPath(this->path(), state);
|
| }
|
|
|
| -void GrTargetCommands::DrawPath::execute(GrGpu* gpu) {
|
| - if (!fState->fCompiled) {
|
| - gpu->buildProgramDesc(&fState->fDesc, *fState->fPrimitiveProcessor, *fState->getPipeline(),
|
| - fState->fBatchTracker);
|
| - fState->fCompiled = true;
|
| - }
|
| - DrawArgs args(fState->fPrimitiveProcessor.get(), fState->getPipeline(),
|
| - &fState->fDesc, &fState->fBatchTracker);
|
| +void GrTargetCommands::DrawPath::execute(GrGpu* gpu, const SetState* state) {
|
| + SkASSERT(state);
|
| + DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state->fDesc,
|
| + &state->fBatchTracker);
|
| gpu->drawPath(args, this->path(), fStencilSettings);
|
| }
|
|
|
| -void GrTargetCommands::DrawPaths::execute(GrGpu* gpu) {
|
| - if (!fState->fCompiled) {
|
| - gpu->buildProgramDesc(&fState->fDesc, *fState->fPrimitiveProcessor, *fState->getPipeline(),
|
| - fState->fBatchTracker);
|
| - fState->fCompiled = true;
|
| - }
|
| - DrawArgs args(fState->fPrimitiveProcessor.get(), fState->getPipeline(),
|
| - &fState->fDesc, &fState->fBatchTracker);
|
| +void GrTargetCommands::DrawPaths::execute(GrGpu* gpu, const SetState* state) {
|
| + SkASSERT(state);
|
| + DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state->fDesc,
|
| + &state->fBatchTracker);
|
| gpu->drawPaths(args, this->pathRange(),
|
| fIndices, fIndexType,
|
| fTransforms, fTransformType,
|
| fCount, fStencilSettings);
|
| }
|
|
|
| -void GrTargetCommands::DrawBatch::execute(GrGpu*) {
|
| - fBatchTarget->flushNext(fBatch->numberOfDraws());
|
| -}
|
| -
|
| -void GrTargetCommands::Clear::execute(GrGpu* gpu) {
|
| +void GrTargetCommands::DrawBatch::execute(GrGpu*, const SetState* state) {
|
| + SkASSERT(state);
|
| + fBatch->generateGeometry(fBatchTarget, state->getPipeline());
|
| +}
|
| +
|
| +void GrTargetCommands::SetState::execute(GrGpu* gpu, const SetState*) {
|
| + // TODO sometimes we have a prim proc, othertimes we have a GrBatch. Eventually we
|
| + // will only have GrBatch and we can delete this
|
| + if (fPrimitiveProcessor) {
|
| + gpu->buildProgramDesc(&fDesc, *fPrimitiveProcessor, *getPipeline(), fBatchTracker);
|
| + }
|
| +}
|
| +
|
| +void GrTargetCommands::Clear::execute(GrGpu* gpu, const SetState*) {
|
| if (GrColor_ILLEGAL == fColor) {
|
| gpu->discard(this->renderTarget());
|
| } else {
|
| @@ -260,15 +311,15 @@
|
| }
|
| }
|
|
|
| -void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu) {
|
| +void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu, const SetState*) {
|
| gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
|
| }
|
|
|
| -void GrTargetCommands::CopySurface::execute(GrGpu* gpu) {
|
| +void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) {
|
| gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
|
| }
|
|
|
| -void GrTargetCommands::XferBarrier::execute(GrGpu* gpu) {
|
| +void GrTargetCommands::XferBarrier::execute(GrGpu* gpu, const SetState* state) {
|
| gpu->xferBarrier(fBarrierType);
|
| }
|
|
|
| @@ -282,10 +333,65 @@
|
| return cs;
|
| }
|
|
|
| -void GrTargetCommands::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
|
| - GrInOrderDrawBuffer* iodb) {
|
| - const GrXferProcessor& xp = *pipeline.getXferProcessor();
|
| - GrRenderTarget* rt = pipeline.getRenderTarget();
|
| +bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb,
|
| + const GrPrimitiveProcessor* primProc,
|
| + const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
| + SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (primProc));
|
| + iodb->setupPipeline(pipelineInfo, ss->pipelineLocation());
|
| +
|
| + if (ss->getPipeline()->mustSkip()) {
|
| + fCmdBuffer.pop_back();
|
| + return false;
|
| + }
|
| +
|
| + ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
|
| + ss->getPipeline()->getInitBatchTracker());
|
| +
|
| + if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
|
| + fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
|
| + *ss->fPrimitiveProcessor,
|
| + ss->fBatchTracker) &&
|
| + fPrevState->getPipeline()->isEqual(*ss->getPipeline())) {
|
| + fCmdBuffer.pop_back();
|
| + } else {
|
| + fPrevState = ss;
|
| + iodb->recordTraceMarkersIfNecessary(ss);
|
| + }
|
| +
|
| + this->recordXferBarrierIfNecessary(iodb, pipelineInfo);
|
| + return true;
|
| +}
|
| +
|
| +bool GrTargetCommands::setupPipelineAndShouldDraw(GrInOrderDrawBuffer* iodb,
|
| + GrBatch* batch,
|
| + const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
| + SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, ());
|
| + iodb->setupPipeline(pipelineInfo, ss->pipelineLocation());
|
| +
|
| + if (ss->getPipeline()->mustSkip()) {
|
| + fCmdBuffer.pop_back();
|
| + return false;
|
| + }
|
| +
|
| + batch->initBatchTracker(ss->getPipeline()->getInitBatchTracker());
|
| +
|
| + if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
|
| + fPrevState->getPipeline()->isEqual(*ss->getPipeline())) {
|
| + fCmdBuffer.pop_back();
|
| + } else {
|
| + fPrevState = ss;
|
| + iodb->recordTraceMarkersIfNecessary(ss);
|
| + }
|
| +
|
| + this->recordXferBarrierIfNecessary(iodb, pipelineInfo);
|
| + return true;
|
| +}
|
| +
|
| +void GrTargetCommands::recordXferBarrierIfNecessary(GrInOrderDrawBuffer* iodb,
|
| + const GrDrawTarget::PipelineInfo& info) {
|
| + SkASSERT(fPrevState);
|
| + const GrXferProcessor& xp = *fPrevState->getXferProcessor();
|
| + GrRenderTarget* rt = fPrevState->getRenderTarget();
|
|
|
| GrXferBarrierType barrierType;
|
| if (!xp.willNeedXferBarrier(rt, *iodb->caps(), &barrierType)) {
|
|
|