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 GrGLSLFragmentShaderBuilder_DEFINED
9 #define GrGLSLFragmentShaderBuilder_DEFINED
10 
11 #include "GrGLSLShaderBuilder.h"
12 
13 #include "glsl/GrGLSLProcessorTypes.h"
14 
15 class GrRenderTarget;
16 class GrGLSLVarying;
17 
18 /*
19  * This base class encapsulates the common functionality which all processors use to build fragment
20  * shaders.
21  */
22 class GrGLSLFragmentBuilder : public GrGLSLShaderBuilder {
23 public:
GrGLSLFragmentBuilder(GrGLSLProgramBuilder * program)24     GrGLSLFragmentBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
~GrGLSLFragmentBuilder()25     virtual ~GrGLSLFragmentBuilder() {}
26 
27     /**
28      * Use of these features may require a GLSL extension to be enabled. Shaders may not compile
29      * if code is added that uses one of these features without calling enableFeature()
30      */
31     enum GLSLFeature {
32         kStandardDerivatives_GLSLFeature = kLastGLSLPrivateFeature + 1,
33         kPixelLocalStorage_GLSLFeature
34     };
35 
36     /**
37      * If the feature is supported then true is returned and any necessary #extension declarations
38      * are added to the shaders. If the feature is not supported then false will be returned.
39      */
40     virtual bool enableFeature(GLSLFeature) = 0;
41 
42     /**
43      * This returns a variable name to access the 2D, perspective correct version of the coords in
44      * the fragment shader. If the coordinates at index are 3-dimensional, it immediately emits a
45      * perspective divide into the fragment shader (xy / z) to convert them to 2D.
46      */
47     virtual SkString ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords, int index) = 0;
48 
49 
50     /** Returns a variable name that represents the position of the fragment in the FS. The position
51         is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
52     virtual const char* fragmentPosition() = 0;
53 
54     // TODO: remove this method.
55     void declAppendf(const char* fmt, ...);
56 
57 private:
58     typedef GrGLSLShaderBuilder INHERITED;
59 };
60 
61 /*
62  * This class is used by fragment processors to build their fragment code.
63  */
64 class GrGLSLFPFragmentBuilder : virtual public GrGLSLFragmentBuilder {
65 public:
66     /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLFPFragmentBuilder()67     GrGLSLFPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
68 
69     /**
70      * Subtracts sample coverage from the fragment. Any sample whose corresponding bit is not found
71      * in the mask will not be written out to the framebuffer.
72      *
73      * @param mask      int that contains the sample mask. Bit N corresponds to the Nth sample.
74      * @param invert    perform a bit-wise NOT on the provided mask before applying it?
75      *
76      * Requires GLSL support for sample variables.
77      */
78     virtual void maskSampleCoverage(const char* mask, bool invert = false) = 0;
79 
80     /**
81      * Fragment procs with child procs should call these functions before/after calling emitCode
82      * on a child proc.
83      */
84     virtual void onBeforeChildProcEmitCode() = 0;
85     virtual void onAfterChildProcEmitCode() = 0;
86 
87     virtual const SkString& getMangleString() const = 0;
88 };
89 
90 /*
91  * This class is used by primitive processors to build their fragment code.
92  */
93 class GrGLSLPPFragmentBuilder : public GrGLSLFPFragmentBuilder {
94 public:
95     /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLPPFragmentBuilder()96     GrGLSLPPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
97 
98     /**
99      * Overrides the fragment's sample coverage. The provided mask determines which samples will now
100      * be written out to the framebuffer. Note that this mask can be reduced by a future call to
101      * maskSampleCoverage.
102      *
103      * If a primitive processor uses this method, it must guarantee that every codepath through the
104      * shader overrides the sample mask at some point.
105      *
106      * @param mask    int that contains the new coverage mask. Bit N corresponds to the Nth sample.
107      *
108      * Requires NV_sample_mask_override_coverage.
109      */
110     virtual void overrideSampleCoverage(const char* mask) = 0;
111 };
112 
113 /*
114  * This class is used by Xfer processors to build their fragment code.
115  */
116 class GrGLSLXPFragmentBuilder : virtual public GrGLSLFragmentBuilder {
117 public:
118     /** Appease the compiler; the derived class initializes GrGLSLFragmentBuilder. */
GrGLSLXPFragmentBuilder()119     GrGLSLXPFragmentBuilder() : GrGLSLFragmentBuilder(nullptr) {}
120 
121     virtual bool hasCustomColorOutput() const = 0;
122     virtual bool hasSecondaryOutput() const = 0;
123 
124     /** Returns the variable name that holds the color of the destination pixel. This may be nullptr
125      * if no effect advertised that it will read the destination. */
126     virtual const char* dstColor() = 0;
127 
128     /** Adds any necessary layout qualifiers in order to legalize the supplied blend equation with
129         this shader. It is only legal to call this method with an advanced blend equation, and only
130         if these equations are supported. */
131     virtual void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) = 0;
132 };
133 
134 /*
135  * This class implements the various fragment builder interfaces.
136  */
137 class GrGLSLFragmentShaderBuilder : public GrGLSLPPFragmentBuilder, public GrGLSLXPFragmentBuilder {
138 public:
139     typedef uint8_t FragPosKey;
140 
141     /** Returns a key for reading the fragment location. This should only be called if there is an
142        effect that will requires the fragment position. If the fragment position is not required,
143        the key is 0. */
144     static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst);
145 
146     GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program, uint8_t fragPosKey);
147 
148     // Shared GrGLSLFragmentBuilder interface.
149     bool enableFeature(GLSLFeature) override;
150     virtual SkString ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords,
151                                       int index) override;
152     const char* fragmentPosition() override;
153 
154     // GrGLSLFPFragmentBuilder interface.
155     void maskSampleCoverage(const char* mask, bool invert = false) override;
156     void overrideSampleCoverage(const char* mask) override;
getMangleString()157     const SkString& getMangleString() const override { return fMangleString; }
158     void onBeforeChildProcEmitCode() override;
159     void onAfterChildProcEmitCode() override;
160 
161     // GrGLSLXPFragmentBuilder interface.
hasCustomColorOutput()162     bool hasCustomColorOutput() const override { return fHasCustomColorOutput; }
hasSecondaryOutput()163     bool hasSecondaryOutput() const override { return fHasSecondaryOutput; }
164     const char* dstColor() override;
165     void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) override;
166 
167 private:
168     // Private public interface, used by GrGLProgramBuilder to build a fragment shader
169     void enableCustomOutput();
170     void enableSecondaryOutput();
171     const char* getPrimaryColorOutputName() const;
172     const char* getSecondaryColorOutputName() const;
173 
174     // As GLSLProcessors emit code, there are some conditions we need to verify.  We use the below
175     // state to track this.  The reset call is called per processor emitted.
hasReadDstColor()176     bool hasReadDstColor() const { return fHasReadDstColor; }
hasReadFragmentPosition()177     bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
reset()178     void reset() {
179         fHasReadDstColor = false;
180         fHasReadFragmentPosition = false;
181     }
182 
DeclaredColorOutputName()183     static const char* DeclaredColorOutputName() { return "fsColorOut"; }
DeclaredSecondaryColorOutputName()184     static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
185 
186     /*
187      * An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
188      */
189     void addVarying(GrGLSLVarying*, GrSLPrecision);
190 
191     void onFinalize() override;
192 
193     // Interpretation of FragPosKey when generating code
194     enum {
195         kNoFragPosRead_FragPosKey           = 0,  // The fragment positition will not be needed.
196         kTopLeftFragPosRead_FragPosKey      = 0x1,// Read frag pos relative to top-left.
197         kBottomLeftFragPosRead_FragPosKey   = 0x2,// Read frag pos relative to bottom-left.
198     };
199 
200     static const char* kDstTextureColorName;
201 
202     /*
203      * State that tracks which child proc in the proc tree is currently emitting code.  This is
204      * used to update the fMangleString, which is used to mangle the names of uniforms and functions
205      * emitted by the proc.  fSubstageIndices is a stack: its count indicates how many levels deep
206      * we are in the tree, and its second-to-last value is the index of the child proc at that
207      * level which is currently emitting code. For example, if fSubstageIndices = [3, 1, 2, 0], that
208      * means we're currently emitting code for the base proc's 3rd child's 1st child's 2nd child.
209      */
210     SkTArray<int> fSubstageIndices;
211 
212     /*
213      * The mangle string is used to mangle the names of uniforms/functions emitted by the child
214      * procs so no duplicate uniforms/functions appear in the generated shader program. The mangle
215      * string is simply based on fSubstageIndices. For example, if fSubstageIndices = [3, 1, 2, 0],
216      * then the manglestring will be "_c3_c1_c2", and any uniform/function emitted by that proc will
217      * have "_c3_c1_c2" appended to its name, which can be interpreted as "base proc's 3rd child's
218      * 1st child's 2nd child".
219      */
220     SkString fMangleString;
221 
222     bool fSetupFragPosition;
223     bool fTopLeftFragPosRead;
224     bool fHasCustomColorOutput;
225     int  fCustomColorOutputIndex;
226     bool fHasSecondaryOutput;
227     bool fHasInitializedSampleMask;
228 
229     // some state to verify shaders and effects are consistent, this is reset between effects by
230     // the program creator
231     bool fHasReadDstColor;
232     bool fHasReadFragmentPosition;
233 
234     friend class GrGLSLProgramBuilder;
235     friend class GrGLProgramBuilder;
236 };
237 
238 #endif
239