aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTargetCommands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrTargetCommands.cpp')
-rw-r--r--src/gpu/GrTargetCommands.cpp194
1 files changed, 150 insertions, 44 deletions
diff --git a/src/gpu/GrTargetCommands.cpp b/src/gpu/GrTargetCommands.cpp
index d68a24292e..a6d3148141 100644
--- a/src/gpu/GrTargetCommands.cpp
+++ b/src/gpu/GrTargetCommands.cpp
@@ -26,19 +26,27 @@ static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettin
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::recordStencilPath(
}
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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
SkASSERT(indexValues);
SkASSERT(transformValues);
+ if (!this->setupPipelineAndShouldDraw(iodb, pathProc, pipelineInfo)) {
+ return NULL;
+ }
+
char* savedIndices;
float* savedTransforms;
@@ -87,7 +103,7 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
}
}
- 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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordClear(const SkIRect* rect,
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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(const SkIRect& r
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,6 +186,7 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrRenderTarget* renderTar
void GrTargetCommands::reset() {
fCmdBuffer.reset();
+ fPrevState = NULL;
}
void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
@@ -175,6 +194,10 @@ void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
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();
// Loop over all batches and generate geometry
@@ -183,8 +206,13 @@ void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
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 @@ void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
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 @@ void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
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 @@ void GrTargetCommands::StencilPath::execute(GrGpu* gpu) {
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::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) {
+void GrTargetCommands::Clear::execute(GrGpu* gpu, const SetState*) {
if (GrColor_ILLEGAL == fColor) {
gpu->discard(this->renderTarget());
} else {
@@ -260,15 +311,15 @@ void GrTargetCommands::Clear::execute(GrGpu* gpu) {
}
}
-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 @@ GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrSurface* dst,
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)) {