/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrInOrderDrawBuffer.h" GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context) : INHERITED(context) , fCommands(GrCommandBuilder::Create(context->getGpu(), false)) , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4) , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4) , fPipelineBuffer(kPipelineBufferMinReserve) , fDrawID(0) { } GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { this->reset(); } void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch, const PipelineInfo& pipelineInfo) { State* state = this->setupPipelineAndShouldDraw(batch, pipelineInfo); if (!state) { return; } GrTargetCommands::Cmd* cmd = fCommands->recordDrawBatch(state, batch); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder, const GrPathProcessor* pathProc, const GrPath* path, const GrScissorState& scissorState, const GrStencilSettings& stencilSettings) { GrTargetCommands::Cmd* cmd = fCommands->recordStencilPath(pipelineBuilder, pathProc, path, scissorState, stencilSettings); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc, const GrPath* path, const GrStencilSettings& stencilSettings, const PipelineInfo& pipelineInfo) { State* state = this->setupPipelineAndShouldDraw(pathProc, pipelineInfo); if (!state) { return; } GrTargetCommands::Cmd* cmd = fCommands->recordDrawPath(state, pathProc, path, stencilSettings); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::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) { 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); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect, GrRenderTarget* 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(rect, insideClip, renderTarget); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) { if (!this->caps()->discardRenderTargetSupport()) { return; } GrTargetCommands::Cmd* cmd = fCommands->recordDiscard(renderTarget); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::onReset() { fCommands->reset(); 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() { fCommands->flush(this); ++fDrawID; } void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint)); GrTargetCommands::Cmd* cmd = fCommands->recordCopySurface(dst, src, srcRect, dstPoint); this->recordTraceMarkersIfNecessary(cmd); } void GrInOrderDrawBuffer::recordTraceMarkersIfNecessary(GrTargetCommands::Cmd* cmd) { if (!cmd) { return; } const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers(); if (activeTraceMarkers.count() > 0) { if (cmd->isTraced()) { fGpuCmdMarkers[cmd->markerID()].addSet(activeTraceMarkers); } else { cmd->setMarkerID(fGpuCmdMarkers.count()); fGpuCmdMarkers.push_back(activeTraceMarkers); } } } 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); } this->recordTraceMarkersIfNecessary( fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps())); 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); } this->recordTraceMarkersIfNecessary( fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps())); return fPrevState; }