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