GrGLShaderBuilder.cpp revision a1bf0fffff821d9c11809c89bd98d4ced480421a
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
25a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) {
26a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    SkString sampler("texture2D");
27a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    switch (samplerMode) {
28a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com      case GrGLShaderBuilder::kDefault_SamplerMode:
29a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com          break;
30a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com      case GrGLShaderBuilder::kProj_SamplerMode:
31a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com          sampler.append("Proj");
32a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com          break;
33a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com      case GrGLShaderBuilder::kExplicitDivide_SamplerMode:
34a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com          break;
35a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
36a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
37a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    return sampler;
38a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
39a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
40a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
41a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                                  const GrTextureAccess& access) {
42a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
43a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        access.referencesAlpha();
44a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
45a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
46a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic SkString build_swizzle_string(const GrTextureAccess& textureAccess,
47a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                     const GrGLCaps& caps) {
48a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
49a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    if (0 == swizzle[0]) {
50a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        return SkString("");
51a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
52a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
53a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    SkString swizzleOut(".");
54a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess);
55a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) {
56a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        if (alphaIsRed && 'a' == swizzle[offset]) {
57a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com            swizzleOut.appendf("r");
58a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        } else {
59a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com            swizzleOut.appendf("%c", swizzle[offset]);
60a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        }
61a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
62a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
63a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    return swizzleOut;
64a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
65a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
66a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com///////////////////////////////////////////////////////////////////////////////
67a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
689c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Architectural assumption: always 2-d input coords.
699c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Likely to become non-constant and non-static, perhaps even
709c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// varying by stage, if we use 1D textures for gradients!
719c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com//const int GrGLShaderBuilder::fCoordDims = 2;
729c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com
73dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comGrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformManager& uniformManager)
74032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    : fUniforms(kVarsPerBlock)
75eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fVSAttrs(kVarsPerBlock)
76eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fVSOutputs(kVarsPerBlock)
77eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fGSInputs(kVarsPerBlock)
78eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fGSOutputs(kVarsPerBlock)
79eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fFSInputs(kVarsPerBlock)
80eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    , fFSOutputs(kMaxFSOutputs)
81040c41a97c58b069015be3f5062eeb6ffe5adbfdtomhudson@google.com    , fUsesGS(false)
829c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com    , fVaryingDims(0)
83ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    , fComplexCoord(false)
84dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    , fContext(ctx)
85777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    , fUniformManager(uniformManager)
86777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    , fCurrentStage(kNonStageIdx) {
87f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com}
88f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
895259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
905259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com   static const uint32_t kMulByAlphaMask =
915259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
925259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com         GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
935259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
945259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    fSwizzle = "";
955259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
965259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags &
975259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
985259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags &
995259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
1005259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        fSwizzle = ".bgra";
1015259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
1025259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags & kMulByAlphaMask));
1035259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags &
1045259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
1055259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        fSwizzle = ".aaaa";
1065259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
1075259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags & kMulByAlphaMask));
1085259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        GrAssert(!(configFlags &
1095259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
1105259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        fSwizzle = ".rrrr";
1115259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    }
1125259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1135259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
1145259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::computeModulate(const char* fsInColor) {
1155259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    if (NULL != fsInColor) {
1165259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        fModulate.printf(" * %s", fsInColor);
117e9b3f7dba0d721c60d296b09a578fbc6adaa7c63robertphillips@google.com    } else {
118e9b3f7dba0d721c60d296b09a578fbc6adaa7c63robertphillips@google.com        fModulate.reset();
1195259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    }
1205259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1215259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
122de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.comvoid GrGLShaderBuilder::setupTextureAccess(int stageNum) {
123f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    SkString retval;
1245259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
125de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    SamplerMode mode = kDefault_SamplerMode;
126de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    // FIXME: we aren't currently using Proj.
127de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    if (fVaryingDims != fCoordDims) {
128de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com        mode = kExplicitDivide_SamplerMode;
129de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    }
130de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com
131de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    switch (mode) {
1325259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        case kDefault_SamplerMode:
1335440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com            GrAssert(fVaryingDims == fCoordDims);
1345259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com            // Do nothing
1355259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com            break;
1365440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com        case kProj_SamplerMode:
137de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com            // Do nothing
1385440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com            break;
1395259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        case kExplicitDivide_SamplerMode:
1405259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com            retval = "inCoord";
1415440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com            retval.appendS32(stageNum);
1425440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com            fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
1435259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                GrGLShaderVar::TypeString
1445259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                    (GrSLFloatVectorType(fCoordDims)),
1455259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                retval.c_str(),
1465259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                fSampleCoords.c_str(),
1475259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                GrGLSLVectorNonhomogCoords(fVaryingDims),
1485259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                fSampleCoords.c_str(),
1495259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                GrGLSLVectorHomogCoord(fVaryingDims));
1505259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com            fSampleCoords = retval;
1515259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com            break;
1525259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    }
153de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com    fTexFunc = build_sampler_string(mode);
1545440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com    fComplexCoord = false;
1555259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1565259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
1575259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
1585259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                                          const char* coordName) {
1595259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    if (NULL == coordName) {
1605259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com        coordName = fSampleCoords.c_str();
1615259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    }
1625440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com    fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName);
1635259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1645259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
1655259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
1665259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com                                         const char* samplerName) {
1675259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    fFSCode.appendf("\t%s = ", outColor);
1685259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    this->emitTextureLookup(samplerName);
1695259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com    fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
1705259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com}
1715259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com
172a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comvoid GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode,
173a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                                const GrTextureAccess& textureAccess,
174a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                                const char* samplerName,
175a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                                const char* coordName) {
176a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    GrAssert(samplerName && coordName);
177a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    SkString sampler = build_sampler_string(samplerMode);
178a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    SkString swizzle = build_swizzle_string(textureAccess, fContext.caps());
179a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
180a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName,
181a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                    coordName, swizzle.c_str());
182a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
183a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
184a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comGrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
185a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com                                                               const GrGLCaps& caps) {
186a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    GrCustomStage::StageKey key = 0;
187d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com
188a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    // Assume that swizzle support implies that we never have to modify a shader to adjust
189a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    // for texture format/swizzle settings.
190a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    if (caps.textureSwizzleSupport()) {
191a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        return key;
192a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
193a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
194a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    if (texture_requires_alpha_to_red_swizzle(caps, access)) {
195a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        key = 1;
196a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    }
197a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
198a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    return key;
199a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com}
200a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
201777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.comGrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
202777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     GrSLType type,
203777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     const char* name,
204777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     int count,
205777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                                     const char** outName) {
206242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    GrAssert(name && strlen(name));
207eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
208eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    GrAssert(0 == (~kVisibilityMask & visibility));
209eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    GrAssert(0 != visibility);
210242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
211dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    BuilderUniform& uni = fUniforms.push_back();
212032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle h = index_to_handle(fUniforms.count() - 1);
213dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GR_DEBUGCODE(UniformHandle h2 =)
214dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    fUniformManager.appendUniform(type, count);
215dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
216dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    // by this function. Therefore, the handles should match.
217dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GrAssert(h2 == h);
218032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setType(type);
219032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
220777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    SkString* uniName = uni.fVariable.accessName();
221777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    if (kNonStageIdx == fCurrentStage) {
222777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        uniName->printf("u%s", name);
223777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    } else {
224777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        uniName->printf("u%s%d", name, fCurrentStage);
225242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    }
226032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVariable.setArrayCount(count);
227032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    uni.fVisibility = visibility;
228242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
229032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // If it is visible in both the VS and FS, the precision must match.
230032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // We declare a default FS precision, but not a default VS. So set the var
231032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    // to use the default FS precision.
232eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
233d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        // the fragment and vertex precisions must match
234032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
235242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    }
236242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com
237777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    if (NULL != outName) {
238777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        *outName = uni.fVariable.c_str();
239777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    }
240777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com
241032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    return h;
242032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com}
243032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
244032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comconst GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
245032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    return fUniforms[handle_to_index(u)].fVariable;
246242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com}
24723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
24823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.comvoid GrGLShaderBuilder::addVarying(GrSLType type,
24923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char* name,
25023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char** vsOutName,
25123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                                   const char** fsInName) {
25223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.push_back();
25323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.back().setType(type);
25423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
255777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    if (kNonStageIdx == fCurrentStage) {
256777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        fVSOutputs.back().accessName()->printf("v%s", name);
257777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    } else {
258777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStage);
259777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    }
26023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (vsOutName) {
26123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *vsOutName = fVSOutputs.back().getName().c_str();
26223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
26323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    // input to FS comes either from VS or GS
264f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    const SkString* fsName;
26523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (fUsesGS) {
26623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        // if we have a GS take each varying in as an array
26723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        // and output as non-array.
26823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.push_back();
26923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setType(type);
27023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
27123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSInputs.back().setUnsizedArray();
27223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
27323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.push_back();
27423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.back().setType(type);
27523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
276d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com        if (kNonStageIdx == fCurrentStage) {
277d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com            fGSOutputs.back().accessName()->printf("g%s", name);
278d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com        } else {
279d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com            fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStage);
280d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com        }
28123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fsName = fGSOutputs.back().accessName();
28223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    } else {
28323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        fsName = fVSOutputs.back().accessName();
28423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
28523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.push_back();
28623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setType(type);
28723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
28823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    fFSInputs.back().setName(*fsName);
28923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    if (fsInName) {
29023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com        *fsInName = fsName->c_str();
29123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    }
29223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com}
29323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
294a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.comvoid GrGLShaderBuilder::emitFunction(ShaderType shader,
295a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     GrSLType returnType,
296a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const char* name,
297a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     int argCnt,
298a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const GrGLShaderVar* args,
299a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     const char* body,
300a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                     SkString* outName) {
301a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    GrAssert(kFragment_ShaderType == shader);
302a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(GrGLShaderVar::TypeString(returnType));
303a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    if (kNonStageIdx != fCurrentStage) {
304a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        outName->printf(" %s_%d", name, fCurrentStage);
305a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    } else {
306a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        *outName = name;
307a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    }
308a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(*outName);
309a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append("(");
310a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    for (int i = 0; i < argCnt; ++i) {
311a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        args[i].appendDecl(fContext, &fFSFunctions);
312a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        if (i < argCnt - 1) {
313a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            fFSFunctions.append(", ");
314a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        }
315a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    }
316a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(") {\n");
317a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append(body);
318a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fFSFunctions.append("}\n\n");
319a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
32023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
321ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comnamespace {
322d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
323d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.cominline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
324d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               GrGLBinding binding,
325d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               SkString* str) {
326d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    // Desktop GLSL has added precision qualifiers but they don't do anything.
327d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    if (kES2_GrGLBinding == binding) {
328d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        switch (p) {
329d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kHigh_Precision:
330d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision highp float;\n");
331d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
332d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kMedium_Precision:
333d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision mediump float;\n");
334d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
335d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kLow_Precision:
336d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                str->append("precision lowp float;\n");
337d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                break;
338d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            case GrGLShaderVar::kDefault_Precision:
339d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                GrCrash("Default precision now allowed.");
340d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            default:
341d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                GrCrash("Unknown precision value.");
342d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com        }
343d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com    }
344d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com}
345032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com}
346d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
347032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
348ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    for (int i = 0; i < vars.count(); ++i) {
349032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        vars[i].appendDecl(fContext, out);
350a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        out->append(";\n");
351ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    }
352ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com}
353032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
354032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
355032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    for (int i = 0; i < fUniforms.count(); ++i) {
356032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        if (fUniforms[i].fVisibility & stype) {
357032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            fUniforms[i].fVariable.appendDecl(fContext, out);
358a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            out->append(";\n");
359032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        }
360032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    }
361ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com}
362ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com
363ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comvoid GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
364ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    switch (type) {
365ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kVertex_ShaderType:
366ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            *shaderStr = fHeader;
367032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
368032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fVSAttrs, shaderStr);
369032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fVSOutputs, shaderStr);
370ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fVSCode);
371ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
372ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kGeometry_ShaderType:
373ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            if (fUsesGS) {
374ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                *shaderStr = fHeader;
375ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->append(fGSHeader);
376032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                this->appendDecls(fGSInputs, shaderStr);
377032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                this->appendDecls(fGSOutputs, shaderStr);
378ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->append(fGSCode);
379ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            } else {
380ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com                shaderStr->reset();
381ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            }
382ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
383ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com        case kFragment_ShaderType:
384ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            *shaderStr = fHeader;
385d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com            append_default_precision_qualifier(kDefaultFragmentPrecision,
386d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               fContext.binding(),
387d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com                                               shaderStr);
388032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
389032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fFSInputs, shaderStr);
390ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            // We shouldn't have declared outputs on 1.10
391ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
392032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            this->appendDecls(fFSOutputs, shaderStr);
393ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fFSFunctions);
394ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            shaderStr->append(fFSCode);
395ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com            break;
396ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com    }
397ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com }
398d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com
399dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comvoid GrGLShaderBuilder::finished(GrGLuint programID) {
400dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    fUniformManager.getUniformLocations(programID, fUniforms);
401dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com}
402