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 "GrDrawEffect.h" 12 #include "GrTexture.h" 13 14 // number of each input/output type in a single allocation block 15 static const int kVarsPerBlock = 8; 16 17 // except FS outputs where we expect 2 at most. 18 static const int kMaxFSOutputs = 2; 19 20 // ES2 FS only guarantees mediump and lowp support 21 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 22 23 typedef GrGLUniformManager::UniformHandle UniformHandle; 24 /////////////////////////////////////////////////////////////////////////////// 25 26 namespace { 27 28 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { 29 if (kVec2f_GrSLType == type) { 30 return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; 31 } else { 32 GrAssert(kVec3f_GrSLType == type); 33 return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; 34 } 35 } 36 37 /** 38 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are 39 * present in the texture's config. swizzleComponentMask indicates the channels present in the 40 * shader swizzle. 41 */ 42 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, 43 uint32_t configComponentMask, 44 uint32_t swizzleComponentMask) { 45 if (caps.textureSwizzleSupport()) { 46 // Any remapping is handled using texture swizzling not shader modifications. 47 return false; 48 } 49 // check if the texture is alpha-only 50 if (kA_GrColorComponentFlag == configComponentMask) { 51 if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { 52 // we must map the swizzle 'a's to 'r'. 53 return true; 54 } 55 if (kRGB_GrColorComponentFlags & swizzleComponentMask) { 56 // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that 57 // alpha-only textures smear alpha across all four channels when read. 58 return true; 59 } 60 } 61 return false; 62 } 63 64 void append_swizzle(SkString* outAppend, 65 const GrGLShaderBuilder::TextureSampler& texSampler, 66 const GrGLCaps& caps) { 67 const char* swizzle = texSampler.swizzle(); 68 char mangledSwizzle[5]; 69 70 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle 71 // is available. 72 if (!caps.textureSwizzleSupport() && 73 (kA_GrColorComponentFlag == texSampler.configComponentMask())) { 74 char alphaChar = caps.textureRedSupport() ? 'r' : 'a'; 75 int i; 76 for (i = 0; '\0' != swizzle[i]; ++i) { 77 mangledSwizzle[i] = alphaChar; 78 } 79 mangledSwizzle[i] ='\0'; 80 swizzle = mangledSwizzle; 81 } 82 // For shader prettiness we omit the swizzle rather than appending ".rgba". 83 if (memcmp(swizzle, "rgba", 4)) { 84 outAppend->appendf(".%s", swizzle); 85 } 86 } 87 88 } 89 90 static const char kDstCopyColorName[] = "_dstColor"; 91 92 /////////////////////////////////////////////////////////////////////////////// 93 94 GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, 95 GrGLUniformManager& uniformManager, 96 const GrGLProgramDesc& desc) 97 : fUniforms(kVarsPerBlock) 98 , fVSAttrs(kVarsPerBlock) 99 , fVSOutputs(kVarsPerBlock) 100 , fGSInputs(kVarsPerBlock) 101 , fGSOutputs(kVarsPerBlock) 102 , fFSInputs(kVarsPerBlock) 103 , fFSOutputs(kMaxFSOutputs) 104 , fCtxInfo(ctxInfo) 105 , fUniformManager(uniformManager) 106 , fFSFeaturesAddedMask(0) 107 #if GR_GL_EXPERIMENTAL_GS 108 , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS)) 109 #else 110 , fUsesGS(false) 111 #endif 112 , fSetupFragPosition(false) 113 , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) 114 , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle) 115 , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle) 116 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { 117 118 const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); 119 120 fPositionVar = &fVSAttrs.push_back(); 121 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); 122 if (-1 != header.fLocalCoordAttributeIndex) { 123 fLocalCoordsVar = &fVSAttrs.push_back(); 124 fLocalCoordsVar->set(kVec2f_GrSLType, 125 GrGLShaderVar::kAttribute_TypeModifier, 126 "aLocalCoords"); 127 } else { 128 fLocalCoordsVar = fPositionVar; 129 } 130 // Emit code to read the dst copy textue if necessary. 131 if (kNoDstRead_DstReadKey != header.fDstReadKey && 132 GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) { 133 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); 134 const char* dstCopyTopLeftName; 135 const char* dstCopyCoordScaleName; 136 uint32_t configMask; 137 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { 138 configMask = kA_GrColorComponentFlag; 139 } else { 140 configMask = kRGBA_GrColorComponentFlags; 141 } 142 fDstCopySampler.init(this, configMask, "rgba", 0); 143 144 fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType, 145 kVec2f_GrSLType, 146 "DstCopyUpperLeft", 147 &dstCopyTopLeftName); 148 fDstCopyScaleUniform = this->addUniform(kFragment_ShaderType, 149 kVec2f_GrSLType, 150 "DstCopyCoordScale", 151 &dstCopyCoordScaleName); 152 const char* fragPos = this->fragmentPosition(); 153 this->fsCodeAppend("\t// Read color from copy of the destination.\n"); 154 this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", 155 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); 156 if (!topDown) { 157 this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); 158 } 159 this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); 160 this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord"); 161 this->fsCodeAppend(";\n\n"); 162 } 163 } 164 165 bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { 166 switch (feature) { 167 case kStandardDerivatives_GLSLFeature: 168 if (!fCtxInfo.caps()->shaderDerivativeSupport()) { 169 return false; 170 } 171 if (kES2_GrGLBinding == fCtxInfo.binding()) { 172 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, 173 "GL_OES_standard_derivatives"); 174 } 175 return true; 176 default: 177 GrCrash("Unexpected GLSLFeature requested."); 178 return false; 179 } 180 } 181 182 bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { 183 switch (feature) { 184 case kFragCoordConventions_GLSLPrivateFeature: 185 if (!fCtxInfo.caps()->fragCoordConventionsSupport()) { 186 return false; 187 } 188 if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) { 189 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 190 "GL_ARB_fragment_coord_conventions"); 191 } 192 return true; 193 case kEXTShaderFramebufferFetch_GLSLPrivateFeature: 194 if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) { 195 return false; 196 } 197 this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, 198 "GL_EXT_shader_framebuffer_fetch"); 199 return true; 200 case kNVShaderFramebufferFetch_GLSLPrivateFeature: 201 if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) { 202 return false; 203 } 204 this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, 205 "GL_NV_shader_framebuffer_fetch"); 206 return true; 207 default: 208 GrCrash("Unexpected GLSLPrivateFeature requested."); 209 return false; 210 } 211 } 212 213 void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { 214 if (!(featureBit & fFSFeaturesAddedMask)) { 215 fFSExtensions.appendf("#extension %s: require\n", extensionName); 216 fFSFeaturesAddedMask |= featureBit; 217 } 218 } 219 220 void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { 221 if ('\0' == prefix) { 222 *out = name; 223 } else { 224 out->printf("%c%s", prefix, name); 225 } 226 if (fCodeStage.inStageCode()) { 227 if (out->endsWith('_')) { 228 // Names containing "__" are reserved. 229 out->append("x"); 230 } 231 out->appendf("_Stage%d", fCodeStage.stageIndex()); 232 } 233 } 234 235 const char* GrGLShaderBuilder::dstColor() { 236 if (fCodeStage.inStageCode()) { 237 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 238 if (!effect->willReadDstColor()) { 239 GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect " 240 "did not request access."); 241 return ""; 242 } 243 } 244 static const char kFBFetchColorName[] = "gl_LastFragData[0]"; 245 GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType(); 246 if (GrGLCaps::kEXT_FBFetchType == fetchType) { 247 SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); 248 return kFBFetchColorName; 249 } else if (GrGLCaps::kNV_FBFetchType == fetchType) { 250 SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature)); 251 return kFBFetchColorName; 252 } else if (fDstCopySampler.isInitialized()) { 253 return kDstCopyColorName; 254 } else { 255 return ""; 256 } 257 } 258 259 void GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) { 260 SkString* string = NULL; 261 switch (type) { 262 case kVertex_ShaderType: 263 string = &fVSCode; 264 break; 265 case kGeometry_ShaderType: 266 string = &fGSCode; 267 break; 268 case kFragment_ShaderType: 269 string = &fFSCode; 270 break; 271 default: 272 GrCrash("Invalid shader type"); 273 } 274 string->appendf(format, args); 275 } 276 277 void GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) { 278 SkString* string = NULL; 279 switch (type) { 280 case kVertex_ShaderType: 281 string = &fVSCode; 282 break; 283 case kGeometry_ShaderType: 284 string = &fGSCode; 285 break; 286 case kFragment_ShaderType: 287 string = &fFSCode; 288 break; 289 default: 290 GrCrash("Invalid shader type"); 291 } 292 string->append(str); 293 } 294 295 void GrGLShaderBuilder::appendTextureLookup(SkString* out, 296 const GrGLShaderBuilder::TextureSampler& sampler, 297 const char* coordName, 298 GrSLType varyingType) const { 299 GrAssert(NULL != coordName); 300 301 out->appendf("%s(%s, %s)", 302 sample_function_name(varyingType, fCtxInfo.glslGeneration()), 303 this->getUniformCStr(sampler.fSamplerUniform), 304 coordName); 305 append_swizzle(out, sampler, *fCtxInfo.caps()); 306 } 307 308 void GrGLShaderBuilder::appendTextureLookup(ShaderType type, 309 const GrGLShaderBuilder::TextureSampler& sampler, 310 const char* coordName, 311 GrSLType varyingType) { 312 GrAssert(kFragment_ShaderType == type); 313 this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); 314 } 315 316 void GrGLShaderBuilder::appendTextureLookupAndModulate( 317 ShaderType type, 318 const char* modulation, 319 const GrGLShaderBuilder::TextureSampler& sampler, 320 const char* coordName, 321 GrSLType varyingType) { 322 GrAssert(kFragment_ShaderType == type); 323 SkString lookup; 324 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 325 GrGLSLModulatef<4>(&fFSCode, modulation, lookup.c_str()); 326 } 327 328 GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess( 329 const GrTextureAccess& access, 330 const GrGLCaps& caps) { 331 uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); 332 if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { 333 return 1; 334 } else { 335 return 0; 336 } 337 } 338 339 GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, 340 const GrGLCaps& caps) { 341 uint32_t key = kYesDstRead_DstReadKeyBit; 342 if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) { 343 return key; 344 } 345 GrAssert(NULL != dstCopy); 346 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 347 // The fact that the config is alpha-only must be considered when generating code. 348 key |= kUseAlphaConfig_DstReadKeyBit; 349 } 350 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 351 key |= kTopLeftOrigin_DstReadKeyBit; 352 } 353 GrAssert(static_cast<DstReadKey>(key) == key); 354 return static_cast<DstReadKey>(key); 355 } 356 357 GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, 358 const GrGLCaps&) { 359 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 360 return kTopLeftFragPosRead_FragPosKey; 361 } else { 362 return kBottomLeftFragPosRead_FragPosKey; 363 } 364 } 365 366 367 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 368 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 369 if (caps.textureRedSupport()) { 370 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 371 return gRedSmear; 372 } else { 373 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 374 GR_GL_ALPHA, GR_GL_ALPHA }; 375 return gAlphaSmear; 376 } 377 } else { 378 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 379 return gStraight; 380 } 381 } 382 383 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 384 GrSLType type, 385 const char* name, 386 int count, 387 const char** outName) { 388 GrAssert(name && strlen(name)); 389 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType); 390 GrAssert(0 == (~kVisibilityMask & visibility)); 391 GrAssert(0 != visibility); 392 393 BuilderUniform& uni = fUniforms.push_back(); 394 UniformHandle h = index_to_handle(fUniforms.count() - 1); 395 GR_DEBUGCODE(UniformHandle h2 =) 396 fUniformManager.appendUniform(type, count); 397 // We expect the uniform manager to initially have no uniforms and that all uniforms are added 398 // by this function. Therefore, the handles should match. 399 GrAssert(h2 == h); 400 uni.fVariable.setType(type); 401 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 402 this->nameVariable(uni.fVariable.accessName(), 'u', name); 403 uni.fVariable.setArrayCount(count); 404 uni.fVisibility = visibility; 405 406 // If it is visible in both the VS and FS, the precision must match. 407 // We declare a default FS precision, but not a default VS. So set the var 408 // to use the default FS precision. 409 if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { 410 // the fragment and vertex precisions must match 411 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 412 } 413 414 if (NULL != outName) { 415 *outName = uni.fVariable.c_str(); 416 } 417 418 return h; 419 } 420 421 const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const { 422 return fUniforms[handle_to_index(u)].fVariable; 423 } 424 425 bool GrGLShaderBuilder::addAttribute(GrSLType type, 426 const char* name) { 427 for (int i = 0; i < fVSAttrs.count(); ++i) { 428 const GrGLShaderVar& attr = fVSAttrs[i]; 429 // if attribute already added, don't add it again 430 if (attr.getName().equals(name)) { 431 GrAssert(attr.getType() == type); 432 return false; 433 } 434 } 435 fVSAttrs.push_back().set(type, 436 GrGLShaderVar::kAttribute_TypeModifier, 437 name); 438 return true; 439 } 440 441 void GrGLShaderBuilder::addVarying(GrSLType type, 442 const char* name, 443 const char** vsOutName, 444 const char** fsInName) { 445 fVSOutputs.push_back(); 446 fVSOutputs.back().setType(type); 447 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 448 this->nameVariable(fVSOutputs.back().accessName(), 'v', name); 449 450 if (vsOutName) { 451 *vsOutName = fVSOutputs.back().getName().c_str(); 452 } 453 // input to FS comes either from VS or GS 454 const SkString* fsName; 455 if (fUsesGS) { 456 // if we have a GS take each varying in as an array 457 // and output as non-array. 458 fGSInputs.push_back(); 459 fGSInputs.back().setType(type); 460 fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); 461 fGSInputs.back().setUnsizedArray(); 462 *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 463 fGSOutputs.push_back(); 464 fGSOutputs.back().setType(type); 465 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 466 this->nameVariable(fGSOutputs.back().accessName(), 'g', name); 467 fsName = fGSOutputs.back().accessName(); 468 } else { 469 fsName = fVSOutputs.back().accessName(); 470 } 471 fFSInputs.push_back(); 472 fFSInputs.back().setType(type); 473 fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); 474 fFSInputs.back().setName(*fsName); 475 if (fsInName) { 476 *fsInName = fsName->c_str(); 477 } 478 } 479 480 const char* GrGLShaderBuilder::fragmentPosition() { 481 if (fCodeStage.inStageCode()) { 482 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 483 if (!effect->willReadFragmentPosition()) { 484 GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect " 485 "did not request access."); 486 return ""; 487 } 488 } 489 if (fTopLeftFragPosRead) { 490 if (!fSetupFragPosition) { 491 fFSInputs.push_back().set(kVec4f_GrSLType, 492 GrGLShaderVar::kIn_TypeModifier, 493 "gl_FragCoord", 494 GrGLShaderVar::kDefault_Precision); 495 fSetupFragPosition = true; 496 } 497 return "gl_FragCoord"; 498 } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) { 499 if (!fSetupFragPosition) { 500 SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); 501 fFSInputs.push_back().set(kVec4f_GrSLType, 502 GrGLShaderVar::kIn_TypeModifier, 503 "gl_FragCoord", 504 GrGLShaderVar::kDefault_Precision, 505 GrGLShaderVar::kUpperLeft_Origin); 506 fSetupFragPosition = true; 507 } 508 return "gl_FragCoord"; 509 } else { 510 static const char* kCoordName = "fragCoordYDown"; 511 if (!fSetupFragPosition) { 512 // temporarily change the stage index because we're inserting non-stage code. 513 CodeStage::AutoStageRestore csar(&fCodeStage, NULL); 514 515 GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform); 516 const char* rtHeightName; 517 518 fRTHeightUniform = this->addUniform(kFragment_ShaderType, 519 kFloat_GrSLType, 520 "RTHeight", 521 &rtHeightName); 522 523 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", 524 kCoordName, rtHeightName); 525 fSetupFragPosition = true; 526 } 527 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform); 528 return kCoordName; 529 } 530 } 531 532 533 void GrGLShaderBuilder::emitFunction(ShaderType shader, 534 GrSLType returnType, 535 const char* name, 536 int argCnt, 537 const GrGLShaderVar* args, 538 const char* body, 539 SkString* outName) { 540 GrAssert(kFragment_ShaderType == shader); 541 fFSFunctions.append(GrGLSLTypeString(returnType)); 542 this->nameVariable(outName, '\0', name); 543 fFSFunctions.appendf(" %s", outName->c_str()); 544 fFSFunctions.append("("); 545 for (int i = 0; i < argCnt; ++i) { 546 args[i].appendDecl(fCtxInfo, &fFSFunctions); 547 if (i < argCnt - 1) { 548 fFSFunctions.append(", "); 549 } 550 } 551 fFSFunctions.append(") {\n"); 552 fFSFunctions.append(body); 553 fFSFunctions.append("}\n\n"); 554 } 555 556 namespace { 557 558 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 559 GrGLBinding binding, 560 SkString* str) { 561 // Desktop GLSL has added precision qualifiers but they don't do anything. 562 if (kES2_GrGLBinding == binding) { 563 switch (p) { 564 case GrGLShaderVar::kHigh_Precision: 565 str->append("precision highp float;\n"); 566 break; 567 case GrGLShaderVar::kMedium_Precision: 568 str->append("precision mediump float;\n"); 569 break; 570 case GrGLShaderVar::kLow_Precision: 571 str->append("precision lowp float;\n"); 572 break; 573 case GrGLShaderVar::kDefault_Precision: 574 GrCrash("Default precision now allowed."); 575 default: 576 GrCrash("Unknown precision value."); 577 } 578 } 579 } 580 } 581 582 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 583 for (int i = 0; i < vars.count(); ++i) { 584 vars[i].appendDecl(fCtxInfo, out); 585 out->append(";\n"); 586 } 587 } 588 589 void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const { 590 for (int i = 0; i < fUniforms.count(); ++i) { 591 if (fUniforms[i].fVisibility & stype) { 592 fUniforms[i].fVariable.appendDecl(fCtxInfo, out); 593 out->append(";\n"); 594 } 595 } 596 } 597 598 void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { 599 const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration()); 600 601 switch (type) { 602 case kVertex_ShaderType: 603 *shaderStr = version; 604 this->appendUniformDecls(kVertex_ShaderType, shaderStr); 605 this->appendDecls(fVSAttrs, shaderStr); 606 this->appendDecls(fVSOutputs, shaderStr); 607 shaderStr->append("void main() {\n"); 608 shaderStr->append(fVSCode); 609 shaderStr->append("}\n"); 610 break; 611 case kGeometry_ShaderType: 612 if (fUsesGS) { 613 *shaderStr = version; 614 shaderStr->append(fGSHeader); 615 this->appendDecls(fGSInputs, shaderStr); 616 this->appendDecls(fGSOutputs, shaderStr); 617 shaderStr->append("void main() {\n"); 618 shaderStr->append(fGSCode); 619 shaderStr->append("}\n"); 620 } else { 621 shaderStr->reset(); 622 } 623 break; 624 case kFragment_ShaderType: 625 *shaderStr = version; 626 shaderStr->append(fFSExtensions); 627 append_default_precision_qualifier(kDefaultFragmentPrecision, 628 fCtxInfo.binding(), 629 shaderStr); 630 this->appendUniformDecls(kFragment_ShaderType, shaderStr); 631 this->appendDecls(fFSInputs, shaderStr); 632 // We shouldn't have declared outputs on 1.10 633 GrAssert(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty()); 634 this->appendDecls(fFSOutputs, shaderStr); 635 shaderStr->append(fFSFunctions); 636 shaderStr->append("void main() {\n"); 637 shaderStr->append(fFSCode); 638 shaderStr->append("}\n"); 639 break; 640 } 641 } 642 643 void GrGLShaderBuilder::finished(GrGLuint programID) { 644 fUniformManager.getUniformLocations(programID, fUniforms); 645 } 646 647 void GrGLShaderBuilder::emitEffects( 648 const GrEffectStage* effectStages[], 649 const GrBackendEffectFactory::EffectKey effectKeys[], 650 int effectCnt, 651 SkString* fsInOutColor, 652 GrSLConstantVec* fsInOutColorKnownValue, 653 SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[], 654 GrGLEffect* glEffects[]) { 655 bool effectEmitted = false; 656 657 SkString inColor = *fsInOutColor; 658 SkString outColor; 659 660 for (int e = 0; e < effectCnt; ++e) { 661 GrAssert(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); 662 const GrEffectStage& stage = *effectStages[e]; 663 const GrEffectRef& effect = *stage.getEffect(); 664 665 CodeStage::AutoStageRestore csar(&fCodeStage, &stage); 666 667 int numTextures = effect->numTextures(); 668 SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; 669 textureSamplers.push_back_n(numTextures); 670 for (int t = 0; t < numTextures; ++t) { 671 textureSamplers[t].init(this, &effect->textureAccess(t), t); 672 effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform); 673 } 674 GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords()); 675 676 int numAttributes = stage.getVertexAttribIndexCount(); 677 const int* attributeIndices = stage.getVertexAttribIndices(); 678 SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames; 679 for (int a = 0; a < numAttributes; ++a) { 680 // TODO: Make addAttribute mangle the name. 681 SkString attributeName("aAttr"); 682 attributeName.appendS32(attributeIndices[a]); 683 if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) { 684 fEffectAttributes.push_back().set(attributeIndices[a], attributeName); 685 } 686 } 687 688 glEffects[e] = effect->getFactory().createGLInstance(drawEffect); 689 690 if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) { 691 // Effects have no way to communicate zeros, they treat an empty string as ones. 692 this->nameVariable(&inColor, '\0', "input"); 693 this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4)); 694 } 695 696 // create var to hold stage result 697 this->nameVariable(&outColor, '\0', "output"); 698 this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str()); 699 700 // Enclose custom code in a block to avoid namespace conflicts 701 SkString openBrace; 702 openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name()); 703 this->fVSCode.append(openBrace); 704 this->fFSCode.append(openBrace); 705 706 glEffects[e]->emitCode(this, 707 drawEffect, 708 effectKeys[e], 709 outColor.c_str(), 710 inColor.isEmpty() ? NULL : inColor.c_str(), 711 textureSamplers); 712 this->fVSCode.append("\t}\n"); 713 this->fFSCode.append("\t}\n"); 714 715 inColor = outColor; 716 *fsInOutColorKnownValue = kNone_GrSLConstantVec; 717 effectEmitted = true; 718 } 719 720 if (effectEmitted) { 721 *fsInOutColor = outColor; 722 } 723 } 724 725 const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const { 726 const AttributePair* attribEnd = this->getEffectAttributes().end(); 727 for (const AttributePair* attrib = this->getEffectAttributes().begin(); 728 attrib != attribEnd; 729 ++attrib) { 730 if (attrib->fIndex == attributeIndex) { 731 return &attrib->fName; 732 } 733 } 734 735 return NULL; 736 } 737