xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrFragmentProcessor.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
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 
11 #include "include/core/SkAlphaType.h"
12 #include "include/core/SkString.h"
13 #include "include/private/SkColorData.h"
14 #include "include/private/SkSLSampleUsage.h"
15 #include "include/private/base/SkAssert.h"
16 #include "include/private/base/SkDebug.h"
17 #include "include/private/base/SkMacros.h"
18 #include "include/private/base/SkTArray.h"
19 #include "include/private/base/SkTo.h"
20 #include "include/private/gpu/ganesh/GrTypesPriv.h"
21 #include "src/gpu/ganesh/GrProcessor.h"
22 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
23 
24 #include <cstdint>
25 #include <functional>
26 #include <memory>
27 #include <string_view>
28 #include <tuple>
29 #include <utility>
30 
31 class GrGLSLFPFragmentBuilder;
32 class GrGLSLProgramDataManager;
33 struct GrShaderCaps;
34 class GrTextureEffect;
35 struct SkPoint;
36 struct SkRect;
37 
38 namespace skgpu {
39 class KeyBuilder;
40 class Swizzle;
41 }
42 
43 /**
44  * Some fragment-processor creation methods have preconditions that might not be satisfied by the
45  * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
46  * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
47  * met, `success` is set to false and the input FP is returned unchanged.
48  */
49 class GrFragmentProcessor;  // IWYU pragma: keep
50 using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
51 
52 /** Provides custom fragment shader code. Fragment processors receive an input position and
53     produce an output color. They may contain uniforms and may have children fragment processors
54     that are sampled.
55  */
56 class GrFragmentProcessor : public GrProcessor {
57 public:
58     /**
59      * Every GrFragmentProcessor must be capable of creating a subclass of ProgramImpl. The
60      * ProgramImpl emits the fragment shader code that implements the GrFragmentProcessor, is
61      * attached to the generated backend API pipeline/program and used to extract uniform data from
62      * GrFragmentProcessor instances.
63      */
64     class ProgramImpl;
65 
66     /** Always returns 'color'. */
67     static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
68 
69     /**
70      *  Returns the input color, modulated by the child's alpha.
71      *
72      *  output = input * child.a
73      */
74     static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
75             std::unique_ptr<GrFragmentProcessor> child);
76 
77     /**
78      *  Invokes child with an opaque version of the input color, then applies the input alpha to
79      *  the result. Used to incorporate paint alpha to the evaluation of an SkShader tree FP.
80      */
81     static std::unique_ptr<GrFragmentProcessor> ApplyPaintAlpha(
82             std::unique_ptr<GrFragmentProcessor> child);
83 
84     /**
85      *  Returns a fragment processor that generates the passed-in color, modulated by the child's
86      *  RGBA color. The child's input color will be the parent's fInputColor. (Pass a null FP to use
87      *  the color from fInputColor instead of a child FP.)
88      */
89     static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
90             std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
91 
92     /**
93      *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
94      *  The parent will ignore its input color and instead feed the passed in color as input to the
95      *  child.
96      */
97     static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
98                                                               const SkPMColor4f&);
99 
100     /**
101      *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
102      *  The parent will simply return the child's color, but disable the coverage-as-alpha
103      *  optimization.
104      */
105     static std::unique_ptr<GrFragmentProcessor> DisableCoverageAsAlpha(
106             std::unique_ptr<GrFragmentProcessor>);
107 
108     /**
109      *  Returns a fragment processor which returns `args.fDestColor`. This is only meaningful in
110      *  contexts like blenders, which use a source and dest color.)
111      */
112     static std::unique_ptr<GrFragmentProcessor> DestColor();
113 
114     /**
115      *  Returns a fragment processor that calls the passed in fragment processor, and then swizzles
116      *  the output.
117      */
118     static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
119                                                               const skgpu::Swizzle&);
120 
121     /**
122      *  Returns a fragment processor that calls the passed in fragment processor, and then clamps
123      *  the output to [0, 1].
124      */
125     static std::unique_ptr<GrFragmentProcessor> ClampOutput(std::unique_ptr<GrFragmentProcessor>);
126 
127     /**
128      * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
129      * This is equivalent to running them in series (`g`, then `f`). This is not the same as
130      * transfer-mode composition; there is no blending step.
131      */
132     static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
133                                                         std::unique_ptr<GrFragmentProcessor> g);
134 
135     /*
136      * Returns a fragment processor that calls the passed in fragment processor, then runs the
137      * resulting color through the supplied color matrix.
138      */
139     static std::unique_ptr<GrFragmentProcessor> ColorMatrix(
140             std::unique_ptr<GrFragmentProcessor> child,
141             const float matrix[20],
142             bool unpremulInput,
143             bool clampRGBOutput,
144             bool premulOutput);
145 
146     /**
147      * Returns a fragment processor that reads back the color on the surface being painted; that is,
148      * sampling this will return the color of the pixel that is currently being painted over.
149      */
150     static std::unique_ptr<GrFragmentProcessor> SurfaceColor();
151 
152     /**
153      * Returns a fragment processor that calls the passed in fragment processor, but evaluates it
154      * in device-space (rather than local space).
155      */
156     static std::unique_ptr<GrFragmentProcessor> DeviceSpace(std::unique_ptr<GrFragmentProcessor>);
157 
158     /**
159      * "Shape" FPs, often used for clipping. Each one evaluates a particular kind of shape (rect,
160      * circle, ellipse), and modulates the coverage of that shape against the results of the input
161      * FP. GrClipEdgeType is used to select inverse/normal fill, and AA or non-AA edges.
162      */
163     static std::unique_ptr<GrFragmentProcessor> Rect(std::unique_ptr<GrFragmentProcessor>,
164                                                      GrClipEdgeType,
165                                                      SkRect);
166 
167     static GrFPResult Circle(std::unique_ptr<GrFragmentProcessor>,
168                              GrClipEdgeType,
169                              SkPoint center,
170                              float radius);
171 
172     static GrFPResult Ellipse(std::unique_ptr<GrFragmentProcessor>,
173                               GrClipEdgeType,
174                               SkPoint center,
175                               SkPoint radii,
176                               const GrShaderCaps&);
177 
178     /**
179      * Returns a fragment processor that calls the passed in fragment processor, but ensures the
180      * entire program is compiled with high-precision types.
181      */
182     static std::unique_ptr<GrFragmentProcessor> HighPrecision(std::unique_ptr<GrFragmentProcessor>);
183 
184     /**
185      * Makes a copy of this fragment processor that draws equivalently to the original.
186      * If the processor has child processors they are cloned as well.
187      */
188     virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
189 
190     // The FP this was registered with as a child function. This will be null if this is a root.
parent()191     const GrFragmentProcessor* parent() const { return fParent; }
192 
193     std::unique_ptr<ProgramImpl> makeProgramImpl() const;
194 
addToKey(const GrShaderCaps & caps,skgpu::KeyBuilder * b)195     void addToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
196         this->onAddToKey(caps, b);
197         for (const auto& child : fChildProcessors) {
198             if (child) {
199                 child->addToKey(caps, b);
200             }
201         }
202     }
203 
numChildProcessors()204     int numChildProcessors() const { return fChildProcessors.size(); }
205     int numNonNullChildProcessors() const;
206 
childProcessor(int index)207     GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
childProcessor(int index)208     const GrFragmentProcessor* childProcessor(int index) const {
209         return fChildProcessors[index].get();
210     }
211 
SkDEBUGCODE(bool isInstantiated ()const;)212     SkDEBUGCODE(bool isInstantiated() const;)
213 
214     /** Do any of the FPs in this tree read back the color from the destination surface? */
215     bool willReadDstColor() const {
216         return SkToBool(fFlags & kWillReadDstColor_Flag);
217     }
218 
219     /** Does the SkSL for this FP take two colors as its input arguments? */
isBlendFunction()220     bool isBlendFunction() const {
221         return SkToBool(fFlags & kIsBlendFunction_Flag);
222     }
223 
224     /**
225      * True if this FP refers directly to the sample coordinate parameter of its function
226      * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is decided at FP-tree construction
227      * time and is not affected by lifting coords to varyings.
228      */
usesSampleCoordsDirectly()229     bool usesSampleCoordsDirectly() const {
230         return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
231     }
232 
233     /**
234      * True if this FP uses its input coordinates or if any descendant FP uses them through a chain
235      * of non-explicit sample usages. (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is
236      * decided at FP-tree construction time and is not affected by lifting coords to varyings.
237      */
usesSampleCoords()238     bool usesSampleCoords() const {
239         return SkToBool(fFlags & (kUsesSampleCoordsDirectly_Flag |
240                                   kUsesSampleCoordsIndirectly_Flag));
241     }
242 
243     // The SampleUsage describing how this FP is invoked by its parent. This only reflects the
244     // immediate sampling from parent to this FP.
sampleUsage()245     const SkSL::SampleUsage& sampleUsage() const {
246         return fUsage;
247     }
248 
249     /**
250      * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
251      * output under the following scenario:
252      *   * all the color fragment processors report true to this query,
253      *   * all the coverage fragment processors report true to this query,
254      *   * the blend mode arithmetic allows for it it.
255      * To be compatible a fragment processor's output must be a modulation of its input color or
256      * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
257      * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
258      * value cannot depend on the input's color channels unless it unpremultiplies the input color
259      * channels by the input alpha.
260      */
compatibleWithCoverageAsAlpha()261     bool compatibleWithCoverageAsAlpha() const {
262         return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
263     }
264 
265     /**
266      * If this is true then all opaque input colors to the processor produce opaque output colors.
267      */
preservesOpaqueInput()268     bool preservesOpaqueInput() const {
269         return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
270     }
271 
272     /**
273      * Tests whether given a constant input color the processor produces a constant output color
274      * (for all fragments). If true outputColor will contain the constant color produces for
275      * inputColor.
276      */
hasConstantOutputForConstantInput(SkPMColor4f inputColor,SkPMColor4f * outputColor)277     bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
278         if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
279             *outputColor = this->constantOutputForConstantInput(inputColor);
280             return true;
281         }
282         return false;
283     }
hasConstantOutputForConstantInput()284     bool hasConstantOutputForConstantInput() const {
285         return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
286     }
287 
clearConstantOutputForConstantInputFlag()288     void clearConstantOutputForConstantInputFlag() {
289         fFlags &= ~kConstantOutputForConstantInput_OptimizationFlag;
290     }
291 
292     /** Returns true if this and other processor conservatively draw identically. It can only return
293         true when the two processor are of the same subclass (i.e. they return the same object from
294         from getFactory()).
295 
296         A return value of true from isEqual() should not be used to test whether the processor would
297         generate the same shader code. To test for identical code generation use addToKey.
298      */
299     bool isEqual(const GrFragmentProcessor& that) const;
300 
301     void visitProxies(const GrVisitProxyFunc&) const;
302 
303     void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
304 
305     void visitWithImpls(const std::function<void(const GrFragmentProcessor&, ProgramImpl&)>&,
306                         ProgramImpl&) const;
307 
308     GrTextureEffect* asTextureEffect();
309     const GrTextureEffect* asTextureEffect() const;
310 
311 #if defined(GPU_TEST_UTILS)
312     // Generates debug info for this processor tree by recursively calling dumpInfo() on this
313     // processor and its children.
314     SkString dumpTreeInfo() const;
315 #endif
316 
317 protected:
318     enum OptimizationFlags : uint32_t {
319         kNone_OptimizationFlags,
320         kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
321         kPreservesOpaqueInput_OptimizationFlag = 0x2,
322         kConstantOutputForConstantInput_OptimizationFlag = 0x4,
323         kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
324                                  kPreservesOpaqueInput_OptimizationFlag |
325                                  kConstantOutputForConstantInput_OptimizationFlag
326     };
SK_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)327     SK_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
328 
329     /**
330      * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
331      * This assumes that the subclass output color will be a modulation of the input color with a
332      * value read from a texture of the passed color type and that the texture contains
333      * premultiplied color or alpha values that are in range.
334      *
335      * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
336      * callers must determine on their own if the sampling uses a decal strategy in any way, in
337      * which case the texture may become transparent regardless of the color type.
338      */
339     static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
340         if (samplingDecal) {
341             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
342         } else {
343             return ModulateForClampedSamplerOptFlags(alphaType);
344         }
345     }
346 
347     // As above, but callers should somehow ensure or assert their sampler still uses clamping
ModulateForClampedSamplerOptFlags(SkAlphaType alphaType)348     static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
349         if (alphaType == kOpaque_SkAlphaType) {
350             return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
351                    kPreservesOpaqueInput_OptimizationFlag;
352         } else {
353             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
354         }
355     }
356 
GrFragmentProcessor(ClassID classID,OptimizationFlags optimizationFlags)357     GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
358             : INHERITED(classID), fFlags(optimizationFlags) {
359         SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
360     }
361 
GrFragmentProcessor(const GrFragmentProcessor & src)362     explicit GrFragmentProcessor(const GrFragmentProcessor& src)
363             : INHERITED(src.classID()), fFlags(src.fFlags) {
364         this->cloneAndRegisterAllChildProcessors(src);
365     }
366 
optimizationFlags()367     OptimizationFlags optimizationFlags() const {
368         return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
369     }
370 
371     /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
ProcessorOptimizationFlags(const GrFragmentProcessor * fp)372     static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
373         return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
374     }
375 
376     /**
377      * This allows one subclass to access another subclass's implementation of
378      * constantOutputForConstantInput. It must only be called when
379      * hasConstantOutputForConstantInput() is known to be true.
380      */
ConstantOutputForConstantInput(const GrFragmentProcessor * fp,const SkPMColor4f & input)381     static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
382                                                       const SkPMColor4f& input) {
383         if (fp) {
384             SkASSERT(fp->hasConstantOutputForConstantInput());
385             return fp->constantOutputForConstantInput(input);
386         } else {
387             return input;
388         }
389     }
390 
391     /**
392      * FragmentProcessor subclasses call this from their constructor to register any child
393      * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
394      * transforms have been added.
395      * This is for processors whose shader code will be composed of nested processors whose output
396      * colors will be combined somehow to produce its output color. Registering these child
397      * processors will allow the ProgramBuilder to automatically handle their transformed coords and
398      * texture accesses and mangle their uniform and output color names.
399      *
400      * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
401      */
402     void registerChild(std::unique_ptr<GrFragmentProcessor> child,
403                        SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
404 
405     /**
406      * This method takes an existing fragment processor, clones all of its children, and registers
407      * the clones as children of this fragment processor.
408      */
409     void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
410 
411     // FP implementations must call this function if their matching ProgramImpl's emitCode()
412     // function uses the EmitArgs::fSampleCoord variable in generated SkSL.
setUsesSampleCoordsDirectly()413     void setUsesSampleCoordsDirectly() {
414         fFlags |= kUsesSampleCoordsDirectly_Flag;
415     }
416 
417     // FP implementations must set this flag if their ProgramImpl's emitCode() function calls
418     // dstColor() to read back the framebuffer.
setWillReadDstColor()419     void setWillReadDstColor() {
420         fFlags |= kWillReadDstColor_Flag;
421     }
422 
423     // FP implementations must set this flag if their ProgramImpl's emitCode() function emits a
424     // blend function (taking two color inputs instead of just one).
setIsBlendFunction()425     void setIsBlendFunction() {
426         fFlags |= kIsBlendFunction_Flag;
427     }
428 
mergeOptimizationFlags(OptimizationFlags flags)429     void mergeOptimizationFlags(OptimizationFlags flags) {
430         SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
431         fFlags &= (flags | ~kAll_OptimizationFlags);
432     }
433 
434 private:
constantOutputForConstantInput(const SkPMColor4f &)435     virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
436         SK_ABORT("Subclass must override this if advertising this optimization.");
437     }
438 
439     /**
440      * Returns a new instance of the appropriate ProgramImpl subclass for the given
441      * GrFragmentProcessor. It will emit the appropriate code and live with the cached program
442      * to setup uniform data for each draw that uses the program.
443      */
444     virtual std::unique_ptr<ProgramImpl> onMakeProgramImpl() const = 0;
445 
446     virtual void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const = 0;
447 
448     /**
449      * Subclass implements this to support isEqual(). It will only be called if it is known that
450      * the two processors are of the same subclass (i.e. have the same ClassID).
451      */
452     virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
453 
454     enum PrivateFlags {
455         kFirstPrivateFlag = kAll_OptimizationFlags + 1,
456 
457         // Propagates up the FP tree to either root or first explicit sample usage.
458         kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,
459 
460         // Does not propagate at all. It means this FP uses its input sample coords in some way.
461         // Note passthrough and matrix sampling of children don't count as a usage of the coords.
462         // Because indirect sampling stops at an explicit sample usage it is imperative that a FP
463         // that calculates explicit coords for its children using its own sample coords sets this.
464         kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,
465 
466         // Does not propagate at all.
467         kIsBlendFunction_Flag = kFirstPrivateFlag << 2,
468 
469         // Propagates up the FP tree to the root.
470         kWillReadDstColor_Flag = kFirstPrivateFlag << 3,
471     };
472 
473     skia_private::STArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
474     const GrFragmentProcessor* fParent = nullptr;
475     uint32_t fFlags = 0;
476     SkSL::SampleUsage fUsage;
477 
478     using INHERITED = GrProcessor;
479 };
480 
481 //////////////////////////////////////////////////////////////////////////////
482 
483 class GrFragmentProcessor::ProgramImpl {
484 public:
485     ProgramImpl() = default;
486 
487     virtual ~ProgramImpl() = default;
488 
489     using UniformHandle = GrGLSLUniformHandler::UniformHandle;
490     using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
491 
492     /** Called when the program stage should insert its code into the shaders. The code in each
493         shader will be in its own block ({}) and so locally scoped names will not collide across
494         stages.
495 
496         @param fragBuilder       Interface used to emit code in the shaders.
497         @param uniformHandler    Interface used for accessing information about our uniforms
498         @param caps              The capabilities of the GPU which will render this FP
499         @param fp                The processor that generated this program stage.
500         @param inputColor        A half4 that holds the input color to the stage in the FS (or the
501                                  source color, for blend processors). nullptr inputs are converted
502                                  to "half4(1.0)" (solid white) during construction.
503                                  TODO: Better system for communicating optimization info
504                                  (e.g. input color is solid white, trans black, known to be opaque,
505                                  etc.) that allows the processor to communicate back similar known
506                                  info about its output.
507         @param destColor         A half4 that holds the dest color to the stage. Only meaningful
508                                  when the "is blend processor" FP flag is set.
509         @param sampleCoord       The name of a local coord reference to a float2 variable. Only
510                                  meaningful when the "references sample coords" FP flag is set.
511      */
512     struct EmitArgs {
EmitArgsEmitArgs513         EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
514                  GrGLSLUniformHandler* uniformHandler,
515                  const GrShaderCaps* caps,
516                  const GrFragmentProcessor& fp,
517                  const char* inputColor,
518                  const char* destColor,
519                  const char* sampleCoord)
520                 : fFragBuilder(fragBuilder)
521                 , fUniformHandler(uniformHandler)
522                 , fShaderCaps(caps)
523                 , fFp(fp)
524                 , fInputColor(inputColor ? inputColor : "half4(1.0)")
525                 , fDestColor(destColor)
526                 , fSampleCoord(sampleCoord) {}
527         GrGLSLFPFragmentBuilder* fFragBuilder;
528         GrGLSLUniformHandler* fUniformHandler;
529         const GrShaderCaps* fShaderCaps;
530         const GrFragmentProcessor& fFp;
531         const char* fInputColor;
532         const char* fDestColor;
533         const char* fSampleCoord;
534     };
535 
536     virtual void emitCode(EmitArgs&) = 0;
537 
538     // This does not recurse to any attached child processors. Recursing the entire processor tree
539     // is the responsibility of the caller.
540     void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
541 
numChildProcessors()542     int numChildProcessors() const { return fChildProcessors.size(); }
543 
childProcessor(int index)544     ProgramImpl* childProcessor(int index) const { return fChildProcessors[index].get(); }
545 
setFunctionName(SkString name)546     void setFunctionName(SkString name) {
547         SkASSERT(fFunctionName.isEmpty());
548         fFunctionName = std::move(name);
549     }
550 
functionName()551     const char* functionName() const {
552         SkASSERT(!fFunctionName.isEmpty());
553         return fFunctionName.c_str();
554     }
555 
556     // Invoke the child with the default input and destination colors (solid white)
557     inline SkString invokeChild(int childIndex,
558                                 EmitArgs& parentArgs,
559                                 std::string_view skslCoords = {}) {
560         return this->invokeChild(childIndex,
561                                  /*inputColor=*/nullptr,
562                                  /*destColor=*/nullptr,
563                                  parentArgs,
564                                  skslCoords);
565     }
566 
invokeChildWithMatrix(int childIndex,EmitArgs & parentArgs)567     inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs) {
568         return this->invokeChildWithMatrix(childIndex,
569                                            /*inputColor=*/nullptr,
570                                            /*destColor=*/nullptr,
571                                            parentArgs);
572     }
573 
574     // Invoke the child with the default destination color (solid white)
575     inline SkString invokeChild(int childIndex,
576                                 const char* inputColor,
577                                 EmitArgs& parentArgs,
578                                 std::string_view skslCoords = {}) {
579         return this->invokeChild(childIndex,
580                                  inputColor,
581                                  /*destColor=*/nullptr,
582                                  parentArgs,
583                                  skslCoords);
584     }
585 
invokeChildWithMatrix(int childIndex,const char * inputColor,EmitArgs & parentArgs)586     inline SkString invokeChildWithMatrix(int childIndex,
587                                           const char* inputColor,
588                                           EmitArgs& parentArgs) {
589         return this->invokeChildWithMatrix(childIndex,
590                                            inputColor,
591                                            /*destColor=*/nullptr,
592                                            parentArgs);
593     }
594 
595     /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
596      *  automatically extract the coords and samplers of that child and pass them on to the child's
597      *  emitCode(). Also, any uniforms or functions emitted by the child will have their names
598      *  mangled to prevent redefinitions. The returned string contains the output color (as a call
599      *  to the child's helper function). It is legal to pass nullptr as inputColor, since all
600      *  fragment processors are required to work without an input color.
601      *
602      *  When skslCoords is empty, the child is invoked at the sample coordinates from parentArgs.
603      *  When skslCoords is not empty, is must be an SkSL expression that evaluates to a float2.
604      *  That expression is passed to the child's processor function as the "_coords" argument.
605      */
606     SkString invokeChild(int childIndex,
607                          const char* inputColor,
608                          const char* destColor,
609                          EmitArgs& parentArgs,
610                          std::string_view skslCoords = {});
611 
612     /**
613      * As invokeChild, but transforms the coordinates according to the matrix expression attached
614      * to the child's SampleUsage object. This is only valid if the child is sampled with a
615      * const-uniform matrix.
616      */
617     SkString invokeChildWithMatrix(int childIndex,
618                                    const char* inputColor,
619                                    const char* destColor,
620                                    EmitArgs& parentArgs);
621 
622     /**
623      * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
624      * GLSLFPS. If initialized with an array color followed by coverage processors installed in a
625      * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with
626      * a GrPipeline that produces the same program key.
627      */
628     class Iter {
629     public:
630         Iter(std::unique_ptr<ProgramImpl> fps[], int cnt);
Iter(ProgramImpl & fp)631         Iter(ProgramImpl& fp) { fFPStack.push_back(&fp); }
632 
633         ProgramImpl& operator*() const;
634         ProgramImpl* operator->() const;
635         Iter& operator++();
636         explicit operator bool() const { return !fFPStack.empty(); }
637 
638         // Because each iterator carries a stack we want to avoid copies.
639         Iter(const Iter&) = delete;
640         Iter& operator=(const Iter&) = delete;
641 
642     private:
643         skia_private::STArray<4, ProgramImpl*, true> fFPStack;
644     };
645 
646 private:
647     /**
648      * A ProgramImpl instance can be reused with any GrFragmentProcessor that produces the same
649      * the same key; this function reads data from a GrFragmentProcessor and uploads any
650      * uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
651      * parameter is guaranteed to be of the same type that created this ProgramImpl and
652      * to have an identical key as the one that created this ProgramImpl.
653      */
onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)654     virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
655 
656     // The (mangled) name of our entry-point function
657     SkString fFunctionName;
658 
659     skia_private::TArray<std::unique_ptr<ProgramImpl>, true> fChildProcessors;
660 
661     friend class GrFragmentProcessor;
662 };
663 
664 //////////////////////////////////////////////////////////////////////////////
665 
SK_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)666 SK_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
667 
668 static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
669     return {false, std::move(fp)};
670 }
GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp)671 static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
672     SkASSERT(fp);
673     return {true, std::move(fp)};
674 }
675 // Equivalent to GrFPSuccess except it allows the returned fragment processor to be null.
GrFPNullableSuccess(std::unique_ptr<GrFragmentProcessor> fp)676 static inline GrFPResult GrFPNullableSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
677     return {true, std::move(fp)};
678 }
679 
680 #endif
681