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 "GrCoordTransform.h" 12#include "GrDrawEffect.h" 13#include "GrGpuGL.h" 14#include "GrTexture.h" 15#include "SkRTConf.h" 16#include "SkTrace.h" 17 18#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) 19#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) 20 21// number of each input/output type in a single allocation block 22static const int kVarsPerBlock = 8; 23 24// except FS outputs where we expect 2 at most. 25static const int kMaxFSOutputs = 2; 26 27// ES2 FS only guarantees mediump and lowp support 28static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 29 30typedef GrGLUniformManager::UniformHandle UniformHandle; 31 32SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, 33 "Print the source code for all shaders generated."); 34 35/////////////////////////////////////////////////////////////////////////////// 36 37namespace { 38 39inline const char* color_attribute_name() { return "aColor"; } 40inline const char* coverage_attribute_name() { return "aCoverage"; } 41inline const char* declared_color_output_name() { return "fsColorOut"; } 42inline const char* dual_source_output_name() { return "dualSourceOut"; } 43inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { 44 if (kVec2f_GrSLType == type) { 45 return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; 46 } else { 47 SkASSERT(kVec3f_GrSLType == type); 48 return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; 49 } 50} 51 52void append_texture_lookup(SkString* out, 53 GrGpuGL* gpu, 54 const char* samplerName, 55 const char* coordName, 56 uint32_t configComponentMask, 57 const char* swizzle, 58 GrSLType varyingType = kVec2f_GrSLType) { 59 SkASSERT(NULL != coordName); 60 61 out->appendf("%s(%s, %s)", 62 sample_function_name(varyingType, gpu->glslGeneration()), 63 samplerName, 64 coordName); 65 66 char mangledSwizzle[5]; 67 68 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle 69 // is available. 70 if (!gpu->glCaps().textureSwizzleSupport() && 71 (kA_GrColorComponentFlag == configComponentMask)) { 72 char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; 73 int i; 74 for (i = 0; '\0' != swizzle[i]; ++i) { 75 mangledSwizzle[i] = alphaChar; 76 } 77 mangledSwizzle[i] ='\0'; 78 swizzle = mangledSwizzle; 79 } 80 // For shader prettiness we omit the swizzle rather than appending ".rgba". 81 if (memcmp(swizzle, "rgba", 4)) { 82 out->appendf(".%s", swizzle); 83 } 84} 85 86} 87 88static const char kDstCopyColorName[] = "_dstColor"; 89 90/////////////////////////////////////////////////////////////////////////////// 91 92GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, 93 GrGLUniformManager& uniformManager, 94 const GrGLProgramDesc& desc) 95 : fGpu(gpu) 96 , fUniformManager(uniformManager) 97 , fFSFeaturesAddedMask(0) 98 , fFSInputs(kVarsPerBlock) 99 , fFSOutputs(kMaxFSOutputs) 100 , fUniforms(kVarsPerBlock) 101 , fSetupFragPosition(false) 102 , fHasCustomColorOutput(false) 103 , fHasSecondaryOutput(false) 104 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { 105 106 const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); 107 108 // Emit code to read the dst copy textue if necessary. 109 if (kNoDstRead_DstReadKey != header.fDstReadKey && 110 GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) { 111 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); 112 const char* dstCopyTopLeftName; 113 const char* dstCopyCoordScaleName; 114 uint32_t configMask; 115 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { 116 configMask = kA_GrColorComponentFlag; 117 } else { 118 configMask = kRGBA_GrColorComponentFlags; 119 } 120 fDstCopySamplerUniform = this->addUniform(kFragment_Visibility, 121 kSampler2D_GrSLType, 122 "DstCopySampler"); 123 fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility, 124 kVec2f_GrSLType, 125 "DstCopyUpperLeft", 126 &dstCopyTopLeftName); 127 fDstCopyScaleUniform = this->addUniform(kFragment_Visibility, 128 kVec2f_GrSLType, 129 "DstCopyCoordScale", 130 &dstCopyCoordScaleName); 131 const char* fragPos = this->fragmentPosition(); 132 this->fsCodeAppend("\t// Read color from copy of the destination.\n"); 133 this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", 134 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); 135 if (!topDown) { 136 this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); 137 } 138 this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); 139 append_texture_lookup(&fFSCode, 140 fGpu, 141 this->getUniformCStr(fDstCopySamplerUniform), 142 "_dstTexCoord", 143 configMask, 144 "rgba"); 145 this->fsCodeAppend(";\n\n"); 146 } 147 148 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { 149 const char* name; 150 fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, 151 kVec4f_GrSLType, "Color", &name); 152 fInputColor = GrGLSLExpr4(name); 153 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) { 154 fInputColor = GrGLSLExpr4(1); 155 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) { 156 fInputColor = GrGLSLExpr4(0); 157 } 158 159 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { 160 const char* name; 161 fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, 162 kVec4f_GrSLType, "Coverage", &name); 163 fInputCoverage = GrGLSLExpr4(name); 164 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { 165 fInputCoverage = GrGLSLExpr4(1); 166 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) { 167 fInputCoverage = GrGLSLExpr4(0); 168 } 169 170 if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { 171 fFSOutputs.push_back().set(kVec4f_GrSLType, 172 GrGLShaderVar::kOut_TypeModifier, 173 declared_color_output_name()); 174 fHasCustomColorOutput = true; 175 } 176} 177 178bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { 179 switch (feature) { 180 case kStandardDerivatives_GLSLFeature: 181 if (!fGpu->glCaps().shaderDerivativeSupport()) { 182 return false; 183 } 184 if (kES_GrGLBinding == fGpu->glBinding()) { 185 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, 186 "GL_OES_standard_derivatives"); 187 } 188 return true; 189 default: 190 GrCrash("Unexpected GLSLFeature requested."); 191 return false; 192 } 193} 194 195bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { 196 switch (feature) { 197 case kFragCoordConventions_GLSLPrivateFeature: 198 if (!fGpu->glCaps().fragCoordConventionsSupport()) { 199 return false; 200 } 201 if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { 202 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 203 "GL_ARB_fragment_coord_conventions"); 204 } 205 return true; 206 case kEXTShaderFramebufferFetch_GLSLPrivateFeature: 207 if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) { 208 return false; 209 } 210 this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, 211 "GL_EXT_shader_framebuffer_fetch"); 212 return true; 213 case kNVShaderFramebufferFetch_GLSLPrivateFeature: 214 if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) { 215 return false; 216 } 217 this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, 218 "GL_NV_shader_framebuffer_fetch"); 219 return true; 220 default: 221 GrCrash("Unexpected GLSLPrivateFeature requested."); 222 return false; 223 } 224} 225 226void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { 227 if (!(featureBit & fFSFeaturesAddedMask)) { 228 fFSExtensions.appendf("#extension %s: require\n", extensionName); 229 fFSFeaturesAddedMask |= featureBit; 230 } 231} 232 233void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { 234 if ('\0' == prefix) { 235 *out = name; 236 } else { 237 out->printf("%c%s", prefix, name); 238 } 239 if (fCodeStage.inStageCode()) { 240 if (out->endsWith('_')) { 241 // Names containing "__" are reserved. 242 out->append("x"); 243 } 244 out->appendf("_Stage%d", fCodeStage.stageIndex()); 245 } 246} 247 248const char* GrGLShaderBuilder::dstColor() { 249 if (fCodeStage.inStageCode()) { 250 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 251 if (!effect->willReadDstColor()) { 252 GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect " 253 "did not request access."); 254 return ""; 255 } 256 } 257 static const char kFBFetchColorName[] = "gl_LastFragData[0]"; 258 GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType(); 259 if (GrGLCaps::kEXT_FBFetchType == fetchType) { 260 SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); 261 return kFBFetchColorName; 262 } else if (GrGLCaps::kNV_FBFetchType == fetchType) { 263 SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature)); 264 return kFBFetchColorName; 265 } else if (fDstCopySamplerUniform.isValid()) { 266 return kDstCopyColorName; 267 } else { 268 return ""; 269 } 270} 271 272void GrGLShaderBuilder::appendTextureLookup(SkString* out, 273 const GrGLShaderBuilder::TextureSampler& sampler, 274 const char* coordName, 275 GrSLType varyingType) const { 276 append_texture_lookup(out, 277 fGpu, 278 this->getUniformCStr(sampler.samplerUniform()), 279 coordName, 280 sampler.configComponentMask(), 281 sampler.swizzle(), 282 varyingType); 283} 284 285void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler, 286 const char* coordName, 287 GrSLType varyingType) { 288 this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); 289} 290 291void GrGLShaderBuilder::fsAppendTextureLookupAndModulate( 292 const char* modulation, 293 const GrGLShaderBuilder::TextureSampler& sampler, 294 const char* coordName, 295 GrSLType varyingType) { 296 SkString lookup; 297 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 298 fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); 299} 300 301GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, 302 const GrGLCaps& caps) { 303 uint32_t key = kYesDstRead_DstReadKeyBit; 304 if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) { 305 return key; 306 } 307 SkASSERT(NULL != dstCopy); 308 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 309 // The fact that the config is alpha-only must be considered when generating code. 310 key |= kUseAlphaConfig_DstReadKeyBit; 311 } 312 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 313 key |= kTopLeftOrigin_DstReadKeyBit; 314 } 315 SkASSERT(static_cast<DstReadKey>(key) == key); 316 return static_cast<DstReadKey>(key); 317} 318 319GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, 320 const GrGLCaps&) { 321 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 322 return kTopLeftFragPosRead_FragPosKey; 323 } else { 324 return kBottomLeftFragPosRead_FragPosKey; 325 } 326} 327 328 329const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 330 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 331 if (caps.textureRedSupport()) { 332 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 333 return gRedSmear; 334 } else { 335 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 336 GR_GL_ALPHA, GR_GL_ALPHA }; 337 return gAlphaSmear; 338 } 339 } else { 340 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 341 return gStraight; 342 } 343} 344 345GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 346 GrSLType type, 347 const char* name, 348 int count, 349 const char** outName) { 350 SkASSERT(name && strlen(name)); 351 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); 352 SkASSERT(0 == (~kVisibilityMask & visibility)); 353 SkASSERT(0 != visibility); 354 355 BuilderUniform& uni = fUniforms.push_back(); 356 UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); 357 SkDEBUGCODE(UniformHandle h2 =) 358 fUniformManager.appendUniform(type, count); 359 // We expect the uniform manager to initially have no uniforms and that all uniforms are added 360 // by this function. Therefore, the handles should match. 361 SkASSERT(h2 == h); 362 uni.fVariable.setType(type); 363 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 364 this->nameVariable(uni.fVariable.accessName(), 'u', name); 365 uni.fVariable.setArrayCount(count); 366 uni.fVisibility = visibility; 367 368 // If it is visible in both the VS and FS, the precision must match. 369 // We declare a default FS precision, but not a default VS. So set the var 370 // to use the default FS precision. 371 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { 372 // the fragment and vertex precisions must match 373 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 374 } 375 376 if (NULL != outName) { 377 *outName = uni.fVariable.c_str(); 378 } 379 380 return h; 381} 382 383SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) { 384 if (kVec3f_GrSLType != coords[index].type()) { 385 SkASSERT(kVec2f_GrSLType == coords[index].type()); 386 return coords[index].getName(); 387 } 388 389 SkString coords2D("coords2D"); 390 if (0 != index) { 391 coords2D.appendf("_%i", index); 392 } 393 this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", 394 coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 395 return coords2D; 396} 397 398const char* GrGLShaderBuilder::fragmentPosition() { 399 if (fCodeStage.inStageCode()) { 400 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 401 if (!effect->willReadFragmentPosition()) { 402 GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect " 403 "did not request access."); 404 return ""; 405 } 406 } 407 if (fTopLeftFragPosRead) { 408 if (!fSetupFragPosition) { 409 fFSInputs.push_back().set(kVec4f_GrSLType, 410 GrGLShaderVar::kIn_TypeModifier, 411 "gl_FragCoord", 412 GrGLShaderVar::kDefault_Precision); 413 fSetupFragPosition = true; 414 } 415 return "gl_FragCoord"; 416 } else if (fGpu->glCaps().fragCoordConventionsSupport()) { 417 if (!fSetupFragPosition) { 418 SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); 419 fFSInputs.push_back().set(kVec4f_GrSLType, 420 GrGLShaderVar::kIn_TypeModifier, 421 "gl_FragCoord", 422 GrGLShaderVar::kDefault_Precision, 423 GrGLShaderVar::kUpperLeft_Origin); 424 fSetupFragPosition = true; 425 } 426 return "gl_FragCoord"; 427 } else { 428 static const char* kCoordName = "fragCoordYDown"; 429 if (!fSetupFragPosition) { 430 // temporarily change the stage index because we're inserting non-stage code. 431 CodeStage::AutoStageRestore csar(&fCodeStage, NULL); 432 433 SkASSERT(!fRTHeightUniform.isValid()); 434 const char* rtHeightName; 435 436 fRTHeightUniform = this->addUniform(kFragment_Visibility, 437 kFloat_GrSLType, 438 "RTHeight", 439 &rtHeightName); 440 441 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", 442 kCoordName, rtHeightName); 443 fSetupFragPosition = true; 444 } 445 SkASSERT(fRTHeightUniform.isValid()); 446 return kCoordName; 447 } 448} 449 450void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, 451 const char* name, 452 int argCnt, 453 const GrGLShaderVar* args, 454 const char* body, 455 SkString* outName) { 456 fFSFunctions.append(GrGLSLTypeString(returnType)); 457 this->nameVariable(outName, '\0', name); 458 fFSFunctions.appendf(" %s", outName->c_str()); 459 fFSFunctions.append("("); 460 for (int i = 0; i < argCnt; ++i) { 461 args[i].appendDecl(this->ctxInfo(), &fFSFunctions); 462 if (i < argCnt - 1) { 463 fFSFunctions.append(", "); 464 } 465 } 466 fFSFunctions.append(") {\n"); 467 fFSFunctions.append(body); 468 fFSFunctions.append("}\n\n"); 469} 470 471namespace { 472 473inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 474 GrGLBinding binding, 475 SkString* str) { 476 // Desktop GLSL has added precision qualifiers but they don't do anything. 477 if (kES_GrGLBinding == binding) { 478 switch (p) { 479 case GrGLShaderVar::kHigh_Precision: 480 str->append("precision highp float;\n"); 481 break; 482 case GrGLShaderVar::kMedium_Precision: 483 str->append("precision mediump float;\n"); 484 break; 485 case GrGLShaderVar::kLow_Precision: 486 str->append("precision lowp float;\n"); 487 break; 488 case GrGLShaderVar::kDefault_Precision: 489 GrCrash("Default precision now allowed."); 490 default: 491 GrCrash("Unknown precision value."); 492 } 493 } 494} 495} 496 497void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 498 for (int i = 0; i < vars.count(); ++i) { 499 vars[i].appendDecl(this->ctxInfo(), out); 500 out->append(";\n"); 501 } 502} 503 504void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, 505 SkString* out) const { 506 for (int i = 0; i < fUniforms.count(); ++i) { 507 if (fUniforms[i].fVisibility & visibility) { 508 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 509 out->append(";\n"); 510 } 511 } 512} 513 514void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, 515 const GrEffectStage* effectStages[], 516 const EffectKey effectKeys[], 517 int effectCnt, 518 GrGLSLExpr4* fsInOutColor) { 519 bool effectEmitted = false; 520 521 GrGLSLExpr4 inColor = *fsInOutColor; 522 GrGLSLExpr4 outColor; 523 524 for (int e = 0; e < effectCnt; ++e) { 525 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); 526 const GrEffectStage& stage = *effectStages[e]; 527 528 CodeStage::AutoStageRestore csar(&fCodeStage, &stage); 529 530 if (inColor.isZeros()) { 531 SkString inColorName; 532 533 // Effects have no way to communicate zeros, they treat an empty string as ones. 534 this->nameVariable(&inColorName, '\0', "input"); 535 this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); 536 inColor = inColorName; 537 } 538 539 // create var to hold stage result 540 SkString outColorName; 541 this->nameVariable(&outColorName, '\0', "output"); 542 this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); 543 outColor = outColorName; 544 545 546 programEffectsBuilder->emitEffect(stage, 547 effectKeys[e], 548 outColor.c_str(), 549 inColor.isOnes() ? NULL : inColor.c_str(), 550 fCodeStage.stageIndex()); 551 552 inColor = outColor; 553 effectEmitted = true; 554 } 555 556 if (effectEmitted) { 557 *fsInOutColor = outColor; 558 } 559} 560 561const char* GrGLShaderBuilder::getColorOutputName() const { 562 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; 563} 564 565const char* GrGLShaderBuilder::enableSecondaryOutput() { 566 if (!fHasSecondaryOutput) { 567 fFSOutputs.push_back().set(kVec4f_GrSLType, 568 GrGLShaderVar::kOut_TypeModifier, 569 dual_source_output_name()); 570 fHasSecondaryOutput = true; 571 } 572 return dual_source_output_name(); 573} 574 575 576bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { 577 SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); 578 579 GrGLuint programId = 0; 580 GL_CALL_RET(programId, CreateProgram()); 581 if (!programId) { 582 return false; 583 } 584 585 if (!this->compileAndAttachShaders(programId)) { 586 GL_CALL(DeleteProgram(programId)); 587 return false; 588 } 589 590 this->bindProgramLocations(programId); 591 if (fUniformManager.isUsingBindUniform()) { 592 fUniformManager.getUniformLocations(programId, fUniforms); 593 } 594 595 GL_CALL(LinkProgram(programId)); 596 597 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 598 bool checkLinked = !fGpu->ctxInfo().isChromium(); 599#ifdef SK_DEBUG 600 checkLinked = true; 601#endif 602 if (checkLinked) { 603 GrGLint linked = GR_GL_INIT_ZERO; 604 GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); 605 if (!linked) { 606 GrGLint infoLen = GR_GL_INIT_ZERO; 607 GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 608 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 609 if (infoLen > 0) { 610 // retrieve length even though we don't need it to workaround 611 // bug in chrome cmd buffer param validation. 612 GrGLsizei length = GR_GL_INIT_ZERO; 613 GL_CALL(GetProgramInfoLog(programId, 614 infoLen+1, 615 &length, 616 (char*)log.get())); 617 GrPrintf((char*)log.get()); 618 } 619 SkDEBUGFAIL("Error linking program"); 620 GL_CALL(DeleteProgram(programId)); 621 return false; 622 } 623 } 624 625 if (!fUniformManager.isUsingBindUniform()) { 626 fUniformManager.getUniformLocations(programId, fUniforms); 627 } 628 *outProgramId = programId; 629 return true; 630} 631 632// Compiles a GL shader, attaches it to a program, and releases the shader's reference. 633// (That way there's no need to hang on to the GL shader id and delete it later.) 634static bool attach_shader(const GrGLContext& glCtx, 635 GrGLuint programId, 636 GrGLenum type, 637 const SkString& shaderSrc) { 638 const GrGLInterface* gli = glCtx.interface(); 639 640 GrGLuint shaderId; 641 GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); 642 if (0 == shaderId) { 643 return false; 644 } 645 646 const GrGLchar* sourceStr = shaderSrc.c_str(); 647 GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); 648 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); 649 GR_GL_CALL(gli, CompileShader(shaderId)); 650 651 // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. 652 bool checkCompiled = !glCtx.info().isChromium(); 653#ifdef SK_DEBUG 654 checkCompiled = true; 655#endif 656 if (checkCompiled) { 657 GrGLint compiled = GR_GL_INIT_ZERO; 658 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); 659 660 if (!compiled) { 661 GrGLint infoLen = GR_GL_INIT_ZERO; 662 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 663 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 664 if (infoLen > 0) { 665 // retrieve length even though we don't need it to workaround bug in Chromium cmd 666 // buffer param validation. 667 GrGLsizei length = GR_GL_INIT_ZERO; 668 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, 669 &length, (char*)log.get())); 670 GrPrintf(shaderSrc.c_str()); 671 GrPrintf("\n%s", log.get()); 672 } 673 SkDEBUGFAIL("Shader compilation failed!"); 674 GR_GL_CALL(gli, DeleteShader(shaderId)); 675 return false; 676 } 677 } 678 if (c_PrintShaders) { 679 GrPrintf(shaderSrc.c_str()); 680 GrPrintf("\n"); 681 } 682 683 GR_GL_CALL(gli, AttachShader(programId, shaderId)); 684 GR_GL_CALL(gli, DeleteShader(shaderId)); 685 return true; 686} 687 688bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId) const { 689 SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 690 fragShaderSrc.append(fFSExtensions); 691 append_default_precision_qualifier(kDefaultFragmentPrecision, 692 fGpu->glBinding(), 693 &fragShaderSrc); 694 this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); 695 this->appendDecls(fFSInputs, &fragShaderSrc); 696 // We shouldn't have declared outputs on 1.10 697 SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty()); 698 this->appendDecls(fFSOutputs, &fragShaderSrc); 699 fragShaderSrc.append(fFSFunctions); 700 fragShaderSrc.append("void main() {\n"); 701 fragShaderSrc.append(fFSCode); 702 fragShaderSrc.append("}\n"); 703 if (!attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc)) { 704 return false; 705 } 706 707 return true; 708} 709 710void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const { 711 if (fHasCustomColorOutput) { 712 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); 713 } 714 if (fHasSecondaryOutput) { 715 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); 716 } 717} 718 719const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { 720 return fGpu->ctxInfo(); 721} 722 723//////////////////////////////////////////////////////////////////////////////// 724 725GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu, 726 GrGLUniformManager& uniformManager, 727 const GrGLProgramDesc& desc) 728 : INHERITED(gpu, uniformManager, desc) 729 , fDesc(desc) 730 , fVSAttrs(kVarsPerBlock) 731 , fVSOutputs(kVarsPerBlock) 732 , fGSInputs(kVarsPerBlock) 733 , fGSOutputs(kVarsPerBlock) { 734 735 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 736 737 fPositionVar = &fVSAttrs.push_back(); 738 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); 739 if (-1 != header.fLocalCoordAttributeIndex) { 740 fLocalCoordsVar = &fVSAttrs.push_back(); 741 fLocalCoordsVar->set(kVec2f_GrSLType, 742 GrGLShaderVar::kAttribute_TypeModifier, 743 "aLocalCoords"); 744 } else { 745 fLocalCoordsVar = fPositionVar; 746 } 747 748 const char* viewMName; 749 fViewMatrixUniform = this->addUniform(GrGLShaderBuilder::kVertex_Visibility, 750 kMat33f_GrSLType, "ViewM", &viewMName); 751 752 this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" 753 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 754 viewMName, fPositionVar->c_str()); 755 756 // we output point size in the GS if present 757 if (header.fEmitsPointSize 758#if GR_GL_EXPERIMENTAL_GS 759 && !header.fExperimentalGS 760#endif 761 ) { 762 this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); 763 } 764 765 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { 766 this->addAttribute(kVec4f_GrSLType, color_attribute_name()); 767 const char *vsName, *fsName; 768 this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 769 this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); 770 this->setInputColor(fsName); 771 } 772 773 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { 774 this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); 775 const char *vsName, *fsName; 776 this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 777 this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); 778 this->setInputCoverage(fsName); 779 } 780} 781 782bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) { 783 for (int i = 0; i < fVSAttrs.count(); ++i) { 784 const GrGLShaderVar& attr = fVSAttrs[i]; 785 // if attribute already added, don't add it again 786 if (attr.getName().equals(name)) { 787 SkASSERT(attr.getType() == type); 788 return false; 789 } 790 } 791 fVSAttrs.push_back().set(type, 792 GrGLShaderVar::kAttribute_TypeModifier, 793 name); 794 return true; 795} 796 797bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex, 798 GrSLType type, 799 const SkString& name) { 800 if (!this->addAttribute(type, name.c_str())) { 801 return false; 802 } 803 804 fEffectAttributes.push_back().set(attributeIndex, name); 805 return true; 806} 807 808void GrGLFullShaderBuilder::addVarying(GrSLType type, 809 const char* name, 810 const char** vsOutName, 811 const char** fsInName) { 812 fVSOutputs.push_back(); 813 fVSOutputs.back().setType(type); 814 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 815 this->nameVariable(fVSOutputs.back().accessName(), 'v', name); 816 817 if (vsOutName) { 818 *vsOutName = fVSOutputs.back().getName().c_str(); 819 } 820 // input to FS comes either from VS or GS 821 const SkString* fsName; 822#if GR_GL_EXPERIMENTAL_GS 823 if (fDesc.getHeader().fExperimentalGS) { 824 // if we have a GS take each varying in as an array 825 // and output as non-array. 826 fGSInputs.push_back(); 827 fGSInputs.back().setType(type); 828 fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); 829 fGSInputs.back().setUnsizedArray(); 830 *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 831 fGSOutputs.push_back(); 832 fGSOutputs.back().setType(type); 833 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 834 this->nameVariable(fGSOutputs.back().accessName(), 'g', name); 835 fsName = fGSOutputs.back().accessName(); 836 } else 837#endif 838 { 839 fsName = fVSOutputs.back().accessName(); 840 } 841 this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName); 842 if (fsInName) { 843 *fsInName = fsName->c_str(); 844 } 845} 846 847const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const { 848 const AttributePair* attribEnd = fEffectAttributes.end(); 849 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 850 if (attrib->fIndex == attributeIndex) { 851 return &attrib->fName; 852 } 853 } 854 855 return NULL; 856} 857 858GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( 859 const GrEffectStage* effectStages[], 860 const EffectKey effectKeys[], 861 int effectCnt, 862 GrGLSLExpr4* inOutFSColor) { 863 864 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); 865 this->INHERITED::createAndEmitEffects(&programEffectsBuilder, 866 effectStages, 867 effectKeys, 868 effectCnt, 869 inOutFSColor); 870 return programEffectsBuilder.finish(); 871} 872 873bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId) const { 874 const GrGLContext& glCtx = this->gpu()->glContext(); 875 SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 876 this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); 877 this->appendDecls(fVSAttrs, &vertShaderSrc); 878 this->appendDecls(fVSOutputs, &vertShaderSrc); 879 vertShaderSrc.append("void main() {\n"); 880 vertShaderSrc.append(fVSCode); 881 vertShaderSrc.append("}\n"); 882 if (!attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc)) { 883 return false; 884 } 885 886#if GR_GL_EXPERIMENTAL_GS 887 if (fDesc.getHeader().fExperimentalGS) { 888 SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); 889 SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 890 geomShaderSrc.append("layout(triangles) in;\n" 891 "layout(triangle_strip, max_vertices = 6) out;\n"); 892 this->appendDecls(fGSInputs, &geomShaderSrc); 893 this->appendDecls(fGSOutputs, &geomShaderSrc); 894 geomShaderSrc.append("void main() {\n"); 895 geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" 896 "\t\tgl_Position = gl_in[i].gl_Position;\n"); 897 if (fDesc.getHeader().fEmitsPointSize) { 898 geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); 899 } 900 SkASSERT(fGSInputs.count() == fGSOutputs.count()); 901 for (int i = 0; i < fGSInputs.count(); ++i) { 902 geomShaderSrc.appendf("\t\t%s = %s[i];\n", 903 fGSOutputs[i].getName().c_str(), 904 fGSInputs[i].getName().c_str()); 905 } 906 geomShaderSrc.append("\t\tEmitVertex();\n" 907 "\t}\n" 908 "\tEndPrimitive();\n"); 909 geomShaderSrc.append("}\n"); 910 if (!attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc)) { 911 return false; 912 } 913 } 914#endif 915 916 return this->INHERITED::compileAndAttachShaders(programId); 917} 918 919void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const { 920 this->INHERITED::bindProgramLocations(programId); 921 922 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 923 924 // Bind the attrib locations to same values for all shaders 925 SkASSERT(-1 != header.fPositionAttributeIndex); 926 GL_CALL(BindAttribLocation(programId, 927 header.fPositionAttributeIndex, 928 fPositionVar->c_str())); 929 if (-1 != header.fLocalCoordAttributeIndex) { 930 GL_CALL(BindAttribLocation(programId, 931 header.fLocalCoordAttributeIndex, 932 fLocalCoordsVar->c_str())); 933 } 934 if (-1 != header.fColorAttributeIndex) { 935 GL_CALL(BindAttribLocation(programId, 936 header.fColorAttributeIndex, 937 color_attribute_name())); 938 } 939 if (-1 != header.fCoverageAttributeIndex) { 940 GL_CALL(BindAttribLocation(programId, 941 header.fCoverageAttributeIndex, 942 coverage_attribute_name())); 943 } 944 945 const AttributePair* attribEnd = fEffectAttributes.end(); 946 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 947 GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); 948 } 949} 950 951//////////////////////////////////////////////////////////////////////////////// 952 953GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu, 954 GrGLUniformManager& uniformManager, 955 const GrGLProgramDesc& desc) 956 : INHERITED(gpu, uniformManager, desc) 957 , fNumTexCoordSets(0) { 958 959 SkASSERT(!desc.getHeader().fHasVertexCode); 960 SkASSERT(gpu->glCaps().fixedFunctionSupport()); 961 SkASSERT(gpu->glCaps().pathRenderingSupport()); 962 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); 963 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); 964} 965 966int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) { 967 int firstFreeCoordSet = fNumTexCoordSets; 968 fNumTexCoordSets += count; 969 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fNumTexCoordSets); 970 return firstFreeCoordSet; 971} 972 973GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( 974 const GrEffectStage* effectStages[], 975 const EffectKey effectKeys[], 976 int effectCnt, 977 GrGLSLExpr4* inOutFSColor) { 978 979 GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt); 980 this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder, 981 effectStages, 982 effectKeys, 983 effectCnt, 984 inOutFSColor); 985 return texGenEffectsBuilder.finish(); 986} 987