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