• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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