1 /* 2 Copyright 2011 Google Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #ifndef GrGLProgram_DEFINED 18 #define GrGLProgram_DEFINED 19 20 #include "GrGLInterface.h" 21 #include "GrStringBuilder.h" 22 #include "GrGpu.h" 23 24 #include "SkXfermode.h" 25 26 class GrBinHashKeyBuilder; 27 28 struct ShaderCodeSegments { 29 GrStringBuilder fHeader; // VS+FS, GLSL version, etc 30 GrStringBuilder fVSUnis; 31 GrStringBuilder fVSAttrs; 32 GrStringBuilder fVaryings; 33 GrStringBuilder fFSUnis; 34 GrStringBuilder fFSOutputs; 35 GrStringBuilder fVSCode; 36 GrStringBuilder fFSCode; 37 }; 38 39 /** 40 * This class manages a GPU program and records per-program information. 41 * We can specify the attribute locations so that they are constant 42 * across our shaders. But the driver determines the uniform locations 43 * at link time. We don't need to remember the sampler uniform location 44 * because we will bind a texture slot to it and never change it 45 * Uniforms are program-local so we can't rely on fHWState to hold the 46 * previous uniform state after a program change. 47 */ 48 class GrGLProgram { 49 public: 50 class CachedData; 51 52 GrGLProgram(); 53 ~GrGLProgram(); 54 55 /** 56 * Streams data that can uniquely identifies the generated 57 * gpu program into a key, for cache indexing purposes. 58 * 59 * @param key The key object to receive the key data 60 */ 61 void buildKey(GrBinHashKeyBuilder& key) const; 62 63 /** 64 * This is the heavy initilization routine for building a GLProgram. 65 * The result of heavy init is not stored in datamembers of GrGLProgam, 66 * but in a separate cacheable container. 67 */ 68 bool genProgram(CachedData* programData) const; 69 70 /** 71 * The shader may modify the blend coeffecients. Params are in/out 72 */ 73 void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; 74 75 /** 76 * Attribute indices 77 */ 78 static int PositionAttributeIdx() { return 0; } 79 static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; } 80 static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; } 81 static int ViewMatrixAttributeIdx() { 82 return 2 + GrDrawTarget::kMaxTexCoords; 83 } 84 static int TextureMatrixAttributeIdx(int stage) { 85 return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage; 86 } 87 88 private: 89 90 // Parameters that affect code generation 91 // These structs should be kept compact; they are the input to an 92 // expensive hash key generator. 93 struct ProgramDesc { 94 ProgramDesc() { 95 // since we use this as part of a key we can't have any unitialized 96 // padding 97 memset(this, 0, sizeof(ProgramDesc)); 98 } 99 100 struct StageDesc { 101 enum OptFlagBits { 102 kNoPerspective_OptFlagBit = 1 << 0, 103 kIdentityMatrix_OptFlagBit = 1 << 1, 104 kCustomTextureDomain_OptFlagBit = 1 << 2, 105 kIsEnabled_OptFlagBit = 1 << 7 106 }; 107 enum Modulation { 108 kColor_Modulation, 109 kAlpha_Modulation 110 }; 111 enum FetchMode { 112 kSingle_FetchMode, 113 k2x2_FetchMode 114 }; 115 enum CoordMapping { 116 kIdentity_CoordMapping, 117 kRadialGradient_CoordMapping, 118 kSweepGradient_CoordMapping, 119 kRadial2Gradient_CoordMapping 120 }; 121 122 uint8_t fOptFlags; 123 uint8_t fModulation; // casts to enum Modulation 124 uint8_t fFetchMode; // casts to enum FetchMode 125 uint8_t fCoordMapping; // casts to enum CoordMapping 126 127 inline bool isEnabled() const { 128 return fOptFlags & kIsEnabled_OptFlagBit; 129 } 130 inline void setEnabled(bool newValue) { 131 if (newValue) { 132 fOptFlags |= kIsEnabled_OptFlagBit; 133 } else { 134 fOptFlags &= ~kIsEnabled_OptFlagBit; 135 } 136 } 137 }; 138 139 enum ColorType { 140 kNone_ColorType = 0, 141 kAttribute_ColorType = 1, 142 kUniform_ColorType = 2, 143 }; 144 // Dual-src blending makes use of a secondary output color that can be 145 // used as a per-pixel blend coeffecient. This controls whether a 146 // secondary source is output and what value it holds. 147 enum DualSrcOutput { 148 kNone_DualSrcOutput, 149 kCoverage_DualSrcOutput, 150 kCoverageISA_DualSrcOutput, 151 kCoverageISC_DualSrcOutput, 152 kDualSrcOutputCnt 153 }; 154 155 // stripped of bits that don't affect prog generation 156 GrVertexLayout fVertexLayout; 157 158 StageDesc fStages[GrDrawTarget::kNumStages]; 159 160 uint8_t fColorType; // casts to enum ColorType 161 uint8_t fDualSrcOutput; // casts to enum DualSrcOutput 162 int8_t fFirstCoverageStage; 163 SkBool8 fEmitsPointSize; 164 165 int8_t fEdgeAANumEdges; 166 uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode 167 168 uint8_t fPadTo32bLengthMultiple [2]; 169 170 } fProgramDesc; 171 172 const ProgramDesc& getDesc() { return fProgramDesc; } 173 174 public: 175 enum { 176 kUnusedUniform = -1, 177 kSetAsAttribute = 1000, 178 }; 179 180 struct StageUniLocations { 181 GrGLint fTextureMatrixUni; 182 GrGLint fNormalizedTexelSizeUni; 183 GrGLint fSamplerUni; 184 GrGLint fRadial2Uni; 185 GrGLint fTexDomUni; 186 void reset() { 187 fTextureMatrixUni = kUnusedUniform; 188 fNormalizedTexelSizeUni = kUnusedUniform; 189 fSamplerUni = kUnusedUniform; 190 fRadial2Uni = kUnusedUniform; 191 fTexDomUni = kUnusedUniform; 192 } 193 }; 194 195 struct UniLocations { 196 GrGLint fViewMatrixUni; 197 GrGLint fColorUni; 198 GrGLint fEdgesUni; 199 GrGLint fColorFilterUni; 200 StageUniLocations fStages[GrDrawTarget::kNumStages]; 201 void reset() { 202 fViewMatrixUni = kUnusedUniform; 203 fColorUni = kUnusedUniform; 204 fEdgesUni = kUnusedUniform; 205 fColorFilterUni = kUnusedUniform; 206 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { 207 fStages[s].reset(); 208 } 209 } 210 }; 211 212 class CachedData : public ::GrNoncopyable { 213 public: 214 CachedData() { 215 } 216 217 ~CachedData() { 218 } 219 220 void copyAndTakeOwnership(CachedData& other) { 221 memcpy(this, &other, sizeof(*this)); 222 } 223 224 public: 225 226 // IDs 227 GrGLuint fVShaderID; 228 GrGLuint fFShaderID; 229 GrGLuint fProgramID; 230 // shader uniform locations (-1 if shader doesn't use them) 231 UniLocations fUniLocations; 232 233 GrMatrix fViewMatrix; 234 235 // these reflect the current values of uniforms 236 // (GL uniform values travel with program) 237 GrColor fColor; 238 GrColor fColorFilterColor; 239 GrMatrix fTextureMatrices[GrDrawTarget::kNumStages]; 240 // width and height used for normalized texel size 241 int fTextureWidth[GrDrawTarget::kNumStages]; 242 int fTextureHeight[GrDrawTarget::kNumStages]; 243 GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages]; 244 GrScalar fRadial2Radius0[GrDrawTarget::kNumStages]; 245 bool fRadial2PosRoot[GrDrawTarget::kNumStages]; 246 GrRect fTextureDomain[GrDrawTarget::kNumStages]; 247 248 private: 249 enum Constants { 250 kUniLocationPreAllocSize = 8 251 }; 252 253 }; // CachedData 254 255 private: 256 enum { 257 kUseUniform = 2000 258 }; 259 260 // should set all fields in locations var to kUseUniform if the 261 // corresponding uniform is required for the program. 262 void genStageCode(int stageNum, 263 const ProgramDesc::StageDesc& desc, 264 const char* fsInColor, // NULL means no incoming color 265 const char* fsOutColor, 266 const char* vsInCoord, 267 ShaderCodeSegments* segments, 268 StageUniLocations* locations) const; 269 270 static bool CompileFSAndVS(const ShaderCodeSegments& segments, 271 CachedData* programData); 272 273 // Compiles a GL shader, returns shader ID or 0 if failed 274 // params have same meaning as glShaderSource 275 static GrGLuint CompileShader(GrGLenum type, int stringCnt, 276 const char** strings, 277 int* stringLengths); 278 279 // Creates a GL program ID, binds shader attributes to GL vertex attrs, and 280 // links the program 281 bool bindOutputsAttribsAndLinkProgram( 282 GrStringBuilder texCoordAttrNames[GrDrawTarget::kMaxTexCoords], 283 bool bindColorOut, 284 bool bindDualSrcOut, 285 CachedData* programData) const; 286 287 // Gets locations for all uniforms set to kUseUniform and initializes cache 288 // to invalid values. 289 void getUniformLocationsAndInitCache(CachedData* programData) const; 290 291 friend class GrGpuGLShaders; 292 }; 293 294 #endif 295