11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrGLProgram.h"
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "../GrAllocator.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrGLShaderVar.h"
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkTrace.h"
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkXfermode.h"
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerenum {
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /// Used to mark a StageUniLocation field that should be bound
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /// to a uniform during getUniformLocationsAndInitCache().
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kUseUniform = 2000
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}  // namespace
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define PRINT_SHADERS 0
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef GrTAllocator<GrGLShaderVar> VarArray;
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// number of each input/output type in a single allocation block
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int gVarsPerBlock = 8;
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// except FS outputs where we expect 2 at most.
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const int gMaxFSOutputs = 2;
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstruct ShaderCodeSegments {
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ShaderCodeSegments()
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    : fVSUnis(gVarsPerBlock)
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fVSAttrs(gVarsPerBlock)
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fVSOutputs(gVarsPerBlock)
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fGSInputs(gVarsPerBlock)
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fGSOutputs(gVarsPerBlock)
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fFSInputs(gVarsPerBlock)
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fFSUnis(gVarsPerBlock)
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fFSOutputs(gMaxFSOutputs)
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fUsesGS(false) {}
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fHeader; // VS+FS, GLSL version, etc
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fVSUnis;
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fVSAttrs;
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fVSOutputs;
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fGSInputs;
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fGSOutputs;
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fFSInputs;
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fGSHeader; // layout qualifiers specific to GS
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fFSUnis;
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    VarArray        fFSOutputs;
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fFSFunctions;
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fVSCode;
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fGSCode;
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fFSCode;
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool            fUsesGS;
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_GL_ATTRIBUTE_MATRICES
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define VIEW_MATRIX_NAME "aViewM"
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define VIEW_MATRIX_NAME "uViewM"
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define POS_ATTR_NAME "aPosition"
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COL_ATTR_NAME "aColor"
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COV_ATTR_NAME "aCoverage"
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define EDGE_ATTR_NAME "aEdge"
771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COL_UNI_NAME "uColor"
784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define COV_UNI_NAME "uCoverage"
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define EDGES_UNI_NAME "uEdges"
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COL_FILTER_UNI_NAME "uColorFilter"
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COL_MATRIX_UNI_NAME "uColorMatrix"
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define COL_MATRIX_VEC_UNI_NAME "uColorMatrixVec"
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "aTexCoord";
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(coordIdx);
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline GrGLShaderVar::Type float_vector_type(int count) {
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GR_STATIC_ASSERT(GrGLShaderVar::kFloat_Type == 0);
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GR_STATIC_ASSERT(GrGLShaderVar::kVec2f_Type == 1);
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GR_STATIC_ASSERT(GrGLShaderVar::kVec3f_Type == 2);
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GR_STATIC_ASSERT(GrGLShaderVar::kVec4f_Type == 3);
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count > 0 && count <= 4);
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return (GrGLShaderVar::Type)(count - 1);
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* float_vector_type_str(int count) {
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return GrGLShaderVar::TypeString(float_vector_type(count));
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* vector_homog_coord(int count) {
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return HOMOGS[count];
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* vector_nonhomog_coords(int count) {
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return NONHOMOGS[count];
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* vector_all_coords(int count) {
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ALL[count];
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* all_ones_vec(int count) {
1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    "vec3(1,1,1)", "vec4(1,1,1,1)"};
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ONESVEC[count];
1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* all_zeros_vec(int count) {
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    "vec3(0,0,0)", "vec4(0,0,0,0)"};
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ZEROSVEC[count];
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* declared_color_output_name() { return "fsColorOut"; }
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline const char* dual_source_output_name() { return "dualSourceOut"; }
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void tex_matrix_name(int stage, GrStringBuilder* s) {
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_GL_ATTRIBUTE_MATRICES
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "aTexM";
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "uTexM";
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(stage);
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void normalized_texel_size_name(int stage, GrStringBuilder* s) {
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "uTexelSize";
1491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(stage);
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void sampler_name(int stage, GrStringBuilder* s) {
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "uSampler";
1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(stage);
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void radial2_param_name(int stage, GrStringBuilder* s) {
1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "uRadial2Params";
1591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(stage);
1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) {
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *k = "uKernel";
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    k->appendS32(stage);
1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *i = "uImageIncrement";
1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    i->appendS32(stage);
1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerinline void image_increment_param_name(int stage, GrStringBuilder* i) {
1704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    *i = "uImageIncrement";
1714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    i->appendS32(stage);
1724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void tex_domain_name(int stage, GrStringBuilder* s) {
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *s = "uTexDom";
1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    s->appendS32(stage);
1771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1801cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrGLProgram::GrGLProgram() {
1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1831cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrGLProgram::~GrGLProgram() {
1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                GrBlendCoeff* dstCoeff) const {
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (fProgramDesc.fDualSrcOutput) {
1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case ProgramDesc::kNone_DualSrcOutput:
1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // the prog will write a coverage value to the secondary
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // output and the dst is blended by one minus that value.
1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case ProgramDesc::kCoverage_DualSrcOutput:
1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case ProgramDesc::kCoverageISA_DualSrcOutput:
1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case ProgramDesc::kCoverageISC_DualSrcOutput:
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_BlendCoeff;
1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        default:
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrCrash("Unexpected dual source blend output");
2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// assigns modulation of two vars to an output var
2051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// vars can be vec4s or floats (or one of each)
2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// result is always vec4
2071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// if either var is "" then assign to the other var
2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// if both are "" then assign all ones
2091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline void modulate_helper(const char* outputVar,
2101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   const char* var0,
2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   const char* var1,
2121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   GrStringBuilder* code) {
2131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != outputVar);
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != var0);
2151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != var1);
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != code);
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool has0 = '\0' != *var0;
2191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool has1 = '\0' != *var1;
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!has0 && !has1) {
2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = %s;\n", outputVar, all_ones_vec(4));
2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (!has0) {
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (!has1) {
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
2271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
2281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s * %s);\n", outputVar, var0, var1);
2291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// assigns addition of two vars to an output var
2331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// vars can be vec4s or floats (or one of each)
2341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// result is always vec4
2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// if either var is "" then assign to the other var
2361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// if both are "" then assign all zeros
2371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline void add_helper(const char* outputVar,
2381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const char* var0,
2391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const char* var1,
2401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              GrStringBuilder* code) {
2411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != outputVar);
2421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != var0);
2431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != var1);
2441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(NULL != code);
2451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool has0 = '\0' != *var0;
2471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool has1 = '\0' != *var1;
2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!has0 && !has1) {
2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = %s;\n", outputVar, all_zeros_vec(4));
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (!has0) {
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (!has1) {
2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        code->appendf("\t%s = vec4(%s + %s);\n", outputVar, var0, var1);
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// given two blend coeffecients determine whether the src
2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// and/or dst computation can be omitted.
2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline void needBlendInputs(SkXfermode::Coeff srcCoeff,
2631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkXfermode::Coeff dstCoeff,
2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   bool* needSrcValue,
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   bool* needDstValue) {
2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkXfermode::kZero_Coeff == srcCoeff) {
2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (dstCoeff) {
2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // these all read the src
2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSC_Coeff:
2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kISC_Coeff:
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSA_Coeff:
2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kISA_Coeff:
2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                *needSrcValue = true;
2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                *needSrcValue = false;
2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *needSrcValue = true;
2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkXfermode::kZero_Coeff == dstCoeff) {
2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (srcCoeff) {
2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // these all read the dst
2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDC_Coeff:
2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kIDC_Coeff:
2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDA_Coeff:
2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kIDA_Coeff:
2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                *needDstValue = true;
2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                *needDstValue = false;
2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
2951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
2961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *needDstValue = true;
2971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/**
3011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Create a blend_coeff * value string to be used in shader code. Sets empty
3021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * string if result is trivially zero.
3031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
3041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void blendTermString(GrStringBuilder* str, SkXfermode::Coeff coeff,
3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const char* src, const char* dst,
3061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const char* value) {
3071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (coeff) {
3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kZero_Coeff:    /** 0 */
3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *str = "";
3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kOne_Coeff:     /** 1 */
3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *str = value;
3131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kSC_Coeff:
3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("(%s * %s)", src, value);
3161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kISC_Coeff:
3181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("((%s - %s) * %s)", all_ones_vec(4), src, value);
3191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kDC_Coeff:
3211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("(%s * %s)", dst, value);
3221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kIDC_Coeff:
3241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("((%s - %s) * %s)", all_ones_vec(4), dst, value);
3251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kSA_Coeff:      /** src alpha */
3271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("(%s.a * %s)", src, value);
3281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("((1.0 - %s.a) * %s)", src, value);
3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kDA_Coeff:      /** dst alpha */
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("(%s.a * %s)", dst, value);
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
3361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        str->printf("((1.0 - %s.a) * %s)", dst, value);
3371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    default:
3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrCrash("Unexpected xfer coeff.");
3401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
3411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/**
3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Adds a line to the fragment shader code which modifies the color by
3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * the specified color filter.
3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void addColorFilter(GrStringBuilder* fsCode, const char * outputVar,
3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           SkXfermode::Coeff uniformCoeff,
3491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           SkXfermode::Coeff colorCoeff,
3501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const char* inColor) {
3511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder colorStr, constStr;
3521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    blendTermString(&colorStr, colorCoeff, COL_FILTER_UNI_NAME,
3531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    inColor, inColor);
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    blendTermString(&constStr, uniformCoeff, COL_FILTER_UNI_NAME,
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    inColor, COL_FILTER_UNI_NAME);
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
3581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/**
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Adds code to the fragment shader code which modifies the color by
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * the specified color matrix.
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void addColorMatrix(GrStringBuilder* fsCode, const char * outputVar,
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const char* inColor) {
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fsCode->appendf("\t%s = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n", outputVar, COL_MATRIX_UNI_NAME, inColor, inColor, inColor, COL_MATRIX_VEC_UNI_NAME);
3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fsCode->appendf("\t%s.rgb *= %s.a;\n", outputVar, outputVar);
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// Adds a var that is computed in the VS and read in FS.
3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// If there is a GS it will just pass it through.
3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid append_varying(GrGLShaderVar::Type type,
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char* name,
3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    ShaderCodeSegments* segments,
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char** vsOutName = NULL,
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char** fsInName = NULL) {
3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSOutputs.push_back();
3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSOutputs.back().setType(type);
3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSOutputs.back().setTypeModifier(
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kOut_TypeModifier);
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSOutputs.back().accessName()->printf("v%s", name);
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (vsOutName) {
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *vsOutName = segments->fVSOutputs.back().getName().c_str();
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // input to FS comes either from VS or GS
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrStringBuilder* fsName;
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (segments->fUsesGS) {
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // if we have a GS take each varying in as an array
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // and output as non-array.
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSInputs.push_back();
3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSInputs.back().setType(type);
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSInputs.back().setTypeModifier(
3941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLShaderVar::kIn_TypeModifier);
3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSInputs.back().setUnsizedArray();
3961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *segments->fGSInputs.back().accessName() =
3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fVSOutputs.back().getName();
3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSOutputs.push_back();
3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSOutputs.back().setType(type);
4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSOutputs.back().setTypeModifier(
4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLShaderVar::kOut_TypeModifier);
4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSOutputs.back().accessName()->printf("g%s", name);
4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fsName = segments->fGSOutputs.back().accessName();
4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fsName = segments->fVSOutputs.back().accessName();
4061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSInputs.push_back();
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSInputs.back().setType(type);
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSInputs.back().setTypeModifier(
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kIn_TypeModifier);
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSInputs.back().setName(*fsName);
4121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fsInName) {
4131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *fsInName = fsName->c_str();
4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// version of above that adds a stage number to the
4181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// the var name (for uniqueness)
4191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid append_varying(GrGLShaderVar::Type type,
4201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char* name,
4211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    int stageNum,
4221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    ShaderCodeSegments* segments,
4231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char** vsOutName = NULL,
4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    const char** fsInName = NULL) {
4251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder nameWithStage(name);
4261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    nameWithStage.appendS32(stageNum);
4271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_varying(type, nameWithStage.c_str(), segments, vsOutName, fsInName);
4281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
4321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  GrVertexLayout layout,
4331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  CachedData* programData,
4341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  GrStringBuilder* coverageVar,
4351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  ShaderCodeSegments* segments) const {
4361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fProgramDesc.fEdgeAANumEdges > 0) {
4371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec3f_Type,
4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                          GrGLShaderVar::kUniform_TypeModifier,
4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                          EDGES_UNI_NAME,
4401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                          fProgramDesc.fEdgeAANumEdges);
4411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fUniLocations.fEdgesUni = kUseUniform;
4421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int count = fProgramDesc.fEdgeAANumEdges;
4431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSCode.append(
4441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            "\tvec3 pos = vec3(gl_FragCoord.xy, 1);\n");
4451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = 0; i < count; i++) {
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append("\tfloat a");
4471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendS32(i);
4481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append(" = clamp(dot(" EDGES_UNI_NAME "[");
4491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendS32(i);
4501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append("], pos), 0.0, 1.0);\n");
4511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (fProgramDesc.fEdgeAAConcave && (count & 0x01) == 0) {
4531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // For concave polys, we consider the edges in pairs.
4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSFunctions.append("float cross2(vec2 a, vec2 b) {\n");
4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSFunctions.append("\treturn dot(a, vec2(b.y, -b.x));\n");
4561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSFunctions.append("}\n");
4571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int i = 0; i < count; i += 2) {
4581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("\tfloat eb%d;\n", i / 2);
4591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("\tif (cross2(" EDGES_UNI_NAME "[%d].xy, " EDGES_UNI_NAME "[%d].xy) < 0.0) {\n", i, i + 1);
4601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("\t\teb%d = a%d * a%d;\n", i / 2, i, i + 1);
4611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.append("\t} else {\n");
4621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("\t\teb%d = a%d + a%d - a%d * a%d;\n", i / 2, i, i + 1, i, i + 1);
4631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.append("\t}\n");
4641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append("\tfloat edgeAlpha = ");
4661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int i = 0; i < count / 2 - 1; i++) {
4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("min(eb%d, ", i);
4681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("eb%d", count / 2 - 1);
4701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int i = 0; i < count / 2 - 1; i++) {
4711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.append(")");
4721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append(";\n");
4741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
4751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append("\tfloat edgeAlpha = ");
4761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int i = 0; i < count - 1; i++) {
4771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.appendf("min(a%d * a%d, ", i, i + 1);
4781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("a%d * a0", count - 1);
4801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (int i = 0; i < count - 1; i++) {
4811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fFSCode.append(")");
4821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
4831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.append(";\n");
4841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *coverageVar = "edgeAlpha";
4861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else  if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
4871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const char *vsName, *fsName;
4881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        append_varying(GrGLShaderVar::kVec4f_Type, "Edge", segments,
4891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            &vsName, &fsName);
4901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
4911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
4921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
4931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (GrDrawState::kHairLine_EdgeType == fProgramDesc.fVertexEdgeType) {
4941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
4954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
4964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else if (GrDrawState::kQuad_EdgeType == fProgramDesc.fVertexEdgeType) {
4974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append("\tfloat edgeAlpha;\n");
4984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // keep the derivative instructions outside the conditional
4994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
5004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
5014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
5024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // today we know z and w are in device space. We could use derivatives
5034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
5044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append ("\t} else {\n");
5054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
5064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
5074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      fsName, fsName);
5084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
5094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
5104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      "\t}\n");
5114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (kES2_GrGLBinding == gl.binding()) {
5124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
5134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
5141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
5151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrAssert(GrDrawState::kHairQuad_EdgeType == fProgramDesc.fVertexEdgeType);
5161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
5171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
5184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
5194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
5204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      fsName, fsName);
5211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
5224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
5234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
5244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (kES2_GrGLBinding == gl.binding()) {
5251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
5261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
5271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
5281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *coverageVar = "edgeAlpha";
5291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
5301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        coverageVar->reset();
5311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
5351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
5371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   GrGLProgram::CachedData* programData,
5381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   ShaderCodeSegments* segments,
5391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   GrStringBuilder* inColor) {
5401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (colorInput) {
5411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
5421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
5431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrGLShaderVar::kAttribute_TypeModifier,
5441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                COL_ATTR_NAME);
5451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            const char *vsName, *fsName;
5461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            append_varying(GrGLShaderVar::kVec4f_Type, "Color", segments, &vsName, &fsName);
5471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
5481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            *inColor = fsName;
5491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } break;
5501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case GrGLProgram::ProgramDesc::kUniform_ColorInput:
5511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
5521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrGLShaderVar::kUniform_TypeModifier,
5531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                COL_UNI_NAME);
5541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            programData->fUniLocations.fColorUni = kUseUniform;
5551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            *inColor = COL_UNI_NAME;
5561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
5571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case GrGLProgram::ProgramDesc::kTransBlack_ColorInput:
5581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrAssert(!"needComputedColor should be false.");
5591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
5601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput:
5611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
5621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        default:
5631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrCrash("Unknown color type.");
5641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;
5651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid genAttributeCoverage(ShaderCodeSegments* segments,
5694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          GrStringBuilder* inOutCoverage) {
5704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
5711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       GrGLShaderVar::kAttribute_TypeModifier,
5721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       COV_ATTR_NAME);
5731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char *vsName, *fsName;
5744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_varying(GrGLShaderVar::kVec4f_Type, "Coverage",
5751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   segments, &vsName, &fsName);
5761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
5774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (inOutCoverage->size()) {
5784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
5794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  fsName, inOutCoverage->c_str());
5804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        *inOutCoverage = "attrCoverage";
5811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
5824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        *inOutCoverage = fsName;
5834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid genUniformCoverage(ShaderCodeSegments* segments,
5874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrGLProgram::CachedData* programData,
5884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrStringBuilder* inOutCoverage) {
5894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
5904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      GrGLShaderVar::kUniform_TypeModifier,
5914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      COV_UNI_NAME);
5924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    programData->fUniLocations.fCoverageUni = kUseUniform;
5934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (inOutCoverage->size()) {
5944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
5954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  COV_UNI_NAME, inOutCoverage->c_str());
5964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        *inOutCoverage = "uniCoverage";
5974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else {
5984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        *inOutCoverage = COV_UNI_NAME;
5991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
6051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    ShaderCodeSegments* segments) const {
6061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_GL_EXPERIMENTAL_GS
6071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fProgramDesc.fExperimentalGS) {
6084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
6091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSHeader.append("layout(triangles) in;\n"
6101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   "layout(triangle_strip, max_vertices = 6) out;\n");
6111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSCode.append("void main() {\n"
6121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 "\tfor (int i = 0; i < 3; ++i) {\n"
6131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  "\t\tgl_Position = gl_in[i].gl_Position;\n");
6141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (this->fProgramDesc.fEmitsPointSize) {
6151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
6161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
6181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int count = segments->fGSInputs.count();
6191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = 0; i < count; ++i) {
6201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fGSCode.appendf("\t\t%s = %s[i];\n",
6211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      segments->fGSOutputs[i].getName().c_str(),
6221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      segments->fGSInputs[i].getName().c_str());
6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fGSCode.append("\t\tEmitVertex();\n"
6251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 "\t}\n"
6261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 "\tEndPrimitive();\n"
6271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 "}\n");
6281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
6301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst char* GrGLProgram::adjustInColor(const GrStringBuilder& inColor) const {
6331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (inColor.size()) {
6341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger          return inColor.c_str();
6351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
6361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) {
6371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return all_ones_vec(4);
6381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
6391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return all_zeros_vec(4);
6401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
6454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool GrGLProgram::genProgram(const GrGLContextInfo& gl,
6461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             GrGLProgram::CachedData* programData) const {
6471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ShaderCodeSegments segments;
6491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const uint32_t& layout = fProgramDesc.fVertexLayout;
6501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fUniLocations.reset();
6521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_GL_EXPERIMENTAL_GS
6541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fUsesGS = fProgramDesc.fExperimentalGS;
6551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
6561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkXfermode::Coeff colorCoeff, uniformCoeff;
6584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled);
6591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // The rest of transfer mode color filters have not been implemented
6601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
6611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GR_DEBUGCODE(bool success =)
6621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
6631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    (fProgramDesc.fColorFilterXfermode),
6641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    &uniformCoeff, &colorCoeff);
6651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GR_DEBUGASSERT(success);
6661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
6671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        colorCoeff = SkXfermode::kOne_Coeff;
6681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        uniformCoeff = SkXfermode::kZero_Coeff;
6691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // no need to do the color filter / matrix at all if coverage is 0. The
6724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // output color is scaled by the coverage. All the dual source outputs are
6734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // scaled by the coverage as well.
6744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) {
6754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        colorCoeff = SkXfermode::kZero_Coeff;
6764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        uniformCoeff = SkXfermode::kZero_Coeff;
6774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        applyColorMatrix = false;
6784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
6794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
6801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // If we know the final color is going to be all zeros then we can
6811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // simplify the color filter coeffecients. needComputedColor will then
6821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // come out false below.
6831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) {
6841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        colorCoeff = SkXfermode::kZero_Coeff;
6851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (SkXfermode::kDC_Coeff == uniformCoeff ||
6861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkXfermode::kDA_Coeff == uniformCoeff) {
6871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            uniformCoeff = SkXfermode::kZero_Coeff;
6881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else if (SkXfermode::kIDC_Coeff == uniformCoeff ||
6891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   SkXfermode::kIDA_Coeff == uniformCoeff) {
6901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            uniformCoeff = SkXfermode::kOne_Coeff;
6911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool needColorFilterUniform;
6951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool needComputedColor;
6961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    needBlendInputs(uniformCoeff, colorCoeff,
6971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    &needColorFilterUniform, &needComputedColor);
6981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // the dual source output has no canonical var name, have to
7001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // declare an output, which is incompatible with gl_FragColor/gl_FragData.
7011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool dualSourceOutputWritten = false;
7024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments.fHeader.printf(GrGetGLSLVersionDecl(gl.binding(),
7034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                                 gl.glslGeneration()));
7044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
7054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrGLShaderVar colorOutput;
7064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool isColorDeclared = GrGLSLSetupFSColorOuput(gl.glslGeneration(),
7074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                                   declared_color_output_name(),
7084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                                   &colorOutput);
7094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (isColorDeclared) {
7104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments.fFSOutputs.push_back(colorOutput);
7114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
7121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_GL_ATTRIBUTE_MATRICES
7141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fVSAttrs.push_back().set(GrGLShaderVar::kMat33f_Type,
7151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kAttribute_TypeModifier, VIEW_MATRIX_NAME);
7161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fUniLocations.fViewMatrixUni = kSetAsAttribute;
7171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
7181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fVSUnis.push_back().set(GrGLShaderVar::kMat33f_Type,
7191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kUniform_TypeModifier, VIEW_MATRIX_NAME);
7201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fUniLocations.fViewMatrixUni = kUseUniform;
7211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
7221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
7231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kAttribute_TypeModifier, POS_ATTR_NAME);
7241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fVSCode.append(
7261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        "void main() {\n"
7271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3("POS_ATTR_NAME", 1);\n"
7281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n");
7291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // incoming color to current stage being processed.
7311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder inColor;
7321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (needComputedColor) {
7341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput,
7351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      programData, &segments, &inColor);
7361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // we output point size in the GS if present
7391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fProgramDesc.fEmitsPointSize && !segments.fUsesGS){
7401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments.fVSCode.append("\tgl_PointSize = 1.0;\n");
7411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fFSCode.append("void main() {\n");
7441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // add texture coordinates that are used to the list of vertex attr decls
7461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder texCoordAttrs[GrDrawState::kMaxTexCoords];
7471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
7481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
7491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            tex_attr_name(t, texCoordAttrs + t);
7501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec2f_Type,
7511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrGLShaderVar::kAttribute_TypeModifier,
7521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                texCoordAttrs[t].c_str());
7531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
7541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
7571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // compute the final color
7581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if we have color stages string them together, feeding the output color
7601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // of each to the next and generating code for each stage.
7611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (needComputedColor) {
7621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder outColor;
7631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) {
7641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (fProgramDesc.fStages[s].isEnabled()) {
7651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                // create var to hold stage result
7661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                outColor = "color";
7671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                outColor.appendS32(s);
7681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
7691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                const char* inCoords;
7711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                // figure out what our input coords are
7721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) &
7731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    layout) {
7741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    inCoords = POS_ATTR_NAME;
7751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                } else {
7761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
7771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                     // we better have input tex coordinates if stage is enabled.
7781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    GrAssert(tcIdx >= 0);
7791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    GrAssert(texCoordAttrs[tcIdx].size());
7801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    inCoords = texCoordAttrs[tcIdx].c_str();
7811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
7821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                this->genStageCode(gl,
7841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   s,
7851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   fProgramDesc.fStages[s],
7861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   inColor.size() ? inColor.c_str() : NULL,
7871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   outColor.c_str(),
7881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   inCoords,
7891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   &segments,
7901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   &programData->fUniLocations.fStages[s]);
7911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                inColor = outColor;
7921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
7931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
7941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if have all ones or zeros for the "dst" input to the color filter then we
7971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // may be able to make additional optimizations.
7981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (needColorFilterUniform && needComputedColor && !inColor.size()) {
7991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput);
8001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
8011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  SkXfermode::kIDA_Coeff == uniformCoeff;
8021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (uniformCoeffIsZero) {
8031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            uniformCoeff = SkXfermode::kZero_Coeff;
8041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            bool bogus;
8051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff,
8061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            &needColorFilterUniform, &bogus);
8071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
8081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (needColorFilterUniform) {
8101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
8111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         GrGLShaderVar::kUniform_TypeModifier,
8121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         COL_FILTER_UNI_NAME);
8131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fUniLocations.fColorFilterUni = kUseUniform;
8141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool wroteFragColorZero = false;
8161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkXfermode::kZero_Coeff == uniformCoeff &&
8171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkXfermode::kZero_Coeff == colorCoeff &&
8184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        !applyColorMatrix) {
8191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments.fFSCode.appendf("\t%s = %s;\n",
8204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 colorOutput.getName().c_str(),
8211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 all_zeros_vec(4));
8221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        wroteFragColorZero = true;
8231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) {
8244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments.fFSCode.append("\tvec4 filteredColor;\n");
8251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const char* color = adjustInColor(inColor);
8261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        addColorFilter(&segments.fFSCode, "filteredColor", uniformCoeff,
8271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       colorCoeff, color);
8281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        inColor = "filteredColor";
8291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (applyColorMatrix) {
8311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments.fFSUnis.push_back().set(GrGLShaderVar::kMat44f_Type,
8321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         GrGLShaderVar::kUniform_TypeModifier,
8331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         COL_MATRIX_UNI_NAME);
8341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
8351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         GrGLShaderVar::kUniform_TypeModifier,
8361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         COL_MATRIX_VEC_UNI_NAME);
8371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fUniLocations.fColorMatrixUni = kUseUniform;
8381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fUniLocations.fColorMatrixVecUni = kUseUniform;
8394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments.fFSCode.append("\tvec4 matrixedColor;\n");
8401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const char* color = adjustInColor(inColor);
8411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        addColorMatrix(&segments.fFSCode, "matrixedColor", color);
8421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        inColor = "matrixedColor";
8431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
8461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // compute the partial coverage (coverage stages and edge aa)
8471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder inCoverage;
8494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput ==
8504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                          fProgramDesc.fCoverageInput;
8511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // we don't need to compute coverage at all if we know the final shader
8521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // output will be zero and we don't have a dual src blend output.
8531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!wroteFragColorZero ||
8541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
8551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (!coverageIsZero) {
8574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            this->genEdgeCoverage(gl,
8584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  layout,
8594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  programData,
8604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  &inCoverage,
8614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  &segments);
8624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
8634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            switch (fProgramDesc.fCoverageInput) {
8644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                case ProgramDesc::kSolidWhite_ColorInput:
8654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    // empty string implies solid white
8664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    break;
8674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                case ProgramDesc::kAttribute_ColorInput:
8684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    genAttributeCoverage(&segments, &inCoverage);
8694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    break;
8704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                case ProgramDesc::kUniform_ColorInput:
8714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    genUniformCoverage(&segments, programData, &inCoverage);
8724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    break;
8734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                default:
8744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GrCrash("Unexpected input coverage.");
8754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
8761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GrStringBuilder outCoverage;
8784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            const int& startStage = fProgramDesc.fFirstCoverageStage;
8794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
8804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                if (fProgramDesc.fStages[s].isEnabled()) {
8814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    // create var to hold stage output
8824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    outCoverage = "coverage";
8834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    outCoverage.appendS32(s);
8844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    segments.fFSCode.appendf("\tvec4 %s;\n",
8854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                             outCoverage.c_str());
8864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
8874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    const char* inCoords;
8884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    // figure out what our input coords are
8894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) &
8904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        layout) {
8914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        inCoords = POS_ATTR_NAME;
8924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    } else {
8934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        int tcIdx =
8944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GrDrawTarget::VertexTexCoordsForStage(s, layout);
8954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        // we better have input tex coordinates if stage is
8964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        // enabled.
8974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrAssert(tcIdx >= 0);
8984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        GrAssert(texCoordAttrs[tcIdx].size());
8994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        inCoords = texCoordAttrs[tcIdx].c_str();
9004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    }
9011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    genStageCode(gl, s,
9034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 fProgramDesc.fStages[s],
9044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 inCoverage.size() ? inCoverage.c_str() : NULL,
9054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 outCoverage.c_str(),
9064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 inCoords,
9074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 &segments,
9084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                 &programData->fUniLocations.fStages[s]);
9094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    inCoverage = outCoverage;
9101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
9111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
9121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
9131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
9141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments.fFSOutputs.push_back().set(GrGLShaderVar::kVec4f_Type,
9151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrGLShaderVar::kOut_TypeModifier,
9161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dual_source_output_name());
9174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            bool outputIsZero = coverageIsZero;
9181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrStringBuilder coeff;
9194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (!outputIsZero &&
9204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                ProgramDesc::kCoverage_DualSrcOutput !=
9211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
9221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (!inColor.size()) {
9231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    outputIsZero = true;
9241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                } else {
9251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    if (fProgramDesc.fDualSrcOutput ==
9261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        ProgramDesc::kCoverageISA_DualSrcOutput) {
9271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        coeff.printf("(1 - %s.a)", inColor.c_str());
9281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    } else {
9291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
9301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    }
9311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
9321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
9331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (outputIsZero) {
9341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                segments.fFSCode.appendf("\t%s = %s;\n",
9351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         dual_source_output_name(),
9361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         all_zeros_vec(4));
9371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else {
9381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                modulate_helper(dual_source_output_name(),
9391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                coeff.c_str(),
9401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                inCoverage.c_str(),
9411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                &segments.fFSCode);
9421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
9431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dualSourceOutputWritten = true;
9441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
9451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
9481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // combine color and coverage as frag color
9491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!wroteFragColorZero) {
9514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (coverageIsZero) {
9524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments.fFSCode.appendf("\t%s = %s;\n",
9534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                     colorOutput.getName().c_str(),
9544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                     all_zeros_vec(4));
9554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else {
9564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            modulate_helper(colorOutput.getName().c_str(),
9574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            inColor.c_str(),
9584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            inCoverage.c_str(),
9594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            &segments.fFSCode);
9604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
9614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig ==
9624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fProgramDesc.fOutputConfig) {
9634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
9644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str());
9694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig ==
9704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                   fProgramDesc.fOutputConfig) {
9714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
9724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str(),
9764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        colorOutput.getName().c_str());
9771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
9781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fVSCode.append("}\n");
9811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments.fFSCode.append("}\n");
9821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
9841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // insert GS
9851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_DEBUG
9864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    this->genGeometryShader(gl, &segments);
9871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
9881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
9901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // compile and setup attribs and unis
9911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!CompileShaders(gl, segments, programData)) {
9931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
9941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs,
9971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                isColorDeclared,
9981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                dualSourceOutputWritten,
9991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                programData)) {
10001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
10011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->getUniformLocationsAndInitCache(gl, programData);
10041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
10061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
10091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void expand_decls(const VarArray& vars,
10114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         const GrGLContextInfo& gl,
10124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         GrStringBuilder* string) {
10131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int count = vars.count();
10141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < count; ++i) {
10154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        vars[i].appendDecl(gl, string);
10161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void print_shader(int stringCnt,
10201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         const char** strings,
10211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         int* stringLengths) {
10221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < stringCnt; ++i) {
10231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL == stringLengths || stringLengths[i] < 0) {
10241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrPrintf(strings[i]);
10251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
10261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrPrintf("%.*s", stringLengths[i], strings[i]);
10271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
10281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef SkTArray<const char*, true>         StrArray;
10321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define PREALLOC_STR_ARRAY(N) SkSTArray<(N), const char*, true>
10331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef SkTArray<int, true>                 LengthArray;
10351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define PREALLOC_LENGTH_ARRAY(N) SkSTArray<(N), int, true>
10361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// these shouldn't relocate
10381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef GrTAllocator<GrStringBuilder>       TempArray;
10391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define PREALLOC_TEMP_ARRAY(N) GrSTAllocator<(N), GrStringBuilder>
10401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void append_string(const GrStringBuilder& str,
10421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          StrArray* strings,
10431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          LengthArray* lengths) {
10441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int length = (int) str.size();
10451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (length) {
10461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        strings->push_back(str.c_str());
10471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        lengths->push_back(length);
10481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(strings->count() == lengths->count());
10501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerinline void append_decls(const VarArray& vars,
10534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         const GrGLContextInfo& gl,
10541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         StrArray* strings,
10551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         LengthArray* lengths,
10564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         TempArray* temp) {
10574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    expand_decls(vars, gl, &temp->push_back());
10581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(temp->back(), strings, lengths);
10591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool GrGLProgram::CompileShaders(const GrGLContextInfo& gl,
10641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 const ShaderCodeSegments& segments,
10651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 CachedData* programData) {
10661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    enum { kPreAllocStringCnt = 8 };
10671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    PREALLOC_STR_ARRAY(kPreAllocStringCnt)    strs;
10691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    PREALLOC_LENGTH_ARRAY(kPreAllocStringCnt) lengths;
10701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    PREALLOC_TEMP_ARRAY(kPreAllocStringCnt)   temps;
10711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder unis;
10731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder inputs;
10741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder outputs;
10751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(segments.fHeader, &strs, &lengths);
10774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fVSUnis, gl, &strs, &lengths, &temps);
10784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fVSAttrs, gl, &strs, &lengths, &temps);
10794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fVSOutputs, gl, &strs, &lengths, &temps);
10801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(segments.fVSCode, &strs, &lengths);
10811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if PRINT_SHADERS
10831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    print_shader(strs.count(), &strs[0], &lengths[0]);
10841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrPrintf("\n");
10851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
10861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fVShaderID =
10881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        CompileShader(gl, GR_GL_VERTEX_SHADER, strs.count(),
10891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      &strs[0], &lengths[0]);
10901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!programData->fVShaderID) {
10921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
10931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (segments.fUsesGS) {
10951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        strs.reset();
10961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        lengths.reset();
10971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        temps.reset();
10981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        append_string(segments.fHeader, &strs, &lengths);
10991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        append_string(segments.fGSHeader, &strs, &lengths);
11004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        append_decls(segments.fGSInputs, gl, &strs, &lengths, &temps);
11014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        append_decls(segments.fGSOutputs, gl, &strs, &lengths, &temps);
11021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        append_string(segments.fGSCode, &strs, &lengths);
11031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if PRINT_SHADERS
11041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        print_shader(strs.count(), &strs[0], &lengths[0]);
11051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrPrintf("\n");
11061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
11071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fGShaderID =
11081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            CompileShader(gl, GR_GL_GEOMETRY_SHADER, strs.count(),
11091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          &strs[0], &lengths[0]);
11101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
11111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fGShaderID = 0;
11121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
11131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    strs.reset();
11151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    lengths.reset();
11161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    temps.reset();
11171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(segments.fHeader, &strs, &lengths);
11194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrStringBuilder precisionStr(GrGetGLSLShaderPrecisionDecl(gl.binding()));
11201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(precisionStr, &strs, &lengths);
11214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fFSUnis, gl, &strs, &lengths, &temps);
11224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fFSInputs, gl, &strs, &lengths, &temps);
11231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // We shouldn't have declared outputs on 1.10
11244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrAssert(k110_GrGLSLGeneration != gl.glslGeneration() ||
11251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             segments.fFSOutputs.empty());
11264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    append_decls(segments.fFSOutputs, gl, &strs, &lengths, &temps);
11271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(segments.fFSFunctions, &strs, &lengths);
11281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_string(segments.fFSCode, &strs, &lengths);
11291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if PRINT_SHADERS
11311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    print_shader(strs.count(), &strs[0], &lengths[0]);
11321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrPrintf("\n");
11331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
11341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fFShaderID =
11361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        CompileShader(gl, GR_GL_FRAGMENT_SHADER, strs.count(),
11371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      &strs[0], &lengths[0]);
11381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!programData->fFShaderID) {
11401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
11411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
11421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
11441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
11451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
11474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
11484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
11494f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerGrGLuint GrGLProgram::CompileShader(const GrGLContextInfo& gl,
11501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrGLenum type,
11511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    int stringCnt,
11521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    const char** strings,
11531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    int* stringLengths) {
11541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
11551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
11561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLuint shader;
11584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL_RET(shader, CreateShader(type));
11591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == shader) {
11601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return 0;
11611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
11621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLint compiled = GR_GL_INIT_ZERO;
11644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(ShaderSource(shader, stringCnt, strings, stringLengths));
11654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(CompileShader(shader));
11664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
11671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!compiled) {
11691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLint infoLen = GR_GL_INIT_ZERO;
11704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
11711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
11721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (infoLen > 0) {
11731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // retrieve length even though we don't need it to workaround
11741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // bug in chrome cmd buffer param validation.
11751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLsizei length = GR_GL_INIT_ZERO;
11764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GL_CALL(GetShaderInfoLog(shader, infoLen+1,
11774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                         &length, (char*)log.get()));
11781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            print_shader(stringCnt, strings, stringLengths);
11791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrPrintf("\n%s", log.get());
11801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
11811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(!"Shader compilation failed!");
11824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(DeleteShader(shader));
11831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return 0;
11841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
11851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return shader;
11861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
11871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool GrGLProgram::bindOutputsAttribsAndLinkProgram(
11894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        const GrGLContextInfo& gl,
11901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        GrStringBuilder texCoordAttrNames[],
11911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        bool bindColorOut,
11921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        bool bindDualSrcOut,
11931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                        CachedData* programData) const {
11944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL_RET(programData->fProgramID, CreateProgram());
11951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!programData->fProgramID) {
11961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
11971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
11981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrGLint& progID = programData->fProgramID;
11991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(AttachShader(progID, programData->fVShaderID));
12011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (programData->fGShaderID) {
12024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(AttachShader(progID, programData->fGShaderID));
12031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(AttachShader(progID, programData->fFShaderID));
12051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (bindColorOut) {
12074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BindFragDataLocation(programData->fProgramID,
12084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                     0, declared_color_output_name()));
12091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (bindDualSrcOut) {
12114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BindFragDataLocationIndexed(programData->fProgramID,
12124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                            0, 1, dual_source_output_name()));
12131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // Bind the attrib locations to same values for all shaders
12164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME));
12171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
12181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (texCoordAttrNames[t].size()) {
12194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GL_CALL(BindAttribLocation(progID,
12204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                       TexCoordAttributeIdx(t),
12214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                       texCoordAttrNames[t].c_str()));
12221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
12231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kSetAsAttribute == programData->fUniLocations.fViewMatrixUni) {
12264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BindAttribLocation(progID,
12274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   ViewMatrixAttributeIdx(),
12284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   VIEW_MATRIX_NAME));
12291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
12321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const StageUniLocations& unis = programData->fUniLocations.fStages[s];
12331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (kSetAsAttribute == unis.fTextureMatrixUni) {
12341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrStringBuilder matName;
12351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            tex_matrix_name(s, &matName);
12364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GL_CALL(BindAttribLocation(progID,
12374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                       TextureMatrixAttributeIdx(s),
12384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                       matName.c_str()));
12391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
12401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME));
12434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME));
12444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
12451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(LinkProgram(progID));
12471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLint linked = GR_GL_INIT_ZERO;
12494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
12501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!linked) {
12511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLint infoLen = GR_GL_INIT_ZERO;
12524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
12531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
12541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (infoLen > 0) {
12551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // retrieve length even though we don't need it to workaround
12561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // bug in chrome cmd buffer param validation.
12571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLsizei length = GR_GL_INIT_ZERO;
12584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GL_CALL(GetProgramInfoLog(progID,
12594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      infoLen+1,
12604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      &length,
12614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      (char*)log.get()));
12621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrPrintf((char*)log.get());
12631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
12641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(!"Error linking program");
12654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(DeleteProgram(progID));
12661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fProgramID = 0;
12671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
12681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
12701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
12711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
12731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                  CachedData* programData) const {
12741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const GrGLint& progID = programData->fProgramID;
12751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fViewMatrixUni) {
12774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fViewMatrixUni,
12784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, VIEW_MATRIX_NAME));
12791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
12801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fColorUni) {
12824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fColorUni,
12834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, COL_UNI_NAME));
12841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
12851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
12874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fColorFilterUni,
12884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, COL_FILTER_UNI_NAME));
12891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
12901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fColorMatrixUni) {
12934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fColorMatrixUni,
12944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, COL_MATRIX_UNI_NAME));
12951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
12961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
12971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) {
12984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni,
12994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME));
13004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
13014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fCoverageUni) {
13024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fCoverageUni,
13034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, COV_UNI_NAME));
13044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni);
13051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kUseUniform == programData->fUniLocations.fEdgesUni) {
13084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL_RET(programData->fUniLocations.fEdgesUni,
13094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    GetUniformLocation(progID, EDGES_UNI_NAME));
13101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni);
13111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
13121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fUniLocations.fEdgesUni = kUnusedUniform;
13131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
13161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        StageUniLocations& locations = programData->fUniLocations.fStages[s];
13171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (fProgramDesc.fStages[s].isEnabled()) {
13181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fTextureMatrixUni) {
13191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrStringBuilder texMName;
13201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                tex_matrix_name(s, &texMName);
13214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fTextureMatrixUni,
13224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID, texMName.c_str()));
13231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
13241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fSamplerUni) {
13271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrStringBuilder samplerName;
13281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                sampler_name(s, &samplerName);
13294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fSamplerUni,
13304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID,samplerName.c_str()));
13311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fSamplerUni);
13321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fNormalizedTexelSizeUni) {
13351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrStringBuilder texelSizeName;
13361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                normalized_texel_size_name(s, &texelSizeName);
13374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fNormalizedTexelSizeUni,
13384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID, texelSizeName.c_str()));
13391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fNormalizedTexelSizeUni);
13401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fRadial2Uni) {
13431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrStringBuilder radial2ParamName;
13441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                radial2_param_name(s, &radial2ParamName);
13454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fRadial2Uni,
13464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID, radial2ParamName.c_str()));
13471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fRadial2Uni);
13481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fTexDomUni) {
13511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrStringBuilder texDomName;
13521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                tex_domain_name(s, &texDomName);
13534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fTexDomUni,
13544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID, texDomName.c_str()));
13551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fTexDomUni);
13561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrStringBuilder kernelName, imageIncrementName;
13591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            convolve_param_names(s, &kernelName, &imageIncrementName);
13601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fKernelUni) {
13614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fKernelUni,
13624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID, kernelName.c_str()));
13631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fKernelUni);
13641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (kUseUniform == locations.fImageIncrementUni) {
13674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                GL_CALL_RET(locations.fImageIncrementUni,
13684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            GetUniformLocation(progID,
13694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                               imageIncrementName.c_str()));
13701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                GrAssert(kUnusedUniform != locations.fImageIncrementUni);
13711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
13721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
13731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GL_CALL(UseProgram(progID));
13751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // init sampler unis and set bogus values for state tracking
13771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
13781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) {
13794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s));
13801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
13811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
13821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fRadial2CenterX1[s] = GR_ScalarMax;
13831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fRadial2Radius0[s] = -GR_ScalarMax;
13841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fTextureWidth[s] = -1;
13851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        programData->fTextureHeight[s] = -1;
13861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fViewMatrix = GrMatrix::InvalidMatrix();
13881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fColor = GrColor_ILLEGAL;
13891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    programData->fColorFilterColor = GrColor_ILLEGAL;
13901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
13911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//============================================================================
13931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// Stage code generation
13941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//============================================================================
13951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace {
13971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) {
13991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return
14001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger       (GrGLProgram::StageDesc::kRadial2Gradient_CoordMapping == mapping ||
14011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLProgram::StageDesc::kRadial2GradientDegenerate_CoordMapping == mapping);
14021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
14031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14041cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrGLShaderVar* genRadialVS(int stageNum,
14051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        ShaderCodeSegments* segments,
14061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        GrGLProgram::StageUniLocations* locations,
14071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const char** radial2VaryingVSName,
14081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const char** radial2VaryingFSName,
14091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const char* varyingVSName,
14101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        int varyingDims, int coordDims) {
14111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
14131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
14141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2FSParams->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
14151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2FSParams->setArrayCount(6);
14161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2_param_name(stageNum, radial2FSParams->accessName());
14171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
14181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    locations->fRadial2Uni = kUseUniform;
14201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // for radial grads without perspective we can pass the linear
14221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // part of the quadratic as a varying.
14231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (varyingDims == coordDims) {
14241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(2 == coordDims);
14251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        append_varying(GrGLShaderVar::kFloat_Type,
14261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       "Radial2BCoeff",
14271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       stageNum,
14281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       segments,
14291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       radial2VaryingVSName,
14301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       radial2VaryingFSName);
14311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder radial2p2;
14331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder radial2p3;
14341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        radial2FSParams->appendArrayAccess(2, &radial2p2);
14351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        radial2FSParams->appendArrayAccess(3, &radial2p3);
14361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
14381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const char* r2ParamName = radial2FSParams->getName().c_str();
14391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fVSCode.appendf("\t%s = 2.0 *(%s * %s.x - %s);\n",
14401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  *radial2VaryingVSName, radial2p2.c_str(),
14411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  varyingVSName, radial2p3.c_str());
14421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
14431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return radial2FSParams;
14451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
14461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool genRadial2GradientCoordMapping(int stageNum,
14481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    ShaderCodeSegments* segments,
14491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    const char* radial2VaryingFSName,
14501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrGLShaderVar* radial2Params,
14511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrStringBuilder& sampleCoords,
14521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrStringBuilder& fsCoordName,
14531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    int varyingDims,
14541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    int coordDims) {
14551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder cName("c");
14561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder ac4Name("ac4");
14571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder rootName("root");
14581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    cName.appendS32(stageNum);
14601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ac4Name.appendS32(stageNum);
14611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    rootName.appendS32(stageNum);
14621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p0;
14641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p1;
14651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p2;
14661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p3;
14671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p4;
14681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p5;
14691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(0, &radial2p0);
14701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(1, &radial2p1);
14711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(2, &radial2p2);
14721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(3, &radial2p3);
14731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(4, &radial2p4);
14741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(5, &radial2p5);
14751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if we were able to interpolate the linear component bVar is the varying
14771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // otherwise compute it
14781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder bVar;
14791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (coordDims == varyingDims) {
14801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar = radial2VaryingFSName;
14811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(2 == varyingDims);
14821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
14831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(3 == varyingDims);
14841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar = "b";
14851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar.appendS32(stageNum);
14861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n",
14871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    bVar.c_str(), radial2p2.c_str(),
14881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    fsCoordName.c_str(), radial2p3.c_str());
14891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
14901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // c = (x^2)+(y^2) - params[4]
14921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n",
14931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              cName.c_str(), fsCoordName.c_str(),
14941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              fsCoordName.c_str(),
14951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              radial2p4.c_str());
14961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // ac4 = 4.0 * params[0] * c
14971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tfloat %s = %s * 4.0 * %s;\n",
14981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              ac4Name.c_str(), radial2p0.c_str(),
14991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              cName.c_str());
15001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // root = sqrt(b^2-4ac)
15021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // (abs to avoid exception due to fp precision)
15031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n",
15041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              rootName.c_str(), bVar.c_str(), bVar.c_str(),
15051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              ac4Name.c_str());
15061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
15081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // y coord is 0.5 (texture is effectively 1D)
15091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)",
15101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        bVar.c_str(), radial2p5.c_str(),
15111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        rootName.c_str(), radial2p1.c_str());
15121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
15131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
15141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool genRadial2GradientDegenerateCoordMapping(int stageNum,
15161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              ShaderCodeSegments* segments,
15171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              const char* radial2VaryingFSName,
15181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              GrGLShaderVar* radial2Params,
15191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              GrStringBuilder& sampleCoords,
15201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              GrStringBuilder& fsCoordName,
15211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              int varyingDims,
15221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                              int coordDims) {
15231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder cName("c");
15241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    cName.appendS32(stageNum);
15261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p2;
15281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p3;
15291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder radial2p4;
15301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(2, &radial2p2);
15311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(3, &radial2p3);
15321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    radial2Params->appendArrayAccess(4, &radial2p4);
15331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if we were able to interpolate the linear component bVar is the varying
15351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // otherwise compute it
15361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder bVar;
15371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (coordDims == varyingDims) {
15381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar = radial2VaryingFSName;
15391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(2 == varyingDims);
15401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
15411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(3 == varyingDims);
15421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar = "b";
15431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bVar.appendS32(stageNum);
15441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n",
15451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    bVar.c_str(), radial2p2.c_str(),
15461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    fsCoordName.c_str(), radial2p3.c_str());
15471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
15481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // c = (x^2)+(y^2) - params[4]
15501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n",
15511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              cName.c_str(), fsCoordName.c_str(),
15521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              fsCoordName.c_str(),
15531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              radial2p4.c_str());
15541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // x coord is: -c/b
15561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // y coord is 0.5 (texture is effectively 1D)
15571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sampleCoords.printf("vec2((-%s / %s), 0.5)", cName.c_str(), bVar.c_str());
15581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
15591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
15601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid gen2x2FS(int stageNum,
15621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              ShaderCodeSegments* segments,
15631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              GrGLProgram::StageUniLocations* locations,
15641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              GrStringBuilder* sampleCoords,
15651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              const char* samplerName,
15661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              const char* texelSizeName,
15671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              const char* swizzle,
15681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              const char* fsOutColor,
15691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              GrStringBuilder& texFunc,
15701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              GrStringBuilder& modulate,
15711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              bool complexCoord,
15721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              int coordDims) {
15731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    locations->fNormalizedTexelSizeUni = kUseUniform;
15741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (complexCoord) {
15751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // assign the coord to a var rather than compute 4x.
15761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder coordVar("tCoord");
15771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        coordVar.appendS32(stageNum);
15781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSCode.appendf("\t%s %s = %s;\n",
15791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            float_vector_type_str(coordDims),
15801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            coordVar.c_str(), sampleCoords->c_str());
15811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *sampleCoords = coordVar;
15821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
15831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(2 == coordDims);
15841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder accumVar("accum");
15851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    accumVar.appendS32(stageNum);
15861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tvec4 %s  = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, swizzle);
15871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, swizzle);
15881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, swizzle);
15891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, swizzle);
15901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
15911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
15931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid genConvolutionVS(int stageNum,
15951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const StageDesc& desc,
15961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      ShaderCodeSegments* segments,
15971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrGLProgram::StageUniLocations* locations,
15981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrGLShaderVar** kernel,
15991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char** imageIncrementName,
16001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char* varyingVSName) {
16011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
16021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *kernel = &segments->fFSUnis.push_back();
16031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    (*kernel)->setType(GrGLShaderVar::kFloat_Type);
16041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    (*kernel)->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
16051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    (*kernel)->setArrayCount(desc.fKernelWidth);
16061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
16071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    imgInc->setType(GrGLShaderVar::kVec2f_Type);
16081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
16091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    convolve_param_names(stageNum,
16111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         (*kernel)->accessName(),
16121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         imgInc->accessName());
16131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *imageIncrementName = imgInc->getName().c_str();
16141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // need image increment in both VS and FS
16161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
16171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    locations->fKernelUni = kUseUniform;
16191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    locations->fImageIncrementUni = kUseUniform;
16201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    float scale = (desc.fKernelWidth - 1) * 0.5f;
16211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
16221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  varyingVSName, scale, scale,
16231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  *imageIncrementName);
16241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
16251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid genConvolutionFS(int stageNum,
16271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const StageDesc& desc,
16281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      ShaderCodeSegments* segments,
16291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char* samplerName,
16301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrGLShaderVar* kernel,
16311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char* swizzle,
16321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char* imageIncrementName,
16331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      const char* fsOutColor,
16341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrStringBuilder& sampleCoords,
16351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrStringBuilder& texFunc,
16361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                      GrStringBuilder& modulate) {
16371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder sumVar("sum");
16381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sumVar.appendS32(stageNum);
16391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder coordVar("coord");
16401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    coordVar.appendS32(stageNum);
16411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder kernelIndex;
16431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kernel->appendArrayAccess("i", &kernelIndex);
16441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
16451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
16461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              sumVar.c_str());
16471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tvec2 %s = %s;\n",
16481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              coordVar.c_str(),
16491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              sampleCoords.c_str());
16501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
16511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              desc.fKernelWidth);
16521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s;\n",
16531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              sumVar.c_str(), texFunc.c_str(),
16541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              samplerName, coordVar.c_str(), swizzle,
16551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              kernelIndex.c_str());
16561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t\t%s += %s;\n",
16571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              coordVar.c_str(),
16581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              imageIncrementName);
16594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.append("\t}\n");
16601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
16611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              sumVar.c_str(), modulate.c_str());
16621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
16634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid genMorphologyVS(int stageNum,
16654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const StageDesc& desc,
16664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     ShaderCodeSegments* segments,
16674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     GrGLProgram::StageUniLocations* locations,
16684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char** imageIncrementName,
16694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char* varyingVSName) {
16704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
16714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    imgInc->setType(GrGLShaderVar::kVec2f_Type);
16724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
16734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    image_increment_param_name(stageNum, imgInc->accessName());
16754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    *imageIncrementName = imgInc->getName().c_str();
16764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // need image increment in both VS and FS
16784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
16794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    locations->fImageIncrementUni = kUseUniform;
16814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fVSCode.appendf("\t%s -= vec2(%d, %d) * %s;\n",
16824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  varyingVSName, desc.fKernelWidth,
16834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  desc.fKernelWidth, *imageIncrementName);
16844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
16854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid genMorphologyFS(int stageNum,
16874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const StageDesc& desc,
16884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     ShaderCodeSegments* segments,
16894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char* samplerName,
16904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char* swizzle,
16914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char* imageIncrementName,
16924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     const char* fsOutColor,
16934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     GrStringBuilder& sampleCoords,
16944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     GrStringBuilder& texFunc,
16954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                     GrStringBuilder& modulate) {
16964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrStringBuilder valueVar("value");
16974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    valueVar.appendS32(stageNum);
16984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    GrStringBuilder coordVar("coord");
16994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    coordVar.appendS32(stageNum);
17004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool isDilate = StageDesc::kDilate_FetchMode == desc.fFetchMode;
17014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
17024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger   if (isDilate) {
17034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
17044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  valueVar.c_str());
17054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else {
17064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        segments->fFSCode.appendf("\tvec4 %s = vec4(1, 1, 1, 1);\n",
17074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  valueVar.c_str());
17084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
17094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\tvec2 %s = %s;\n",
17104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              coordVar.c_str(),
17114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              sampleCoords.c_str());
17124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
17134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              desc.fKernelWidth * 2 + 1);
17144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\t\t%s = %s(%s, %s(%s, %s)%s);\n",
17154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              valueVar.c_str(), isDilate ? "max" : "min",
17164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              valueVar.c_str(), texFunc.c_str(),
17174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              samplerName, coordVar.c_str(), swizzle);
17184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\t\t%s += %s;\n",
17194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              coordVar.c_str(),
17204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              imageIncrementName);
17214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\t}\n");
17224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
17234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              valueVar.c_str(), modulate.c_str());
17244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
17251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
17271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid GrGLProgram::genStageCode(const GrGLContextInfo& gl,
17291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               int stageNum,
17301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               const GrGLProgram::StageDesc& desc,
17311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               const char* fsInColor, // NULL means no incoming color
17321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               const char* fsOutColor,
17331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               const char* vsInCoord,
17341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               ShaderCodeSegments* segments,
17351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               StageUniLocations* locations) const {
17361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
17381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) ==
17391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             desc.fInConfigFlags);
17401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // First decide how many coords are needed to access the texture
17421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // Right now it's always 2 but we could start using 1D textures for
17431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // gradients.
17441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const int coordDims = 2;
17451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int varyingDims;
17461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /// Vertex Shader Stuff
17471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // decide whether we need a matrix to transform texture coords
17491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // and whether the varying needs a perspective coord.
17501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* matName = NULL;
17511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
17521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        varyingDims = coordDims;
17531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
17541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar* mat;
17551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #if GR_GL_ATTRIBUTE_MATRICES
17561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mat = &segments->fVSAttrs.push_back();
17571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mat->setTypeModifier(GrGLShaderVar::kAttribute_TypeModifier);
17581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        locations->fTextureMatrixUni = kSetAsAttribute;
17591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #else
17601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mat = &segments->fVSUnis.push_back();
17611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mat->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
17621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        locations->fTextureMatrixUni = kUseUniform;
17631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #endif
17641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        tex_matrix_name(stageNum, mat->accessName());
17651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        mat->setType(GrGLShaderVar::kMat33f_Type);
17661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        matName = mat->getName().c_str();
17671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
17691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            varyingDims = coordDims;
17701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
17711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            varyingDims = coordDims + 1;
17721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
17731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
17741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    segments->fFSUnis.push_back().set(GrGLShaderVar::kSampler2D_Type,
17761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLShaderVar::kUniform_TypeModifier, "");
17771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sampler_name(stageNum, segments->fFSUnis.back().accessName());
17781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    locations->fSamplerUni = kUseUniform;
17791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* samplerName = segments->fFSUnis.back().getName().c_str();
17801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* texelSizeName = NULL;
17821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (StageDesc::k2x2_FetchMode == desc.fFetchMode) {
17831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec2f_Type,
17841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLShaderVar::kUniform_TypeModifier, "");
17851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        normalized_texel_size_name(stageNum, segments->fFSUnis.back().accessName());
17861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        texelSizeName = segments->fFSUnis.back().getName().c_str();
17871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
17881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char *varyingVSName, *varyingFSName;
17901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    append_varying(float_vector_type(varyingDims),
17911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    "Stage",
17921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   stageNum,
17931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   segments,
17941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   &varyingVSName,
17951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   &varyingFSName);
17961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!matName) {
17981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(varyingDims == coordDims);
17991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord);
18001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
18011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // varying = texMatrix * texCoord
18021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
18031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  varyingVSName, matName, vsInCoord,
18041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  vector_all_coords(varyingDims));
18051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
18061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLShaderVar* radial2Params = NULL;
18081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* radial2VaryingVSName = NULL;
18091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* radial2VaryingFSName = NULL;
18101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (isRadialMapping((StageDesc::CoordMapping) desc.fCoordMapping)) {
18121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        radial2Params = genRadialVS(stageNum, segments,
18131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    locations,
18141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    &radial2VaryingVSName,
18151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    &radial2VaryingFSName,
18161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    varyingVSName,
18171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    varyingDims, coordDims);
18181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
18191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLShaderVar* kernel = NULL;
18211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* imageIncrementName = NULL;
18221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
18231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        genConvolutionVS(stageNum, desc, segments, locations,
18241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         &kernel, &imageIncrementName, varyingVSName);
18254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else if (StageDesc::kDilate_FetchMode == desc.fFetchMode ||
18264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger               StageDesc::kErode_FetchMode == desc.fFetchMode) {
18274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        genMorphologyVS(stageNum, desc, segments, locations,
18284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        &imageIncrementName, varyingVSName);
18291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
18301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /// Fragment Shader Stuff
18321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder fsCoordName;
18331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // function used to access the shader, may be made projective
18341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder texFunc("texture2D");
18351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
18361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          StageDesc::kNoPerspective_OptFlagBit)) {
18371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(varyingDims == coordDims);
18381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fsCoordName = varyingFSName;
18391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
18401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // if we have to do some special op on the varyings to get
18411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // our final tex coords then when in perspective we have to
18421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // do an explicit divide. Otherwise, we can use a Proj func.
18431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if  (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping &&
18441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             StageDesc::kSingle_FetchMode == desc.fFetchMode) {
18451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            texFunc.append("Proj");
18461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fsCoordName = varyingFSName;
18471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
18481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fsCoordName = "inCoord";
18491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fsCoordName.appendS32(stageNum);
18501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
18511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                GrGLShaderVar::TypeString(float_vector_type(coordDims)),
18521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                fsCoordName.c_str(),
18531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                varyingFSName,
18541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                vector_nonhomog_coords(varyingDims),
18551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                varyingFSName,
18561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                vector_homog_coord(varyingDims));
18571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
18581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
18591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder sampleCoords;
18611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool complexCoord = false;
18621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (desc.fCoordMapping) {
18631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kIdentity_CoordMapping:
18641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        sampleCoords = fsCoordName;
18651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
18661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kSweepGradient_CoordMapping:
18671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        sampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", fsCoordName.c_str(), fsCoordName.c_str());
18681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        complexCoord = true;
18691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
18701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kRadialGradient_CoordMapping:
18711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        sampleCoords.printf("vec2(length(%s.xy), 0.5)", fsCoordName.c_str());
18721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        complexCoord = true;
18731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
18741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kRadial2Gradient_CoordMapping:
18751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        complexCoord = genRadial2GradientCoordMapping(
18761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           stageNum, segments,
18771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           radial2VaryingFSName, radial2Params,
18781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           sampleCoords, fsCoordName,
18791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           varyingDims, coordDims);
18801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
18821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kRadial2GradientDegenerate_CoordMapping:
18831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        complexCoord = genRadial2GradientDegenerateCoordMapping(
18841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           stageNum, segments,
18851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           radial2VaryingFSName, radial2Params,
18861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           sampleCoords, fsCoordName,
18871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           varyingDims, coordDims);
18881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
18891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    };
18911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const uint32_t kMulByAlphaMask =
18934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        (StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
18944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger         StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
18954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
18961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const char* swizzle = "";
18971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (desc.fInConfigFlags & StageDesc::kSwapRAndB_InConfigFlag) {
18981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(!(desc.fInConfigFlags & StageDesc::kSmearAlpha_InConfigFlag));
18991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        swizzle = ".bgra";
19001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (desc.fInConfigFlags & StageDesc::kSmearAlpha_InConfigFlag) {
19014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
19021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        swizzle = ".aaaa";
19031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
19041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrStringBuilder modulate;
19061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL != fsInColor) {
19071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        modulate.printf(" * %s", fsInColor);
19081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
19091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (desc.fOptFlags &
19111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        StageDesc::kCustomTextureDomain_OptFlagBit) {
19121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder texDomainName;
19131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        tex_domain_name(stageNum, &texDomainName);
19141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
19151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrGLShaderVar::kUniform_TypeModifier, texDomainName);
19161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrStringBuilder coordVar("clampCoord");
19171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        segments->fFSCode.appendf("\t%s %s = clamp(%s, %s.xy, %s.zw);\n",
19181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  float_vector_type_str(coordDims),
19191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  coordVar.c_str(),
19201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  sampleCoords.c_str(),
19211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  texDomainName.c_str(),
19221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  texDomainName.c_str());
19231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        sampleCoords = coordVar;
19241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        locations->fTexDomUni = kUseUniform;
19251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
19261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    switch (desc.fFetchMode) {
19281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::k2x2_FetchMode:
19294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
19301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        gen2x2FS(stageNum, segments, locations, &sampleCoords,
19311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            samplerName, texelSizeName, swizzle, fsOutColor,
19321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            texFunc, modulate, complexCoord, coordDims);
19331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
19341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    case StageDesc::kConvolution_FetchMode:
19354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
19361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        genConvolutionFS(stageNum, desc, segments,
19371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            samplerName, kernel, swizzle, imageIncrementName, fsOutColor,
19381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            sampleCoords, texFunc, modulate);
19391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        break;
19404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    case StageDesc::kDilate_FetchMode:
19414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    case StageDesc::kErode_FetchMode:
19424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
19434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        genMorphologyFS(stageNum, desc, segments,
19444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            samplerName, swizzle, imageIncrementName, fsOutColor,
19454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            sampleCoords, texFunc, modulate);
19464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        break;
19471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    default:
19484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (desc.fInConfigFlags & kMulByAlphaMask) {
19494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // only one of the mul by alpha flags should be set
19504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            GrAssert(GrIsPow2(kMulByAlphaMask & desc.fInConfigFlags));
19511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            GrAssert(!(desc.fInConfigFlags &
19521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       StageDesc::kSmearAlpha_InConfigFlag));
19531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\t%s = %s(%s, %s)%s;\n",
19541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      fsOutColor, texFunc.c_str(),
19551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      samplerName, sampleCoords.c_str(),
19561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      swizzle);
19574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (desc.fInConfigFlags &
19584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag) {
19594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                segments->fFSCode.appendf("\t%s = vec4(ceil(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
19604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          fsOutColor, fsOutColor, fsOutColor,
19614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          fsOutColor, modulate.c_str());
19624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            } else {
19634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                segments->fFSCode.appendf("\t%s = vec4(floor(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
19644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          fsOutColor, fsOutColor, fsOutColor,
19654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                          fsOutColor, modulate.c_str());
19664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
19671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
19681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
19691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      fsOutColor, texFunc.c_str(),
19701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      samplerName, sampleCoords.c_str(),
19711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      swizzle, modulate.c_str());
19721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
19731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
19741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
19751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1977