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