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 
GrPipeline(const GrPipelineBuilder & pipelineBuilder,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,const GrDrawTargetCaps & caps,const GrScissorState & scissorState,const GrDeviceCoordTexture * dstCopy)17 GrPipeline::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 
adjustProgramFromOptimizations(const GrPipelineBuilder & pipelineBuilder,GrXferProcessor::OptFlags flags,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,int * firstColorStageIdx,int * firstCoverageStageIdx)109 void 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 
isEqual(const GrPipeline & that) const137 bool 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