1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrInOrderDrawBuffer.h"
9
GrInOrderDrawBuffer(GrContext * context)10 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context)
11 : INHERITED(context)
12 , fCommands(GrCommandBuilder::Create(context->getGpu(), false))
13 , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4)
14 , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4)
15 , fPipelineBuffer(kPipelineBufferMinReserve)
16 , fDrawID(0) {
17 }
18
~GrInOrderDrawBuffer()19 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
20 this->reset();
21 }
22
onDrawBatch(GrBatch * batch,const PipelineInfo & pipelineInfo)23 void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
24 const PipelineInfo& pipelineInfo) {
25 State* state = this->setupPipelineAndShouldDraw(batch, pipelineInfo);
26 if (!state) {
27 return;
28 }
29
30 GrTargetCommands::Cmd* cmd = fCommands->recordDrawBatch(state, batch);
31 this->recordTraceMarkersIfNecessary(cmd);
32 }
33
onStencilPath(const GrPipelineBuilder & pipelineBuilder,const GrPathProcessor * pathProc,const GrPath * path,const GrScissorState & scissorState,const GrStencilSettings & stencilSettings)34 void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder,
35 const GrPathProcessor* pathProc,
36 const GrPath* path,
37 const GrScissorState& scissorState,
38 const GrStencilSettings& stencilSettings) {
39 GrTargetCommands::Cmd* cmd = fCommands->recordStencilPath(pipelineBuilder,
40 pathProc, path, scissorState,
41 stencilSettings);
42 this->recordTraceMarkersIfNecessary(cmd);
43 }
44
onDrawPath(const GrPathProcessor * pathProc,const GrPath * path,const GrStencilSettings & stencilSettings,const PipelineInfo & pipelineInfo)45 void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
46 const GrPath* path,
47 const GrStencilSettings& stencilSettings,
48 const PipelineInfo& pipelineInfo) {
49 State* state = this->setupPipelineAndShouldDraw(pathProc, pipelineInfo);
50 if (!state) {
51 return;
52 }
53 GrTargetCommands::Cmd* cmd = fCommands->recordDrawPath(state, pathProc, path, stencilSettings);
54 this->recordTraceMarkersIfNecessary(cmd);
55 }
56
onDrawPaths(const GrPathProcessor * pathProc,const GrPathRange * pathRange,const void * indices,PathIndexType indexType,const float transformValues[],PathTransformType transformType,int count,const GrStencilSettings & stencilSettings,const PipelineInfo & pipelineInfo)57 void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
58 const GrPathRange* pathRange,
59 const void* indices,
60 PathIndexType indexType,
61 const float transformValues[],
62 PathTransformType transformType,
63 int count,
64 const GrStencilSettings& stencilSettings,
65 const PipelineInfo& pipelineInfo) {
66 State* state = this->setupPipelineAndShouldDraw(pathProc, pipelineInfo);
67 if (!state) {
68 return;
69 }
70 GrTargetCommands::Cmd* cmd = fCommands->recordDrawPaths(state, this, pathProc, pathRange,
71 indices, indexType, transformValues,
72 transformType, count,
73 stencilSettings, pipelineInfo);
74 this->recordTraceMarkersIfNecessary(cmd);
75 }
76
onClear(const SkIRect * rect,GrColor color,bool canIgnoreRect,GrRenderTarget * renderTarget)77 void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
78 bool canIgnoreRect, GrRenderTarget* renderTarget) {
79 GrTargetCommands::Cmd* cmd = fCommands->recordClear(rect, color, canIgnoreRect, renderTarget);
80 this->recordTraceMarkersIfNecessary(cmd);
81 }
82
clearStencilClip(const SkIRect & rect,bool insideClip,GrRenderTarget * renderTarget)83 void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
84 bool insideClip,
85 GrRenderTarget* renderTarget) {
86 GrTargetCommands::Cmd* cmd = fCommands->recordClearStencilClip(rect, insideClip, renderTarget);
87 this->recordTraceMarkersIfNecessary(cmd);
88 }
89
discard(GrRenderTarget * renderTarget)90 void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
91 if (!this->caps()->discardRenderTargetSupport()) {
92 return;
93 }
94
95 GrTargetCommands::Cmd* cmd = fCommands->recordDiscard(renderTarget);
96 this->recordTraceMarkersIfNecessary(cmd);
97 }
98
onReset()99 void GrInOrderDrawBuffer::onReset() {
100 fCommands->reset();
101 fPathIndexBuffer.rewind();
102 fPathTransformBuffer.rewind();
103 fGpuCmdMarkers.reset();
104
105 fPrevState.reset(NULL);
106 // Note, fPrevState points into fPipelineBuffer's allocation, so we have to reset first.
107 // Furthermore, we have to reset fCommands before fPipelineBuffer too.
108 if (fDrawID % kPipelineBufferHighWaterMark) {
109 fPipelineBuffer.rewind();
110 } else {
111 fPipelineBuffer.reset();
112 }
113 }
114
onFlush()115 void GrInOrderDrawBuffer::onFlush() {
116 fCommands->flush(this);
117 ++fDrawID;
118 }
119
onCopySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)120 void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
121 GrSurface* src,
122 const SkIRect& srcRect,
123 const SkIPoint& dstPoint) {
124 SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
125 GrTargetCommands::Cmd* cmd = fCommands->recordCopySurface(dst, src, srcRect, dstPoint);
126 this->recordTraceMarkersIfNecessary(cmd);
127 }
128
recordTraceMarkersIfNecessary(GrTargetCommands::Cmd * cmd)129 void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) {
130 if (!cmd) {
131 return;
132 }
133 const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
134 if (activeTraceMarkers.count() > 0) {
135 if (cmd->isTraced()) {
136 fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers);
137 } else {
138 cmd->setMarkerID(fGpuCmdMarkers.count());
139 fGpuCmdMarkers.push_back(activeTraceMarkers);
140 }
141 }
142 }
143
144 GrTargetCommands::State*
setupPipelineAndShouldDraw(const GrPrimitiveProcessor * primProc,const GrDrawTarget::PipelineInfo & pipelineInfo)145 GrInOrderDrawBuffer::setupPipelineAndShouldDraw(const GrPrimitiveProcessor* primProc,
146 const GrDrawTarget::PipelineInfo& pipelineInfo) {
147 State* state = this->allocState(primProc);
148 this->setupPipeline(pipelineInfo, state->pipelineLocation());
149
150 if (state->getPipeline()->mustSkip()) {
151 this->unallocState(state);
152 return NULL;
153 }
154
155 state->fPrimitiveProcessor->initBatchTracker(&state->fBatchTracker,
156 state->getPipeline()->getInitBatchTracker());
157
158 if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
159 fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
160 *state->fPrimitiveProcessor,
161 state->fBatchTracker) &&
162 fPrevState->getPipeline()->isEqual(*state->getPipeline())) {
163 this->unallocState(state);
164 } else {
165 fPrevState.reset(state);
166 }
167
168 this->recordTraceMarkersIfNecessary(
169 fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
170 return fPrevState;
171 }
172
173 GrTargetCommands::State*
setupPipelineAndShouldDraw(GrBatch * batch,const GrDrawTarget::PipelineInfo & pipelineInfo)174 GrInOrderDrawBuffer::setupPipelineAndShouldDraw(GrBatch* batch,
175 const GrDrawTarget::PipelineInfo& pipelineInfo) {
176 State* state = this->allocState();
177 this->setupPipeline(pipelineInfo, state->pipelineLocation());
178
179 if (state->getPipeline()->mustSkip()) {
180 this->unallocState(state);
181 return NULL;
182 }
183
184 batch->initBatchTracker(state->getPipeline()->getInitBatchTracker());
185
186 if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
187 fPrevState->getPipeline()->isEqual(*state->getPipeline())) {
188 this->unallocState(state);
189 } else {
190 fPrevState.reset(state);
191 }
192
193 this->recordTraceMarkersIfNecessary(
194 fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
195 return fPrevState;
196 }
197