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 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 19 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { 20 this->reset(); 21 } 22 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 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 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 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 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 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 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 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 115 void GrInOrderDrawBuffer::onFlush() { 116 fCommands->flush(this); 117 ++fDrawID; 118 } 119 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 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* 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* 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