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