blob: d69b34d94d3ae603fc273e976529f7864ee6808f [file] [log] [blame]
bsalomonbf877302015-09-22 09:06:13 -07001/*
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 "GrFragmentProcessor.h"
9#include "GrCoordTransform.h"
bsalomona624bf32016-09-20 09:12:47 -070010#include "GrPipeline.h"
Brian Salomona811b122017-03-30 08:21:32 -040011#include "GrProcessorAnalysis.h"
Brian Salomonc0b642c2017-03-27 13:09:36 -040012#include "effects/GrConstColorProcessor.h"
13#include "effects/GrXfermodeFragmentProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080014#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070016#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080017#include "glsl/GrGLSLUniformHandler.h"
bsalomonbf877302015-09-22 09:06:13 -070018
19GrFragmentProcessor::~GrFragmentProcessor() {
20 // If we got here then our ref count must have reached zero, so we will have converted refs
21 // to pending executions for all children.
22 for (int i = 0; i < fChildProcessors.count(); ++i) {
23 fChildProcessors[i]->completedExecution();
24 }
25}
26
bsalomon7312ff82016-09-12 08:55:38 -070027bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
bsalomonbf877302015-09-22 09:06:13 -070028 if (this->classID() != that.classID() ||
Brian Salomonf9f45122016-11-29 11:59:17 -050029 !this->hasSameSamplersAndAccesses(that)) {
bsalomonbf877302015-09-22 09:06:13 -070030 return false;
31 }
bsalomon7312ff82016-09-12 08:55:38 -070032 if (!this->hasSameTransforms(that)) {
bsalomonbf877302015-09-22 09:06:13 -070033 return false;
34 }
35 if (!this->onIsEqual(that)) {
36 return false;
37 }
38 if (this->numChildProcessors() != that.numChildProcessors()) {
39 return false;
40 }
41 for (int i = 0; i < this->numChildProcessors(); ++i) {
bsalomon7312ff82016-09-12 08:55:38 -070042 if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
bsalomonbf877302015-09-22 09:06:13 -070043 return false;
44 }
45 }
46 return true;
47}
48
egdaniel57d3b032015-11-13 11:57:27 -080049GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
50 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070051 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
52 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080053 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070054 }
55 return glFragProc;
56}
57
bsalomonbf877302015-09-22 09:06:13 -070058void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
bsalomonbf877302015-09-22 09:06:13 -070059 fCoordTransforms.push_back(transform);
Brian Salomon587e08f2017-01-27 10:59:27 -050060 fFlags |= kUsesLocalCoords_Flag;
bsalomonbf877302015-09-22 09:06:13 -070061 SkDEBUGCODE(transform->setInProcessor();)
bsalomonbf877302015-09-22 09:06:13 -070062}
63
Robert Phillips9bee2e52017-05-29 12:37:20 -040064bool GrFragmentProcessor::instantiate(GrResourceProvider* resourceProvider) const {
65 if (!INHERITED::instantiate(resourceProvider)) {
66 return false;
Robert Phillipsa91e0b72017-05-01 13:12:20 -040067 }
68
Robert Phillips9bee2e52017-05-29 12:37:20 -040069 for (int i = 0; i < this->numChildProcessors(); ++i) {
70 if (!this->childProcessor(i).instantiate(resourceProvider)) {
71 return false;
72 }
73 }
74
75 return true;
76}
77
78int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
cdalton87332102016-02-26 12:22:02 -080079 this->combineRequiredFeatures(*child);
bsalomonbf877302015-09-22 09:06:13 -070080
81 if (child->usesLocalCoords()) {
Brian Salomon587e08f2017-01-27 10:59:27 -050082 fFlags |= kUsesLocalCoords_Flag;
bsalomonbf877302015-09-22 09:06:13 -070083 }
84
bungeman06ca8ec2016-06-09 08:01:03 -070085 int index = fChildProcessors.count();
86 fChildProcessors.push_back(child.release());
87
bsalomonbf877302015-09-22 09:06:13 -070088 return index;
89}
90
91void GrFragmentProcessor::notifyRefCntIsZero() const {
92 // See comment above GrProgramElement for a detailed explanation of why we do this.
93 for (int i = 0; i < fChildProcessors.count(); ++i) {
94 fChildProcessors[i]->addPendingExecution();
95 fChildProcessors[i]->unref();
96 }
97}
98
99bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
bsalomona624bf32016-09-20 09:12:47 -0700100 if (this->numCoordTransforms() != that.numCoordTransforms()) {
bsalomonbf877302015-09-22 09:06:13 -0700101 return false;
102 }
bsalomona624bf32016-09-20 09:12:47 -0700103 int count = this->numCoordTransforms();
bsalomonbf877302015-09-22 09:06:13 -0700104 for (int i = 0; i < count; ++i) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500105 if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
bsalomonbf877302015-09-22 09:06:13 -0700106 return false;
107 }
108 }
109 return true;
110}
111
bungeman06ca8ec2016-06-09 08:01:03 -0700112sk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
113 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700114 if (!fp) {
115 return nullptr;
116 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400117 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
bsalomonbf877302015-09-22 09:06:13 -0700118}
119
Brian Osmande1a6052017-03-22 10:57:00 -0400120namespace {
121
122class PremulInputFragmentProcessor : public GrFragmentProcessor {
123public:
124 PremulInputFragmentProcessor()
125 : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
126 kConstantOutputForConstantInput_OptimizationFlag) {
127 this->initClassID<PremulInputFragmentProcessor>();
128 }
129
130 const char* name() const override { return "PremultiplyInput"; }
131
132private:
133 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
134 class GLFP : public GrGLSLFragmentProcessor {
135 public:
136 void emitCode(EmitArgs& args) override {
137 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
138
139 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
140 fragBuilder->codeAppendf("%s.rgb *= %s.a;",
141 args.fOutputColor, args.fInputColor);
142 }
143 };
144 return new GLFP;
145 }
146
147 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
148
149 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
150
151 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
152 return input.premul();
153 }
154
155 typedef GrFragmentProcessor INHERITED;
156};
157
158class UnpremulInputFragmentProcessor : public GrFragmentProcessor {
159public:
160 UnpremulInputFragmentProcessor()
161 : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
162 kConstantOutputForConstantInput_OptimizationFlag) {
163 this->initClassID<UnpremulInputFragmentProcessor>();
164 }
165
166 const char* name() const override { return "UnpremultiplyInput"; }
167
168private:
169 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
170 class GLFP : public GrGLSLFragmentProcessor {
171 public:
172 void emitCode(EmitArgs& args) override {
173 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
174
175 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
176 fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
177 args.fInputColor, args.fInputColor);
178 fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
179 }
180 };
181 return new GLFP;
182 }
183
184 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
185
186 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
187
188 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
189 return input.unpremul();
190 }
191
192 typedef GrFragmentProcessor INHERITED;
193};
194
195}
196
dvonbeckc526da92016-07-20 11:20:30 -0700197sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
dvonbeckc526da92016-07-20 11:20:30 -0700198 if (!fp) {
199 return nullptr;
200 }
201 sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
202 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
203}
204
Brian Osmande1a6052017-03-22 10:57:00 -0400205sk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
206 if (!fp) {
207 return nullptr;
208 }
209 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<PremulInputFragmentProcessor>() };
210 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
211}
212
213sk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
214 if (!fp) {
215 return nullptr;
216 }
217 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<UnpremulInputFragmentProcessor>() };
218 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
219}
220
Brian Osmance425512017-03-22 14:37:50 -0400221sk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
222 const GrSwizzle& swizzle) {
223 class SwizzleFragmentProcessor : public GrFragmentProcessor {
224 public:
225 SwizzleFragmentProcessor(const GrSwizzle& swizzle)
226 : INHERITED(kAll_OptimizationFlags)
227 , fSwizzle(swizzle) {
228 this->initClassID<SwizzleFragmentProcessor>();
229 }
230
231 const char* name() const override { return "Swizzle"; }
232 const GrSwizzle& swizzle() const { return fSwizzle; }
233
234 private:
235 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
236 class GLFP : public GrGLSLFragmentProcessor {
237 public:
238 void emitCode(EmitArgs& args) override {
239 const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
240 const GrSwizzle& swizzle = sfp.swizzle();
241 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
242
243 fragBuilder->codeAppendf("%s = %s.%s;",
244 args.fOutputColor, args.fInputColor, swizzle.c_str());
245 }
246 };
247 return new GLFP;
248 }
249
250 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
251 b->add32(fSwizzle.asKey());
252 }
253
254 bool onIsEqual(const GrFragmentProcessor& other) const override {
255 const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
256 return fSwizzle == sfp.fSwizzle;
257 }
258
259 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
260 return fSwizzle.applyTo(input);
261 }
262
263 GrSwizzle fSwizzle;
264
265 typedef GrFragmentProcessor INHERITED;
266 };
267
268 if (!fp) {
269 return nullptr;
270 }
271 if (GrSwizzle::RGBA() == swizzle) {
272 return fp;
273 }
274 sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<SwizzleFragmentProcessor>(swizzle) };
275 return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
276}
277
Brian Salomon22af73f2017-01-26 11:25:12 -0500278sk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
279 sk_sp<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700280
281 class PremulFragmentProcessor : public GrFragmentProcessor {
282 public:
Brian Salomon587e08f2017-01-27 10:59:27 -0500283 PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
284 : INHERITED(OptFlags(processor.get())) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700285 this->initClassID<PremulFragmentProcessor>();
286 this->registerChildProcessor(processor);
287 }
288
289 const char* name() const override { return "Premultiply"; }
290
291 private:
egdaniel57d3b032015-11-13 11:57:27 -0800292 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800293 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700294 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700295 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800296 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Ethan Nicholas2983f402017-05-08 09:36:08 -0400297 this->emitChild(0, args);
egdaniel4ca2e602015-11-18 08:01:26 -0800298 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
bsalomonf1b7a1d2015-09-28 06:26:28 -0700299 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800300 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700301 }
302 };
303 return new GLFP;
304 }
305
Brian Salomon94efbf52016-11-29 13:43:05 -0500306 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700307
308 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
309
Brian Salomon587e08f2017-01-27 10:59:27 -0500310 static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
311 OptimizationFlags flags = kNone_OptimizationFlags;
312 if (inner->preservesOpaqueInput()) {
313 flags |= kPreservesOpaqueInput_OptimizationFlag;
314 }
315 if (inner->hasConstantOutputForConstantInput()) {
316 flags |= kConstantOutputForConstantInput_OptimizationFlag;
317 }
318 return flags;
319 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700320
Brian Salomon587e08f2017-01-27 10:59:27 -0500321 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
322 GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
323 GrColor4f::OpaqueWhite());
324 return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
325 input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
326 input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
327 input.fRGBA[3] * childColor.fRGBA[3]);
328 }
329
330 typedef GrFragmentProcessor INHERITED;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700331 };
332 if (!fp) {
333 return nullptr;
334 }
bungeman06ca8ec2016-06-09 08:01:03 -0700335 return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700336}
337
338//////////////////////////////////////////////////////////////////////////////
339
bungeman06ca8ec2016-06-09 08:01:03 -0700340sk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
brianosman4cea3b92016-09-08 09:33:50 -0700341 GrColor4f color) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700342 class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
343 public:
brianosman4cea3b92016-09-08 09:33:50 -0700344 ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
Brian Salomon587e08f2017-01-27 10:59:27 -0500345 : INHERITED(OptFlags(child.get(), color)), fColor(color) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700346 this->initClassID<ReplaceInputFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700347 this->registerChildProcessor(std::move(child));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700348 }
349
350 const char* name() const override { return "Replace Color"; }
351
egdaniel57d3b032015-11-13 11:57:27 -0800352 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800353 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700354 public:
355 GLFP() : fHaveSetColor(false) {}
356 void emitCode(EmitArgs& args) override {
357 const char* colorName;
cdalton5e58cee2016-02-11 12:49:47 -0800358 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
359 kVec4f_GrSLType,
360 kDefault_GrSLPrecision,
361 "Color", &colorName);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700362 this->emitChild(0, colorName, args);
363 }
364
365 private:
egdaniel018fb622015-10-28 07:26:40 -0700366 void onSetData(const GrGLSLProgramDataManager& pdman,
Brian Salomonab015ef2017-04-04 10:15:51 -0400367 const GrFragmentProcessor& fp) override {
brianosman4cea3b92016-09-08 09:33:50 -0700368 GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700369 if (!fHaveSetColor || color != fPreviousColor) {
brianosman4cea3b92016-09-08 09:33:50 -0700370 pdman.set4fv(fColorUni, 1, color.fRGBA);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700371 fPreviousColor = color;
372 fHaveSetColor = true;
373 }
374 }
375
egdaniel018fb622015-10-28 07:26:40 -0700376 GrGLSLProgramDataManager::UniformHandle fColorUni;
brianosman4cea3b92016-09-08 09:33:50 -0700377 bool fHaveSetColor;
378 GrColor4f fPreviousColor;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700379 };
380
381 return new GLFP;
382 }
383
384 private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500385 static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
386 OptimizationFlags childFlags = child->optimizationFlags();
387 OptimizationFlags flags = kNone_OptimizationFlags;
388 if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
389 flags |= kConstantOutputForConstantInput_OptimizationFlag;
390 }
391 if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
392 flags |= kPreservesOpaqueInput_OptimizationFlag;
393 }
394 return flags;
395 }
396
Brian Salomon94efbf52016-11-29 13:43:05 -0500397 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
egdaniel57d3b032015-11-13 11:57:27 -0800398 {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700399
400 bool onIsEqual(const GrFragmentProcessor& that) const override {
401 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
402 }
403
Brian Salomon587e08f2017-01-27 10:59:27 -0500404 GrColor4f constantOutputForConstantInput(GrColor4f) const override {
405 return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
406 }
407
brianosman4cea3b92016-09-08 09:33:50 -0700408 GrColor4f fColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500409
410 typedef GrFragmentProcessor INHERITED;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700411 };
412
Brian Salomon5f13fba2017-01-23 14:35:25 -0500413 return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700414}
bsalomone25eea42015-09-29 06:38:55 -0700415
bungeman06ca8ec2016-06-09 08:01:03 -0700416sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
bsalomone25eea42015-09-29 06:38:55 -0700417 int cnt) {
418 class SeriesFragmentProcessor : public GrFragmentProcessor {
419 public:
Brian Salomon587e08f2017-01-27 10:59:27 -0500420 SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
421 : INHERITED(OptFlags(children, cnt)) {
bsalomone25eea42015-09-29 06:38:55 -0700422 SkASSERT(cnt > 1);
423 this->initClassID<SeriesFragmentProcessor>();
424 for (int i = 0; i < cnt; ++i) {
bungeman06ca8ec2016-06-09 08:01:03 -0700425 this->registerChildProcessor(std::move(children[i]));
bsalomone25eea42015-09-29 06:38:55 -0700426 }
427 }
428
429 const char* name() const override { return "Series"; }
430
egdaniel57d3b032015-11-13 11:57:27 -0800431 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800432 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700433 public:
bsalomone25eea42015-09-29 06:38:55 -0700434 void emitCode(EmitArgs& args) override {
dvonbeckca9eeab2016-07-06 12:00:06 -0700435 // First guy's input might be nil.
436 SkString temp("out0");
437 this->emitChild(0, args.fInputColor, &temp, args);
438 SkString input = temp;
439 for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
bsalomone25eea42015-09-29 06:38:55 -0700440 temp.printf("out%d", i);
441 this->emitChild(i, input.c_str(), &temp, args);
442 input = temp;
443 }
444 // Last guy writes to our output variable.
445 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
446 }
447 };
448 return new GLFP;
449 }
bsalomone25eea42015-09-29 06:38:55 -0700450 private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500451 static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
452 OptimizationFlags flags = kAll_OptimizationFlags;
453 for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
454 flags &= children[i]->optimizationFlags();
455 }
456 return flags;
457 }
Brian Salomon94efbf52016-11-29 13:43:05 -0500458 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700459
460 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
461
Brian Salomon587e08f2017-01-27 10:59:27 -0500462 GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
463 int childCnt = this->numChildProcessors();
464 for (int i = 0; i < childCnt; ++i) {
465 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
466 }
467 return color;
468 }
469
470 typedef GrFragmentProcessor INHERITED;
bsalomone25eea42015-09-29 06:38:55 -0700471 };
472
473 if (!cnt) {
474 return nullptr;
475 }
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500476 if (1 == cnt) {
477 return series[0];
478 }
bsalomone25eea42015-09-29 06:38:55 -0700479 // Run the through the series, do the invariant output processing, and look for eliminations.
Brian Salomonc0b642c2017-03-27 13:09:36 -0400480 GrColorFragmentProcessorAnalysis info;
Brian Salomon0831f1b2017-01-18 11:08:41 -0500481 info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
bungeman06ca8ec2016-06-09 08:01:03 -0700482 SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500483 GrColor4f knownColor;
484 int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
485 if (leadingFPsToEliminate) {
486 sk_sp<GrFragmentProcessor> colorFP(
487 GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
488 if (leadingFPsToEliminate == cnt) {
489 return colorFP;
490 }
491 cnt = cnt - leadingFPsToEliminate + 1;
bungeman06ca8ec2016-06-09 08:01:03 -0700492 replacementSeries.reserve(cnt);
493 replacementSeries.emplace_back(std::move(colorFP));
494 for (int i = 0; i < cnt - 1; ++i) {
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500495 replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
bsalomone25eea42015-09-29 06:38:55 -0700496 }
bungeman06ca8ec2016-06-09 08:01:03 -0700497 series = replacementSeries.begin();
bsalomone25eea42015-09-29 06:38:55 -0700498 }
bungeman06ca8ec2016-06-09 08:01:03 -0700499 return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700500}
bsalomona624bf32016-09-20 09:12:47 -0700501
502//////////////////////////////////////////////////////////////////////////////
503
504GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
505 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
506 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
507 }
508}
509
510const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
511 if (fFPStack.empty()) {
512 return nullptr;
513 }
514 const GrFragmentProcessor* back = fFPStack.back();
515 fFPStack.pop_back();
516 for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
517 fFPStack.push_back(&back->childProcessor(i));
518 }
519 return back;
520}
521