1 /* 2 * Copyright 2012 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 #include "gl/GrGLShaderBuilder.h" 9 #include "gl/GrGLProgram.h" 10 #include "gl/GrGLUniformHandle.h" 11 #include "GrTexture.h" 12 13 // number of each input/output type in a single allocation block 14 static const int kVarsPerBlock = 8; 15 16 // except FS outputs where we expect 2 at most. 17 static const int kMaxFSOutputs = 2; 18 19 // ES2 FS only guarantees mediump and lowp support 20 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 21 22 typedef GrGLUniformManager::UniformHandle UniformHandle; 23 /////////////////////////////////////////////////////////////////////////////// 24 25 namespace { 26 27 inline const char* sample_function_name(GrSLType type) { 28 if (kVec2f_GrSLType == type) { 29 return "texture2D"; 30 } else { 31 GrAssert(kVec3f_GrSLType == type); 32 return "texture2DProj"; 33 } 34 } 35 36 /** 37 * Do we need to either map r,g,b->a or a->r. 38 */ 39 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, 40 const GrTextureAccess& access) { 41 if (GrPixelConfigIsAlphaOnly(access.getTexture()->config())) { 42 if (caps.textureRedSupport() && (GrTextureAccess::kA_SwizzleFlag & access.swizzleMask())) { 43 return true; 44 } 45 if (GrTextureAccess::kRGB_SwizzleMask & access.swizzleMask()) { 46 return true; 47 } 48 } 49 return false; 50 } 51 52 void append_swizzle(SkString* outAppend, 53 const GrTextureAccess& access, 54 const GrGLCaps& caps) { 55 const char* swizzle = access.getSwizzle(); 56 char mangledSwizzle[5]; 57 58 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle 59 // is available. 60 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(access.getTexture()->config())) { 61 char alphaChar = caps.textureRedSupport() ? 'r' : 'a'; 62 int i; 63 for (i = 0; '\0' != swizzle[i]; ++i) { 64 mangledSwizzle[i] = alphaChar; 65 } 66 mangledSwizzle[i] ='\0'; 67 swizzle = mangledSwizzle; 68 } 69 // For shader prettiness we omit the swizzle rather than appending ".rgba". 70 if (memcmp(swizzle, "rgba", 4)) { 71 outAppend->appendf(".%s", swizzle); 72 } 73 } 74 75 } 76 77 /////////////////////////////////////////////////////////////////////////////// 78 79 // Architectural assumption: always 2-d input coords. 80 // Likely to become non-constant and non-static, perhaps even 81 // varying by stage, if we use 1D textures for gradients! 82 //const int GrGLShaderBuilder::fCoordDims = 2; 83 84 GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformManager& uniformManager) 85 : fUniforms(kVarsPerBlock) 86 , fVSAttrs(kVarsPerBlock) 87 , fVSOutputs(kVarsPerBlock) 88 , fGSInputs(kVarsPerBlock) 89 , fGSOutputs(kVarsPerBlock) 90 , fFSInputs(kVarsPerBlock) 91 , fFSOutputs(kMaxFSOutputs) 92 , fUsesGS(false) 93 , fContext(ctx) 94 , fUniformManager(uniformManager) 95 , fCurrentStageIdx(kNonStageIdx) 96 , fSetupFragPosition(false) 97 , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) { 98 99 fPositionVar = &fVSAttrs.push_back(); 100 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); 101 } 102 103 void GrGLShaderBuilder::appendTextureLookup(SkString* out, 104 const GrGLShaderBuilder::TextureSampler& sampler, 105 const char* coordName, 106 GrSLType varyingType) const { 107 GrAssert(NULL != sampler.textureAccess()); 108 GrAssert(NULL != coordName); 109 110 out->appendf("%s(%s, %s)", 111 sample_function_name(varyingType), 112 this->getUniformCStr(sampler.fSamplerUniform), 113 coordName); 114 append_swizzle(out, *sampler.textureAccess(), fContext.caps()); 115 } 116 117 void GrGLShaderBuilder::appendTextureLookupAndModulate( 118 SkString* out, 119 const char* modulation, 120 const GrGLShaderBuilder::TextureSampler& sampler, 121 const char* coordName, 122 GrSLType varyingType) const { 123 GrAssert(NULL != out); 124 SkString lookup; 125 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 126 GrGLSLModulate4f(out, modulation, lookup.c_str()); 127 } 128 129 GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess( 130 const GrTextureAccess& access, 131 const GrGLCaps& caps) { 132 GrBackendEffectFactory::EffectKey key = 0; 133 134 // Assume that swizzle support implies that we never have to modify a shader to adjust 135 // for texture format/swizzle settings. 136 if (!caps.textureSwizzleSupport() && swizzle_requires_alpha_remapping(caps, access)) { 137 key = 1; 138 } 139 #if GR_DEBUG 140 // Assert that key is set iff the swizzle will be modified. 141 SkString origString(access.getSwizzle()); 142 origString.prepend("."); 143 SkString modifiedString; 144 append_swizzle(&modifiedString, access, caps); 145 if (!modifiedString.size()) { 146 modifiedString = ".rgba"; 147 } 148 GrAssert(SkToBool(key) == (modifiedString != origString)); 149 #endif 150 return key; 151 } 152 153 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 154 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 155 if (caps.textureRedSupport()) { 156 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 157 return gRedSmear; 158 } else { 159 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 160 GR_GL_ALPHA, GR_GL_ALPHA }; 161 return gAlphaSmear; 162 } 163 } else { 164 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 165 return gStraight; 166 } 167 } 168 169 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 170 GrSLType type, 171 const char* name, 172 int count, 173 const char** outName) { 174 GrAssert(name && strlen(name)); 175 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType); 176 GrAssert(0 == (~kVisibilityMask & visibility)); 177 GrAssert(0 != visibility); 178 179 BuilderUniform& uni = fUniforms.push_back(); 180 UniformHandle h = index_to_handle(fUniforms.count() - 1); 181 GR_DEBUGCODE(UniformHandle h2 =) 182 fUniformManager.appendUniform(type, count); 183 // We expect the uniform manager to initially have no uniforms and that all uniforms are added 184 // by this function. Therefore, the handles should match. 185 GrAssert(h2 == h); 186 uni.fVariable.setType(type); 187 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 188 SkString* uniName = uni.fVariable.accessName(); 189 if (kNonStageIdx == fCurrentStageIdx) { 190 uniName->printf("u%s", name); 191 } else { 192 uniName->printf("u%s%d", name, fCurrentStageIdx); 193 } 194 uni.fVariable.setArrayCount(count); 195 uni.fVisibility = visibility; 196 197 // If it is visible in both the VS and FS, the precision must match. 198 // We declare a default FS precision, but not a default VS. So set the var 199 // to use the default FS precision. 200 if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { 201 // the fragment and vertex precisions must match 202 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 203 } 204 205 if (NULL != outName) { 206 *outName = uni.fVariable.c_str(); 207 } 208 209 return h; 210 } 211 212 const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const { 213 return fUniforms[handle_to_index(u)].fVariable; 214 } 215 216 void GrGLShaderBuilder::addVarying(GrSLType type, 217 const char* name, 218 const char** vsOutName, 219 const char** fsInName) { 220 fVSOutputs.push_back(); 221 fVSOutputs.back().setType(type); 222 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); 223 if (kNonStageIdx == fCurrentStageIdx) { 224 fVSOutputs.back().accessName()->printf("v%s", name); 225 } else { 226 fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx); 227 } 228 if (vsOutName) { 229 *vsOutName = fVSOutputs.back().getName().c_str(); 230 } 231 // input to FS comes either from VS or GS 232 const SkString* fsName; 233 if (fUsesGS) { 234 // if we have a GS take each varying in as an array 235 // and output as non-array. 236 fGSInputs.push_back(); 237 fGSInputs.back().setType(type); 238 fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); 239 fGSInputs.back().setUnsizedArray(); 240 *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 241 fGSOutputs.push_back(); 242 fGSOutputs.back().setType(type); 243 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); 244 if (kNonStageIdx == fCurrentStageIdx) { 245 fGSOutputs.back().accessName()->printf("g%s", name); 246 } else { 247 fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx); 248 } 249 fsName = fGSOutputs.back().accessName(); 250 } else { 251 fsName = fVSOutputs.back().accessName(); 252 } 253 fFSInputs.push_back(); 254 fFSInputs.back().setType(type); 255 fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); 256 fFSInputs.back().setName(*fsName); 257 if (fsInName) { 258 *fsInName = fsName->c_str(); 259 } 260 } 261 262 const char* GrGLShaderBuilder::fragmentPosition() { 263 if (fContext.caps().fragCoordConventionsSupport()) { 264 if (!fSetupFragPosition) { 265 fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n"); 266 fFSInputs.push_back().set(kVec4f_GrSLType, 267 GrGLShaderVar::kIn_TypeModifier, 268 "gl_FragCoord", 269 GrGLShaderVar::kDefault_Precision, 270 GrGLShaderVar::kUpperLeft_Origin); 271 fSetupFragPosition = true; 272 } 273 return "gl_FragCoord"; 274 } else { 275 static const char* kCoordName = "fragCoordYDown"; 276 if (!fSetupFragPosition) { 277 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform); 278 const char* rtHeightName; 279 280 // temporarily change the stage index because we're inserting a uniform whose name 281 // shouldn't be mangled to be stage-specific. 282 int oldStageIdx = fCurrentStageIdx; 283 fCurrentStageIdx = kNonStageIdx; 284 fRTHeightUniform = this->addUniform(kFragment_ShaderType, 285 kFloat_GrSLType, 286 "RTHeight", 287 &rtHeightName); 288 fCurrentStageIdx = oldStageIdx; 289 290 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", 291 kCoordName, rtHeightName); 292 fSetupFragPosition = true; 293 } 294 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform); 295 return kCoordName; 296 } 297 } 298 299 300 void GrGLShaderBuilder::emitFunction(ShaderType shader, 301 GrSLType returnType, 302 const char* name, 303 int argCnt, 304 const GrGLShaderVar* args, 305 const char* body, 306 SkString* outName) { 307 GrAssert(kFragment_ShaderType == shader); 308 fFSFunctions.append(GrGLShaderVar::TypeString(returnType)); 309 if (kNonStageIdx != fCurrentStageIdx) { 310 outName->printf(" %s_%d", name, fCurrentStageIdx); 311 } else { 312 *outName = name; 313 } 314 fFSFunctions.append(*outName); 315 fFSFunctions.append("("); 316 for (int i = 0; i < argCnt; ++i) { 317 args[i].appendDecl(fContext, &fFSFunctions); 318 if (i < argCnt - 1) { 319 fFSFunctions.append(", "); 320 } 321 } 322 fFSFunctions.append(") {\n"); 323 fFSFunctions.append(body); 324 fFSFunctions.append("}\n\n"); 325 } 326 327 namespace { 328 329 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 330 GrGLBinding binding, 331 SkString* str) { 332 // Desktop GLSL has added precision qualifiers but they don't do anything. 333 if (kES2_GrGLBinding == binding) { 334 switch (p) { 335 case GrGLShaderVar::kHigh_Precision: 336 str->append("precision highp float;\n"); 337 break; 338 case GrGLShaderVar::kMedium_Precision: 339 str->append("precision mediump float;\n"); 340 break; 341 case GrGLShaderVar::kLow_Precision: 342 str->append("precision lowp float;\n"); 343 break; 344 case GrGLShaderVar::kDefault_Precision: 345 GrCrash("Default precision now allowed."); 346 default: 347 GrCrash("Unknown precision value."); 348 } 349 } 350 } 351 } 352 353 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 354 for (int i = 0; i < vars.count(); ++i) { 355 vars[i].appendDecl(fContext, out); 356 out->append(";\n"); 357 } 358 } 359 360 void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const { 361 for (int i = 0; i < fUniforms.count(); ++i) { 362 if (fUniforms[i].fVisibility & stype) { 363 fUniforms[i].fVariable.appendDecl(fContext, out); 364 out->append(";\n"); 365 } 366 } 367 } 368 369 void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { 370 switch (type) { 371 case kVertex_ShaderType: 372 *shaderStr = fHeader; 373 this->appendUniformDecls(kVertex_ShaderType, shaderStr); 374 this->appendDecls(fVSAttrs, shaderStr); 375 this->appendDecls(fVSOutputs, shaderStr); 376 shaderStr->append("void main() {\n"); 377 shaderStr->append(fVSCode); 378 shaderStr->append("}\n"); 379 break; 380 case kGeometry_ShaderType: 381 if (fUsesGS) { 382 *shaderStr = fHeader; 383 shaderStr->append(fGSHeader); 384 this->appendDecls(fGSInputs, shaderStr); 385 this->appendDecls(fGSOutputs, shaderStr); 386 shaderStr->append("void main() {\n"); 387 shaderStr->append(fGSCode); 388 shaderStr->append("}\n"); 389 } else { 390 shaderStr->reset(); 391 } 392 break; 393 case kFragment_ShaderType: 394 *shaderStr = fHeader; 395 append_default_precision_qualifier(kDefaultFragmentPrecision, 396 fContext.binding(), 397 shaderStr); 398 shaderStr->append(fFSHeader); 399 this->appendUniformDecls(kFragment_ShaderType, shaderStr); 400 this->appendDecls(fFSInputs, shaderStr); 401 // We shouldn't have declared outputs on 1.10 402 GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty()); 403 this->appendDecls(fFSOutputs, shaderStr); 404 shaderStr->append(fFSFunctions); 405 shaderStr->append("void main() {\n"); 406 shaderStr->append(fFSCode); 407 shaderStr->append("}\n"); 408 break; 409 } 410 } 411 412 void GrGLShaderBuilder::finished(GrGLuint programID) { 413 fUniformManager.getUniformLocations(programID, fUniforms); 414 } 415 416 GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect( 417 const GrEffectStage& stage, 418 GrGLEffect::EffectKey key, 419 const char* fsInColor, 420 const char* fsOutColor, 421 const char* vsInCoord, 422 SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) { 423 GrAssert(NULL != stage.getEffect()); 424 425 const GrEffectRef& effect = *stage.getEffect(); 426 int numTextures = effect->numTextures(); 427 SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; 428 textureSamplers.push_back_n(numTextures); 429 for (int i = 0; i < numTextures; ++i) { 430 textureSamplers[i].init(this, &effect->textureAccess(i), i); 431 samplerHandles->push_back(textureSamplers[i].fSamplerUniform); 432 } 433 434 GrGLEffect* glEffect = effect->getFactory().createGLInstance(effect); 435 436 // Enclose custom code in a block to avoid namespace conflicts 437 this->fVSCode.appendf("\t{ // %s\n", glEffect->name()); 438 this->fFSCode.appendf("\t{ // %s \n", glEffect->name()); 439 glEffect->emitCode(this, 440 stage, 441 key, 442 vsInCoord, 443 fsOutColor, 444 fsInColor, 445 textureSamplers); 446 this->fVSCode.appendf("\t}\n"); 447 this->fFSCode.appendf("\t}\n"); 448 449 return glEffect; 450 } 451