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)) { |