GrGLProgram.cpp revision af3a3b9fb1f3be46082013a2d1977d12faf1f61c
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 "GrGLEffect.h"
13#include "GrGpuGL.h"
14#include "GrGLShaderVar.h"
15#include "GrBackendEffectFactory.h"
16#include "SkTrace.h"
17#include "SkXfermode.h"
18
19#include "SkRTConf.h"
20
21SK_DEFINE_INST_COUNT(GrGLProgram)
22
23#define GL_CALL(X) GR_GL_CALL(fContext.interface(), X)
24#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContext.interface(), R, X)
25
26SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, "Print the source code for all shaders generated.");
27
28#define TEX_ATTR_NAME "aTexCoord"
29#define COL_ATTR_NAME "aColor"
30#define COV_ATTR_NAME "aCoverage"
31#define EDGE_ATTR_NAME "aEdge"
32
33namespace {
34inline const char* declared_color_output_name() { return "fsColorOut"; }
35inline const char* dual_source_output_name() { return "dualSourceOut"; }
36}
37
38void GrGLProgram::BuildDesc(const GrDrawState& drawState,
39                            bool isPoints,
40                            GrDrawState::BlendOptFlags blendOpts,
41                            GrBlendCoeff srcCoeff,
42                            GrBlendCoeff dstCoeff,
43                            const GrGpuGL* gpu,
44                            Desc* desc) {
45
46    // This should already have been caught
47    GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts));
48
49    bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
50
51    bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag |
52                                           GrDrawState::kEmitCoverage_BlendOptFlag));
53
54    // The descriptor is used as a cache key. Thus when a field of the
55    // descriptor will not affect program generation (because of the vertex
56    // layout in use or other descriptor field settings) it should be set
57    // to a canonical value to avoid duplicate programs with different keys.
58
59    // Must initialize all fields or cache will have false negatives!
60    desc->fVertexLayout = drawState.getVertexLayout();
61
62    desc->fEmitsPointSize = isPoints;
63
64    bool requiresAttributeColors = !skipColor &&
65                                   SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit);
66    bool requiresAttributeCoverage = !skipCoverage &&
67                                     SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit);
68
69    // fColorInput/fCoverageInput records how colors are specified for the program So we strip the
70    // bits from the layout to avoid false negatives when searching for an existing program in the
71    // cache.
72    desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit);
73
74    desc->fColorFilterXfermode = skipColor ?
75                                SkXfermode::kDst_Mode :
76                                drawState.getColorFilterMode();
77
78    // no reason to do edge aa or look at per-vertex coverage if coverage is ignored
79    if (skipCoverage) {
80        desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit |
81                                 GrDrawState::kCoverage_VertexLayoutBit);
82    }
83
84    bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
85    bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
86                             (!requiresAttributeColors && 0xffffffff == drawState.getColor());
87    if (colorIsTransBlack) {
88        desc->fColorInput = Desc::kTransBlack_ColorInput;
89    } else if (colorIsSolidWhite) {
90        desc->fColorInput = Desc::kSolidWhite_ColorInput;
91    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
92        desc->fColorInput = Desc::kUniform_ColorInput;
93    } else {
94        desc->fColorInput = Desc::kAttribute_ColorInput;
95    }
96
97    bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
98
99    if (skipCoverage) {
100        desc->fCoverageInput = Desc::kTransBlack_ColorInput;
101    } else if (covIsSolidWhite) {
102        desc->fCoverageInput = Desc::kSolidWhite_ColorInput;
103    } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
104        desc->fCoverageInput = Desc::kUniform_ColorInput;
105    } else {
106        desc->fCoverageInput = Desc::kAttribute_ColorInput;
107    }
108
109    int lastEnabledStage = -1;
110
111    if (!skipCoverage && (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit)) {
112        desc->fVertexEdgeType = drawState.getVertexEdgeType();
113        desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite();
114    } else {
115        // Use canonical values when edge-aa is not enabled to avoid program cache misses.
116        desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
117        desc->fDiscardIfOutsideEdge = false;
118    }
119
120    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
121
122        bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
123        if (!skip && drawState.isStageEnabled(s)) {
124            lastEnabledStage = s;
125            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
126            const GrBackendEffectFactory& factory = effect->getFactory();
127            desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), gpu->glCaps());
128        } else {
129            desc->fEffectKeys[s] = 0;
130        }
131    }
132
133    desc->fDualSrcOutput = Desc::kNone_DualSrcOutput;
134
135    // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
136    // other than pass through values from the VS to the FS anyway).
137#if GR_GL_EXPERIMENTAL_GS
138#if 0
139    desc->fExperimentalGS = gpu->getCaps().geometryShaderSupport();
140#else
141    desc->fExperimentalGS = false;
142#endif
143#endif
144
145    // We want to avoid generating programs with different "first cov stage" values when they would
146    // compute the same result. We set field in the desc to kNumStages when either there are no
147    // coverage stages or the distinction between coverage and color is immaterial.
148    int firstCoverageStage = GrDrawState::kNumStages;
149    desc->fFirstCoverageStage = GrDrawState::kNumStages;
150    bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
151    if (hasCoverage) {
152        firstCoverageStage = drawState.getFirstCoverageStage();
153    }
154
155    // other coverage inputs
156    if (!hasCoverage) {
157        hasCoverage = requiresAttributeCoverage ||
158                      (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit);
159    }
160
161    if (hasCoverage) {
162        // color filter is applied between color/coverage computation
163        if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
164            desc->fFirstCoverageStage = firstCoverageStage;
165        }
166
167        if (gpu->getCaps().dualSourceBlendingSupport() &&
168            !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
169                           GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
170            if (kZero_GrBlendCoeff == dstCoeff) {
171                // write the coverage value to second color
172                desc->fDualSrcOutput =  Desc::kCoverage_DualSrcOutput;
173                desc->fFirstCoverageStage = firstCoverageStage;
174            } else if (kSA_GrBlendCoeff == dstCoeff) {
175                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
176                desc->fDualSrcOutput = Desc::kCoverageISA_DualSrcOutput;
177                desc->fFirstCoverageStage = firstCoverageStage;
178            } else if (kSC_GrBlendCoeff == dstCoeff) {
179                // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
180                desc->fDualSrcOutput = Desc::kCoverageISC_DualSrcOutput;
181                desc->fFirstCoverageStage = firstCoverageStage;
182            }
183        }
184    }
185}
186
187GrGLProgram* GrGLProgram::Create(const GrGLContext& gl,
188                                 const Desc& desc,
189                                 const GrEffectStage* stages[]) {
190    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages));
191    if (!program->succeeded()) {
192        delete program;
193        program = NULL;
194    }
195    return program;
196}
197
198GrGLProgram::GrGLProgram(const GrGLContext& gl,
199                         const Desc& desc,
200                         const GrEffectStage* stages[])
201: fContext(gl)
202, fUniformManager(gl) {
203    fDesc = desc;
204    fVShaderID = 0;
205    fGShaderID = 0;
206    fFShaderID = 0;
207    fProgramID = 0;
208
209    fColor = GrColor_ILLEGAL;
210    fColorFilterColor = GrColor_ILLEGAL;
211
212    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
213        fEffects[s] = NULL;
214    }
215
216    this->genProgram(stages);
217}
218
219GrGLProgram::~GrGLProgram() {
220    if (fVShaderID) {
221        GL_CALL(DeleteShader(fVShaderID));
222    }
223    if (fGShaderID) {
224        GL_CALL(DeleteShader(fGShaderID));
225    }
226    if (fFShaderID) {
227        GL_CALL(DeleteShader(fFShaderID));
228    }
229    if (fProgramID) {
230        GL_CALL(DeleteProgram(fProgramID));
231    }
232
233    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
234        delete fEffects[i];
235    }
236}
237
238void GrGLProgram::abandon() {
239    fVShaderID = 0;
240    fGShaderID = 0;
241    fFShaderID = 0;
242    fProgramID = 0;
243}
244
245void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
246                                GrBlendCoeff* dstCoeff) const {
247    switch (fDesc.fDualSrcOutput) {
248        case Desc::kNone_DualSrcOutput:
249            break;
250        // the prog will write a coverage value to the secondary
251        // output and the dst is blended by one minus that value.
252        case Desc::kCoverage_DualSrcOutput:
253        case Desc::kCoverageISA_DualSrcOutput:
254        case Desc::kCoverageISC_DualSrcOutput:
255        *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
256        break;
257        default:
258            GrCrash("Unexpected dual source blend output");
259            break;
260    }
261}
262
263namespace {
264
265// given two blend coeffecients determine whether the src
266// and/or dst computation can be omitted.
267inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
268                              SkXfermode::Coeff dstCoeff,
269                              bool* needSrcValue,
270                              bool* needDstValue) {
271    if (SkXfermode::kZero_Coeff == srcCoeff) {
272        switch (dstCoeff) {
273            // these all read the src
274            case SkXfermode::kSC_Coeff:
275            case SkXfermode::kISC_Coeff:
276            case SkXfermode::kSA_Coeff:
277            case SkXfermode::kISA_Coeff:
278                *needSrcValue = true;
279                break;
280            default:
281                *needSrcValue = false;
282                break;
283        }
284    } else {
285        *needSrcValue = true;
286    }
287    if (SkXfermode::kZero_Coeff == dstCoeff) {
288        switch (srcCoeff) {
289            // these all read the dst
290            case SkXfermode::kDC_Coeff:
291            case SkXfermode::kIDC_Coeff:
292            case SkXfermode::kDA_Coeff:
293            case SkXfermode::kIDA_Coeff:
294                *needDstValue = true;
295                break;
296            default:
297                *needDstValue = false;
298                break;
299        }
300    } else {
301        *needDstValue = true;
302    }
303}
304
305/**
306 * Create a blend_coeff * value string to be used in shader code. Sets empty
307 * string if result is trivially zero.
308 */
309inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
310                       const char* src, const char* dst,
311                       const char* value) {
312    switch (coeff) {
313    case SkXfermode::kZero_Coeff:    /** 0 */
314        *str = "";
315        break;
316    case SkXfermode::kOne_Coeff:     /** 1 */
317        *str = value;
318        break;
319    case SkXfermode::kSC_Coeff:
320        str->printf("(%s * %s)", src, value);
321        break;
322    case SkXfermode::kISC_Coeff:
323        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
324        break;
325    case SkXfermode::kDC_Coeff:
326        str->printf("(%s * %s)", dst, value);
327        break;
328    case SkXfermode::kIDC_Coeff:
329        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
330        break;
331    case SkXfermode::kSA_Coeff:      /** src alpha */
332        str->printf("(%s.a * %s)", src, value);
333        break;
334    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
335        str->printf("((1.0 - %s.a) * %s)", src, value);
336        break;
337    case SkXfermode::kDA_Coeff:      /** dst alpha */
338        str->printf("(%s.a * %s)", dst, value);
339        break;
340    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
341        str->printf("((1.0 - %s.a) * %s)", dst, value);
342        break;
343    default:
344        GrCrash("Unexpected xfer coeff.");
345        break;
346    }
347}
348/**
349 * Adds a line to the fragment shader code which modifies the color by
350 * the specified color filter.
351 */
352void add_color_filter(SkString* fsCode, const char * outputVar,
353                      SkXfermode::Coeff uniformCoeff,
354                      SkXfermode::Coeff colorCoeff,
355                      const char* filterColor,
356                      const char* inColor) {
357    SkString colorStr, constStr;
358    blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
359    blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
360
361    fsCode->appendf("\t%s = ", outputVar);
362    GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str());
363    fsCode->append(";\n");
364}
365}
366
367bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
368                                  GrGLShaderBuilder* builder) const {
369    if (fDesc.fVertexLayout & GrDrawState::kEdge_VertexLayoutBit) {
370        const char *vsName, *fsName;
371        builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
372        builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
373                                          GrGLShaderVar::kAttribute_TypeModifier,
374                                          EDGE_ATTR_NAME);
375        builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
376        switch (fDesc.fVertexEdgeType) {
377        case GrDrawState::kHairLine_EdgeType:
378            builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName);
379            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
380            break;
381        case GrDrawState::kQuad_EdgeType:
382            builder->fFSCode.append("\tfloat edgeAlpha;\n");
383            // keep the derivative instructions outside the conditional
384            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
385            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
386            builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
387            // today we know z and w are in device space. We could use derivatives
388            builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
389            builder->fFSCode.append ("\t} else {\n");
390            builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
391                                     "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
392                                     fsName, fsName);
393            builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
394            builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
395                                    "\t}\n");
396            if (kES2_GrGLBinding == fContext.info().binding()) {
397                builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
398            }
399            break;
400        case GrDrawState::kHairQuad_EdgeType:
401            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
402            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
403            builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
404                                     "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
405                                     fsName, fsName);
406            builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
407            builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
408            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
409            if (kES2_GrGLBinding == fContext.info().binding()) {
410                builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
411            }
412            break;
413        case GrDrawState::kCircle_EdgeType:
414            builder->fFSCode.append("\tfloat edgeAlpha;\n");
415            builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName);
416            builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
417            builder->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
418            builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
419            break;
420        case GrDrawState::kEllipse_EdgeType:
421            builder->fFSCode.append("\tfloat edgeAlpha;\n");
422            builder->fFSCode.appendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
423            builder->fFSCode.appendf("\toffset.y *= %s.w;\n", fsName);
424            builder->fFSCode.append("\tfloat d = length(offset);\n");
425            builder->fFSCode.appendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
426            break;
427        default:
428            GrCrash("Unknown Edge Type!");
429            break;
430        }
431        if (fDesc.fDiscardIfOutsideEdge) {
432            builder->fFSCode.appendf("\tif (edgeAlpha <= 0.0) {\n\t\tdiscard;\n\t}\n");
433        }
434        *coverageVar = "edgeAlpha";
435        return true;
436    } else {
437        coverageVar->reset();
438        return false;
439    }
440}
441
442void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
443    switch (fDesc.fColorInput) {
444        case GrGLProgram::Desc::kAttribute_ColorInput: {
445            builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
446                GrGLShaderVar::kAttribute_TypeModifier,
447                COL_ATTR_NAME);
448            const char *vsName, *fsName;
449            builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
450            builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
451            *inColor = fsName;
452            } break;
453        case GrGLProgram::Desc::kUniform_ColorInput: {
454            const char* name;
455            fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
456                                                            kVec4f_GrSLType, "Color", &name);
457            *inColor = name;
458            break;
459        }
460        case GrGLProgram::Desc::kTransBlack_ColorInput:
461            GrAssert(!"needComputedColor should be false.");
462            break;
463        case GrGLProgram::Desc::kSolidWhite_ColorInput:
464            break;
465        default:
466            GrCrash("Unknown color type.");
467            break;
468    }
469}
470
471void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
472    const char* covUniName;
473    fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
474                                                       kVec4f_GrSLType, "Coverage", &covUniName);
475    if (inOutCoverage->size()) {
476        builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
477                                  covUniName, inOutCoverage->c_str());
478        *inOutCoverage = "uniCoverage";
479    } else {
480        *inOutCoverage = covUniName;
481    }
482}
483
484namespace {
485void gen_attribute_coverage(GrGLShaderBuilder* segments,
486                            SkString* inOutCoverage) {
487    segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
488                                       GrGLShaderVar::kAttribute_TypeModifier,
489                                       COV_ATTR_NAME);
490    const char *vsName, *fsName;
491    segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
492    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
493    if (inOutCoverage->size()) {
494        segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
495                                  fsName, inOutCoverage->c_str());
496        *inOutCoverage = "attrCoverage";
497    } else {
498        *inOutCoverage = fsName;
499    }
500}
501}
502
503void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const {
504#if GR_GL_EXPERIMENTAL_GS
505    if (fDesc.fExperimentalGS) {
506        GrAssert(fContext.info().glslGeneration() >= k150_GrGLSLGeneration);
507        segments->fGSHeader.append("layout(triangles) in;\n"
508                                   "layout(triangle_strip, max_vertices = 6) out;\n");
509        segments->fGSCode.append("\tfor (int i = 0; i < 3; ++i) {\n"
510                                 "\t\tgl_Position = gl_in[i].gl_Position;\n");
511        if (fDesc.fEmitsPointSize) {
512            segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
513        }
514        GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
515        int count = segments->fGSInputs.count();
516        for (int i = 0; i < count; ++i) {
517            segments->fGSCode.appendf("\t\t%s = %s[i];\n",
518                                      segments->fGSOutputs[i].getName().c_str(),
519                                      segments->fGSInputs[i].getName().c_str());
520        }
521        segments->fGSCode.append("\t\tEmitVertex();\n"
522                                 "\t}\n"
523                                 "\tEndPrimitive();\n");
524    }
525#endif
526}
527
528const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
529    if (inColor.size()) {
530          return inColor.c_str();
531    } else {
532        if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
533            return GrGLSLOnesVecf(4);
534        } else {
535            return GrGLSLZerosVecf(4);
536        }
537    }
538}
539
540namespace {
541// prints a shader using params similar to glShaderSource
542void print_shader(GrGLint stringCnt,
543                  const GrGLchar** strings,
544                  GrGLint* stringLengths) {
545    for (int i = 0; i < stringCnt; ++i) {
546        if (NULL == stringLengths || stringLengths[i] < 0) {
547            GrPrintf(strings[i]);
548        } else {
549            GrPrintf("%.*s", stringLengths[i], strings[i]);
550        }
551    }
552}
553
554// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
555GrGLuint compile_shader(const GrGLContext& gl,
556                        GrGLenum type,
557                        int stringCnt,
558                        const char** strings,
559                        int* stringLengths) {
560    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
561                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
562
563    GrGLuint shader;
564    GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type));
565    if (0 == shader) {
566        return 0;
567    }
568
569    const GrGLInterface* gli = gl.interface();
570    GrGLint compiled = GR_GL_INIT_ZERO;
571    GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths));
572    GR_GL_CALL(gli, CompileShader(shader));
573    GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
574
575    if (!compiled) {
576        GrGLint infoLen = GR_GL_INIT_ZERO;
577        GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
578        SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
579        if (infoLen > 0) {
580            // retrieve length even though we don't need it to workaround bug in chrome cmd buffer
581            // param validation.
582            GrGLsizei length = GR_GL_INIT_ZERO;
583            GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1,
584                                             &length, (char*)log.get()));
585            print_shader(stringCnt, strings, stringLengths);
586            GrPrintf("\n%s", log.get());
587        }
588        GrAssert(!"Shader compilation failed!");
589        GR_GL_CALL(gli, DeleteShader(shader));
590        return 0;
591    }
592    return shader;
593}
594
595// helper version of above for when shader is already flattened into a single SkString
596GrGLuint compile_shader(const GrGLContext& gl, GrGLenum type, const SkString& shader) {
597    const GrGLchar* str = shader.c_str();
598    int length = shader.size();
599    return compile_shader(gl, type, 1, &str, &length);
600}
601
602}
603
604// compiles all the shaders from builder and stores the shader IDs
605bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
606
607    SkString shader;
608
609    builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader);
610    if (c_PrintShaders) {
611        GrPrintf(shader.c_str());
612        GrPrintf("\n");
613    }
614
615    if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) {
616        return false;
617    }
618
619    if (builder.fUsesGS) {
620        builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader);
621        if (c_PrintShaders) {
622            GrPrintf(shader.c_str());
623            GrPrintf("\n");
624        }
625        if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) {
626            return false;
627        }
628    } else {
629        fGShaderID = 0;
630    }
631
632    builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
633    if (c_PrintShaders) {
634        GrPrintf(shader.c_str());
635        GrPrintf("\n");
636    }
637    if (!(fFShaderID = compile_shader(fContext, GR_GL_FRAGMENT_SHADER, shader))) {
638        return false;
639    }
640
641    return true;
642}
643
644bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
645    GrAssert(0 == fProgramID);
646
647    GrGLShaderBuilder builder(fContext.info(), fUniformManager);
648    const uint32_t& layout = fDesc.fVertexLayout;
649
650#if GR_GL_EXPERIMENTAL_GS
651    builder.fUsesGS = fDesc.fExperimentalGS;
652#endif
653
654    SkXfermode::Coeff colorCoeff, uniformCoeff;
655    // The rest of transfer mode color filters have not been implemented
656    if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
657        GR_DEBUGCODE(bool success =)
658            SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
659                                    (fDesc.fColorFilterXfermode),
660                                    &uniformCoeff, &colorCoeff);
661        GR_DEBUGASSERT(success);
662    } else {
663        colorCoeff = SkXfermode::kOne_Coeff;
664        uniformCoeff = SkXfermode::kZero_Coeff;
665    }
666
667    // no need to do the color filter if coverage is 0. The output color is scaled by the coverage.
668    // All the dual source outputs are scaled by the coverage as well.
669    if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
670        colorCoeff = SkXfermode::kZero_Coeff;
671        uniformCoeff = SkXfermode::kZero_Coeff;
672    }
673
674    // If we know the final color is going to be all zeros then we can
675    // simplify the color filter coefficients. needComputedColor will then
676    // come out false below.
677    if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
678        colorCoeff = SkXfermode::kZero_Coeff;
679        if (SkXfermode::kDC_Coeff == uniformCoeff ||
680            SkXfermode::kDA_Coeff == uniformCoeff) {
681            uniformCoeff = SkXfermode::kZero_Coeff;
682        } else if (SkXfermode::kIDC_Coeff == uniformCoeff ||
683                   SkXfermode::kIDA_Coeff == uniformCoeff) {
684            uniformCoeff = SkXfermode::kOne_Coeff;
685        }
686    }
687
688    bool needColorFilterUniform;
689    bool needComputedColor;
690    need_blend_inputs(uniformCoeff, colorCoeff,
691                      &needColorFilterUniform, &needComputedColor);
692
693    // the dual source output has no canonical var name, have to
694    // declare an output, which is incompatible with gl_FragColor/gl_FragData.
695    bool dualSourceOutputWritten = false;
696    builder.fHeader.append(GrGetGLSLVersionDecl(fContext.info().binding(),
697                                                fContext.info().glslGeneration()));
698
699    GrGLShaderVar colorOutput;
700    bool isColorDeclared = GrGLSLSetupFSColorOuput(fContext.info().glslGeneration(),
701                                                   declared_color_output_name(),
702                                                   &colorOutput);
703    if (isColorDeclared) {
704        builder.fFSOutputs.push_back(colorOutput);
705    }
706
707    const char* viewMName;
708    fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
709                                                        kMat33f_GrSLType, "ViewM", &viewMName);
710
711
712    builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
713                            "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
714                            viewMName, builder.positionAttribute().getName().c_str());
715
716    // incoming color to current stage being processed.
717    SkString inColor;
718
719    if (needComputedColor) {
720        this->genInputColor(&builder, &inColor);
721    }
722
723    // we output point size in the GS if present
724    if (fDesc.fEmitsPointSize && !builder.fUsesGS){
725        builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
726    }
727
728    // add texture coordinates that are used to the list of vertex attr decls
729    if (GrDrawState::VertexUsesTexCoords(layout)) {
730        builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
731            GrGLShaderVar::kAttribute_TypeModifier,
732            TEX_ATTR_NAME);
733    }
734
735    ///////////////////////////////////////////////////////////////////////////
736    // compute the final color
737
738    // if we have color stages string them together, feeding the output color
739    // of each to the next and generating code for each stage.
740    if (needComputedColor) {
741        SkString outColor;
742        for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
743            if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) {
744                // create var to hold stage result
745                outColor = "color";
746                outColor.appendS32(s);
747                builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
748
749                const char* inCoords;
750                // figure out what our input coords are
751                if (!GrDrawState::StageUsesTexCoords(layout, s)) {
752                    inCoords = builder.positionAttribute().c_str();
753                } else {
754                    // must have input tex coordinates if stage is enabled.
755                    inCoords = TEX_ATTR_NAME;
756                }
757
758                builder.setCurrentStage(s);
759                fEffects[s] = builder.createAndEmitGLEffect(*stages[s],
760                                                            fDesc.fEffectKeys[s],
761                                                            inColor.size() ? inColor.c_str() : NULL,
762                                                            outColor.c_str(),
763                                                            inCoords,
764                                                            &fUniformHandles.fSamplerUnis[s]);
765                builder.setNonStage();
766                inColor = outColor;
767            }
768        }
769    }
770
771    // if have all ones or zeros for the "dst" input to the color filter then we
772    // may be able to make additional optimizations.
773    if (needColorFilterUniform && needComputedColor && !inColor.size()) {
774        GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
775        bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
776                                  SkXfermode::kIDA_Coeff == uniformCoeff;
777        if (uniformCoeffIsZero) {
778            uniformCoeff = SkXfermode::kZero_Coeff;
779            bool bogus;
780            need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff,
781                              &needColorFilterUniform, &bogus);
782        }
783    }
784    const char* colorFilterColorUniName = NULL;
785    if (needColorFilterUniform) {
786        fUniformHandles.fColorFilterUni = builder.addUniform(
787                                                        GrGLShaderBuilder::kFragment_ShaderType,
788                                                        kVec4f_GrSLType, "FilterColor",
789                                                        &colorFilterColorUniName);
790    }
791    bool wroteFragColorZero = false;
792    if (SkXfermode::kZero_Coeff == uniformCoeff &&
793        SkXfermode::kZero_Coeff == colorCoeff) {
794        builder.fFSCode.appendf("\t%s = %s;\n",
795                                colorOutput.getName().c_str(),
796                                GrGLSLZerosVecf(4));
797        wroteFragColorZero = true;
798    } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
799        builder.fFSCode.append("\tvec4 filteredColor;\n");
800        const char* color = adjustInColor(inColor);
801        add_color_filter(&builder.fFSCode, "filteredColor", uniformCoeff,
802                       colorCoeff, colorFilterColorUniName, color);
803        inColor = "filteredColor";
804    }
805
806    ///////////////////////////////////////////////////////////////////////////
807    // compute the partial coverage (coverage stages and edge aa)
808
809    SkString inCoverage;
810    bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput;
811    // we don't need to compute coverage at all if we know the final shader
812    // output will be zero and we don't have a dual src blend output.
813    if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
814
815        if (!coverageIsZero) {
816            bool inCoverageIsScalar  = this->genEdgeCoverage(&inCoverage, &builder);
817
818            switch (fDesc.fCoverageInput) {
819                case Desc::kSolidWhite_ColorInput:
820                    // empty string implies solid white
821                    break;
822                case Desc::kAttribute_ColorInput:
823                    gen_attribute_coverage(&builder, &inCoverage);
824                    inCoverageIsScalar = false;
825                    break;
826                case Desc::kUniform_ColorInput:
827                    this->genUniformCoverage(&builder, &inCoverage);
828                    inCoverageIsScalar = false;
829                    break;
830                default:
831                    GrCrash("Unexpected input coverage.");
832            }
833
834            SkString outCoverage;
835            const int& startStage = fDesc.fFirstCoverageStage;
836            for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
837                if (fDesc.fEffectKeys[s]) {
838                    // create var to hold stage output
839                    outCoverage = "coverage";
840                    outCoverage.appendS32(s);
841                    builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str());
842
843                    const char* inCoords;
844                    // figure out what our input coords are
845                    if (!GrDrawState::StageUsesTexCoords(layout, s)) {
846                        inCoords = builder.positionAttribute().c_str();
847                    } else {
848                        // must have input tex coordinates if stage is
849                        // enabled.
850                        inCoords = TEX_ATTR_NAME;
851                    }
852
853                    // stages don't know how to deal with a scalar input. (Maybe they should. We
854                    // could pass a GrGLShaderVar)
855                    if (inCoverageIsScalar) {
856                        builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n",
857                                                inCoverage.c_str(), inCoverage.c_str());
858                        inCoverage.append("4");
859                    }
860                    builder.setCurrentStage(s);
861                    fEffects[s] = builder.createAndEmitGLEffect(
862                                                    *stages[s],
863                                                    fDesc.fEffectKeys[s],
864                                                    inCoverage.size() ? inCoverage.c_str() : NULL,
865                                                    outCoverage.c_str(),
866                                                    inCoords,
867                                                    &fUniformHandles.fSamplerUnis[s]);
868                    builder.setNonStage();
869                    inCoverage = outCoverage;
870                }
871            }
872        }
873
874        if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
875            builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
876                                               GrGLShaderVar::kOut_TypeModifier,
877                                               dual_source_output_name());
878            bool outputIsZero = coverageIsZero;
879            SkString coeff;
880            if (!outputIsZero &&
881                Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
882                if (!inColor.size()) {
883                    outputIsZero = true;
884                } else {
885                    if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
886                        coeff.printf("(1 - %s.a)", inColor.c_str());
887                    } else {
888                        coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
889                    }
890                }
891            }
892            if (outputIsZero) {
893                builder.fFSCode.appendf("\t%s = %s;\n",
894                                        dual_source_output_name(),
895                                        GrGLSLZerosVecf(4));
896            } else {
897                builder.fFSCode.appendf("\t%s =", dual_source_output_name());
898                GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str());
899                builder.fFSCode.append(";\n");
900            }
901            dualSourceOutputWritten = true;
902        }
903    }
904
905    ///////////////////////////////////////////////////////////////////////////
906    // combine color and coverage as frag color
907
908    if (!wroteFragColorZero) {
909        if (coverageIsZero) {
910            builder.fFSCode.appendf("\t%s = %s;\n",
911                                    colorOutput.getName().c_str(),
912                                    GrGLSLZerosVecf(4));
913        } else {
914            builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str());
915            GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str());
916            builder.fFSCode.append(";\n");
917        }
918    }
919
920    ///////////////////////////////////////////////////////////////////////////
921    // insert GS
922#if GR_DEBUG
923    this->genGeometryShader(&builder);
924#endif
925
926    ///////////////////////////////////////////////////////////////////////////
927    // compile and setup attribs and unis
928
929    if (!this->compileShaders(builder)) {
930        return false;
931    }
932
933    if (!this->bindOutputsAttribsAndLinkProgram(builder,
934                                                isColorDeclared,
935                                                dualSourceOutputWritten)) {
936        return false;
937    }
938
939    builder.finished(fProgramID);
940    this->initSamplerUniforms();
941    fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
942
943    return true;
944}
945
946bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
947                                                   bool bindColorOut,
948                                                   bool bindDualSrcOut) {
949    GL_CALL_RET(fProgramID, CreateProgram());
950    if (!fProgramID) {
951        return false;
952    }
953
954    GL_CALL(AttachShader(fProgramID, fVShaderID));
955    if (fGShaderID) {
956        GL_CALL(AttachShader(fProgramID, fGShaderID));
957    }
958    GL_CALL(AttachShader(fProgramID, fFShaderID));
959
960    if (bindColorOut) {
961        GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
962    }
963    if (bindDualSrcOut) {
964        GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
965    }
966
967    // Bind the attrib locations to same values for all shaders
968    GL_CALL(BindAttribLocation(fProgramID,
969                               kPositionAttributeIndex,
970                               builder.positionAttribute().c_str()));
971    GL_CALL(BindAttribLocation(fProgramID, kTexCoordAttributeIndex, TEX_ATTR_NAME));
972    GL_CALL(BindAttribLocation(fProgramID, kColorAttributeIndex, COL_ATTR_NAME));
973    GL_CALL(BindAttribLocation(fProgramID, kCoverageAttributeIndex, COV_ATTR_NAME));
974    GL_CALL(BindAttribLocation(fProgramID, kEdgeAttributeIndex, EDGE_ATTR_NAME));
975
976    GL_CALL(LinkProgram(fProgramID));
977
978    GrGLint linked = GR_GL_INIT_ZERO;
979    GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
980    if (!linked) {
981        GrGLint infoLen = GR_GL_INIT_ZERO;
982        GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
983        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
984        if (infoLen > 0) {
985            // retrieve length even though we don't need it to workaround
986            // bug in chrome cmd buffer param validation.
987            GrGLsizei length = GR_GL_INIT_ZERO;
988            GL_CALL(GetProgramInfoLog(fProgramID,
989                                      infoLen+1,
990                                      &length,
991                                      (char*)log.get()));
992            GrPrintf((char*)log.get());
993        }
994        GrAssert(!"Error linking program");
995        GL_CALL(DeleteProgram(fProgramID));
996        fProgramID = 0;
997        return false;
998    }
999    return true;
1000}
1001
1002void GrGLProgram::initSamplerUniforms() {
1003    GL_CALL(UseProgram(fProgramID));
1004    // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes this
1005    // behavior.
1006    GrGLint texUnitIdx = 0;
1007    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1008        int numSamplers = fUniformHandles.fSamplerUnis[s].count();
1009        for (int u = 0; u < numSamplers; ++u) {
1010            UniformHandle handle = fUniformHandles.fSamplerUnis[s][u];
1011            if (GrGLUniformManager::kInvalidUniformHandle != handle) {
1012                fUniformManager.setSampler(handle, texUnitIdx);
1013                ++texUnitIdx;
1014            }
1015        }
1016    }
1017}
1018
1019///////////////////////////////////////////////////////////////////////////////
1020
1021void GrGLProgram::setData(GrGpuGL* gpu,
1022                          GrColor color,
1023                          GrColor coverage,
1024                          SharedGLState* sharedState) {
1025    const GrDrawState& drawState = gpu->getDrawState();
1026
1027    this->setColor(drawState, color, sharedState);
1028    this->setCoverage(drawState, coverage, sharedState);
1029    this->setMatrixAndRenderTargetHeight(drawState);
1030
1031    // Setup the SkXfermode::Mode-based colorfilter uniform if necessary
1032    if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fColorFilterUni &&
1033        fColorFilterColor != drawState.getColorFilterColor()) {
1034        GrGLfloat c[4];
1035        GrColorToRGBAFloat(drawState.getColorFilterColor(), c);
1036        fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c);
1037        fColorFilterColor = drawState.getColorFilterColor();
1038    }
1039
1040    GrGLint texUnitIdx = 0;
1041    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1042        if (NULL != fEffects[s]) {
1043            const GrEffectStage& stage = drawState.getStage(s);
1044            GrAssert(NULL != stage.getEffect());
1045            fEffects[s]->setData(fUniformManager, stage);
1046            int numSamplers = fUniformHandles.fSamplerUnis[s].count();
1047            for (int u = 0; u < numSamplers; ++u) {
1048                UniformHandle handle = fUniformHandles.fSamplerUnis[s][u];
1049                if (GrGLUniformManager::kInvalidUniformHandle != handle) {
1050                    const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u);
1051                    GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
1052                    gpu->bindTexture(texUnitIdx, access.getParams(), texture);
1053                    ++texUnitIdx;
1054                }
1055            }
1056        }
1057    }
1058}
1059
1060void GrGLProgram::setColor(const GrDrawState& drawState,
1061                           GrColor color,
1062                           SharedGLState* sharedState) {
1063    if (!(drawState.getVertexLayout() & GrDrawState::kColor_VertexLayoutBit)) {
1064        switch (fDesc.fColorInput) {
1065            case GrGLProgram::Desc::kAttribute_ColorInput:
1066                if (sharedState->fConstAttribColor != color) {
1067                    // OpenGL ES only supports the float varieties of glVertexAttrib
1068                    GrGLfloat c[4];
1069                    GrColorToRGBAFloat(color, c);
1070                    GL_CALL(VertexAttrib4fv(kColorAttributeIndex, c));
1071                    sharedState->fConstAttribColor = color;
1072                }
1073                break;
1074            case GrGLProgram::Desc::kUniform_ColorInput:
1075                if (fColor != color) {
1076                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
1077                    GrGLfloat c[4];
1078                    GrColorToRGBAFloat(color, c);
1079                    GrAssert(GrGLUniformManager::kInvalidUniformHandle !=
1080                             fUniformHandles.fColorUni);
1081                    fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
1082                    fColor = color;
1083                }
1084                break;
1085            case GrGLProgram::Desc::kSolidWhite_ColorInput:
1086            case GrGLProgram::Desc::kTransBlack_ColorInput:
1087                break;
1088            default:
1089                GrCrash("Unknown color type.");
1090        }
1091    }
1092}
1093
1094void GrGLProgram::setCoverage(const GrDrawState& drawState,
1095                              GrColor coverage,
1096                              SharedGLState* sharedState) {
1097    if (!(drawState.getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit)) {
1098        switch (fDesc.fCoverageInput) {
1099            case Desc::kAttribute_ColorInput:
1100                if (sharedState->fConstAttribCoverage != coverage) {
1101                    // OpenGL ES only supports the float varieties of  glVertexAttrib
1102                    GrGLfloat c[4];
1103                    GrColorToRGBAFloat(coverage, c);
1104                    GL_CALL(VertexAttrib4fv(kCoverageAttributeIndex, c));
1105                    sharedState->fConstAttribCoverage = coverage;
1106                }
1107                break;
1108            case Desc::kUniform_ColorInput:
1109                if (fCoverage != coverage) {
1110                    // OpenGL ES doesn't support unsigned byte varieties of glUniform
1111                    GrGLfloat c[4];
1112                    GrColorToRGBAFloat(coverage, c);
1113                    GrAssert(GrGLUniformManager::kInvalidUniformHandle !=
1114                             fUniformHandles.fCoverageUni);
1115                    fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
1116                    fCoverage = coverage;
1117                }
1118                break;
1119            case Desc::kSolidWhite_ColorInput:
1120            case Desc::kTransBlack_ColorInput:
1121                break;
1122            default:
1123                GrCrash("Unknown coverage type.");
1124        }
1125    }
1126}
1127
1128void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
1129    const GrRenderTarget* rt = drawState.getRenderTarget();
1130    SkISize size;
1131    size.set(rt->width(), rt->height());
1132
1133    // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
1134    if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni &&
1135        fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
1136        fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
1137    }
1138
1139    if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
1140        !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
1141        fMatrixState.fRenderTargetSize != size) {
1142        SkMatrix m;
1143        if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
1144            m.setAll(
1145                SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1,
1146                0,-SkIntToScalar(2) / size.fHeight, SK_Scalar1,
1147            0, 0, SkMatrix::I()[8]);
1148        } else {
1149            m.setAll(
1150                SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1,
1151                0, SkIntToScalar(2) / size.fHeight,-SK_Scalar1,
1152            0, 0, SkMatrix::I()[8]);
1153        }
1154        m.setConcat(m, drawState.getViewMatrix());
1155
1156        // ES doesn't allow you to pass true to the transpose param so we do our own transpose.
1157        GrGLfloat mt[]  = {
1158            SkScalarToFloat(m[SkMatrix::kMScaleX]),
1159            SkScalarToFloat(m[SkMatrix::kMSkewY]),
1160            SkScalarToFloat(m[SkMatrix::kMPersp0]),
1161            SkScalarToFloat(m[SkMatrix::kMSkewX]),
1162            SkScalarToFloat(m[SkMatrix::kMScaleY]),
1163            SkScalarToFloat(m[SkMatrix::kMPersp1]),
1164            SkScalarToFloat(m[SkMatrix::kMTransX]),
1165            SkScalarToFloat(m[SkMatrix::kMTransY]),
1166            SkScalarToFloat(m[SkMatrix::kMPersp2])
1167        };
1168        fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, mt);
1169        fMatrixState.fViewMatrix = drawState.getViewMatrix();
1170        fMatrixState.fRenderTargetSize = size;
1171        fMatrixState.fRenderTargetOrigin = rt->origin();
1172    }
1173}
1174