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