blob: 5a8b0df5fe644e0f0113851a9c269a14c105c3d1 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrFragmentProcessor.h"
9#include "src/gpu/GrPipeline.h"
10#include "src/gpu/GrProcessorAnalysis.h"
11#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
Brian Osman6f5e9402020-01-22 10:39:31 -050012#include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/effects/generated/GrConstColorProcessor.h"
14#include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
16#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
17#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
18#include "src/gpu/glsl/GrGLSLUniformHandler.h"
bsalomonbf877302015-09-22 09:06:13 -070019
bsalomon7312ff82016-09-12 08:55:38 -070020bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
Brian Salomone782f842018-07-31 13:53:11 -040021 if (this->classID() != that.classID()) {
bsalomonbf877302015-09-22 09:06:13 -070022 return false;
23 }
Brian Osman9cf98dc2020-07-01 17:21:27 -040024 if (this->usesVaryingCoordsDirectly() != that.usesVaryingCoordsDirectly()) {
bsalomonbf877302015-09-22 09:06:13 -070025 return false;
26 }
27 if (!this->onIsEqual(that)) {
28 return false;
29 }
30 if (this->numChildProcessors() != that.numChildProcessors()) {
31 return false;
32 }
33 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osman12c5d292020-07-13 16:11:35 -040034 auto thisChild = this->childProcessor(i),
35 thatChild = that .childProcessor(i);
36 if (SkToBool(thisChild) != SkToBool(thatChild)) {
37 return false;
38 }
39 if (thisChild && !thisChild->isEqual(*thatChild)) {
bsalomonbf877302015-09-22 09:06:13 -070040 return false;
41 }
42 }
43 return true;
44}
45
Brian Salomond90b3d32020-07-09 12:04:31 -040046void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) const {
47 this->visitTextureEffects([&func](const GrTextureEffect& te) {
48 bool mipped = (GrSamplerState::Filter::kMipMap == te.samplerState().filter());
49 func(te.view().proxy(), GrMipMapped(mipped));
50 });
51}
52
53void GrFragmentProcessor::visitTextureEffects(
54 const std::function<void(const GrTextureEffect&)>& func) const {
55 if (auto* te = this->asTextureEffect()) {
56 func(*te);
Brian Salomone782f842018-07-31 13:53:11 -040057 }
Brian Salomond90b3d32020-07-09 12:04:31 -040058 for (auto& child : fChildProcessors) {
Brian Osman12c5d292020-07-13 16:11:35 -040059 if (child) {
60 child->visitTextureEffects(func);
61 }
Brian Salomond90b3d32020-07-09 12:04:31 -040062 }
63}
64
65GrTextureEffect* GrFragmentProcessor::asTextureEffect() {
66 if (this->classID() == kGrTextureEffect_ClassID) {
67 return static_cast<GrTextureEffect*>(this);
68 }
69 return nullptr;
70}
71
72const GrTextureEffect* GrFragmentProcessor::asTextureEffect() const {
73 if (this->classID() == kGrTextureEffect_ClassID) {
74 return static_cast<const GrTextureEffect*>(this);
75 }
76 return nullptr;
Brian Salomone782f842018-07-31 13:53:11 -040077}
78
egdaniel57d3b032015-11-13 11:57:27 -080079GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
80 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070081 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
82 for (int i = 0; i < fChildProcessors.count(); ++i) {
Brian Osman12c5d292020-07-13 16:11:35 -040083 glFragProc->fChildProcessors[i] =
84 fChildProcessors[i] ? fChildProcessors[i]->createGLSLInstance() : nullptr;
bsalomonbf877302015-09-22 09:06:13 -070085 }
86 return glFragProc;
87}
88
Michael Ludwige88320b2020-06-24 09:04:56 -040089void GrFragmentProcessor::addAndPushFlagToChildren(PrivateFlags flag) {
90 // This propagates down, so if we've already marked it, all our children should have it too
91 if (!(fFlags & flag)) {
92 fFlags |= flag;
93 for (auto& child : fChildProcessors) {
Brian Osman12c5d292020-07-13 16:11:35 -040094 if (child) {
95 child->addAndPushFlagToChildren(flag);
96 }
Michael Ludwige88320b2020-06-24 09:04:56 -040097 }
Michael Ludwig9aba6252020-06-22 14:46:36 -040098 }
Michael Ludwige88320b2020-06-24 09:04:56 -040099#ifdef SK_DEBUG
100 for (auto& child : fChildProcessors) {
Brian Osman12c5d292020-07-13 16:11:35 -0400101 SkASSERT(!child || (child->fFlags & flag));
Michael Ludwige88320b2020-06-24 09:04:56 -0400102 }
103#endif
Michael Ludwig9aba6252020-06-22 14:46:36 -0400104}
105
Brian Osman12c5d292020-07-13 16:11:35 -0400106int GrFragmentProcessor::numNonNullChildProcessors() const {
107 return std::count_if(fChildProcessors.begin(), fChildProcessors.end(),
108 [](const auto& c) { return c != nullptr; });
109}
110
Robert Phillips82774f82019-06-20 14:38:27 -0400111#ifdef SK_DEBUG
112bool GrFragmentProcessor::isInstantiated() const {
Brian Salomond90b3d32020-07-09 12:04:31 -0400113 bool result = true;
114 this->visitTextureEffects([&result](const GrTextureEffect& te) {
115 if (!te.texture()) {
116 result = false;
Brian Salomone782f842018-07-31 13:53:11 -0400117 }
Brian Salomond90b3d32020-07-09 12:04:31 -0400118 });
119 return result;
Robert Phillips9bee2e52017-05-29 12:37:20 -0400120}
Robert Phillips82774f82019-06-20 14:38:27 -0400121#endif
Robert Phillips9bee2e52017-05-29 12:37:20 -0400122
Brian Osman12c5d292020-07-13 16:11:35 -0400123void GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
124 SkSL::SampleUsage sampleUsage) {
Brian Osman54867de2020-07-10 14:22:57 -0400125 if (!child) {
Brian Osman12c5d292020-07-13 16:11:35 -0400126 fChildProcessors.push_back(nullptr);
127 return;
Brian Osman54867de2020-07-10 14:22:57 -0400128 }
129
Michael Ludwige88320b2020-06-24 09:04:56 -0400130 // The child should not have been attached to another FP already and not had any sampling
131 // strategy set on it.
Brian Osman54867de2020-07-10 14:22:57 -0400132 SkASSERT(!child->fParent && !child->sampleUsage().isSampled() &&
Michael Ludwige88320b2020-06-24 09:04:56 -0400133 !child->isSampledWithExplicitCoords() && !child->hasPerspectiveTransform());
134
Brian Osman1298bc42020-06-30 13:39:35 -0400135 // If a child is sampled directly (sample(child)), and with a single uniform matrix, we need to
136 // treat it as if it were sampled with multiple matrices (eg variable).
137 bool variableMatrix = sampleUsage.hasVariableMatrix() ||
138 (sampleUsage.fPassThrough && sampleUsage.hasUniformMatrix());
139
Michael Ludwig9aba6252020-06-22 14:46:36 -0400140 // Configure child's sampling state first
Brian Osman1298bc42020-06-30 13:39:35 -0400141 child->fUsage = sampleUsage;
142
143 // When an FP is sampled using variable matrix expressions, it is effectively being sampled
144 // explicitly, except that the call site will automatically evaluate the matrix expression to
145 // produce the float2 passed into this FP.
146 if (sampleUsage.fExplicitCoords || variableMatrix) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400147 child->addAndPushFlagToChildren(kSampledWithExplicitCoords_Flag);
Michael Ludwig9aba6252020-06-22 14:46:36 -0400148 }
Brian Osman1298bc42020-06-30 13:39:35 -0400149
150 // Push perspective matrix type to children
151 if (sampleUsage.fHasPerspective) {
152 child->addAndPushFlagToChildren(kNetTransformHasPerspective_Flag);
Michael Ludwig9aba6252020-06-22 14:46:36 -0400153 }
154
Brian Osman1298bc42020-06-30 13:39:35 -0400155 // If the child is sampled with a variable matrix expression, auto-generated code in
156 // invokeChildWithMatrix() for this FP will refer to the local coordinates.
157 if (variableMatrix) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400158 this->setUsesSampleCoordsDirectly();
159 }
160
161 // If the child is not sampled explicitly and not already accessing sample coords directly
162 // (through reference or variable matrix expansion), then mark that this FP tree relies on
163 // coordinates at a lower level. If the child is sampled with explicit coordinates and
164 // there isn't any other direct reference to the sample coords, we halt the upwards propagation
165 // because it means this FP is determining coordinates on its own.
166 if (!child->isSampledWithExplicitCoords()) {
167 if ((child->fFlags & kUsesSampleCoordsDirectly_Flag ||
168 child->fFlags & kUsesSampleCoordsIndirectly_Flag)) {
169 fFlags |= kUsesSampleCoordsIndirectly_Flag;
170 }
171 }
172
Chris Daltond7291ba2019-03-07 14:17:03 -0700173 fRequestedFeatures |= child->fRequestedFeatures;
bsalomonbf877302015-09-22 09:06:13 -0700174
Michael Ludwige88320b2020-06-24 09:04:56 -0400175 // Record that the child is attached to us; this FP is the source of any uniform data needed
176 // to evaluate the child sample matrix.
177 child->fParent = this;
Brian Salomonaff329b2017-08-11 09:40:37 -0400178 fChildProcessors.push_back(std::move(child));
Michael Ludwige88320b2020-06-24 09:04:56 -0400179
180 // Sanity check: our sample strategy comes from a parent we shouldn't have yet.
181 SkASSERT(!this->isSampledWithExplicitCoords() && !this->hasPerspectiveTransform() &&
Brian Osman1298bc42020-06-30 13:39:35 -0400182 !fUsage.isSampled() && !fParent);
John Stiles3779f442020-06-15 10:48:49 -0400183}
184
John Stiles9ec6b052020-06-15 12:06:10 -0400185void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) {
186 for (int i = 0; i < src.numChildProcessors(); ++i) {
Brian Osman12c5d292020-07-13 16:11:35 -0400187 if (auto fp = src.childProcessor(i)) {
188 this->registerChild(fp->clone(), fp->sampleUsage());
189 } else {
190 this->registerChild(nullptr);
191 }
John Stiles9ec6b052020-06-15 12:06:10 -0400192 }
193}
194
Mike Reed28eaed22018-02-01 11:24:53 -0500195std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulChildByInputAlpha(
Brian Salomonaff329b2017-08-11 09:40:37 -0400196 std::unique_ptr<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700197 if (!fp) {
198 return nullptr;
199 }
John Stiles5c57e882020-06-30 14:05:03 -0400200 return GrXfermodeFragmentProcessor::Make(/*src=*/nullptr, std::move(fp), SkBlendMode::kDstIn);
bsalomonbf877302015-09-22 09:06:13 -0700201}
202
Mike Reed28eaed22018-02-01 11:24:53 -0500203std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
204 std::unique_ptr<GrFragmentProcessor> fp) {
205 if (!fp) {
206 return nullptr;
207 }
John Stiles5c57e882020-06-30 14:05:03 -0400208 return GrXfermodeFragmentProcessor::Make(/*src=*/nullptr, std::move(fp), SkBlendMode::kSrcIn);
Mike Reed28eaed22018-02-01 11:24:53 -0500209}
210
John Stiles7bf26002020-07-13 11:30:12 -0400211std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateAlpha(
212 std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) {
213 auto colorFP = GrConstColorProcessor::Make(color);
214 return GrXfermodeFragmentProcessor::Make(
215 std::move(colorFP), std::move(inputFP), SkBlendMode::kSrcIn,
216 GrXfermodeFragmentProcessor::ComposeBehavior::kSkModeBehavior);
217}
218
John Stiles85894302020-07-13 11:39:52 -0400219std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ModulateRGBA(
220 std::unique_ptr<GrFragmentProcessor> inputFP, const SkPMColor4f& color) {
221 auto colorFP = GrConstColorProcessor::Make(color);
222 return GrXfermodeFragmentProcessor::Make(
223 std::move(colorFP), std::move(inputFP), SkBlendMode::kModulate,
224 GrXfermodeFragmentProcessor::ComposeBehavior::kSkModeBehavior);
225}
226
Brian Osman6f5e9402020-01-22 10:39:31 -0500227std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput(
228 std::unique_ptr<GrFragmentProcessor> fp) {
229 if (!fp) {
230 return nullptr;
231 }
John Stiles5a2a7b32020-06-04 10:57:21 -0400232 return GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/true);
Brian Osman6f5e9402020-01-22 10:39:31 -0500233}
234
Brian Salomonaff329b2017-08-11 09:40:37 -0400235std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
236 std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) {
Brian Osmance425512017-03-22 14:37:50 -0400237 class SwizzleFragmentProcessor : public GrFragmentProcessor {
238 public:
John Stileseed56f02020-06-04 13:30:51 -0400239 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
240 const GrSwizzle& swizzle) {
241 return std::unique_ptr<GrFragmentProcessor>(
242 new SwizzleFragmentProcessor(std::move(fp), swizzle));
Brian Osmance425512017-03-22 14:37:50 -0400243 }
244
245 const char* name() const override { return "Swizzle"; }
246 const GrSwizzle& swizzle() const { return fSwizzle; }
247
John Stileseed56f02020-06-04 13:30:51 -0400248 std::unique_ptr<GrFragmentProcessor> clone() const override {
Brian Osman12c5d292020-07-13 16:11:35 -0400249 return Make(this->childProcessor(0)->clone(), fSwizzle);
John Stileseed56f02020-06-04 13:30:51 -0400250 }
Brian Salomon216f2e02017-07-25 15:52:51 -0400251
Brian Osmance425512017-03-22 14:37:50 -0400252 private:
John Stileseed56f02020-06-04 13:30:51 -0400253 SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle)
254 : INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get()))
255 , fSwizzle(swizzle) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400256 this->registerChild(std::move(fp));
John Stileseed56f02020-06-04 13:30:51 -0400257 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400258
Brian Osmance425512017-03-22 14:37:50 -0400259 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
260 class GLFP : public GrGLSLFragmentProcessor {
261 public:
262 void emitCode(EmitArgs& args) override {
Brian Osman6b5dbb42020-07-15 15:31:05 -0400263 SkString childColor = this->invokeChild(0, args);
John Stileseed56f02020-06-04 13:30:51 -0400264
Brian Osmance425512017-03-22 14:37:50 -0400265 const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
266 const GrSwizzle& swizzle = sfp.swizzle();
267 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
268
269 fragBuilder->codeAppendf("%s = %s.%s;",
John Stileseed56f02020-06-04 13:30:51 -0400270 args.fOutputColor, childColor.c_str(), swizzle.asString().c_str());
Brian Osmance425512017-03-22 14:37:50 -0400271 }
272 };
273 return new GLFP;
274 }
275
276 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
277 b->add32(fSwizzle.asKey());
278 }
279
280 bool onIsEqual(const GrFragmentProcessor& other) const override {
281 const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
282 return fSwizzle == sfp.fSwizzle;
283 }
284
Brian Osman1d5b5982018-10-01 13:41:39 -0400285 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
Brian Osmance425512017-03-22 14:37:50 -0400286 return fSwizzle.applyTo(input);
287 }
288
289 GrSwizzle fSwizzle;
290
291 typedef GrFragmentProcessor INHERITED;
292 };
293
294 if (!fp) {
295 return nullptr;
296 }
297 if (GrSwizzle::RGBA() == swizzle) {
298 return fp;
299 }
John Stileseed56f02020-06-04 13:30:51 -0400300 return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
Brian Osmance425512017-03-22 14:37:50 -0400301}
302
Brian Salomonaff329b2017-08-11 09:40:37 -0400303std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
304 std::unique_ptr<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700305 class PremulFragmentProcessor : public GrFragmentProcessor {
306 public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400307 static std::unique_ptr<GrFragmentProcessor> Make(
308 std::unique_ptr<GrFragmentProcessor> processor) {
309 return std::unique_ptr<GrFragmentProcessor>(
310 new PremulFragmentProcessor(std::move(processor)));
Robert Phillips1c9686b2017-06-30 08:40:28 -0400311 }
312
313 const char* name() const override { return "Premultiply"; }
314
Brian Salomonaff329b2017-08-11 09:40:37 -0400315 std::unique_ptr<GrFragmentProcessor> clone() const override {
Brian Osman12c5d292020-07-13 16:11:35 -0400316 return Make(this->childProcessor(0)->clone());
Brian Salomon216f2e02017-07-25 15:52:51 -0400317 }
318
Robert Phillips1c9686b2017-06-30 08:40:28 -0400319 private:
Brian Salomonaff329b2017-08-11 09:40:37 -0400320 PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400321 : INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400322 this->registerChild(std::move(processor));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700323 }
324
egdaniel57d3b032015-11-13 11:57:27 -0800325 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800326 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700327 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700328 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800329 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Brian Osman6b5dbb42020-07-15 15:31:05 -0400330 SkString temp = this->invokeChild(0, "half4(1)", args);
Brian Osmancddfc5e2020-01-24 10:24:27 -0500331 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, temp.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800332 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
Brian Osmancddfc5e2020-01-24 10:24:27 -0500333 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800334 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700335 }
336 };
337 return new GLFP;
338 }
339
Brian Salomon94efbf52016-11-29 13:43:05 -0500340 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700341
342 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
343
Brian Salomon587e08f2017-01-27 10:59:27 -0500344 static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
345 OptimizationFlags flags = kNone_OptimizationFlags;
346 if (inner->preservesOpaqueInput()) {
347 flags |= kPreservesOpaqueInput_OptimizationFlag;
348 }
349 if (inner->hasConstantOutputForConstantInput()) {
350 flags |= kConstantOutputForConstantInput_OptimizationFlag;
351 }
352 return flags;
353 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700354
Brian Osman1d5b5982018-10-01 13:41:39 -0400355 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
356 SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
Brian Osmanf28e55d2018-10-03 16:35:54 -0400357 SK_PMColor4fWHITE);
Brian Osman1d5b5982018-10-01 13:41:39 -0400358 SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul();
359 return premulInput * childColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500360 }
361
362 typedef GrFragmentProcessor INHERITED;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700363 };
364 if (!fp) {
365 return nullptr;
366 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400367 return PremulFragmentProcessor::Make(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700368}
369
370//////////////////////////////////////////////////////////////////////////////
371
Brian Salomonaff329b2017-08-11 09:40:37 -0400372std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
Brian Salomonc0d79e52019-04-10 15:02:11 -0400373 std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color, bool useUniform) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400374 if (!fp) {
375 return nullptr;
376 }
Brian Salomonc0d79e52019-04-10 15:02:11 -0400377 return GrOverrideInputFragmentProcessor::Make(std::move(fp), color, useUniform);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700378}
bsalomone25eea42015-09-29 06:38:55 -0700379
Brian Salomonaff329b2017-08-11 09:40:37 -0400380std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
Brian Salomon64f42062020-02-14 10:42:45 -0500381 std::unique_ptr<GrFragmentProcessor> series[], int cnt) {
bsalomone25eea42015-09-29 06:38:55 -0700382 class SeriesFragmentProcessor : public GrFragmentProcessor {
383 public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400384 static std::unique_ptr<GrFragmentProcessor> Make(
385 std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
386 return std::unique_ptr<GrFragmentProcessor>(new SeriesFragmentProcessor(children, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700387 }
388
389 const char* name() const override { return "Series"; }
390
Brian Salomonaff329b2017-08-11 09:40:37 -0400391 std::unique_ptr<GrFragmentProcessor> clone() const override {
392 SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> children(this->numChildProcessors());
Brian Salomon216f2e02017-07-25 15:52:51 -0400393 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osman12c5d292020-07-13 16:11:35 -0400394 if (this->childProcessor(i)) {
395 if (!children.push_back(this->childProcessor(i)->clone())) {
396 return nullptr;
397 }
398 } else {
399 children.push_back(nullptr);
Brian Salomon216f2e02017-07-25 15:52:51 -0400400 }
401 }
402 return Make(children.begin(), this->numChildProcessors());
403 }
404
405 private:
egdaniel57d3b032015-11-13 11:57:27 -0800406 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800407 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700408 public:
bsalomone25eea42015-09-29 06:38:55 -0700409 void emitCode(EmitArgs& args) override {
Brian Osman6b5dbb42020-07-15 15:31:05 -0400410 SkString result = this->invokeChild(0, args);
Brian Osmancddfc5e2020-01-24 10:24:27 -0500411 for (int i = 1; i < this->numChildProcessors(); ++i) {
Brian Osman978693c2020-01-24 14:52:10 -0500412 result = this->invokeChild(i, result.c_str(), args);
bsalomone25eea42015-09-29 06:38:55 -0700413 }
Brian Osmancddfc5e2020-01-24 10:24:27 -0500414 // Copy last output to our output variable
Brian Osman978693c2020-01-24 14:52:10 -0500415 args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, result.c_str());
bsalomone25eea42015-09-29 06:38:55 -0700416 }
417 };
418 return new GLFP;
419 }
Brian Salomon216f2e02017-07-25 15:52:51 -0400420
Brian Salomonaff329b2017-08-11 09:40:37 -0400421 SeriesFragmentProcessor(std::unique_ptr<GrFragmentProcessor>* children, int cnt)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400422 : INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400423 SkASSERT(cnt > 1);
Robert Phillips1c9686b2017-06-30 08:40:28 -0400424 for (int i = 0; i < cnt; ++i) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400425 this->registerChild(std::move(children[i]));
Robert Phillips1c9686b2017-06-30 08:40:28 -0400426 }
427 }
428
Brian Salomonaff329b2017-08-11 09:40:37 -0400429 static OptimizationFlags OptFlags(std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500430 OptimizationFlags flags = kAll_OptimizationFlags;
431 for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
432 flags &= children[i]->optimizationFlags();
433 }
434 return flags;
435 }
Brian Salomon94efbf52016-11-29 13:43:05 -0500436 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700437
438 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
439
Brian Osman1d5b5982018-10-01 13:41:39 -0400440 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
441 SkPMColor4f color = inColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500442 int childCnt = this->numChildProcessors();
443 for (int i = 0; i < childCnt; ++i) {
444 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
445 }
446 return color;
447 }
448
449 typedef GrFragmentProcessor INHERITED;
bsalomone25eea42015-09-29 06:38:55 -0700450 };
451
452 if (!cnt) {
453 return nullptr;
454 }
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500455 if (1 == cnt) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400456 return std::move(series[0]);
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500457 }
bsalomone25eea42015-09-29 06:38:55 -0700458 // Run the through the series, do the invariant output processing, and look for eliminations.
Brian Salomon650ced02017-07-20 16:46:46 -0400459 GrProcessorAnalysisColor inputColor;
460 inputColor.setToUnknown();
Brian Salomon64f42062020-02-14 10:42:45 -0500461 GrColorFragmentProcessorAnalysis info(inputColor, series, cnt);
Brian Salomonaff329b2017-08-11 09:40:37 -0400462 SkTArray<std::unique_ptr<GrFragmentProcessor>> replacementSeries;
Brian Osmanf28e55d2018-10-03 16:35:54 -0400463 SkPMColor4f knownColor;
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500464 int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
465 if (leadingFPsToEliminate) {
John Stiles7c196772020-07-13 10:00:16 -0400466 std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make(knownColor);
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500467 if (leadingFPsToEliminate == cnt) {
468 return colorFP;
469 }
470 cnt = cnt - leadingFPsToEliminate + 1;
bungeman06ca8ec2016-06-09 08:01:03 -0700471 replacementSeries.reserve(cnt);
472 replacementSeries.emplace_back(std::move(colorFP));
473 for (int i = 0; i < cnt - 1; ++i) {
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500474 replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
bsalomone25eea42015-09-29 06:38:55 -0700475 }
bungeman06ca8ec2016-06-09 08:01:03 -0700476 series = replacementSeries.begin();
bsalomone25eea42015-09-29 06:38:55 -0700477 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400478 return SeriesFragmentProcessor::Make(series, cnt);
bsalomone25eea42015-09-29 06:38:55 -0700479}
bsalomona624bf32016-09-20 09:12:47 -0700480
481//////////////////////////////////////////////////////////////////////////////
482
Brian Salomon7eabfe82019-12-02 14:20:20 -0500483GrFragmentProcessor::CIter::CIter(const GrPaint& paint) {
Chris Dalton1c548942018-05-22 13:09:48 -0600484 for (int i = paint.numCoverageFragmentProcessors() - 1; i >= 0; --i) {
485 fFPStack.push_back(paint.getCoverageFragmentProcessor(i));
486 }
487 for (int i = paint.numColorFragmentProcessors() - 1; i >= 0; --i) {
488 fFPStack.push_back(paint.getColorFragmentProcessor(i));
489 }
490}
491
Brian Salomon7eabfe82019-12-02 14:20:20 -0500492GrFragmentProcessor::CIter::CIter(const GrPipeline& pipeline) {
Brian Salomonc241b582019-11-27 08:57:17 -0500493 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
494 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
495 }
496}
Brian Salomon87f4d292020-07-09 12:48:38 -0400497
498GrFragmentProcessor::CIter& GrFragmentProcessor::CIter::operator++() {
499 SkASSERT(!fFPStack.empty());
500 const GrFragmentProcessor* back = fFPStack.back();
501 fFPStack.pop_back();
502 for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
Brian Osman12c5d292020-07-13 16:11:35 -0400503 if (auto child = back->childProcessor(i)) {
504 fFPStack.push_back(child);
505 }
Brian Salomon87f4d292020-07-09 12:48:38 -0400506 }
507 return *this;
508}
509