2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "gl/GrGLShaderBuilder.h"
9 #include "gl/GrGLProgram.h"
10 #include "gl/GrGLUniformHandle.h"
11 #include "GrCoordTransform.h"
12 #include "GrDrawEffect.h"
14 #include "GrTexture.h"
16 #include "SkTraceEvent.h"
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)
21 // number of each input/output type in a single allocation block
22 static const int kVarsPerBlock = 8;
24 // except FS outputs where we expect 2 at most.
25 static const int kMaxFSOutputs = 2;
27 // ES2 FS only guarantees mediump and lowp support
28 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
30 typedef GrGLUniformManager::UniformHandle UniformHandle;
32 SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false,
33 "Print the source code for all shaders generated.");
35 ///////////////////////////////////////////////////////////////////////////////
39 inline const char* color_attribute_name() { return "aColor"; }
40 inline const char* coverage_attribute_name() { return "aCoverage"; }
41 inline const char* declared_color_output_name() { return "fsColorOut"; }
42 inline const char* dual_source_output_name() { return "dualSourceOut"; }
43 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
44 if (kVec2f_GrSLType == type) {
45 return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
47 SkASSERT(kVec3f_GrSLType == type);
48 return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
52 void append_texture_lookup(SkString* out,
54 const char* samplerName,
55 const char* coordName,
56 uint32_t configComponentMask,
58 GrSLType varyingType = kVec2f_GrSLType) {
59 SkASSERT(NULL != coordName);
61 out->appendf("%s(%s, %s)",
62 sample_function_name(varyingType, gpu->glslGeneration()),
66 char mangledSwizzle[5];
68 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
70 if (!gpu->glCaps().textureSwizzleSupport() &&
71 (kA_GrColorComponentFlag == configComponentMask)) {
72 char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a';
74 for (i = 0; '\0' != swizzle[i]; ++i) {
75 mangledSwizzle[i] = alphaChar;
77 mangledSwizzle[i] ='\0';
78 swizzle = mangledSwizzle;
80 // For shader prettiness we omit the swizzle rather than appending ".rgba".
81 if (memcmp(swizzle, "rgba", 4)) {
82 out->appendf(".%s", swizzle);
88 static const char kDstCopyColorName[] = "_dstColor";
90 ///////////////////////////////////////////////////////////////////////////////
92 GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
93 GrGLUniformManager& uniformManager,
94 const GrGLProgramDesc& desc)
96 , fUniformManager(uniformManager)
97 , fFSFeaturesAddedMask(0)
98 , fFSInputs(kVarsPerBlock)
99 , fFSOutputs(kMaxFSOutputs)
100 , fUniforms(kVarsPerBlock)
101 , fSetupFragPosition(false)
102 , fHasCustomColorOutput(false)
103 , fHasSecondaryOutput(false)
104 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
106 const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
108 // Emit code to read the dst copy textue if necessary.
109 if (kNoDstRead_DstReadKey != header.fDstReadKey &&
110 GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) {
111 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
112 const char* dstCopyTopLeftName;
113 const char* dstCopyCoordScaleName;
115 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
116 configMask = kA_GrColorComponentFlag;
118 configMask = kRGBA_GrColorComponentFlags;
120 fDstCopySamplerUniform = this->addUniform(kFragment_Visibility,
123 fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility,
126 &dstCopyTopLeftName);
127 fDstCopyScaleUniform = this->addUniform(kFragment_Visibility,
130 &dstCopyCoordScaleName);
131 const char* fragPos = this->fragmentPosition();
132 this->fsCodeAppend("\t// Read color from copy of the destination.\n");
133 this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
134 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
136 this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
138 this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
139 append_texture_lookup(&fFSCode,
141 this->getUniformCStr(fDstCopySamplerUniform),
145 this->fsCodeAppend(";\n\n");
148 if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
150 fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
151 kVec4f_GrSLType, "Color", &name);
152 fInputColor = GrGLSLExpr4(name);
153 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
154 fInputColor = GrGLSLExpr4(1);
155 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
156 fInputColor = GrGLSLExpr4(0);
159 if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
161 fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
162 kVec4f_GrSLType, "Coverage", &name);
163 fInputCoverage = GrGLSLExpr4(name);
164 } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
165 fInputCoverage = GrGLSLExpr4(1);
166 } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
167 fInputCoverage = GrGLSLExpr4(0);
170 if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
171 fFSOutputs.push_back().set(kVec4f_GrSLType,
172 GrGLShaderVar::kOut_TypeModifier,
173 declared_color_output_name());
174 fHasCustomColorOutput = true;
178 bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
180 case kStandardDerivatives_GLSLFeature:
181 if (!fGpu->glCaps().shaderDerivativeSupport()) {
184 if (kGLES_GrGLStandard == fGpu->glStandard()) {
185 this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
186 "GL_OES_standard_derivatives");
190 SkFAIL("Unexpected GLSLFeature requested.");
195 bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
197 case kFragCoordConventions_GLSLPrivateFeature:
198 if (!fGpu->glCaps().fragCoordConventionsSupport()) {
201 if (fGpu->glslGeneration() < k150_GrGLSLGeneration) {
202 this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
203 "GL_ARB_fragment_coord_conventions");
206 case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
207 if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) {
210 this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
211 "GL_EXT_shader_framebuffer_fetch");
213 case kNVShaderFramebufferFetch_GLSLPrivateFeature:
214 if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) {
217 this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
218 "GL_NV_shader_framebuffer_fetch");
221 SkFAIL("Unexpected GLSLPrivateFeature requested.");
226 void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
227 if (!(featureBit & fFSFeaturesAddedMask)) {
228 fFSExtensions.appendf("#extension %s: require\n", extensionName);
229 fFSFeaturesAddedMask |= featureBit;
233 void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
234 if ('\0' == prefix) {
237 out->printf("%c%s", prefix, name);
239 if (fCodeStage.inStageCode()) {
240 if (out->endsWith('_')) {
241 // Names containing "__" are reserved.
244 out->appendf("_Stage%d", fCodeStage.stageIndex());
248 const char* GrGLShaderBuilder::dstColor() {
249 if (fCodeStage.inStageCode()) {
250 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
251 if (!effect->willReadDstColor()) {
252 SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect "
253 "did not request access.");
257 static const char kFBFetchColorName[] = "gl_LastFragData[0]";
258 GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType();
259 if (GrGLCaps::kEXT_FBFetchType == fetchType) {
260 SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
261 return kFBFetchColorName;
262 } else if (GrGLCaps::kNV_FBFetchType == fetchType) {
263 SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
264 return kFBFetchColorName;
265 } else if (fDstCopySamplerUniform.isValid()) {
266 return kDstCopyColorName;
272 void GrGLShaderBuilder::appendTextureLookup(SkString* out,
273 const GrGLShaderBuilder::TextureSampler& sampler,
274 const char* coordName,
275 GrSLType varyingType) const {
276 append_texture_lookup(out,
278 this->getUniformCStr(sampler.samplerUniform()),
280 sampler.configComponentMask(),
285 void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler,
286 const char* coordName,
287 GrSLType varyingType) {
288 this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
291 void GrGLShaderBuilder::fsAppendTextureLookupAndModulate(
292 const char* modulation,
293 const GrGLShaderBuilder::TextureSampler& sampler,
294 const char* coordName,
295 GrSLType varyingType) {
297 this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
298 fFSCode.append((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
301 GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
302 const GrGLCaps& caps) {
303 uint32_t key = kYesDstRead_DstReadKeyBit;
304 if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) {
307 SkASSERT(NULL != dstCopy);
308 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
309 // The fact that the config is alpha-only must be considered when generating code.
310 key |= kUseAlphaConfig_DstReadKeyBit;
312 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
313 key |= kTopLeftOrigin_DstReadKeyBit;
315 SkASSERT(static_cast<DstReadKey>(key) == key);
316 return static_cast<DstReadKey>(key);
319 GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
321 if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
322 return kTopLeftFragPosRead_FragPosKey;
324 return kBottomLeftFragPosRead_FragPosKey;
329 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
330 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
331 if (caps.textureRedSupport()) {
332 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
335 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
336 GR_GL_ALPHA, GR_GL_ALPHA };
340 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
345 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
349 const char** outName) {
350 SkASSERT(name && strlen(name));
351 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
352 SkASSERT(0 == (~kVisibilityMask & visibility));
353 SkASSERT(0 != visibility);
355 BuilderUniform& uni = fUniforms.push_back();
356 UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
357 SkDEBUGCODE(UniformHandle h2 =)
358 fUniformManager.appendUniform(type, count);
359 // We expect the uniform manager to initially have no uniforms and that all uniforms are added
360 // by this function. Therefore, the handles should match.
362 uni.fVariable.setType(type);
363 uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
364 this->nameVariable(uni.fVariable.accessName(), 'u', name);
365 uni.fVariable.setArrayCount(count);
366 uni.fVisibility = visibility;
368 // If it is visible in both the VS and FS, the precision must match.
369 // We declare a default FS precision, but not a default VS. So set the var
370 // to use the default FS precision.
371 if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
372 // the fragment and vertex precisions must match
373 uni.fVariable.setPrecision(kDefaultFragmentPrecision);
376 if (NULL != outName) {
377 *outName = uni.fVariable.c_str();
383 SkString GrGLShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) {
384 if (kVec3f_GrSLType != coords[index].type()) {
385 SkASSERT(kVec2f_GrSLType == coords[index].type());
386 return coords[index].getName();
389 SkString coords2D("coords2D");
391 coords2D.appendf("_%i", index);
393 this->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;",
394 coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
398 const char* GrGLShaderBuilder::fragmentPosition() {
399 if (fCodeStage.inStageCode()) {
400 const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
401 if (!effect->willReadFragmentPosition()) {
402 SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect "
403 "did not request access.");
407 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
408 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
409 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
410 if (fTopLeftFragPosRead) {
411 fSetupFragPosition = true;
412 return "gl_FragCoord";
413 } else if (fGpu->glCaps().fragCoordConventionsSupport()) {
414 if (!fSetupFragPosition) {
415 SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
416 fFSInputs.push_back().set(kVec4f_GrSLType,
417 GrGLShaderVar::kIn_TypeModifier,
419 GrGLShaderVar::kDefault_Precision,
420 GrGLShaderVar::kUpperLeft_Origin);
421 fSetupFragPosition = true;
423 return "gl_FragCoord";
425 static const char* kCoordName = "fragCoordYDown";
426 if (!fSetupFragPosition) {
427 // temporarily change the stage index because we're inserting non-stage code.
428 CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
430 SkASSERT(!fRTHeightUniform.isValid());
431 const char* rtHeightName;
433 fRTHeightUniform = this->addUniform(kFragment_Visibility,
438 this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
439 kCoordName, rtHeightName);
440 fSetupFragPosition = true;
442 SkASSERT(fRTHeightUniform.isValid());
447 void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
450 const GrGLShaderVar* args,
453 fFSFunctions.append(GrGLSLTypeString(returnType));
454 this->nameVariable(outName, '\0', name);
455 fFSFunctions.appendf(" %s", outName->c_str());
456 fFSFunctions.append("(");
457 for (int i = 0; i < argCnt; ++i) {
458 args[i].appendDecl(this->ctxInfo(), &fFSFunctions);
459 if (i < argCnt - 1) {
460 fFSFunctions.append(", ");
463 fFSFunctions.append(") {\n");
464 fFSFunctions.append(body);
465 fFSFunctions.append("}\n\n");
470 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
471 GrGLStandard standard,
473 // Desktop GLSL has added precision qualifiers but they don't do anything.
474 if (kGLES_GrGLStandard == standard) {
476 case GrGLShaderVar::kHigh_Precision:
477 str->append("precision highp float;\n");
479 case GrGLShaderVar::kMedium_Precision:
480 str->append("precision mediump float;\n");
482 case GrGLShaderVar::kLow_Precision:
483 str->append("precision lowp float;\n");
485 case GrGLShaderVar::kDefault_Precision:
486 SkFAIL("Default precision now allowed.");
488 SkFAIL("Unknown precision value.");
494 void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
495 for (int i = 0; i < vars.count(); ++i) {
496 vars[i].appendDecl(this->ctxInfo(), out);
501 void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
502 SkString* out) const {
503 for (int i = 0; i < fUniforms.count(); ++i) {
504 if (fUniforms[i].fVisibility & visibility) {
505 fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
511 void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
512 const GrEffectStage* effectStages[],
513 const EffectKey effectKeys[],
515 GrGLSLExpr4* fsInOutColor) {
516 bool effectEmitted = false;
518 GrGLSLExpr4 inColor = *fsInOutColor;
519 GrGLSLExpr4 outColor;
521 for (int e = 0; e < effectCnt; ++e) {
522 SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
523 const GrEffectStage& stage = *effectStages[e];
525 CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
527 if (inColor.isZeros()) {
528 SkString inColorName;
530 // Effects have no way to communicate zeros, they treat an empty string as ones.
531 this->nameVariable(&inColorName, '\0', "input");
532 this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
533 inColor = inColorName;
536 // create var to hold stage result
537 SkString outColorName;
538 this->nameVariable(&outColorName, '\0', "output");
539 this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str());
540 outColor = outColorName;
543 programEffectsBuilder->emitEffect(stage,
546 inColor.isOnes() ? NULL : inColor.c_str(),
547 fCodeStage.stageIndex());
550 effectEmitted = true;
554 *fsInOutColor = outColor;
558 const char* GrGLShaderBuilder::getColorOutputName() const {
559 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
562 const char* GrGLShaderBuilder::enableSecondaryOutput() {
563 if (!fHasSecondaryOutput) {
564 fFSOutputs.push_back().set(kVec4f_GrSLType,
565 GrGLShaderVar::kOut_TypeModifier,
566 dual_source_output_name());
567 fHasSecondaryOutput = true;
569 return dual_source_output_name();
572 bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) {
573 GrGLuint programId = 0;
574 GL_CALL_RET(programId, CreateProgram());
579 SkTDArray<GrGLuint> shadersToDelete;
581 if (!this->compileAndAttachShaders(programId, &shadersToDelete)) {
582 GL_CALL(DeleteProgram(programId));
586 this->bindProgramLocations(programId);
587 if (fUniformManager.isUsingBindUniform()) {
588 fUniformManager.getUniformLocations(programId, fUniforms);
591 GL_CALL(LinkProgram(programId));
593 // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
594 bool checkLinked = !fGpu->ctxInfo().isChromium();
599 GrGLint linked = GR_GL_INIT_ZERO;
600 GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked));
602 GrGLint infoLen = GR_GL_INIT_ZERO;
603 GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen));
604 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
606 // retrieve length even though we don't need it to workaround
607 // bug in chrome cmd buffer param validation.
608 GrGLsizei length = GR_GL_INIT_ZERO;
609 GL_CALL(GetProgramInfoLog(programId,
613 GrPrintf((char*)log.get());
615 SkDEBUGFAIL("Error linking program");
616 GL_CALL(DeleteProgram(programId));
621 if (!fUniformManager.isUsingBindUniform()) {
622 fUniformManager.getUniformLocations(programId, fUniforms);
625 for (int i = 0; i < shadersToDelete.count(); ++i) {
626 GL_CALL(DeleteShader(shadersToDelete[i]));
629 *outProgramId = programId;
633 // Compiles a GL shader and attaches it to a program. Returns the shader ID if
634 // successful, or 0 if not.
635 static GrGLuint attach_shader(const GrGLContext& glCtx,
638 const SkString& shaderSrc) {
639 const GrGLInterface* gli = glCtx.interface();
642 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
647 const GrGLchar* sourceStr = shaderSrc.c_str();
648 GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size());
649 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength));
650 GR_GL_CALL(gli, CompileShader(shaderId));
652 // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
653 bool checkCompiled = !glCtx.isChromium();
655 checkCompiled = true;
658 GrGLint compiled = GR_GL_INIT_ZERO;
659 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
662 GrGLint infoLen = GR_GL_INIT_ZERO;
663 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
664 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
666 // retrieve length even though we don't need it to workaround bug in Chromium cmd
667 // buffer param validation.
668 GrGLsizei length = GR_GL_INIT_ZERO;
669 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1,
670 &length, (char*)log.get()));
671 GrPrintf(shaderSrc.c_str());
672 GrPrintf("\n%s", log.get());
674 SkDEBUGFAIL("Shader compilation failed!");
675 GR_GL_CALL(gli, DeleteShader(shaderId));
679 if (c_PrintShaders) {
680 GrPrintf(shaderSrc.c_str());
684 // Attach the shader, but defer deletion until after we have linked the program.
685 // This works around a bug in the Android emulator's GLES2 wrapper which
686 // will immediately delete the shader object and free its memory even though it's
687 // attached to a program, which then causes glLinkProgram to fail.
688 GR_GL_CALL(gli, AttachShader(programId, shaderId));
693 bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
694 SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
695 fragShaderSrc.append(fFSExtensions);
696 append_default_precision_qualifier(kDefaultFragmentPrecision,
699 this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc);
700 this->appendDecls(fFSInputs, &fragShaderSrc);
701 // We shouldn't have declared outputs on 1.10
702 SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty());
703 this->appendDecls(fFSOutputs, &fragShaderSrc);
704 fragShaderSrc.append(fFSFunctions);
705 fragShaderSrc.append("void main() {\n");
706 fragShaderSrc.append(fFSCode);
707 fragShaderSrc.append("}\n");
709 GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc);
714 *shaderIds->append() = fragShaderId;
719 void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const {
720 if (fHasCustomColorOutput) {
721 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
723 if (fHasSecondaryOutput) {
724 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
728 const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const {
729 return fGpu->ctxInfo();
732 ////////////////////////////////////////////////////////////////////////////////
734 GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
735 GrGLUniformManager& uniformManager,
736 const GrGLProgramDesc& desc)
737 : INHERITED(gpu, uniformManager, desc)
739 , fVSAttrs(kVarsPerBlock)
740 , fVSOutputs(kVarsPerBlock)
741 , fGSInputs(kVarsPerBlock)
742 , fGSOutputs(kVarsPerBlock) {
744 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
746 fPositionVar = &fVSAttrs.push_back();
747 fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
748 if (-1 != header.fLocalCoordAttributeIndex) {
749 fLocalCoordsVar = &fVSAttrs.push_back();
750 fLocalCoordsVar->set(kVec2f_GrSLType,
751 GrGLShaderVar::kAttribute_TypeModifier,
754 fLocalCoordsVar = fPositionVar;
757 const char* viewMName;
758 fViewMatrixUniform = this->addUniform(GrGLShaderBuilder::kVertex_Visibility,
759 kMat33f_GrSLType, "ViewM", &viewMName);
761 this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
762 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
763 viewMName, fPositionVar->c_str());
765 // we output point size in the GS if present
766 if (header.fEmitsPointSize
767 #if GR_GL_EXPERIMENTAL_GS
768 && !header.fExperimentalGS
771 this->vsCodeAppend("\tgl_PointSize = 1.0;\n");
774 if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
775 this->addAttribute(kVec4f_GrSLType, color_attribute_name());
776 const char *vsName, *fsName;
777 this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
778 this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
779 this->setInputColor(fsName);
782 if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
783 this->addAttribute(kVec4f_GrSLType, coverage_attribute_name());
784 const char *vsName, *fsName;
785 this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
786 this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
787 this->setInputCoverage(fsName);
791 bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) {
792 for (int i = 0; i < fVSAttrs.count(); ++i) {
793 const GrGLShaderVar& attr = fVSAttrs[i];
794 // if attribute already added, don't add it again
795 if (attr.getName().equals(name)) {
796 SkASSERT(attr.getType() == type);
800 fVSAttrs.push_back().set(type,
801 GrGLShaderVar::kAttribute_TypeModifier,
806 bool GrGLFullShaderBuilder::addEffectAttribute(int attributeIndex,
808 const SkString& name) {
809 if (!this->addAttribute(type, name.c_str())) {
813 fEffectAttributes.push_back().set(attributeIndex, name);
817 void GrGLFullShaderBuilder::addVarying(GrSLType type,
819 const char** vsOutName,
820 const char** fsInName) {
821 fVSOutputs.push_back();
822 fVSOutputs.back().setType(type);
823 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
824 this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
827 *vsOutName = fVSOutputs.back().getName().c_str();
829 // input to FS comes either from VS or GS
830 const SkString* fsName;
831 #if GR_GL_EXPERIMENTAL_GS
832 if (fDesc.getHeader().fExperimentalGS) {
833 // if we have a GS take each varying in as an array
834 // and output as non-array.
835 fGSInputs.push_back();
836 fGSInputs.back().setType(type);
837 fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
838 fGSInputs.back().setUnsizedArray();
839 *fGSInputs.back().accessName() = fVSOutputs.back().getName();
840 fGSOutputs.push_back();
841 fGSOutputs.back().setType(type);
842 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
843 this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
844 fsName = fGSOutputs.back().accessName();
848 fsName = fVSOutputs.back().accessName();
850 this->fsInputAppend().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, *fsName);
852 *fsInName = fsName->c_str();
856 const SkString* GrGLFullShaderBuilder::getEffectAttributeName(int attributeIndex) const {
857 const AttributePair* attribEnd = fEffectAttributes.end();
858 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
859 if (attrib->fIndex == attributeIndex) {
860 return &attrib->fName;
867 GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
868 const GrEffectStage* effectStages[],
869 const EffectKey effectKeys[],
871 GrGLSLExpr4* inOutFSColor) {
873 GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
874 this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
879 return programEffectsBuilder.finish();
882 bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
883 const GrGLContext& glCtx = this->gpu()->glContext();
884 SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
885 this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc);
886 this->appendDecls(fVSAttrs, &vertShaderSrc);
887 this->appendDecls(fVSOutputs, &vertShaderSrc);
888 vertShaderSrc.append("void main() {\n");
889 vertShaderSrc.append(fVSCode);
890 vertShaderSrc.append("}\n");
891 GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc);
895 *shaderIds->append() = vertShaderId;
897 #if GR_GL_EXPERIMENTAL_GS
898 if (fDesc.getHeader().fExperimentalGS) {
899 SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
900 SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
901 geomShaderSrc.append("layout(triangles) in;\n"
902 "layout(triangle_strip, max_vertices = 6) out;\n");
903 this->appendDecls(fGSInputs, &geomShaderSrc);
904 this->appendDecls(fGSOutputs, &geomShaderSrc);
905 geomShaderSrc.append("void main() {\n");
906 geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
907 "\t\tgl_Position = gl_in[i].gl_Position;\n");
908 if (fDesc.getHeader().fEmitsPointSize) {
909 geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n");
911 SkASSERT(fGSInputs.count() == fGSOutputs.count());
912 for (int i = 0; i < fGSInputs.count(); ++i) {
913 geomShaderSrc.appendf("\t\t%s = %s[i];\n",
914 fGSOutputs[i].getName().c_str(),
915 fGSInputs[i].getName().c_str());
917 geomShaderSrc.append("\t\tEmitVertex();\n"
919 "\tEndPrimitive();\n");
920 geomShaderSrc.append("}\n");
921 GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc);
925 *shaderIds->append() = geomShaderId;
929 return this->INHERITED::compileAndAttachShaders(programId, shaderIds);
932 void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
933 this->INHERITED::bindProgramLocations(programId);
935 const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
937 // Bind the attrib locations to same values for all shaders
938 SkASSERT(-1 != header.fPositionAttributeIndex);
939 GL_CALL(BindAttribLocation(programId,
940 header.fPositionAttributeIndex,
941 fPositionVar->c_str()));
942 if (-1 != header.fLocalCoordAttributeIndex) {
943 GL_CALL(BindAttribLocation(programId,
944 header.fLocalCoordAttributeIndex,
945 fLocalCoordsVar->c_str()));
947 if (-1 != header.fColorAttributeIndex) {
948 GL_CALL(BindAttribLocation(programId,
949 header.fColorAttributeIndex,
950 color_attribute_name()));
952 if (-1 != header.fCoverageAttributeIndex) {
953 GL_CALL(BindAttribLocation(programId,
954 header.fCoverageAttributeIndex,
955 coverage_attribute_name()));
958 const AttributePair* attribEnd = fEffectAttributes.end();
959 for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
960 GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
964 ////////////////////////////////////////////////////////////////////////////////
966 GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
967 GrGLUniformManager& uniformManager,
968 const GrGLProgramDesc& desc)
969 : INHERITED(gpu, uniformManager, desc)
970 , fNumTexCoordSets(0) {
972 SkASSERT(!desc.getHeader().fHasVertexCode);
973 SkASSERT(gpu->glCaps().pathRenderingSupport());
974 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
975 SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
978 int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) {
979 int firstFreeCoordSet = fNumTexCoordSets;
980 fNumTexCoordSets += count;
981 SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fNumTexCoordSets);
982 return firstFreeCoordSet;
985 GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
986 const GrEffectStage* effectStages[],
987 const EffectKey effectKeys[],
989 GrGLSLExpr4* inOutFSColor) {
991 GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
993 this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
998 return pathTexGenEffectsBuilder.finish();