1 /* 2 * Copyright 2011 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 9 #ifndef GrGLProgram_DEFINED 10 #define GrGLProgram_DEFINED 11 12 #include "GrDrawState.h" 13 #include "GrGLEffect.h" 14 #include "GrGLContextInfo.h" 15 #include "GrGLSL.h" 16 #include "GrGLTexture.h" 17 #include "GrGLUniformManager.h" 18 19 #include "SkString.h" 20 #include "SkXfermode.h" 21 22 class GrBinHashKeyBuilder; 23 class GrGLEffect; 24 class GrGLShaderBuilder; 25 26 // optionally compile the experimental GS code. Set to GR_DEBUG 27 // so that debug build bots will execute the code. 28 #define GR_GL_EXPERIMENTAL_GS GR_DEBUG 29 30 /** 31 * This class manages a GPU program and records per-program information. 32 * We can specify the attribute locations so that they are constant 33 * across our shaders. But the driver determines the uniform locations 34 * at link time. We don't need to remember the sampler uniform location 35 * because we will bind a texture slot to it and never change it 36 * Uniforms are program-local so we can't rely on fHWState to hold the 37 * previous uniform state after a program change. 38 */ 39 class GrGLProgram : public GrRefCnt { 40 public: 41 SK_DECLARE_INST_COUNT(GrGLProgram) 42 43 struct Desc; 44 45 static GrGLProgram* Create(const GrGLContextInfo& gl, 46 const Desc& desc, 47 const GrEffectStage* stages[]); 48 49 virtual ~GrGLProgram(); 50 51 /** 52 * Call to abandon GL objects owned by this program. 53 */ 54 void abandon(); 55 56 /** 57 * The shader may modify the blend coefficients. Params are in/out 58 */ 59 void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; 60 61 const Desc& getDesc() { return fDesc; } 62 63 /** 64 * Attribute indices. These should not overlap. 65 */ 66 static int PositionAttributeIdx() { return 0; } 67 static int ColorAttributeIdx() { return 1; } 68 static int CoverageAttributeIdx() { return 2; } 69 static int EdgeAttributeIdx() { return 3; } 70 static int TexCoordAttributeIdx(int tcIdx) { return 4 + tcIdx; } 71 72 /** 73 * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a 74 * draw occurs using the program after the program has already been bound. It also uses the 75 * GrGpuGL object to bind the textures required by the GrGLEffects. 76 */ 77 void setData(GrGpuGL*); 78 79 // Parameters that affect code generation 80 // This structs should be kept compact; it is input to an expensive hash key generator. 81 struct Desc { 82 Desc() { 83 // since we use this as part of a key we can't have any uninitialized 84 // padding 85 memset(this, 0, sizeof(Desc)); 86 } 87 88 // returns this as a uint32_t array to be used as a key in the program cache 89 const uint32_t* asKey() const { 90 return reinterpret_cast<const uint32_t*>(this); 91 } 92 93 // Specifies where the initial color comes from before the stages are applied. 94 enum ColorInput { 95 kSolidWhite_ColorInput, 96 kTransBlack_ColorInput, 97 kAttribute_ColorInput, 98 kUniform_ColorInput, 99 100 kColorInputCnt 101 }; 102 // Dual-src blending makes use of a secondary output color that can be 103 // used as a per-pixel blend coefficient. This controls whether a 104 // secondary source is output and what value it holds. 105 enum DualSrcOutput { 106 kNone_DualSrcOutput, 107 kCoverage_DualSrcOutput, 108 kCoverageISA_DualSrcOutput, 109 kCoverageISC_DualSrcOutput, 110 111 kDualSrcOutputCnt 112 }; 113 114 // TODO: remove these two members when edge-aa can be rewritten as a GrEffect. 115 GrDrawState::VertexEdgeType fVertexEdgeType; 116 // should the FS discard if the edge-aa coverage is zero (to avoid stencil manipulation) 117 bool fDiscardIfOutsideEdge; 118 119 // stripped of bits that don't affect program generation 120 GrVertexLayout fVertexLayout; 121 122 /** Non-zero if this stage has an effect */ 123 GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; 124 125 // To enable experimental geometry shader code (not for use in 126 // production) 127 #if GR_GL_EXPERIMENTAL_GS 128 bool fExperimentalGS; 129 #endif 130 uint8_t fColorInput; // casts to enum ColorInput 131 uint8_t fCoverageInput; // casts to enum ColorInput 132 uint8_t fDualSrcOutput; // casts to enum DualSrcOutput 133 int8_t fFirstCoverageStage; 134 SkBool8 fEmitsPointSize; 135 uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode 136 }; 137 private: 138 GrGLProgram(const GrGLContextInfo& gl, 139 const Desc& desc, 140 const GrEffectStage* stages[]); 141 142 bool succeeded() const { return 0 != fProgramID; } 143 144 /** 145 * This is the heavy initialization routine for building a GLProgram. 146 */ 147 bool genProgram(const GrEffectStage* stages[]); 148 149 void genInputColor(GrGLShaderBuilder* builder, SkString* inColor); 150 151 void genGeometryShader(GrGLShaderBuilder* segments) const; 152 153 typedef GrGLUniformManager::UniformHandle UniformHandle; 154 155 void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage); 156 157 // generates code to compute coverage based on edge AA. Returns true if edge coverage was 158 // inserted in which case coverageVar will be updated to refer to a scalar. Otherwise, 159 // coverageVar is set to an empty string. 160 bool genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* builder) const; 161 162 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program 163 bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, 164 SkString texCoordAttrNames[GrDrawState::kMaxTexCoords], 165 bool bindColorOut, 166 bool bindDualSrcOut); 167 168 // Sets the texture units for samplers 169 void initSamplerUniforms(); 170 171 bool compileShaders(const GrGLShaderBuilder& builder); 172 173 const char* adjustInColor(const SkString& inColor) const; 174 175 typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray; 176 177 struct UniformHandles { 178 UniformHandle fViewMatrixUni; 179 UniformHandle fColorUni; 180 UniformHandle fCoverageUni; 181 UniformHandle fColorFilterUni; 182 // We use the render target height to provide a y-down frag coord when specifying 183 // origin_upper_left is not supported. 184 UniformHandle fRTHeightUni; 185 // An array of sampler uniform handles for each effect. 186 SamplerUniSArray fSamplerUnis[GrDrawState::kNumStages]; 187 188 UniformHandles() { 189 fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle; 190 fColorUni = GrGLUniformManager::kInvalidUniformHandle; 191 fCoverageUni = GrGLUniformManager::kInvalidUniformHandle; 192 fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle; 193 fRTHeightUni = GrGLUniformManager::kInvalidUniformHandle; 194 } 195 }; 196 197 // GL IDs 198 GrGLuint fVShaderID; 199 GrGLuint fGShaderID; 200 GrGLuint fFShaderID; 201 GrGLuint fProgramID; 202 // The matrix sent to GL is determined by both the client's matrix and 203 // the size of the viewport. 204 SkMatrix fViewMatrix; 205 SkISize fViewportSize; 206 207 // these reflect the current values of uniforms (GL uniform values travel with program) 208 GrColor fColor; 209 GrColor fCoverage; 210 GrColor fColorFilterColor; 211 int fRTHeight; 212 213 GrGLEffect* fEffects[GrDrawState::kNumStages]; 214 215 Desc fDesc; 216 const GrGLContextInfo& fContextInfo; 217 218 GrGLUniformManager fUniformManager; 219 UniformHandles fUniformHandles; 220 221 friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality. 222 223 typedef GrRefCnt INHERITED; 224 }; 225 226 #endif 227