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