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