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 "GrProcessor.h"
12 #include "GrProxyRef.h"
13 
14 class GrCoordTransform;
15 class GrGLSLFragmentProcessor;
16 class GrPaint;
17 class GrPipeline;
18 class GrProcessorKeyBuilder;
19 class GrShaderCaps;
20 class GrSwizzle;
21 
22 /** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
23     produce an output color. They may reference textures and uniforms. They may use
24     GrCoordTransforms to receive a transformation of the local coordinates that map from local space
25     to the fragment being processed.
26  */
27 class GrFragmentProcessor : public GrProcessor {
28 public:
29     class TextureSampler;
30 
31     /**
32     *  In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
33     *  only consider the input color's alpha. However, there is a competing desire to have reusable
34     *  GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
35     *  color is considered. This function exists to filter the input color and pass it to a FP. It
36     *  does so by returning a parent FP that multiplies the passed in FPs output by the parent's
37     *  input alpha. The passed in FP will not receive an input color.
38     */
39     static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
40             std::unique_ptr<GrFragmentProcessor> child);
41 
42     /**
43      *  Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
44      *  the input modulated by the child's alpha. The passed in FP will not receive an input color.
45      *
46      *  output = input * child.a
47      */
48     static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
49             std::unique_ptr<GrFragmentProcessor> child);
50 
51     /**
52      *  This assumes that the input color to the returned processor will be unpremul and that the
53      *  passed processor (which becomes the returned processor's child) produces a premul output.
54      *  The result of the returned processor is a premul of its input color modulated by the child
55      *  processor's premul output.
56      */
57     static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
58             std::unique_ptr<GrFragmentProcessor>);
59 
60     /**
61      *  Returns a parent fragment processor that adopts the passed fragment processor as a child.
62      *  The parent will ignore its input color and instead feed the passed in color as input to the
63      *  child.
64      */
65     static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
66                                                               const SkPMColor4f&,
67                                                               bool useUniform = true);
68 
69     /**
70      *  Returns a fragment processor that premuls the input before calling the passed in fragment
71      *  processor.
72      */
73     static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
74 
75     /**
76      *  Returns a fragment processor that calls the passed in fragment processor, and then swizzles
77      *  the output.
78      */
79     static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
80                                                               const GrSwizzle&);
81 
82     /**
83      * Returns a fragment processor that runs the passed in array of fragment processors in a
84      * series. The original input is passed to the first, the first's output is passed to the
85      * second, etc. The output of the returned processor is the output of the last processor of the
86      * series.
87      *
88      * The array elements with be moved.
89      */
90     static std::unique_ptr<GrFragmentProcessor> RunInSeries(std::unique_ptr<GrFragmentProcessor>*,
91                                                             int cnt);
92 
93     /**
94      * Makes a copy of this fragment processor that draws equivalently to the original.
95      * If the processor has child processors they are cloned as well.
96      */
97     virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
98 
99     GrGLSLFragmentProcessor* createGLSLInstance() const;
100 
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b)101     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
102         this->onGetGLSLProcessorKey(caps, b);
103         for (int i = 0; i < fChildProcessors.count(); ++i) {
104             fChildProcessors[i]->getGLSLProcessorKey(caps, b);
105         }
106     }
107 
numTextureSamplers()108     int numTextureSamplers() const { return fTextureSamplerCnt; }
109     const TextureSampler& textureSampler(int i) const;
110 
numCoordTransforms()111     int numCoordTransforms() const { return fCoordTransforms.count(); }
112 
113     /** Returns the coordinate transformation at index. index must be valid according to
114         numTransforms(). */
coordTransform(int index)115     const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
116 
coordTransforms()117     const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
118         return fCoordTransforms;
119     }
120 
numChildProcessors()121     int numChildProcessors() const { return fChildProcessors.count(); }
122 
childProcessor(int index)123     const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
124 
125     bool instantiate(GrResourceProvider*) const;
126 
127     void markPendingExecution() const;
128 
129     /** Do any of the coordtransforms for this processor require local coords? */
usesLocalCoords()130     bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
131 
132     /**
133      * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
134      * output under the following scenario:
135      *   * all the color fragment processors report true to this query,
136      *   * all the coverage fragment processors report true to this query,
137      *   * the blend mode arithmetic allows for it it.
138      * To be compatible a fragment processor's output must be a modulation of its input color or
139      * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
140      * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
141      * value cannot depend on the input's color channels unless it unpremultiplies the input color
142      * channels by the input alpha.
143      */
compatibleWithCoverageAsAlpha()144     bool compatibleWithCoverageAsAlpha() const {
145         return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
146     }
147 
148     /**
149      * If this is true then all opaque input colors to the processor produce opaque output colors.
150      */
preservesOpaqueInput()151     bool preservesOpaqueInput() const {
152         return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
153     }
154 
155     /**
156      * Tests whether given a constant input color the processor produces a constant output color
157      * (for all fragments). If true outputColor will contain the constant color produces for
158      * inputColor.
159      */
hasConstantOutputForConstantInput(SkPMColor4f inputColor,SkPMColor4f * outputColor)160     bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
161         if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
162             *outputColor = this->constantOutputForConstantInput(inputColor);
163             return true;
164         }
165         return false;
166     }
hasConstantOutputForConstantInput()167     bool hasConstantOutputForConstantInput() const {
168         return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
169     }
170 
171     /** Returns true if this and other processor conservatively draw identically. It can only return
172         true when the two processor are of the same subclass (i.e. they return the same object from
173         from getFactory()).
174 
175         A return value of true from isEqual() should not be used to test whether the processor would
176         generate the same shader code. To test for identical code generation use getGLSLProcessorKey
177      */
178     bool isEqual(const GrFragmentProcessor& that) const;
179 
180     /**
181      * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
182      * case the tree rooted at each FP in the GrPipeline is visited successively.
183      */
184     class Iter : public SkNoncopyable {
185     public:
Iter(const GrFragmentProcessor * fp)186         explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
187         explicit Iter(const GrPipeline& pipeline);
188         explicit Iter(const GrPaint&);
189         const GrFragmentProcessor* next();
190 
191     private:
192         SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
193     };
194 
195     /**
196      * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
197      * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
198      * order as Iter and each of an FP's Ts are visited in order.
199      */
200     template <typename T, int (GrFragmentProcessor::*COUNT)() const,
201               const T& (GrFragmentProcessor::*GET)(int)const>
202     class FPItemIter : public SkNoncopyable {
203     public:
FPItemIter(const GrFragmentProcessor * fp)204         explicit FPItemIter(const GrFragmentProcessor* fp)
205                 : fCurrFP(nullptr)
206                 , fCTIdx(0)
207                 , fFPIter(fp) {
208             fCurrFP = fFPIter.next();
209         }
FPItemIter(const GrPipeline & pipeline)210         explicit FPItemIter(const GrPipeline& pipeline)
211                 : fCurrFP(nullptr)
212                 , fCTIdx(0)
213                 , fFPIter(pipeline) {
214             fCurrFP = fFPIter.next();
215         }
216 
next()217         const T* next() {
218             if (!fCurrFP) {
219                 return nullptr;
220             }
221             while (fCTIdx == (fCurrFP->*COUNT)()) {
222                 fCTIdx = 0;
223                 fCurrFP = fFPIter.next();
224                 if (!fCurrFP) {
225                     return nullptr;
226                 }
227             }
228             return &(fCurrFP->*GET)(fCTIdx++);
229         }
230 
231     private:
232         const GrFragmentProcessor*  fCurrFP;
233         int                         fCTIdx;
234         GrFragmentProcessor::Iter   fFPIter;
235     };
236 
237     using CoordTransformIter = FPItemIter<GrCoordTransform,
238                                           &GrFragmentProcessor::numCoordTransforms,
239                                           &GrFragmentProcessor::coordTransform>;
240 
241     using TextureAccessIter = FPItemIter<TextureSampler,
242                                          &GrFragmentProcessor::numTextureSamplers,
243                                          &GrFragmentProcessor::textureSampler>;
244 
245     void visitProxies(const std::function<void(GrSurfaceProxy*)>& func);
246 
247 protected:
248     enum OptimizationFlags : uint32_t {
249         kNone_OptimizationFlags,
250         kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
251         kPreservesOpaqueInput_OptimizationFlag = 0x2,
252         kConstantOutputForConstantInput_OptimizationFlag = 0x4,
253         kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
254                                  kPreservesOpaqueInput_OptimizationFlag |
255                                  kConstantOutputForConstantInput_OptimizationFlag
256     };
GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)257     GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
258 
259     /**
260      * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
261      * This assumes that the subclass output color will be a modulation of the input color with a
262      * value read from a texture of the passed config and that the texture contains premultiplied
263      * color or alpha values that are in range.
264      *
265      * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
266      * callers must determine on their own if the sampling uses a decal strategy in any way, in
267      * which case the texture may become transparent regardless of the pixel config.
268      */
269     static OptimizationFlags ModulateForSamplerOptFlags(GrPixelConfig config, bool samplingDecal) {
270         if (samplingDecal) {
271             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
272         } else {
273             return ModulateForClampedSamplerOptFlags(config);
274         }
275     }
276 
277     // As above, but callers should somehow ensure or assert their sampler still uses clamping
ModulateForClampedSamplerOptFlags(GrPixelConfig config)278     static OptimizationFlags ModulateForClampedSamplerOptFlags(GrPixelConfig config) {
279         if (GrPixelConfigIsOpaque(config)) {
280             return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
281                    kPreservesOpaqueInput_OptimizationFlag;
282         } else {
283             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
284         }
285     }
286 
GrFragmentProcessor(ClassID classID,OptimizationFlags optimizationFlags)287     GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
288     : INHERITED(classID)
289     , fFlags(optimizationFlags) {
290         SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
291     }
292 
optimizationFlags()293     OptimizationFlags optimizationFlags() const {
294         return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
295     }
296 
297     /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
ProcessorOptimizationFlags(const GrFragmentProcessor * fp)298     static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
299         return fp->optimizationFlags();
300     }
301 
302     /**
303      * This allows one subclass to access another subclass's implementation of
304      * constantOutputForConstantInput. It must only be called when
305      * hasConstantOutputForConstantInput() is known to be true.
306      */
ConstantOutputForConstantInput(const GrFragmentProcessor & fp,const SkPMColor4f & input)307     static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
308                                                       const SkPMColor4f& input) {
309         SkASSERT(fp.hasConstantOutputForConstantInput());
310         return fp.constantOutputForConstantInput(input);
311     }
312 
313     /**
314      * Fragment Processor subclasses call this from their constructor to register coordinate
315      * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
316      * in their FS code. The matrix expresses a transformation from local space. For a given
317      * fragment the matrix will be applied to the local coordinate that maps to the fragment.
318      *
319      * When the transformation has perspective, the transformed coordinates will have
320      * 3 components. Otherwise they'll have 2.
321      *
322      * This must only be called from the constructor because GrProcessors are immutable. The
323      * processor subclass manages the lifetime of the transformations (this function only stores a
324      * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
325      *
326      * A processor subclass that has multiple methods of construction should always add its coord
327      * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
328      * compares transforms and will assume they line up across the two processor instances.
329      */
330     void addCoordTransform(const GrCoordTransform*);
331 
332     /**
333      * FragmentProcessor subclasses call this from their constructor to register any child
334      * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
335      * transforms have been added.
336      * This is for processors whose shader code will be composed of nested processors whose output
337      * colors will be combined somehow to produce its output color.  Registering these child
338      * processors will allow the ProgramBuilder to automatically handle their transformed coords and
339      * texture accesses and mangle their uniform and output color names.
340      */
341     int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);
342 
setTextureSamplerCnt(int cnt)343     void setTextureSamplerCnt(int cnt) {
344         SkASSERT(cnt >= 0);
345         fTextureSamplerCnt = cnt;
346     }
347 
348     /**
349      * Helper for implementing onTextureSampler(). E.g.:
350      * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
351      */
352     template <typename... Args>
IthTextureSampler(int i,const TextureSampler & samp0,const Args &...samps)353     static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
354                                                    const Args&... samps) {
355         return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
356     }
357     inline static const TextureSampler& IthTextureSampler(int i);
358 
359 private:
constantOutputForConstantInput(const SkPMColor4f &)360     virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
361         SK_ABORT("Subclass must override this if advertising this optimization.");
362         return SK_PMColor4fTRANSPARENT;
363     }
364 
365     /** Returns a new instance of the appropriate *GL* implementation class
366         for the given GrFragmentProcessor; caller is responsible for deleting
367         the object. */
368     virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
369 
370     /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
371     virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
372 
373     /**
374      * Subclass implements this to support isEqual(). It will only be called if it is known that
375      * the two processors are of the same subclass (i.e. they return the same object from
376      * getFactory()). The processor subclass should not compare its coord transforms as that will
377      * be performed automatically in the non-virtual isEqual().
378      */
379     virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
380 
onTextureSampler(int)381     virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
382 
383     bool hasSameTransforms(const GrFragmentProcessor&) const;
384 
385     enum PrivateFlags {
386         kFirstPrivateFlag = kAll_OptimizationFlags + 1,
387         kUsesLocalCoords_Flag = kFirstPrivateFlag,
388     };
389 
390     mutable uint32_t fFlags = 0;
391 
392     int fTextureSamplerCnt = 0;
393 
394     SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
395 
396     SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
397 
398     typedef GrProcessor INHERITED;
399 };
400 
401 /**
402  * Used to represent a texture that is required by a GrFragmentProcessor. It holds a GrTextureProxy
403  * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to
404  * account for texture origin.
405  */
406 class GrFragmentProcessor::TextureSampler {
407 public:
408     TextureSampler() = default;
409 
410     /**
411      * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
412      * always takes a new ref on the texture proxy as the new fragment processor will not yet be
413      * in pending execution state.
414      */
TextureSampler(const TextureSampler & that)415     explicit TextureSampler(const TextureSampler& that)
416             : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType())
417             , fSamplerState(that.fSamplerState) {}
418 
419     TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerState&);
420 
421     explicit TextureSampler(sk_sp<GrTextureProxy>,
422                             GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
423                             GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp);
424 
425     TextureSampler& operator=(const TextureSampler&) = delete;
426 
427     void reset(sk_sp<GrTextureProxy>, const GrSamplerState&);
428     void reset(sk_sp<GrTextureProxy>,
429                GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
430                GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp);
431 
432     bool operator==(const TextureSampler& that) const {
433         return this->proxy()->underlyingUniqueID() == that.proxy()->underlyingUniqueID() &&
434                fSamplerState == that.fSamplerState;
435     }
436 
437     bool operator!=(const TextureSampler& other) const { return !(*this == other); }
438 
439     // 'instantiate' should only ever be called at flush time.
instantiate(GrResourceProvider * resourceProvider)440     bool instantiate(GrResourceProvider* resourceProvider) const {
441         return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
442     }
443 
444     // 'peekTexture' should only ever be called after a successful 'instantiate' call
peekTexture()445     GrTexture* peekTexture() const {
446         SkASSERT(fProxyRef.get()->peekTexture());
447         return fProxyRef.get()->peekTexture();
448     }
449 
proxy()450     GrTextureProxy* proxy() const { return fProxyRef.get(); }
samplerState()451     const GrSamplerState& samplerState() const { return fSamplerState; }
452 
isInitialized()453     bool isInitialized() const { return SkToBool(fProxyRef.get()); }
454     /**
455      * For internal use by GrFragmentProcessor.
456      */
proxyRef()457     const GrTextureProxyRef* proxyRef() const { return &fProxyRef; }
458 
459 private:
460     GrTextureProxyRef fProxyRef;
461     GrSamplerState fSamplerState;
462 };
463 
464 //////////////////////////////////////////////////////////////////////////////
465 
IthTextureSampler(int i)466 const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::IthTextureSampler(int i) {
467     SK_ABORT("Illegal texture sampler index");
468     static const TextureSampler kBogus;
469     return kBogus;
470 }
471 
472 GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
473 
474 #endif
475