16c09952db60814e0c97611ba715db21000705d09tomhudson@google.com/*
26c09952db60814e0c97611ba715db21000705d09tomhudson@google.com * Copyright 2012 Google Inc.
36c09952db60814e0c97611ba715db21000705d09tomhudson@google.com *
46c09952db60814e0c97611ba715db21000705d09tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
56c09952db60814e0c97611ba715db21000705d09tomhudson@google.com * found in the LICENSE file.
66c09952db60814e0c97611ba715db21000705d09tomhudson@google.com */
76c09952db60814e0c97611ba715db21000705d09tomhudson@google.com
86c09952db60814e0c97611ba715db21000705d09tomhudson@google.com#include "gl/GrGLShaderBuilder.h"
90878c5fc961357735119655af4aa41bbd35953b0tomhudson@google.com#include "gl/GrGLProgram.h"
10e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com#include "gl/GrGLUniformHandle.h"
118bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com#include "GrDrawEffect.h"
12069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com#include "GrTexture.h"
136c09952db60814e0c97611ba715db21000705d09tomhudson@google.com
146c09952db60814e0c97611ba715db21000705d09tomhudson@google.com// number of each input/output type in a single allocation block
15549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.comstatic const int kVarsPerBlock = 8;
166c09952db60814e0c97611ba715db21000705d09tomhudson@google.com
176c09952db60814e0c97611ba715db21000705d09tomhudson@google.com// except FS outputs where we expect 2 at most.
18549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.comstatic const int kMaxFSOutputs = 2;
196c09952db60814e0c97611ba715db21000705d09tomhudson@google.com
20e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com// ES2 FS only guarantees mediump and lowp support
21e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.comstatic const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
22e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com
23e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle;
24e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
25e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com
260ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.comnamespace {
27069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
28eee0885f22929c914788f97737061524d06284efbsalomon@google.cominline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
290ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com    if (kVec2f_GrSLType == type) {
30eee0885f22929c914788f97737061524d06284efbsalomon@google.com        return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
310ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com    } else {
320ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com        GrAssert(kVec3f_GrSLType == type);
33eee0885f22929c914788f97737061524d06284efbsalomon@google.com        return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
340ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com    }
35069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com}
36069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
37dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com/**
3803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
3903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com * present in the texture's config. swizzleComponentMask indicates the channels present in the
4003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com * shader swizzle.
41dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com */
42dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.cominline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
4303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                             uint32_t configComponentMask,
4403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                             uint32_t swizzleComponentMask) {
4503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    if (caps.textureSwizzleSupport()) {
4603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        // Any remapping is handled using texture swizzling not shader modifications.
4703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        return false;
4803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    }
4903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    // check if the texture is alpha-only
5003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    if (kA_GrColorComponentFlag == configComponentMask) {
5103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
5203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            // we must map the swizzle 'a's to 'r'.
53dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            return true;
54dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        }
5503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
5603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
5703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            // alpha-only textures smear alpha across all four channels when read.
58dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            return true;
59dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        }
60069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com    }
61dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    return false;
62dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com}
63069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
64dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.comvoid append_swizzle(SkString* outAppend,
65c3abb7baff528b64f175e08350a92a0d72ca24bebsalomon@google.com                    const GrGLShaderBuilder::TextureSampler& texSampler,
66dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com                    const GrGLCaps& caps) {
67c3abb7baff528b64f175e08350a92a0d72ca24bebsalomon@google.com    const char* swizzle = texSampler.swizzle();
68dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    char mangledSwizzle[5];
69dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com
70dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
71dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    // is available.
72c3abb7baff528b64f175e08350a92a0d72ca24bebsalomon@google.com    if (!caps.textureSwizzleSupport() &&
73c3abb7baff528b64f175e08350a92a0d72ca24bebsalomon@google.com        (kA_GrColorComponentFlag == texSampler.configComponentMask())) {
74dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        char alphaChar = caps.textureRedSupport() ? 'r' : 'a';
75dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        int i;
76dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        for (i = 0; '\0' != swizzle[i]; ++i) {
77dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            mangledSwizzle[i] = alphaChar;
78069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com        }
79dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        mangledSwizzle[i] ='\0';
80dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        swizzle = mangledSwizzle;
81069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com    }
824170fb6754377fbcbee376b918170844d4de7c79bsalomon@google.com    // For shader prettiness we omit the swizzle rather than appending ".rgba".
834170fb6754377fbcbee376b918170844d4de7c79bsalomon@google.com    if (memcmp(swizzle, "rgba", 4)) {
844170fb6754377fbcbee376b918170844d4de7c79bsalomon@google.com        outAppend->appendf(".%s", swizzle);
854170fb6754377fbcbee376b918170844d4de7c79bsalomon@google.com    }
86069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com}
87069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
880ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com}
890ff0afd5262591b0cf2b381c0767df5770ddc076bsalomon@google.com
90a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.comstatic const char kDstCopyColorName[] = "_dstColor";
91069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
9203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
93eb1f13640c7f2d770a145a9568cd1483aaba4e0etomhudson@google.com
9459034d1330e77fb7749eae61d15b6dd5900c038askia.committer@gmail.comGrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
958bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                                     GrGLUniformManager& uniformManager,
9603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                     const GrGLProgramDesc& desc)
97894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    : fUniforms(kVarsPerBlock)
98549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fVSAttrs(kVarsPerBlock)
99549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fVSOutputs(kVarsPerBlock)
100549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fGSInputs(kVarsPerBlock)
101549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fGSOutputs(kVarsPerBlock)
102549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fFSInputs(kVarsPerBlock)
103549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    , fFSOutputs(kMaxFSOutputs)
104860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com    , fCtxInfo(ctxInfo)
105f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com    , fUniformManager(uniformManager)
1064661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    , fFSFeaturesAddedMask(0)
10703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com#if GR_GL_EXPERIMENTAL_GS
10866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
10903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com#else
11003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    , fUsesGS(false)
11103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com#endif
11225c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com    , fSetupFragPosition(false)
11303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle)
11403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle)
115034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle)
11666307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
11766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com
11866307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
1193d9e74fa463118b4b3adb34571fc555ad7841397skia.committer@gmail.com
1208780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com    fPositionVar = &fVSAttrs.push_back();
1218780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com    fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
12266307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (-1 != header.fLocalCoordAttributeIndex) {
1238bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        fLocalCoordsVar = &fVSAttrs.push_back();
1248bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        fLocalCoordsVar->set(kVec2f_GrSLType,
1258bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                             GrGLShaderVar::kAttribute_TypeModifier,
1268bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                             "aLocalCoords");
1278bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    } else {
1288bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com        fLocalCoordsVar = fPositionVar;
1298bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    }
130a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    // Emit code to read the dst copy textue if necessary.
13166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com    if (kNoDstRead_DstReadKey != header.fDstReadKey &&
132a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
13366307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
13403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        const char* dstCopyTopLeftName;
13503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        const char* dstCopyCoordScaleName;
13603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        uint32_t configMask;
13766307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
13803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            configMask = kA_GrColorComponentFlag;
13903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        } else {
14003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            configMask = kRGBA_GrColorComponentFlags;
14103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        }
14203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        fDstCopySampler.init(this, configMask, "rgba", 0);
14303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com
14403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType,
14503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                  kVec2f_GrSLType,
14603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                  "DstCopyUpperLeft",
14703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                  &dstCopyTopLeftName);
14803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        fDstCopyScaleUniform     = this->addUniform(kFragment_ShaderType,
14903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                    kVec2f_GrSLType,
15003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                    "DstCopyCoordScale",
15103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                    &dstCopyCoordScaleName);
15203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        const char* fragPos = this->fragmentPosition();
15303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        this->fsCodeAppend("\t// Read color from copy of the destination.\n");
15403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
15503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                            fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
15603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        if (!topDown) {
15703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com            this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n");
15803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        }
159a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
16003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord");
16103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        this->fsCodeAppend(";\n\n");
16203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    }
16303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com}
16403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com
1654661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.combool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
1664661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    switch (feature) {
1674661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        case kStandardDerivatives_GLSLFeature:
1684661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            if (!fCtxInfo.caps()->shaderDerivativeSupport()) {
1694661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                return false;
1704661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            }
1714661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            if (kES2_GrGLBinding == fCtxInfo.binding()) {
1724661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
1734661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                                   "GL_OES_standard_derivatives");
1744661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            }
1754661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            return true;
1764661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        default:
1774661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            GrCrash("Unexpected GLSLFeature requested.");
1784661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            return false;
1794661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    }
1804661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com}
1814661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com
1824661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.combool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
1834661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    switch (feature) {
1844661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        case kFragCoordConventions_GLSLPrivateFeature:
1854661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            if (!fCtxInfo.caps()->fragCoordConventionsSupport()) {
1864661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                return false;
1874661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            }
1884661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
1894661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
1904661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                                   "GL_ARB_fragment_coord_conventions");
1914661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            }
1924661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            return true;
193a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
194a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
195a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com                return false;
196a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            }
197a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
198a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com                               "GL_EXT_shader_framebuffer_fetch");
199a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            return true;
200a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        case kNVShaderFramebufferFetch_GLSLPrivateFeature:
201a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
202a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com                return false;
203a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            }
204a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
205a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com                               "GL_NV_shader_framebuffer_fetch");
206a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com            return true;
2074661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        default:
2084661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            GrCrash("Unexpected GLSLPrivateFeature requested.");
2094661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            return false;
2104661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    }
2114661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com}
2124661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com
2134661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.comvoid GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) {
2144661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    if (!(featureBit & fFSFeaturesAddedMask)) {
2154661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        fFSExtensions.appendf("#extension %s: require\n", extensionName);
2164661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com        fFSFeaturesAddedMask |= featureBit;
2174661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    }
2184661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com}
2194661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com
2206bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.comvoid GrGLShaderBuilder::nameVariable(SkString* out, char prefix, const char* name) {
2216bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    if ('\0' == prefix) {
2226bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        *out = name;
2236bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    } else {
2246bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        out->printf("%c%s", prefix, name);
2256bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    }
2266bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    if (fCodeStage.inStageCode()) {
2276bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        if (out->endsWith('_')) {
2286bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            // Names containing "__" are reserved.
2296bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            out->append("x");
2306bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        }
2316bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        out->appendf("_Stage%d", fCodeStage.stageIndex());
2326bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    }
2336bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com}
2346bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
235a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.comconst char* GrGLShaderBuilder::dstColor() {
236dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org    if (fCodeStage.inStageCode()) {
237dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
238dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        if (!effect->willReadDstColor()) {
239dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org            GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect "
240dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org                         "did not request access.");
241dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org            return "";
242dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        }
243dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org    }
244a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    static const char kFBFetchColorName[] = "gl_LastFragData[0]";
245a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
246a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    if (GrGLCaps::kEXT_FBFetchType == fetchType) {
247a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
248a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        return kFBFetchColorName;
249a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    } else if (GrGLCaps::kNV_FBFetchType == fetchType) {
250a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
251a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        return kFBFetchColorName;
252a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    } else if (fDstCopySampler.isInitialized()) {
253a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        return kDstCopyColorName;
25403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    } else {
255dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        return "";
25603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    }
2576c09952db60814e0c97611ba715db21000705d09tomhudson@google.com}
2586c09952db60814e0c97611ba715db21000705d09tomhudson@google.com
259093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.comvoid GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) {
2604927640233ebcd54d09e2517692ada57cb69ce55sugoi@google.com    SkString* string = NULL;
261093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    switch (type) {
262093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kVertex_ShaderType:
263093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fVSCode;
264093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
265093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kGeometry_ShaderType:
266093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fGSCode;
267093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
268093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kFragment_ShaderType:
269093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fFSCode;
270093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
271093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        default:
272093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            GrCrash("Invalid shader type");
273093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    }
274093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    string->appendf(format, args);
275093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com}
276093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com
277093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.comvoid GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) {
2784927640233ebcd54d09e2517692ada57cb69ce55sugoi@google.com    SkString* string = NULL;
279093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    switch (type) {
280093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kVertex_ShaderType:
281093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fVSCode;
282093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
283093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kGeometry_ShaderType:
284093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fGSCode;
285093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
286093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        case kFragment_ShaderType:
287093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            string = &fFSCode;
288093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            break;
289093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com        default:
290093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com            GrCrash("Invalid shader type");
291093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    }
292093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    string->append(str);
293093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com}
294093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com
295a365de8bd1dd9367e5b0a12197f0f70327da2b65bsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookup(SkString* out,
296f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
297a365de8bd1dd9367e5b0a12197f0f70327da2b65bsalomon@google.com                                            const char* coordName,
298a365de8bd1dd9367e5b0a12197f0f70327da2b65bsalomon@google.com                                            GrSLType varyingType) const {
2998f0339887c862ab42e1c8ecc7c9085183fd2953cbsalomon@google.com    GrAssert(NULL != coordName);
3005c1e47ac3c2a31bd4109eb8b3c205782fe57c8b4bsalomon@google.com
301dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    out->appendf("%s(%s, %s)",
302eee0885f22929c914788f97737061524d06284efbsalomon@google.com                 sample_function_name(varyingType, fCtxInfo.glslGeneration()),
303f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com                 this->getUniformCStr(sampler.fSamplerUniform),
304dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com                 coordName);
305c3abb7baff528b64f175e08350a92a0d72ca24bebsalomon@google.com    append_swizzle(out, sampler, *fCtxInfo.caps());
3060878c5fc961357735119655af4aa41bbd35953b0tomhudson@google.com}
3070878c5fc961357735119655af4aa41bbd35953b0tomhudson@google.com
308093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookup(ShaderType type,
309093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
310093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com                                            const char* coordName,
311093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com                                            GrSLType varyingType) {
312093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    GrAssert(kFragment_ShaderType == type);
313093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType);
314093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com}
315093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com
316f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.comvoid GrGLShaderBuilder::appendTextureLookupAndModulate(
317093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com                                            ShaderType type,
318f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com                                            const char* modulation,
319f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com                                            const GrGLShaderBuilder::TextureSampler& sampler,
320f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com                                            const char* coordName,
321093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com                                            GrSLType varyingType) {
322093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com    GrAssert(kFragment_ShaderType == type);
323a365de8bd1dd9367e5b0a12197f0f70327da2b65bsalomon@google.com    SkString lookup;
324f8cea0d62e6f4bf641e300a98be14bb2da65afb5bsalomon@google.com    this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
3251c1f300d25dcc959580badd34dd9d7e8b125f573bsalomon@google.com    GrGLSLModulatef<4>(&fFSCode, modulation, lookup.c_str());
3260878c5fc961357735119655af4aa41bbd35953b0tomhudson@google.com}
3270878c5fc961357735119655af4aa41bbd35953b0tomhudson@google.com
3288780f037626b5196962a39ab76afd51f094a7765bsalomon@google.comGrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess(
3298780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com                                                            const GrTextureAccess& access,
3308780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com                                                            const GrGLCaps& caps) {
33103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
33203d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
33303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        return 1;
33403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    } else {
33503d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        return 0;
33603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    }
33703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com}
33878ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com
33903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.comGrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
34003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com                                                               const GrGLCaps& caps) {
34103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    uint32_t key = kYesDstRead_DstReadKeyBit;
342a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    if (GrGLCaps::kNone_FBFetchType != caps.fbFetchType()) {
343a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com        return key;
344a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    }
345a54574529842df79f5c41d903cfade74fc7ca5d1bsalomon@google.com    GrAssert(NULL != dstCopy);
34603d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
34703d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        // The fact that the config is alpha-only must be considered when generating code.
34803d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        key |= kUseAlphaConfig_DstReadKeyBit;
34903d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    }
35003d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
35103d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com        key |= kTopLeftOrigin_DstReadKeyBit;
352069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com    }
35303d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    GrAssert(static_cast<DstReadKey>(key) == key);
35403d5ebc1af70a1c30c7b0ac72e7f0d3311f0e97dbsalomon@google.com    return static_cast<DstReadKey>(key);
355069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com}
356069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com
357034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.comGrGLShaderBuilder::FragPosKey GrGLShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
358034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com                                                                        const GrGLCaps&) {
359034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
360034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com        return kTopLeftFragPosRead_FragPosKey;
361034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    } else {
362034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com        return kBottomLeftFragPosRead_FragPosKey;
363034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    }
364034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com}
365034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com
366034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com
367dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.comconst GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
368dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
369dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        if (caps.textureRedSupport()) {
370dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
371dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            return gRedSmear;
372dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        } else {
373dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
374dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com                                                    GR_GL_ALPHA, GR_GL_ALPHA };
375dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com            return gAlphaSmear;
376dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        }
377dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    } else {
378dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
379dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com        return gStraight;
380dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com    }
381dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com}
382dcfd55e0e0f70857010de259a44b406f746c8e3dbsalomon@google.com
383f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.comGrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
384f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com                                                                     GrSLType type,
385f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com                                                                     const char* name,
386f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com                                                                     int count,
387f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com                                                                     const char** outName) {
388bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com    GrAssert(name && strlen(name));
389afcc161571327871da95761248abefeaafed40a4humper@google.com    SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType);
390549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    GrAssert(0 == (~kVisibilityMask & visibility));
391549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    GrAssert(0 != visibility);
392bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com
393e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    BuilderUniform& uni = fUniforms.push_back();
394894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    UniformHandle h = index_to_handle(fUniforms.count() - 1);
395e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    GR_DEBUGCODE(UniformHandle h2 =)
396e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    fUniformManager.appendUniform(type, count);
397e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    // We expect the uniform manager to initially have no uniforms and that all uniforms are added
398e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    // by this function. Therefore, the handles should match.
399e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    GrAssert(h2 == h);
400894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    uni.fVariable.setType(type);
401894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
4026bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    this->nameVariable(uni.fVariable.accessName(), 'u', name);
403894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    uni.fVariable.setArrayCount(count);
404894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    uni.fVisibility = visibility;
405bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com
406894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    // If it is visible in both the VS and FS, the precision must match.
407894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    // We declare a default FS precision, but not a default VS. So set the var
408894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    // to use the default FS precision.
409549f60f1762d1629db3aabb1811365fb9731cb29bsalomon@google.com    if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
410e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com        // the fragment and vertex precisions must match
411894952f198be3090780ef2071fec83aed274bf8absalomon@google.com        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
412bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com    }
413bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com
414f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com    if (NULL != outName) {
415f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com        *outName = uni.fVariable.c_str();
416f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com    }
417f017294c5402bcd37084f94dcd514d254b937710bsalomon@google.com
418894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    return h;
419894952f198be3090780ef2071fec83aed274bf8absalomon@google.com}
420894952f198be3090780ef2071fec83aed274bf8absalomon@google.com
421894952f198be3090780ef2071fec83aed274bf8absalomon@google.comconst GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const {
422894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    return fUniforms[handle_to_index(u)].fVariable;
423bac5902a49b892ef9d7581ee02476637aec0ca2atomhudson@google.com}
4247814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com
425f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.orgbool GrGLShaderBuilder::addAttribute(GrSLType type,
426f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org                                     const char* name) {
427f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    for (int i = 0; i < fVSAttrs.count(); ++i) {
428f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        const GrGLShaderVar& attr = fVSAttrs[i];
429f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        // if attribute already added, don't add it again
430f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        if (attr.getName().equals(name)) {
431f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org            GrAssert(attr.getType() == type);
432f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org            return false;
433f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        }
434f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    }
435f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    fVSAttrs.push_back().set(type,
436f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org                             GrGLShaderVar::kAttribute_TypeModifier,
437f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org                             name);
438f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    return true;
439f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org}
440f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org
4417814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.comvoid GrGLShaderBuilder::addVarying(GrSLType type,
4427814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com                                   const char* name,
4437814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com                                   const char** vsOutName,
4447814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com                                   const char** fsInName) {
4457814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    fVSOutputs.push_back();
4467814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    fVSOutputs.back().setType(type);
447314f1bb53e527e028f9f8a7b676b8d949c8a2ebebsalomon@google.com    fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
4486bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    this->nameVariable(fVSOutputs.back().accessName(), 'v', name);
4496bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
4507814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    if (vsOutName) {
4517814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        *vsOutName = fVSOutputs.back().getName().c_str();
4527814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    }
4537814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    // input to FS comes either from VS or GS
454bfdf20d85e455c31aae4aa7800c65b149bde2cd2bsalomon@google.com    const SkString* fsName;
4557814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    if (fUsesGS) {
4567814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        // if we have a GS take each varying in as an array
4577814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        // and output as non-array.
4587814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fGSInputs.push_back();
4597814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fGSInputs.back().setType(type);
460314f1bb53e527e028f9f8a7b676b8d949c8a2ebebsalomon@google.com        fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
4617814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fGSInputs.back().setUnsizedArray();
4627814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        *fGSInputs.back().accessName() = fVSOutputs.back().getName();
4637814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fGSOutputs.push_back();
4647814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fGSOutputs.back().setType(type);
465314f1bb53e527e028f9f8a7b676b8d949c8a2ebebsalomon@google.com        fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
4666bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->nameVariable(fGSOutputs.back().accessName(), 'g', name);
4677814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fsName = fGSOutputs.back().accessName();
4687814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    } else {
4697814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        fsName = fVSOutputs.back().accessName();
4707814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    }
4717814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    fFSInputs.push_back();
4727814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    fFSInputs.back().setType(type);
473314f1bb53e527e028f9f8a7b676b8d949c8a2ebebsalomon@google.com    fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
4747814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    fFSInputs.back().setName(*fsName);
4757814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    if (fsInName) {
4767814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com        *fsInName = fsName->c_str();
4777814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com    }
4787814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com}
4797814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com
48025c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.comconst char* GrGLShaderBuilder::fragmentPosition() {
481dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org    if (fCodeStage.inStageCode()) {
482dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
483dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        if (!effect->willReadFragmentPosition()) {
484dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org            GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect "
485dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org                         "did not request access.");
486dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org            return "";
487dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org        }
488dfac782d850885a9bf2a55a51d9e802ddc0a4583commit-bot@chromium.org    }
489034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    if (fTopLeftFragPosRead) {
490034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com        if (!fSetupFragPosition) {
491034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com            fFSInputs.push_back().set(kVec4f_GrSLType,
492034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com                                      GrGLShaderVar::kIn_TypeModifier,
493034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com                                      "gl_FragCoord",
494034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com                                      GrGLShaderVar::kDefault_Precision);
495034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com            fSetupFragPosition = true;
496034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com        }
497034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com        return "gl_FragCoord";
498034620a763fbd2e2deb16aa502b257e980b3f62ebsalomon@google.com    } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
49925c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        if (!fSetupFragPosition) {
5004661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
501e13b024af858aeb5a5c71c06e81a3e7ac8840108bsalomon@google.com            fFSInputs.push_back().set(kVec4f_GrSLType,
502e13b024af858aeb5a5c71c06e81a3e7ac8840108bsalomon@google.com                                      GrGLShaderVar::kIn_TypeModifier,
503e13b024af858aeb5a5c71c06e81a3e7ac8840108bsalomon@google.com                                      "gl_FragCoord",
504e13b024af858aeb5a5c71c06e81a3e7ac8840108bsalomon@google.com                                      GrGLShaderVar::kDefault_Precision,
505e13b024af858aeb5a5c71c06e81a3e7ac8840108bsalomon@google.com                                      GrGLShaderVar::kUpperLeft_Origin);
50625c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            fSetupFragPosition = true;
50725c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        }
5082dd7052351e6c52bf0347f9adaa5b2e497914f9fskia.committer@gmail.com        return "gl_FragCoord";
50925c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com    } else {
51025c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        static const char* kCoordName = "fragCoordYDown";
51125c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        if (!fSetupFragPosition) {
5126bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            // temporarily change the stage index because we're inserting non-stage code.
5136bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
5146bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
51525c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform);
51625c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            const char* rtHeightName;
5172dd7052351e6c52bf0347f9adaa5b2e497914f9fskia.committer@gmail.com
51825c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            fRTHeightUniform = this->addUniform(kFragment_ShaderType,
51925c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com                                                kFloat_GrSLType,
52025c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com                                                "RTHeight",
52125c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com                                                &rtHeightName);
5222dd7052351e6c52bf0347f9adaa5b2e497914f9fskia.committer@gmail.com
52325c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
52425c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com                                   kCoordName, rtHeightName);
52525c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com            fSetupFragPosition = true;
52625c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        }
52725c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform);
52825c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com        return kCoordName;
52925c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com    }
53025c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com}
53125c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com
53225c5de00a3906b6f60b407a80033cf32efc13eb0bsalomon@google.com
533d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.comvoid GrGLShaderBuilder::emitFunction(ShaderType shader,
534d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     GrSLType returnType,
535d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     const char* name,
536d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     int argCnt,
537d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     const GrGLShaderVar* args,
538d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     const char* body,
539d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com                                     SkString* outName) {
540d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    GrAssert(kFragment_ShaderType == shader);
5411c1f300d25dcc959580badd34dd9d7e8b125f573bsalomon@google.com    fFSFunctions.append(GrGLSLTypeString(returnType));
5426bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    this->nameVariable(outName, '\0', name);
543314f1bb53e527e028f9f8a7b676b8d949c8a2ebebsalomon@google.com    fFSFunctions.appendf(" %s", outName->c_str());
544d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    fFSFunctions.append("(");
545d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    for (int i = 0; i < argCnt; ++i) {
546860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com        args[i].appendDecl(fCtxInfo, &fFSFunctions);
547d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com        if (i < argCnt - 1) {
548d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com            fFSFunctions.append(", ");
549d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com        }
550d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    }
551d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    fFSFunctions.append(") {\n");
552d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    fFSFunctions.append(body);
553d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com    fFSFunctions.append("}\n\n");
554d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com}
5557814ede05ce151be3880a694fbcedf376fc58e19tomhudson@google.com
55614fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.comnamespace {
557e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com
558e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.cominline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
559e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                                               GrGLBinding binding,
560e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                                               SkString* str) {
561e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com    // Desktop GLSL has added precision qualifiers but they don't do anything.
562e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com    if (kES2_GrGLBinding == binding) {
563e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com        switch (p) {
564e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            case GrGLShaderVar::kHigh_Precision:
565e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                str->append("precision highp float;\n");
566e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                break;
567e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            case GrGLShaderVar::kMedium_Precision:
568e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                str->append("precision mediump float;\n");
569e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                break;
570e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            case GrGLShaderVar::kLow_Precision:
571e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                str->append("precision lowp float;\n");
572e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                break;
573e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            case GrGLShaderVar::kDefault_Precision:
574e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                GrCrash("Default precision now allowed.");
575e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            default:
576e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                GrCrash("Unknown precision value.");
577e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com        }
578e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com    }
579e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com}
580894952f198be3090780ef2071fec83aed274bf8absalomon@google.com}
581e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com
582894952f198be3090780ef2071fec83aed274bf8absalomon@google.comvoid GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
58314fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com    for (int i = 0; i < vars.count(); ++i) {
584860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com        vars[i].appendDecl(fCtxInfo, out);
585d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com        out->append(";\n");
58614fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com    }
58714fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com}
588894952f198be3090780ef2071fec83aed274bf8absalomon@google.com
589894952f198be3090780ef2071fec83aed274bf8absalomon@google.comvoid GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const {
590894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    for (int i = 0; i < fUniforms.count(); ++i) {
591894952f198be3090780ef2071fec83aed274bf8absalomon@google.com        if (fUniforms[i].fVisibility & stype) {
592860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com            fUniforms[i].fVariable.appendDecl(fCtxInfo, out);
593d3f53a1deffc295332cb5cd8c45c15342586e5ddbsalomon@google.com            out->append(";\n");
594894952f198be3090780ef2071fec83aed274bf8absalomon@google.com        }
595894952f198be3090780ef2071fec83aed274bf8absalomon@google.com    }
59614fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com}
59714fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com
59814fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.comvoid GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
5994661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com    const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration());
6004661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com
60114fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com    switch (type) {
60214fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com        case kVertex_ShaderType:
6034661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            *shaderStr = version;
604894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendUniformDecls(kVertex_ShaderType, shaderStr);
605894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendDecls(fVSAttrs, shaderStr);
606894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendDecls(fVSOutputs, shaderStr);
6075a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com            shaderStr->append("void main() {\n");
60814fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            shaderStr->append(fVSCode);
6095a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com            shaderStr->append("}\n");
61014fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            break;
61114fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com        case kGeometry_ShaderType:
61214fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            if (fUsesGS) {
6134661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com                *shaderStr = version;
61414fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com                shaderStr->append(fGSHeader);
615894952f198be3090780ef2071fec83aed274bf8absalomon@google.com                this->appendDecls(fGSInputs, shaderStr);
616894952f198be3090780ef2071fec83aed274bf8absalomon@google.com                this->appendDecls(fGSOutputs, shaderStr);
6175a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com                shaderStr->append("void main() {\n");
61814fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com                shaderStr->append(fGSCode);
6195a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com                shaderStr->append("}\n");
62014fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            } else {
62114fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com                shaderStr->reset();
62214fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            }
62314fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            break;
62414fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com        case kFragment_ShaderType:
6254661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            *shaderStr = version;
6264661488d92dc1b477653ea8dc726debf7a6a8386bsalomon@google.com            shaderStr->append(fFSExtensions);
627e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com            append_default_precision_qualifier(kDefaultFragmentPrecision,
628860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com                                               fCtxInfo.binding(),
629e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com                                               shaderStr);
630894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendUniformDecls(kFragment_ShaderType, shaderStr);
631894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendDecls(fFSInputs, shaderStr);
63214fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            // We shouldn't have declared outputs on 1.10
633860f3b88452e3dd2cf47282f1a1527e8876d41e1robertphillips@google.com            GrAssert(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty());
634894952f198be3090780ef2071fec83aed274bf8absalomon@google.com            this->appendDecls(fFSOutputs, shaderStr);
63514fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            shaderStr->append(fFSFunctions);
6365a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com            shaderStr->append("void main() {\n");
63714fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            shaderStr->append(fFSCode);
6385a9d7b4e69bf715461bfa1d533ef184dd3d92bf7bsalomon@google.com            shaderStr->append("}\n");
63914fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com            break;
64014fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com    }
64114fbe0445e3bf24f86e05a1f58d33b184813efd4bsalomon@google.com }
642e183e55b0fbe55b54f7fabe212c4af08d6e081eabsalomon@google.com
643e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.comvoid GrGLShaderBuilder::finished(GrGLuint programID) {
644e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com    fUniformManager.getUniformLocations(programID, fUniforms);
645e00b4571a397999a5120758f947bc00e812dee82bsalomon@google.com}
64657d258a610dff47be00cdc1c075557ac38b74a10bsalomon@google.com
6476bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.comvoid GrGLShaderBuilder::emitEffects(
6486bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        const GrEffectStage* effectStages[],
6496bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        const GrBackendEffectFactory::EffectKey effectKeys[],
6506bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        int effectCnt,
6516bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        SkString* fsInOutColor,
6526bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        GrSLConstantVec* fsInOutColorKnownValue,
6536bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
6546bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                        GrGLEffect* glEffects[]) {
6556bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    bool effectEmitted = false;
6566bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6576bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    SkString inColor = *fsInOutColor;
6586bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    SkString outColor;
6596bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6606bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    for (int e = 0; e < effectCnt; ++e) {
66166307f1cfee47ae4d2a1f7dff821bdf1c0e853a8bsalomon@google.com        GrAssert(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
6626bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        const GrEffectStage& stage = *effectStages[e];
6636bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        const GrEffectRef& effect = *stage.getEffect();
6646bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6656bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
6666bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6676bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        int numTextures = effect->numTextures();
6686bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
6696bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        textureSamplers.push_back_n(numTextures);
6706bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        for (int t = 0; t < numTextures; ++t) {
6716bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            textureSamplers[t].init(this, &effect->textureAccess(t), t);
6726bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
6736bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        }
6746bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords());
6756bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6766bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        int numAttributes = stage.getVertexAttribIndexCount();
6776bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        const int* attributeIndices = stage.getVertexAttribIndices();
6786bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
6796bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        for (int a = 0; a < numAttributes; ++a) {
6806bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            // TODO: Make addAttribute mangle the name.
6816bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            SkString attributeName("aAttr");
6826bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            attributeName.appendS32(attributeIndices[a]);
6836bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            if (this->addAttribute(effect->vertexAttribType(a), attributeName.c_str())) {
6846bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                fEffectAttributes.push_back().set(attributeIndices[a], attributeName);
6856bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            }
6866bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        }
6876bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6886bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        glEffects[e] = effect->getFactory().createGLInstance(drawEffect);
6896bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
6906bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) {
6916bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            // Effects have no way to communicate zeros, they treat an empty string as ones.
6926bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            this->nameVariable(&inColor, '\0', "input");
6936bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com            this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
694f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        }
695f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org
6966bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        // create var to hold stage result
6976bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->nameVariable(&outColor, '\0', "output");
6986bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
69957d258a610dff47be00cdc1c075557ac38b74a10bsalomon@google.com
7006bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        // Enclose custom code in a block to avoid namespace conflicts
7016bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        SkString openBrace;
7026bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name());
7036bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->fVSCode.append(openBrace);
7046bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->fFSCode.append(openBrace);
7058bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com
7066bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        glEffects[e]->emitCode(this,
7076bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                               drawEffect,
7086bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                               effectKeys[e],
7096bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                               outColor.c_str(),
7106bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                               inColor.isEmpty() ? NULL : inColor.c_str(),
7116bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com                               textureSamplers);
7126bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->fVSCode.append("\t}\n");
7136bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        this->fFSCode.append("\t}\n");
71457d258a610dff47be00cdc1c075557ac38b74a10bsalomon@google.com
7156bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        inColor = outColor;
7166bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        *fsInOutColorKnownValue = kNone_GrSLConstantVec;
7176bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        effectEmitted = true;
7186bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    }
7196bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com
7206bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    if (effectEmitted) {
7216bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com        *fsInOutColor = outColor;
7226bff201a977bb0560f462d14c54602ad0e2f6797bsalomon@google.com    }
72357d258a610dff47be00cdc1c075557ac38b74a10bsalomon@google.com}
724f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org
725f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.orgconst SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
726f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    const AttributePair* attribEnd = this->getEffectAttributes().end();
727010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com    for (const AttributePair* attrib = this->getEffectAttributes().begin();
728f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org         attrib != attribEnd;
729f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org         ++attrib) {
730f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        if (attrib->fIndex == attributeIndex) {
731f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org            return &attrib->fName;
732f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org        }
733010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com    }
734f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org
735f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org    return NULL;
736f7c3ed0aee438c87cdfd7fcd09e558d96f507cc0commit-bot@chromium.org}
737