1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLShaderBuilder.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1001 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "gl/GrGLShaderBuilder.h" 1.12 +#include "gl/GrGLProgram.h" 1.13 +#include "gl/GrGLUniformHandle.h" 1.14 +#include "GrCoordTransform.h" 1.15 +#include "GrDrawEffect.h" 1.16 +#include "GrGpuGL.h" 1.17 +#include "GrTexture.h" 1.18 +#include "SkRTConf.h" 1.19 +#include "SkTrace.h" 1.20 + 1.21 +#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) 1.22 +#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X) 1.23 + 1.24 +// number of each input/output type in a single allocation block 1.25 +static const int kVarsPerBlock = 8; 1.26 + 1.27 +// except FS outputs where we expect 2 at most. 1.28 +static const int kMaxFSOutputs = 2; 1.29 + 1.30 +// ES2 FS only guarantees mediump and lowp support 1.31 +static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 1.32 + 1.33 +typedef GrGLUniformManager::UniformHandle UniformHandle; 1.34 + 1.35 +SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, 1.36 + "Print the source code for all shaders generated."); 1.37 + 1.38 +/////////////////////////////////////////////////////////////////////////////// 1.39 + 1.40 +namespace { 1.41 + 1.42 +inline const char* color_attribute_name() { return "aColor"; } 1.43 +inline const char* coverage_attribute_name() { return "aCoverage"; } 1.44 +inline const char* declared_color_output_name() { return "fsColorOut"; } 1.45 +inline const char* dual_source_output_name() { return "dualSourceOut"; } 1.46 +inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { 1.47 + if (kVec2f_GrSLType == type) { 1.48 + return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; 1.49 + } else { 1.50 + SkASSERT(kVec3f_GrSLType == type); 1.51 + return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; 1.52 + } 1.53 +} 1.54 + 1.55 +void append_texture_lookup(SkString* out, 1.56 + GrGpuGL* gpu, 1.57 + const char* samplerName, 1.58 + const char* coordName, 1.59 + uint32_t configComponentMask, 1.60 + const char* swizzle, 1.61 + GrSLType varyingType = kVec2f_GrSLType) { 1.62 + SkASSERT(NULL != coordName); 1.63 + 1.64 + out->appendf("%s(%s, %s)", 1.65 + sample_function_name(varyingType, gpu->glslGeneration()), 1.66 + samplerName, 1.67 + coordName); 1.68 + 1.69 + char mangledSwizzle[5]; 1.70 + 1.71 + // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle 1.72 + // is available. 1.73 + if (!gpu->glCaps().textureSwizzleSupport() && 1.74 + (kA_GrColorComponentFlag == configComponentMask)) { 1.75 + char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; 1.76 + int i; 1.77 + for (i = 0; '\0' != swizzle[i]; ++i) { 1.78 + mangledSwizzle[i] = alphaChar; 1.79 + } 1.80 + mangledSwizzle[i] ='\0'; 1.81 + swizzle = mangledSwizzle; 1.82 + } 1.83 + // For shader prettiness we omit the swizzle rather than appending ".rgba". 1.84 + if (memcmp(swizzle, "rgba", 4)) { 1.85 + out->appendf(".%s", swizzle); 1.86 + } 1.87 +} 1.88 + 1.89 +} 1.90 + 1.91 +static const char kDstCopyColorName[] = "_dstColor"; 1.92 + 1.93 +/////////////////////////////////////////////////////////////////////////////// 1.94 + 1.95 +GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, 1.96 + GrGLUniformManager& uniformManager, 1.97 + const GrGLProgramDesc& desc) 1.98 + : fGpu(gpu) 1.99 + , fUniformManager(uniformManager) 1.100 + , fFSFeaturesAddedMask(0) 1.101 + , fFSInputs(kVarsPerBlock) 1.102 + , fFSOutputs(kMaxFSOutputs) 1.103 + , fUniforms(kVarsPerBlock) 1.104 + , fSetupFragPosition(false) 1.105 + , fHasCustomColorOutput(false) 1.106 + , fHasSecondaryOutput(false) 1.107 + , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { 1.108 + 1.109 + const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); 1.110 + 1.111 + // Emit code to read the dst copy textue if necessary. 1.112 + if (kNoDstRead_DstReadKey != header.fDstReadKey && 1.113 + GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) { 1.114 + bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); 1.115 + const char* dstCopyTopLeftName; 1.116 + const char* dstCopyCoordScaleName; 1.117 + uint32_t configMask; 1.118 + if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { 1.119 + configMask = kA_GrColorComponentFlag; 1.120 + } else { 1.121 + configMask = kRGBA_GrColorComponentFlags; 1.122 + } 1.123 + fDstCopySamplerUniform = this->addUniform(kFragment_Visibility, 1.124 + kSampler2D_GrSLType, 1.125 + "DstCopySampler"); 1.126 + fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility, 1.127 + kVec2f_GrSLType, 1.128 + "DstCopyUpperLeft", 1.129 + &dstCopyTopLeftName); 1.130 + fDstCopyScaleUniform = this->addUniform(kFragment_Visibility, 1.131 + kVec2f_GrSLType, 1.132 + "DstCopyCoordScale", 1.133 + &dstCopyCoordScaleName); 1.134 + const char* fragPos = this->fragmentPosition(); 1.135 + this->fsCodeAppend("\t// Read color from copy of the destination.\n"); 1.136 + this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", 1.137 + fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); 1.138 + if (!topDown) { 1.139 + this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); 1.140 + } 1.141 + this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); 1.142 + append_texture_lookup(&fFSCode, 1.143 + fGpu, 1.144 + this->getUniformCStr(fDstCopySamplerUniform), 1.145 + "_dstTexCoord", 1.146 + configMask, 1.147 + "rgba"); 1.148 + this->fsCodeAppend(";\n\n"); 1.149 + } 1.150 + 1.151 + if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { 1.152 + const char* name; 1.153 + fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1.154 + kVec4f_GrSLType, "Color", &name); 1.155 + fInputColor = GrGLSLExpr4(name); 1.156 + } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) { 1.157 + fInputColor = GrGLSLExpr4(1); 1.158 + } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) { 1.159 + fInputColor = GrGLSLExpr4(0); 1.160 + } 1.161 + 1.162 + if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { 1.163 + const char* name; 1.164 + fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1.165 + kVec4f_GrSLType, "Coverage", &name); 1.166 + fInputCoverage = GrGLSLExpr4(name); 1.167 + } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { 1.168 + fInputCoverage = GrGLSLExpr4(1); 1.169 + } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) { 1.170 + fInputCoverage = GrGLSLExpr4(0); 1.171 + } 1.172 + 1.173 + if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { 1.174 + fFSOutputs.push_back().set(kVec4f_GrSLType, 1.175 + GrGLShaderVar::kOut_TypeModifier, 1.176 + declared_color_output_name()); 1.177 + fHasCustomColorOutput = true; 1.178 + } 1.179 +} 1.180 + 1.181 +bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { 1.182 + switch (feature) { 1.183 + case kStandardDerivatives_GLSLFeature: 1.184 + if (!fGpu->glCaps().shaderDerivativeSupport()) { 1.185 + return false; 1.186 + } 1.187 + if (kGLES_GrGLStandard == fGpu->glStandard()) { 1.188 + this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, 1.189 + "GL_OES_standard_derivatives"); 1.190 + } 1.191 + return true; 1.192 + default: 1.193 + GrCrash("Unexpected GLSLFeature requested."); 1.194 + return false; 1.195 + } 1.196 +} 1.197 + 1.198 +bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { 1.199 + switch (feature) { 1.200 + case kFragCoordConventions_GLSLPrivateFeature: 1.201 + if (!fGpu->glCaps().fragCoordConventionsSupport()) { 1.202 + return false; 1.203 + } 1.204 + if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { 1.205 + this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 1.206 + "GL_ARB_fragment_coord_conventions"); 1.207 + } 1.208 + return true; 1.209 + case kEXTShaderFramebufferFetch_GLSLPrivateFeature: 1.210 + if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) { 1.211 + return false; 1.212 + } 1.213 + this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature, 1.214 + "GL_EXT_shader_framebuffer_fetch"); 1.215 + return true; 1.216 + case kNVShaderFramebufferFetch_GLSLPrivateFeature: 1.217 + if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) { 1.218 + return false; 1.219 + } 1.220 + this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature, 1.221 + "GL_NV_shader_framebuffer_fetch"); 1.222 + return true; 1.223 + default: 1.224 + GrCrash("Unexpected GLSLPrivateFeature requested."); 1.225 + return false; 1.226 + } 1.227 +} 1.228 + 1.229 +void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { 1.230 + if (!(featureBit & fFSFeaturesAddedMask)) { 1.231 + fFSExtensions.appendf("#extension %s: require\n", extensionName); 1.232 + fFSFeaturesAddedMask |= featureBit; 1.233 + } 1.234 +} 1.235 + 1.236 +void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) { 1.237 + if ('\0' == prefix) { 1.238 + *out = name; 1.239 + } else { 1.240 + out->printf("%c%s", prefix, name); 1.241 + } 1.242 + if (fCodeStage.inStageCode()) { 1.243 + if (out->endsWith('_')) { 1.244 + // Names containing "__" are reserved. 1.245 + out->append("x"); 1.246 + } 1.247 + out->appendf("_Stage%d", fCodeStage.stageIndex()); 1.248 + } 1.249 +} 1.250 + 1.251 +const char* GrGLShaderBuilder::dstColor() { 1.252 + if (fCodeStage.inStageCode()) { 1.253 + const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 1.254 + if (!effect->willReadDstColor()) { 1.255 + GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect " 1.256 + "did not request access."); 1.257 + return ""; 1.258 + } 1.259 + } 1.260 + static const char kFBFetchColorName[] = "gl_LastFragData[0]"; 1.261 + GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType(); 1.262 + if (GrGLCaps::kEXT_FBFetchType == fetchType) { 1.263 + SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature)); 1.264 + return kFBFetchColorName; 1.265 + } else if (GrGLCaps::kNV_FBFetchType == fetchType) { 1.266 + SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature)); 1.267 + return kFBFetchColorName; 1.268 + } else if (fDstCopySamplerUniform.isValid()) { 1.269 + return kDstCopyColorName; 1.270 + } else { 1.271 + return ""; 1.272 + } 1.273 +} 1.274 + 1.275 +void GrGLShaderBuilder::appendTextureLookup(SkString* out, 1.276 + const GrGLShaderBuilder::TextureSampler& sampler, 1.277 + const char* coordName, 1.278 + GrSLType varyingType) const { 1.279 + append_texture_lookup(out, 1.280 + fGpu, 1.281 + this->getUniformCStr(sampler.samplerUniform()), 1.282 + coordName, 1.283 + sampler.configComponentMask(), 1.284 + sampler.swizzle(), 1.285 + varyingType); 1.286 +} 1.287 + 1.288 +void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler, 1.289 + const char* coordName, 1.290 + GrSLType varyingType) { 1.291 + this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); 1.292 +} 1.293 + 1.294 +void GrGLShaderBuilder::fsAppendTextureLookupAndModulate( 1.295 + const char* modulation, 1.296 + const GrGLShaderBuilder::TextureSampler& sampler, 1.297 + const char* coordName, 1.298 + GrSLType varyingType) { 1.299 + SkString lookup; 1.300 + this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 1.301 + fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); 1.302 +} 1.303 + 1.304 +GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, 1.305 + const GrGLCaps& caps) { 1.306 + uint32_t key = kYesDstRead_DstReadKeyBit; 1.307 + if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) { 1.308 + return key; 1.309 + } 1.310 + SkASSERT(NULL != dstCopy); 1.311 + if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 1.312 + // The fact that the config is alpha-only must be considered when generating code. 1.313 + key |= kUseAlphaConfig_DstReadKeyBit; 1.314 + } 1.315 + if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 1.316 + key |= kTopLeftOrigin_DstReadKeyBit; 1.317 + } 1.318 + SkASSERT(static_cast<DstReadKey>(key) == key); 1.319 + return static_cast<DstReadKey>(key); 1.320 +} 1.321 + 1.322 +GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, 1.323 + const GrGLCaps&) { 1.324 + if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 1.325 + return kTopLeftFragPosRead_FragPosKey; 1.326 + } else { 1.327 + return kBottomLeftFragPosRead_FragPosKey; 1.328 + } 1.329 +} 1.330 + 1.331 + 1.332 +const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 1.333 + if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 1.334 + if (caps.textureRedSupport()) { 1.335 + static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 1.336 + return gRedSmear; 1.337 + } else { 1.338 + static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 1.339 + GR_GL_ALPHA, GR_GL_ALPHA }; 1.340 + return gAlphaSmear; 1.341 + } 1.342 + } else { 1.343 + static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 1.344 + return gStraight; 1.345 + } 1.346 +} 1.347 + 1.348 +GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 1.349 + GrSLType type, 1.350 + const char* name, 1.351 + int count, 1.352 + const char** outName) { 1.353 + SkASSERT(name && strlen(name)); 1.354 + SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility); 1.355 + SkASSERT(0 == (~kVisibilityMask & visibility)); 1.356 + SkASSERT(0 != visibility); 1.357 + 1.358 + BuilderUniform& uni = fUniforms.push_back(); 1.359 + UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1); 1.360 + SkDEBUGCODE(UniformHandle h2 =) 1.361 + fUniformManager.appendUniform(type, count); 1.362 + // We expect the uniform manager to initially have no uniforms and that all uniforms are added 1.363 + // by this function. Therefore, the handles should match. 1.364 + SkASSERT(h2 == h); 1.365 + uni.fVariable.setType(type); 1.366 + uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 1.367 + this->nameVariable(uni.fVariable.accessName(), 'u', name); 1.368 + uni.fVariable.setArrayCount(count); 1.369 + uni.fVisibility = visibility; 1.370 + 1.371 + // If it is visible in both the VS and FS, the precision must match. 1.372 + // We declare a default FS precision, but not a default VS. So set the var 1.373 + // to use the default FS precision. 1.374 + if ((kVertex_Visibility | kFragment_Visibility) == visibility) { 1.375 + // the fragment and vertex precisions must match 1.376 + uni.fVariable.setPrecision(kDefaultFragmentPrecision); 1.377 + } 1.378 + 1.379 + if (NULL != outName) { 1.380 + *outName = uni.fVariable.c_str(); 1.381 + } 1.382 + 1.383 + return h; 1.384 +} 1.385 + 1.386 +SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) { 1.387 + if (kVec3f_GrSLType != coords[index].type()) { 1.388 + SkASSERT(kVec2f_GrSLType == coords[index].type()); 1.389 + return coords[index].getName(); 1.390 + } 1.391 + 1.392 + SkString coords2D("coords2D"); 1.393 + if (0 != index) { 1.394 + coords2D.appendf("_%i", index); 1.395 + } 1.396 + this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", 1.397 + coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 1.398 + return coords2D; 1.399 +} 1.400 + 1.401 +const char* GrGLShaderBuilder::fragmentPosition() { 1.402 + if (fCodeStage.inStageCode()) { 1.403 + const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); 1.404 + if (!effect->willReadFragmentPosition()) { 1.405 + GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect " 1.406 + "did not request access."); 1.407 + return ""; 1.408 + } 1.409 + } 1.410 + // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 1.411 + // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 1.412 + // declaration varies in earlier GLSL specs. So it is simpler to omit it. 1.413 + if (fTopLeftFragPosRead) { 1.414 + fSetupFragPosition = true; 1.415 + return "gl_FragCoord"; 1.416 + } else if (fGpu->glCaps().fragCoordConventionsSupport()) { 1.417 + if (!fSetupFragPosition) { 1.418 + SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); 1.419 + fFSInputs.push_back().set(kVec4f_GrSLType, 1.420 + GrGLShaderVar::kIn_TypeModifier, 1.421 + "gl_FragCoord", 1.422 + GrGLShaderVar::kDefault_Precision, 1.423 + GrGLShaderVar::kUpperLeft_Origin); 1.424 + fSetupFragPosition = true; 1.425 + } 1.426 + return "gl_FragCoord"; 1.427 + } else { 1.428 + static const char* kCoordName = "fragCoordYDown"; 1.429 + if (!fSetupFragPosition) { 1.430 + // temporarily change the stage index because we're inserting non-stage code. 1.431 + CodeStage::AutoStageRestore csar(&fCodeStage, NULL); 1.432 + 1.433 + SkASSERT(!fRTHeightUniform.isValid()); 1.434 + const char* rtHeightName; 1.435 + 1.436 + fRTHeightUniform = this->addUniform(kFragment_Visibility, 1.437 + kFloat_GrSLType, 1.438 + "RTHeight", 1.439 + &rtHeightName); 1.440 + 1.441 + this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", 1.442 + kCoordName, rtHeightName); 1.443 + fSetupFragPosition = true; 1.444 + } 1.445 + SkASSERT(fRTHeightUniform.isValid()); 1.446 + return kCoordName; 1.447 + } 1.448 +} 1.449 + 1.450 +void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType, 1.451 + const char* name, 1.452 + int argCnt, 1.453 + const GrGLShaderVar* args, 1.454 + const char* body, 1.455 + SkString* outName) { 1.456 + fFSFunctions.append(GrGLSLTypeString(returnType)); 1.457 + this->nameVariable(outName, '\0', name); 1.458 + fFSFunctions.appendf(" %s", outName->c_str()); 1.459 + fFSFunctions.append("("); 1.460 + for (int i = 0; i < argCnt; ++i) { 1.461 + args[i].appendDecl(this->ctxInfo(), &fFSFunctions); 1.462 + if (i < argCnt - 1) { 1.463 + fFSFunctions.append(", "); 1.464 + } 1.465 + } 1.466 + fFSFunctions.append(") {\n"); 1.467 + fFSFunctions.append(body); 1.468 + fFSFunctions.append("}\n\n"); 1.469 +} 1.470 + 1.471 +namespace { 1.472 + 1.473 +inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 1.474 + GrGLStandard standard, 1.475 + SkString* str) { 1.476 + // Desktop GLSL has added precision qualifiers but they don't do anything. 1.477 + if (kGLES_GrGLStandard == standard) { 1.478 + switch (p) { 1.479 + case GrGLShaderVar::kHigh_Precision: 1.480 + str->append("precision highp float;\n"); 1.481 + break; 1.482 + case GrGLShaderVar::kMedium_Precision: 1.483 + str->append("precision mediump float;\n"); 1.484 + break; 1.485 + case GrGLShaderVar::kLow_Precision: 1.486 + str->append("precision lowp float;\n"); 1.487 + break; 1.488 + case GrGLShaderVar::kDefault_Precision: 1.489 + GrCrash("Default precision now allowed."); 1.490 + default: 1.491 + GrCrash("Unknown precision value."); 1.492 + } 1.493 + } 1.494 +} 1.495 +} 1.496 + 1.497 +void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 1.498 + for (int i = 0; i < vars.count(); ++i) { 1.499 + vars[i].appendDecl(this->ctxInfo(), out); 1.500 + out->append(";\n"); 1.501 + } 1.502 +} 1.503 + 1.504 +void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility, 1.505 + SkString* out) const { 1.506 + for (int i = 0; i < fUniforms.count(); ++i) { 1.507 + if (fUniforms[i].fVisibility & visibility) { 1.508 + fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out); 1.509 + out->append(";\n"); 1.510 + } 1.511 + } 1.512 +} 1.513 + 1.514 +void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, 1.515 + const GrEffectStage* effectStages[], 1.516 + const EffectKey effectKeys[], 1.517 + int effectCnt, 1.518 + GrGLSLExpr4* fsInOutColor) { 1.519 + bool effectEmitted = false; 1.520 + 1.521 + GrGLSLExpr4 inColor = *fsInOutColor; 1.522 + GrGLSLExpr4 outColor; 1.523 + 1.524 + for (int e = 0; e < effectCnt; ++e) { 1.525 + SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); 1.526 + const GrEffectStage& stage = *effectStages[e]; 1.527 + 1.528 + CodeStage::AutoStageRestore csar(&fCodeStage, &stage); 1.529 + 1.530 + if (inColor.isZeros()) { 1.531 + SkString inColorName; 1.532 + 1.533 + // Effects have no way to communicate zeros, they treat an empty string as ones. 1.534 + this->nameVariable(&inColorName, '\0', "input"); 1.535 + this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); 1.536 + inColor = inColorName; 1.537 + } 1.538 + 1.539 + // create var to hold stage result 1.540 + SkString outColorName; 1.541 + this->nameVariable(&outColorName, '\0', "output"); 1.542 + this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); 1.543 + outColor = outColorName; 1.544 + 1.545 + 1.546 + programEffectsBuilder->emitEffect(stage, 1.547 + effectKeys[e], 1.548 + outColor.c_str(), 1.549 + inColor.isOnes() ? NULL : inColor.c_str(), 1.550 + fCodeStage.stageIndex()); 1.551 + 1.552 + inColor = outColor; 1.553 + effectEmitted = true; 1.554 + } 1.555 + 1.556 + if (effectEmitted) { 1.557 + *fsInOutColor = outColor; 1.558 + } 1.559 +} 1.560 + 1.561 +const char* GrGLShaderBuilder::getColorOutputName() const { 1.562 + return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; 1.563 +} 1.564 + 1.565 +const char* GrGLShaderBuilder::enableSecondaryOutput() { 1.566 + if (!fHasSecondaryOutput) { 1.567 + fFSOutputs.push_back().set(kVec4f_GrSLType, 1.568 + GrGLShaderVar::kOut_TypeModifier, 1.569 + dual_source_output_name()); 1.570 + fHasSecondaryOutput = true; 1.571 + } 1.572 + return dual_source_output_name(); 1.573 +} 1.574 + 1.575 +bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { 1.576 + SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); 1.577 + 1.578 + GrGLuint programId = 0; 1.579 + GL_CALL_RET(programId, CreateProgram()); 1.580 + if (!programId) { 1.581 + return false; 1.582 + } 1.583 + 1.584 + SkTDArray<GrGLuint> shadersToDelete; 1.585 + 1.586 + if (!this->compileAndAttachShaders(programId, &shadersToDelete)) { 1.587 + GL_CALL(DeleteProgram(programId)); 1.588 + return false; 1.589 + } 1.590 + 1.591 + this->bindProgramLocations(programId); 1.592 + if (fUniformManager.isUsingBindUniform()) { 1.593 + fUniformManager.getUniformLocations(programId, fUniforms); 1.594 + } 1.595 + 1.596 + GL_CALL(LinkProgram(programId)); 1.597 + 1.598 + // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. 1.599 + bool checkLinked = !fGpu->ctxInfo().isChromium(); 1.600 +#ifdef SK_DEBUG 1.601 + checkLinked = true; 1.602 +#endif 1.603 + if (checkLinked) { 1.604 + GrGLint linked = GR_GL_INIT_ZERO; 1.605 + GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); 1.606 + if (!linked) { 1.607 + GrGLint infoLen = GR_GL_INIT_ZERO; 1.608 + GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 1.609 + SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 1.610 + if (infoLen > 0) { 1.611 + // retrieve length even though we don't need it to workaround 1.612 + // bug in chrome cmd buffer param validation. 1.613 + GrGLsizei length = GR_GL_INIT_ZERO; 1.614 + GL_CALL(GetProgramInfoLog(programId, 1.615 + infoLen+1, 1.616 + &length, 1.617 + (char*)log.get())); 1.618 + GrPrintf((char*)log.get()); 1.619 + } 1.620 + SkDEBUGFAIL("Error linking program"); 1.621 + GL_CALL(DeleteProgram(programId)); 1.622 + return false; 1.623 + } 1.624 + } 1.625 + 1.626 + if (!fUniformManager.isUsingBindUniform()) { 1.627 + fUniformManager.getUniformLocations(programId, fUniforms); 1.628 + } 1.629 + 1.630 + for (int i = 0; i < shadersToDelete.count(); ++i) { 1.631 + GL_CALL(DeleteShader(shadersToDelete[i])); 1.632 + } 1.633 + 1.634 + *outProgramId = programId; 1.635 + return true; 1.636 +} 1.637 + 1.638 +// Compiles a GL shader and attaches it to a program. Returns the shader ID if 1.639 +// successful, or 0 if not. 1.640 +static GrGLuint attach_shader(const GrGLContext& glCtx, 1.641 + GrGLuint programId, 1.642 + GrGLenum type, 1.643 + const SkString& shaderSrc) { 1.644 + const GrGLInterface* gli = glCtx.interface(); 1.645 + 1.646 + GrGLuint shaderId; 1.647 + GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); 1.648 + if (0 == shaderId) { 1.649 + return 0; 1.650 + } 1.651 + 1.652 + const GrGLchar* sourceStr = shaderSrc.c_str(); 1.653 + GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); 1.654 + GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); 1.655 + GR_GL_CALL(gli, CompileShader(shaderId)); 1.656 + 1.657 + // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. 1.658 + bool checkCompiled = !glCtx.isChromium(); 1.659 +#ifdef SK_DEBUG 1.660 + checkCompiled = true; 1.661 +#endif 1.662 + if (checkCompiled) { 1.663 + GrGLint compiled = GR_GL_INIT_ZERO; 1.664 + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); 1.665 + 1.666 + if (!compiled) { 1.667 + GrGLint infoLen = GR_GL_INIT_ZERO; 1.668 + GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); 1.669 + SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 1.670 + if (infoLen > 0) { 1.671 + // retrieve length even though we don't need it to workaround bug in Chromium cmd 1.672 + // buffer param validation. 1.673 + GrGLsizei length = GR_GL_INIT_ZERO; 1.674 + GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, 1.675 + &length, (char*)log.get())); 1.676 + GrPrintf(shaderSrc.c_str()); 1.677 + GrPrintf("\n%s", log.get()); 1.678 + } 1.679 + SkDEBUGFAIL("Shader compilation failed!"); 1.680 + GR_GL_CALL(gli, DeleteShader(shaderId)); 1.681 + return 0; 1.682 + } 1.683 + } 1.684 + if (c_PrintShaders) { 1.685 + GrPrintf(shaderSrc.c_str()); 1.686 + GrPrintf("\n"); 1.687 + } 1.688 + 1.689 + // Attach the shader, but defer deletion until after we have linked the program. 1.690 + // This works around a bug in the Android emulator's GLES2 wrapper which 1.691 + // will immediately delete the shader object and free its memory even though it's 1.692 + // attached to a program, which then causes glLinkProgram to fail. 1.693 + GR_GL_CALL(gli, AttachShader(programId, shaderId)); 1.694 + 1.695 + return shaderId; 1.696 +} 1.697 + 1.698 +bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const { 1.699 + SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 1.700 + fragShaderSrc.append(fFSExtensions); 1.701 + append_default_precision_qualifier(kDefaultFragmentPrecision, 1.702 + fGpu->glStandard(), 1.703 + &fragShaderSrc); 1.704 + this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc); 1.705 + this->appendDecls(fFSInputs, &fragShaderSrc); 1.706 + // We shouldn't have declared outputs on 1.10 1.707 + SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty()); 1.708 + this->appendDecls(fFSOutputs, &fragShaderSrc); 1.709 + fragShaderSrc.append(fFSFunctions); 1.710 + fragShaderSrc.append("void main() {\n"); 1.711 + fragShaderSrc.append(fFSCode); 1.712 + fragShaderSrc.append("}\n"); 1.713 + 1.714 + GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc); 1.715 + if (!fragShaderId) { 1.716 + return false; 1.717 + } 1.718 + 1.719 + *shaderIds->append() = fragShaderId; 1.720 + 1.721 + return true; 1.722 +} 1.723 + 1.724 +void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const { 1.725 + if (fHasCustomColorOutput) { 1.726 + GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); 1.727 + } 1.728 + if (fHasSecondaryOutput) { 1.729 + GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); 1.730 + } 1.731 +} 1.732 + 1.733 +const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const { 1.734 + return fGpu->ctxInfo(); 1.735 +} 1.736 + 1.737 +//////////////////////////////////////////////////////////////////////////////// 1.738 + 1.739 +GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu, 1.740 + GrGLUniformManager& uniformManager, 1.741 + const GrGLProgramDesc& desc) 1.742 + : INHERITED(gpu, uniformManager, desc) 1.743 + , fDesc(desc) 1.744 + , fVSAttrs(kVarsPerBlock) 1.745 + , fVSOutputs(kVarsPerBlock) 1.746 + , fGSInputs(kVarsPerBlock) 1.747 + , fGSOutputs(kVarsPerBlock) { 1.748 + 1.749 + const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 1.750 + 1.751 + fPositionVar = &fVSAttrs.push_back(); 1.752 + fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); 1.753 + if (-1 != header.fLocalCoordAttributeIndex) { 1.754 + fLocalCoordsVar = &fVSAttrs.push_back(); 1.755 + fLocalCoordsVar->set(kVec2f_GrSLType, 1.756 + GrGLShaderVar::kAttribute_TypeModifier, 1.757 + "aLocalCoords"); 1.758 + } else { 1.759 + fLocalCoordsVar = fPositionVar; 1.760 + } 1.761 + 1.762 + const char* viewMName; 1.763 + fViewMatrixUniform = this->addUniform(GrGLShaderBuilder::kVertex_Visibility, 1.764 + kMat33f_GrSLType, "ViewM", &viewMName); 1.765 + 1.766 + this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" 1.767 + "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 1.768 + viewMName, fPositionVar->c_str()); 1.769 + 1.770 + // we output point size in the GS if present 1.771 + if (header.fEmitsPointSize 1.772 +#if GR_GL_EXPERIMENTAL_GS 1.773 + && !header.fExperimentalGS 1.774 +#endif 1.775 + ) { 1.776 + this->vsCodeAppend("\tgl_PointSize = 1.0;\n"); 1.777 + } 1.778 + 1.779 + if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) { 1.780 + this->addAttribute(kVec4f_GrSLType, color_attribute_name()); 1.781 + const char *vsName, *fsName; 1.782 + this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 1.783 + this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name()); 1.784 + this->setInputColor(fsName); 1.785 + } 1.786 + 1.787 + if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) { 1.788 + this->addAttribute(kVec4f_GrSLType, coverage_attribute_name()); 1.789 + const char *vsName, *fsName; 1.790 + this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 1.791 + this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name()); 1.792 + this->setInputCoverage(fsName); 1.793 + } 1.794 +} 1.795 + 1.796 +bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) { 1.797 + for (int i = 0; i < fVSAttrs.count(); ++i) { 1.798 + const GrGLShaderVar& attr = fVSAttrs[i]; 1.799 + // if attribute already added, don't add it again 1.800 + if (attr.getName().equals(name)) { 1.801 + SkASSERT(attr.getType() == type); 1.802 + return false; 1.803 + } 1.804 + } 1.805 + fVSAttrs.push_back().set(type, 1.806 + GrGLShaderVar::kAttribute_TypeModifier, 1.807 + name); 1.808 + return true; 1.809 +} 1.810 + 1.811 +bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex, 1.812 + GrSLType type, 1.813 + const SkString& name) { 1.814 + if (!this->addAttribute(type, name.c_str())) { 1.815 + return false; 1.816 + } 1.817 + 1.818 + fEffectAttributes.push_back().set(attributeIndex, name); 1.819 + return true; 1.820 +} 1.821 + 1.822 +void GrGLFullShaderBuilder::addVarying(GrSLType type, 1.823 + const char* name, 1.824 + const char** vsOutName, 1.825 + const char** fsInName) { 1.826 + fVSOutputs.push_back(); 1.827 + fVSOutputs.back().setType(type); 1.828 + fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 1.829 + this->nameVariable(fVSOutputs.back().accessName(), 'v', name); 1.830 + 1.831 + if (vsOutName) { 1.832 + *vsOutName = fVSOutputs.back().getName().c_str(); 1.833 + } 1.834 + // input to FS comes either from VS or GS 1.835 + const SkString* fsName; 1.836 +#if GR_GL_EXPERIMENTAL_GS 1.837 + if (fDesc.getHeader().fExperimentalGS) { 1.838 + // if we have a GS take each varying in as an array 1.839 + // and output as non-array. 1.840 + fGSInputs.push_back(); 1.841 + fGSInputs.back().setType(type); 1.842 + fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier); 1.843 + fGSInputs.back().setUnsizedArray(); 1.844 + *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 1.845 + fGSOutputs.push_back(); 1.846 + fGSOutputs.back().setType(type); 1.847 + fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier); 1.848 + this->nameVariable(fGSOutputs.back().accessName(), 'g', name); 1.849 + fsName = fGSOutputs.back().accessName(); 1.850 + } else 1.851 +#endif 1.852 + { 1.853 + fsName = fVSOutputs.back().accessName(); 1.854 + } 1.855 + this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName); 1.856 + if (fsInName) { 1.857 + *fsInName = fsName->c_str(); 1.858 + } 1.859 +} 1.860 + 1.861 +const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const { 1.862 + const AttributePair* attribEnd = fEffectAttributes.end(); 1.863 + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 1.864 + if (attrib->fIndex == attributeIndex) { 1.865 + return &attrib->fName; 1.866 + } 1.867 + } 1.868 + 1.869 + return NULL; 1.870 +} 1.871 + 1.872 +GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects( 1.873 + const GrEffectStage* effectStages[], 1.874 + const EffectKey effectKeys[], 1.875 + int effectCnt, 1.876 + GrGLSLExpr4* inOutFSColor) { 1.877 + 1.878 + GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt); 1.879 + this->INHERITED::createAndEmitEffects(&programEffectsBuilder, 1.880 + effectStages, 1.881 + effectKeys, 1.882 + effectCnt, 1.883 + inOutFSColor); 1.884 + return programEffectsBuilder.finish(); 1.885 +} 1.886 + 1.887 +bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const { 1.888 + const GrGLContext& glCtx = this->gpu()->glContext(); 1.889 + SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 1.890 + this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc); 1.891 + this->appendDecls(fVSAttrs, &vertShaderSrc); 1.892 + this->appendDecls(fVSOutputs, &vertShaderSrc); 1.893 + vertShaderSrc.append("void main() {\n"); 1.894 + vertShaderSrc.append(fVSCode); 1.895 + vertShaderSrc.append("}\n"); 1.896 + GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc); 1.897 + if (!vertShaderId) { 1.898 + return false; 1.899 + } 1.900 + *shaderIds->append() = vertShaderId; 1.901 + 1.902 +#if GR_GL_EXPERIMENTAL_GS 1.903 + if (fDesc.getHeader().fExperimentalGS) { 1.904 + SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration); 1.905 + SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo())); 1.906 + geomShaderSrc.append("layout(triangles) in;\n" 1.907 + "layout(triangle_strip, max_vertices = 6) out;\n"); 1.908 + this->appendDecls(fGSInputs, &geomShaderSrc); 1.909 + this->appendDecls(fGSOutputs, &geomShaderSrc); 1.910 + geomShaderSrc.append("void main() {\n"); 1.911 + geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n" 1.912 + "\t\tgl_Position = gl_in[i].gl_Position;\n"); 1.913 + if (fDesc.getHeader().fEmitsPointSize) { 1.914 + geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n"); 1.915 + } 1.916 + SkASSERT(fGSInputs.count() == fGSOutputs.count()); 1.917 + for (int i = 0; i < fGSInputs.count(); ++i) { 1.918 + geomShaderSrc.appendf("\t\t%s = %s[i];\n", 1.919 + fGSOutputs[i].getName().c_str(), 1.920 + fGSInputs[i].getName().c_str()); 1.921 + } 1.922 + geomShaderSrc.append("\t\tEmitVertex();\n" 1.923 + "\t}\n" 1.924 + "\tEndPrimitive();\n"); 1.925 + geomShaderSrc.append("}\n"); 1.926 + GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc); 1.927 + if (!geomShaderId) { 1.928 + return false; 1.929 + } 1.930 + *shaderIds->append() = geomShaderId; 1.931 + } 1.932 +#endif 1.933 + 1.934 + return this->INHERITED::compileAndAttachShaders(programId, shaderIds); 1.935 +} 1.936 + 1.937 +void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const { 1.938 + this->INHERITED::bindProgramLocations(programId); 1.939 + 1.940 + const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader(); 1.941 + 1.942 + // Bind the attrib locations to same values for all shaders 1.943 + SkASSERT(-1 != header.fPositionAttributeIndex); 1.944 + GL_CALL(BindAttribLocation(programId, 1.945 + header.fPositionAttributeIndex, 1.946 + fPositionVar->c_str())); 1.947 + if (-1 != header.fLocalCoordAttributeIndex) { 1.948 + GL_CALL(BindAttribLocation(programId, 1.949 + header.fLocalCoordAttributeIndex, 1.950 + fLocalCoordsVar->c_str())); 1.951 + } 1.952 + if (-1 != header.fColorAttributeIndex) { 1.953 + GL_CALL(BindAttribLocation(programId, 1.954 + header.fColorAttributeIndex, 1.955 + color_attribute_name())); 1.956 + } 1.957 + if (-1 != header.fCoverageAttributeIndex) { 1.958 + GL_CALL(BindAttribLocation(programId, 1.959 + header.fCoverageAttributeIndex, 1.960 + coverage_attribute_name())); 1.961 + } 1.962 + 1.963 + const AttributePair* attribEnd = fEffectAttributes.end(); 1.964 + for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) { 1.965 + GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str())); 1.966 + } 1.967 +} 1.968 + 1.969 +//////////////////////////////////////////////////////////////////////////////// 1.970 + 1.971 +GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu, 1.972 + GrGLUniformManager& uniformManager, 1.973 + const GrGLProgramDesc& desc) 1.974 + : INHERITED(gpu, uniformManager, desc) 1.975 + , fNumTexCoordSets(0) { 1.976 + 1.977 + SkASSERT(!desc.getHeader().fHasVertexCode); 1.978 + SkASSERT(gpu->glCaps().fixedFunctionSupport()); 1.979 + SkASSERT(gpu->glCaps().pathRenderingSupport()); 1.980 + SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput); 1.981 + SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput); 1.982 +} 1.983 + 1.984 +int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) { 1.985 + int firstFreeCoordSet = fNumTexCoordSets; 1.986 + fNumTexCoordSets += count; 1.987 + SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fNumTexCoordSets); 1.988 + return firstFreeCoordSet; 1.989 +} 1.990 + 1.991 +GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects( 1.992 + const GrEffectStage* effectStages[], 1.993 + const EffectKey effectKeys[], 1.994 + int effectCnt, 1.995 + GrGLSLExpr4* inOutFSColor) { 1.996 + 1.997 + GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt); 1.998 + this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder, 1.999 + effectStages, 1.1000 + effectKeys, 1.1001 + effectCnt, 1.1002 + inOutFSColor); 1.1003 + return texGenEffectsBuilder.finish(); 1.1004 +}