blob: 46ed3e0a803ce627e6f4ba22b1fc577f93ae6ca4 [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"
bsalomon6251d172014-10-15 10:50:36 -070015
Chris Dalton1c548942018-05-22 13:09:48 -060016class GrPaint;
bsalomona624bf32016-09-20 09:12:47 -070017class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080018class GrProcessorKeyBuilder;
Brian Salomon94efbf52016-11-29 13:43:05 -050019class GrShaderCaps;
Brian Osmance425512017-03-22 14:37:50 -040020class GrSwizzle;
Brian Salomond90b3d32020-07-09 12:04:31 -040021class GrTextureEffect;
bsalomon6251d172014-10-15 10:50:36 -070022
Brian Osmanb384eb22021-06-24 15:34:08 -040023/**
24 * Some fragment-processor creation methods have preconditions that might not be satisfied by the
25 * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
26 * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
27 * met, `success` is set to false and the input FP is returned unchanged.
28 */
29class GrFragmentProcessor;
30using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
31
Brian Salomon354147a2021-04-14 11:15:05 -040032/** Provides custom fragment shader code. Fragment processors receive an input position and
33 produce an output color. They may contain uniforms and may have children fragment processors
34 that are sampled.
bsalomon6251d172014-10-15 10:50:36 -070035 */
Brian Salomone782f842018-07-31 13:53:11 -040036class GrFragmentProcessor : public GrProcessor {
bsalomon6251d172014-10-15 10:50:36 -070037public:
Brian Salomon3176e862021-08-09 11:23:04 -040038 /**
39 * Any GrFragmentProcessor is capable of creating a subclass of ProgramImpl. The ProgramImpl
40 * emits the fragment shader code that implements the GrFragmentProcessor, is attached to the
41 * generated backend API pipeline/program and used to extract uniform data from
42 * GrFragmentProcessor instances.
43 */
44 class ProgramImpl;
45
Brian Salomon354147a2021-04-14 11:15:05 -040046 /** Always returns 'color'. */
47 static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
48
bsalomon87ba62e2015-09-22 06:41:59 -070049 /**
50 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
51 * only consider the input color's alpha. However, there is a competing desire to have reusable
52 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
53 * color is considered. This function exists to filter the input color and pass it to a FP. It
54 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
55 * input alpha. The passed in FP will not receive an input color.
56 */
Mike Reed28eaed22018-02-01 11:24:53 -050057 static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
58 std::unique_ptr<GrFragmentProcessor> child);
59
60 /**
61 * Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
62 * the input modulated by the child's alpha. The passed in FP will not receive an input color.
63 *
64 * output = input * child.a
65 */
66 static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
67 std::unique_ptr<GrFragmentProcessor> child);
bsalomonf1b7a1d2015-09-28 06:26:28 -070068
69 /**
John Stiles7bf26002020-07-13 11:30:12 -040070 * Returns a fragment processor that generates the passed-in color, modulated by the child's
Brian Salomon31580b32021-07-07 16:35:51 -040071 * alpha channel. The child's input color will be the parent's fInputColor. (Pass a null FP to
72 * use the alpha from fInputColor instead of a child FP.)
John Stiles7bf26002020-07-13 11:30:12 -040073 */
74 static std::unique_ptr<GrFragmentProcessor> ModulateAlpha(
75 std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
76
77 /**
John Stiles85894302020-07-13 11:39:52 -040078 * Returns a fragment processor that generates the passed-in color, modulated by the child's
Brian Salomon31580b32021-07-07 16:35:51 -040079 * RGBA color. The child's input color will be the parent's fInputColor. (Pass a null FP to use
80 * the color from fInputColor instead of a child FP.)
John Stiles85894302020-07-13 11:39:52 -040081 */
82 static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
83 std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
84
85 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050086 * This assumes that the input color to the returned processor will be unpremul and that the
87 * passed processor (which becomes the returned processor's child) produces a premul output.
88 * The result of the returned processor is a premul of its input color modulated by the child
89 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070090 */
Brian Salomonaff329b2017-08-11 09:40:37 -040091 static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
92 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070093
94 /**
bsalomone25eea42015-09-29 06:38:55 -070095 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
96 * The parent will ignore its input color and instead feed the passed in color as input to the
97 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070098 */
Brian Salomonaff329b2017-08-11 09:40:37 -040099 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
Brian Salomonc0d79e52019-04-10 15:02:11 -0400100 const SkPMColor4f&,
101 bool useUniform = true);
bsalomon87ba62e2015-09-22 06:41:59 -0700102
bsalomone25eea42015-09-29 06:38:55 -0700103 /**
John Stiles2a6f73c2021-07-29 19:36:20 -0400104 * Returns a fragment processor which samples the passed-in fragment processor using
105 * `args.fDestColor` as its input color. Pass a null FP to access `args.fDestColor` directly.
106 * (This is only meaningful in contexts like blenders, which use a source and dest color.)
107 */
108 static std::unique_ptr<GrFragmentProcessor> UseDestColorAsInput(
109 std::unique_ptr<GrFragmentProcessor>);
110
111 /**
Brian Salomon25af4802021-07-07 16:24:16 -0400112 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
113 * The parent will unpremul its input color, make it opaque, and pass that as the input to
114 * the child. Then the original input alpha is applied to the result of the child.
115 */
116 static std::unique_ptr<GrFragmentProcessor> MakeInputOpaqueAndPostApplyAlpha(
117 std::unique_ptr<GrFragmentProcessor>);
118
119 /**
Brian Osmance425512017-03-22 14:37:50 -0400120 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
121 * the output.
122 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400123 static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
124 const GrSwizzle&);
Brian Osmance425512017-03-22 14:37:50 -0400125
126 /**
Brian Osman8e814b32021-06-17 14:14:26 -0400127 * Returns a fragment processor that calls the passed in fragment processor, and then clamps
128 * the output to [0, 1].
129 */
130 static std::unique_ptr<GrFragmentProcessor> ClampOutput(std::unique_ptr<GrFragmentProcessor>);
131
132 /**
Brian Osman6f5e9402020-01-22 10:39:31 -0500133 * Returns a fragment processor that calls the passed in fragment processor, and then ensures
134 * the output is a valid premul color by clamping RGB to [0, A].
135 */
136 static std::unique_ptr<GrFragmentProcessor> ClampPremulOutput(
137 std::unique_ptr<GrFragmentProcessor>);
138
139 /**
John Stiles024d7452020-07-22 19:07:15 -0400140 * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
Brian Osmanc5422d02021-03-12 16:06:35 -0500141 * This is equivalent to running them in series (`g`, then `f`). This is not the same as
142 * transfer-mode composition; there is no blending step.
John Stiles024d7452020-07-22 19:07:15 -0400143 */
144 static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
145 std::unique_ptr<GrFragmentProcessor> g);
146
Brian Osman48f83fd2021-06-23 15:51:26 +0000147 /*
148 * Returns a fragment processor that calls the passed in fragment processor, then runs the
149 * resulting color through the supplied color matrix.
150 */
151 static std::unique_ptr<GrFragmentProcessor> ColorMatrix(
152 std::unique_ptr<GrFragmentProcessor> child,
153 const float matrix[20],
154 bool unpremulInput,
155 bool clampRGBOutput,
156 bool premulOutput);
157
John Stiles024d7452020-07-22 19:07:15 -0400158 /**
John Stiles5b3aff42021-07-29 17:20:22 -0400159 * Returns a fragment processor that reads back the color on the surface being painted; that is,
160 * sampling this will return the color of the pixel that is currently being painted over.
John Stilesbb04e3d2021-06-04 12:09:11 -0400161 */
John Stiles5b3aff42021-07-29 17:20:22 -0400162 static std::unique_ptr<GrFragmentProcessor> SurfaceColor();
John Stilesbb04e3d2021-06-04 12:09:11 -0400163
164 /**
Brian Osman62905552021-06-21 13:11:01 -0400165 * Returns a fragment processor that calls the passed in fragment processor, but evaluates it
166 * in device-space (rather than local space).
167 */
168 static std::unique_ptr<GrFragmentProcessor> DeviceSpace(std::unique_ptr<GrFragmentProcessor>);
169
170 /**
Brian Osmanb384eb22021-06-24 15:34:08 -0400171 * "Shape" FPs, often used for clipping. Each one evaluates a particular kind of shape (rect,
172 * circle, ellipse), and modulates the coverage of that shape against the results of the input
173 * FP. GrClipEdgeType is used to select inverse/normal fill, and AA or non-AA edges.
174 */
175 static std::unique_ptr<GrFragmentProcessor> Rect(std::unique_ptr<GrFragmentProcessor>,
176 GrClipEdgeType,
177 SkRect);
178
179 static GrFPResult Circle(std::unique_ptr<GrFragmentProcessor>,
180 GrClipEdgeType,
181 SkPoint center,
182 float radius);
183
184 static GrFPResult Ellipse(std::unique_ptr<GrFragmentProcessor>,
185 GrClipEdgeType,
186 SkPoint center,
187 SkPoint radii,
188 const GrShaderCaps&);
189
190 /**
Brian Osman043f0102021-06-30 14:30:34 -0400191 * Returns a fragment processor that calls the passed in fragment processor, but ensures the
192 * entire program is compiled with high-precision types.
193 */
194 static std::unique_ptr<GrFragmentProcessor> HighPrecision(std::unique_ptr<GrFragmentProcessor>);
195
196 /**
Brian Salomon0e05a822017-07-25 09:43:22 -0400197 * Makes a copy of this fragment processor that draws equivalently to the original.
Brian Salomon96271cd2017-07-31 16:27:23 -0400198 * If the processor has child processors they are cloned as well.
Brian Salomon0e05a822017-07-25 09:43:22 -0400199 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400200 virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
Brian Salomon0e05a822017-07-25 09:43:22 -0400201
Michael Ludwige88320b2020-06-24 09:04:56 -0400202 // The FP this was registered with as a child function. This will be null if this is a root.
203 const GrFragmentProcessor* parent() const { return fParent; }
204
Brian Salomon3176e862021-08-09 11:23:04 -0400205 std::unique_ptr<ProgramImpl> makeProgramImpl() const;
joshualitteb2a6762014-12-04 11:35:33 -0800206
Brian Salomon13b28732021-08-06 15:33:58 -0400207 void addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
208 this->onAddToKey(caps, b);
Brian Osman12c5d292020-07-13 16:11:35 -0400209 for (const auto& child : fChildProcessors) {
210 if (child) {
Brian Salomon13b28732021-08-06 15:33:58 -0400211 child->addToKey(caps, b);
Brian Osman12c5d292020-07-13 16:11:35 -0400212 }
wangyix4b3050b2015-08-04 07:59:37 -0700213 }
214 }
215
wangyix4b3050b2015-08-04 07:59:37 -0700216 int numChildProcessors() const { return fChildProcessors.count(); }
Brian Osman12c5d292020-07-13 16:11:35 -0400217 int numNonNullChildProcessors() const;
wangyix4b3050b2015-08-04 07:59:37 -0700218
Brian Osman12c5d292020-07-13 16:11:35 -0400219 GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
220 const GrFragmentProcessor* childProcessor(int index) const {
221 return fChildProcessors[index].get();
222 }
wangyix4b3050b2015-08-04 07:59:37 -0700223
Robert Phillips82774f82019-06-20 14:38:27 -0400224 SkDEBUGCODE(bool isInstantiated() const;)
Robert Phillips9bee2e52017-05-29 12:37:20 -0400225
John Stilese69f25f2021-06-03 12:23:33 -0400226 /** Do any of the FPs in this tree read back the color from the destination surface? */
227 bool willReadDstColor() const {
228 return SkToBool(fFlags & kWillReadDstColor_Flag);
229 }
230
John Stiles0ce95922021-07-28 22:21:49 -0400231 /** Does the SkSL for this FP take two colors as its input arguments? */
232 bool isBlendFunction() const {
233 return SkToBool(fFlags & kIsBlendFunction_Flag);
234 }
235
Brian Salomon66b500a2021-08-02 12:37:14 -0400236 /**
Michael Ludwige88320b2020-06-24 09:04:56 -0400237 * True if this FP refers directly to the sample coordinate parameter of its function
Brian Salomon66b500a2021-08-02 12:37:14 -0400238 * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is decided at FP-tree construction
239 * time and is not affected by lifting coords to varyings.
Michael Ludwige88320b2020-06-24 09:04:56 -0400240 */
Brian Salomon66b500a2021-08-02 12:37:14 -0400241 bool usesSampleCoordsDirectly() const {
Michael Ludwigfbe28592020-06-26 16:02:15 -0400242 return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
Michael Ludwige88320b2020-06-24 09:04:56 -0400243 }
244
Brian Salomon66b500a2021-08-02 12:37:14 -0400245 /**
246 * True if this FP uses its input coordinates or if any descendant FP uses them through a chain
247 * of non-explicit sample usages. (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is
248 * decided at FP-tree construction time and is not affected by lifting coords to varyings.
249 */
250 bool usesSampleCoords() const {
251 return SkToBool(fFlags & (kUsesSampleCoordsDirectly_Flag |
252 kUsesSampleCoordsIndirectly_Flag));
Brian Salomon7d8b3972019-11-26 22:34:44 -0500253 }
254
Brian Salomon66b500a2021-08-02 12:37:14 -0400255 // The SampleUsage describing how this FP is invoked by its parent. This only reflects the
256 // immediate sampling from parent to this FP.
Brian Osman1298bc42020-06-30 13:39:35 -0400257 const SkSL::SampleUsage& sampleUsage() const {
258 return fUsage;
Ethan Nicholas58430122020-04-14 09:54:02 -0400259 }
260
Brian Salomon587e08f2017-01-27 10:59:27 -0500261 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500262 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
263 * output under the following scenario:
264 * * all the color fragment processors report true to this query,
265 * * all the coverage fragment processors report true to this query,
266 * * the blend mode arithmetic allows for it it.
267 * To be compatible a fragment processor's output must be a modulation of its input color or
268 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
269 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
270 * value cannot depend on the input's color channels unless it unpremultiplies the input color
271 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500272 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500273 bool compatibleWithCoverageAsAlpha() const {
274 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
275 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500276
277 /**
278 * If this is true then all opaque input colors to the processor produce opaque output colors.
279 */
280 bool preservesOpaqueInput() const {
281 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
282 }
283
284 /**
285 * Tests whether given a constant input color the processor produces a constant output color
286 * (for all fragments). If true outputColor will contain the constant color produces for
287 * inputColor.
288 */
Brian Osman1d5b5982018-10-01 13:41:39 -0400289 bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
Brian Salomon587e08f2017-01-27 10:59:27 -0500290 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
291 *outputColor = this->constantOutputForConstantInput(inputColor);
292 return true;
293 }
294 return false;
295 }
296 bool hasConstantOutputForConstantInput() const {
297 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
298 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700299
joshualitteb2a6762014-12-04 11:35:33 -0800300 /** Returns true if this and other processor conservatively draw identically. It can only return
301 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700302 from getFactory()).
303
joshualitteb2a6762014-12-04 11:35:33 -0800304 A return value of true from isEqual() should not be used to test whether the processor would
Brian Salomon13b28732021-08-06 15:33:58 -0400305 generate the same shader code. To test for identical code generation use addToKey.
egdaniel57d3b032015-11-13 11:57:27 -0800306 */
bsalomon7312ff82016-09-12 08:55:38 -0700307 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700308
Robert Phillips294723d2021-06-17 09:23:58 -0400309 void visitProxies(const GrVisitProxyFunc&) const;
Brian Salomond90b3d32020-07-09 12:04:31 -0400310
311 void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
312
Brian Salomon3176e862021-08-09 11:23:04 -0400313 void visitWithImpls(const std::function<void(const GrFragmentProcessor&, ProgramImpl&)>&,
314 ProgramImpl&) const;
Brian Salomon91398032021-08-05 10:02:08 -0400315
Brian Salomond90b3d32020-07-09 12:04:31 -0400316 GrTextureEffect* asTextureEffect();
317 const GrTextureEffect* asTextureEffect() const;
bsalomona624bf32016-09-20 09:12:47 -0700318
John Stiles8d9bf642020-08-12 15:07:45 -0400319#if GR_TEST_UTILS
John Stilesba1879d2020-08-11 13:58:32 -0400320 // Generates debug info for this processor tree by recursively calling dumpInfo() on this
321 // processor and its children.
322 SkString dumpTreeInfo() const;
John Stilesba1879d2020-08-11 13:58:32 -0400323#endif
324
bsalomon6251d172014-10-15 10:50:36 -0700325protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500326 enum OptimizationFlags : uint32_t {
327 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500328 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500329 kPreservesOpaqueInput_OptimizationFlag = 0x2,
330 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500331 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500332 kPreservesOpaqueInput_OptimizationFlag |
333 kConstantOutputForConstantInput_OptimizationFlag
334 };
335 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
336
Brian Salomon6cd51b52017-07-26 19:07:15 -0400337 /**
338 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
339 * This assumes that the subclass output color will be a modulation of the input color with a
Greg Danielc594e622019-10-15 14:01:49 -0400340 * value read from a texture of the passed color type and that the texture contains
341 * premultiplied color or alpha values that are in range.
Michael Ludwig257a03d2018-12-13 14:07:07 -0500342 *
343 * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
344 * callers must determine on their own if the sampling uses a decal strategy in any way, in
Greg Danielc594e622019-10-15 14:01:49 -0400345 * which case the texture may become transparent regardless of the color type.
Brian Salomon6cd51b52017-07-26 19:07:15 -0400346 */
Brian Salomonfc118442019-11-22 19:09:27 -0500347 static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
Michael Ludwig257a03d2018-12-13 14:07:07 -0500348 if (samplingDecal) {
349 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
350 } else {
Brian Salomonfc118442019-11-22 19:09:27 -0500351 return ModulateForClampedSamplerOptFlags(alphaType);
Michael Ludwig257a03d2018-12-13 14:07:07 -0500352 }
353 }
354
355 // As above, but callers should somehow ensure or assert their sampler still uses clamping
Brian Salomonfc118442019-11-22 19:09:27 -0500356 static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
357 if (alphaType == kOpaque_SkAlphaType) {
Brian Salomon6cd51b52017-07-26 19:07:15 -0400358 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
359 kPreservesOpaqueInput_OptimizationFlag;
360 } else {
361 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
362 }
363 }
364
Ethan Nicholasabff9562017-10-09 10:54:08 -0400365 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
Brian Salomonb10a6622020-02-20 13:36:01 -0500366 : INHERITED(classID), fFlags(optimizationFlags) {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400367 SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
Brian Salomon587e08f2017-01-27 10:59:27 -0500368 }
369
John Stiles307f8f52021-08-09 15:36:59 -0400370 explicit GrFragmentProcessor(const GrFragmentProcessor& src)
371 : INHERITED(src.classID()), fFlags(src.fFlags) {
372 this->cloneAndRegisterAllChildProcessors(src);
373 }
374
Brian Salomon587e08f2017-01-27 10:59:27 -0500375 OptimizationFlags optimizationFlags() const {
376 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
377 }
378
Brian Salomonc0d79e52019-04-10 15:02:11 -0400379 /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
380 static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
Brian Osman12c5d292020-07-13 16:11:35 -0400381 return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
Brian Salomonc0d79e52019-04-10 15:02:11 -0400382 }
383
Brian Salomon587e08f2017-01-27 10:59:27 -0500384 /**
385 * This allows one subclass to access another subclass's implementation of
386 * constantOutputForConstantInput. It must only be called when
387 * hasConstantOutputForConstantInput() is known to be true.
388 */
Brian Osman12c5d292020-07-13 16:11:35 -0400389 static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
Brian Osman1d5b5982018-10-01 13:41:39 -0400390 const SkPMColor4f& input) {
Brian Osman12c5d292020-07-13 16:11:35 -0400391 if (fp) {
392 SkASSERT(fp->hasConstantOutputForConstantInput());
393 return fp->constantOutputForConstantInput(input);
394 } else {
395 return input;
396 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500397 }
398
bsalomon6251d172014-10-15 10:50:36 -0700399 /**
wangyix58d890b2015-08-12 09:40:47 -0700400 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700401 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
402 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700403 * This is for processors whose shader code will be composed of nested processors whose output
Brian Osman1298bc42020-06-30 13:39:35 -0400404 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700405 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
406 * texture accesses and mangle their uniform and output color names.
Michael Ludwig9aba6252020-06-22 14:46:36 -0400407 *
Brian Osman1298bc42020-06-30 13:39:35 -0400408 * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
wangyix4b3050b2015-08-04 07:59:37 -0700409 */
Brian Osman12c5d292020-07-13 16:11:35 -0400410 void registerChild(std::unique_ptr<GrFragmentProcessor> child,
411 SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
John Stiles3779f442020-06-15 10:48:49 -0400412
John Stiles9ec6b052020-06-15 12:06:10 -0400413 /**
414 * This method takes an existing fragment processor, clones all of its children, and registers
415 * the clones as children of this fragment processor.
416 */
417 void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
418
Brian Salomon3176e862021-08-09 11:23:04 -0400419 // FP implementations must call this function if their matching ProgramImpl's emitCode()
420 // function uses the EmitArgs::fSampleCoord variable in generated SkSL.
Michael Ludwige88320b2020-06-24 09:04:56 -0400421 void setUsesSampleCoordsDirectly() {
422 fFlags |= kUsesSampleCoordsDirectly_Flag;
423 }
424
Brian Salomon3176e862021-08-09 11:23:04 -0400425 // FP implementations must set this flag if their ProgramImpl's emitCode() function calls
426 // dstColor() to read back the framebuffer.
John Stilesbc4bc5f2021-06-11 16:43:15 -0400427 void setWillReadDstColor() {
428 fFlags |= kWillReadDstColor_Flag;
429 }
430
Brian Salomon3176e862021-08-09 11:23:04 -0400431 // FP implementations must set this flag if their ProgramImpl's emitCode() function emits a
432 // blend function (taking two color inputs instead of just one).
John Stiles0ce95922021-07-28 22:21:49 -0400433 void setIsBlendFunction() {
434 fFlags |= kIsBlendFunction_Flag;
435 }
436
Brian Osmanc18a6452021-03-22 11:44:03 -0400437 void mergeOptimizationFlags(OptimizationFlags flags) {
438 SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
439 fFlags &= (flags | ~kAll_OptimizationFlags);
440 }
441
bsalomon6251d172014-10-15 10:50:36 -0700442private:
Brian Osman1d5b5982018-10-01 13:41:39 -0400443 virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400444 SK_ABORT("Subclass must override this if advertising this optimization.");
Brian Salomon587e08f2017-01-27 10:59:27 -0500445 }
446
Brian Salomon3176e862021-08-09 11:23:04 -0400447 /**
448 * Returns a new instance of the appropriate ProgramImpl subclass for the given
449 * GrFragmentProcessor. It will emit the appropriate code and live with the cached program
450 * to setup uniform data for each draw that uses the program.
451 */
452 virtual std::unique_ptr<ProgramImpl> onMakeProgramImpl() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700453
Brian Salomon13b28732021-08-06 15:33:58 -0400454 virtual void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700455
bsalomonde258cd2014-10-15 19:06:21 -0700456 /**
457 * Subclass implements this to support isEqual(). It will only be called if it is known that
Brian Salomon66b500a2021-08-02 12:37:14 -0400458 * the two processors are of the same subclass (i.e. have the same ClassID).
bsalomonde258cd2014-10-15 19:06:21 -0700459 */
460 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
461
Brian Salomon587e08f2017-01-27 10:59:27 -0500462 enum PrivateFlags {
463 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
Michael Ludwige88320b2020-06-24 09:04:56 -0400464
Brian Salomon66b500a2021-08-02 12:37:14 -0400465 // Propagates up the FP tree to either root or first explicit sample usage.
Michael Ludwigfbe28592020-06-26 16:02:15 -0400466 kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,
Michael Ludwige88320b2020-06-24 09:04:56 -0400467
Brian Salomon66b500a2021-08-02 12:37:14 -0400468 // Does not propagate at all. It means this FP uses its input sample coords in some way.
469 // Note passthrough and matrix sampling of children don't count as a usage of the coords.
470 // Because indirect sampling stops at an explicit sample usage it is imperative that a FP
471 // that calculates explicit coords for its children using its own sample coords sets this.
Michael Ludwigfbe28592020-06-26 16:02:15 -0400472 kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,
Brian Salomon66b500a2021-08-02 12:37:14 -0400473
474 // Does not propagate at all.
John Stiles0ce95922021-07-28 22:21:49 -0400475 kIsBlendFunction_Flag = kFirstPrivateFlag << 2,
Michael Ludwige88320b2020-06-24 09:04:56 -0400476
Brian Salomon66b500a2021-08-02 12:37:14 -0400477 // Propagates up the FP tree to the root.
478 kWillReadDstColor_Flag = kFirstPrivateFlag << 3,
Brian Salomon587e08f2017-01-27 10:59:27 -0500479 };
480
Brian Salomonaff329b2017-08-11 09:40:37 -0400481 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
Michael Ludwige88320b2020-06-24 09:04:56 -0400482 const GrFragmentProcessor* fParent = nullptr;
Brian Salomond90b3d32020-07-09 12:04:31 -0400483 uint32_t fFlags = 0;
Brian Osman1298bc42020-06-30 13:39:35 -0400484 SkSL::SampleUsage fUsage;
Ethan Nicholas58430122020-04-14 09:54:02 -0400485
John Stiles7571f9e2020-09-02 22:42:33 -0400486 using INHERITED = GrProcessor;
bsalomon6251d172014-10-15 10:50:36 -0700487};
488
Brian Salomone782f842018-07-31 13:53:11 -0400489//////////////////////////////////////////////////////////////////////////////
490
Brian Salomon587e08f2017-01-27 10:59:27 -0500491GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
492
John Stiles72e57642020-06-24 10:42:35 -0400493static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
494 return {false, std::move(fp)};
495}
496static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
Brian Salomon066f4112021-02-23 10:55:22 -0500497 SkASSERT(fp);
John Stiles72e57642020-06-24 10:42:35 -0400498 return {true, std::move(fp)};
499}
500
bsalomon6251d172014-10-15 10:50:36 -0700501#endif