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