blob: 22e511e4c63e946a0efa1566a85b7dd49de895a0 [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/GrCoordTransform.h"
9#include "src/gpu/GrFragmentProcessor.h"
10#include "src/gpu/GrPipeline.h"
11#include "src/gpu/GrProcessorAnalysis.h"
12#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
Brian Osman6f5e9402020-01-22 10:39:31 -050013#include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/effects/generated/GrConstColorProcessor.h"
15#include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
17#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
18#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
19#include "src/gpu/glsl/GrGLSLUniformHandler.h"
bsalomonbf877302015-09-22 09:06:13 -070020
bsalomon7312ff82016-09-12 08:55:38 -070021bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
Brian Salomone782f842018-07-31 13:53:11 -040022 if (this->classID() != that.classID()) {
bsalomonbf877302015-09-22 09:06:13 -070023 return false;
24 }
Brian Salomone782f842018-07-31 13:53:11 -040025 if (this->numTextureSamplers() != that.numTextureSamplers()) {
26 return false;
27 }
28 for (int i = 0; i < this->numTextureSamplers(); ++i) {
29 if (this->textureSampler(i) != that.textureSampler(i)) {
30 return false;
31 }
32 }
bsalomon7312ff82016-09-12 08:55:38 -070033 if (!this->hasSameTransforms(that)) {
bsalomonbf877302015-09-22 09:06:13 -070034 return false;
35 }
36 if (!this->onIsEqual(that)) {
37 return false;
38 }
39 if (this->numChildProcessors() != that.numChildProcessors()) {
40 return false;
41 }
42 for (int i = 0; i < this->numChildProcessors(); ++i) {
bsalomon7312ff82016-09-12 08:55:38 -070043 if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
bsalomonbf877302015-09-22 09:06:13 -070044 return false;
45 }
46 }
47 return true;
48}
49
Chris Dalton7eb5c0f2019-05-23 15:15:47 -060050void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) {
Brian Salomonc241b582019-11-27 08:57:17 -050051 for (auto [sampler, fp] : FPTextureSamplerRange(*this)) {
52 bool mipped = (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter());
Robert Phillipsbd99c0c2019-12-12 13:26:58 +000053 func(sampler.view().proxy(), GrMipMapped(mipped));
Brian Salomone782f842018-07-31 13:53:11 -040054 }
55}
56
egdaniel57d3b032015-11-13 11:57:27 -080057GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
58 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070059 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
60 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080061 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
bsalomonbf877302015-09-22 09:06:13 -070062 }
63 return glFragProc;
64}
65
Brian Salomone782f842018-07-31 13:53:11 -040066const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::textureSampler(int i) const {
67 SkASSERT(i >= 0 && i < fTextureSamplerCnt);
68 return this->onTextureSampler(i);
69}
70
Michael Ludwige88320b2020-06-24 09:04:56 -040071int GrFragmentProcessor::numCoordTransforms() const {
72 if (SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) && fCoordTransforms.empty() &&
73 !this->isSampledWithExplicitCoords()) {
74 // coordTransform(0) will return an implicitly defined coord transform so that varyings are
75 // added for this FP in order to support const/uniform sample matrix lifting.
76 return 1;
77 } else {
78 return fCoordTransforms.count();
79 }
80}
81
82const GrCoordTransform& GrFragmentProcessor::coordTransform(int i) const {
83 SkASSERT(i >= 0 && i < this->numCoordTransforms());
84 if (SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) && fCoordTransforms.empty() &&
85 !this->isSampledWithExplicitCoords()) {
86 SkASSERT(i == 0);
87
88 // as things stand, matrices only work when there's a coord transform, so we need to add
89 // an identity transform to keep the downstream code happy
90 static const GrCoordTransform kImplicitIdentity;
91 return kImplicitIdentity;
92 } else {
93 return *fCoordTransforms[i];
94 }
95}
96
Ethan Nicholasd4efe682019-08-29 16:10:13 -040097void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) {
bsalomonbf877302015-09-22 09:06:13 -070098 fCoordTransforms.push_back(transform);
Ethan Nicholas7ef777e2020-02-12 13:06:27 -050099 fFlags |= kHasCoordTransforms_Flag;
bsalomonbf877302015-09-22 09:06:13 -0700100}
101
Ethan Nicholasd3a95c22020-06-03 13:24:46 -0400102void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix newMatrix) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400103 SkASSERT(!newMatrix.isNoOp());
104 SkASSERT(fMatrix.isNoOp());
105
106 fMatrix = newMatrix;
107 // When an FP is sampled using variable matrix expressions, it is effectively being sampled
108 // explicitly, except that the call site will automatically evaluate the matrix expression to
109 // produce the float2 passed into this FP.
110 if (fMatrix.isVariable()) {
111 this->addAndPushFlagToChildren(kSampledWithExplicitCoords_Flag);
Ethan Nicholas58430122020-04-14 09:54:02 -0400112 }
Michael Ludwige88320b2020-06-24 09:04:56 -0400113 // Push perspective matrix type to children
114 if (fMatrix.fHasPerspective) {
115 this->addAndPushFlagToChildren(kNetTransformHasPerspective_Flag);
Ethan Nicholas58430122020-04-14 09:54:02 -0400116 }
117}
118
Michael Ludwige88320b2020-06-24 09:04:56 -0400119void GrFragmentProcessor::addAndPushFlagToChildren(PrivateFlags flag) {
120 // This propagates down, so if we've already marked it, all our children should have it too
121 if (!(fFlags & flag)) {
122 fFlags |= flag;
123 for (auto& child : fChildProcessors) {
124 child->addAndPushFlagToChildren(flag);
125 }
Michael Ludwig9aba6252020-06-22 14:46:36 -0400126 }
Michael Ludwige88320b2020-06-24 09:04:56 -0400127#ifdef SK_DEBUG
128 for (auto& child : fChildProcessors) {
129 SkASSERT(child->fFlags & flag);
130 }
131#endif
Michael Ludwig9aba6252020-06-22 14:46:36 -0400132}
133
Robert Phillips82774f82019-06-20 14:38:27 -0400134#ifdef SK_DEBUG
135bool GrFragmentProcessor::isInstantiated() const {
Brian Salomone782f842018-07-31 13:53:11 -0400136 for (int i = 0; i < fTextureSamplerCnt; ++i) {
Robert Phillips82774f82019-06-20 14:38:27 -0400137 if (!this->textureSampler(i).isInstantiated()) {
Brian Salomone782f842018-07-31 13:53:11 -0400138 return false;
139 }
Robert Phillipsa91e0b72017-05-01 13:12:20 -0400140 }
141
Robert Phillips9bee2e52017-05-29 12:37:20 -0400142 for (int i = 0; i < this->numChildProcessors(); ++i) {
Robert Phillips82774f82019-06-20 14:38:27 -0400143 if (!this->childProcessor(i).isInstantiated()) {
Robert Phillips9bee2e52017-05-29 12:37:20 -0400144 return false;
145 }
146 }
147
148 return true;
149}
Robert Phillips82774f82019-06-20 14:38:27 -0400150#endif
Robert Phillips9bee2e52017-05-29 12:37:20 -0400151
Michael Ludwig9aba6252020-06-22 14:46:36 -0400152int GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
153 SkSL::SampleMatrix sampleMatrix,
154 bool explicitlySampled) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400155 // The child should not have been attached to another FP already and not had any sampling
156 // strategy set on it.
157 SkASSERT(child && !child->fParent && child->sampleMatrix().isNoOp() &&
158 !child->isSampledWithExplicitCoords() && !child->hasPerspectiveTransform());
159
Michael Ludwig9aba6252020-06-22 14:46:36 -0400160 // Configure child's sampling state first
161 if (explicitlySampled) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400162 child->addAndPushFlagToChildren(kSampledWithExplicitCoords_Flag);
Michael Ludwig9aba6252020-06-22 14:46:36 -0400163 }
164 if (sampleMatrix.fKind != SkSL::SampleMatrix::Kind::kNone) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400165 child->setSampleMatrix(sampleMatrix);
166 }
167
Ethan Nicholas7ef777e2020-02-12 13:06:27 -0500168 if (child->fFlags & kHasCoordTransforms_Flag) {
169 fFlags |= kHasCoordTransforms_Flag;
bsalomonbf877302015-09-22 09:06:13 -0700170 }
Michael Ludwige88320b2020-06-24 09:04:56 -0400171
172 if (child->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kVariable) {
173 // Since the child is sampled with a variable matrix expression, auto-generated code in
174 // invokeChildWithMatrix() for this FP will refer to the local coordinates.
175 this->setUsesSampleCoordsDirectly();
176 }
177
178 // If the child is not sampled explicitly and not already accessing sample coords directly
179 // (through reference or variable matrix expansion), then mark that this FP tree relies on
180 // coordinates at a lower level. If the child is sampled with explicit coordinates and
181 // there isn't any other direct reference to the sample coords, we halt the upwards propagation
182 // because it means this FP is determining coordinates on its own.
183 if (!child->isSampledWithExplicitCoords()) {
184 if ((child->fFlags & kUsesSampleCoordsDirectly_Flag ||
185 child->fFlags & kUsesSampleCoordsIndirectly_Flag)) {
186 fFlags |= kUsesSampleCoordsIndirectly_Flag;
187 }
188 }
189
Chris Daltond7291ba2019-03-07 14:17:03 -0700190 fRequestedFeatures |= child->fRequestedFeatures;
bsalomonbf877302015-09-22 09:06:13 -0700191
bungeman06ca8ec2016-06-09 08:01:03 -0700192 int index = fChildProcessors.count();
Michael Ludwige88320b2020-06-24 09:04:56 -0400193 // Record that the child is attached to us; this FP is the source of any uniform data needed
194 // to evaluate the child sample matrix.
195 child->fParent = this;
Brian Salomonaff329b2017-08-11 09:40:37 -0400196 fChildProcessors.push_back(std::move(child));
Michael Ludwige88320b2020-06-24 09:04:56 -0400197
198 // Sanity check: our sample strategy comes from a parent we shouldn't have yet.
199 SkASSERT(!this->isSampledWithExplicitCoords() && !this->hasPerspectiveTransform() &&
200 fMatrix.isNoOp() && !fParent);
bsalomonbf877302015-09-22 09:06:13 -0700201 return index;
202}
203
John Stiles3779f442020-06-15 10:48:49 -0400204int GrFragmentProcessor::cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp) {
205 std::unique_ptr<GrFragmentProcessor> clone = fp.clone();
Michael Ludwig9aba6252020-06-22 14:46:36 -0400206 return this->registerChild(std::move(clone), fp.sampleMatrix(),
207 fp.isSampledWithExplicitCoords());
John Stiles3779f442020-06-15 10:48:49 -0400208}
209
John Stiles9ec6b052020-06-15 12:06:10 -0400210void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) {
211 for (int i = 0; i < src.numChildProcessors(); ++i) {
212 this->cloneAndRegisterChildProcessor(src.childProcessor(i));
213 }
214}
215
bsalomonbf877302015-09-22 09:06:13 -0700216bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
bsalomona624bf32016-09-20 09:12:47 -0700217 if (this->numCoordTransforms() != that.numCoordTransforms()) {
bsalomonbf877302015-09-22 09:06:13 -0700218 return false;
219 }
bsalomona624bf32016-09-20 09:12:47 -0700220 int count = this->numCoordTransforms();
bsalomonbf877302015-09-22 09:06:13 -0700221 for (int i = 0; i < count; ++i) {
Brian Salomon7d8b3972019-11-26 22:34:44 -0500222 if (!this->coordTransform(i).hasSameEffectiveMatrix(that.coordTransform(i))) {
bsalomonbf877302015-09-22 09:06:13 -0700223 return false;
224 }
225 }
226 return true;
227}
228
Mike Reed28eaed22018-02-01 11:24:53 -0500229std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulChildByInputAlpha(
Brian Salomonaff329b2017-08-11 09:40:37 -0400230 std::unique_ptr<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700231 if (!fp) {
232 return nullptr;
233 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400234 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
bsalomonbf877302015-09-22 09:06:13 -0700235}
236
Mike Reed28eaed22018-02-01 11:24:53 -0500237std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
238 std::unique_ptr<GrFragmentProcessor> fp) {
239 if (!fp) {
240 return nullptr;
241 }
242 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kSrcIn);
243}
244
Brian Osman6f5e9402020-01-22 10:39:31 -0500245std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput(
246 std::unique_ptr<GrFragmentProcessor> fp) {
247 if (!fp) {
248 return nullptr;
249 }
John Stiles5a2a7b32020-06-04 10:57:21 -0400250 return GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/true);
Brian Osman6f5e9402020-01-22 10:39:31 -0500251}
252
Brian Salomonaff329b2017-08-11 09:40:37 -0400253std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
254 std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) {
Brian Osmance425512017-03-22 14:37:50 -0400255 class SwizzleFragmentProcessor : public GrFragmentProcessor {
256 public:
John Stileseed56f02020-06-04 13:30:51 -0400257 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
258 const GrSwizzle& swizzle) {
259 return std::unique_ptr<GrFragmentProcessor>(
260 new SwizzleFragmentProcessor(std::move(fp), swizzle));
Brian Osmance425512017-03-22 14:37:50 -0400261 }
262
263 const char* name() const override { return "Swizzle"; }
264 const GrSwizzle& swizzle() const { return fSwizzle; }
265
John Stileseed56f02020-06-04 13:30:51 -0400266 std::unique_ptr<GrFragmentProcessor> clone() const override {
267 return Make(this->childProcessor(0).clone(), fSwizzle);
268 }
Brian Salomon216f2e02017-07-25 15:52:51 -0400269
Brian Osmance425512017-03-22 14:37:50 -0400270 private:
John Stileseed56f02020-06-04 13:30:51 -0400271 SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle)
272 : INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get()))
273 , fSwizzle(swizzle) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400274 this->registerChild(std::move(fp));
John Stileseed56f02020-06-04 13:30:51 -0400275 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400276
Brian Osmance425512017-03-22 14:37:50 -0400277 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
278 class GLFP : public GrGLSLFragmentProcessor {
279 public:
280 void emitCode(EmitArgs& args) override {
John Stiles0af87fe2020-06-05 13:33:09 -0400281 SkString childColor = this->invokeChild(0, args.fInputColor, args);
John Stileseed56f02020-06-04 13:30:51 -0400282
Brian Osmance425512017-03-22 14:37:50 -0400283 const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
284 const GrSwizzle& swizzle = sfp.swizzle();
285 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
286
287 fragBuilder->codeAppendf("%s = %s.%s;",
John Stileseed56f02020-06-04 13:30:51 -0400288 args.fOutputColor, childColor.c_str(), swizzle.asString().c_str());
Brian Osmance425512017-03-22 14:37:50 -0400289 }
290 };
291 return new GLFP;
292 }
293
294 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
295 b->add32(fSwizzle.asKey());
296 }
297
298 bool onIsEqual(const GrFragmentProcessor& other) const override {
299 const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
300 return fSwizzle == sfp.fSwizzle;
301 }
302
Brian Osman1d5b5982018-10-01 13:41:39 -0400303 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
Brian Osmance425512017-03-22 14:37:50 -0400304 return fSwizzle.applyTo(input);
305 }
306
307 GrSwizzle fSwizzle;
308
309 typedef GrFragmentProcessor INHERITED;
310 };
311
312 if (!fp) {
313 return nullptr;
314 }
315 if (GrSwizzle::RGBA() == swizzle) {
316 return fp;
317 }
John Stileseed56f02020-06-04 13:30:51 -0400318 return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
Brian Osmance425512017-03-22 14:37:50 -0400319}
320
Brian Salomonaff329b2017-08-11 09:40:37 -0400321std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
322 std::unique_ptr<GrFragmentProcessor> fp) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700323 class PremulFragmentProcessor : public GrFragmentProcessor {
324 public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400325 static std::unique_ptr<GrFragmentProcessor> Make(
326 std::unique_ptr<GrFragmentProcessor> processor) {
327 return std::unique_ptr<GrFragmentProcessor>(
328 new PremulFragmentProcessor(std::move(processor)));
Robert Phillips1c9686b2017-06-30 08:40:28 -0400329 }
330
331 const char* name() const override { return "Premultiply"; }
332
Brian Salomonaff329b2017-08-11 09:40:37 -0400333 std::unique_ptr<GrFragmentProcessor> clone() const override {
Brian Salomon96271cd2017-07-31 16:27:23 -0400334 return Make(this->childProcessor(0).clone());
Brian Salomon216f2e02017-07-25 15:52:51 -0400335 }
336
Robert Phillips1c9686b2017-06-30 08:40:28 -0400337 private:
Brian Salomonaff329b2017-08-11 09:40:37 -0400338 PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400339 : INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400340 this->registerChild(std::move(processor));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700341 }
342
egdaniel57d3b032015-11-13 11:57:27 -0800343 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800344 class GLFP : public GrGLSLFragmentProcessor {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700345 public:
bsalomonf1b7a1d2015-09-28 06:26:28 -0700346 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800347 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Brian Osman978693c2020-01-24 14:52:10 -0500348 SkString temp = this->invokeChild(0, args);
Brian Osmancddfc5e2020-01-24 10:24:27 -0500349 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, temp.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800350 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
Brian Osmancddfc5e2020-01-24 10:24:27 -0500351 args.fInputColor);
egdaniel4ca2e602015-11-18 08:01:26 -0800352 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700353 }
354 };
355 return new GLFP;
356 }
357
Brian Salomon94efbf52016-11-29 13:43:05 -0500358 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomonf1b7a1d2015-09-28 06:26:28 -0700359
360 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
361
Brian Salomon587e08f2017-01-27 10:59:27 -0500362 static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
363 OptimizationFlags flags = kNone_OptimizationFlags;
364 if (inner->preservesOpaqueInput()) {
365 flags |= kPreservesOpaqueInput_OptimizationFlag;
366 }
367 if (inner->hasConstantOutputForConstantInput()) {
368 flags |= kConstantOutputForConstantInput_OptimizationFlag;
369 }
370 return flags;
371 }
bsalomonf1b7a1d2015-09-28 06:26:28 -0700372
Brian Osman1d5b5982018-10-01 13:41:39 -0400373 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
374 SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
Brian Osmanf28e55d2018-10-03 16:35:54 -0400375 SK_PMColor4fWHITE);
Brian Osman1d5b5982018-10-01 13:41:39 -0400376 SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul();
377 return premulInput * childColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500378 }
379
380 typedef GrFragmentProcessor INHERITED;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700381 };
382 if (!fp) {
383 return nullptr;
384 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400385 return PremulFragmentProcessor::Make(std::move(fp));
bsalomonf1b7a1d2015-09-28 06:26:28 -0700386}
387
388//////////////////////////////////////////////////////////////////////////////
389
Brian Salomonaff329b2017-08-11 09:40:37 -0400390std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
Brian Salomonc0d79e52019-04-10 15:02:11 -0400391 std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color, bool useUniform) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400392 if (!fp) {
393 return nullptr;
394 }
Brian Salomonc0d79e52019-04-10 15:02:11 -0400395 return GrOverrideInputFragmentProcessor::Make(std::move(fp), color, useUniform);
bsalomonf1b7a1d2015-09-28 06:26:28 -0700396}
bsalomone25eea42015-09-29 06:38:55 -0700397
Brian Salomonaff329b2017-08-11 09:40:37 -0400398std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
Brian Salomon64f42062020-02-14 10:42:45 -0500399 std::unique_ptr<GrFragmentProcessor> series[], int cnt) {
bsalomone25eea42015-09-29 06:38:55 -0700400 class SeriesFragmentProcessor : public GrFragmentProcessor {
401 public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400402 static std::unique_ptr<GrFragmentProcessor> Make(
403 std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
404 return std::unique_ptr<GrFragmentProcessor>(new SeriesFragmentProcessor(children, cnt));
bsalomone25eea42015-09-29 06:38:55 -0700405 }
406
407 const char* name() const override { return "Series"; }
408
Brian Salomonaff329b2017-08-11 09:40:37 -0400409 std::unique_ptr<GrFragmentProcessor> clone() const override {
410 SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> children(this->numChildProcessors());
Brian Salomon216f2e02017-07-25 15:52:51 -0400411 for (int i = 0; i < this->numChildProcessors(); ++i) {
412 if (!children.push_back(this->childProcessor(i).clone())) {
413 return nullptr;
414 }
415 }
416 return Make(children.begin(), this->numChildProcessors());
417 }
418
419 private:
egdaniel57d3b032015-11-13 11:57:27 -0800420 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
egdaniel64c47282015-11-13 06:54:19 -0800421 class GLFP : public GrGLSLFragmentProcessor {
bsalomone25eea42015-09-29 06:38:55 -0700422 public:
bsalomone25eea42015-09-29 06:38:55 -0700423 void emitCode(EmitArgs& args) override {
dvonbeckca9eeab2016-07-06 12:00:06 -0700424 // First guy's input might be nil.
Brian Osman978693c2020-01-24 14:52:10 -0500425 SkString result = this->invokeChild(0, args.fInputColor, args);
Brian Osmancddfc5e2020-01-24 10:24:27 -0500426 for (int i = 1; i < this->numChildProcessors(); ++i) {
Brian Osman978693c2020-01-24 14:52:10 -0500427 result = this->invokeChild(i, result.c_str(), args);
bsalomone25eea42015-09-29 06:38:55 -0700428 }
Brian Osmancddfc5e2020-01-24 10:24:27 -0500429 // Copy last output to our output variable
Brian Osman978693c2020-01-24 14:52:10 -0500430 args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, result.c_str());
bsalomone25eea42015-09-29 06:38:55 -0700431 }
432 };
433 return new GLFP;
434 }
Brian Salomon216f2e02017-07-25 15:52:51 -0400435
Brian Salomonaff329b2017-08-11 09:40:37 -0400436 SeriesFragmentProcessor(std::unique_ptr<GrFragmentProcessor>* children, int cnt)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400437 : INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400438 SkASSERT(cnt > 1);
Robert Phillips1c9686b2017-06-30 08:40:28 -0400439 for (int i = 0; i < cnt; ++i) {
Michael Ludwig9aba6252020-06-22 14:46:36 -0400440 this->registerChild(std::move(children[i]));
Robert Phillips1c9686b2017-06-30 08:40:28 -0400441 }
442 }
443
Brian Salomonaff329b2017-08-11 09:40:37 -0400444 static OptimizationFlags OptFlags(std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500445 OptimizationFlags flags = kAll_OptimizationFlags;
446 for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
447 flags &= children[i]->optimizationFlags();
448 }
449 return flags;
450 }
Brian Salomon94efbf52016-11-29 13:43:05 -0500451 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bsalomone25eea42015-09-29 06:38:55 -0700452
453 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
454
Brian Osman1d5b5982018-10-01 13:41:39 -0400455 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
456 SkPMColor4f color = inColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500457 int childCnt = this->numChildProcessors();
458 for (int i = 0; i < childCnt; ++i) {
459 color = ConstantOutputForConstantInput(this->childProcessor(i), color);
460 }
461 return color;
462 }
463
464 typedef GrFragmentProcessor INHERITED;
bsalomone25eea42015-09-29 06:38:55 -0700465 };
466
467 if (!cnt) {
468 return nullptr;
469 }
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500470 if (1 == cnt) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400471 return std::move(series[0]);
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500472 }
bsalomone25eea42015-09-29 06:38:55 -0700473 // Run the through the series, do the invariant output processing, and look for eliminations.
Brian Salomon650ced02017-07-20 16:46:46 -0400474 GrProcessorAnalysisColor inputColor;
475 inputColor.setToUnknown();
Brian Salomon64f42062020-02-14 10:42:45 -0500476 GrColorFragmentProcessorAnalysis info(inputColor, series, cnt);
Brian Salomonaff329b2017-08-11 09:40:37 -0400477 SkTArray<std::unique_ptr<GrFragmentProcessor>> replacementSeries;
Brian Osmanf28e55d2018-10-03 16:35:54 -0400478 SkPMColor4f knownColor;
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500479 int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
480 if (leadingFPsToEliminate) {
John Stilese3a39f72020-06-15 13:58:48 -0400481 std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make(
482 /*inputFP=*/nullptr, knownColor, GrConstColorProcessor::InputMode::kIgnore);
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500483 if (leadingFPsToEliminate == cnt) {
484 return colorFP;
485 }
486 cnt = cnt - leadingFPsToEliminate + 1;
bungeman06ca8ec2016-06-09 08:01:03 -0700487 replacementSeries.reserve(cnt);
488 replacementSeries.emplace_back(std::move(colorFP));
489 for (int i = 0; i < cnt - 1; ++i) {
Brian Salomoneec6f7b2017-02-10 14:29:38 -0500490 replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
bsalomone25eea42015-09-29 06:38:55 -0700491 }
bungeman06ca8ec2016-06-09 08:01:03 -0700492 series = replacementSeries.begin();
bsalomone25eea42015-09-29 06:38:55 -0700493 }
Robert Phillips1c9686b2017-06-30 08:40:28 -0400494 return SeriesFragmentProcessor::Make(series, cnt);
bsalomone25eea42015-09-29 06:38:55 -0700495}
bsalomona624bf32016-09-20 09:12:47 -0700496
497//////////////////////////////////////////////////////////////////////////////
498
Brian Salomon7eabfe82019-12-02 14:20:20 -0500499GrFragmentProcessor::CIter::CIter(const GrPaint& paint) {
Chris Dalton1c548942018-05-22 13:09:48 -0600500 for (int i = paint.numCoverageFragmentProcessors() - 1; i >= 0; --i) {
501 fFPStack.push_back(paint.getCoverageFragmentProcessor(i));
502 }
503 for (int i = paint.numColorFragmentProcessors() - 1; i >= 0; --i) {
504 fFPStack.push_back(paint.getColorFragmentProcessor(i));
505 }
506}
507
Brian Salomon7eabfe82019-12-02 14:20:20 -0500508GrFragmentProcessor::CIter::CIter(const GrProcessorSet& set) {
Brian Salomonc241b582019-11-27 08:57:17 -0500509 for (int i = set.numCoverageFragmentProcessors() - 1; i >= 0; --i) {
510 fFPStack.push_back(set.coverageFragmentProcessor(i));
bsalomona624bf32016-09-20 09:12:47 -0700511 }
Brian Salomonc241b582019-11-27 08:57:17 -0500512 for (int i = set.numColorFragmentProcessors() - 1; i >= 0; --i) {
513 fFPStack.push_back(set.colorFragmentProcessor(i));
514 }
515}
516
Brian Salomon7eabfe82019-12-02 14:20:20 -0500517GrFragmentProcessor::CIter::CIter(const GrPipeline& pipeline) {
Brian Salomonc241b582019-11-27 08:57:17 -0500518 for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
519 fFPStack.push_back(&pipeline.getFragmentProcessor(i));
520 }
521}
522
Brian Salomone782f842018-07-31 13:53:11 -0400523///////////////////////////////////////////////////////////////////////////////////////////////////
524
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000525GrFragmentProcessor::TextureSampler::TextureSampler(GrSurfaceProxyView view,
Brian Salomonccb61422020-01-09 10:46:36 -0500526 GrSamplerState samplerState)
527 : fView(std::move(view)), fSamplerState(samplerState) {
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000528 GrSurfaceProxy* proxy = this->proxy();
Greg Danielacf59292019-12-11 13:45:17 -0500529 fSamplerState.setFilterMode(
Brian Osman788b9162020-02-07 10:36:46 -0500530 std::min(samplerState.filter(),
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000531 GrTextureProxy::HighestFilterMode(proxy->backendFormat().textureType())));
Greg Danielacf59292019-12-11 13:45:17 -0500532}
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000533
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000534#if GR_TEST_UTILS
535void GrFragmentProcessor::TextureSampler::set(GrSurfaceProxyView view,
Brian Salomonccb61422020-01-09 10:46:36 -0500536 GrSamplerState samplerState) {
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000537 SkASSERT(view.proxy()->asTextureProxy());
538 fView = std::move(view);
539 fSamplerState = samplerState;
540
541 fSamplerState.setFilterMode(
Brian Osman788b9162020-02-07 10:36:46 -0500542 std::min(samplerState.filter(),
Robert Phillipsbd99c0c2019-12-12 13:26:58 +0000543 GrTextureProxy::HighestFilterMode(this->proxy()->backendFormat().textureType())));
544}
545#endif