blob: 87eb9cacf90b57496f85e4ab1b5d566fbfdebfc9 [file] [log] [blame]
bsalomon6251d172014-10-15 10:50:36 -07001/*
2 * Copyright 2014 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#ifndef GrFragmentProcessor_DEFINED
9#define GrFragmentProcessor_DEFINED
10
John Stilesf08a82b2020-06-16 16:34:12 -040011#include <tuple>
12
Brian Osman1298bc42020-06-30 13:39:35 -040013#include "include/private/SkSLSampleUsage.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrProcessor.h"
Chris Dalton7eb5c0f2019-05-23 15:15:47 -060015#include "src/gpu/ops/GrOp.h"
bsalomon6251d172014-10-15 10:50:36 -070016
egdaniel64c47282015-11-13 06:54:19 -080017class GrGLSLFragmentProcessor;
Chris Dalton1c548942018-05-22 13:09:48 -060018class GrPaint;
bsalomona624bf32016-09-20 09:12:47 -070019class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080020class GrProcessorKeyBuilder;
Brian Salomon94efbf52016-11-29 13:43:05 -050021class GrShaderCaps;
Brian Osmance425512017-03-22 14:37:50 -040022class GrSwizzle;
Brian Salomond90b3d32020-07-09 12:04:31 -040023class GrTextureEffect;
bsalomon6251d172014-10-15 10:50:36 -070024
Brian Salomon354147a2021-04-14 11:15:05 -040025/** Provides custom fragment shader code. Fragment processors receive an input position and
26 produce an output color. They may contain uniforms and may have children fragment processors
27 that are sampled.
bsalomon6251d172014-10-15 10:50:36 -070028 */
Brian Salomone782f842018-07-31 13:53:11 -040029class GrFragmentProcessor : public GrProcessor {
bsalomon6251d172014-10-15 10:50:36 -070030public:
Brian Salomon354147a2021-04-14 11:15:05 -040031 /** Always returns 'color'. */
32 static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
33
bsalomon87ba62e2015-09-22 06:41:59 -070034 /**
35 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
36 * only consider the input color's alpha. However, there is a competing desire to have reusable
37 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
38 * color is considered. This function exists to filter the input color and pass it to a FP. It
39 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
40 * input alpha. The passed in FP will not receive an input color.
41 */
Mike Reed28eaed22018-02-01 11:24:53 -050042 static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
43 std::unique_ptr<GrFragmentProcessor> child);
44
45 /**
46 * Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
47 * the input modulated by the child's alpha. The passed in FP will not receive an input color.
48 *
49 * output = input * child.a
50 */
51 static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
52 std::unique_ptr<GrFragmentProcessor> child);
bsalomonf1b7a1d2015-09-28 06:26:28 -070053
54 /**
John Stiles7bf26002020-07-13 11:30:12 -040055 * Returns a fragment processor that generates the passed-in color, modulated by the child's
John Stilesda858882020-08-19 16:18:47 -040056 * alpha channel. (Pass a null FP to use the alpha from fInputColor instead of a child FP.)
John Stiles7bf26002020-07-13 11:30:12 -040057 */
58 static std::unique_ptr<GrFragmentProcessor> ModulateAlpha(
59 std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
60
61 /**
John Stiles85894302020-07-13 11:39:52 -040062 * Returns a fragment processor that generates the passed-in color, modulated by the child's
John Stilesda858882020-08-19 16:18:47 -040063 * RGBA color. (Pass a null FP to use the color from fInputColor instead of a child FP.)
John Stiles85894302020-07-13 11:39:52 -040064 */
65 static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
66 std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
67
68 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050069 * This assumes that the input color to the returned processor will be unpremul and that the
70 * passed processor (which becomes the returned processor's child) produces a premul output.
71 * The result of the returned processor is a premul of its input color modulated by the child
72 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070073 */
Brian Salomonaff329b2017-08-11 09:40:37 -040074 static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
75 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070076
77 /**
bsalomone25eea42015-09-29 06:38:55 -070078 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
79 * The parent will ignore its input color and instead feed the passed in color as input to the
80 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070081 */
Brian Salomonaff329b2017-08-11 09:40:37 -040082 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
Brian Salomonc0d79e52019-04-10 15:02:11 -040083 const SkPMColor4f&,
84 bool useUniform = true);
bsalomon87ba62e2015-09-22 06:41:59 -070085
bsalomone25eea42015-09-29 06:38:55 -070086 /**
dvonbeckc526da92016-07-20 11:20:30 -070087 * Returns a fragment processor that premuls the input before calling the passed in fragment
88 * processor.
89 */
Brian Salomonaff329b2017-08-11 09:40:37 -040090 static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
dvonbeckc526da92016-07-20 11:20:30 -070091
92 /**
Brian Osmance425512017-03-22 14:37:50 -040093 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
94 * the output.
95 */
Brian Salomonaff329b2017-08-11 09:40:37 -040096 static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
97 const GrSwizzle&);
Brian Osmance425512017-03-22 14:37:50 -040098
99 /**
Brian Osman6f5e9402020-01-22 10:39:31 -0500100 * Returns a fragment processor that calls the passed in fragment processor, and then ensures
101 * the output is a valid premul color by clamping RGB to [0, A].
102 */
103 static std::unique_ptr<GrFragmentProcessor> ClampPremulOutput(
104 std::unique_ptr<GrFragmentProcessor>);
105
106 /**
John Stiles024d7452020-07-22 19:07:15 -0400107 * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
Brian Osmanc5422d02021-03-12 16:06:35 -0500108 * This is equivalent to running them in series (`g`, then `f`). This is not the same as
109 * transfer-mode composition; there is no blending step.
John Stiles024d7452020-07-22 19:07:15 -0400110 */
111 static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
112 std::unique_ptr<GrFragmentProcessor> g);
113
114 /**
John Stilesbb04e3d2021-06-04 12:09:11 -0400115 * Returns a fragment processor that reads back the destination color; that is, sampling will
116 * return the color of the sample that is currently being painted over.
117 */
118 static std::unique_ptr<GrFragmentProcessor> DestColor();
119
120 /**
Brian Salomon0e05a822017-07-25 09:43:22 -0400121 * Makes a copy of this fragment processor that draws equivalently to the original.
Brian Salomon96271cd2017-07-31 16:27:23 -0400122 * If the processor has child processors they are cloned as well.
Brian Salomon0e05a822017-07-25 09:43:22 -0400123 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400124 virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
Brian Salomon0e05a822017-07-25 09:43:22 -0400125
Michael Ludwige88320b2020-06-24 09:04:56 -0400126 // The FP this was registered with as a child function. This will be null if this is a root.
127 const GrFragmentProcessor* parent() const { return fParent; }
128
Brian Salomon18ab2032021-02-23 10:07:05 -0500129 std::unique_ptr<GrGLSLFragmentProcessor> makeProgramImpl() const;
joshualitteb2a6762014-12-04 11:35:33 -0800130
Brian Salomon94efbf52016-11-29 13:43:05 -0500131 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -0800132 this->onGetGLSLProcessorKey(caps, b);
Brian Osman12c5d292020-07-13 16:11:35 -0400133 for (const auto& child : fChildProcessors) {
134 if (child) {
135 child->getGLSLProcessorKey(caps, b);
136 }
wangyix4b3050b2015-08-04 07:59:37 -0700137 }
138 }
139
Brian Osman9cf98dc2020-07-01 17:21:27 -0400140 int numVaryingCoordsUsed() const { return this->usesVaryingCoordsDirectly() ? 1 : 0; }
joshualittabb52a12015-01-13 15:02:10 -0800141
wangyix4b3050b2015-08-04 07:59:37 -0700142 int numChildProcessors() const { return fChildProcessors.count(); }
Brian Osman12c5d292020-07-13 16:11:35 -0400143 int numNonNullChildProcessors() const;
wangyix4b3050b2015-08-04 07:59:37 -0700144
Brian Osman12c5d292020-07-13 16:11:35 -0400145 GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
146 const GrFragmentProcessor* childProcessor(int index) const {
147 return fChildProcessors[index].get();
148 }
wangyix4b3050b2015-08-04 07:59:37 -0700149
Robert Phillips82774f82019-06-20 14:38:27 -0400150 SkDEBUGCODE(bool isInstantiated() const;)
Robert Phillips9bee2e52017-05-29 12:37:20 -0400151
Michael Ludwige88320b2020-06-24 09:04:56 -0400152 /**
Brian Osman9cf98dc2020-07-01 17:21:27 -0400153 * Does this FP require local coordinates to be produced by the primitive processor? This only
154 * returns true if this FP will directly read those local coordinates. FPs that are sampled
155 * explicitly do not require primitive-generated local coordinates (because the sample
156 * coordinates are supplied by the parent FP).
Michael Ludwige88320b2020-06-24 09:04:56 -0400157 *
158 * If the root of an FP tree does not provide explicit coordinates, the geometry processor
159 * provides the original local coordinates to start. This may be implicit as part of vertex
160 * shader-lifted varyings, or by providing the base local coordinate to the fragment shader.
161 */
Brian Osman9cf98dc2020-07-01 17:21:27 -0400162 bool usesVaryingCoordsDirectly() const {
163 return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) &&
164 !SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
165 }
166
167 /**
168 * Do any of the FPs in this tree require local coordinates to be produced by the primitive
169 * processor? This can return true even if this FP does not refer to sample coordinates, but
170 * true if a descendant FP uses them.
171 */
172 bool usesVaryingCoords() const {
Michael Ludwigfbe28592020-06-26 16:02:15 -0400173 return (SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) ||
Michael Ludwige88320b2020-06-24 09:04:56 -0400174 SkToBool(fFlags & kUsesSampleCoordsIndirectly_Flag)) &&
175 !SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400176 }
177
John Stilese69f25f2021-06-03 12:23:33 -0400178 /** Do any of the FPs in this tree read back the color from the destination surface? */
179 bool willReadDstColor() const {
180 return SkToBool(fFlags & kWillReadDstColor_Flag);
181 }
182
Michael Ludwige88320b2020-06-24 09:04:56 -0400183 /**
184 * True if this FP refers directly to the sample coordinate parameter of its function
185 * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This also returns true if the
186 * coordinate reference comes from autogenerated code invoking 'sample(matrix)' expressions.
187 *
Brian Osman9cf98dc2020-07-01 17:21:27 -0400188 * Unlike usesVaryingCoords(), this can return true whether or not the FP is explicitly
189 * sampled, and does not change based on how the FP is composed. This property is specific to
190 * the FP's function and not the entire program.
Michael Ludwige88320b2020-06-24 09:04:56 -0400191 */
192 bool referencesSampleCoords() const {
Michael Ludwigfbe28592020-06-26 16:02:15 -0400193 return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
Michael Ludwige88320b2020-06-24 09:04:56 -0400194 }
195
196 // True if this FP's parent invokes it with 'sample(float2)' or a variable 'sample(matrix)'
Brian Salomonb10a6622020-02-20 13:36:01 -0500197 bool isSampledWithExplicitCoords() const {
Michael Ludwige88320b2020-06-24 09:04:56 -0400198 return SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
Brian Salomon7d8b3972019-11-26 22:34:44 -0500199 }
200
Michael Ludwige88320b2020-06-24 09:04:56 -0400201 // True if the transform chain from root to this FP introduces perspective into the local
202 // coordinate expression.
203 bool hasPerspectiveTransform() const {
204 return SkToBool(fFlags & kNetTransformHasPerspective_Flag);
205 }
206
Brian Osman1298bc42020-06-30 13:39:35 -0400207 // The SampleUsage describing how this FP is invoked by its parent using 'sample(matrix)'
Michael Ludwige88320b2020-06-24 09:04:56 -0400208 // This only reflects the immediate sampling from parent to this FP
Brian Osman1298bc42020-06-30 13:39:35 -0400209 const SkSL::SampleUsage& sampleUsage() const {
210 return fUsage;
Ethan Nicholas58430122020-04-14 09:54:02 -0400211 }
212
Brian Salomon587e08f2017-01-27 10:59:27 -0500213 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500214 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
215 * output under the following scenario:
216 * * all the color fragment processors report true to this query,
217 * * all the coverage fragment processors report true to this query,
218 * * the blend mode arithmetic allows for it it.
219 * To be compatible a fragment processor's output must be a modulation of its input color or
220 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
221 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
222 * value cannot depend on the input's color channels unless it unpremultiplies the input color
223 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500224 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500225 bool compatibleWithCoverageAsAlpha() const {
226 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
227 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500228
229 /**
230 * If this is true then all opaque input colors to the processor produce opaque output colors.
231 */
232 bool preservesOpaqueInput() const {
233 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
234 }
235
236 /**
237 * Tests whether given a constant input color the processor produces a constant output color
238 * (for all fragments). If true outputColor will contain the constant color produces for
239 * inputColor.
240 */
Brian Osman1d5b5982018-10-01 13:41:39 -0400241 bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
Brian Salomon587e08f2017-01-27 10:59:27 -0500242 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
243 *outputColor = this->constantOutputForConstantInput(inputColor);
244 return true;
245 }
246 return false;
247 }
248 bool hasConstantOutputForConstantInput() const {
249 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
250 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700251
joshualitteb2a6762014-12-04 11:35:33 -0800252 /** Returns true if this and other processor conservatively draw identically. It can only return
253 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700254 from getFactory()).
255
joshualitteb2a6762014-12-04 11:35:33 -0800256 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800257 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
258 */
bsalomon7312ff82016-09-12 08:55:38 -0700259 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700260
Brian Salomond90b3d32020-07-09 12:04:31 -0400261 void visitProxies(const GrOp::VisitProxyFunc& func) const;
262
263 void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
264
265 GrTextureEffect* asTextureEffect();
266 const GrTextureEffect* asTextureEffect() const;
bsalomona624bf32016-09-20 09:12:47 -0700267
John Stiles8d9bf642020-08-12 15:07:45 -0400268#if GR_TEST_UTILS
John Stilesba1879d2020-08-11 13:58:32 -0400269 // Generates debug info for this processor tree by recursively calling dumpInfo() on this
270 // processor and its children.
271 SkString dumpTreeInfo() const;
John Stilesba1879d2020-08-11 13:58:32 -0400272#endif
273
Brian Salomonc241b582019-11-27 08:57:17 -0500274 // A pre-order traversal iterator over a hierarchy of FPs. It can also iterate over all the FP
275 // hierarchies rooted in a GrPaint, GrProcessorSet, or GrPipeline. For these collections it
276 // iterates the tree rooted at each color FP and then each coverage FP.
277 //
278 // An iterator is constructed from one of the srcs and used like this:
279 // for (GrFragmentProcessor::Iter iter(pipeline); iter; ++iter) {
Brian Salomon7eabfe82019-12-02 14:20:20 -0500280 // GrFragmentProcessor& fp = *iter;
Brian Salomonc241b582019-11-27 08:57:17 -0500281 // }
Brian Salomon87f4d292020-07-09 12:48:38 -0400282 // The exit test for the loop is using CIter's operator bool().
Brian Salomon7eabfe82019-12-02 14:20:20 -0500283 // To use a range-for loop instead see CIterRange below.
Brian Salomon7eabfe82019-12-02 14:20:20 -0500284 class CIter;
bsalomona624bf32016-09-20 09:12:47 -0700285
Brian Salomon7eabfe82019-12-02 14:20:20 -0500286 // Used to implement a range-for loop using CIter. Src is one of GrFragmentProcessor,
287 // GrPaint, GrProcessorSet, or GrPipeline. Type aliases for these defined below.
Brian Salomonc241b582019-11-27 08:57:17 -0500288 // Example usage:
Brian Salomon87f4d292020-07-09 12:48:38 -0400289 // for (const auto& fp : GrFragmentProcessor::PaintRange(paint)) {
Brian Salomonc241b582019-11-27 08:57:17 -0500290 // if (fp.usesLocalCoords()) {
291 // ...
292 // }
293 // }
Brian Salomon7eabfe82019-12-02 14:20:20 -0500294 template <typename Src> class CIterRange;
Brian Salomond90b3d32020-07-09 12:04:31 -0400295
Brian Salomon87f4d292020-07-09 12:48:38 -0400296 // We would use template deduction guides for CIter but for:
Brian Salomonc241b582019-11-27 08:57:17 -0500297 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79501
298 // Instead we use these specialized type aliases to make it prettier
Brian Salomon87f4d292020-07-09 12:48:38 -0400299 // to construct CIters for particular sources of FPs.
300 using FPRange = CIterRange<GrFragmentProcessor>;
301 using PaintRange = CIterRange<GrPaint>;
bsalomona624bf32016-09-20 09:12:47 -0700302
Brian Salomon87f4d292020-07-09 12:48:38 -0400303 // Sentinel type for range-for using CIter.
304 class EndCIter {};
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400305
bsalomon6251d172014-10-15 10:50:36 -0700306protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500307 enum OptimizationFlags : uint32_t {
308 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500309 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500310 kPreservesOpaqueInput_OptimizationFlag = 0x2,
311 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500312 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500313 kPreservesOpaqueInput_OptimizationFlag |
314 kConstantOutputForConstantInput_OptimizationFlag
315 };
316 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
317
Brian Salomon6cd51b52017-07-26 19:07:15 -0400318 /**
319 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
320 * This assumes that the subclass output color will be a modulation of the input color with a
Greg Danielc594e622019-10-15 14:01:49 -0400321 * value read from a texture of the passed color type and that the texture contains
322 * premultiplied color or alpha values that are in range.
Michael Ludwig257a03d2018-12-13 14:07:07 -0500323 *
324 * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
325 * callers must determine on their own if the sampling uses a decal strategy in any way, in
Greg Danielc594e622019-10-15 14:01:49 -0400326 * which case the texture may become transparent regardless of the color type.
Brian Salomon6cd51b52017-07-26 19:07:15 -0400327 */
Brian Salomonfc118442019-11-22 19:09:27 -0500328 static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
Michael Ludwig257a03d2018-12-13 14:07:07 -0500329 if (samplingDecal) {
330 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
331 } else {
Brian Salomonfc118442019-11-22 19:09:27 -0500332 return ModulateForClampedSamplerOptFlags(alphaType);
Michael Ludwig257a03d2018-12-13 14:07:07 -0500333 }
334 }
335
336 // As above, but callers should somehow ensure or assert their sampler still uses clamping
Brian Salomonfc118442019-11-22 19:09:27 -0500337 static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
338 if (alphaType == kOpaque_SkAlphaType) {
Brian Salomon6cd51b52017-07-26 19:07:15 -0400339 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
340 kPreservesOpaqueInput_OptimizationFlag;
341 } else {
342 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
343 }
344 }
345
Ethan Nicholasabff9562017-10-09 10:54:08 -0400346 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
Brian Salomonb10a6622020-02-20 13:36:01 -0500347 : INHERITED(classID), fFlags(optimizationFlags) {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400348 SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
Brian Salomon587e08f2017-01-27 10:59:27 -0500349 }
350
351 OptimizationFlags optimizationFlags() const {
352 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
353 }
354
Brian Salomonc0d79e52019-04-10 15:02:11 -0400355 /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
356 static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
Brian Osman12c5d292020-07-13 16:11:35 -0400357 return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
Brian Salomonc0d79e52019-04-10 15:02:11 -0400358 }
359
Brian Salomon587e08f2017-01-27 10:59:27 -0500360 /**
361 * This allows one subclass to access another subclass's implementation of
362 * constantOutputForConstantInput. It must only be called when
363 * hasConstantOutputForConstantInput() is known to be true.
364 */
Brian Osman12c5d292020-07-13 16:11:35 -0400365 static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
Brian Osman1d5b5982018-10-01 13:41:39 -0400366 const SkPMColor4f& input) {
Brian Osman12c5d292020-07-13 16:11:35 -0400367 if (fp) {
368 SkASSERT(fp->hasConstantOutputForConstantInput());
369 return fp->constantOutputForConstantInput(input);
370 } else {
371 return input;
372 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500373 }
374
bsalomon6251d172014-10-15 10:50:36 -0700375 /**
wangyix58d890b2015-08-12 09:40:47 -0700376 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700377 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
378 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700379 * This is for processors whose shader code will be composed of nested processors whose output
Brian Osman1298bc42020-06-30 13:39:35 -0400380 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700381 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
382 * texture accesses and mangle their uniform and output color names.
Michael Ludwig9aba6252020-06-22 14:46:36 -0400383 *
Brian Osman1298bc42020-06-30 13:39:35 -0400384 * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
wangyix4b3050b2015-08-04 07:59:37 -0700385 */
Brian Osman12c5d292020-07-13 16:11:35 -0400386 void registerChild(std::unique_ptr<GrFragmentProcessor> child,
387 SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
John Stiles3779f442020-06-15 10:48:49 -0400388
John Stiles9ec6b052020-06-15 12:06:10 -0400389 /**
390 * This method takes an existing fragment processor, clones all of its children, and registers
391 * the clones as children of this fragment processor.
392 */
393 void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
394
Michael Ludwige88320b2020-06-24 09:04:56 -0400395 // FP implementations must call this function if their matching GrGLSLFragmentProcessor's
396 // emitCode() function uses the EmitArgs::fSampleCoord variable in generated SkSL.
397 void setUsesSampleCoordsDirectly() {
398 fFlags |= kUsesSampleCoordsDirectly_Flag;
399 }
400
John Stilesbc4bc5f2021-06-11 16:43:15 -0400401 // FP implementations must set this flag if their GrGLSLFragmentProcessor's emitCode() function
402 // calls dstColor() to read back the framebuffer.
403 void setWillReadDstColor() {
404 fFlags |= kWillReadDstColor_Flag;
405 }
406
Brian Osmanc18a6452021-03-22 11:44:03 -0400407 void mergeOptimizationFlags(OptimizationFlags flags) {
408 SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
409 fFlags &= (flags | ~kAll_OptimizationFlags);
410 }
411
bsalomon6251d172014-10-15 10:50:36 -0700412private:
Brian Osman1d5b5982018-10-01 13:41:39 -0400413 virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400414 SK_ABORT("Subclass must override this if advertising this optimization.");
Brian Salomon587e08f2017-01-27 10:59:27 -0500415 }
416
wangyixb1daa862015-08-18 11:29:31 -0700417 /** Returns a new instance of the appropriate *GL* implementation class
418 for the given GrFragmentProcessor; caller is responsible for deleting
419 the object. */
Brian Salomon18ab2032021-02-23 10:07:05 -0500420 virtual std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700421
wangyix4b3050b2015-08-04 07:59:37 -0700422 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500423 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700424
bsalomonde258cd2014-10-15 19:06:21 -0700425 /**
426 * Subclass implements this to support isEqual(). It will only be called if it is known that
427 * the two processors are of the same subclass (i.e. they return the same object from
Brian Osman9cf98dc2020-07-01 17:21:27 -0400428 * getFactory()).
bsalomonde258cd2014-10-15 19:06:21 -0700429 */
430 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
431
Brian Salomon587e08f2017-01-27 10:59:27 -0500432 enum PrivateFlags {
433 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
Michael Ludwige88320b2020-06-24 09:04:56 -0400434
John Stilese69f25f2021-06-03 12:23:33 -0400435 // Propagates up the FP tree to the root
Michael Ludwigfbe28592020-06-26 16:02:15 -0400436 kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,
Michael Ludwige88320b2020-06-24 09:04:56 -0400437
438 // Does not propagate at all
Michael Ludwigfbe28592020-06-26 16:02:15 -0400439 kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,
Michael Ludwige88320b2020-06-24 09:04:56 -0400440
441 // Propagates down the FP to all its leaves
Michael Ludwigfbe28592020-06-26 16:02:15 -0400442 kSampledWithExplicitCoords_Flag = kFirstPrivateFlag << 2,
443 kNetTransformHasPerspective_Flag = kFirstPrivateFlag << 3,
John Stilese69f25f2021-06-03 12:23:33 -0400444
445 // Propagates up the FP tree to the root
446 kWillReadDstColor_Flag = kFirstPrivateFlag << 4,
Brian Salomon587e08f2017-01-27 10:59:27 -0500447 };
Michael Ludwige88320b2020-06-24 09:04:56 -0400448 void addAndPushFlagToChildren(PrivateFlags flag);
Brian Salomon587e08f2017-01-27 10:59:27 -0500449
Brian Salomonaff329b2017-08-11 09:40:37 -0400450 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
Michael Ludwige88320b2020-06-24 09:04:56 -0400451 const GrFragmentProcessor* fParent = nullptr;
Brian Salomond90b3d32020-07-09 12:04:31 -0400452 uint32_t fFlags = 0;
Brian Osman1298bc42020-06-30 13:39:35 -0400453 SkSL::SampleUsage fUsage;
Ethan Nicholas58430122020-04-14 09:54:02 -0400454
John Stiles7571f9e2020-09-02 22:42:33 -0400455 using INHERITED = GrProcessor;
bsalomon6251d172014-10-15 10:50:36 -0700456};
457
Brian Salomone782f842018-07-31 13:53:11 -0400458//////////////////////////////////////////////////////////////////////////////
459
Brian Salomon587e08f2017-01-27 10:59:27 -0500460GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
461
Brian Salomonc241b582019-11-27 08:57:17 -0500462//////////////////////////////////////////////////////////////////////////////
463
Brian Salomon87f4d292020-07-09 12:48:38 -0400464class GrFragmentProcessor::CIter {
Brian Salomonc241b582019-11-27 08:57:17 -0500465public:
Brian Salomon87f4d292020-07-09 12:48:38 -0400466 explicit CIter(const GrFragmentProcessor& fp) { fFPStack.push_back(&fp); }
Brian Salomon7eabfe82019-12-02 14:20:20 -0500467 explicit CIter(const GrPaint&);
Brian Salomon7eabfe82019-12-02 14:20:20 -0500468 explicit CIter(const GrPipeline&);
Brian Salomon87f4d292020-07-09 12:48:38 -0400469
470 const GrFragmentProcessor& operator*() const { return *fFPStack.back(); }
471 const GrFragmentProcessor* operator->() const { return fFPStack.back(); }
472
473 CIter& operator++();
474
475 operator bool() const { return !fFPStack.empty(); }
476
477 bool operator!=(const EndCIter&) { return (bool)*this; }
478
479 // Hopefully this does not actually get called because of RVO.
480 CIter(const CIter&) = default;
481
482 // Because each iterator carries a stack we want to avoid copies.
483 CIter& operator=(const CIter&) = delete;
484
485protected:
486 CIter() = delete;
487
488 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
Brian Salomon7eabfe82019-12-02 14:20:20 -0500489};
490
491//////////////////////////////////////////////////////////////////////////////
492
493template <typename Src> class GrFragmentProcessor::CIterRange {
494public:
495 explicit CIterRange(const Src& t) : fT(t) {}
496 CIter begin() const { return CIter(fT); }
Brian Salomon87f4d292020-07-09 12:48:38 -0400497 EndCIter end() const { return EndCIter(); }
Brian Salomonc241b582019-11-27 08:57:17 -0500498
499private:
500 const Src& fT;
501};
502
John Stiles72e57642020-06-24 10:42:35 -0400503/**
504 * Some fragment-processor creation methods have preconditions that might not be satisfied by the
505 * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
506 * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
507 * met, `success` is set to false and the input FP is returned unchanged.
508 */
509using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
510static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
511 return {false, std::move(fp)};
512}
513static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
Brian Salomon066f4112021-02-23 10:55:22 -0500514 SkASSERT(fp);
John Stiles72e57642020-06-24 10:42:35 -0400515 return {true, std::move(fp)};
516}
517
bsalomon6251d172014-10-15 10:50:36 -0700518#endif