• 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 <tuple>
12 
13 #include "include/private/SkSLSampleUsage.h"
14 #include "src/gpu/GrProcessor.h"
15 #include "src/gpu/ops/GrOp.h"
16 
17 class GrGLSLFragmentProcessor;
18 class GrPaint;
19 class GrPipeline;
20 class GrProcessorKeyBuilder;
21 class GrShaderCaps;
22 class GrSwizzle;
23 class GrTextureEffect;
24 
25 /** Provides custom fragment shader code. Fragment processors receive an input position and
26     produce an output color. They may contain uniforms and may have children fragment processors
27     that are sampled.
28  */
29 class GrFragmentProcessor : public GrProcessor {
30 public:
31     /** Always returns 'color'. */
32     static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
33 
34     /**
35     *  In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
36     *  only consider the input color's alpha. However, there is a competing desire to have reusable
37     *  GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
38     *  color is considered. This function exists to filter the input color and pass it to a FP. It
39     *  does so by returning a parent FP that multiplies the passed in FPs output by the parent's
40     *  input alpha. The passed in FP will not receive an input color.
41     */
42     static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
43             std::unique_ptr<GrFragmentProcessor> child);
44 
45     /**
46      *  Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
47      *  the input modulated by the child's alpha. The passed in FP will not receive an input color.
48      *
49      *  output = input * child.a
50      */
51     static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
52             std::unique_ptr<GrFragmentProcessor> child);
53 
54     /**
55      *  Returns a fragment processor that generates the passed-in color, modulated by the child's
56      *  alpha channel. (Pass a null FP to use the alpha from fInputColor instead of a child FP.)
57      */
58     static std::unique_ptr<GrFragmentProcessor> ModulateAlpha(
59             std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
60 
61     /**
62      *  Returns a fragment processor that generates the passed-in color, modulated by the child's
63      *  RGBA color. (Pass a null FP to use the color from fInputColor instead of a child FP.)
64      */
65     static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
66             std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
67 
68     /**
69      *  This assumes that the input color to the returned processor will be unpremul and that the
70      *  passed processor (which becomes the returned processor's child) produces a premul output.
71      *  The result of the returned processor is a premul of its input color modulated by the child
72      *  processor's premul output.
73      */
74     static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
75             std::unique_ptr<GrFragmentProcessor>);
76 
77     /**
78      *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
79      *  The parent will ignore its input color and instead feed the passed in color as input to the
80      *  child.
81      */
82     static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
83                                                               const SkPMColor4f&,
84                                                               bool useUniform = true);
85 
86     /**
87      *  Returns a fragment processor that premuls the input before calling the passed in fragment
88      *  processor.
89      */
90     static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
91 
92     /**
93      *  Returns a fragment processor that calls the passed in fragment processor, and then swizzles
94      *  the output.
95      */
96     static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
97                                                               const GrSwizzle&);
98 
99     /**
100      *  Returns a fragment processor that calls the passed in fragment processor, and then ensures
101      *  the output is a valid premul color by clamping RGB to [0, A].
102      */
103     static std::unique_ptr<GrFragmentProcessor> ClampPremulOutput(
104             std::unique_ptr<GrFragmentProcessor>);
105 
106     /**
107      * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
108      * This is equivalent to running them in series (`g`, then `f`). This is not the same as
109      * transfer-mode composition; there is no blending step.
110      */
111     static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
112                                                         std::unique_ptr<GrFragmentProcessor> g);
113 
114     /**
115      * Makes a copy of this fragment processor that draws equivalently to the original.
116      * If the processor has child processors they are cloned as well.
117      */
118     virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
119 
120     // The FP this was registered with as a child function. This will be null if this is a root.
parent()121     const GrFragmentProcessor* parent() const { return fParent; }
122 
123     std::unique_ptr<GrGLSLFragmentProcessor> makeProgramImpl() const;
124 
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b)125     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
126         this->onGetGLSLProcessorKey(caps, b);
127         for (const auto& child : fChildProcessors) {
128             if (child) {
129                 child->getGLSLProcessorKey(caps, b);
130             }
131         }
132     }
133 
numVaryingCoordsUsed()134     int numVaryingCoordsUsed() const { return this->usesVaryingCoordsDirectly() ? 1 : 0; }
135 
numChildProcessors()136     int numChildProcessors() const { return fChildProcessors.count(); }
137     int numNonNullChildProcessors() const;
138 
childProcessor(int index)139     GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
childProcessor(int index)140     const GrFragmentProcessor* childProcessor(int index) const {
141         return fChildProcessors[index].get();
142     }
143 
SkDEBUGCODE(bool isInstantiated ()const;)144     SkDEBUGCODE(bool isInstantiated() const;)
145 
146     /**
147      * Does this FP require local coordinates to be produced by the primitive processor? This only
148      * returns true if this FP will directly read those local coordinates. FPs that are sampled
149      * explicitly do not require primitive-generated local coordinates (because the sample
150      * coordinates are supplied by the parent FP).
151      *
152      * If the root of an FP tree does not provide explicit coordinates, the geometry processor
153      * provides the original local coordinates to start. This may be implicit as part of vertex
154      * shader-lifted varyings, or by providing the base local coordinate to the fragment shader.
155      */
156     bool usesVaryingCoordsDirectly() const {
157         return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) &&
158                !SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
159     }
160 
161     /**
162      * Do any of the FPs in this tree require local coordinates to be produced by the primitive
163      * processor? This can return true even if this FP does not refer to sample coordinates, but
164      * true if a descendant FP uses them.
165      */
usesVaryingCoords()166     bool usesVaryingCoords() const {
167         return (SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag) ||
168                 SkToBool(fFlags & kUsesSampleCoordsIndirectly_Flag)) &&
169                !SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
170     }
171 
172    /**
173      * True if this FP refers directly to the sample coordinate parameter of its function
174      * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This also returns true if the
175      * coordinate reference comes from autogenerated code invoking 'sample(matrix)' expressions.
176      *
177      * Unlike usesVaryingCoords(), this can return true whether or not the FP is explicitly
178      * sampled, and does not change based on how the FP is composed. This property is specific to
179      * the FP's function and not the entire program.
180      */
referencesSampleCoords()181     bool referencesSampleCoords() const {
182         return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
183     }
184 
185     // True if this FP's parent invokes it with 'sample(float2)' or a variable 'sample(matrix)'
isSampledWithExplicitCoords()186     bool isSampledWithExplicitCoords() const {
187         return SkToBool(fFlags & kSampledWithExplicitCoords_Flag);
188     }
189 
190     // True if the transform chain from root to this FP introduces perspective into the local
191     // coordinate expression.
hasPerspectiveTransform()192     bool hasPerspectiveTransform() const {
193         return SkToBool(fFlags & kNetTransformHasPerspective_Flag);
194     }
195 
196     // The SampleUsage describing how this FP is invoked by its parent using 'sample(matrix)'
197     // This only reflects the immediate sampling from parent to this FP
sampleUsage()198     const SkSL::SampleUsage& sampleUsage() const {
199         return fUsage;
200     }
201 
202     /**
203      * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
204      * output under the following scenario:
205      *   * all the color fragment processors report true to this query,
206      *   * all the coverage fragment processors report true to this query,
207      *   * the blend mode arithmetic allows for it it.
208      * To be compatible a fragment processor's output must be a modulation of its input color or
209      * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
210      * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
211      * value cannot depend on the input's color channels unless it unpremultiplies the input color
212      * channels by the input alpha.
213      */
compatibleWithCoverageAsAlpha()214     bool compatibleWithCoverageAsAlpha() const {
215         return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
216     }
217 
218     /**
219      * If this is true then all opaque input colors to the processor produce opaque output colors.
220      */
preservesOpaqueInput()221     bool preservesOpaqueInput() const {
222         return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
223     }
224 
225     /**
226      * Tests whether given a constant input color the processor produces a constant output color
227      * (for all fragments). If true outputColor will contain the constant color produces for
228      * inputColor.
229      */
hasConstantOutputForConstantInput(SkPMColor4f inputColor,SkPMColor4f * outputColor)230     bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
231         if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
232             *outputColor = this->constantOutputForConstantInput(inputColor);
233             return true;
234         }
235         return false;
236     }
hasConstantOutputForConstantInput()237     bool hasConstantOutputForConstantInput() const {
238         return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
239     }
240 
241     /** Returns true if this and other processor conservatively draw identically. It can only return
242         true when the two processor are of the same subclass (i.e. they return the same object from
243         from getFactory()).
244 
245         A return value of true from isEqual() should not be used to test whether the processor would
246         generate the same shader code. To test for identical code generation use getGLSLProcessorKey
247      */
248     bool isEqual(const GrFragmentProcessor& that) const;
249 
250     void visitProxies(const GrOp::VisitProxyFunc& func) const;
251 
252     void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
253 
254     GrTextureEffect* asTextureEffect();
255     const GrTextureEffect* asTextureEffect() const;
256 
257 #if GR_TEST_UTILS
258     // Generates debug info for this processor tree by recursively calling dumpInfo() on this
259     // processor and its children.
260     SkString dumpTreeInfo() const;
261 #endif
262 
263     // A pre-order traversal iterator over a hierarchy of FPs. It can also iterate over all the FP
264     // hierarchies rooted in a GrPaint, GrProcessorSet, or GrPipeline. For these collections it
265     // iterates the tree rooted at each color FP and then each coverage FP.
266     //
267     // An iterator is constructed from one of the srcs and used like this:
268     //   for (GrFragmentProcessor::Iter iter(pipeline); iter; ++iter) {
269     //       GrFragmentProcessor& fp = *iter;
270     //   }
271     // The exit test for the loop is using CIter's operator bool().
272     // To use a range-for loop instead see CIterRange below.
273     class CIter;
274 
275     // Used to implement a range-for loop using CIter. Src is one of GrFragmentProcessor,
276     // GrPaint, GrProcessorSet, or GrPipeline. Type aliases for these defined below.
277     // Example usage:
278     //   for (const auto& fp : GrFragmentProcessor::PaintRange(paint)) {
279     //       if (fp.usesLocalCoords()) {
280     //       ...
281     //       }
282     //   }
283     template <typename Src> class CIterRange;
284 
285     // We would use template deduction guides for CIter but for:
286     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79501
287     // Instead we use these specialized type aliases to make it prettier
288     // to construct CIters for particular sources of FPs.
289     using FPRange = CIterRange<GrFragmentProcessor>;
290     using PaintRange = CIterRange<GrPaint>;
291 
292     // Sentinel type for range-for using CIter.
293     class EndCIter {};
294 
295 protected:
296     enum OptimizationFlags : uint32_t {
297         kNone_OptimizationFlags,
298         kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
299         kPreservesOpaqueInput_OptimizationFlag = 0x2,
300         kConstantOutputForConstantInput_OptimizationFlag = 0x4,
301         kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
302                                  kPreservesOpaqueInput_OptimizationFlag |
303                                  kConstantOutputForConstantInput_OptimizationFlag
304     };
GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)305     GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
306 
307     /**
308      * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
309      * This assumes that the subclass output color will be a modulation of the input color with a
310      * value read from a texture of the passed color type and that the texture contains
311      * premultiplied color or alpha values that are in range.
312      *
313      * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
314      * callers must determine on their own if the sampling uses a decal strategy in any way, in
315      * which case the texture may become transparent regardless of the color type.
316      */
317     static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
318         if (samplingDecal) {
319             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
320         } else {
321             return ModulateForClampedSamplerOptFlags(alphaType);
322         }
323     }
324 
325     // As above, but callers should somehow ensure or assert their sampler still uses clamping
ModulateForClampedSamplerOptFlags(SkAlphaType alphaType)326     static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
327         if (alphaType == kOpaque_SkAlphaType) {
328             return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
329                    kPreservesOpaqueInput_OptimizationFlag;
330         } else {
331             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
332         }
333     }
334 
GrFragmentProcessor(ClassID classID,OptimizationFlags optimizationFlags)335     GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
336             : INHERITED(classID), fFlags(optimizationFlags) {
337         SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
338     }
339 
optimizationFlags()340     OptimizationFlags optimizationFlags() const {
341         return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
342     }
343 
344     /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
ProcessorOptimizationFlags(const GrFragmentProcessor * fp)345     static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
346         return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
347     }
348 
349     /**
350      * This allows one subclass to access another subclass's implementation of
351      * constantOutputForConstantInput. It must only be called when
352      * hasConstantOutputForConstantInput() is known to be true.
353      */
ConstantOutputForConstantInput(const GrFragmentProcessor * fp,const SkPMColor4f & input)354     static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
355                                                       const SkPMColor4f& input) {
356         if (fp) {
357             SkASSERT(fp->hasConstantOutputForConstantInput());
358             return fp->constantOutputForConstantInput(input);
359         } else {
360             return input;
361         }
362     }
363 
364     /**
365      * FragmentProcessor subclasses call this from their constructor to register any child
366      * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
367      * transforms have been added.
368      * This is for processors whose shader code will be composed of nested processors whose output
369      * colors will be combined somehow to produce its output color. Registering these child
370      * processors will allow the ProgramBuilder to automatically handle their transformed coords and
371      * texture accesses and mangle their uniform and output color names.
372      *
373      * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
374      */
375     void registerChild(std::unique_ptr<GrFragmentProcessor> child,
376                        SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
377 
378     /**
379      * This method takes an existing fragment processor, clones all of its children, and registers
380      * the clones as children of this fragment processor.
381      */
382     void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
383 
384     // FP implementations must call this function if their matching GrGLSLFragmentProcessor's
385     // emitCode() function uses the EmitArgs::fSampleCoord variable in generated SkSL.
setUsesSampleCoordsDirectly()386     void setUsesSampleCoordsDirectly() {
387         fFlags |= kUsesSampleCoordsDirectly_Flag;
388     }
389 
mergeOptimizationFlags(OptimizationFlags flags)390     void mergeOptimizationFlags(OptimizationFlags flags) {
391         SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
392         fFlags &= (flags | ~kAll_OptimizationFlags);
393     }
394 
395 private:
constantOutputForConstantInput(const SkPMColor4f &)396     virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
397         SK_ABORT("Subclass must override this if advertising this optimization.");
398     }
399 
400     /** Returns a new instance of the appropriate *GL* implementation class
401         for the given GrFragmentProcessor; caller is responsible for deleting
402         the object. */
403     virtual std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const = 0;
404 
405     /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
406     virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
407 
408     /**
409      * Subclass implements this to support isEqual(). It will only be called if it is known that
410      * the two processors are of the same subclass (i.e. they return the same object from
411      * getFactory()).
412      */
413     virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
414 
415     enum PrivateFlags {
416         kFirstPrivateFlag = kAll_OptimizationFlags + 1,
417 
418         // Propagate up the FP tree to the root
419         kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,
420 
421         // Does not propagate at all
422         kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,
423 
424         // Propagates down the FP to all its leaves
425         kSampledWithExplicitCoords_Flag = kFirstPrivateFlag << 2,
426         kNetTransformHasPerspective_Flag = kFirstPrivateFlag << 3,
427     };
428     void addAndPushFlagToChildren(PrivateFlags flag);
429 
430     SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
431     const GrFragmentProcessor* fParent = nullptr;
432     uint32_t fFlags = 0;
433     SkSL::SampleUsage fUsage;
434 
435     using INHERITED = GrProcessor;
436 };
437 
438 //////////////////////////////////////////////////////////////////////////////
439 
GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)440 GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
441 
442 //////////////////////////////////////////////////////////////////////////////
443 
444 class GrFragmentProcessor::CIter {
445 public:
446     explicit CIter(const GrFragmentProcessor& fp) { fFPStack.push_back(&fp); }
447     explicit CIter(const GrPaint&);
448     explicit CIter(const GrPipeline&);
449 
450     const GrFragmentProcessor& operator*() const  { return *fFPStack.back(); }
451     const GrFragmentProcessor* operator->() const { return fFPStack.back(); }
452 
453     CIter& operator++();
454 
455     operator bool() const { return !fFPStack.empty(); }
456 
457     bool operator!=(const EndCIter&) { return (bool)*this; }
458 
459     // Hopefully this does not actually get called because of RVO.
460     CIter(const CIter&) = default;
461 
462     // Because each iterator carries a stack we want to avoid copies.
463     CIter& operator=(const CIter&) = delete;
464 
465 protected:
466     CIter() = delete;
467 
468     SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
469 };
470 
471 //////////////////////////////////////////////////////////////////////////////
472 
473 template <typename Src> class GrFragmentProcessor::CIterRange {
474 public:
CIterRange(const Src & t)475     explicit CIterRange(const Src& t) : fT(t) {}
begin()476     CIter begin() const { return CIter(fT); }
end()477     EndCIter end() const { return EndCIter(); }
478 
479 private:
480     const Src& fT;
481 };
482 
483 /**
484  * Some fragment-processor creation methods have preconditions that might not be satisfied by the
485  * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
486  * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
487  * met, `success` is set to false and the input FP is returned unchanged.
488  */
489 using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp)490 static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
491     return {false, std::move(fp)};
492 }
GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp)493 static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
494     SkASSERT(fp);
495     return {true, std::move(fp)};
496 }
497 
498 #endif
499