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