GrGLProgram.cpp revision a4acf12a9353ffc834d2c6ee673be447487963c9
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrGLProgram.h"
9
10#include "GrAllocator.h"
11#include "GrEffect.h"
12#include "GrDrawEffect.h"
13#include "GrGLEffect.h"
14#include "GrGpuGL.h"
15#include "GrGLShaderVar.h"
16#include "GrGLSL.h"
17#include "SkTrace.h"
18#include "SkXfermode.h"
19
20#include "SkRTConf.h"
21
22SK_DEFINE_INST_COUNT(GrGLProgram)
23
24#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
25#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
26
27SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false,
28                "Print the source code for all shaders generated.");
29
30#define COL_ATTR_NAME "aColor"
31#define COV_ATTR_NAME "aCoverage"
32#define EDGE_ATTR_NAME "aEdge"
33
34namespace {
35inline const char* declared_color_output_name() { return "fsColorOut"; }
36inline const char* dual_source_output_name() { return "dualSourceOut"; }
37}
38
39GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
40                                 const GrGLProgramDesc& desc,
41                                 const GrEffectStage* colorStages[],
42                                 const GrEffectStage* coverageStages[]) {
43    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
44    if (!program->succeeded()) {
45        delete program;
46        program = NULL;
47    }
48    return program;
49}
50
51GrGLProgram::GrGLProgram(GrGpuGL* gpu,
52                         const GrGLProgramDesc& desc,
53                         const GrEffectStage* colorStages[],
54                         const GrEffectStage* coverageStages[])
55: fGpu(gpu)
56, fUniformManager(gpu) {
57    fDesc = desc;
58    fVShaderID = 0;
59    fGShaderID = 0;
60    fFShaderID = 0;
61    fProgramID = 0;
62
63    fDstCopyTexUnit = -1;
64
65    fColor = GrColor_ILLEGAL;
66    fColorFilterColor = GrColor_ILLEGAL;
67
68    fColorEffects.reset(desc.numColorEffects());
69    fCoverageEffects.reset(desc.numCoverageEffects());
70
71    this->genProgram(colorStages, coverageStages);
72}
73
74GrGLProgram::~GrGLProgram() {
75    if (fVShaderID) {
76        GL_CALL(DeleteShader(fVShaderID));
77    }
78    if (fGShaderID) {
79        GL_CALL(DeleteShader(fGShaderID));
80    }
81    if (fFShaderID) {
82        GL_CALL(DeleteShader(fFShaderID));
83    }
84    if (fProgramID) {
85        GL_CALL(DeleteProgram(fProgramID));
86    }
87}
88
89void GrGLProgram::abandon() {
90    fVShaderID = 0;
91    fGShaderID = 0;
92    fFShaderID = 0;
93    fProgramID = 0;
94}
95
96void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
97                                GrBlendCoeff* dstCoeff) const {
98    switch (fDesc.getHeader().fCoverageOutput) {
99        case GrGLProgramDesc::kModulate_CoverageOutput:
100            break;
101        // The prog will write a coverage value to the secondary
102        // output and the dst is blended by one minus that value.
103        case GrGLProgramDesc::kSecondaryCoverage_CoverageOutput:
104        case GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput:
105        case GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput:
106            *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
107            break;
108        case GrGLProgramDesc::kCombineWithDst_CoverageOutput:
109            // We should only have set this if the blend was specified as (1, 0)
110            SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
111            break;
112        default:
113            GrCrash("Unexpected coverage output");
114            break;
115    }
116}
117
118namespace {
119// given two blend coefficients determine whether the src
120// and/or dst computation can be omitted.
121inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
122                              SkXfermode::Coeff dstCoeff,
123                              bool* needSrcValue,
124                              bool* needDstValue) {
125    if (SkXfermode::kZero_Coeff == srcCoeff) {
126        switch (dstCoeff) {
127            // these all read the src
128            case SkXfermode::kSC_Coeff:
129            case SkXfermode::kISC_Coeff:
130            case SkXfermode::kSA_Coeff:
131            case SkXfermode::kISA_Coeff:
132                *needSrcValue = true;
133                break;
134            default:
135                *needSrcValue = false;
136                break;
137        }
138    } else {
139        *needSrcValue = true;
140    }
141    if (SkXfermode::kZero_Coeff == dstCoeff) {
142        switch (srcCoeff) {
143            // these all read the dst
144            case SkXfermode::kDC_Coeff:
145            case SkXfermode::kIDC_Coeff:
146            case SkXfermode::kDA_Coeff:
147            case SkXfermode::kIDA_Coeff:
148                *needDstValue = true;
149                break;
150            default:
151                *needDstValue = false;
152                break;
153        }
154    } else {
155        *needDstValue = true;
156    }
157}
158
159/**
160 * Create a blend_coeff * value string to be used in shader code. Sets empty
161 * string if result is trivially zero.
162 */
163inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
164                       const char* src, const char* dst,
165                       const char* value) {
166    switch (coeff) {
167    case SkXfermode::kZero_Coeff:    /** 0 */
168        *str = "";
169        break;
170    case SkXfermode::kOne_Coeff:     /** 1 */
171        *str = value;
172        break;
173    case SkXfermode::kSC_Coeff:
174        str->printf("(%s * %s)", src, value);
175        break;
176    case SkXfermode::kISC_Coeff:
177        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
178        break;
179    case SkXfermode::kDC_Coeff:
180        str->printf("(%s * %s)", dst, value);
181        break;
182    case SkXfermode::kIDC_Coeff:
183        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
184        break;
185    case SkXfermode::kSA_Coeff:      /** src alpha */
186        str->printf("(%s.a * %s)", src, value);
187        break;
188    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
189        str->printf("((1.0 - %s.a) * %s)", src, value);
190        break;
191    case SkXfermode::kDA_Coeff:      /** dst alpha */
192        str->printf("(%s.a * %s)", dst, value);
193        break;
194    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
195        str->printf("((1.0 - %s.a) * %s)", dst, value);
196        break;
197    default:
198        GrCrash("Unexpected xfer coeff.");
199        break;
200    }
201}
202/**
203 * Adds a line to the fragment shader code which modifies the color by
204 * the specified color filter.
205 */
206void add_color_filter(GrGLShaderBuilder* builder,
207                      const char * outputVar,
208                      SkXfermode::Coeff uniformCoeff,
209                      SkXfermode::Coeff colorCoeff,
210                      const char* filterColor,
211                      const char* inColor) {
212    SkString colorStr, constStr;
213    blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
214    blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
215
216    SkString sum;
217    GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
218    builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
219}
220}
221
222GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
223    switch (fDesc.getHeader().fColorInput) {
224        case GrGLProgramDesc::kAttribute_ColorInput: {
225            GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
226            SkASSERT(NULL != vertexBuilder);
227            vertexBuilder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
228            const char *vsName, *fsName;
229            vertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
230            vertexBuilder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
231            *inColor = fsName;
232            return kNone_GrSLConstantVec;
233        }
234        case GrGLProgramDesc::kUniform_ColorInput: {
235            const char* name;
236            fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
237                                                            kVec4f_GrSLType, "Color", &name);
238            *inColor = name;
239            return kNone_GrSLConstantVec;
240        }
241        case GrGLProgramDesc::kTransBlack_ColorInput:
242            inColor->reset();
243            return kZeros_GrSLConstantVec;
244        case GrGLProgramDesc::kSolidWhite_ColorInput:
245            inColor->reset();
246            return kOnes_GrSLConstantVec;
247        default:
248            GrCrash("Unknown color type.");
249            return kNone_GrSLConstantVec;
250    }
251}
252
253GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage) {
254    switch (fDesc.getHeader().fCoverageInput) {
255        case GrGLProgramDesc::kAttribute_ColorInput: {
256            GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
257            SkASSERT(NULL != vertexBuilder);
258            vertexBuilder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
259            const char *vsName, *fsName;
260            vertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
261            vertexBuilder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
262            *inCoverage = fsName;
263            return kNone_GrSLConstantVec;
264        }
265        case GrGLProgramDesc::kUniform_ColorInput: {
266            const char* name;
267            fUniformHandles.fCoverageUni =
268                builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
269                                    kVec4f_GrSLType, "Coverage", &name);
270            *inCoverage = name;
271            return kNone_GrSLConstantVec;
272        }
273        case GrGLProgramDesc::kTransBlack_ColorInput:
274            inCoverage->reset();
275            return kZeros_GrSLConstantVec;
276        case GrGLProgramDesc::kSolidWhite_ColorInput:
277            inCoverage->reset();
278            return kOnes_GrSLConstantVec;
279        default:
280            GrCrash("Unknown color type.");
281            return kNone_GrSLConstantVec;
282    }
283}
284
285void GrGLProgram::genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const {
286#if GR_GL_EXPERIMENTAL_GS
287    // TODO: The builder should add all this glue code.
288    if (fDesc.getHeader().fExperimentalGS) {
289        SkASSERT(fGpu->glslGeneration() >= k150_GrGLSLGeneration);
290        vertexBuilder->fGSHeader.append("layout(triangles) in;\n"
291                                        "layout(triangle_strip, max_vertices = 6) out;\n");
292        vertexBuilder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n"
293                                    "\t\tgl_Position = gl_in[i].gl_Position;\n");
294        if (fDesc.getHeader().fEmitsPointSize) {
295            vertexBuilder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n");
296        }
297        SkASSERT(vertexBuilder->fGSInputs.count() == vertexBuilder->fGSOutputs.count());
298        int count = vertexBuilder->fGSInputs.count();
299        for (int i = 0; i < count; ++i) {
300            vertexBuilder->gsCodeAppendf("\t\t%s = %s[i];\n",
301                                         vertexBuilder->fGSOutputs[i].getName().c_str(),
302                                         vertexBuilder->fGSInputs[i].getName().c_str());
303        }
304        vertexBuilder->gsCodeAppend("\t\tEmitVertex();\n"
305                                    "\t}\n"
306                                    "\tEndPrimitive();\n");
307    }
308#endif
309}
310
311const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
312    if (inColor.size()) {
313          return inColor.c_str();
314    } else {
315        if (GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.getHeader().fColorInput) {
316            return GrGLSLOnesVecf(4);
317        } else {
318            return GrGLSLZerosVecf(4);
319        }
320    }
321}
322
323namespace {
324// prints a shader using params similar to glShaderSource
325void print_shader(GrGLint stringCnt,
326                  const GrGLchar** strings,
327                  GrGLint* stringLengths) {
328    for (int i = 0; i < stringCnt; ++i) {
329        if (NULL == stringLengths || stringLengths[i] < 0) {
330            GrPrintf(strings[i]);
331        } else {
332            GrPrintf("%.*s", stringLengths[i], strings[i]);
333        }
334    }
335}
336
337// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
338GrGLuint compile_shader(const GrGLInterface* gli,
339                        GrGLenum type,
340                        int stringCnt,
341                        const char** strings,
342                        int* stringLengths) {
343    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
344                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
345
346    GrGLuint shader;
347    GR_GL_CALL_RET(gli, shader, CreateShader(type));
348    if (0 == shader) {
349        return 0;
350    }
351
352    GrGLint compiled = GR_GL_INIT_ZERO;
353    GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths));
354    GR_GL_CALL(gli, CompileShader(shader));
355    GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
356
357    if (!compiled) {
358        GrGLint infoLen = GR_GL_INIT_ZERO;
359        GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
360        SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
361        if (infoLen > 0) {
362            // retrieve length even though we don't need it to workaround bug in chrome cmd buffer
363            // param validation.
364            GrGLsizei length = GR_GL_INIT_ZERO;
365            GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1,
366                                             &length, (char*)log.get()));
367            print_shader(stringCnt, strings, stringLengths);
368            GrPrintf("\n%s", log.get());
369        }
370        SkDEBUGFAIL("Shader compilation failed!");
371        GR_GL_CALL(gli, DeleteShader(shader));
372        return 0;
373    }
374    return shader;
375}
376
377// helper version of above for when shader is already flattened into a single SkString
378GrGLuint compile_shader(const GrGLInterface* gli, GrGLenum type, const SkString& shader) {
379    const GrGLchar* str = shader.c_str();
380    int length = shader.size();
381    return compile_shader(gli, type, 1, &str, &length);
382}
383
384void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
385    SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
386    switch (vec) {
387        case kNone_GrSLConstantVec:
388            break;
389        case kZeros_GrSLConstantVec:
390            *string = GrGLSLZerosVecf(4);
391            break;
392        case kOnes_GrSLConstantVec:
393            *string = GrGLSLOnesVecf(4);
394            break;
395    }
396}
397
398}
399
400// compiles all the shaders from builder and stores the shader IDs
401bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
402
403    SkASSERT(!fVShaderID);
404    SkASSERT(!fGShaderID);
405    SkASSERT(!fFShaderID);
406
407    SkString shader;
408    if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
409        vertexBuilder->vsGetShader(&shader);
410        if (c_PrintShaders) {
411            GrPrintf(shader.c_str());
412            GrPrintf("\n");
413        }
414        if (!(fVShaderID = compile_shader(fGpu->glInterface(), GR_GL_VERTEX_SHADER, shader))) {
415            return false;
416        }
417
418#if GR_GL_EXPERIMENTAL_GS
419        if (fDesc.getHeader().fExperimentalGS) {
420            vertexBuilder->gsGetShader(&shader);
421            if (c_PrintShaders) {
422                GrPrintf(shader.c_str());
423                GrPrintf("\n");
424            }
425            if (!(fGShaderID = compile_shader(fGpu->glInterface(), GR_GL_GEOMETRY_SHADER, shader))) {
426                return false;
427            }
428        }
429#endif
430    }
431
432    builder.fsGetShader(&shader);
433    if (c_PrintShaders) {
434        GrPrintf(shader.c_str());
435        GrPrintf("\n");
436    }
437    if (!(fFShaderID = compile_shader(fGpu->glInterface(), GR_GL_FRAGMENT_SHADER, shader))) {
438        return false;
439    }
440
441    return true;
442}
443
444bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
445                             const GrEffectStage* coverageStages[]) {
446    SkASSERT(0 == fProgramID);
447
448    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
449
450    bool needsVertexShader = true;
451
452    GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, needsVertexShader);
453
454    if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
455        const char* viewMName;
456        fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility,
457                                                            kMat33f_GrSLType, "ViewM", &viewMName);
458
459        vertexBuilder->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
460                                     "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
461                                     viewMName, vertexBuilder->positionAttribute().c_str());
462
463        // we output point size in the GS if present
464        if (header.fEmitsPointSize
465#if GR_GL_EXPERIMENTAL_GS
466            && !header.fExperimentalGS
467#endif
468            ) {
469            vertexBuilder->vsCodeAppend("\tgl_PointSize = 1.0;\n");
470        }
471    }
472
473    // the dual source output has no canonical var name, have to
474    // declare an output, which is incompatible with gl_FragColor/gl_FragData.
475    bool dualSourceOutputWritten = false;
476
477    GrGLShaderVar colorOutput;
478    bool isColorDeclared = GrGLSLSetupFSColorOuput(fGpu->glslGeneration(),
479                                                   declared_color_output_name(),
480                                                   &colorOutput);
481    if (isColorDeclared) {
482        builder.fsOutputAppend(colorOutput);
483    }
484
485    // incoming color to current stage being processed.
486    SkString inColor;
487    GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor);
488
489    // Get the coeffs for the Mode-based color filter, determine if color is needed.
490    SkXfermode::Coeff colorCoeff;
491    SkXfermode::Coeff filterColorCoeff;
492    SkAssertResult(
493        SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>(header.fColorFilterXfermode),
494                                &filterColorCoeff,
495                                &colorCoeff));
496    bool needColor, needFilterColor;
497    need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
498
499    // used in order for builder to return the per-stage uniform handles.
500    typedef SkTArray<GrGLUniformManager::UniformHandle, true>* UniHandleArrayPtr;
501    int maxColorOrCovEffectCnt = GrMax(fDesc.numColorEffects(), fDesc.numCoverageEffects());
502    SkAutoTArray<UniHandleArrayPtr> effectUniformArrays(maxColorOrCovEffectCnt);
503    SkAutoTArray<GrGLEffect*> glEffects(maxColorOrCovEffectCnt);
504
505    if (needColor) {
506        for (int e = 0; e < fDesc.numColorEffects(); ++e) {
507            effectUniformArrays[e] = &fColorEffects[e].fSamplerUnis;
508        }
509
510        builder.emitEffects(colorStages,
511                            fDesc.effectKeys(),
512                            fDesc.numColorEffects(),
513                            &inColor,
514                            &knownColorValue,
515                            effectUniformArrays.get(),
516                            glEffects.get());
517
518        for (int e = 0; e < fDesc.numColorEffects(); ++e) {
519            fColorEffects[e].fGLEffect = glEffects[e];
520        }
521    }
522
523    // Insert the color filter. This will soon be replaced by a color effect.
524    if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
525        const char* colorFilterColorUniName = NULL;
526        fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_Visibility,
527                                                             kVec4f_GrSLType, "FilterColor",
528                                                             &colorFilterColorUniName);
529
530        builder.fsCodeAppend("\tvec4 filteredColor;\n");
531        const char* color;
532        // add_color_filter requires a real input string.
533        if (knownColorValue == kOnes_GrSLConstantVec) {
534            color = GrGLSLOnesVecf(4);
535        } else if (knownColorValue == kZeros_GrSLConstantVec) {
536            color = GrGLSLZerosVecf(4);
537        } else {
538            color = inColor.c_str();
539        }
540        add_color_filter(&builder, "filteredColor", filterColorCoeff,
541                         colorCoeff, colorFilterColorUniName, color);
542        inColor = "filteredColor";
543    }
544
545    ///////////////////////////////////////////////////////////////////////////
546    // compute the partial coverage
547    SkString inCoverage;
548    GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
549
550    for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
551        effectUniformArrays[e] = &fCoverageEffects[e].fSamplerUnis;
552    }
553
554    builder.emitEffects(coverageStages,
555                        fDesc.getEffectKeys() + fDesc.numColorEffects(),
556                        fDesc.numCoverageEffects(),
557                        &inCoverage,
558                        &knownCoverageValue,
559                        effectUniformArrays.get(),
560                        glEffects.get());
561    for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
562        fCoverageEffects[e].fGLEffect = glEffects[e];
563    }
564
565    // discard if coverage is zero
566    if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
567        if (kZeros_GrSLConstantVec == knownCoverageValue) {
568            // This is unfortunate.
569            builder.fsCodeAppend("\tdiscard;\n");
570        } else {
571            builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
572                                  inCoverage.c_str());
573        }
574    }
575
576    GrGLProgramDesc::CoverageOutput coverageOutput =
577        static_cast<GrGLProgramDesc::CoverageOutput>(header.fCoverageOutput);
578    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(coverageOutput)) {
579        builder.fsOutputAppend().set(kVec4f_GrSLType,
580                                     GrGLShaderVar::kOut_TypeModifier,
581                                     dual_source_output_name());
582        // default coeff to ones for kCoverage_DualSrcOutput
583        SkString coeff;
584        GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
585        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
586            // Get (1-A) into coeff
587            SkString inColorAlpha;
588            GrGLSLGetComponent4f(&inColorAlpha,
589                                    inColor.c_str(),
590                                    kA_GrColorComponentFlag,
591                                    knownColorValue,
592                                    true);
593            knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
594                                                 NULL,
595                                                 inColorAlpha.c_str(),
596                                                 kOnes_GrSLConstantVec,
597                                                 knownColorValue,
598                                                 true);
599        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == coverageOutput) {
600            // Get (1-RGBA) into coeff
601            knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
602                                                 NULL,
603                                                 inColor.c_str(),
604                                                 kOnes_GrSLConstantVec,
605                                                 knownColorValue,
606                                                 true);
607        }
608        // Get coeff * coverage into modulate and then write that to the dual source output.
609        SkString modulate;
610        GrGLSLModulatef<4>(&modulate,
611                           coeff.c_str(),
612                           inCoverage.c_str(),
613                           knownCoeffValue,
614                           knownCoverageValue,
615                           false);
616        builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str());
617        dualSourceOutputWritten = true;
618    }
619
620    ///////////////////////////////////////////////////////////////////////////
621    // combine color and coverage as frag color
622
623    // Get "color * coverage" into fragColor
624    SkString fragColor;
625    GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
626                                                             inColor.c_str(),
627                                                             inCoverage.c_str(),
628                                                             knownColorValue,
629                                                             knownCoverageValue,
630                                                             true);
631    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
632    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == coverageOutput) {
633        SkString dstCoeff;
634        GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
635                                                                NULL,
636                                                                inCoverage.c_str(),
637                                                                kOnes_GrSLConstantVec,
638                                                                knownCoverageValue,
639                                                                true);
640        SkString dstContribution;
641        GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
642                                                                       dstCoeff.c_str(),
643                                                                       builder.dstColor(),
644                                                                       knownDstCoeffValue,
645                                                                       kNone_GrSLConstantVec,
646                                                                       true);
647        SkString oldFragColor = fragColor;
648        fragColor.reset();
649        GrGLSLAddf<4>(&fragColor,
650                      oldFragColor.c_str(),
651                      dstContribution.c_str(),
652                      knownFragColorValue,
653                      knownDstContributionValue,
654                      false);
655    } else {
656        expand_known_value4f(&fragColor, knownFragColorValue);
657    }
658    builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), fragColor.c_str());
659
660    ///////////////////////////////////////////////////////////////////////////
661    // insert GS
662#ifdef SK_DEBUG
663    if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
664        this->genGeometryShader(vertexBuilder);
665    }
666#endif
667
668    ///////////////////////////////////////////////////////////////////////////
669    // compile and setup attribs and unis
670
671    if (!this->compileShaders(builder)) {
672        return false;
673    }
674
675    if (!this->bindOutputsAttribsAndLinkProgram(builder,
676                                                isColorDeclared,
677                                                dualSourceOutputWritten)) {
678        return false;
679    }
680
681    builder.finished(fProgramID);
682    fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
683    fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
684    fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
685    fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
686    // This must be called after we set fDstCopySamplerUni above.
687    this->initSamplerUniforms();
688
689    return true;
690}
691
692bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
693                                                   bool bindColorOut,
694                                                   bool bindDualSrcOut) {
695    GL_CALL_RET(fProgramID, CreateProgram());
696    if (!fProgramID) {
697        return false;
698    }
699
700    if (fVShaderID) {
701        GL_CALL(AttachShader(fProgramID, fVShaderID));
702    }
703    if (fGShaderID) {
704        GL_CALL(AttachShader(fProgramID, fGShaderID));
705    }
706    GL_CALL(AttachShader(fProgramID, fFShaderID));
707
708    if (bindColorOut) {
709        GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
710    }
711    if (bindDualSrcOut) {
712        GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
713    }
714
715    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
716
717    // Bind the attrib locations to same values for all shaders
718    if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
719        GL_CALL(BindAttribLocation(fProgramID,
720                                   header.fPositionAttributeIndex,
721                                   vertexBuilder->positionAttribute().c_str()));
722        if (-1 != header.fLocalCoordAttributeIndex) {
723            GL_CALL(BindAttribLocation(fProgramID,
724                                       header.fLocalCoordAttributeIndex,
725                                       vertexBuilder->localCoordsAttribute().c_str()));
726        }
727        if (-1 != header.fColorAttributeIndex) {
728            GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME));
729        }
730        if (-1 != header.fCoverageAttributeIndex) {
731            GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME));
732        }
733
734        const GrGLShaderBuilder::VertexBuilder::AttributePair* attribEnd = vertexBuilder->getEffectAttributes().end();
735        for (const GrGLShaderBuilder::VertexBuilder::AttributePair* attrib = vertexBuilder->getEffectAttributes().begin();
736             attrib != attribEnd;
737             ++attrib) {
738             GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str()));
739        }
740    }
741
742    GL_CALL(LinkProgram(fProgramID));
743
744    GrGLint linked = GR_GL_INIT_ZERO;
745    GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
746    if (!linked) {
747        GrGLint infoLen = GR_GL_INIT_ZERO;
748        GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
749        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
750        if (infoLen > 0) {
751            // retrieve length even though we don't need it to workaround
752            // bug in chrome cmd buffer param validation.
753            GrGLsizei length = GR_GL_INIT_ZERO;
754            GL_CALL(GetProgramInfoLog(fProgramID,
755                                      infoLen+1,
756                                      &length,
757                                      (char*)log.get()));
758            GrPrintf((char*)log.get());
759        }
760        SkDEBUGFAIL("Error linking program");
761        GL_CALL(DeleteProgram(fProgramID));
762        fProgramID = 0;
763        return false;
764    }
765    return true;
766}
767
768void GrGLProgram::initSamplerUniforms() {
769    GL_CALL(UseProgram(fProgramID));
770    GrGLint texUnitIdx = 0;
771    if (fUniformHandles.fDstCopySamplerUni.isValid()) {
772        fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
773        fDstCopyTexUnit = texUnitIdx++;
774    }
775
776    for (int e = 0; e < fColorEffects.count(); ++e) {
777        this->initEffectSamplerUniforms(&fColorEffects[e], &texUnitIdx);
778    }
779
780    for (int e = 0; e < fCoverageEffects.count(); ++e) {
781        this->initEffectSamplerUniforms(&fCoverageEffects[e], &texUnitIdx);
782    }
783}
784
785void GrGLProgram::initEffectSamplerUniforms(EffectAndSamplers* effect, int* texUnitIdx) {
786    int numSamplers = effect->fSamplerUnis.count();
787    effect->fTextureUnits.reset(numSamplers);
788    for (int s = 0; s < numSamplers; ++s) {
789        UniformHandle handle = effect->fSamplerUnis[s];
790        if (handle.isValid()) {
791            fUniformManager.setSampler(handle, *texUnitIdx);
792            effect->fTextureUnits[s] = (*texUnitIdx)++;
793        }
794    }
795}
796
797///////////////////////////////////////////////////////////////////////////////
798
799void GrGLProgram::setEffectData(const GrEffectStage& stage,
800                                const EffectAndSamplers& effect) {
801
802    // Let the GrGLEffect set its data.
803    bool explicitLocalCoords = -1 != fDesc.getHeader().fLocalCoordAttributeIndex;
804    GrDrawEffect drawEffect(stage, explicitLocalCoords);
805    effect.fGLEffect->setData(fUniformManager, drawEffect);
806
807    // Bind the texures for the effect.
808    int numSamplers = effect.fSamplerUnis.count();
809    SkASSERT((*stage.getEffect())->numTextures() == numSamplers);
810    for (int s = 0; s < numSamplers; ++s) {
811        UniformHandle handle = effect.fSamplerUnis[s];
812        if (handle.isValid()) {
813            const GrTextureAccess& access = (*stage.getEffect())->textureAccess(s);
814            GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
815            int unit = effect.fTextureUnits[s];
816            fGpu->bindTexture(unit, access.getParams(), texture);
817        }
818    }
819}
820
821void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
822                          const GrEffectStage* colorStages[],
823                          const GrEffectStage* coverageStages[],
824                          const GrDeviceCoordTexture* dstCopy,
825                          SharedGLState* sharedState) {
826    const GrDrawState& drawState = fGpu->getDrawState();
827
828    GrColor color;
829    GrColor coverage;
830    if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
831        color = 0;
832        coverage = 0;
833    } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
834        color = 0xffffffff;
835        coverage = drawState.getCoverage();
836    } else {
837        color = drawState.getColor();
838        coverage = drawState.getCoverage();
839    }
840
841    this->setColor(drawState, color, sharedState);
842    this->setCoverage(drawState, coverage, sharedState);
843    this->setMatrixAndRenderTargetHeight(drawState);
844
845    // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
846    if (fUniformHandles.fColorFilterUni.isValid() &&
847        fColorFilterColor != drawState.getColorFilterColor()) {
848        GrGLfloat c[4];
849        GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
850        fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
851        fColorFilterColor = drawState.getColorFilterColor();
852    }
853
854    if (NULL != dstCopy) {
855        if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
856            fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
857                                  static_cast<GrGLfloat>(dstCopy->offset().fX),
858                                  static_cast<GrGLfloat>(dstCopy->offset().fY));
859            fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
860                                  1.f / dstCopy->texture()->width(),
861                                  1.f / dstCopy->texture()->height());
862            GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
863            static GrTextureParams kParams; // the default is clamp, nearest filtering.
864            fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
865        } else {
866            SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
867            SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
868        }
869    } else {
870        SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
871        SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
872        SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
873    }
874
875    for (int e = 0; e < fColorEffects.count(); ++e) {
876        // We may have omitted the GrGLEffect because of the color filter logic in genProgram.
877        // This can be removed when the color filter is an effect.
878        if (NULL != fColorEffects[e].fGLEffect) {
879            this->setEffectData(*colorStages[e], fColorEffects[e]);
880        }
881    }
882
883    for (int e = 0; e < fCoverageEffects.count(); ++e) {
884        if (NULL != fCoverageEffects[e].fGLEffect) {
885            this->setEffectData(*coverageStages[e], fCoverageEffects[e]);
886        }
887    }
888}
889
890void GrGLProgram::setColor(const GrDrawState& drawState,
891                           GrColor color,
892                           SharedGLState* sharedState) {
893    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
894    if (!drawState.hasColorVertexAttribute()) {
895        switch (header.fColorInput) {
896            case GrGLProgramDesc::kAttribute_ColorInput:
897                SkASSERT(-1 != header.fColorAttributeIndex);
898                if (sharedState->fConstAttribColor != color ||
899                    sharedState->fConstAttribColorIndex != header.fColorAttributeIndex) {
900                    // OpenGL ES only supports the float varieties of glVertexAttrib
901                    GrGLfloat c[4];
902                    GrColorToRGBAFloat(color, c);
903                    GL_CALL(VertexAttrib4fv(header.fColorAttributeIndex, c));
904                    sharedState->fConstAttribColor = color;
905                    sharedState->fConstAttribColorIndex = header.fColorAttributeIndex;
906                }
907                break;
908            case GrGLProgramDesc::kUniform_ColorInput:
909                if (fColor != color) {
910                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
911                    GrGLfloat c[4];
912                    GrColorToRGBAFloat(color, c);
913                    fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
914                    fColor = color;
915                }
916                sharedState->fConstAttribColorIndex = -1;
917                break;
918            case GrGLProgramDesc::kSolidWhite_ColorInput:
919            case GrGLProgramDesc::kTransBlack_ColorInput:
920                sharedState->fConstAttribColorIndex = -1;
921                break;
922            default:
923                GrCrash("Unknown color type.");
924        }
925    } else {
926        sharedState->fConstAttribColorIndex = -1;
927    }
928}
929
930void GrGLProgram::setCoverage(const GrDrawState& drawState,
931                              GrColor coverage,
932                              SharedGLState* sharedState) {
933    const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
934    if (!drawState.hasCoverageVertexAttribute()) {
935        switch (header.fCoverageInput) {
936            case GrGLProgramDesc::kAttribute_ColorInput:
937                if (sharedState->fConstAttribCoverage != coverage ||
938                    sharedState->fConstAttribCoverageIndex != header.fCoverageAttributeIndex) {
939                    // OpenGL ES only supports the float varieties of  glVertexAttrib
940                    GrGLfloat c[4];
941                    GrColorToRGBAFloat(coverage, c);
942                    GL_CALL(VertexAttrib4fv(header.fCoverageAttributeIndex, c));
943                    sharedState->fConstAttribCoverage = coverage;
944                    sharedState->fConstAttribCoverageIndex = header.fCoverageAttributeIndex;
945                }
946                break;
947            case GrGLProgramDesc::kUniform_ColorInput:
948                if (fCoverage != coverage) {
949                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
950                    GrGLfloat c[4];
951                    GrColorToRGBAFloat(coverage, c);
952                    fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
953                    fCoverage = coverage;
954                }
955                sharedState->fConstAttribCoverageIndex = -1;
956                break;
957            case GrGLProgramDesc::kSolidWhite_ColorInput:
958            case GrGLProgramDesc::kTransBlack_ColorInput:
959                sharedState->fConstAttribCoverageIndex = -1;
960                break;
961            default:
962                GrCrash("Unknown coverage type.");
963        }
964    } else {
965        sharedState->fConstAttribCoverageIndex = -1;
966    }
967}
968
969void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
970    const GrRenderTarget* rt = drawState.getRenderTarget();
971    SkISize size;
972    size.set(rt->width(), rt->height());
973
974    // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
975    if (fUniformHandles.fRTHeightUni.isValid() &&
976        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
977        fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
978    }
979
980    if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
981        !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
982        fMatrixState.fRenderTargetSize != size) {
983
984        fMatrixState.fViewMatrix = drawState.getViewMatrix();
985        fMatrixState.fRenderTargetSize = size;
986        fMatrixState.fRenderTargetOrigin = rt->origin();
987
988        GrGLfloat viewMatrix[3 * 3];
989        fMatrixState.getGLMatrix<3>(viewMatrix);
990        fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
991    }
992}
993