GrGLProgram.h revision d8f856c32b679d9f5a9926feac005e2c0186f83f
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 "GrGLContextInfo.h" 14#include "GrGLSL.h" 15#include "GrStringBuilder.h" 16#include "GrGpu.h" 17 18#include "SkXfermode.h" 19 20class GrBinHashKeyBuilder; 21class GrGLProgramStage; 22 23struct ShaderCodeSegments; 24 25// optionally compile the experimental GS code. Set to GR_DEBUG 26// so that debug build bots will execute the code. 27#define GR_GL_EXPERIMENTAL_GS GR_DEBUG 28 29/** 30 * This class manages a GPU program and records per-program information. 31 * We can specify the attribute locations so that they are constant 32 * across our shaders. But the driver determines the uniform locations 33 * at link time. We don't need to remember the sampler uniform location 34 * because we will bind a texture slot to it and never change it 35 * Uniforms are program-local so we can't rely on fHWState to hold the 36 * previous uniform state after a program change. 37 */ 38class GrGLProgram { 39public: 40 41 class CachedData; 42 43 GrGLProgram(); 44 ~GrGLProgram(); 45 46 /** 47 * This is the heavy initilization routine for building a GLProgram. 48 * The result of heavy init is not stored in datamembers of GrGLProgam, 49 * but in a separate cacheable container. 50 */ 51 bool genProgram(const GrGLContextInfo& gl, 52 GrCustomStage** customStages, 53 CachedData* programData) const; 54 55 /** 56 * The shader may modify the blend coeffecients. Params are in/out 57 */ 58 void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; 59 60 /** 61 * Attribute indices. These should not overlap. Matrices consume 3 slots. 62 */ 63 static int PositionAttributeIdx() { return 0; } 64 static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; } 65 static int ColorAttributeIdx() { return 1 + GrDrawState::kMaxTexCoords; } 66 static int CoverageAttributeIdx() { 67 return 2 + GrDrawState::kMaxTexCoords; 68 } 69 static int EdgeAttributeIdx() { return 3 + GrDrawState::kMaxTexCoords; } 70 71 static int ViewMatrixAttributeIdx() { 72 return 4 + GrDrawState::kMaxTexCoords; 73 } 74 static int TextureMatrixAttributeIdx(int stage) { 75 return 7 + GrDrawState::kMaxTexCoords + 3 * stage; 76 } 77 78public: 79 80 // Parameters that affect code generation 81 // These structs should be kept compact; they are the input to an 82 // expensive hash key generator. 83 struct ProgramDesc { 84 ProgramDesc() { 85 // since we use this as part of a key we can't have any unitialized 86 // padding 87 memset(this, 0, sizeof(ProgramDesc)); 88 } 89 90 enum OutputConfig { 91 // PM-color OR color with no alpha channel 92 kPremultiplied_OutputConfig, 93 // nonPM-color with alpha channel. Round components up after 94 // dividing by alpha. Assumes output is 8 bits for r, g, and b 95 kUnpremultiplied_RoundUp_OutputConfig, 96 // nonPM-color with alpha channel. Round components down after 97 // dividing by alpha. Assumes output is 8 bits for r, g, and b 98 kUnpremultiplied_RoundDown_OutputConfig, 99 100 kOutputConfigCnt 101 }; 102 103 struct StageDesc { 104 enum OptFlagBits { 105 kNoPerspective_OptFlagBit = 1 << 0, 106 kIdentityMatrix_OptFlagBit = 1 << 1, 107 kCustomTextureDomain_OptFlagBit = 1 << 2, 108 kIsEnabled_OptFlagBit = 1 << 7 109 }; 110 // Convolution is obsolete; left in for testing only 111 enum FetchMode { 112 kSingle_FetchMode, 113 k2x2_FetchMode, 114 kConvolution_FetchMode, 115 kErode_FetchMode, 116 kDilate_FetchMode, 117 118 kFetchModeCnt, 119 }; 120 /** 121 Flags set based on a src texture's pixel config. The operations 122 described are performed after reading a texel. 123 */ 124 enum InConfigFlags { 125 kNone_InConfigFlag = 0x00, 126 127 /** 128 Swap the R and B channels. This is incompatible with 129 kSmearAlpha. It is prefereable to perform the swizzle outside 130 the shader using GL_ARB_texture_swizzle if possible rather 131 than setting this flag. 132 */ 133 kSwapRAndB_InConfigFlag = 0x01, 134 135 /** 136 Smear alpha across all four channels. This is incompatible with 137 kSwapRAndB, kMulRGBByAlpha* and kSmearRed. It is prefereable 138 to perform the smear outside the shader using 139 GL_ARB_texture_swizzle if possible rather than setting this 140 flag. 141 */ 142 kSmearAlpha_InConfigFlag = 0x02, 143 144 /** 145 Smear the red channel across all four channels. This flag is 146 incompatible with kSwapRAndB, kMulRGBByAlpha*and kSmearAlpha. 147 It is preferable to use GL_ARB_texture_swizzle instead of this 148 flag. 149 */ 150 kSmearRed_InConfigFlag = 0x04, 151 152 /** 153 Multiply r,g,b by a after texture reads. This flag incompatible 154 with kSmearAlpha and may only be used with FetchMode kSingle. 155 156 It is assumed the src texture has 8bit color components. After 157 reading the texture one version rounds up to the next multiple 158 of 1/255.0 and the other rounds down. At most one of these 159 flags may be set. 160 */ 161 kMulRGBByAlpha_RoundUp_InConfigFlag = 0x08, 162 kMulRGBByAlpha_RoundDown_InConfigFlag = 0x10, 163 164 kDummyInConfigFlag, 165 kInConfigBitMask = (kDummyInConfigFlag-1) | 166 (kDummyInConfigFlag-2) 167 }; 168 enum CoordMapping { 169 kIdentity_CoordMapping, 170 kRadialGradient_CoordMapping, 171 kSweepGradient_CoordMapping, 172 kRadial2Gradient_CoordMapping, 173 // need different shader computation when quadratic 174 // eq describing the gradient degenerates to a linear eq. 175 kRadial2GradientDegenerate_CoordMapping, 176 kCoordMappingCnt 177 }; 178 179 uint8_t fOptFlags; 180 uint8_t fInConfigFlags; // bitfield of InConfigFlags values 181 uint8_t fFetchMode; // casts to enum FetchMode 182 uint8_t fCoordMapping; // casts to enum CoordMapping 183 uint8_t fKernelWidth; 184 185 /** Non-zero if user-supplied code will write the stage's 186 contribution to the fragment shader. */ 187 uint16_t fCustomStageKey; 188 189 GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask == 190 kInConfigBitMask); 191 192 inline bool isEnabled() const { 193 return SkToBool(fOptFlags & kIsEnabled_OptFlagBit); 194 } 195 inline void setEnabled(bool newValue) { 196 if (newValue) { 197 fOptFlags |= kIsEnabled_OptFlagBit; 198 } else { 199 fOptFlags &= ~kIsEnabled_OptFlagBit; 200 } 201 } 202 }; 203 204 // Specifies where the intitial color comes from before the stages are 205 // applied. 206 enum ColorInput { 207 kSolidWhite_ColorInput, 208 kTransBlack_ColorInput, 209 kAttribute_ColorInput, 210 kUniform_ColorInput, 211 212 kColorInputCnt 213 }; 214 // Dual-src blending makes use of a secondary output color that can be 215 // used as a per-pixel blend coeffecient. This controls whether a 216 // secondary source is output and what value it holds. 217 enum DualSrcOutput { 218 kNone_DualSrcOutput, 219 kCoverage_DualSrcOutput, 220 kCoverageISA_DualSrcOutput, 221 kCoverageISC_DualSrcOutput, 222 223 kDualSrcOutputCnt 224 }; 225 226 GrDrawState::VertexEdgeType fVertexEdgeType; 227 228 // stripped of bits that don't affect prog generation 229 GrVertexLayout fVertexLayout; 230 231 StageDesc fStages[GrDrawState::kNumStages]; 232 233 // To enable experimental geometry shader code (not for use in 234 // production) 235#if GR_GL_EXPERIMENTAL_GS 236 bool fExperimentalGS; 237#endif 238 239 uint8_t fColorInput; // casts to enum ColorInput 240 uint8_t fCoverageInput; // casts to enum CoverageInput 241 uint8_t fOutputConfig; // casts to enum OutputConfig 242 uint8_t fDualSrcOutput; // casts to enum DualSrcOutput 243 int8_t fFirstCoverageStage; 244 SkBool8 fEmitsPointSize; 245 SkBool8 fEdgeAAConcave; 246 SkBool8 fColorMatrixEnabled; 247 248 int8_t fEdgeAANumEdges; 249 uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode 250 int8_t fPadding[3]; 251 252 } fProgramDesc; 253 GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4)); 254 255 // for code readability 256 typedef ProgramDesc::StageDesc StageDesc; 257 258private: 259 260 const ProgramDesc& getDesc() { return fProgramDesc; } 261 const char* adjustInColor(const GrStringBuilder& inColor) const; 262 263public: 264 enum { 265 kUnusedUniform = -1, 266 kSetAsAttribute = 1000, 267 }; 268 269 struct StageUniLocations { 270 GrGLint fTextureMatrixUni; 271 GrGLint fNormalizedTexelSizeUni; 272 GrGLint fSamplerUni; 273 GrGLint fRadial2Uni; 274 GrGLint fTexDomUni; 275 GrGLint fKernelUni; 276 GrGLint fImageIncrementUni; 277 void reset() { 278 fTextureMatrixUni = kUnusedUniform; 279 fNormalizedTexelSizeUni = kUnusedUniform; 280 fSamplerUni = kUnusedUniform; 281 fRadial2Uni = kUnusedUniform; 282 fTexDomUni = kUnusedUniform; 283 fKernelUni = kUnusedUniform; 284 fImageIncrementUni = kUnusedUniform; 285 } 286 }; 287 288 struct UniLocations { 289 GrGLint fViewMatrixUni; 290 GrGLint fColorUni; 291 GrGLint fCoverageUni; 292 GrGLint fEdgesUni; 293 GrGLint fColorFilterUni; 294 GrGLint fColorMatrixUni; 295 GrGLint fColorMatrixVecUni; 296 StageUniLocations fStages[GrDrawState::kNumStages]; 297 void reset() { 298 fViewMatrixUni = kUnusedUniform; 299 fColorUni = kUnusedUniform; 300 fCoverageUni = kUnusedUniform; 301 fEdgesUni = kUnusedUniform; 302 fColorFilterUni = kUnusedUniform; 303 fColorMatrixUni = kUnusedUniform; 304 fColorMatrixVecUni = kUnusedUniform; 305 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 306 fStages[s].reset(); 307 } 308 } 309 }; 310 311 class CachedData : public ::GrNoncopyable { 312 public: 313 CachedData() { 314 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 315 fCustomStage[i] = NULL; 316 } 317 } 318 319 ~CachedData(); 320 321 void copyAndTakeOwnership(CachedData& other) { 322 memcpy(this, &other, sizeof(*this)); 323 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 324 other.fCustomStage[i] = NULL; 325 } 326 } 327 328 public: 329 330 // IDs 331 GrGLuint fVShaderID; 332 GrGLuint fGShaderID; 333 GrGLuint fFShaderID; 334 GrGLuint fProgramID; 335 // shader uniform locations (-1 if shader doesn't use them) 336 UniLocations fUniLocations; 337 338 GrMatrix fViewMatrix; 339 340 // these reflect the current values of uniforms 341 // (GL uniform values travel with program) 342 GrColor fColor; 343 GrColor fCoverage; 344 GrColor fColorFilterColor; 345 GrMatrix fTextureMatrices[GrDrawState::kNumStages]; 346 // width and height used for normalized texel size 347 int fTextureWidth[GrDrawState::kNumStages]; 348 int fTextureHeight[GrDrawState::kNumStages]; 349 GrScalar fRadial2CenterX1[GrDrawState::kNumStages]; 350 GrScalar fRadial2Radius0[GrDrawState::kNumStages]; 351 bool fRadial2PosRoot[GrDrawState::kNumStages]; 352 GrRect fTextureDomain[GrDrawState::kNumStages]; 353 354 GrGLProgramStage* fCustomStage[GrDrawState::kNumStages]; 355 356 private: 357 enum Constants { 358 kUniLocationPreAllocSize = 8 359 }; 360 361 }; // CachedData 362 363 enum Constants { 364 kProgramKeySize = sizeof(ProgramDesc) 365 }; 366 367 // Provide an opaque ProgramDesc 368 const uint32_t* keyData() const{ 369 return reinterpret_cast<const uint32_t*>(&fProgramDesc); 370 } 371 372private: 373 374 // Determines which uniforms will need to be bound. 375 void genStageCode(const GrGLContextInfo& gl, 376 int stageNum, 377 const ProgramDesc::StageDesc& desc, 378 const char* fsInColor, // NULL means no incoming color 379 const char* fsOutColor, 380 const char* vsInCoord, 381 ShaderCodeSegments* segments, 382 StageUniLocations* locations, 383 GrGLProgramStage* override) const; 384 385 void genGeometryShader(const GrGLContextInfo& gl, 386 ShaderCodeSegments* segments) const; 387 388 // generates code to compute coverage based on edge AA. 389 void genEdgeCoverage(const GrGLContextInfo& gl, 390 GrVertexLayout layout, 391 CachedData* programData, 392 GrStringBuilder* coverageVar, 393 ShaderCodeSegments* segments) const; 394 395 static bool CompileShaders(const GrGLContextInfo& gl, 396 const ShaderCodeSegments& segments, 397 CachedData* programData); 398 399 // Compiles a GL shader, returns shader ID or 0 if failed 400 // params have same meaning as glShaderSource 401 static GrGLuint CompileShader(const GrGLContextInfo& gl, 402 GrGLenum type, int stringCnt, 403 const char** strings, 404 int* stringLengths); 405 406 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and 407 // links the program 408 bool bindOutputsAttribsAndLinkProgram( 409 const GrGLContextInfo& gl, 410 GrStringBuilder texCoordAttrNames[GrDrawState::kMaxTexCoords], 411 bool bindColorOut, 412 bool bindDualSrcOut, 413 CachedData* programData) const; 414 415 // Binds uniforms; initializes cache to invalid values. 416 void getUniformLocationsAndInitCache(const GrGLContextInfo& gl, 417 CachedData* programData) const; 418 419 friend class GrGpuGLShaders; 420}; 421 422#endif 423