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