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