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