1/* 2 * Copyright 2015 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 "GrPipeline.h" 9 10#include "GrBatch.h" 11#include "GrDrawTargetCaps.h" 12#include "GrGpu.h" 13#include "GrPipelineBuilder.h" 14#include "GrProcOptInfo.h" 15#include "GrXferProcessor.h" 16 17GrPipeline::GrPipeline(const GrPipelineBuilder& pipelineBuilder, 18 const GrProcOptInfo& colorPOI, 19 const GrProcOptInfo& coveragePOI, 20 const GrDrawTargetCaps& caps, 21 const GrScissorState& scissorState, 22 const GrDeviceCoordTexture* dstCopy) { 23 // Create XferProcessor from DS's XPFactory 24 SkAutoTUnref<GrXferProcessor> xferProcessor( 25 pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI, dstCopy, caps)); 26 27 GrColor overrideColor = GrColor_ILLEGAL; 28 if (colorPOI.firstEffectiveStageIndex() != 0) { 29 overrideColor = colorPOI.inputColorToEffectiveStage(); 30 } 31 32 GrXferProcessor::OptFlags optFlags; 33 if (xferProcessor) { 34 fXferProcessor.reset(xferProcessor.get()); 35 36 optFlags = xferProcessor->getOptimizations(colorPOI, 37 coveragePOI, 38 pipelineBuilder.getStencil().doesWrite(), 39 &overrideColor, 40 caps); 41 } 42 43 // When path rendering the stencil settings are not always set on the GrPipelineBuilder 44 // so we must check the draw type. In cases where we will skip drawing we simply return a 45 // null GrPipeline. 46 if (!xferProcessor || (GrXferProcessor::kSkipDraw_OptFlag & optFlags)) { 47 // Set the fields that don't default init and return. The lack of a render target will 48 // indicate that this can be skipped. 49 fFlags = 0; 50 fDrawFace = GrPipelineBuilder::kInvalid_DrawFace; 51 return; 52 } 53 54 fRenderTarget.reset(pipelineBuilder.fRenderTarget.get()); 55 SkASSERT(fRenderTarget); 56 fScissorState = scissorState; 57 fStencilSettings = pipelineBuilder.getStencil(); 58 fDrawFace = pipelineBuilder.getDrawFace(); 59 60 fFlags = 0; 61 if (pipelineBuilder.isHWAntialias()) { 62 fFlags |= kHWAA_Flag; 63 } 64 if (pipelineBuilder.isDither()) { 65 fFlags |= kDither_Flag; 66 } 67 if (pipelineBuilder.snapVerticesToPixelCenters()) { 68 fFlags |= kSnapVertices_Flag; 69 } 70 71 int firstColorStageIdx = colorPOI.firstEffectiveStageIndex(); 72 73 // TODO: Once we can handle single or four channel input into coverage stages then we can use 74 // GrPipelineBuilder's coverageProcInfo (like color above) to set this initial information. 75 int firstCoverageStageIdx = 0; 76 77 this->adjustProgramFromOptimizations(pipelineBuilder, optFlags, colorPOI, coveragePOI, 78 &firstColorStageIdx, &firstCoverageStageIdx); 79 80 bool usesLocalCoords = false; 81 82 // Copy Stages from PipelineBuilder to Pipeline 83 for (int i = firstColorStageIdx; i < pipelineBuilder.numColorFragmentStages(); ++i) { 84 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, 85 GrPendingFragmentStage, 86 (pipelineBuilder.fColorStages[i])); 87 usesLocalCoords = usesLocalCoords || 88 pipelineBuilder.fColorStages[i].processor()->usesLocalCoords(); 89 } 90 91 fNumColorStages = fFragmentStages.count(); 92 for (int i = firstCoverageStageIdx; i < pipelineBuilder.numCoverageFragmentStages(); ++i) { 93 SkNEW_APPEND_TO_TARRAY(&fFragmentStages, 94 GrPendingFragmentStage, 95 (pipelineBuilder.fCoverageStages[i])); 96 usesLocalCoords = usesLocalCoords || 97 pipelineBuilder.fCoverageStages[i].processor()->usesLocalCoords(); 98 } 99 100 // let the GP init the batch tracker 101 fInitBT.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag); 102 fInitBT.fOverrideColor = fInitBT.fColorIgnored ? GrColor_ILLEGAL : overrideColor; 103 fInitBT.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag); 104 fInitBT.fUsesLocalCoords = usesLocalCoords; 105 fInitBT.fCanTweakAlphaForCoverage = 106 SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); 107} 108 109void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder, 110 GrXferProcessor::OptFlags flags, 111 const GrProcOptInfo& colorPOI, 112 const GrProcOptInfo& coveragePOI, 113 int* firstColorStageIdx, 114 int* firstCoverageStageIdx) { 115 fReadsFragPosition = fXferProcessor->willReadFragmentPosition(); 116 117 if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) || 118 (flags & GrXferProcessor::kOverrideColor_OptFlag)) { 119 *firstColorStageIdx = pipelineBuilder.numColorFragmentStages(); 120 } else { 121 if (coveragePOI.readsFragPosition()) { 122 fReadsFragPosition = true; 123 } 124 } 125 126 if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) { 127 *firstCoverageStageIdx = pipelineBuilder.numCoverageFragmentStages(); 128 } else { 129 if (coveragePOI.readsFragPosition()) { 130 fReadsFragPosition = true; 131 } 132 } 133} 134 135//////////////////////////////////////////////////////////////////////////////// 136 137bool GrPipeline::isEqual(const GrPipeline& that) const { 138 if (this->getRenderTarget() != that.getRenderTarget() || 139 this->fFragmentStages.count() != that.fFragmentStages.count() || 140 this->fNumColorStages != that.fNumColorStages || 141 this->fScissorState != that.fScissorState || 142 this->fFlags != that.fFlags || 143 this->fStencilSettings != that.fStencilSettings || 144 this->fDrawFace != that.fDrawFace) { 145 return false; 146 } 147 148 if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) { 149 return false; 150 } 151 152 // The program desc comparison should have already assured that the stage counts match. 153 SkASSERT(this->numFragmentStages() == that.numFragmentStages()); 154 for (int i = 0; i < this->numFragmentStages(); i++) { 155 156 if (this->getFragmentStage(i) != that.getFragmentStage(i)) { 157 return false; 158 } 159 } 160 return true; 161} 162 163