GrGLProgram.cpp revision ed8659b51d9f2bad3f004df6033d72cc32d71c0d
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(fContextInfo.interface(), X)
24#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContextInfo.interface(), R, X)
25
26SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, "Print the source code for all shaders generated.");
27
28#define COL_ATTR_NAME "aColor"
29#define COV_ATTR_NAME "aCoverage"
30#define EDGE_ATTR_NAME "aEdge"
31
32namespace {
33inline void tex_attr_name(int coordIdx, SkString* s) {
34    *s = "aTexCoord";
35    s->appendS32(coordIdx);
36}
37
38inline const char* declared_color_output_name() { return "fsColorOut"; }
39inline const char* dual_source_output_name() { return "dualSourceOut"; }
40
41}
42
43GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl,
44                                 const Desc& desc,
45                                 const GrEffectStage* stages[]) {
46    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages));
47    if (!program->succeeded()) {
48        delete program;
49        program = NULL;
50    }
51    return program;
52}
53
54GrGLProgram::GrGLProgram(const GrGLContextInfo& gl,
55                         const Desc& desc,
56                         const GrEffectStage* stages[])
57: fContextInfo(gl)
58, fUniformManager(gl) {
59    fDesc = desc;
60    fVShaderID = 0;
61    fGShaderID = 0;
62    fFShaderID = 0;
63    fProgramID = 0;
64
65    fViewMatrix = SkMatrix::InvalidMatrix();
66    fViewportSize.set(-1, -1);
67    fOrigin = (GrSurfaceOrigin) -1;
68    fColor = GrColor_ILLEGAL;
69    fColorFilterColor = GrColor_ILLEGAL;
70    fRTHeight = -1;
71
72    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
73        fEffects[s] = NULL;
74    }
75
76    this->genProgram(stages);
77}
78
79GrGLProgram::~GrGLProgram() {
80    if (fVShaderID) {
81        GL_CALL(DeleteShader(fVShaderID));
82    }
83    if (fGShaderID) {
84        GL_CALL(DeleteShader(fGShaderID));
85    }
86    if (fFShaderID) {
87        GL_CALL(DeleteShader(fFShaderID));
88    }
89    if (fProgramID) {
90        GL_CALL(DeleteProgram(fProgramID));
91    }
92
93    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
94        delete fEffects[i];
95    }
96}
97
98void GrGLProgram::abandon() {
99    fVShaderID = 0;
100    fGShaderID = 0;
101    fFShaderID = 0;
102    fProgramID = 0;
103}
104
105void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
106                                GrBlendCoeff* dstCoeff) const {
107    switch (fDesc.fDualSrcOutput) {
108        case Desc::kNone_DualSrcOutput:
109            break;
110        // the prog will write a coverage value to the secondary
111        // output and the dst is blended by one minus that value.
112        case Desc::kCoverage_DualSrcOutput:
113        case Desc::kCoverageISA_DualSrcOutput:
114        case Desc::kCoverageISC_DualSrcOutput:
115        *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
116        break;
117        default:
118            GrCrash("Unexpected dual source blend output");
119            break;
120    }
121}
122
123namespace {
124
125// given two blend coeffecients determine whether the src
126// and/or dst computation can be omitted.
127inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
128                              SkXfermode::Coeff dstCoeff,
129                              bool* needSrcValue,
130                              bool* needDstValue) {
131    if (SkXfermode::kZero_Coeff == srcCoeff) {
132        switch (dstCoeff) {
133            // these all read the src
134            case SkXfermode::kSC_Coeff:
135            case SkXfermode::kISC_Coeff:
136            case SkXfermode::kSA_Coeff:
137            case SkXfermode::kISA_Coeff:
138                *needSrcValue = true;
139                break;
140            default:
141                *needSrcValue = false;
142                break;
143        }
144    } else {
145        *needSrcValue = true;
146    }
147    if (SkXfermode::kZero_Coeff == dstCoeff) {
148        switch (srcCoeff) {
149            // these all read the dst
150            case SkXfermode::kDC_Coeff:
151            case SkXfermode::kIDC_Coeff:
152            case SkXfermode::kDA_Coeff:
153            case SkXfermode::kIDA_Coeff:
154                *needDstValue = true;
155                break;
156            default:
157                *needDstValue = false;
158                break;
159        }
160    } else {
161        *needDstValue = true;
162    }
163}
164
165/**
166 * Create a blend_coeff * value string to be used in shader code. Sets empty
167 * string if result is trivially zero.
168 */
169inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
170                       const char* src, const char* dst,
171                       const char* value) {
172    switch (coeff) {
173    case SkXfermode::kZero_Coeff:    /** 0 */
174        *str = "";
175        break;
176    case SkXfermode::kOne_Coeff:     /** 1 */
177        *str = value;
178        break;
179    case SkXfermode::kSC_Coeff:
180        str->printf("(%s * %s)", src, value);
181        break;
182    case SkXfermode::kISC_Coeff:
183        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
184        break;
185    case SkXfermode::kDC_Coeff:
186        str->printf("(%s * %s)", dst, value);
187        break;
188    case SkXfermode::kIDC_Coeff:
189        str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
190        break;
191    case SkXfermode::kSA_Coeff:      /** src alpha */
192        str->printf("(%s.a * %s)", src, value);
193        break;
194    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
195        str->printf("((1.0 - %s.a) * %s)", src, value);
196        break;
197    case SkXfermode::kDA_Coeff:      /** dst alpha */
198        str->printf("(%s.a * %s)", dst, value);
199        break;
200    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
201        str->printf("((1.0 - %s.a) * %s)", dst, value);
202        break;
203    default:
204        GrCrash("Unexpected xfer coeff.");
205        break;
206    }
207}
208/**
209 * Adds a line to the fragment shader code which modifies the color by
210 * the specified color filter.
211 */
212void add_color_filter(SkString* fsCode, const char * outputVar,
213                      SkXfermode::Coeff uniformCoeff,
214                      SkXfermode::Coeff colorCoeff,
215                      const char* filterColor,
216                      const char* inColor) {
217    SkString colorStr, constStr;
218    blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
219    blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
220
221    fsCode->appendf("\t%s = ", outputVar);
222    GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str());
223    fsCode->append(";\n");
224}
225}
226
227bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
228                                  GrGLShaderBuilder* builder) const {
229    if (fDesc.fVertexLayout & GrDrawState::kEdge_VertexLayoutBit) {
230        const char *vsName, *fsName;
231        builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
232        builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
233                                          GrGLShaderVar::kAttribute_TypeModifier,
234                                          EDGE_ATTR_NAME);
235        builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
236        switch (fDesc.fVertexEdgeType) {
237        case GrDrawState::kHairLine_EdgeType:
238            builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName);
239            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
240            break;
241        case GrDrawState::kQuad_EdgeType:
242            builder->fFSCode.append("\tfloat edgeAlpha;\n");
243            // keep the derivative instructions outside the conditional
244            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
245            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
246            builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
247            // today we know z and w are in device space. We could use derivatives
248            builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
249            builder->fFSCode.append ("\t} else {\n");
250            builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
251                                     "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
252                                     fsName, fsName);
253            builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
254            builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
255                                    "\t}\n");
256            if (kES2_GrGLBinding == fContextInfo.binding()) {
257                builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
258            }
259            break;
260        case GrDrawState::kHairQuad_EdgeType:
261            builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
262            builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
263            builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
264                                     "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
265                                     fsName, fsName);
266            builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
267            builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
268            builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
269            if (kES2_GrGLBinding == fContextInfo.binding()) {
270                builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
271            }
272            break;
273        case GrDrawState::kCircle_EdgeType:
274            builder->fFSCode.append("\tfloat edgeAlpha;\n");
275            builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName);
276            builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
277            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);
278            builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
279            break;
280        case GrDrawState::kEllipse_EdgeType:
281            builder->fFSCode.append("\tfloat edgeAlpha;\n");
282            builder->fFSCode.appendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
283            builder->fFSCode.appendf("\toffset.y *= %s.w;\n", fsName);
284            builder->fFSCode.append("\tfloat d = length(offset);\n");
285            builder->fFSCode.appendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
286            break;
287        default:
288            GrCrash("Unknown Edge Type!");
289            break;
290        }
291        if (fDesc.fDiscardIfOutsideEdge) {
292            builder->fFSCode.appendf("\tif (edgeAlpha <= 0.0) {\n\t\tdiscard;\n\t}\n");
293        }
294        *coverageVar = "edgeAlpha";
295        return true;
296    } else {
297        coverageVar->reset();
298        return false;
299    }
300}
301
302void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
303    switch (fDesc.fColorInput) {
304        case GrGLProgram::Desc::kAttribute_ColorInput: {
305            builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
306                GrGLShaderVar::kAttribute_TypeModifier,
307                COL_ATTR_NAME);
308            const char *vsName, *fsName;
309            builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
310            builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
311            *inColor = fsName;
312            } break;
313        case GrGLProgram::Desc::kUniform_ColorInput: {
314            const char* name;
315            fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
316                                                            kVec4f_GrSLType, "Color", &name);
317            *inColor = name;
318            break;
319        }
320        case GrGLProgram::Desc::kTransBlack_ColorInput:
321            GrAssert(!"needComputedColor should be false.");
322            break;
323        case GrGLProgram::Desc::kSolidWhite_ColorInput:
324            break;
325        default:
326            GrCrash("Unknown color type.");
327            break;
328    }
329}
330
331void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
332    const char* covUniName;
333    fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
334                                                       kVec4f_GrSLType, "Coverage", &covUniName);
335    if (inOutCoverage->size()) {
336        builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
337                                  covUniName, inOutCoverage->c_str());
338        *inOutCoverage = "uniCoverage";
339    } else {
340        *inOutCoverage = covUniName;
341    }
342}
343
344namespace {
345void gen_attribute_coverage(GrGLShaderBuilder* segments,
346                            SkString* inOutCoverage) {
347    segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
348                                       GrGLShaderVar::kAttribute_TypeModifier,
349                                       COV_ATTR_NAME);
350    const char *vsName, *fsName;
351    segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
352    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
353    if (inOutCoverage->size()) {
354        segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
355                                  fsName, inOutCoverage->c_str());
356        *inOutCoverage = "attrCoverage";
357    } else {
358        *inOutCoverage = fsName;
359    }
360}
361}
362
363void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const {
364#if GR_GL_EXPERIMENTAL_GS
365    if (fDesc.fExperimentalGS) {
366        GrAssert(fContextInfo.glslGeneration() >= k150_GrGLSLGeneration);
367        segments->fGSHeader.append("layout(triangles) in;\n"
368                                   "layout(triangle_strip, max_vertices = 6) out;\n");
369        segments->fGSCode.append("\tfor (int i = 0; i < 3; ++i) {\n"
370                                 "\t\tgl_Position = gl_in[i].gl_Position;\n");
371        if (fDesc.fEmitsPointSize) {
372            segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
373        }
374        GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
375        int count = segments->fGSInputs.count();
376        for (int i = 0; i < count; ++i) {
377            segments->fGSCode.appendf("\t\t%s = %s[i];\n",
378                                      segments->fGSOutputs[i].getName().c_str(),
379                                      segments->fGSInputs[i].getName().c_str());
380        }
381        segments->fGSCode.append("\t\tEmitVertex();\n"
382                                 "\t}\n"
383                                 "\tEndPrimitive();\n");
384    }
385#endif
386}
387
388const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
389    if (inColor.size()) {
390          return inColor.c_str();
391    } else {
392        if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
393            return GrGLSLOnesVecf(4);
394        } else {
395            return GrGLSLZerosVecf(4);
396        }
397    }
398}
399
400namespace {
401// prints a shader using params similar to glShaderSource
402void print_shader(GrGLint stringCnt,
403                  const GrGLchar** strings,
404                  GrGLint* stringLengths) {
405    for (int i = 0; i < stringCnt; ++i) {
406        if (NULL == stringLengths || stringLengths[i] < 0) {
407            GrPrintf(strings[i]);
408        } else {
409            GrPrintf("%.*s", stringLengths[i], strings[i]);
410        }
411    }
412}
413
414// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
415GrGLuint compile_shader(const GrGLContextInfo& gl,
416                        GrGLenum type,
417                        int stringCnt,
418                        const char** strings,
419                        int* stringLengths) {
420    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
421                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
422
423    GrGLuint shader;
424    GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type));
425    if (0 == shader) {
426        return 0;
427    }
428
429    const GrGLInterface* gli = gl.interface();
430    GrGLint compiled = GR_GL_INIT_ZERO;
431    GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths));
432    GR_GL_CALL(gli, CompileShader(shader));
433    GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
434
435    if (!compiled) {
436        GrGLint infoLen = GR_GL_INIT_ZERO;
437        GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
438        SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
439        if (infoLen > 0) {
440            // retrieve length even though we don't need it to workaround bug in chrome cmd buffer
441            // param validation.
442            GrGLsizei length = GR_GL_INIT_ZERO;
443            GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1,
444                                             &length, (char*)log.get()));
445            print_shader(stringCnt, strings, stringLengths);
446            GrPrintf("\n%s", log.get());
447        }
448        GrAssert(!"Shader compilation failed!");
449        GR_GL_CALL(gli, DeleteShader(shader));
450        return 0;
451    }
452    return shader;
453}
454
455// helper version of above for when shader is already flattened into a single SkString
456GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString& shader) {
457    const GrGLchar* str = shader.c_str();
458    int length = shader.size();
459    return compile_shader(gl, type, 1, &str, &length);
460}
461
462}
463
464// compiles all the shaders from builder and stores the shader IDs
465bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
466
467    SkString shader;
468
469    builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader);
470    if (c_PrintShaders) {
471        GrPrintf(shader.c_str());
472        GrPrintf("\n");
473    }
474
475    if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) {
476        return false;
477    }
478
479    if (builder.fUsesGS) {
480        builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader);
481        if (c_PrintShaders) {
482            GrPrintf(shader.c_str());
483            GrPrintf("\n");
484        }
485        if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) {
486            return false;
487        }
488    } else {
489        fGShaderID = 0;
490    }
491
492    builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
493    if (c_PrintShaders) {
494        GrPrintf(shader.c_str());
495        GrPrintf("\n");
496    }
497    if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) {
498        return false;
499    }
500
501    return true;
502}
503
504bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
505    GrAssert(0 == fProgramID);
506
507    GrGLShaderBuilder builder(fContextInfo, fUniformManager);
508    const uint32_t& layout = fDesc.fVertexLayout;
509
510#if GR_GL_EXPERIMENTAL_GS
511    builder.fUsesGS = fDesc.fExperimentalGS;
512#endif
513
514    SkXfermode::Coeff colorCoeff, uniformCoeff;
515    // The rest of transfer mode color filters have not been implemented
516    if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
517        GR_DEBUGCODE(bool success =)
518            SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
519                                    (fDesc.fColorFilterXfermode),
520                                    &uniformCoeff, &colorCoeff);
521        GR_DEBUGASSERT(success);
522    } else {
523        colorCoeff = SkXfermode::kOne_Coeff;
524        uniformCoeff = SkXfermode::kZero_Coeff;
525    }
526
527    // no need to do the color filter if coverage is 0. The output color is scaled by the coverage.
528    // All the dual source outputs are scaled by the coverage as well.
529    if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
530        colorCoeff = SkXfermode::kZero_Coeff;
531        uniformCoeff = SkXfermode::kZero_Coeff;
532    }
533
534    // If we know the final color is going to be all zeros then we can
535    // simplify the color filter coefficients. needComputedColor will then
536    // come out false below.
537    if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
538        colorCoeff = SkXfermode::kZero_Coeff;
539        if (SkXfermode::kDC_Coeff == uniformCoeff ||
540            SkXfermode::kDA_Coeff == uniformCoeff) {
541            uniformCoeff = SkXfermode::kZero_Coeff;
542        } else if (SkXfermode::kIDC_Coeff == uniformCoeff ||
543                   SkXfermode::kIDA_Coeff == uniformCoeff) {
544            uniformCoeff = SkXfermode::kOne_Coeff;
545        }
546    }
547
548    bool needColorFilterUniform;
549    bool needComputedColor;
550    need_blend_inputs(uniformCoeff, colorCoeff,
551                      &needColorFilterUniform, &needComputedColor);
552
553    // the dual source output has no canonical var name, have to
554    // declare an output, which is incompatible with gl_FragColor/gl_FragData.
555    bool dualSourceOutputWritten = false;
556    builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(),
557                                                fContextInfo.glslGeneration()));
558
559    GrGLShaderVar colorOutput;
560    bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(),
561                                                   declared_color_output_name(),
562                                                   &colorOutput);
563    if (isColorDeclared) {
564        builder.fFSOutputs.push_back(colorOutput);
565    }
566
567    const char* viewMName;
568    fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
569                                                        kMat33f_GrSLType, "ViewM", &viewMName);
570
571
572    builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
573                            "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
574                            viewMName, builder.positionAttribute().getName().c_str());
575
576    // incoming color to current stage being processed.
577    SkString inColor;
578
579    if (needComputedColor) {
580        this->genInputColor(&builder, &inColor);
581    }
582
583    // we output point size in the GS if present
584    if (fDesc.fEmitsPointSize && !builder.fUsesGS){
585        builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
586    }
587
588    // add texture coordinates that are used to the list of vertex attr decls
589    SkString texCoordAttrs[GrDrawState::kMaxTexCoords];
590    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
591        if (GrDrawState::VertexUsesTexCoordIdx(t, layout)) {
592            tex_attr_name(t, texCoordAttrs + t);
593            builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
594                GrGLShaderVar::kAttribute_TypeModifier,
595                texCoordAttrs[t].c_str());
596        }
597    }
598
599    ///////////////////////////////////////////////////////////////////////////
600    // compute the final color
601
602    // if we have color stages string them together, feeding the output color
603    // of each to the next and generating code for each stage.
604    if (needComputedColor) {
605        SkString outColor;
606        for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
607            if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) {
608                // create var to hold stage result
609                outColor = "color";
610                outColor.appendS32(s);
611                builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
612
613                const char* inCoords;
614                // figure out what our input coords are
615                int tcIdx = GrDrawState::VertexTexCoordsForStage(s, layout);
616                if (tcIdx < 0) {
617                    inCoords = builder.positionAttribute().c_str();
618                } else {
619                    // must have input tex coordinates if stage is enabled.
620                    GrAssert(texCoordAttrs[tcIdx].size());
621                    inCoords = texCoordAttrs[tcIdx].c_str();
622                }
623
624                builder.setCurrentStage(s);
625                fEffects[s] = builder.createAndEmitGLEffect(*stages[s],
626                                                            fDesc.fEffectKeys[s],
627                                                            inColor.size() ? inColor.c_str() : NULL,
628                                                            outColor.c_str(),
629                                                            inCoords,
630                                                            &fUniformHandles.fSamplerUnis[s]);
631                builder.setNonStage();
632                inColor = outColor;
633            }
634        }
635    }
636
637    // if have all ones or zeros for the "dst" input to the color filter then we
638    // may be able to make additional optimizations.
639    if (needColorFilterUniform && needComputedColor && !inColor.size()) {
640        GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
641        bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
642                                  SkXfermode::kIDA_Coeff == uniformCoeff;
643        if (uniformCoeffIsZero) {
644            uniformCoeff = SkXfermode::kZero_Coeff;
645            bool bogus;
646            need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff,
647                              &needColorFilterUniform, &bogus);
648        }
649    }
650    const char* colorFilterColorUniName = NULL;
651    if (needColorFilterUniform) {
652        fUniformHandles.fColorFilterUni = builder.addUniform(
653                                                        GrGLShaderBuilder::kFragment_ShaderType,
654                                                        kVec4f_GrSLType, "FilterColor",
655                                                        &colorFilterColorUniName);
656    }
657    bool wroteFragColorZero = false;
658    if (SkXfermode::kZero_Coeff == uniformCoeff &&
659        SkXfermode::kZero_Coeff == colorCoeff) {
660        builder.fFSCode.appendf("\t%s = %s;\n",
661                                colorOutput.getName().c_str(),
662                                GrGLSLZerosVecf(4));
663        wroteFragColorZero = true;
664    } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
665        builder.fFSCode.append("\tvec4 filteredColor;\n");
666        const char* color = adjustInColor(inColor);
667        add_color_filter(&builder.fFSCode, "filteredColor", uniformCoeff,
668                       colorCoeff, colorFilterColorUniName, color);
669        inColor = "filteredColor";
670    }
671
672    ///////////////////////////////////////////////////////////////////////////
673    // compute the partial coverage (coverage stages and edge aa)
674
675    SkString inCoverage;
676    bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput;
677    // we don't need to compute coverage at all if we know the final shader
678    // output will be zero and we don't have a dual src blend output.
679    if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
680
681        if (!coverageIsZero) {
682            bool inCoverageIsScalar  = this->genEdgeCoverage(&inCoverage, &builder);
683
684            switch (fDesc.fCoverageInput) {
685                case Desc::kSolidWhite_ColorInput:
686                    // empty string implies solid white
687                    break;
688                case Desc::kAttribute_ColorInput:
689                    gen_attribute_coverage(&builder, &inCoverage);
690                    inCoverageIsScalar = false;
691                    break;
692                case Desc::kUniform_ColorInput:
693                    this->genUniformCoverage(&builder, &inCoverage);
694                    inCoverageIsScalar = false;
695                    break;
696                default:
697                    GrCrash("Unexpected input coverage.");
698            }
699
700            SkString outCoverage;
701            const int& startStage = fDesc.fFirstCoverageStage;
702            for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
703                if (fDesc.fEffectKeys[s]) {
704                    // create var to hold stage output
705                    outCoverage = "coverage";
706                    outCoverage.appendS32(s);
707                    builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str());
708
709                    const char* inCoords;
710                    // figure out what our input coords are
711                    int tcIdx =
712                        GrDrawState::VertexTexCoordsForStage(s, layout);
713                    if (tcIdx < 0) {
714                        inCoords = builder.positionAttribute().c_str();
715                    } else {
716                        // must have input tex coordinates if stage is
717                        // enabled.
718                        GrAssert(texCoordAttrs[tcIdx].size());
719                        inCoords = texCoordAttrs[tcIdx].c_str();
720                    }
721
722                    // stages don't know how to deal with a scalar input. (Maybe they should. We
723                    // could pass a GrGLShaderVar)
724                    if (inCoverageIsScalar) {
725                        builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n",
726                                                inCoverage.c_str(), inCoverage.c_str());
727                        inCoverage.append("4");
728                    }
729                    builder.setCurrentStage(s);
730                    fEffects[s] = builder.createAndEmitGLEffect(
731                                                    *stages[s],
732                                                    fDesc.fEffectKeys[s],
733                                                    inCoverage.size() ? inCoverage.c_str() : NULL,
734                                                    outCoverage.c_str(),
735                                                    inCoords,
736                                                    &fUniformHandles.fSamplerUnis[s]);
737                    builder.setNonStage();
738                    inCoverage = outCoverage;
739                }
740            }
741        }
742
743        if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
744            builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
745                                               GrGLShaderVar::kOut_TypeModifier,
746                                               dual_source_output_name());
747            bool outputIsZero = coverageIsZero;
748            SkString coeff;
749            if (!outputIsZero &&
750                Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
751                if (!inColor.size()) {
752                    outputIsZero = true;
753                } else {
754                    if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
755                        coeff.printf("(1 - %s.a)", inColor.c_str());
756                    } else {
757                        coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
758                    }
759                }
760            }
761            if (outputIsZero) {
762                builder.fFSCode.appendf("\t%s = %s;\n",
763                                        dual_source_output_name(),
764                                        GrGLSLZerosVecf(4));
765            } else {
766                builder.fFSCode.appendf("\t%s =", dual_source_output_name());
767                GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str());
768                builder.fFSCode.append(";\n");
769            }
770            dualSourceOutputWritten = true;
771        }
772    }
773
774    ///////////////////////////////////////////////////////////////////////////
775    // combine color and coverage as frag color
776
777    if (!wroteFragColorZero) {
778        if (coverageIsZero) {
779            builder.fFSCode.appendf("\t%s = %s;\n",
780                                    colorOutput.getName().c_str(),
781                                    GrGLSLZerosVecf(4));
782        } else {
783            builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str());
784            GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str());
785            builder.fFSCode.append(";\n");
786        }
787    }
788
789    ///////////////////////////////////////////////////////////////////////////
790    // insert GS
791#if GR_DEBUG
792    this->genGeometryShader(&builder);
793#endif
794
795    ///////////////////////////////////////////////////////////////////////////
796    // compile and setup attribs and unis
797
798    if (!this->compileShaders(builder)) {
799        return false;
800    }
801
802    if (!this->bindOutputsAttribsAndLinkProgram(builder,
803                                                texCoordAttrs,
804                                                isColorDeclared,
805                                                dualSourceOutputWritten)) {
806        return false;
807    }
808
809    builder.finished(fProgramID);
810    this->initSamplerUniforms();
811    fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
812
813    return true;
814}
815
816bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
817                                                   SkString texCoordAttrNames[],
818                                                   bool bindColorOut,
819                                                   bool bindDualSrcOut) {
820    GL_CALL_RET(fProgramID, CreateProgram());
821    if (!fProgramID) {
822        return false;
823    }
824
825    GL_CALL(AttachShader(fProgramID, fVShaderID));
826    if (fGShaderID) {
827        GL_CALL(AttachShader(fProgramID, fGShaderID));
828    }
829    GL_CALL(AttachShader(fProgramID, fFShaderID));
830
831    if (bindColorOut) {
832        GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
833    }
834    if (bindDualSrcOut) {
835        GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
836    }
837
838    // Bind the attrib locations to same values for all shaders
839    GL_CALL(BindAttribLocation(fProgramID,
840                               PositionAttributeIdx(),
841                               builder.positionAttribute().c_str()));
842    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
843        if (texCoordAttrNames[t].size()) {
844            GL_CALL(BindAttribLocation(fProgramID,
845                                       TexCoordAttributeIdx(t),
846                                       texCoordAttrNames[t].c_str()));
847        }
848    }
849
850    GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
851    GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
852    GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
853
854    GL_CALL(LinkProgram(fProgramID));
855
856    GrGLint linked = GR_GL_INIT_ZERO;
857    GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
858    if (!linked) {
859        GrGLint infoLen = GR_GL_INIT_ZERO;
860        GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
861        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
862        if (infoLen > 0) {
863            // retrieve length even though we don't need it to workaround
864            // bug in chrome cmd buffer param validation.
865            GrGLsizei length = GR_GL_INIT_ZERO;
866            GL_CALL(GetProgramInfoLog(fProgramID,
867                                      infoLen+1,
868                                      &length,
869                                      (char*)log.get()));
870            GrPrintf((char*)log.get());
871        }
872        GrAssert(!"Error linking program");
873        GL_CALL(DeleteProgram(fProgramID));
874        fProgramID = 0;
875        return false;
876    }
877    return true;
878}
879
880void GrGLProgram::initSamplerUniforms() {
881    GL_CALL(UseProgram(fProgramID));
882    // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes this
883    // behavior.
884    GrGLint texUnitIdx = 0;
885    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
886        int numSamplers = fUniformHandles.fSamplerUnis[s].count();
887        for (int u = 0; u < numSamplers; ++u) {
888            UniformHandle handle = fUniformHandles.fSamplerUnis[s][u];
889            if (GrGLUniformManager::kInvalidUniformHandle != handle) {
890                fUniformManager.setSampler(handle, texUnitIdx);
891                ++texUnitIdx;
892            }
893        }
894    }
895}
896
897///////////////////////////////////////////////////////////////////////////////
898
899void GrGLProgram::setData(GrGpuGL* gpu) {
900    const GrDrawState& drawState = gpu->getDrawState();
901
902    int rtHeight = drawState.getRenderTarget()->height();
903    if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni &&
904        fRTHeight != rtHeight) {
905        fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(rtHeight));
906        fRTHeight = rtHeight;
907    }
908    GrGLint texUnitIdx = 0;
909    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
910        if (NULL != fEffects[s]) {
911            const GrEffectStage& stage = drawState.getStage(s);
912            GrAssert(NULL != stage.getEffect());
913            fEffects[s]->setData(fUniformManager, stage);
914            int numSamplers = fUniformHandles.fSamplerUnis[s].count();
915            for (int u = 0; u < numSamplers; ++u) {
916                UniformHandle handle = fUniformHandles.fSamplerUnis[s][u];
917                if (GrGLUniformManager::kInvalidUniformHandle != handle) {
918                    const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u);
919                    GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
920                    gpu->bindTexture(texUnitIdx, access.getParams(), texture);
921                    ++texUnitIdx;
922                }
923            }
924        }
925    }
926}
927