1 /* 2 * Copyright 2013 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 #ifndef GrGLProgramEffects_DEFINED 9 #define GrGLProgramEffects_DEFINED 10 11 #include "GrBackendEffectFactory.h" 12 #include "GrTexture.h" 13 #include "GrTextureAccess.h" 14 #include "GrGLUniformManager.h" 15 16 class GrEffectStage; 17 class GrGLVertexProgramEffectsBuilder; 18 class GrGLShaderBuilder; 19 class GrGLFullShaderBuilder; 20 class GrGLFragmentOnlyShaderBuilder; 21 22 /** 23 * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms 24 * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL 25 * state and shader uniforms. 26 */ 27 class GrGLProgramEffects { 28 public: 29 typedef GrBackendEffectFactory::EffectKey EffectKey; 30 typedef GrGLUniformManager::UniformHandle UniformHandle; 31 32 /** 33 * These methods generate different portions of an effect's final key. 34 */ 35 static EffectKey GenAttribKey(const GrDrawEffect&); 36 static EffectKey GenTransformKey(const GrDrawEffect&); 37 static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&); 38 39 virtual ~GrGLProgramEffects(); 40 41 /** 42 * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next 43 * available unit to *texUnitIdx when it returns. 44 */ 45 void initSamplers(const GrGLUniformManager&, int* texUnitIdx); 46 47 /** 48 * Calls setData() on each effect, and sets their transformation matrices and texture bindings. 49 */ 50 virtual void setData(GrGpuGL*, 51 const GrGLUniformManager&, 52 const GrEffectStage* effectStages[]) = 0; 53 54 /** 55 * Passed to GrGLEffects so they can add transformed coordinates to their shader code. 56 */ 57 class TransformedCoords { 58 public: 59 TransformedCoords(const SkString& name, GrSLType type) 60 : fName(name), fType(type) { 61 } 62 63 const char* c_str() const { return fName.c_str(); } 64 GrSLType type() const { return fType; } 65 const SkString& getName() const { return fName; } 66 67 private: 68 SkString fName; 69 GrSLType fType; 70 }; 71 72 typedef SkTArray<TransformedCoords> TransformedCoordsArray; 73 74 /** 75 * Passed to GrGLEffects so they can add texture reads to their shader code. 76 */ 77 class TextureSampler { 78 public: 79 TextureSampler(UniformHandle uniform, const GrTextureAccess& access) 80 : fSamplerUniform(uniform) 81 , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) { 82 SkASSERT(0 != fConfigComponentMask); 83 memcpy(fSwizzle, access.getSwizzle(), 5); 84 } 85 86 UniformHandle samplerUniform() const { return fSamplerUniform; } 87 // bitfield of GrColorComponentFlags present in the texture's config. 88 uint32_t configComponentMask() const { return fConfigComponentMask; } 89 const char* swizzle() const { return fSwizzle; } 90 91 private: 92 UniformHandle fSamplerUniform; 93 uint32_t fConfigComponentMask; 94 char fSwizzle[5]; 95 }; 96 97 typedef SkTArray<TextureSampler> TextureSamplerArray; 98 99 protected: 100 GrGLProgramEffects(int reserveCount) 101 : fGLEffects(reserveCount) 102 , fSamplers(reserveCount) { 103 } 104 105 /** 106 * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and 107 * appends the necessary data to the TextureSamplerArray* object so effects can add texture 108 * lookups to their code. This method is only meant to be called during the construction phase. 109 */ 110 void emitSamplers(GrGLShaderBuilder*, const GrEffectRef&, TextureSamplerArray*); 111 112 /** 113 * Helper for setData(). Binds all the textures for an effect. 114 */ 115 void bindTextures(GrGpuGL*, const GrEffectRef&, int effectIdx); 116 117 struct Sampler { 118 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {}) 119 UniformHandle fUniform; 120 int fTextureUnit; 121 }; 122 123 SkTArray<GrGLEffect*> fGLEffects; 124 SkTArray<SkSTArray<4, Sampler, true> > fSamplers; 125 }; 126 127 /** 128 * This is an abstract base class for constructing different types of GrGLProgramEffects objects. 129 */ 130 class GrGLProgramEffectsBuilder { 131 public: 132 virtual ~GrGLProgramEffectsBuilder() { } 133 134 /** 135 * Emits the effect's shader code, and stores the necessary uniforms internally. 136 */ 137 virtual void emitEffect(const GrEffectStage&, 138 GrGLProgramEffects::EffectKey, 139 const char* outColor, 140 const char* inColor, 141 int stageIndex) = 0; 142 }; 143 144 //////////////////////////////////////////////////////////////////////////////// 145 146 /** 147 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader. 148 */ 149 class GrGLVertexProgramEffects : public GrGLProgramEffects { 150 public: 151 virtual void setData(GrGpuGL*, 152 const GrGLUniformManager&, 153 const GrEffectStage* effectStages[]) SK_OVERRIDE; 154 155 private: 156 friend class GrGLVertexProgramEffectsBuilder; 157 158 GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords) 159 : INHERITED(reserveCount) 160 , fTransforms(reserveCount) 161 , fHasExplicitLocalCoords(explicitLocalCoords) { 162 } 163 164 /** 165 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called 166 * during the construction phase. 167 */ 168 void emitEffect(GrGLFullShaderBuilder*, 169 const GrEffectStage&, 170 GrGLProgramEffects::EffectKey, 171 const char* outColor, 172 const char* inColor, 173 int stageIndex); 174 175 /** 176 * Helper for emitEffect(). Emits any attributes an effect may have. 177 */ 178 void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&); 179 180 /** 181 * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS. 182 * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a 183 * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names 184 * of the varyings in the VS and FS as well their types are appended to the 185 * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function. 186 */ 187 void emitTransforms(GrGLFullShaderBuilder*, 188 const GrEffectRef&, 189 EffectKey, 190 TransformedCoordsArray*); 191 192 /** 193 * Helper for setData(). Sets all the transform matrices for an effect. 194 */ 195 void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx); 196 197 struct Transform { 198 Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); } 199 UniformHandle fHandle; 200 GrSLType fType; 201 SkMatrix fCurrentValue; 202 }; 203 204 SkTArray<SkSTArray<2, Transform, true> > fTransforms; 205 bool fHasExplicitLocalCoords; 206 207 typedef GrGLProgramEffects INHERITED; 208 }; 209 210 /** 211 * This class is used to construct a GrGLVertexProgramEffects* object. 212 */ 213 class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder { 214 public: 215 GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount); 216 virtual ~GrGLVertexProgramEffectsBuilder() { } 217 218 virtual void emitEffect(const GrEffectStage&, 219 GrGLProgramEffects::EffectKey, 220 const char* outColor, 221 const char* inColor, 222 int stageIndex) SK_OVERRIDE; 223 224 /** 225 * Finalizes the building process and returns the effect array. After this call, the builder 226 * becomes invalid. 227 */ 228 GrGLProgramEffects* finish() { return fProgramEffects.detach(); } 229 230 private: 231 GrGLFullShaderBuilder* fBuilder; 232 SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects; 233 234 typedef GrGLProgramEffectsBuilder INHERITED; 235 }; 236 237 //////////////////////////////////////////////////////////////////////////////// 238 239 /** 240 * This is a GrGLProgramEffects implementation that does coord transforms with the the built-in GL 241 * TexGen functionality. 242 */ 243 class GrGLTexGenProgramEffects : public GrGLProgramEffects { 244 public: 245 virtual void setData(GrGpuGL*, 246 const GrGLUniformManager&, 247 const GrEffectStage* effectStages[]) SK_OVERRIDE; 248 249 private: 250 friend class GrGLTexGenProgramEffectsBuilder; 251 252 GrGLTexGenProgramEffects(int reserveCount) 253 : INHERITED(reserveCount) 254 , fTransforms(reserveCount) { 255 } 256 257 /** 258 * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called 259 * during the construction phase. 260 */ 261 void emitEffect(GrGLFragmentOnlyShaderBuilder*, 262 const GrEffectStage&, 263 GrGLProgramEffects::EffectKey, 264 const char* outColor, 265 const char* inColor, 266 int stageIndex); 267 268 /** 269 * Helper for emitEffect(). Allocates texture units from the builder for each transform in an 270 * effect. The transforms all use adjacent texture units. They either use two or three of the 271 * coordinates at a given texture unit, depending on if they need perspective interpolation. 272 * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the 273 * types are appended to the TransformedCoordsArray* object, which is in turn passed to the 274 * effect's emitCode() function. 275 */ 276 void setupTexGen(GrGLFragmentOnlyShaderBuilder*, 277 const GrEffectRef&, 278 EffectKey, 279 TransformedCoordsArray*); 280 281 /** 282 * Helper for setData(). Sets the TexGen state for each transform in an effect. 283 */ 284 void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx); 285 286 struct Transforms { 287 Transforms(EffectKey transformKey, int texCoordIndex) 288 : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {} 289 EffectKey fTransformKey; 290 int fTexCoordIndex; 291 }; 292 293 SkTArray<Transforms> fTransforms; 294 295 typedef GrGLProgramEffects INHERITED; 296 }; 297 298 /** 299 * This class is used to construct a GrGLTexGenProgramEffects* object. 300 */ 301 class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder { 302 public: 303 GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount); 304 virtual ~GrGLTexGenProgramEffectsBuilder() { } 305 306 virtual void emitEffect(const GrEffectStage&, 307 GrGLProgramEffects::EffectKey, 308 const char* outColor, 309 const char* inColor, 310 int stageIndex) SK_OVERRIDE; 311 312 /** 313 * Finalizes the building process and returns the effect array. After this call, the builder 314 * becomes invalid. 315 */ 316 GrGLProgramEffects* finish() { return fProgramEffects.detach(); } 317 318 private: 319 GrGLFragmentOnlyShaderBuilder* fBuilder; 320 SkAutoTDelete<GrGLTexGenProgramEffects> fProgramEffects; 321 322 typedef GrGLProgramEffectsBuilder INHERITED; 323 }; 324 325 #endif 326