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