• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrCaps.h"
11 #include "GrDrawTarget.h"
12 #include "GrGpu.h"
13 #include "GrPipelineBuilder.h"
14 #include "GrProcOptInfo.h"
15 #include "GrXferProcessor.h"
16 
17 #include "batches/GrBatch.h"
18 
CreateAt(void * memory,const CreateArgs & args,GrXPOverridesForBatch * overrides)19 GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
20                                  GrXPOverridesForBatch* overrides) {
21     const GrPipelineBuilder& builder = *args.fPipelineBuilder;
22 
23     // Create XferProcessor from DS's XPFactory
24     const GrXPFactory* xpFactory = builder.getXPFactory();
25     SkAutoTUnref<GrXferProcessor> xferProcessor;
26     if (xpFactory) {
27         xferProcessor.reset(xpFactory->createXferProcessor(args.fOpts,
28                                                            builder.hasMixedSamples(),
29                                                            &args.fDstTexture,
30                                                            *args.fCaps));
31         if (!xferProcessor) {
32             return nullptr;
33         }
34     } else {
35         // This may return nullptr in the common case of src-over implemented using hw blending.
36         xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
37                                                                         *args.fCaps,
38                                                                         args.fOpts,
39                                                                         builder.hasMixedSamples(),
40                                                                         &args.fDstTexture));
41     }
42    GrColor overrideColor = GrColor_ILLEGAL;
43     if (args.fOpts.fColorPOI.firstEffectiveProcessorIndex() != 0) {
44         overrideColor = args.fOpts.fColorPOI.inputColorToFirstEffectiveProccesor();
45     }
46 
47     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
48 
49     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
50                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
51     optFlags = xpForOpts->getOptimizations(args.fOpts,
52                                            builder.getStencil().doesWrite(),
53                                            &overrideColor,
54                                            *args.fCaps);
55 
56     // When path rendering the stencil settings are not always set on the GrPipelineBuilder
57     // so we must check the draw type. In cases where we will skip drawing we simply return a
58     // null GrPipeline.
59     if (GrXferProcessor::kSkipDraw_OptFlag & optFlags) {
60         return nullptr;
61     }
62 
63     // No need to have an override color if it isn't even going to be used.
64     if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) {
65         overrideColor = GrColor_ILLEGAL;
66     }
67 
68     GrPipeline* pipeline = new (memory) GrPipeline;
69     pipeline->fXferProcessor.reset(xferProcessor);
70 
71     pipeline->fRenderTarget.reset(builder.fRenderTarget.get());
72     SkASSERT(pipeline->fRenderTarget);
73     pipeline->fScissorState = *args.fScissor;
74     pipeline->fStencilSettings = builder.getStencil();
75     pipeline->fDrawFace = builder.getDrawFace();
76 
77     pipeline->fFlags = 0;
78     if (builder.isHWAntialias()) {
79         pipeline->fFlags |= kHWAA_Flag;
80     }
81     if (builder.snapVerticesToPixelCenters()) {
82         pipeline->fFlags |= kSnapVertices_Flag;
83     }
84 
85     int firstColorProcessorIdx = args.fOpts.fColorPOI.firstEffectiveProcessorIndex();
86 
87     // TODO: Once we can handle single or four channel input into coverage GrFragmentProcessors
88     // then we can use GrPipelineBuilder's coverageProcInfo (like color above) to set this initial
89     // information.
90     int firstCoverageProcessorIdx = 0;
91 
92     pipeline->adjustProgramFromOptimizations(builder, optFlags, args.fOpts.fColorPOI,
93                                              args.fOpts.fCoveragePOI, &firstColorProcessorIdx,
94                                              &firstCoverageProcessorIdx);
95 
96     bool usesLocalCoords = false;
97 
98     // Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline
99     pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx;
100     int numTotalProcessors = pipeline->fNumColorProcessors +
101                              builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx;
102     pipeline->fFragmentProcessors.reset(numTotalProcessors);
103     int currFPIdx = 0;
104     for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors();
105          ++i, ++currFPIdx) {
106         const GrFragmentProcessor* fp = builder.getColorFragmentProcessor(i);
107         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
108         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
109     }
110 
111     for (int i = firstCoverageProcessorIdx; i < builder.numCoverageFragmentProcessors();
112          ++i, ++currFPIdx) {
113         const GrFragmentProcessor* fp = builder.getCoverageFragmentProcessor(i);
114         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
115         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
116     }
117 
118     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
119     overrides->fFlags = 0;
120     if (!SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) {
121         overrides->fFlags |= GrXPOverridesForBatch::kReadsColor_Flag;
122     }
123     if (GrColor_ILLEGAL != overrideColor) {
124         overrides->fFlags |= GrXPOverridesForBatch::kUseOverrideColor_Flag;
125         overrides->fOverrideColor = overrideColor;
126     }
127     if (!SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag)) {
128         overrides->fFlags |= GrXPOverridesForBatch::kReadsCoverage_Flag;
129     }
130     if (usesLocalCoords) {
131         overrides->fFlags |= GrXPOverridesForBatch::kReadsLocalCoords_Flag;
132     }
133     if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
134         overrides->fFlags |= GrXPOverridesForBatch::kCanTweakAlphaForCoverage_Flag;
135     }
136 
137     GrXPFactory::InvariantBlendedColor blendedColor;
138     if (xpFactory) {
139         xpFactory->getInvariantBlendedColor(args.fOpts.fColorPOI, &blendedColor);
140     } else {
141         GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(args.fOpts.fColorPOI.color(),
142                                                             args.fOpts.fColorPOI.validFlags(),
143                                                             args.fOpts.fColorPOI.isOpaque(),
144                                                             &blendedColor);
145     }
146     if (blendedColor.fWillBlendWithDst) {
147         overrides->fFlags |= GrXPOverridesForBatch::kWillColorBlendWithDst_Flag;
148     }
149 
150     return pipeline;
151 }
152 
add_dependencies_for_processor(const GrFragmentProcessor * proc,GrRenderTarget * rt)153 static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) {
154     for (int i = 0; i < proc->numChildProcessors(); ++i) {
155         // need to recurse
156         add_dependencies_for_processor(&proc->childProcessor(i), rt);
157     }
158 
159     for (int i = 0; i < proc->numTextures(); ++i) {
160         GrTexture* texture = proc->textureAccess(i).getTexture();
161         SkASSERT(rt->getLastDrawTarget());
162         rt->getLastDrawTarget()->addDependency(texture);
163     }
164 }
165 
addDependenciesTo(GrRenderTarget * rt) const166 void GrPipeline::addDependenciesTo(GrRenderTarget* rt) const {
167     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
168         add_dependencies_for_processor(fFragmentProcessors[i].get(), rt);
169     }
170 
171     const GrXferProcessor& xfer = this->getXferProcessor();
172 
173     for (int i = 0; i < xfer.numTextures(); ++i) {
174         GrTexture* texture = xfer.textureAccess(i).getTexture();
175         SkASSERT(rt->getLastDrawTarget());
176         rt->getLastDrawTarget()->addDependency(texture);
177     }
178 }
179 
adjustProgramFromOptimizations(const GrPipelineBuilder & pipelineBuilder,GrXferProcessor::OptFlags flags,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,int * firstColorProcessorIdx,int * firstCoverageProcessorIdx)180 void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder,
181                                                 GrXferProcessor::OptFlags flags,
182                                                 const GrProcOptInfo& colorPOI,
183                                                 const GrProcOptInfo& coveragePOI,
184                                                 int* firstColorProcessorIdx,
185                                                 int* firstCoverageProcessorIdx) {
186     fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag);
187     fReadsFragPosition = this->getXferProcessor().willReadFragmentPosition();
188 
189     if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
190         (flags & GrXferProcessor::kOverrideColor_OptFlag)) {
191         *firstColorProcessorIdx = pipelineBuilder.numColorFragmentProcessors();
192     } else {
193         if (colorPOI.readsFragPosition()) {
194             fReadsFragPosition = true;
195         }
196     }
197 
198     if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
199         *firstCoverageProcessorIdx = pipelineBuilder.numCoverageFragmentProcessors();
200     } else {
201         if (coveragePOI.readsFragPosition()) {
202             fReadsFragPosition = true;
203         }
204     }
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 
AreEqual(const GrPipeline & a,const GrPipeline & b,bool ignoreCoordTransforms)209 bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b,
210                           bool ignoreCoordTransforms) {
211     SkASSERT(&a != &b);
212 
213     if (a.getRenderTarget() != b.getRenderTarget() ||
214         a.fFragmentProcessors.count() != b.fFragmentProcessors.count() ||
215         a.fNumColorProcessors != b.fNumColorProcessors ||
216         a.fScissorState != b.fScissorState ||
217         a.fFlags != b.fFlags ||
218         a.fStencilSettings != b.fStencilSettings ||
219         a.fDrawFace != b.fDrawFace) {
220         return false;
221     }
222 
223     // Most of the time both are nullptr
224     if (a.fXferProcessor.get() || b.fXferProcessor.get()) {
225         if (!a.getXferProcessor().isEqual(b.getXferProcessor())) {
226             return false;
227         }
228     }
229 
230     for (int i = 0; i < a.numFragmentProcessors(); i++) {
231         if (!a.getFragmentProcessor(i).isEqual(b.getFragmentProcessor(i), ignoreCoordTransforms)) {
232             return false;
233         }
234     }
235     return true;
236 }
237 
238