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