1af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt/* 2af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * Copyright 2015 Google Inc. 3af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * 4af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * Use of this source code is governed by a BSD-style license that can be 5af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * found in the LICENSE file. 6af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt */ 7af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 8af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrInOrderCommandBuilder.h" 9af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 10af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrColor.h" 11af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrInOrderDrawBuffer.h" 12af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrTemplates.h" 13af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "SkPoint.h" 14af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 15af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittstatic bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) { 16af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face; 17af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace); 18af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (isWinding) { 19af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // Double check that it is in fact winding. 20af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace)); 21af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace)); 22af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace)); 23af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(!pathStencilSettings.isTwoSided()); 24af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 25af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return isWinding; 26af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt} 27af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 28af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd* GrInOrderCommandBuilder::recordDrawBatch(State* state, GrBatch* batch) { 29af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // Check if there is a Batch Draw we can batch with 30af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (!this->cmdBuffer()->empty() && 31af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt Cmd::kDrawBatch_CmdType == this->cmdBuffer()->back().type()) { 32af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt DrawBatch* previous = static_cast<DrawBatch*>(&this->cmdBuffer()->back()); 33af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) { 34af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return NULL; 35af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 36af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 37af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 38af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawBatch, (state, batch, 39af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt this->batchTarget())); 40af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt} 41af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 42af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd* 43af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordStencilPath(const GrPipelineBuilder& pipelineBuilder, 44af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPathProcessor* pathProc, 45af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPath* path, 46af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrScissorState& scissorState, 47af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrStencilSettings& stencilSettings) { 48af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt StencilPath* sp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), StencilPath, 49af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt (path, pipelineBuilder.getRenderTarget())); 50af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 51af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt sp->fScissor = scissorState; 52af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt sp->fUseHWAA = pipelineBuilder.isHWAntialias(); 53af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt sp->fViewMatrix = pathProc->viewMatrix(); 54af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt sp->fStencil = stencilSettings; 55af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return sp; 56af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt} 57af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 58af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd* 59af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordDrawPath(State* state, 60af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPathProcessor* pathProc, 61af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPath* path, 62af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrStencilSettings& stencilSettings) { 63af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt DrawPath* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPath, (state, path)); 64af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fStencilSettings = stencilSettings; 65af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return dp; 66af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt} 67af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 68af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd* 69af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordDrawPaths(State* state, 70af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt GrInOrderDrawBuffer* iodb, 71af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPathProcessor* pathProc, 72af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrPathRange* pathRange, 73af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const void* indexValues, 74af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt GrDrawTarget::PathIndexType indexType, 75af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const float transformValues[], 76af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt GrDrawTarget::PathTransformType transformType, 77af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt int count, 78af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrStencilSettings& stencilSettings, 79af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const GrDrawTarget::PipelineInfo& pipelineInfo) { 80af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(pathRange); 81af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(indexValues); 82af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt SkASSERT(transformValues); 83af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 84af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt char* savedIndices; 85af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt float* savedTransforms; 86af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 87af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt iodb->appendIndicesAndTransforms(indexValues, indexType, 88af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt transformValues, transformType, 89af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt count, &savedIndices, &savedTransforms); 90af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 91af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (!this->cmdBuffer()->empty() && 92af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt Cmd::kDrawPaths_CmdType == this->cmdBuffer()->back().type()) { 93af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // The previous command was also DrawPaths. Try to collapse this call into the one 94af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // before. Note that stenciling all the paths at once, then covering, may not be 95af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // equivalent to two separate draw calls if there is overlap. Blending won't work, 96af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // and the combined calls may also cancel each other's winding numbers in some 97af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // places. For now the winding numbers are only an issue if the fill is even/odd, 98af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // because DrawPaths is currently only used for glyphs, and glyphs in the same 99af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // font tend to all wind in the same direction. 100af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt DrawPaths* previous = static_cast<DrawPaths*>(&this->cmdBuffer()->back()); 101af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (pathRange == previous->pathRange() && 102af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt indexType == previous->fIndexType && 103af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt transformType == previous->fTransformType && 104af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt stencilSettings == previous->fStencilSettings && 105af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt path_fill_type_is_winding(stencilSettings) && 106af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt !pipelineInfo.willBlendWithDst(pathProc) && 107af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt previous->fState == state) { 108af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType); 109af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt const int xformSize = GrPathRendering::PathTransformSize(transformType); 110af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices && 111af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt (0 == xformSize || 112af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) { 113af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt // Fold this DrawPaths call into the one previous. 114af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt previous->fCount += count; 115af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return NULL; 116af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 117af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 118af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt } 119af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt 120af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPaths, (state, pathRange)); 121af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fIndices = savedIndices; 122af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fIndexType = indexType; 123af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fTransforms = savedTransforms; 124af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fTransformType = transformType; 125af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fCount = count; 126af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt dp->fStencilSettings = stencilSettings; 127af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt return dp; 128af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt} 129