GrGLShaderBuilder.cpp revision f6de475e5cbd143f348ff7738919e397b7fe7f57
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 "GrDrawEffect.h"
12#include "GrTexture.h"
13
14// number of each input/output type in a single allocation block
15static const int kVarsPerBlock = 8;
16
17// except FS outputs where we expect 2 at most.
18static const int kMaxFSOutputs = 2;
19
20// ES2 FS only guarantees mediump and lowp support
21static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
22
23typedef GrGLUniformManager::UniformHandle UniformHandle;
24///////////////////////////////////////////////////////////////////////////////
25
26namespace {
27
28inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
29    if (kVec2f_GrSLType == type) {
30        return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
31    } else {
32        SkASSERT(kVec3f_GrSLType == type);
33        return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
34    }
35}
36
37/**
38 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
39 * present in the texture's config. swizzleComponentMask indicates the channels present in the
40 * shader swizzle.
41 */
42inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
43                                             uint32_t configComponentMask,
44                                             uint32_t swizzleComponentMask) {
45    if (caps.textureSwizzleSupport()) {
46        // Any remapping is handled using texture swizzling not shader modifications.
47        return false;
48    }
49    // check if the texture is alpha-only
50    if (kA_GrColorComponentFlag == configComponentMask) {
51        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
52            // we must map the swizzle 'a's to 'r'.
53            return true;
54        }
55        if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
56            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
57            // alpha-only textures smear alpha across all four channels when read.
58            return true;
59        }
60    }
61    return false;
62}
63
64void append_swizzle(SkString* outAppend,
65                    const GrGLShaderBuilder::TextureSampler& texSampler,
66                    const GrGLCaps& caps) {
67    const char* swizzle = texSampler.swizzle();
68    char mangledSwizzle[5];
69
70    // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
71    // is available.
72    if (!caps.textureSwizzleSupport() &&
73        (kA_GrColorComponentFlag == texSampler.configComponentMask())) {
74        char alphaChar = caps.textureRedSupport() ? 'r' : 'a';
75        int i;
76        for (i = 0; '\0' != swizzle[i]; ++i) {
77            mangledSwizzle[i] = alphaChar;
78        }
79        mangledSwizzle[i] ='\0';
80        swizzle = mangledSwizzle;
81    }
82    // For shader prettiness we omit the swizzle rather than appending ".rgba".
83    if (memcmp(swizzle, "rgba", 4)) {
84        outAppend->appendf(".%s", swizzle);
85    }
86}
87
88}
89
90static const char kDstCopyColorName[] = "_dstColor";
91
92///////////////////////////////////////////////////////////////////////////////
93
94GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
95                                     GrGLUniformManager& uniformManager,
96                                     const GrGLProgramDesc& desc)
97    : fUniforms(kVarsPerBlock)
98    , fVSAttrs(kVarsPerBlock)
99    , fVSOutputs(kVarsPerBlock)
100    , fGSInputs(kVarsPerBlock)
101    , fGSOutputs(kVarsPerBlock)
102    , fFSInputs(kVarsPerBlock)
103    , fFSOutputs(kMaxFSOutputs)
104    , fCtxInfo(ctxInfo)
105    , fUniformManager(uniformManager)
106    , fFSFeaturesAddedMask(0)
107#if GR_GL_EXPERIMENTAL_GS
108    , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
109#else
110    , fUsesGS(false)
111#endif
112    , fSetupFragPosition(false)
113    , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
114
115    const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
116
117    fPositionVar = &fVSAttrs.push_back();
118    fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
119    if (-1 != header.fLocalCoordAttributeIndex) {
120        fLocalCoordsVar = &fVSAttrs.push_back();
121        fLocalCoordsVar->set(kVec2f_GrSLType,
122                             GrGLShaderVar::kAttribute_TypeModifier,
123                             "aLocalCoords");
124    } else {
125        fLocalCoordsVar = fPositionVar;
126    }
127    // Emit code to read the dst copy textue if necessary.
128    if (kNoDstRead_DstReadKey != header.fDstReadKey &&
129        GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
130        bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
131        const char* dstCopyTopLeftName;
132        const char* dstCopyCoordScaleName;
133        uint32_t configMask;
134        if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
135            configMask = kA_GrColorComponentFlag;
136        } else {
137            configMask = kRGBA_GrColorComponentFlags;
138        }
139        fDstCopySampler.init(this, configMask, "rgba", 0);
140
141        fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType,
142                                                  kVec2f_GrSLType,
143                                                  "DstCopyUpperLeft",
144                                                  &dstCopyTopLeftName);
145        fDstCopyScaleUniform     = this->addUniform(kFragment_ShaderType,
146                                                    kVec2f_GrSLType,
147                                                    "DstCopyCoordScale",
148                                                    &dstCopyCoordScaleName);
149        const char* fragPos = this->fragmentPosition();
150        this->fsCodeAppend("\t// Read color from copy of the destination.\n");
151        this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
152                            fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
153        if (!topDown) {
154            this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
155        }
156        this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
157        this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord");
158        this->fsCodeAppend(";\n\n");
159    }
160}
161
162bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
163    switch (feature) {
164        case kStandardDerivatives_GLSLFeature:
165            if (!fCtxInfo.caps()->shaderDerivativeSupport()) {
166                return false;
167            }
168            if (kES_GrGLBinding == fCtxInfo.binding()) {
169                this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
170                                   "GL_OES_standard_derivatives");
171            }
172            return true;
173        default:
174            GrCrash("Unexpected GLSLFeature requested.");
175            return false;
176    }
177}
178
179bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
180    switch (feature) {
181        case kFragCoordConventions_GLSLPrivateFeature:
182            if (!fCtxInfo.caps()->fragCoordConventionsSupport()) {
183                return false;
184            }
185            if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
186                this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
187                                   "GL_ARB_fragment_coord_conventions");
188            }
189            return true;
190        case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
191            if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
192                return false;
193            }
194            this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
195                               "GL_EXT_shader_framebuffer_fetch");
196            return true;
197        case kNVShaderFramebufferFetch_GLSLPrivateFeature:
198            if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
199                return false;
200            }
201            this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
202                               "GL_NV_shader_framebuffer_fetch");
203            return true;
204        default:
205            GrCrash("Unexpected GLSLPrivateFeature requested.");
206            return false;
207    }
208}
209
210void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
211    if (!(featureBit & fFSFeaturesAddedMask)) {
212        fFSExtensions.appendf("#extension %s: require\n", extensionName);
213        fFSFeaturesAddedMask |= featureBit;
214    }
215}
216
217void GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
218    if ('\0' == prefix) {
219        *out = name;
220    } else {
221        out->printf("%c%s", prefix, name);
222    }
223    if (fCodeStage.inStageCode()) {
224        if (out->endsWith('_')) {
225            // Names containing "__" are reserved.
226            out->append("x");
227        }
228        out->appendf("_Stage%d", fCodeStage.stageIndex());
229    }
230}
231
232const char* GrGLShaderBuilder::dstColor() {
233    if (fCodeStage.inStageCode()) {
234        const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
235        if (!effect->willReadDstColor()) {
236            GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect "
237                         "did not request access.");
238            return "";
239        }
240    }
241    static const char kFBFetchColorName[] = "gl_LastFragData[0]";
242    GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
243    if (GrGLCaps::kEXT_FBFetchType == fetchType) {
244        SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
245        return kFBFetchColorName;
246    } else if (GrGLCaps::kNV_FBFetchType == fetchType) {
247        SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
248        return kFBFetchColorName;
249    } else if (fDstCopySampler.isInitialized()) {
250        return kDstCopyColorName;
251    } else {
252        return "";
253    }
254}
255
256void GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) {
257    SkString* string = NULL;
258    switch (type) {
259        case kVertex_ShaderType:
260            string = &fVSCode;
261            break;
262        case kGeometry_ShaderType:
263            string = &fGSCode;
264            break;
265        case kFragment_ShaderType:
266            string = &fFSCode;
267            break;
268        default:
269            GrCrash("Invalid shader type");
270    }
271    string->appendf(format, args);
272}
273
274void GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) {
275    SkString* string = NULL;
276    switch (type) {
277        case kVertex_ShaderType:
278            string = &fVSCode;
279            break;
280        case kGeometry_ShaderType:
281            string = &fGSCode;
282            break;
283        case kFragment_ShaderType:
284            string = &fFSCode;
285            break;
286        default:
287            GrCrash("Invalid shader type");
288    }
289    string->append(str);
290}
291
292void GrGLShaderBuilder::appendTextureLookup(SkString* out,
293                                            const GrGLShaderBuilder::TextureSampler& sampler,
294                                            const char* coordName,
295                                            GrSLType varyingType) const {
296    SkASSERT(NULL != coordName);
297
298    out->appendf("%s(%s, %s)",
299                 sample_function_name(varyingType, fCtxInfo.glslGeneration()),
300                 this->getUniformCStr(sampler.fSamplerUniform),
301                 coordName);
302    append_swizzle(out, sampler, *fCtxInfo.caps());
303}
304
305void GrGLShaderBuilder::appendTextureLookup(ShaderType type,
306                                            const GrGLShaderBuilder::TextureSampler& sampler,
307                                            const char* coordName,
308                                            GrSLType varyingType) {
309    SkASSERT(kFragment_ShaderType == type);
310    this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
311}
312
313void GrGLShaderBuilder::appendTextureLookupAndModulate(
314                                            ShaderType type,
315                                            const char* modulation,
316                                            const GrGLShaderBuilder::TextureSampler& sampler,
317                                            const char* coordName,
318                                            GrSLType varyingType) {
319    SkASSERT(kFragment_ShaderType == type);
320    SkString lookup;
321    this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
322    GrGLSLModulatef<4>(&fFSCode, modulation, lookup.c_str());
323}
324
325GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess(
326                                                            const GrTextureAccess& access,
327                                                            const GrGLCaps& caps) {
328    uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
329    if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
330        return 1;
331    } else {
332        return 0;
333    }
334}
335
336GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
337                                                               const GrGLCaps& caps) {
338    uint32_t key = kYesDstRead_DstReadKeyBit;
339    if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) {
340        return key;
341    }
342    SkASSERT(NULL != dstCopy);
343    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
344        // The fact that the config is alpha-only must be considered when generating code.
345        key |= kUseAlphaConfig_DstReadKeyBit;
346    }
347    if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
348        key |= kTopLeftOrigin_DstReadKeyBit;
349    }
350    SkASSERT(static_cast<DstReadKey>(key) == key);
351    return static_cast<DstReadKey>(key);
352}
353
354GrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
355                                                                        const GrGLCaps&) {
356    if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
357        return kTopLeftFragPosRead_FragPosKey;
358    } else {
359        return kBottomLeftFragPosRead_FragPosKey;
360    }
361}
362
363
364const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
365    if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
366        if (caps.textureRedSupport()) {
367            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
368            return gRedSmear;
369        } else {
370            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
371                                                    GR_GL_ALPHA, GR_GL_ALPHA };
372            return gAlphaSmear;
373        }
374    } else {
375        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
376        return gStraight;
377    }
378}
379
380GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
381                                                                     GrSLType type,
382                                                                     const char* name,
383                                                                     int count,
384                                                                     const char** outName) {
385    SkASSERT(name && strlen(name));
386    SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType);
387    SkASSERT(0 == (~kVisibilityMask & visibility));
388    SkASSERT(0 != visibility);
389
390    BuilderUniform& uni = fUniforms.push_back();
391    UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
392    GR_DEBUGCODE(UniformHandle h2 =)
393    fUniformManager.appendUniform(type, count);
394    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
395    // by this function. Therefore, the handles should match.
396    SkASSERT(h2 == h);
397    uni.fVariable.setType(type);
398    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
399    this->nameVariable(uni.fVariable.accessName(), 'u', name);
400    uni.fVariable.setArrayCount(count);
401    uni.fVisibility = visibility;
402
403    // If it is visible in both the VS and FS, the precision must match.
404    // We declare a default FS precision, but not a default VS. So set the var
405    // to use the default FS precision.
406    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
407        // the fragment and vertex precisions must match
408        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
409    }
410
411    if (NULL != outName) {
412        *outName = uni.fVariable.c_str();
413    }
414
415    return h;
416}
417
418bool GrGLShaderBuilder::addAttribute(GrSLType type,
419                                     const char* name) {
420    for (int i = 0; i < fVSAttrs.count(); ++i) {
421        const GrGLShaderVar& attr = fVSAttrs[i];
422        // if attribute already added, don't add it again
423        if (attr.getName().equals(name)) {
424            SkASSERT(attr.getType() == type);
425            return false;
426        }
427    }
428    fVSAttrs.push_back().set(type,
429                             GrGLShaderVar::kAttribute_TypeModifier,
430                             name);
431    return true;
432}
433
434void GrGLShaderBuilder::addVarying(GrSLType type,
435                                   const char* name,
436                                   const char** vsOutName,
437                                   const char** fsInName) {
438    fVSOutputs.push_back();
439    fVSOutputs.back().setType(type);
440    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
441    this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
442
443    if (vsOutName) {
444        *vsOutName = fVSOutputs.back().getName().c_str();
445    }
446    // input to FS comes either from VS or GS
447    const SkString* fsName;
448    if (fUsesGS) {
449        // if we have a GS take each varying in as an array
450        // and output as non-array.
451        fGSInputs.push_back();
452        fGSInputs.back().setType(type);
453        fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
454        fGSInputs.back().setUnsizedArray();
455        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
456        fGSOutputs.push_back();
457        fGSOutputs.back().setType(type);
458        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
459        this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
460        fsName = fGSOutputs.back().accessName();
461    } else {
462        fsName = fVSOutputs.back().accessName();
463    }
464    fFSInputs.push_back();
465    fFSInputs.back().setType(type);
466    fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
467    fFSInputs.back().setName(*fsName);
468    if (fsInName) {
469        *fsInName = fsName->c_str();
470    }
471}
472
473const char* GrGLShaderBuilder::fragmentPosition() {
474    if (fCodeStage.inStageCode()) {
475        const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
476        if (!effect->willReadFragmentPosition()) {
477            GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect "
478                         "did not request access.");
479            return "";
480        }
481    }
482    if (fTopLeftFragPosRead) {
483        if (!fSetupFragPosition) {
484            fFSInputs.push_back().set(kVec4f_GrSLType,
485                                      GrGLShaderVar::kIn_TypeModifier,
486                                      "gl_FragCoord",
487                                      GrGLShaderVar::kDefault_Precision);
488            fSetupFragPosition = true;
489        }
490        return "gl_FragCoord";
491    } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
492        if (!fSetupFragPosition) {
493            SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
494            fFSInputs.push_back().set(kVec4f_GrSLType,
495                                      GrGLShaderVar::kIn_TypeModifier,
496                                      "gl_FragCoord",
497                                      GrGLShaderVar::kDefault_Precision,
498                                      GrGLShaderVar::kUpperLeft_Origin);
499            fSetupFragPosition = true;
500        }
501        return "gl_FragCoord";
502    } else {
503        static const char* kCoordName = "fragCoordYDown";
504        if (!fSetupFragPosition) {
505            // temporarily change the stage index because we're inserting non-stage code.
506            CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
507
508            SkASSERT(!fRTHeightUniform.isValid());
509            const char* rtHeightName;
510
511            fRTHeightUniform = this->addUniform(kFragment_ShaderType,
512                                                kFloat_GrSLType,
513                                                "RTHeight",
514                                                &rtHeightName);
515
516            this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
517                                   kCoordName, rtHeightName);
518            fSetupFragPosition = true;
519        }
520        SkASSERT(fRTHeightUniform.isValid());
521        return kCoordName;
522    }
523}
524
525
526void GrGLShaderBuilder::emitFunction(ShaderType shader,
527                                     GrSLType returnType,
528                                     const char* name,
529                                     int argCnt,
530                                     const GrGLShaderVar* args,
531                                     const char* body,
532                                     SkString* outName) {
533    SkASSERT(kFragment_ShaderType == shader);
534    fFSFunctions.append(GrGLSLTypeString(returnType));
535    this->nameVariable(outName, '\0', name);
536    fFSFunctions.appendf(" %s", outName->c_str());
537    fFSFunctions.append("(");
538    for (int i = 0; i < argCnt; ++i) {
539        args[i].appendDecl(fCtxInfo, &fFSFunctions);
540        if (i < argCnt - 1) {
541            fFSFunctions.append(", ");
542        }
543    }
544    fFSFunctions.append(") {\n");
545    fFSFunctions.append(body);
546    fFSFunctions.append("}\n\n");
547}
548
549namespace {
550
551inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
552                                               GrGLBinding binding,
553                                               SkString* str) {
554    // Desktop GLSL has added precision qualifiers but they don't do anything.
555    if (kES_GrGLBinding == binding) {
556        switch (p) {
557            case GrGLShaderVar::kHigh_Precision:
558                str->append("precision highp float;\n");
559                break;
560            case GrGLShaderVar::kMedium_Precision:
561                str->append("precision mediump float;\n");
562                break;
563            case GrGLShaderVar::kLow_Precision:
564                str->append("precision lowp float;\n");
565                break;
566            case GrGLShaderVar::kDefault_Precision:
567                GrCrash("Default precision now allowed.");
568            default:
569                GrCrash("Unknown precision value.");
570        }
571    }
572}
573}
574
575void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
576    for (int i = 0; i < vars.count(); ++i) {
577        vars[i].appendDecl(fCtxInfo, out);
578        out->append(";\n");
579    }
580}
581
582void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
583    for (int i = 0; i < fUniforms.count(); ++i) {
584        if (fUniforms[i].fVisibility & stype) {
585            fUniforms[i].fVariable.appendDecl(fCtxInfo, out);
586            out->append(";\n");
587        }
588    }
589}
590
591void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
592    const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration());
593
594    switch (type) {
595        case kVertex_ShaderType:
596            *shaderStr = version;
597            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
598            this->appendDecls(fVSAttrs, shaderStr);
599            this->appendDecls(fVSOutputs, shaderStr);
600            shaderStr->append("void main() {\n");
601            shaderStr->append(fVSCode);
602            shaderStr->append("}\n");
603            break;
604        case kGeometry_ShaderType:
605            if (fUsesGS) {
606                *shaderStr = version;
607                shaderStr->append(fGSHeader);
608                this->appendDecls(fGSInputs, shaderStr);
609                this->appendDecls(fGSOutputs, shaderStr);
610                shaderStr->append("void main() {\n");
611                shaderStr->append(fGSCode);
612                shaderStr->append("}\n");
613            } else {
614                shaderStr->reset();
615            }
616            break;
617        case kFragment_ShaderType:
618            *shaderStr = version;
619            shaderStr->append(fFSExtensions);
620            append_default_precision_qualifier(kDefaultFragmentPrecision,
621                                               fCtxInfo.binding(),
622                                               shaderStr);
623            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
624            this->appendDecls(fFSInputs, shaderStr);
625            // We shouldn't have declared outputs on 1.10
626            SkASSERT(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty());
627            this->appendDecls(fFSOutputs, shaderStr);
628            shaderStr->append(fFSFunctions);
629            shaderStr->append("void main() {\n");
630            shaderStr->append(fFSCode);
631            shaderStr->append("}\n");
632            break;
633    }
634 }
635
636void GrGLShaderBuilder::finished(GrGLuint programID) {
637    fUniformManager.getUniformLocations(programID, fUniforms);
638}
639
640void GrGLShaderBuilder::emitEffects(
641                        const GrEffectStage* effectStages[],
642                        const GrBackendEffectFactory::EffectKey effectKeys[],
643                        int effectCnt,
644                        SkString* fsInOutColor,
645                        GrSLConstantVec* fsInOutColorKnownValue,
646                        SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
647                        GrGLEffect* glEffects[]) {
648    bool effectEmitted = false;
649
650    SkString inColor = *fsInOutColor;
651    SkString outColor;
652
653    for (int e = 0; e < effectCnt; ++e) {
654        SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
655        const GrEffectStage& stage = *effectStages[e];
656        const GrEffectRef& effect = *stage.getEffect();
657
658        CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
659
660        int numTextures = effect->numTextures();
661        SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
662        textureSamplers.push_back_n(numTextures);
663        for (int t = 0; t < numTextures; ++t) {
664            textureSamplers[t].init(this, &effect->textureAccess(t), t);
665            effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
666        }
667        GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords());
668
669        int numAttributes = stage.getVertexAttribIndexCount();
670        const int* attributeIndices = stage.getVertexAttribIndices();
671        SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
672        for (int a = 0; a < numAttributes; ++a) {
673            // TODO: Make addAttribute mangle the name.
674            SkString attributeName("aAttr");
675            attributeName.appendS32(attributeIndices[a]);
676            if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) {
677                fEffectAttributes.push_back().set(attributeIndices[a], attributeName);
678            }
679        }
680
681        glEffects[e] = effect->getFactory().createGLInstance(drawEffect);
682
683        if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) {
684            // Effects have no way to communicate zeros, they treat an empty string as ones.
685            this->nameVariable(&inColor, '\0', "input");
686            this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
687        }
688
689        // create var to hold stage result
690        this->nameVariable(&outColor, '\0', "output");
691        this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
692
693        // Enclose custom code in a block to avoid namespace conflicts
694        SkString openBrace;
695        openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name());
696        this->fVSCode.append(openBrace);
697        this->fFSCode.append(openBrace);
698
699        glEffects[e]->emitCode(this,
700                               drawEffect,
701                               effectKeys[e],
702                               outColor.c_str(),
703                               inColor.isEmpty() ? NULL : inColor.c_str(),
704                               textureSamplers);
705        this->fVSCode.append("\t}\n");
706        this->fFSCode.append("\t}\n");
707
708        inColor = outColor;
709        *fsInOutColorKnownValue = kNone_GrSLConstantVec;
710        effectEmitted = true;
711    }
712
713    if (effectEmitted) {
714        *fsInOutColor = outColor;
715    }
716}
717
718const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
719    const AttributePair* attribEnd = this->getEffectAttributes().end();
720    for (const AttributePair* attrib = this->getEffectAttributes().begin();
721         attrib != attribEnd;
722         ++attrib) {
723        if (attrib->fIndex == attributeIndex) {
724            return &attrib->fName;
725        }
726    }
727
728    return NULL;
729}
730