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