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