| OLD | NEW |
| (Empty) |
| 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/GrGLSLPrettyPrint.h" | |
| 11 #include "gl/GrGLUniformHandle.h" | |
| 12 #include "GrCoordTransform.h" | |
| 13 #include "GrDrawEffect.h" | |
| 14 #include "GrGpuGL.h" | |
| 15 #include "GrTexture.h" | |
| 16 #include "SkRTConf.h" | |
| 17 #include "SkTraceEvent.h" | |
| 18 | |
| 19 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) | |
| 20 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) | |
| 21 | |
| 22 // number of each input/output type in a single allocation block | |
| 23 static const int kVarsPerBlock = 8; | |
| 24 | |
| 25 // except FS outputs where we expect 2 at most. | |
| 26 static const int kMaxFSOutputs = 2; | |
| 27 | |
| 28 // ES2 FS only guarantees mediump and lowp support | |
| 29 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
:kMedium_Precision; | |
| 30 | |
| 31 typedef GrGLProgramDataManager::UniformHandle UniformHandle; | |
| 32 | |
| 33 SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, | |
| 34 "Print the source code for all shaders generated."); | |
| 35 | |
| 36 /////////////////////////////////////////////////////////////////////////////// | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 inline const char* color_attribute_name() { return "aColor"; } | |
| 41 inline const char* coverage_attribute_name() { return "aCoverage"; } | |
| 42 inline const char* declared_color_output_name() { return "fsColorOut"; } | |
| 43 inline const char* dual_source_output_name() { return "dualSourceOut"; } | |
| 44 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen)
{ | |
| 45 if (kVec2f_GrSLType == type) { | |
| 46 return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; | |
| 47 } else { | |
| 48 SkASSERT(kVec3f_GrSLType == type); | |
| 49 return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj
"; | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 void append_texture_lookup(SkString* out, | |
| 54 GrGpuGL* gpu, | |
| 55 const char* samplerName, | |
| 56 const char* coordName, | |
| 57 uint32_t configComponentMask, | |
| 58 const char* swizzle, | |
| 59 GrSLType varyingType = kVec2f_GrSLType) { | |
| 60 SkASSERT(NULL != coordName); | |
| 61 | |
| 62 out->appendf("%s(%s, %s)", | |
| 63 sample_function_name(varyingType, gpu->glslGeneration()), | |
| 64 samplerName, | |
| 65 coordName); | |
| 66 | |
| 67 char mangledSwizzle[5]; | |
| 68 | |
| 69 // The swizzling occurs using texture params instead of shader-mangling if A
RB_texture_swizzle | |
| 70 // is available. | |
| 71 if (!gpu->glCaps().textureSwizzleSupport() && | |
| 72 (kA_GrColorComponentFlag == configComponentMask)) { | |
| 73 char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; | |
| 74 int i; | |
| 75 for (i = 0; '\0' != swizzle[i]; ++i) { | |
| 76 mangledSwizzle[i] = alphaChar; | |
| 77 } | |
| 78 mangledSwizzle[i] ='\0'; | |
| 79 swizzle = mangledSwizzle; | |
| 80 } | |
| 81 // For shader prettiness we omit the swizzle rather than appending ".rgba". | |
| 82 if (memcmp(swizzle, "rgba", 4)) { | |
| 83 out->appendf(".%s", swizzle); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 } | |
| 88 | |
| 89 static const char kDstCopyColorName[] = "_dstColor"; | |
| 90 | |
| 91 /////////////////////////////////////////////////////////////////////////////// | |
| 92 | |
| 93 bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[], | |
| 94 const GrEffectStage* coverageStages[]) { | |
| 95 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); | |
| 96 | |
| 97 /////////////////////////////////////////////////////////////////////////// | |
| 98 // emit code to read the dst copy texture, if necessary | |
| 99 if (kNoDstRead_DstReadKey != header.fDstReadKey && !fGpu->glCaps().fbFetchSu
pport()) { | |
| 100 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKe
y); | |
| 101 const char* dstCopyTopLeftName; | |
| 102 const char* dstCopyCoordScaleName; | |
| 103 const char* dstCopySamplerName; | |
| 104 uint32_t configMask; | |
| 105 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { | |
| 106 configMask = kA_GrColorComponentFlag; | |
| 107 } else { | |
| 108 configMask = kRGBA_GrColorComponentFlags; | |
| 109 } | |
| 110 fUniformHandles.fDstCopySamplerUni = | |
| 111 this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopy
Sampler", | |
| 112 &dstCopySamplerName); | |
| 113 fUniformHandles.fDstCopyTopLeftUni = | |
| 114 this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUppe
rLeft", | |
| 115 &dstCopyTopLeftName); | |
| 116 fUniformHandles.fDstCopyScaleUni = | |
| 117 this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoor
dScale", | |
| 118 &dstCopyCoordScaleName); | |
| 119 const char* fragPos = this->fragmentPosition(); | |
| 120 this->fsCodeAppend("\t// Read color from copy of the destination.\n"); | |
| 121 this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", | |
| 122 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); | |
| 123 if (!topDown) { | |
| 124 this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); | |
| 125 } | |
| 126 this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); | |
| 127 append_texture_lookup(&fFSCode, | |
| 128 fGpu, | |
| 129 dstCopySamplerName, | |
| 130 "_dstTexCoord", | |
| 131 configMask, | |
| 132 "rgba"); | |
| 133 this->fsCodeAppend(";\n\n"); | |
| 134 } | |
| 135 | |
| 136 /////////////////////////////////////////////////////////////////////////// | |
| 137 // get the initial color and coverage to feed into the first effect in each
effect chain | |
| 138 | |
| 139 GrGLSLExpr4 inputColor; | |
| 140 GrGLSLExpr4 inputCoverage; | |
| 141 | |
| 142 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { | |
| 143 const char* name; | |
| 144 fUniformHandles.fColorUni = | |
| 145 this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrS
LType, "Color", | |
| 146 &name); | |
| 147 inputColor = GrGLSLExpr4(name); | |
| 148 } | |
| 149 | |
| 150 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { | |
| 151 const char* name; | |
| 152 fUniformHandles.fCoverageUni = | |
| 153 this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrS
LType, "Coverage", | |
| 154 &name); | |
| 155 inputCoverage = GrGLSLExpr4(name); | |
| 156 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput)
{ | |
| 157 inputCoverage = GrGLSLExpr4(1); | |
| 158 } | |
| 159 | |
| 160 if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { | |
| 161 fFSOutputs.push_back().set(kVec4f_GrSLType, | |
| 162 GrGLShaderVar::kOut_TypeModifier, | |
| 163 declared_color_output_name()); | |
| 164 fHasCustomColorOutput = true; | |
| 165 } | |
| 166 | |
| 167 this->emitCodeBeforeEffects(&inputColor, &inputCoverage); | |
| 168 | |
| 169 /////////////////////////////////////////////////////////////////////////// | |
| 170 // emit the per-effect code for both color and coverage effects | |
| 171 | |
| 172 GrGLProgramDesc::EffectKeyProvider colorKeyProvider( | |
| 173 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType); | |
| 174 fColorEffects.reset(this->createAndEmitEffects(colorStages, | |
| 175 this->desc().numColorEffects(
), | |
| 176 colorKeyProvider, | |
| 177 &inputColor)); | |
| 178 | |
| 179 GrGLProgramDesc::EffectKeyProvider coverageKeyProvider( | |
| 180 &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType)
; | |
| 181 fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, | |
| 182 this->desc().numCoverageEf
fects(), | |
| 183 coverageKeyProvider, | |
| 184 &inputCoverage)); | |
| 185 | |
| 186 this->emitCodeAfterEffects(); | |
| 187 | |
| 188 /////////////////////////////////////////////////////////////////////////// | |
| 189 // write the secondary color output if necessary | |
| 190 if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutpu
t)) { | |
| 191 const char* secondaryOutputName = this->enableSecondaryOutput(); | |
| 192 | |
| 193 // default coeff to ones for kCoverage_DualSrcOutput | |
| 194 GrGLSLExpr4 coeff(1); | |
| 195 if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCov
erageOutput) { | |
| 196 // Get (1-A) into coeff | |
| 197 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); | |
| 198 } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == | |
| 199 header.fCoverageOutput){ | |
| 200 // Get (1-RGBA) into coeff | |
| 201 coeff = GrGLSLExpr4(1) - inputColor; | |
| 202 } | |
| 203 // Get coeff * coverage into modulate and then write that to the dual so
urce output. | |
| 204 this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputC
overage).c_str()); | |
| 205 } | |
| 206 | |
| 207 /////////////////////////////////////////////////////////////////////////// | |
| 208 // combine color and coverage as frag color | |
| 209 | |
| 210 // Get "color * coverage" into fragColor | |
| 211 GrGLSLExpr4 fragColor = inputColor * inputCoverage; | |
| 212 // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do
so. | |
| 213 if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutpu
t) { | |
| 214 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; | |
| 215 | |
| 216 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor()); | |
| 217 | |
| 218 fragColor = fragColor + dstContribution; | |
| 219 } | |
| 220 this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_
str()); | |
| 221 | |
| 222 if (!this->finish()) { | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 return true; | |
| 227 } | |
| 228 | |
| 229 ////////////////////////////////////////////////////////////////////////////// | |
| 230 | |
| 231 GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, | |
| 232 const GrGLProgramDesc& desc) | |
| 233 : fHasVertexShader(false) | |
| 234 , fTexCoordSetCnt(0) | |
| 235 , fProgramID(0) | |
| 236 , fDesc(desc) | |
| 237 , fGpu(gpu) | |
| 238 , fFSFeaturesAddedMask(0) | |
| 239 , fFSInputs(kVarsPerBlock) | |
| 240 , fFSOutputs(kMaxFSOutputs) | |
| 241 , fUniforms(kVarsPerBlock) | |
| 242 , fSetupFragPosition(false) | |
| 243 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFr
agPosKey) | |
| 244 , fHasCustomColorOutput(false) | |
| 245 , fHasSecondaryOutput(false) { | |
| 246 } | |
| 247 | |
| 248 bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { | |
| 249 switch (feature) { | |
| 250 case kStandardDerivatives_GLSLFeature: | |
| 251 if (!fGpu->glCaps().shaderDerivativeSupport()) { | |
| 252 return false; | |
| 253 } | |
| 254 if (kGLES_GrGLStandard == fGpu->glStandard()) { | |
| 255 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, | |
| 256 "GL_OES_standard_derivatives"); | |
| 257 } | |
| 258 return true; | |
| 259 default: | |
| 260 SkFAIL("Unexpected GLSLFeature requested."); | |
| 261 return false; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionN
ame) { | |
| 266 if (!(featureBit & fFSFeaturesAddedMask)) { | |
| 267 fFSExtensions.appendf("#extension %s: require\n", extensionName); | |
| 268 fFSFeaturesAddedMask |= featureBit; | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* nam
e) { | |
| 273 if ('\0' == prefix) { | |
| 274 *out = name; | |
| 275 } else { | |
| 276 out->printf("%c%s", prefix, name); | |
| 277 } | |
| 278 if (fCodeStage.inStageCode()) { | |
| 279 if (out->endsWith('_')) { | |
| 280 // Names containing "__" are reserved. | |
| 281 out->append("x"); | |
| 282 } | |
| 283 out->appendf("_Stage%d", fCodeStage.stageIndex()); | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 const char* GrGLShaderBuilder::dstColor() { | |
| 288 if (fCodeStage.inStageCode()) { | |
| 289 const GrEffect* effect = fCodeStage.effectStage()->getEffect(); | |
| 290 if (!effect->willReadDstColor()) { | |
| 291 SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEff
ect " | |
| 292 "did not request access."); | |
| 293 return ""; | |
| 294 } | |
| 295 } | |
| 296 | |
| 297 if (fGpu->glCaps().fbFetchSupport()) { | |
| 298 this->addFSFeature(1 << (kLastGLSLPrivateFeature + 1), | |
| 299 fGpu->glCaps().fbFetchExtensionString()); | |
| 300 return fGpu->glCaps().fbFetchColorName(); | |
| 301 } else if (fUniformHandles.fDstCopySamplerUni.isValid()) { | |
| 302 return kDstCopyColorName; | |
| 303 } else { | |
| 304 return ""; | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 void GrGLShaderBuilder::appendTextureLookup(SkString* out, | |
| 309 const GrGLShaderBuilder::TextureSamp
ler& sampler, | |
| 310 const char* coordName, | |
| 311 GrSLType varyingType) const { | |
| 312 append_texture_lookup(out, | |
| 313 fGpu, | |
| 314 this->getUniformCStr(sampler.samplerUniform()), | |
| 315 coordName, | |
| 316 sampler.configComponentMask(), | |
| 317 sampler.swizzle(), | |
| 318 varyingType); | |
| 319 } | |
| 320 | |
| 321 void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSa
mpler& sampler, | |
| 322 const char* coordName, | |
| 323 GrSLType varyingType) { | |
| 324 this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); | |
| 325 } | |
| 326 | |
| 327 void GrGLShaderBuilder::fsAppendTextureLookupAndModulate( | |
| 328 const char* modulation, | |
| 329 const GrGLShaderBuilder::TextureSamp
ler& sampler, | |
| 330 const char* coordName, | |
| 331 GrSLType varyingType) { | |
| 332 SkString lookup; | |
| 333 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); | |
| 334 fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); | |
| 335 } | |
| 336 | |
| 337 GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture*
dstCopy, | |
| 338 const GrGLCaps& c
aps) { | |
| 339 uint32_t key = kYesDstRead_DstReadKeyBit; | |
| 340 if (caps.fbFetchSupport()) { | |
| 341 return key; | |
| 342 } | |
| 343 SkASSERT(NULL != dstCopy); | |
| 344 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->confi
g())) { | |
| 345 // The fact that the config is alpha-only must be considered when genera
ting code. | |
| 346 key |= kUseAlphaConfig_DstReadKeyBit; | |
| 347 } | |
| 348 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { | |
| 349 key |= kTopLeftOrigin_DstReadKeyBit; | |
| 350 } | |
| 351 SkASSERT(static_cast<DstReadKey>(key) == key); | |
| 352 return static_cast<DstReadKey>(key); | |
| 353 } | |
| 354 | |
| 355 GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const Gr
RenderTarget* dst, | |
| 356 const Gr
GLCaps&) { | |
| 357 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { | |
| 358 return kTopLeftFragPosRead_FragPosKey; | |
| 359 } else { | |
| 360 return kBottomLeftFragPosRead_FragPosKey; | |
| 361 } | |
| 362 } | |
| 363 | |
| 364 | |
| 365 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, cons
t GrGLCaps& caps) { | |
| 366 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { | |
| 367 if (caps.textureRedSupport()) { | |
| 368 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RE
D, GR_GL_RED }; | |
| 369 return gRedSmear; | |
| 370 } else { | |
| 371 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, | |
| 372 GR_GL_ALPHA, GR_GL_ALPHA }; | |
| 373 return gAlphaSmear; | |
| 374 } | |
| 375 } else { | |
| 376 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE
, GR_GL_ALPHA }; | |
| 377 return gStraight; | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 GrGLProgramDataManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_
t visibility, | |
| 382 GrSLTyp
e type, | |
| 383 const c
har* name, | |
| 384 int cou
nt, | |
| 385 const c
har** outName) { | |
| 386 SkASSERT(name && strlen(name)); | |
| 387 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFr
agment_Visibility); | |
| 388 SkASSERT(0 == (~kVisibilityMask & visibility)); | |
| 389 SkASSERT(0 != visibility); | |
| 390 | |
| 391 UniformInfo& uni = fUniforms.push_back(); | |
| 392 uni.fVariable.setType(type); | |
| 393 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); | |
| 394 this->nameVariable(uni.fVariable.accessName(), 'u', name); | |
| 395 uni.fVariable.setArrayCount(count); | |
| 396 uni.fVisibility = visibility; | |
| 397 | |
| 398 // If it is visible in both the VS and FS, the precision must match. | |
| 399 // We declare a default FS precision, but not a default VS. So set the var | |
| 400 // to use the default FS precision. | |
| 401 if ((kVertex_Visibility | kFragment_Visibility) == visibility) { | |
| 402 // the fragment and vertex precisions must match | |
| 403 uni.fVariable.setPrecision(kDefaultFragmentPrecision); | |
| 404 } | |
| 405 | |
| 406 if (NULL != outName) { | |
| 407 *outName = uni.fVariable.c_str(); | |
| 408 } | |
| 409 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUnifor
ms.count() - 1); | |
| 410 } | |
| 411 | |
| 412 SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coord
s, int index) { | |
| 413 if (kVec3f_GrSLType != coords[index].type()) { | |
| 414 SkASSERT(kVec2f_GrSLType == coords[index].type()); | |
| 415 return coords[index].getName(); | |
| 416 } | |
| 417 | |
| 418 SkString coords2D("coords2D"); | |
| 419 if (0 != index) { | |
| 420 coords2D.appendf("_%i", index); | |
| 421 } | |
| 422 this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", | |
| 423 coords2D.c_str(), coords[index].c_str(), coords[index].c
_str()); | |
| 424 return coords2D; | |
| 425 } | |
| 426 | |
| 427 const char* GrGLShaderBuilder::fragmentPosition() { | |
| 428 if (fCodeStage.inStageCode()) { | |
| 429 const GrEffect* effect = fCodeStage.effectStage()->getEffect(); | |
| 430 if (!effect->willReadFragmentPosition()) { | |
| 431 SkDEBUGFAIL("GrGLEffect asked for frag position but its generating G
rEffect " | |
| 432 "did not request access."); | |
| 433 return ""; | |
| 434 } | |
| 435 } | |
| 436 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers | |
| 437 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the | |
| 438 // declaration varies in earlier GLSL specs. So it is simpler to omit it. | |
| 439 if (fTopLeftFragPosRead) { | |
| 440 fSetupFragPosition = true; | |
| 441 return "gl_FragCoord"; | |
| 442 } else if (fGpu->glCaps().fragCoordConventionsSupport()) { | |
| 443 if (!fSetupFragPosition) { | |
| 444 if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { | |
| 445 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature
, | |
| 446 "GL_ARB_fragment_coord_conventions"); | |
| 447 } | |
| 448 fFSInputs.push_back().set(kVec4f_GrSLType, | |
| 449 GrGLShaderVar::kIn_TypeModifier, | |
| 450 "gl_FragCoord", | |
| 451 GrGLShaderVar::kDefault_Precision, | |
| 452 GrGLShaderVar::kUpperLeft_Origin); | |
| 453 fSetupFragPosition = true; | |
| 454 } | |
| 455 return "gl_FragCoord"; | |
| 456 } else { | |
| 457 static const char* kCoordName = "fragCoordYDown"; | |
| 458 if (!fSetupFragPosition) { | |
| 459 // temporarily change the stage index because we're inserting non-st
age code. | |
| 460 CodeStage::AutoStageRestore csar(&fCodeStage, NULL); | |
| 461 | |
| 462 SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); | |
| 463 const char* rtHeightName; | |
| 464 | |
| 465 fUniformHandles.fRTHeightUni = | |
| 466 this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeigh
t", &rtHeightName); | |
| 467 | |
| 468 // Using glFragCoord.zw for the last two components tickles an Adren
o driver bug that | |
| 469 // causes programs to fail to link. Making this function return a ve
c2() didn't fix the | |
| 470 // problem but using 1.0 for the last two components does. | |
| 471 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_Fra
gCoord.y, 1.0, " | |
| 472 "1.0);\n", kCoordName, rtHeightName); | |
| 473 fSetupFragPosition = true; | |
| 474 } | |
| 475 SkASSERT(fUniformHandles.fRTHeightUni.isValid()); | |
| 476 return kCoordName; | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, | |
| 481 const char* name, | |
| 482 int argCnt, | |
| 483 const GrGLShaderVar* args, | |
| 484 const char* body, | |
| 485 SkString* outName) { | |
| 486 fFSFunctions.append(GrGLSLTypeString(returnType)); | |
| 487 this->nameVariable(outName, '\0', name); | |
| 488 fFSFunctions.appendf(" %s", outName->c_str()); | |
| 489 fFSFunctions.append("("); | |
| 490 for (int i = 0; i < argCnt; ++i) { | |
| 491 args[i].appendDecl(this->ctxInfo(), &fFSFunctions); | |
| 492 if (i < argCnt - 1) { | |
| 493 fFSFunctions.append(", "); | |
| 494 } | |
| 495 } | |
| 496 fFSFunctions.append(") {\n"); | |
| 497 fFSFunctions.append(body); | |
| 498 fFSFunctions.append("}\n\n"); | |
| 499 } | |
| 500 | |
| 501 namespace { | |
| 502 | |
| 503 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, | |
| 504 GrGLStandard standard, | |
| 505 SkString* str) { | |
| 506 // Desktop GLSL has added precision qualifiers but they don't do anything. | |
| 507 if (kGLES_GrGLStandard == standard) { | |
| 508 switch (p) { | |
| 509 case GrGLShaderVar::kHigh_Precision: | |
| 510 str->append("precision highp float;\n"); | |
| 511 break; | |
| 512 case GrGLShaderVar::kMedium_Precision: | |
| 513 str->append("precision mediump float;\n"); | |
| 514 break; | |
| 515 case GrGLShaderVar::kLow_Precision: | |
| 516 str->append("precision lowp float;\n"); | |
| 517 break; | |
| 518 case GrGLShaderVar::kDefault_Precision: | |
| 519 SkFAIL("Default precision now allowed."); | |
| 520 default: | |
| 521 SkFAIL("Unknown precision value."); | |
| 522 } | |
| 523 } | |
| 524 } | |
| 525 } | |
| 526 | |
| 527 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { | |
| 528 for (int i = 0; i < vars.count(); ++i) { | |
| 529 vars[i].appendDecl(this->ctxInfo(), out); | |
| 530 out->append(";\n"); | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, | |
| 535 SkString* out) const { | |
| 536 for (int i = 0; i < fUniforms.count(); ++i) { | |
| 537 if (fUniforms[i].fVisibility & visibility) { | |
| 538 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); | |
| 539 out->append(";\n"); | |
| 540 } | |
| 541 } | |
| 542 } | |
| 543 | |
| 544 void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
ffectsBuilder, | |
| 545 const GrEffectStage* effectStages[]
, | |
| 546 int effectCnt, | |
| 547 const GrGLProgramDesc::EffectKeyPro
vider& keyProvider, | |
| 548 GrGLSLExpr4* fsInOutColor) { | |
| 549 bool effectEmitted = false; | |
| 550 | |
| 551 GrGLSLExpr4 inColor = *fsInOutColor; | |
| 552 GrGLSLExpr4 outColor; | |
| 553 | |
| 554 for (int e = 0; e < effectCnt; ++e) { | |
| 555 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()
); | |
| 556 const GrEffectStage& stage = *effectStages[e]; | |
| 557 | |
| 558 CodeStage::AutoStageRestore csar(&fCodeStage, &stage); | |
| 559 | |
| 560 if (inColor.isZeros()) { | |
| 561 SkString inColorName; | |
| 562 | |
| 563 // Effects have no way to communicate zeros, they treat an empty str
ing as ones. | |
| 564 this->nameVariable(&inColorName, '\0', "input"); | |
| 565 this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColo
r.c_str()); | |
| 566 inColor = inColorName; | |
| 567 } | |
| 568 | |
| 569 // create var to hold stage result | |
| 570 SkString outColorName; | |
| 571 this->nameVariable(&outColorName, '\0', "output"); | |
| 572 this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); | |
| 573 outColor = outColorName; | |
| 574 | |
| 575 | |
| 576 programEffectsBuilder->emitEffect(stage, | |
| 577 keyProvider.get(e), | |
| 578 outColor.c_str(), | |
| 579 inColor.isOnes() ? NULL : inColor.c_st
r(), | |
| 580 fCodeStage.stageIndex()); | |
| 581 | |
| 582 inColor = outColor; | |
| 583 effectEmitted = true; | |
| 584 } | |
| 585 | |
| 586 if (effectEmitted) { | |
| 587 *fsInOutColor = outColor; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 const char* GrGLShaderBuilder::getColorOutputName() const { | |
| 592 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"
; | |
| 593 } | |
| 594 | |
| 595 const char* GrGLShaderBuilder::enableSecondaryOutput() { | |
| 596 if (!fHasSecondaryOutput) { | |
| 597 fFSOutputs.push_back().set(kVec4f_GrSLType, | |
| 598 GrGLShaderVar::kOut_TypeModifier, | |
| 599 dual_source_output_name()); | |
| 600 fHasSecondaryOutput = true; | |
| 601 } | |
| 602 return dual_source_output_name(); | |
| 603 } | |
| 604 | |
| 605 bool GrGLShaderBuilder::finish() { | |
| 606 SkASSERT(0 == fProgramID); | |
| 607 GL_CALL_RET(fProgramID, CreateProgram()); | |
| 608 if (!fProgramID) { | |
| 609 return false; | |
| 610 } | |
| 611 | |
| 612 SkTDArray<GrGLuint> shadersToDelete; | |
| 613 | |
| 614 if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) { | |
| 615 GL_CALL(DeleteProgram(fProgramID)); | |
| 616 return false; | |
| 617 } | |
| 618 | |
| 619 this->bindProgramLocations(fProgramID); | |
| 620 | |
| 621 GL_CALL(LinkProgram(fProgramID)); | |
| 622 | |
| 623 // Calling GetProgramiv is expensive in Chromium. Assume success in release
builds. | |
| 624 bool checkLinked = !fGpu->ctxInfo().isChromium(); | |
| 625 #ifdef SK_DEBUG | |
| 626 checkLinked = true; | |
| 627 #endif | |
| 628 if (checkLinked) { | |
| 629 GrGLint linked = GR_GL_INIT_ZERO; | |
| 630 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); | |
| 631 if (!linked) { | |
| 632 GrGLint infoLen = GR_GL_INIT_ZERO; | |
| 633 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); | |
| 634 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debug
ger | |
| 635 if (infoLen > 0) { | |
| 636 // retrieve length even though we don't need it to workaround | |
| 637 // bug in chrome cmd buffer param validation. | |
| 638 GrGLsizei length = GR_GL_INIT_ZERO; | |
| 639 GL_CALL(GetProgramInfoLog(fProgramID, | |
| 640 infoLen+1, | |
| 641 &length, | |
| 642 (char*)log.get())); | |
| 643 GrPrintf((char*)log.get()); | |
| 644 } | |
| 645 SkDEBUGFAIL("Error linking program"); | |
| 646 GL_CALL(DeleteProgram(fProgramID)); | |
| 647 fProgramID = 0; | |
| 648 return false; | |
| 649 } | |
| 650 } | |
| 651 | |
| 652 this->resolveProgramLocations(fProgramID); | |
| 653 | |
| 654 for (int i = 0; i < shadersToDelete.count(); ++i) { | |
| 655 GL_CALL(DeleteShader(shadersToDelete[i])); | |
| 656 } | |
| 657 | |
| 658 return true; | |
| 659 } | |
| 660 | |
| 661 // Compiles a GL shader and attaches it to a program. Returns the shader ID if | |
| 662 // successful, or 0 if not. | |
| 663 static GrGLuint attach_shader(const GrGLContext& glCtx, | |
| 664 GrGLuint programId, | |
| 665 GrGLenum type, | |
| 666 const SkString& shaderSrc) { | |
| 667 const GrGLInterface* gli = glCtx.interface(); | |
| 668 | |
| 669 GrGLuint shaderId; | |
| 670 GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); | |
| 671 if (0 == shaderId) { | |
| 672 return 0; | |
| 673 } | |
| 674 | |
| 675 #ifdef SK_DEBUG | |
| 676 SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, false)
; | |
| 677 const GrGLchar* sourceStr = prettySource.c_str(); | |
| 678 GrGLint sourceLength = static_cast<GrGLint>(prettySource.size()); | |
| 679 #else | |
| 680 GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); | |
| 681 const GrGLchar* sourceStr = shaderSrc.c_str(); | |
| 682 #endif | |
| 683 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); | |
| 684 GR_GL_CALL(gli, CompileShader(shaderId)); | |
| 685 | |
| 686 // Calling GetShaderiv in Chromium is quite expensive. Assume success in rel
ease builds. | |
| 687 bool checkCompiled = !glCtx.isChromium(); | |
| 688 #ifdef SK_DEBUG | |
| 689 checkCompiled = true; | |
| 690 #endif | |
| 691 if (checkCompiled) { | |
| 692 GrGLint compiled = GR_GL_INIT_ZERO; | |
| 693 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); | |
| 694 | |
| 695 if (!compiled) { | |
| 696 GrGLint infoLen = GR_GL_INIT_ZERO; | |
| 697 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLe
n)); | |
| 698 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugg
er | |
| 699 if (infoLen > 0) { | |
| 700 // retrieve length even though we don't need it to workaround bu
g in Chromium cmd | |
| 701 // buffer param validation. | |
| 702 GrGLsizei length = GR_GL_INIT_ZERO; | |
| 703 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, | |
| 704 &length, (char*)log.get())); | |
| 705 GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_s
tr()); | |
| 706 GrPrintf("\n%s", log.get()); | |
| 707 } | |
| 708 SkDEBUGFAIL("Shader compilation failed!"); | |
| 709 GR_GL_CALL(gli, DeleteShader(shaderId)); | |
| 710 return 0; | |
| 711 } | |
| 712 } | |
| 713 | |
| 714 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLSha
der", | |
| 715 TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shad
erSrc.c_str())); | |
| 716 if (c_PrintShaders) { | |
| 717 GrPrintf(GrGLSLPrettyPrint::PrettyPrintGLSL(shaderSrc, true).c_str()); | |
| 718 GrPrintf("\n"); | |
| 719 } | |
| 720 | |
| 721 // Attach the shader, but defer deletion until after we have linked the prog
ram. | |
| 722 // This works around a bug in the Android emulator's GLES2 wrapper which | |
| 723 // will immediately delete the shader object and free its memory even though
it's | |
| 724 // attached to a program, which then causes glLinkProgram to fail. | |
| 725 GR_GL_CALL(gli, AttachShader(programId, shaderId)); | |
| 726 | |
| 727 return shaderId; | |
| 728 } | |
| 729 | |
| 730 bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<Gr
GLuint>* shaderIds) const { | |
| 731 SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); | |
| 732 fragShaderSrc.append(fFSExtensions); | |
| 733 append_default_precision_qualifier(kDefaultFragmentPrecision, | |
| 734 fGpu->glStandard(), | |
| 735 &fragShaderSrc); | |
| 736 this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); | |
| 737 this->appendDecls(fFSInputs, &fragShaderSrc); | |
| 738 // We shouldn't have declared outputs on 1.10 | |
| 739 SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty
()); | |
| 740 this->appendDecls(fFSOutputs, &fragShaderSrc); | |
| 741 fragShaderSrc.append(fFSFunctions); | |
| 742 fragShaderSrc.append("void main() {\n"); | |
| 743 fragShaderSrc.append(fFSCode); | |
| 744 fragShaderSrc.append("}\n"); | |
| 745 | |
| 746 GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FR
AGMENT_SHADER, fragShaderSrc); | |
| 747 if (!fragShaderId) { | |
| 748 return false; | |
| 749 } | |
| 750 | |
| 751 *shaderIds->append() = fragShaderId; | |
| 752 | |
| 753 return true; | |
| 754 } | |
| 755 | |
| 756 void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) { | |
| 757 if (fHasCustomColorOutput) { | |
| 758 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())
); | |
| 759 } | |
| 760 if (fHasSecondaryOutput) { | |
| 761 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_
name())); | |
| 762 } | |
| 763 // skbug.com/2056 | |
| 764 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | |
| 765 if (usingBindUniform) { | |
| 766 int count = fUniforms.count(); | |
| 767 for (int i = 0; i < count; ++i) { | |
| 768 GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_s
tr())); | |
| 769 fUniforms[i].fLocation = i; | |
| 770 } | |
| 771 } | |
| 772 } | |
| 773 | |
| 774 void GrGLShaderBuilder::resolveProgramLocations(GrGLuint programId) { | |
| 775 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation
!= NULL; | |
| 776 if (!usingBindUniform) { | |
| 777 int count = fUniforms.count(); | |
| 778 for (int i = 0; i < count; ++i) { | |
| 779 GrGLint location; | |
| 780 GL_CALL_RET(location, | |
| 781 GetUniformLocation(programId, fUniforms[i].fVariable.c_s
tr())); | |
| 782 fUniforms[i].fLocation = location; | |
| 783 } | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { | |
| 788 return fGpu->ctxInfo(); | |
| 789 } | |
| 790 | |
| 791 //////////////////////////////////////////////////////////////////////////////// | |
| 792 | |
| 793 GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu, | |
| 794 const GrGLProgramDesc& desc) | |
| 795 : INHERITED(gpu, desc) | |
| 796 , fVSAttrs(kVarsPerBlock) | |
| 797 , fVSOutputs(kVarsPerBlock) | |
| 798 , fGSInputs(kVarsPerBlock) | |
| 799 , fGSOutputs(kVarsPerBlock) { | |
| 800 } | |
| 801 | |
| 802 void GrGLFullShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr
4* coverage) { | |
| 803 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); | |
| 804 | |
| 805 fHasVertexShader = true; | |
| 806 | |
| 807 fPositionVar = &fVSAttrs.push_back(); | |
| 808 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "
aPosition"); | |
| 809 if (-1 != header.fLocalCoordAttributeIndex) { | |
| 810 fLocalCoordsVar = &fVSAttrs.push_back(); | |
| 811 fLocalCoordsVar->set(kVec2f_GrSLType, | |
| 812 GrGLShaderVar::kAttribute_TypeModifier, | |
| 813 "aLocalCoords"); | |
| 814 } else { | |
| 815 fLocalCoordsVar = fPositionVar; | |
| 816 } | |
| 817 | |
| 818 const char* viewMName; | |
| 819 fUniformHandles.fViewMatrixUni = | |
| 820 this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kMat33f_GrSLType
, "ViewM", | |
| 821 &viewMName); | |
| 822 | |
| 823 // Transform the position into Skia's device coords. | |
| 824 this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n", | |
| 825 viewMName, fPositionVar->c_str()); | |
| 826 | |
| 827 // we output point size in the GS if present | |
| 828 if (header.fEmitsPointSize | |
| 829 #if GR_GL_EXPERIMENTAL_GS | |
| 830 && !header.fExperimentalGS | |
| 831 #endif | |
| 832 ) { | |
| 833 this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); | |
| 834 } | |
| 835 | |
| 836 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { | |
| 837 this->addAttribute(kVec4f_GrSLType, color_attribute_name()); | |
| 838 const char *vsName, *fsName; | |
| 839 this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); | |
| 840 this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); | |
| 841 *color = fsName; | |
| 842 } | |
| 843 | |
| 844 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { | |
| 845 this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); | |
| 846 const char *vsName, *fsName; | |
| 847 this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); | |
| 848 this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); | |
| 849 *coverage = fsName; | |
| 850 } | |
| 851 } | |
| 852 | |
| 853 void GrGLFullShaderBuilder::emitCodeAfterEffects() { | |
| 854 const char* rtAdjustName; | |
| 855 fUniformHandles.fRTAdjustmentUni = | |
| 856 this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kVec4f_GrSLType,
"rtAdjustment", | |
| 857 &rtAdjustName); | |
| 858 | |
| 859 // Transform from Skia's device coords to GL's normalized device coords. | |
| 860 this->vsCodeAppendf( | |
| 861 "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.
z);\n", | |
| 862 rtAdjustName, rtAdjustName); | |
| 863 } | |
| 864 | |
| 865 bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) { | |
| 866 for (int i = 0; i < fVSAttrs.count(); ++i) { | |
| 867 const GrGLShaderVar& attr = fVSAttrs[i]; | |
| 868 // if attribute already added, don't add it again | |
| 869 if (attr.getName().equals(name)) { | |
| 870 SkASSERT(attr.getType() == type); | |
| 871 return false; | |
| 872 } | |
| 873 } | |
| 874 fVSAttrs.push_back().set(type, | |
| 875 GrGLShaderVar::kAttribute_TypeModifier, | |
| 876 name); | |
| 877 return true; | |
| 878 } | |
| 879 | |
| 880 bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex, | |
| 881 GrSLType type, | |
| 882 const SkString& name) { | |
| 883 if (!this->addAttribute(type, name.c_str())) { | |
| 884 return false; | |
| 885 } | |
| 886 | |
| 887 fEffectAttributes.push_back().set(attributeIndex, name); | |
| 888 return true; | |
| 889 } | |
| 890 | |
| 891 void GrGLFullShaderBuilder::addVarying(GrSLType type, | |
| 892 const char* name, | |
| 893 const char** vsOutName, | |
| 894 const char** fsInName) { | |
| 895 fVSOutputs.push_back(); | |
| 896 fVSOutputs.back().setType(type); | |
| 897 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); | |
| 898 this->nameVariable(fVSOutputs.back().accessName(), 'v', name); | |
| 899 | |
| 900 if (vsOutName) { | |
| 901 *vsOutName = fVSOutputs.back().getName().c_str(); | |
| 902 } | |
| 903 // input to FS comes either from VS or GS | |
| 904 const SkString* fsName; | |
| 905 #if GR_GL_EXPERIMENTAL_GS | |
| 906 if (this->desc().getHeader().fExperimentalGS) { | |
| 907 // if we have a GS take each varying in as an array | |
| 908 // and output as non-array. | |
| 909 fGSInputs.push_back(); | |
| 910 fGSInputs.back().setType(type); | |
| 911 fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier)
; | |
| 912 fGSInputs.back().setUnsizedArray(); | |
| 913 *fGSInputs.back().accessName() = fVSOutputs.back().getName(); | |
| 914 fGSOutputs.push_back(); | |
| 915 fGSOutputs.back().setType(type); | |
| 916 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifie
r); | |
| 917 this->nameVariable(fGSOutputs.back().accessName(), 'g', name); | |
| 918 fsName = fGSOutputs.back().accessName(); | |
| 919 } else | |
| 920 #endif | |
| 921 { | |
| 922 fsName = fVSOutputs.back().accessName(); | |
| 923 } | |
| 924 this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsN
ame); | |
| 925 if (fsInName) { | |
| 926 *fsInName = fsName->c_str(); | |
| 927 } | |
| 928 } | |
| 929 | |
| 930 const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex
) const { | |
| 931 const AttributePair* attribEnd = fEffectAttributes.end(); | |
| 932 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attr
ibEnd; ++attrib) { | |
| 933 if (attrib->fIndex == attributeIndex) { | |
| 934 return &attrib->fName; | |
| 935 } | |
| 936 } | |
| 937 | |
| 938 return NULL; | |
| 939 } | |
| 940 | |
| 941 GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( | |
| 942 const GrEffectStage* effectStages[], | |
| 943 int effectCnt, | |
| 944 const GrGLProgramDesc::EffectKeyProvider& keyProvider, | |
| 945 GrGLSLExpr4* inOutFSColor) { | |
| 946 | |
| 947 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); | |
| 948 this->INHERITED::createAndEmitEffects(&programEffectsBuilder, | |
| 949 effectStages, | |
| 950 effectCnt, | |
| 951 keyProvider, | |
| 952 inOutFSColor); | |
| 953 return programEffectsBuilder.finish(); | |
| 954 } | |
| 955 | |
| 956 bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, | |
| 957 SkTDArray<GrGLuint>* shaderI
ds) const { | |
| 958 const GrGLContext& glCtx = this->gpu()->glContext(); | |
| 959 SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); | |
| 960 this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); | |
| 961 this->appendDecls(fVSAttrs, &vertShaderSrc); | |
| 962 this->appendDecls(fVSOutputs, &vertShaderSrc); | |
| 963 vertShaderSrc.append("void main() {\n"); | |
| 964 vertShaderSrc.append(fVSCode); | |
| 965 vertShaderSrc.append("}\n"); | |
| 966 GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER,
vertShaderSrc); | |
| 967 if (!vertShaderId) { | |
| 968 return false; | |
| 969 } | |
| 970 *shaderIds->append() = vertShaderId; | |
| 971 | |
| 972 #if GR_GL_EXPERIMENTAL_GS | |
| 973 if (this->desc().getHeader().fExperimentalGS) { | |
| 974 SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); | |
| 975 SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); | |
| 976 geomShaderSrc.append("layout(triangles) in;\n" | |
| 977 "layout(triangle_strip, max_vertices = 6) out;\n"); | |
| 978 this->appendDecls(fGSInputs, &geomShaderSrc); | |
| 979 this->appendDecls(fGSOutputs, &geomShaderSrc); | |
| 980 geomShaderSrc.append("void main() {\n"); | |
| 981 geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" | |
| 982 "\t\tgl_Position = gl_in[i].gl_Position;\n"); | |
| 983 if (this->desc().getHeader().fEmitsPointSize) { | |
| 984 geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); | |
| 985 } | |
| 986 SkASSERT(fGSInputs.count() == fGSOutputs.count()); | |
| 987 for (int i = 0; i < fGSInputs.count(); ++i) { | |
| 988 geomShaderSrc.appendf("\t\t%s = %s[i];\n", | |
| 989 fGSOutputs[i].getName().c_str(), | |
| 990 fGSInputs[i].getName().c_str()); | |
| 991 } | |
| 992 geomShaderSrc.append("\t\tEmitVertex();\n" | |
| 993 "\t}\n" | |
| 994 "\tEndPrimitive();\n"); | |
| 995 geomShaderSrc.append("}\n"); | |
| 996 GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_S
HADER, geomShaderSrc); | |
| 997 if (!geomShaderId) { | |
| 998 return false; | |
| 999 } | |
| 1000 *shaderIds->append() = geomShaderId; | |
| 1001 } | |
| 1002 #endif | |
| 1003 | |
| 1004 return this->INHERITED::compileAndAttachShaders(programId, shaderIds); | |
| 1005 } | |
| 1006 | |
| 1007 void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) { | |
| 1008 this->INHERITED::bindProgramLocations(programId); | |
| 1009 | |
| 1010 const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); | |
| 1011 | |
| 1012 // Bind the attrib locations to same values for all shaders | |
| 1013 SkASSERT(-1 != header.fPositionAttributeIndex); | |
| 1014 GL_CALL(BindAttribLocation(programId, | |
| 1015 header.fPositionAttributeIndex, | |
| 1016 fPositionVar->c_str())); | |
| 1017 if (-1 != header.fLocalCoordAttributeIndex) { | |
| 1018 GL_CALL(BindAttribLocation(programId, | |
| 1019 header.fLocalCoordAttributeIndex, | |
| 1020 fLocalCoordsVar->c_str())); | |
| 1021 } | |
| 1022 if (-1 != header.fColorAttributeIndex) { | |
| 1023 GL_CALL(BindAttribLocation(programId, | |
| 1024 header.fColorAttributeIndex, | |
| 1025 color_attribute_name())); | |
| 1026 } | |
| 1027 if (-1 != header.fCoverageAttributeIndex) { | |
| 1028 GL_CALL(BindAttribLocation(programId, | |
| 1029 header.fCoverageAttributeIndex, | |
| 1030 coverage_attribute_name())); | |
| 1031 } | |
| 1032 | |
| 1033 const AttributePair* attribEnd = fEffectAttributes.end(); | |
| 1034 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attr
ibEnd; ++attrib) { | |
| 1035 GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_s
tr())); | |
| 1036 } | |
| 1037 } | |
| 1038 | |
| 1039 //////////////////////////////////////////////////////////////////////////////// | |
| 1040 | |
| 1041 GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu, | |
| 1042 const GrGLProgramDe
sc& desc) | |
| 1043 : INHERITED(gpu, desc) { | |
| 1044 SkASSERT(!desc.getHeader().fHasVertexCode); | |
| 1045 SkASSERT(gpu->glCaps().pathRenderingSupport()); | |
| 1046 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorIn
put); | |
| 1047 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverag
eInput); | |
| 1048 } | |
| 1049 | |
| 1050 int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) { | |
| 1051 int firstFreeCoordSet = fTexCoordSetCnt; | |
| 1052 fTexCoordSetCnt += count; | |
| 1053 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt)
; | |
| 1054 return firstFreeCoordSet; | |
| 1055 } | |
| 1056 | |
| 1057 GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( | |
| 1058 const GrEffectStage* effectStages[], | |
| 1059 int effectCnt, | |
| 1060 const GrGLProgramDesc::EffectKeyProvider& keyProvider, | |
| 1061 GrGLSLExpr4* inOutFSColor) { | |
| 1062 | |
| 1063 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this, | |
| 1064 effectCnt); | |
| 1065 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder, | |
| 1066 effectStages, | |
| 1067 effectCnt, | |
| 1068 keyProvider, | |
| 1069 inOutFSColor); | |
| 1070 return pathTexGenEffectsBuilder.finish(); | |
| 1071 } | |
| OLD | NEW |