GrGLShaderBuilder.cpp revision 91274b99722d9be62e077ab979c630c23cdd04b1
1f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com/*
2f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Copyright 2012 Google Inc.
3f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com *
4f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
5f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * found in the LICENSE file.
6f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com */
7f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
8f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#include "gl/GrGLShaderBuilder.h"
95259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com#include "gl/GrGLProgram.h"
10dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com#include "gl/GrGLUniformHandle.h"
11a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com#include "GrTexture.h"
12f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
13f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com// number of each input/output type in a single allocation block
14eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.comstatic const int kVarsPerBlock = 8;
15f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
16f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com// except FS outputs where we expect 2 at most.
17eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.comstatic const int kMaxFSOutputs = 2;
18f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
19d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com// ES2 FS only guarantees mediump and lowp support
20d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.comstatic const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
21d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
22dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle;
23dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com///////////////////////////////////////////////////////////////////////////////
24dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com
2534bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.comnamespace {
26a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
272b1b8c083b969a2a798b03d1754a3fc99ea054dfbsalomon@google.cominline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
2834bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com    if (kVec2f_GrSLType == type) {
292b1b8c083b969a2a798b03d1754a3fc99ea054dfbsalomon@google.com        return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
3034bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com    } else {
3134bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com        GrAssert(kVec3f_GrSLType == type);
322b1b8c083b969a2a798b03d1754a3fc99ea054dfbsalomon@google.com        return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
3334bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com    }
34a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
35a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
366d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com/**
376d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com * Do we need to either map r,g,b->a or a->r.
386d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com */
396d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.cominline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
406d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com                                             const GrTextureAccess& access) {
416d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    if (GrPixelConfigIsAlphaOnly(access.getTexture()->config())) {
426d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        if (caps.textureRedSupport() && (GrTextureAccess::kA_SwizzleFlag & access.swizzleMask())) {
436d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            return true;
446d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        }
456d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        if (GrTextureAccess::kRGB_SwizzleMask & access.swizzleMask()) {
466d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            return true;
476d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        }
48a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
496d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    return false;
506d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com}
51a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
526d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.comvoid append_swizzle(SkString* outAppend,
536d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com                    const GrTextureAccess& access,
546d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com                    const GrGLCaps& caps) {
556d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    const char* swizzle = access.getSwizzle();
566d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    char mangledSwizzle[5];
576d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com
586d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
596d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    // is available.
606d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(access.getTexture()->config())) {
616d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        char alphaChar = caps.textureRedSupport() ? 'r' : 'a';
626d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        int i;
636d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        for (i = 0; '\0' != swizzle[i]; ++i) {
646d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            mangledSwizzle[i] = alphaChar;
65a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        }
666d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        mangledSwizzle[i] ='\0';
676d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        swizzle = mangledSwizzle;
68a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
6973d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    // For shader prettiness we omit the swizzle rather than appending ".rgba".
7073d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    if (memcmp(swizzle, "rgba", 4)) {
7173d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com        outAppend->appendf(".%s", swizzle);
7273d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    }
73a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
74a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
7534bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com}
7634bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com
77a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com///////////////////////////////////////////////////////////////////////////////
78a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
799c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Architectural assumption: always 2-d input coords.
809c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Likely to become non-constant and non-static, perhaps even
819c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// varying by stage, if we use 1D textures for gradients!
829c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com//const int GrGLShaderBuilder::fCoordDims = 2;
839c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com
84631cdcb4a6b926b6447f328b81911a4499fb3698skia.committer@gmail.comGrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
856177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com                                     GrGLUniformManager& uniformManager)
86032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    : fUniforms(kVarsPerBlock)
87eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fVSAttrs(kVarsPerBlock)
88eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fVSOutputs(kVarsPerBlock)
89eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fGSInputs(kVarsPerBlock)
90eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fGSOutputs(kVarsPerBlock)
91eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fFSInputs(kVarsPerBlock)
92eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fFSOutputs(kMaxFSOutputs)
93040c41a97c58b069015be3f5062eeb6ffe5adbfdtomhudson@google.com    , fUsesGS(false)
946177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    , fCtxInfo(ctxInfo)
95777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    , fUniformManager(uniformManager)
9608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    , fCurrentStageIdx(kNonStageIdx)
97706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    , fSetupFragPosition(false)
98dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com    , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) {
99e862d16162fd46ad9b2832c8844b00c81bedbac0skia.committer@gmail.com
10017504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com    fPositionVar = &fVSAttrs.push_back();
10117504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com    fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
102f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com}
103f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
104f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.comvoid GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) {
1059c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com    SkString* string = NULL;
106f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    switch (type) {
107f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kVertex_ShaderType:
108f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fVSCode;
109f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
110f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kGeometry_ShaderType:
111f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fGSCode;
112f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
113f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kFragment_ShaderType:
114f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fFSCode;
115f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
116f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        default:
117f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            GrCrash("Invalid shader type");
118f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    }
119f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    string->appendf(format, args);
120f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com}
121f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
122f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.comvoid GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) {
1239c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com    SkString* string = NULL;
124f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    switch (type) {
125f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kVertex_ShaderType:
126f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fVSCode;
127f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
128f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kGeometry_ShaderType:
129f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fGSCode;
130f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
131f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        case kFragment_ShaderType:
132f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            string = &fFSCode;
133f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            break;
134f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        default:
135f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com            GrCrash("Invalid shader type");
136f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    }
137f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    string->append(str);
138f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com}
139f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
140868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookup(SkString* out,
141f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
142868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                                            const char* coordName,
143868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                                            GrSLType varyingType) const {
1442d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com    GrAssert(NULL != sampler.textureAccess());
145dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com    GrAssert(NULL != coordName);
1462d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com
1476d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    out->appendf("%s(%s, %s)",
1482b1b8c083b969a2a798b03d1754a3fc99ea054dfbsalomon@google.com                 sample_function_name(varyingType, fCtxInfo.glslGeneration()),
149f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                 this->getUniformCStr(sampler.fSamplerUniform),
1506d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com                 coordName);
1516177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    append_swizzle(out, *sampler.textureAccess(), fCtxInfo.caps());
1525259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1535259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
154f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookup(ShaderType type,
155f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
156f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                            const char* coordName,
157f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                            GrSLType varyingType) {
158f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    GrAssert(kFragment_ShaderType == type);
159f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
160f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com}
161f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
162f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookupAndModulate(
163f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                            ShaderType type,
164f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            const char* modulation,
165f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
166f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            const char* coordName,
167f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                            GrSLType varyingType) {
168f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    GrAssert(kFragment_ShaderType == type);
169868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com    SkString lookup;
170f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
171f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    GrGLSLModulate4f(&fFSCode, modulation, lookup.c_str());
1725259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1735259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
1742eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.comGrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess(
1752eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com                                                            const GrTextureAccess& access,
1762eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com                                                            const GrGLCaps& caps) {
1772eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com    GrBackendEffectFactory::EffectKey key = 0;
178d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com
179a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    // Assume that swizzle support implies that we never have to modify a shader to adjust
180a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    // for texture format/swizzle settings.
1816d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    if (!caps.textureSwizzleSupport() && swizzle_requires_alpha_remapping(caps, access)) {
182a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        key = 1;
183a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
18473d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com#if GR_DEBUG
18573d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    // Assert that key is set iff the swizzle will be modified.
18673d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    SkString origString(access.getSwizzle());
18773d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    origString.prepend(".");
18873d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    SkString modifiedString;
18973d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    append_swizzle(&modifiedString, access, caps);
19073d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    if (!modifiedString.size()) {
19173d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com        modifiedString = ".rgba";
19273d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    }
19373d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com    GrAssert(SkToBool(key) == (modifiedString != origString));
19473d5b2f620c02f0741c9ce13091f108855f066aebsalomon@google.com#endif
195a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    return key;
196a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
197a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
1986d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.comconst GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
1996d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
2006d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        if (caps.textureRedSupport()) {
2016d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
2026d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            return gRedSmear;
2036d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        } else {
2046d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
2056d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com                                                    GR_GL_ALPHA, GR_GL_ALPHA };
2066d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com            return gAlphaSmear;
2076d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        }
2086d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    } else {
2096d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
2106d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        return gStraight;
2116d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    }
2126d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com}
2136d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com
214777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.comGrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
215777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     GrSLType type,
216777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     const char* name,
217777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     int count,
218777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     const char** outName) {
219242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    GrAssert(name && strlen(name));
2200e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com    SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType);
221eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    GrAssert(0 == (~kVisibilityMask & visibility));
222eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    GrAssert(0 != visibility);
223242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
224dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    BuilderUniform& uni = fUniforms.push_back();
225032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle h = index_to_handle(fUniforms.count() - 1);
226dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GR_DEBUGCODE(UniformHandle h2 =)
227dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    fUniformManager.appendUniform(type, count);
228dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
229dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    // by this function. Therefore, the handles should match.
230dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GrAssert(h2 == h);
231032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setType(type);
232032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
233777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    SkString* uniName = uni.fVariable.accessName();
23408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    if (kNonStageIdx == fCurrentStageIdx) {
235777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        uniName->printf("u%s", name);
236777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    } else {
23708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        uniName->printf("u%s%d", name, fCurrentStageIdx);
238242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    }
239032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setArrayCount(count);
240032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVisibility = visibility;
241242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
242032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // If it is visible in both the VS and FS, the precision must match.
243032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // We declare a default FS precision, but not a default VS. So set the var
244032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // to use the default FS precision.
245eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
246d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        // the fragment and vertex precisions must match
247032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
248242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    }
249242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
250777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    if (NULL != outName) {
251777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        *outName = uni.fVariable.c_str();
252777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    }
253777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com
254032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    return h;
255032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com}
256032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
257032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comconst GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
258032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    return fUniforms[handle_to_index(u)].fVariable;
259242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com}
26023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
261ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.orgbool GrGLShaderBuilder::addAttribute(GrSLType type,
262ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org                                     const char* name) {
263ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    for (int i = 0; i < fVSAttrs.count(); ++i) {
264ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        const GrGLShaderVar& attr = fVSAttrs[i];
265ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        // if attribute already added, don't add it again
266ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        if (attr.getName().equals(name)) {
267ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            GrAssert(attr.getType() == type);
268ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            return false;
269ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
270ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
271ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    fVSAttrs.push_back().set(type,
272ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org                             GrGLShaderVar::kAttribute_TypeModifier,
273ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org                             name);
274ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    return true;
275ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org}
276ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
27723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.comvoid GrGLShaderBuilder::addVarying(GrSLType type,
27823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char* name,
27923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char** vsOutName,
28023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char** fsInName) {
28123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.push_back();
28223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.back().setType(type);
28323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
28408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    if (kNonStageIdx == fCurrentStageIdx) {
285777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        fVSOutputs.back().accessName()->printf("v%s", name);
286777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    } else {
28708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx);
288777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    }
28923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (vsOutName) {
29023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *vsOutName = fVSOutputs.back().getName().c_str();
29123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
29223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    // input to FS comes either from VS or GS
293f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    const SkString* fsName;
29423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (fUsesGS) {
29523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        // if we have a GS take each varying in as an array
29623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        // and output as non-array.
29723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.push_back();
29823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setType(type);
29923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
30023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setUnsizedArray();
30123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
30223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.push_back();
30323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.back().setType(type);
30423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
30508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        if (kNonStageIdx == fCurrentStageIdx) {
306d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com            fGSOutputs.back().accessName()->printf("g%s", name);
307d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com        } else {
30808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx);
309d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com        }
31023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fsName = fGSOutputs.back().accessName();
31123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    } else {
31223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fsName = fVSOutputs.back().accessName();
31323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
31423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.push_back();
31523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setType(type);
31623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
31723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setName(*fsName);
31823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (fsInName) {
31923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *fsInName = fsName->c_str();
32023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
32123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com}
32223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
323706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.comconst char* GrGLShaderBuilder::fragmentPosition() {
3243cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org#if 1
3256177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    if (fCtxInfo.caps().fragCoordConventionsSupport()) {
326706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        if (!fSetupFragPosition) {
3276918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com            if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
3286918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n");
3296918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com            }
3305fa2107842e017ee5932955ecf89ceca179e4630bsalomon@google.com            fFSInputs.push_back().set(kVec4f_GrSLType,
3315fa2107842e017ee5932955ecf89ceca179e4630bsalomon@google.com                                      GrGLShaderVar::kIn_TypeModifier,
3325fa2107842e017ee5932955ecf89ceca179e4630bsalomon@google.com                                      "gl_FragCoord",
3335fa2107842e017ee5932955ecf89ceca179e4630bsalomon@google.com                                      GrGLShaderVar::kDefault_Precision,
3345fa2107842e017ee5932955ecf89ceca179e4630bsalomon@google.com                                      GrGLShaderVar::kUpperLeft_Origin);
335706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            fSetupFragPosition = true;
336706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        }
3371e34ff7030c95a96c3cd5940de9b4dda4e1cef86skia.committer@gmail.com        return "gl_FragCoord";
338706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    } else {
339706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        static const char* kCoordName = "fragCoordYDown";
340706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        if (!fSetupFragPosition) {
341706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
342706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            const char* rtHeightName;
3431e34ff7030c95a96c3cd5940de9b4dda4e1cef86skia.committer@gmail.com
344706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            // temporarily change the stage index because we're inserting a uniform whose name
345706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            // shouldn't be mangled to be stage-specific.
34608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            int oldStageIdx = fCurrentStageIdx;
34708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            fCurrentStageIdx = kNonStageIdx;
348706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            fRTHeightUniform = this->addUniform(kFragment_ShaderType,
349706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com                                                kFloat_GrSLType,
350706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com                                                "RTHeight",
351706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com                                                &rtHeightName);
35208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            fCurrentStageIdx = oldStageIdx;
3531e34ff7030c95a96c3cd5940de9b4dda4e1cef86skia.committer@gmail.com
354706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
355706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com                                   kCoordName, rtHeightName);
356706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            fSetupFragPosition = true;
357706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        }
358706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform);
359706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        return kCoordName;
360706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    }
3613cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org#else
3623cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    // This is the path we'll need to use once we have support for TopLeft
3633cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    // render targets.
3643cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    if (!fSetupFragPosition) {
3653cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        fFSInputs.push_back().set(kVec4f_GrSLType,
3663cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                                  GrGLShaderVar::kIn_TypeModifier,
3673cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                                  "gl_FragCoord",
3683cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                                  GrGLShaderVar::kDefault_Precision);
3693cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        fSetupFragPosition = true;
3703cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    }
3713cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    return "gl_FragCoord";
3723cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org#endif
373706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com}
374706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com
375706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com
376a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.comvoid GrGLShaderBuilder::emitFunction(ShaderType shader,
377a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     GrSLType returnType,
378a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const char* name,
379a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     int argCnt,
380a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const GrGLShaderVar* args,
381a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const char* body,
382a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     SkString* outName) {
383a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    GrAssert(kFragment_ShaderType == shader);
384a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(GrGLShaderVar::TypeString(returnType));
38508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    if (kNonStageIdx != fCurrentStageIdx) {
38608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        outName->printf(" %s_%d", name, fCurrentStageIdx);
387a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    } else {
388a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        *outName = name;
389a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    }
390a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(*outName);
391a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append("(");
392a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    for (int i = 0; i < argCnt; ++i) {
3936177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com        args[i].appendDecl(fCtxInfo, &fFSFunctions);
394a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        if (i < argCnt - 1) {
395a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            fFSFunctions.append(", ");
396a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        }
397a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    }
398a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(") {\n");
399a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(body);
400a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append("}\n\n");
401a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
40223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
403ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comnamespace {
404d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
405d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.cominline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
406d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               GrGLBinding binding,
407d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               SkString* str) {
408d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    // Desktop GLSL has added precision qualifiers but they don't do anything.
409d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    if (kES2_GrGLBinding == binding) {
410d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        switch (p) {
411d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kHigh_Precision:
412d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision highp float;\n");
413d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
414d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kMedium_Precision:
415d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision mediump float;\n");
416d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
417d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kLow_Precision:
418d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision lowp float;\n");
419d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
420d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kDefault_Precision:
421d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                GrCrash("Default precision now allowed.");
422d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            default:
423d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                GrCrash("Unknown precision value.");
424d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        }
425d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    }
426d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com}
427032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com}
428d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
429032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
430ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    for (int i = 0; i < vars.count(); ++i) {
4316177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com        vars[i].appendDecl(fCtxInfo, out);
432a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        out->append(";\n");
433ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    }
434ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com}
435032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
436032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
437032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    for (int i = 0; i < fUniforms.count(); ++i) {
438032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        if (fUniforms[i].fVisibility & stype) {
4396177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com            fUniforms[i].fVariable.appendDecl(fCtxInfo, out);
440a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            out->append(";\n");
441032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        }
442032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    }
443ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com}
444ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com
445ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comvoid GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
446ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    switch (type) {
447ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kVertex_ShaderType:
448ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            *shaderStr = fHeader;
449032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
450032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fVSAttrs, shaderStr);
451032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fVSOutputs, shaderStr);
452d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com            shaderStr->append("void main() {\n");
453ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fVSCode);
454d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com            shaderStr->append("}\n");
455ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
456ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kGeometry_ShaderType:
457ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            if (fUsesGS) {
458ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                *shaderStr = fHeader;
459ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->append(fGSHeader);
460032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                this->appendDecls(fGSInputs, shaderStr);
461032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                this->appendDecls(fGSOutputs, shaderStr);
462d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com                shaderStr->append("void main() {\n");
463ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->append(fGSCode);
464d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com                shaderStr->append("}\n");
465ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            } else {
466ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->reset();
467ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            }
468ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
469ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kFragment_ShaderType:
470ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            *shaderStr = fHeader;
471d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            append_default_precision_qualifier(kDefaultFragmentPrecision,
4726177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com                                               fCtxInfo.binding(),
473d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               shaderStr);
474706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com            shaderStr->append(fFSHeader);
475032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
476032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fFSInputs, shaderStr);
477ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            // We shouldn't have declared outputs on 1.10
4786177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com            GrAssert(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty());
479032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fFSOutputs, shaderStr);
480ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fFSFunctions);
481d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com            shaderStr->append("void main() {\n");
482ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fFSCode);
483d7bafb700c62dff466a88bee81d793e51737284bbsalomon@google.com            shaderStr->append("}\n");
484ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
485ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    }
486ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com }
487d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
488dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comvoid GrGLShaderBuilder::finished(GrGLuint programID) {
489dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    fUniformManager.getUniformLocations(programID, fUniforms);
490dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com}
49134cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
49234cccde630fc618649b9737bee464203d042bfbbbsalomon@google.comGrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect(
49334cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const GrEffectStage& stage,
49434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                GrGLEffect::EffectKey key,
49534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const char* fsInColor,
49634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const char* fsOutColor,
49734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const char* vsInCoord,
49834cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) {
49934cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    GrAssert(NULL != stage.getEffect());
50034cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
5016340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com    const GrEffectRef& effect = *stage.getEffect();
5026340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com    int numTextures = effect->numTextures();
50334cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
50434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    textureSamplers.push_back_n(numTextures);
50534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    for (int i = 0; i < numTextures; ++i) {
5066340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        textureSamplers[i].init(this, &effect->textureAccess(i), i);
50734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com        samplerHandles->push_back(textureSamplers[i].fSamplerUniform);
50834cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    }
50934cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
510ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    int numAttributes = stage.getVertexAttribIndexCount();
511ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    const int* attributeIndices = stage.getVertexAttribIndices();
512ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
513ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    for (int i = 0; i < numAttributes; ++i) {
514ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        SkString attributeName("aAttr");
515ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        attributeName.appendS32(attributeIndices[i]);
516ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
517ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        if (this->addAttribute(effect->vertexAttribType(i), attributeName.c_str())) {
518ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            fEffectAttributes.push_back().set(attributeIndices[i], attributeName);
519ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
520ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
521ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
5226340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com    GrGLEffect* glEffect = effect->getFactory().createGLInstance(effect);
52334cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
52434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    // Enclose custom code in a block to avoid namespace conflicts
52534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    this->fVSCode.appendf("\t{ // %s\n", glEffect->name());
52634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    this->fFSCode.appendf("\t{ // %s \n", glEffect->name());
52734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    glEffect->emitCode(this,
52834cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       stage,
52934cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       key,
53034cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       vsInCoord,
53134cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       fsOutColor,
53234cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       fsInColor,
53334cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                       textureSamplers);
53434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    this->fVSCode.appendf("\t}\n");
53534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    this->fFSCode.appendf("\t}\n");
53634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
53734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    return glEffect;
53834cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com}
539ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
540ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.orgconst SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
541ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    const AttributePair* attribEnd = this->getEffectAttributes().end();
54291274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com    for (const AttributePair* attrib = this->getEffectAttributes().begin();
543ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org         attrib != attribEnd;
544ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org         ++attrib) {
545ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        if (attrib->fIndex == attributeIndex) {
546ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            return &attrib->fName;
547ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
54891274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com    }
549ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
550ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    return NULL;
551ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org}
552