Index: src/gpu/GrInOrderDrawBuffer.cpp |
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp |
index e298be6c8bffb575798ae14250512495626e0fe5..fbe48a9b52ee33caa70186fec93df8cbb14e8c7e 100644 |
--- a/src/gpu/GrInOrderDrawBuffer.cpp |
+++ b/src/gpu/GrInOrderDrawBuffer.cpp |
@@ -17,6 +17,7 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context, |
, fCommands(context->getGpu(), vertexPool, indexPool) |
, fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) |
, fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) |
+ , fPipelineBuffer(kPipelineBufferMinReserve) |
, fDrawID(0) { |
SkASSERT(vertexPool); |
@@ -300,7 +301,12 @@ void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder, |
void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, |
const PipelineInfo& pipelineInfo) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(this, batch, pipelineInfo); |
+ State* state = this->setupPipelineAndShouldDraw(batch, pipelineInfo); |
+ if (!state) { |
+ return; |
+ } |
+ |
+ GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(state, batch); |
this->recordTraceMarkersIfNecessary(cmd); |
} |
@@ -309,7 +315,7 @@ void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder |
const GrPath* path, |
const GrScissorState& scissorState, |
const GrStencilSettings& stencilSettings) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(this, pipelineBuilder, |
+ GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(pipelineBuilder, |
pathProc, path, scissorState, |
stencilSettings); |
this->recordTraceMarkersIfNecessary(cmd); |
@@ -319,9 +325,11 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, |
const GrPath* path, |
const GrStencilSettings& stencilSettings, |
const PipelineInfo& pipelineInfo) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(this, pathProc, |
- path, stencilSettings, |
- pipelineInfo); |
+ State* state = this->setupPipelineAndShouldDraw(pathProc, pipelineInfo); |
+ if (!state) { |
+ return; |
+ } |
+ GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(state, pathProc, path, stencilSettings); |
this->recordTraceMarkersIfNecessary(cmd); |
} |
@@ -334,7 +342,11 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, |
int count, |
const GrStencilSettings& stencilSettings, |
const PipelineInfo& pipelineInfo) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(this, pathProc, pathRange, |
+ State* state = this->setupPipelineAndShouldDraw(pathProc, pipelineInfo); |
+ if (!state) { |
+ return; |
+ } |
+ GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(state, this, pathProc, pathRange, |
indices, indexType, transformValues, |
transformType, count, |
stencilSettings, pipelineInfo); |
@@ -343,16 +355,14 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc, |
void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, |
bool canIgnoreRect, GrRenderTarget* renderTarget) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordClear(this, rect, color, |
- canIgnoreRect, renderTarget); |
+ GrTargetCommands::Cmd* cmd = fCommands.recordClear(rect, color, canIgnoreRect, renderTarget); |
this->recordTraceMarkersIfNecessary(cmd); |
} |
void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect, |
bool insideClip, |
GrRenderTarget* renderTarget) { |
- GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(this, rect, |
- insideClip, renderTarget); |
+ GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(rect, insideClip, renderTarget); |
this->recordTraceMarkersIfNecessary(cmd); |
} |
@@ -361,7 +371,7 @@ void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { |
return; |
} |
- GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(this, renderTarget); |
+ GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(renderTarget); |
this->recordTraceMarkersIfNecessary(cmd); |
} |
@@ -370,6 +380,15 @@ void GrInOrderDrawBuffer::onReset() { |
fPathIndexBuffer.rewind(); |
fPathTransformBuffer.rewind(); |
fGpuCmdMarkers.reset(); |
+ |
+ fPrevState.reset(NULL); |
+ // Note, fPrevState points into fPipelineBuffer's allocation, so we have to reset first. |
+ // Furthermore, we have to reset fCommands before fPipelineBuffer too. |
+ if (fDrawID % kPipelineBufferHighWaterMark) { |
+ fPipelineBuffer.rewind(); |
+ } else { |
+ fPipelineBuffer.reset(); |
+ } |
} |
void GrInOrderDrawBuffer::onFlush() { |
@@ -400,3 +419,55 @@ void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* c |
} |
} |
} |
+ |
+GrTargetCommands::State* |
+GrInOrderDrawBuffer::setupPipelineAndShouldDraw(const GrPrimitiveProcessor* primProc, |
+ const GrDrawTarget::PipelineInfo& pipelineInfo) { |
+ State* state = this->allocState(primProc); |
+ this->setupPipeline(pipelineInfo, state->pipelineLocation()); |
+ |
+ if (state->getPipeline()->mustSkip()) { |
+ this->unallocState(state); |
+ return NULL; |
+ } |
+ |
+ state->fPrimitiveProcessor->initBatchTracker(&state->fBatchTracker, |
+ state->getPipeline()->getInitBatchTracker()); |
+ |
+ if (fPrevState && fPrevState->fPrimitiveProcessor.get() && |
+ fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker, |
+ *state->fPrimitiveProcessor, |
+ state->fBatchTracker) && |
+ fPrevState->getPipeline()->isEqual(*state->getPipeline())) { |
+ this->unallocState(state); |
+ } else { |
+ fPrevState.reset(state); |
+ } |
+ |
+ fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this); |
+ return fPrevState; |
+} |
+ |
+GrTargetCommands::State* |
+GrInOrderDrawBuffer::setupPipelineAndShouldDraw(GrBatch* batch, |
+ const GrDrawTarget::PipelineInfo& pipelineInfo) { |
+ State* state = this->allocState(); |
+ this->setupPipeline(pipelineInfo, state->pipelineLocation()); |
+ |
+ if (state->getPipeline()->mustSkip()) { |
+ this->unallocState(state); |
+ return NULL; |
+ } |
+ |
+ batch->initBatchTracker(state->getPipeline()->getInitBatchTracker()); |
+ |
+ if (fPrevState && !fPrevState->fPrimitiveProcessor.get() && |
+ fPrevState->getPipeline()->isEqual(*state->getPipeline())) { |
+ this->unallocState(state); |
+ } else { |
+ fPrevState.reset(state); |
+ } |
+ |
+ fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this); |
+ return fPrevState; |
+} |