GrGLShaderBuilder.cpp revision 9681eebb0e441cee25b6faac82c3728512acda27
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 "SkTraceEvent.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 92bool GrGLShaderBuilder::GenProgram(GrGpuGL* gpu, 93 GrGLUniformManager* uman, 94 const GrGLProgramDesc& desc, 95 const GrEffectStage* inColorStages[], 96 const GrEffectStage* inCoverageStages[], 97 GenProgramOutput* output) { 98 SkAutoTDelete<GrGLShaderBuilder> builder; 99 if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) { 100 builder.reset(SkNEW_ARGS(GrGLFullShaderBuilder, (gpu, uman, desc))); 101 } else { 102 builder.reset(SkNEW_ARGS(GrGLFragmentOnlyShaderBuilder, (gpu, uman, desc))); 103 } 104 if (builder->genProgram(inColorStages, inCoverageStages)) { 105 *output = builder->getOutput(); 106 return true; 107 } 108 return false; 109} 110 111bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[], 112 const GrEffectStage* coverageStages[]) { 113 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); 114 115 // incoming color to current stage being processed. 116 GrGLSLExpr4 inColor = this->getInputColor(); 117 118 fOutput.fColorEffects = 119 this->createAndEmitEffects(colorStages, 120 this->desc().getEffectKeys(), 121 this->desc().numColorEffects(), 122 &inColor); 123 124 /////////////////////////////////////////////////////////////////////////// 125 // compute the partial coverage 126 GrGLSLExpr4 inCoverage = this->getInputCoverage(); 127 128 fOutput.fCoverageEffects = 129 this->createAndEmitEffects(coverageStages, 130 this->desc().getEffectKeys() + this->desc().numColorEffects(), 131 this->desc().numCoverageEffects(), 132 &inCoverage); 133 134 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { 135 const char* secondaryOutputName = this->enableSecondaryOutput(); 136 137 // default coeff to ones for kCoverage_DualSrcOutput 138 GrGLSLExpr4 coeff(1); 139 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { 140 // Get (1-A) into coeff 141 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a()); 142 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == 143 header.fCoverageOutput){ 144 // Get (1-RGBA) into coeff 145 coeff = GrGLSLExpr4(1) - inColor; 146 } 147 // Get coeff * coverage into modulate and then write that to the dual source output. 148 this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str()); 149 } 150 151 /////////////////////////////////////////////////////////////////////////// 152 // combine color and coverage as frag color 153 154 // Get "color * coverage" into fragColor 155 GrGLSLExpr4 fragColor = inColor * inCoverage; 156 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. 157 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { 158 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage; 159 160 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor()); 161 162 fragColor = fragColor + dstContribution; 163 } 164 this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); 165 166 if (!this->finish()) { 167 return false; 168 } 169 170 return true; 171} 172 173////////////////////////////////////////////////////////////////////////////// 174 175GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, 176 GrGLUniformManager* uniformManager, 177 const GrGLProgramDesc& desc) 178 : fDesc(desc) 179 , fGpu(gpu) 180 , fUniformManager(SkRef(uniformManager)) 181 , fFSFeaturesAddedMask(0) 182 , fFSInputs(kVarsPerBlock) 183 , fFSOutputs(kMaxFSOutputs) 184 , fUniforms(kVarsPerBlock) 185 , fSetupFragPosition(false) 186 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) 187 , fHasCustomColorOutput(false) 188 , fHasSecondaryOutput(false) { 189 190 const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); 191 192 // Emit code to read the dst copy textue if necessary. 193 if (kNoDstRead_DstReadKey != header.fDstReadKey && 194 GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) { 195 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); 196 const char* dstCopyTopLeftName; 197 const char* dstCopyCoordScaleName; 198 const char* dstCopySamplerName; 199 uint32_t configMask; 200 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { 201 configMask = kA_GrColorComponentFlag; 202 } else { 203 configMask = kRGBA_GrColorComponentFlags; 204 } 205 fOutput.fUniformHandles.fDstCopySamplerUni = 206 this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopySampler", 207 &dstCopySamplerName); 208 fOutput.fUniformHandles.fDstCopyTopLeftUni = 209 this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUpperLeft", 210 &dstCopyTopLeftName); 211 fOutput.fUniformHandles.fDstCopyScaleUni = 212 this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoordScale", 213 &dstCopyCoordScaleName); 214 const char* fragPos = this->fragmentPosition(); 215 this->fsCodeAppend("\t// Read color from copy of the destination.\n"); 216 this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", 217 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); 218 if (!topDown) { 219 this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); 220 } 221 this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); 222 append_texture_lookup(&fFSCode, 223 fGpu, 224 dstCopySamplerName, 225 "_dstTexCoord", 226 configMask, 227 "rgba"); 228 this->fsCodeAppend(";\n\n"); 229 } 230 231 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { 232 const char* name; 233 fOutput.fUniformHandles.fColorUni = 234 this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Color", 235 &name); 236 fInputColor = GrGLSLExpr4(name); 237 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) { 238 fInputColor = GrGLSLExpr4(1); 239 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) { 240 fInputColor = GrGLSLExpr4(0); 241 } 242 243 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { 244 const char* name; 245 fOutput.fUniformHandles.fCoverageUni = 246 this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Coverage", 247 &name); 248 fInputCoverage = GrGLSLExpr4(name); 249 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { 250 fInputCoverage = GrGLSLExpr4(1); 251 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) { 252 fInputCoverage = GrGLSLExpr4(0); 253 } 254 255 if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { 256 fFSOutputs.push_back().set(kVec4f_GrSLType, 257 GrGLShaderVar::kOut_TypeModifier, 258 declared_color_output_name()); 259 fHasCustomColorOutput = true; 260 } 261} 262 263bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { 264 switch (feature) { 265 case kStandardDerivatives_GLSLFeature: 266 if (!fGpu->glCaps().shaderDerivativeSupport()) { 267 return false; 268 } 269 if (kGLES_GrGLStandard == fGpu->glStandard()) { 270 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, 271 "GL_OES_standard_derivatives"); 272 } 273 return true; 274 default: 275 SkFAIL("Unexpected GLSLFeature requested."); 276 return false; 277 } 278} 279 280bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { 281 switch (feature) { 282 case kFragCoordConventions_GLSLPrivateFeature: 283 if (!fGpu->glCaps().fragCoordConventionsSupport()) { 284 return false; 285 } 286 if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { 287 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 288 "GL_ARB_fragment_coord_conventions"); 289 } 290 return true; 291 case kEXTShaderFramebufferFetch_GLSLPrivateFeature: 292 if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) { 293 return false; 294 } 295 this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, 296 "GL_EXT_shader_framebuffer_fetch"); 297 return true; 298 case kNVShaderFramebufferFetch_GLSLPrivateFeature: 299 if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) { 300 return false; 301 } 302 this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, 303 "GL_NV_shader_framebuffer_fetch"); 304 return true; 305 default: 306 SkFAIL("Unexpected GLSLPrivateFeature requested."); 307 return false; 308 } 309} 310 311void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { 312 if (!(featureBit & fFSFeaturesAddedMask)) { 313 fFSExtensions.appendf("#extension %s: require\n", extensionName); 314 fFSFeaturesAddedMask |= featureBit; 315 } 316} 317 318void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { 319 if ('\0' == prefix) { 320 *out = name; 321 } else { 322 out->printf("%c%s", prefix, name); 323 } 324 if (fCodeStage.inStageCode()) { 325 if (out->endsWith('_')) { 326 // Names containing "__" are reserved. 327 out->append("x"); 328 } 329 out->appendf("_Stage%d", fCodeStage.stageIndex()); 330 } 331} 332 333const char* GrGLShaderBuilder::dstColor() { 334 if (fCodeStage.inStageCode()) { 335 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 336 if (!effect->willReadDstColor()) { 337 SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect " 338 "did not request access."); 339 return ""; 340 } 341 } 342 static const char kFBFetchColorName[] = "gl_LastFragData[0]"; 343 GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType(); 344 if (GrGLCaps::kEXT_FBFetchType == fetchType) { 345 SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); 346 return kFBFetchColorName; 347 } else if (GrGLCaps::kNV_FBFetchType == fetchType) { 348 SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature)); 349 return kFBFetchColorName; 350 } else if (fOutput.fUniformHandles.fDstCopySamplerUni.isValid()) { 351 return kDstCopyColorName; 352 } else { 353 return ""; 354 } 355} 356 357void GrGLShaderBuilder::appendTextureLookup(SkString* out, 358 const GrGLShaderBuilder::TextureSampler& sampler, 359 const char* coordName, 360 GrSLType varyingType) const { 361 append_texture_lookup(out, 362 fGpu, 363 this->getUniformCStr(sampler.samplerUniform()), 364 coordName, 365 sampler.configComponentMask(), 366 sampler.swizzle(), 367 varyingType); 368} 369 370void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler, 371 const char* coordName, 372 GrSLType varyingType) { 373 this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); 374} 375 376void GrGLShaderBuilder::fsAppendTextureLookupAndModulate( 377 const char* modulation, 378 const GrGLShaderBuilder::TextureSampler& sampler, 379 const char* coordName, 380 GrSLType varyingType) { 381 SkString lookup; 382 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 383 fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); 384} 385 386GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, 387 const GrGLCaps& caps) { 388 uint32_t key = kYesDstRead_DstReadKeyBit; 389 if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) { 390 return key; 391 } 392 SkASSERT(NULL != dstCopy); 393 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 394 // The fact that the config is alpha-only must be considered when generating code. 395 key |= kUseAlphaConfig_DstReadKeyBit; 396 } 397 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 398 key |= kTopLeftOrigin_DstReadKeyBit; 399 } 400 SkASSERT(static_cast<DstReadKey>(key) == key); 401 return static_cast<DstReadKey>(key); 402} 403 404GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, 405 const GrGLCaps&) { 406 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 407 return kTopLeftFragPosRead_FragPosKey; 408 } else { 409 return kBottomLeftFragPosRead_FragPosKey; 410 } 411} 412 413 414const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 415 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 416 if (caps.textureRedSupport()) { 417 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 418 return gRedSmear; 419 } else { 420 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 421 GR_GL_ALPHA, GR_GL_ALPHA }; 422 return gAlphaSmear; 423 } 424 } else { 425 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 426 return gStraight; 427 } 428} 429 430GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 431 GrSLType type, 432 const char* name, 433 int count, 434 const char** outName) { 435 SkASSERT(name && strlen(name)); 436 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); 437 SkASSERT(0 == (~kVisibilityMask & visibility)); 438 SkASSERT(0 != visibility); 439 440 BuilderUniform& uni = fUniforms.push_back(); 441 UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); 442 SkDEBUGCODE(UniformHandle h2 =) 443 fUniformManager->appendUniform(type, count); 444 // We expect the uniform manager to initially have no uniforms and that all uniforms are added 445 // by this function. Therefore, the handles should match. 446 SkASSERT(h2 == h); 447 uni.fVariable.setType(type); 448 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 449 this->nameVariable(uni.fVariable.accessName(), 'u', name); 450 uni.fVariable.setArrayCount(count); 451 uni.fVisibility = visibility; 452 453 // If it is visible in both the VS and FS, the precision must match. 454 // We declare a default FS precision, but not a default VS. So set the var 455 // to use the default FS precision. 456 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { 457 // the fragment and vertex precisions must match 458 uni.fVariable.setPrecision(kDefaultFragmentPrecision); 459 } 460 461 if (NULL != outName) { 462 *outName = uni.fVariable.c_str(); 463 } 464 465 return h; 466} 467 468SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) { 469 if (kVec3f_GrSLType != coords[index].type()) { 470 SkASSERT(kVec2f_GrSLType == coords[index].type()); 471 return coords[index].getName(); 472 } 473 474 SkString coords2D("coords2D"); 475 if (0 != index) { 476 coords2D.appendf("_%i", index); 477 } 478 this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", 479 coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 480 return coords2D; 481} 482 483const char* GrGLShaderBuilder::fragmentPosition() { 484 if (fCodeStage.inStageCode()) { 485 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 486 if (!effect->willReadFragmentPosition()) { 487 SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect " 488 "did not request access."); 489 return ""; 490 } 491 } 492 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 493 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 494 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 495 if (fTopLeftFragPosRead) { 496 fSetupFragPosition = true; 497 return "gl_FragCoord"; 498 } else if (fGpu->glCaps().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 SkASSERT(!fOutput.fUniformHandles.fRTHeightUni.isValid()); 516 const char* rtHeightName; 517 518 fOutput.fUniformHandles.fRTHeightUni = 519 this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeight", &rtHeightName); 520 521 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", 522 kCoordName, rtHeightName); 523 fSetupFragPosition = true; 524 } 525 SkASSERT(fOutput.fUniformHandles.fRTHeightUni.isValid()); 526 return kCoordName; 527 } 528} 529 530void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, 531 const char* name, 532 int argCnt, 533 const GrGLShaderVar* args, 534 const char* body, 535 SkString* outName) { 536 fFSFunctions.append(GrGLSLTypeString(returnType)); 537 this->nameVariable(outName, '\0', name); 538 fFSFunctions.appendf(" %s", outName->c_str()); 539 fFSFunctions.append("("); 540 for (int i = 0; i < argCnt; ++i) { 541 args[i].appendDecl(this->ctxInfo(), &fFSFunctions); 542 if (i < argCnt - 1) { 543 fFSFunctions.append(", "); 544 } 545 } 546 fFSFunctions.append(") {\n"); 547 fFSFunctions.append(body); 548 fFSFunctions.append("}\n\n"); 549} 550 551namespace { 552 553inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 554 GrGLStandard standard, 555 SkString* str) { 556 // Desktop GLSL has added precision qualifiers but they don't do anything. 557 if (kGLES_GrGLStandard == standard) { 558 switch (p) { 559 case GrGLShaderVar::kHigh_Precision: 560 str->append("precision highp float;\n"); 561 break; 562 case GrGLShaderVar::kMedium_Precision: 563 str->append("precision mediump float;\n"); 564 break; 565 case GrGLShaderVar::kLow_Precision: 566 str->append("precision lowp float;\n"); 567 break; 568 case GrGLShaderVar::kDefault_Precision: 569 SkFAIL("Default precision now allowed."); 570 default: 571 SkFAIL("Unknown precision value."); 572 } 573 } 574} 575} 576 577void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 578 for (int i = 0; i < vars.count(); ++i) { 579 vars[i].appendDecl(this->ctxInfo(), out); 580 out->append(";\n"); 581 } 582} 583 584void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, 585 SkString* out) const { 586 for (int i = 0; i < fUniforms.count(); ++i) { 587 if (fUniforms[i].fVisibility & visibility) { 588 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 589 out->append(";\n"); 590 } 591 } 592} 593 594void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, 595 const GrEffectStage* effectStages[], 596 const EffectKey effectKeys[], 597 int effectCnt, 598 GrGLSLExpr4* fsInOutColor) { 599 bool effectEmitted = false; 600 601 GrGLSLExpr4 inColor = *fsInOutColor; 602 GrGLSLExpr4 outColor; 603 604 for (int e = 0; e < effectCnt; ++e) { 605 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); 606 const GrEffectStage& stage = *effectStages[e]; 607 608 CodeStage::AutoStageRestore csar(&fCodeStage, &stage); 609 610 if (inColor.isZeros()) { 611 SkString inColorName; 612 613 // Effects have no way to communicate zeros, they treat an empty string as ones. 614 this->nameVariable(&inColorName, '\0', "input"); 615 this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); 616 inColor = inColorName; 617 } 618 619 // create var to hold stage result 620 SkString outColorName; 621 this->nameVariable(&outColorName, '\0', "output"); 622 this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); 623 outColor = outColorName; 624 625 626 programEffectsBuilder->emitEffect(stage, 627 effectKeys[e], 628 outColor.c_str(), 629 inColor.isOnes() ? NULL : inColor.c_str(), 630 fCodeStage.stageIndex()); 631 632 inColor = outColor; 633 effectEmitted = true; 634 } 635 636 if (effectEmitted) { 637 *fsInOutColor = outColor; 638 } 639} 640 641const char* GrGLShaderBuilder::getColorOutputName() const { 642 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; 643} 644 645const char* GrGLShaderBuilder::enableSecondaryOutput() { 646 if (!fHasSecondaryOutput) { 647 fFSOutputs.push_back().set(kVec4f_GrSLType, 648 GrGLShaderVar::kOut_TypeModifier, 649 dual_source_output_name()); 650 fHasSecondaryOutput = true; 651 } 652 return dual_source_output_name(); 653} 654 655bool GrGLShaderBuilder::finish() { 656 SkASSERT(0 == fOutput.fProgramID); 657 GL_CALL_RET(fOutput.fProgramID, CreateProgram()); 658 if (!fOutput.fProgramID) { 659 return false; 660 } 661 662 SkTDArray<GrGLuint> shadersToDelete; 663 664 if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) { 665 GL_CALL(DeleteProgram(fOutput.fProgramID)); 666 return false; 667 } 668 669 this->bindProgramLocations(fOutput.fProgramID); 670 if (fUniformManager->isUsingBindUniform()) { 671 fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); 672 } 673 674 GL_CALL(LinkProgram(fOutput.fProgramID)); 675 676 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 677 bool checkLinked = !fGpu->ctxInfo().isChromium(); 678#ifdef SK_DEBUG 679 checkLinked = true; 680#endif 681 if (checkLinked) { 682 GrGLint linked = GR_GL_INIT_ZERO; 683 GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked)); 684 if (!linked) { 685 GrGLint infoLen = GR_GL_INIT_ZERO; 686 GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 687 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 688 if (infoLen > 0) { 689 // retrieve length even though we don't need it to workaround 690 // bug in chrome cmd buffer param validation. 691 GrGLsizei length = GR_GL_INIT_ZERO; 692 GL_CALL(GetProgramInfoLog(fOutput.fProgramID, 693 infoLen+1, 694 &length, 695 (char*)log.get())); 696 GrPrintf((char*)log.get()); 697 } 698 SkDEBUGFAIL("Error linking program"); 699 GL_CALL(DeleteProgram(fOutput.fProgramID)); 700 fOutput.fProgramID = 0; 701 return false; 702 } 703 } 704 705 if (!fUniformManager->isUsingBindUniform()) { 706 fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); 707 } 708 709 for (int i = 0; i < shadersToDelete.count(); ++i) { 710 GL_CALL(DeleteShader(shadersToDelete[i])); 711 } 712 713 return true; 714} 715 716// Compiles a GL shader and attaches it to a program. Returns the shader ID if 717// successful, or 0 if not. 718static GrGLuint attach_shader(const GrGLContext& glCtx, 719 GrGLuint programId, 720 GrGLenum type, 721 const SkString& shaderSrc) { 722 const GrGLInterface* gli = glCtx.interface(); 723 724 GrGLuint shaderId; 725 GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); 726 if (0 == shaderId) { 727 return 0; 728 } 729 730 const GrGLchar* sourceStr = shaderSrc.c_str(); 731 GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); 732 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); 733 GR_GL_CALL(gli, CompileShader(shaderId)); 734 735 // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. 736 bool checkCompiled = !glCtx.isChromium(); 737#ifdef SK_DEBUG 738 checkCompiled = true; 739#endif 740 if (checkCompiled) { 741 GrGLint compiled = GR_GL_INIT_ZERO; 742 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); 743 744 if (!compiled) { 745 GrGLint infoLen = GR_GL_INIT_ZERO; 746 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 747 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 748 if (infoLen > 0) { 749 // retrieve length even though we don't need it to workaround bug in Chromium cmd 750 // buffer param validation. 751 GrGLsizei length = GR_GL_INIT_ZERO; 752 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, 753 &length, (char*)log.get())); 754 GrPrintf(shaderSrc.c_str()); 755 GrPrintf("\n%s", log.get()); 756 } 757 SkDEBUGFAIL("Shader compilation failed!"); 758 GR_GL_CALL(gli, DeleteShader(shaderId)); 759 return 0; 760 } 761 } 762 if (c_PrintShaders) { 763 GrPrintf(shaderSrc.c_str()); 764 GrPrintf("\n"); 765 } 766 767 // Attach the shader, but defer deletion until after we have linked the program. 768 // This works around a bug in the Android emulator's GLES2 wrapper which 769 // will immediately delete the shader object and free its memory even though it's 770 // attached to a program, which then causes glLinkProgram to fail. 771 GR_GL_CALL(gli, AttachShader(programId, shaderId)); 772 773 return shaderId; 774} 775 776bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const { 777 SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 778 fragShaderSrc.append(fFSExtensions); 779 append_default_precision_qualifier(kDefaultFragmentPrecision, 780 fGpu->glStandard(), 781 &fragShaderSrc); 782 this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); 783 this->appendDecls(fFSInputs, &fragShaderSrc); 784 // We shouldn't have declared outputs on 1.10 785 SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty()); 786 this->appendDecls(fFSOutputs, &fragShaderSrc); 787 fragShaderSrc.append(fFSFunctions); 788 fragShaderSrc.append("void main() {\n"); 789 fragShaderSrc.append(fFSCode); 790 fragShaderSrc.append("}\n"); 791 792 GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc); 793 if (!fragShaderId) { 794 return false; 795 } 796 797 *shaderIds->append() = fragShaderId; 798 799 return true; 800} 801 802void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const { 803 if (fHasCustomColorOutput) { 804 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); 805 } 806 if (fHasSecondaryOutput) { 807 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); 808 } 809} 810 811const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { 812 return fGpu->ctxInfo(); 813} 814 815//////////////////////////////////////////////////////////////////////////////// 816 817GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu, 818 GrGLUniformManager* uniformManager, 819 const GrGLProgramDesc& desc) 820 : INHERITED(gpu, uniformManager, desc) 821 , fVSAttrs(kVarsPerBlock) 822 , fVSOutputs(kVarsPerBlock) 823 , fGSInputs(kVarsPerBlock) 824 , fGSOutputs(kVarsPerBlock) { 825 826 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); 827 828 fOutput.fHasVertexShader = true; 829 830 fPositionVar = &fVSAttrs.push_back(); 831 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); 832 if (-1 != header.fLocalCoordAttributeIndex) { 833 fLocalCoordsVar = &fVSAttrs.push_back(); 834 fLocalCoordsVar->set(kVec2f_GrSLType, 835 GrGLShaderVar::kAttribute_TypeModifier, 836 "aLocalCoords"); 837 } else { 838 fLocalCoordsVar = fPositionVar; 839 } 840 841 const char* viewMName; 842 fOutput.fUniformHandles.fViewMatrixUni = 843 this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kMat33f_GrSLType, "ViewM", 844 &viewMName); 845 const char* rtAdjustName; 846 fOutput.fUniformHandles.fRTAdjustmentUni = 847 this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kVec4f_GrSLType, "rtAdjustment", 848 &rtAdjustName); 849 850 // Transform the position into Skia's device coords. 851 this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n", 852 viewMName, fPositionVar->c_str()); 853 854 // Transform from Skia's device coords to GL's normalized device coords. 855 this->vsCodeAppendf( 856 "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n", 857 rtAdjustName, rtAdjustName); 858 859 // we output point size in the GS if present 860 if (header.fEmitsPointSize 861#if GR_GL_EXPERIMENTAL_GS 862 && !header.fExperimentalGS 863#endif 864 ) { 865 this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); 866 } 867 868 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { 869 this->addAttribute(kVec4f_GrSLType, color_attribute_name()); 870 const char *vsName, *fsName; 871 this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 872 this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); 873 this->setInputColor(fsName); 874 } 875 876 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { 877 this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); 878 const char *vsName, *fsName; 879 this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 880 this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); 881 this->setInputCoverage(fsName); 882 } 883} 884 885bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) { 886 for (int i = 0; i < fVSAttrs.count(); ++i) { 887 const GrGLShaderVar& attr = fVSAttrs[i]; 888 // if attribute already added, don't add it again 889 if (attr.getName().equals(name)) { 890 SkASSERT(attr.getType() == type); 891 return false; 892 } 893 } 894 fVSAttrs.push_back().set(type, 895 GrGLShaderVar::kAttribute_TypeModifier, 896 name); 897 return true; 898} 899 900bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex, 901 GrSLType type, 902 const SkString& name) { 903 if (!this->addAttribute(type, name.c_str())) { 904 return false; 905 } 906 907 fEffectAttributes.push_back().set(attributeIndex, name); 908 return true; 909} 910 911void GrGLFullShaderBuilder::addVarying(GrSLType type, 912 const char* name, 913 const char** vsOutName, 914 const char** fsInName) { 915 fVSOutputs.push_back(); 916 fVSOutputs.back().setType(type); 917 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 918 this->nameVariable(fVSOutputs.back().accessName(), 'v', name); 919 920 if (vsOutName) { 921 *vsOutName = fVSOutputs.back().getName().c_str(); 922 } 923 // input to FS comes either from VS or GS 924 const SkString* fsName; 925#if GR_GL_EXPERIMENTAL_GS 926 if (this->desc().getHeader().fExperimentalGS) { 927 // if we have a GS take each varying in as an array 928 // and output as non-array. 929 fGSInputs.push_back(); 930 fGSInputs.back().setType(type); 931 fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); 932 fGSInputs.back().setUnsizedArray(); 933 *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 934 fGSOutputs.push_back(); 935 fGSOutputs.back().setType(type); 936 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 937 this->nameVariable(fGSOutputs.back().accessName(), 'g', name); 938 fsName = fGSOutputs.back().accessName(); 939 } else 940#endif 941 { 942 fsName = fVSOutputs.back().accessName(); 943 } 944 this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName); 945 if (fsInName) { 946 *fsInName = fsName->c_str(); 947 } 948} 949 950const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const { 951 const AttributePair* attribEnd = fEffectAttributes.end(); 952 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 953 if (attrib->fIndex == attributeIndex) { 954 return &attrib->fName; 955 } 956 } 957 958 return NULL; 959} 960 961GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( 962 const GrEffectStage* effectStages[], 963 const EffectKey effectKeys[], 964 int effectCnt, 965 GrGLSLExpr4* inOutFSColor) { 966 967 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); 968 this->INHERITED::createAndEmitEffects(&programEffectsBuilder, 969 effectStages, 970 effectKeys, 971 effectCnt, 972 inOutFSColor); 973 return programEffectsBuilder.finish(); 974} 975 976bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, 977 SkTDArray<GrGLuint>* shaderIds) const { 978 const GrGLContext& glCtx = this->gpu()->glContext(); 979 SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 980 this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); 981 this->appendDecls(fVSAttrs, &vertShaderSrc); 982 this->appendDecls(fVSOutputs, &vertShaderSrc); 983 vertShaderSrc.append("void main() {\n"); 984 vertShaderSrc.append(fVSCode); 985 vertShaderSrc.append("}\n"); 986 GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc); 987 if (!vertShaderId) { 988 return false; 989 } 990 *shaderIds->append() = vertShaderId; 991 992#if GR_GL_EXPERIMENTAL_GS 993 if (this->desc().getHeader().fExperimentalGS) { 994 SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); 995 SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 996 geomShaderSrc.append("layout(triangles) in;\n" 997 "layout(triangle_strip, max_vertices = 6) out;\n"); 998 this->appendDecls(fGSInputs, &geomShaderSrc); 999 this->appendDecls(fGSOutputs, &geomShaderSrc); 1000 geomShaderSrc.append("void main() {\n"); 1001 geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" 1002 "\t\tgl_Position = gl_in[i].gl_Position;\n"); 1003 if (this->desc().getHeader().fEmitsPointSize) { 1004 geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); 1005 } 1006 SkASSERT(fGSInputs.count() == fGSOutputs.count()); 1007 for (int i = 0; i < fGSInputs.count(); ++i) { 1008 geomShaderSrc.appendf("\t\t%s = %s[i];\n", 1009 fGSOutputs[i].getName().c_str(), 1010 fGSInputs[i].getName().c_str()); 1011 } 1012 geomShaderSrc.append("\t\tEmitVertex();\n" 1013 "\t}\n" 1014 "\tEndPrimitive();\n"); 1015 geomShaderSrc.append("}\n"); 1016 GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc); 1017 if (!geomShaderId) { 1018 return false; 1019 } 1020 *shaderIds->append() = geomShaderId; 1021 } 1022#endif 1023 1024 return this->INHERITED::compileAndAttachShaders(programId, shaderIds); 1025} 1026 1027void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const { 1028 this->INHERITED::bindProgramLocations(programId); 1029 1030 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); 1031 1032 // Bind the attrib locations to same values for all shaders 1033 SkASSERT(-1 != header.fPositionAttributeIndex); 1034 GL_CALL(BindAttribLocation(programId, 1035 header.fPositionAttributeIndex, 1036 fPositionVar->c_str())); 1037 if (-1 != header.fLocalCoordAttributeIndex) { 1038 GL_CALL(BindAttribLocation(programId, 1039 header.fLocalCoordAttributeIndex, 1040 fLocalCoordsVar->c_str())); 1041 } 1042 if (-1 != header.fColorAttributeIndex) { 1043 GL_CALL(BindAttribLocation(programId, 1044 header.fColorAttributeIndex, 1045 color_attribute_name())); 1046 } 1047 if (-1 != header.fCoverageAttributeIndex) { 1048 GL_CALL(BindAttribLocation(programId, 1049 header.fCoverageAttributeIndex, 1050 coverage_attribute_name())); 1051 } 1052 1053 const AttributePair* attribEnd = fEffectAttributes.end(); 1054 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 1055 GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); 1056 } 1057} 1058 1059//////////////////////////////////////////////////////////////////////////////// 1060 1061GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu, 1062 GrGLUniformManager* uniformManager, 1063 const GrGLProgramDesc& desc) 1064 : INHERITED(gpu, uniformManager, desc) { 1065 1066 SkASSERT(!desc.getHeader().fHasVertexCode); 1067 SkASSERT(gpu->glCaps().pathRenderingSupport()); 1068 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); 1069 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); 1070} 1071 1072int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) { 1073 int firstFreeCoordSet = fOutput.fTexCoordSetCnt; 1074 fOutput.fTexCoordSetCnt += count; 1075 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fOutput.fTexCoordSetCnt); 1076 return firstFreeCoordSet; 1077} 1078 1079GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( 1080 const GrEffectStage* effectStages[], 1081 const EffectKey effectKeys[], 1082 int effectCnt, 1083 GrGLSLExpr4* inOutFSColor) { 1084 1085 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, 1086 effectCnt); 1087 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, 1088 effectStages, 1089 effectKeys, 1090 effectCnt, 1091 inOutFSColor); 1092 return pathTexGenEffectsBuilder.finish(); 1093} 1094