GrGLProgram.h revision e9144c64a6e75795b591d2adc28f627d7c3fb8f7
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 "GrGLContext.h" 15#include "GrGLSL.h" 16#include "GrGLTexture.h" 17#include "GrGLUniformManager.h" 18 19#include "SkString.h" 20#include "SkXfermode.h" 21 22class GrBinHashKeyBuilder; 23class GrGLEffect; 24class GrGLShaderBuilder; 25class SkMWCRandom; 26 27// optionally compile the experimental GS code. Set to GR_DEBUG 28// so that debug build bots will execute the code. 29#define GR_GL_EXPERIMENTAL_GS GR_DEBUG 30 31/** 32 * This class manages a GPU program and records per-program information. 33 * We can specify the attribute locations so that they are constant 34 * across our shaders. But the driver determines the uniform locations 35 * at link time. We don't need to remember the sampler uniform location 36 * because we will bind a texture slot to it and never change it 37 * Uniforms are program-local so we can't rely on fHWState to hold the 38 * previous uniform state after a program change. 39 */ 40class GrGLProgram : public GrRefCnt { 41public: 42 SK_DECLARE_INST_COUNT(GrGLProgram) 43 44 class Desc; 45 46 /** 47 * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the 48 * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. 49 */ 50 static void BuildDesc(const GrDrawState&, 51 bool isPoints, 52 GrDrawState::BlendOptFlags, 53 GrBlendCoeff srcCoeff, 54 GrBlendCoeff dstCoeff, 55 const GrGpuGL* gpu, 56 Desc* outDesc); 57 58 static GrGLProgram* Create(const GrGLContext& gl, 59 const Desc& desc, 60 const GrEffectStage* stages[]); 61 62 virtual ~GrGLProgram(); 63 64 /** 65 * Call to abandon GL objects owned by this program. 66 */ 67 void abandon(); 68 69 /** 70 * The shader may modify the blend coefficients. Params are in/out 71 */ 72 void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; 73 74 const Desc& getDesc() { return fDesc; } 75 76 /** 77 * Gets the GL program ID for this program. 78 */ 79 GrGLuint programID() const { return fProgramID; } 80 81 /** 82 * Some GL state that is relevant to programs is not stored per-program. In particular vertex 83 * attributes are global state. This struct is read and updated by GrGLProgram::setData to 84 * allow us to avoid setting this state redundantly. 85 */ 86 struct SharedGLState { 87 GrColor fConstAttribColor; 88 GrColor fConstAttribCoverage; 89 90 SharedGLState() { this->invalidate(); } 91 void invalidate() { 92 fConstAttribColor = GrColor_ILLEGAL; 93 fConstAttribCoverage = GrColor_ILLEGAL; 94 } 95 }; 96 97 /** 98 * The GrDrawState's view matrix along with the aspects of the render target determine the 99 * matrix sent to GL. The size of the render target affects the GL matrix because we must 100 * convert from Skia device coords to GL's normalized coords. Also the origin of the render 101 * target may require us to perform a mirror-flip. 102 */ 103 struct MatrixState { 104 SkMatrix fViewMatrix; 105 SkISize fRenderTargetSize; 106 GrSurfaceOrigin fRenderTargetOrigin; 107 108 MatrixState() { this->invalidate(); } 109 void invalidate() { 110 fViewMatrix = SkMatrix::InvalidMatrix(); 111 fRenderTargetSize.fWidth = -1; 112 fRenderTargetSize.fHeight = -1; 113 fRenderTargetOrigin = (GrSurfaceOrigin) -1; 114 } 115 }; 116 117 /** 118 * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a 119 * draw occurs using the program after the program has already been bound. It also uses the 120 * GrGpuGL object to bind the textures required by the GrGLEffects. 121 * 122 * The color and coverage params override the GrDrawState's getColor() and getCoverage() values. 123 */ 124 void setData(GrGpuGL*, GrColor color, GrColor coverage, SharedGLState*); 125 126 // Parameters that affect code generation 127 // This structs should be kept compact; it is input to an expensive hash key generator. 128 class Desc { 129 public: 130 Desc() { 131 // since we use this as part of a key we can't have any uninitialized 132 // padding 133 memset(this, 0, sizeof(Desc)); 134 } 135 136 // returns this as a uint32_t array to be used as a key in the program cache 137 const uint32_t* asKey() const { 138 return reinterpret_cast<const uint32_t*>(this); 139 } 140 141 // For unit testing. 142 void setRandom(SkMWCRandom*, 143 const GrGpuGL* gpu, 144 const GrEffectStage stages[GrDrawState::kNumStages]); 145 146 private: 147 // Specifies where the initial color comes from before the stages are applied. 148 enum ColorInput { 149 kSolidWhite_ColorInput, 150 kTransBlack_ColorInput, 151 kAttribute_ColorInput, 152 kUniform_ColorInput, 153 154 kColorInputCnt 155 }; 156 // Dual-src blending makes use of a secondary output color that can be 157 // used as a per-pixel blend coefficient. This controls whether a 158 // secondary source is output and what value it holds. 159 enum DualSrcOutput { 160 kNone_DualSrcOutput, 161 kCoverage_DualSrcOutput, 162 kCoverageISA_DualSrcOutput, 163 kCoverageISC_DualSrcOutput, 164 165 kDualSrcOutputCnt 166 }; 167 168 // should the FS discard if the coverage is zero (to avoid stencil manipulation) 169 bool fDiscardIfZeroCoverage; 170 171 // stripped of bits that don't affect program generation 172 GrAttribBindings fAttribBindings; 173 174 /** Non-zero if this stage has an effect */ 175 GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; 176 177 // To enable experimental geometry shader code (not for use in 178 // production) 179#if GR_GL_EXPERIMENTAL_GS 180 bool fExperimentalGS; 181#endif 182 uint8_t fColorInput; // casts to enum ColorInput 183 uint8_t fCoverageInput; // casts to enum ColorInput 184 uint8_t fDualSrcOutput; // casts to enum DualSrcOutput 185 int8_t fFirstCoverageStage; 186 SkBool8 fEmitsPointSize; 187 uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode 188 189 int8_t fPositionAttributeIndex; 190 int8_t fColorAttributeIndex; 191 int8_t fCoverageAttributeIndex; 192 int8_t fLocalCoordsAttributeIndex; 193 194 friend class GrGLProgram; 195 }; 196 197 // Layout information for OpenGL vertex attributes 198 struct AttribLayout { 199 GrGLint fCount; 200 GrGLenum fType; 201 GrGLboolean fNormalized; 202 }; 203 static const AttribLayout kAttribLayouts[kGrVertexAttribTypeCount]; 204 205private: 206 GrGLProgram(const GrGLContext& gl, 207 const Desc& desc, 208 const GrEffectStage* stages[]); 209 210 bool succeeded() const { return 0 != fProgramID; } 211 212 /** 213 * This is the heavy initialization routine for building a GLProgram. 214 */ 215 bool genProgram(const GrEffectStage* stages[]); 216 217 void genInputColor(GrGLShaderBuilder* builder, SkString* inColor); 218 219 void genGeometryShader(GrGLShaderBuilder* segments) const; 220 221 typedef GrGLUniformManager::UniformHandle UniformHandle; 222 223 void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage); 224 225 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program 226 bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, 227 bool bindColorOut, 228 bool bindDualSrcOut); 229 230 // Sets the texture units for samplers 231 void initSamplerUniforms(); 232 233 bool compileShaders(const GrGLShaderBuilder& builder); 234 235 const char* adjustInColor(const SkString& inColor) const; 236 237 // Helper for setData(). Makes GL calls to specify the initial color when there is not 238 // per-vertex colors. 239 void setColor(const GrDrawState&, GrColor color, SharedGLState*); 240 241 // Helper for setData(). Makes GL calls to specify the initial coverage when there is not 242 // per-vertex coverages. 243 void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*); 244 245 // Helper for setData() that sets the view matrix and loads the render target height uniform 246 void setMatrixAndRenderTargetHeight(const GrDrawState&); 247 248 typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray; 249 250 struct UniformHandles { 251 UniformHandle fViewMatrixUni; 252 UniformHandle fColorUni; 253 UniformHandle fCoverageUni; 254 UniformHandle fColorFilterUni; 255 // We use the render target height to provide a y-down frag coord when specifying 256 // origin_upper_left is not supported. 257 UniformHandle fRTHeightUni; 258 // An array of sampler uniform handles for each effect. 259 SamplerUniSArray fSamplerUnis[GrDrawState::kNumStages]; 260 261 UniformHandles() { 262 fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle; 263 fColorUni = GrGLUniformManager::kInvalidUniformHandle; 264 fCoverageUni = GrGLUniformManager::kInvalidUniformHandle; 265 fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle; 266 fRTHeightUni = GrGLUniformManager::kInvalidUniformHandle; 267 } 268 }; 269 270 // GL IDs 271 GrGLuint fVShaderID; 272 GrGLuint fGShaderID; 273 GrGLuint fFShaderID; 274 GrGLuint fProgramID; 275 276 // these reflect the current values of uniforms (GL uniform values travel with program) 277 MatrixState fMatrixState; 278 GrColor fColor; 279 GrColor fCoverage; 280 GrColor fColorFilterColor; 281 282 GrGLEffect* fEffects[GrDrawState::kNumStages]; 283 284 Desc fDesc; 285 const GrGLContext& fContext; 286 287 GrGLUniformManager fUniformManager; 288 UniformHandles fUniformHandles; 289 290 typedef GrRefCnt INHERITED; 291}; 292 293#endif 294