GrGLProgram.cpp revision cddaf340f1474cc1ff429b8ef9bc8739c72f80ba
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 "GrCustomStage.h"
12#include "GrGLProgramStage.h"
13#include "gl/GrGLShaderBuilder.h"
14#include "GrGLShaderVar.h"
15#include "GrProgramStageFactory.h"
16#include "SkTrace.h"
17#include "SkXfermode.h"
18
19SK_DEFINE_INST_COUNT(GrGLProgram)
20
21#define GL_CALL(X) GR_GL_CALL(fContextInfo.interface(), X)
22#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContextInfo.interface(), R, X)
23
24#define PRINT_SHADERS 0
25
26typedef GrGLProgram::Desc::StageDesc StageDesc;
27
28#define POS_ATTR_NAME "aPosition"
29#define COL_ATTR_NAME "aColor"
30#define COV_ATTR_NAME "aCoverage"
31#define EDGE_ATTR_NAME "aEdge"
32
33namespace {
34inline void tex_attr_name(int coordIdx, SkString* s) {
35    *s = "aTexCoord";
36    s->appendS32(coordIdx);
37}
38
39inline const char* float_vector_type_str(int count) {
40    return GrGLShaderVar::TypeString(GrSLFloatVectorType(count));
41}
42
43inline const char* vector_all_coords(int count) {
44    static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"};
45    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL));
46    return ALL[count];
47}
48
49inline const char* all_ones_vec(int count) {
50    static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
51                                    "vec3(1,1,1)", "vec4(1,1,1,1)"};
52    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC));
53    return ONESVEC[count];
54}
55
56inline const char* all_zeros_vec(int count) {
57    static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
58                                    "vec3(0,0,0)", "vec4(0,0,0,0)"};
59    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC));
60    return ZEROSVEC[count];
61}
62
63inline const char* declared_color_output_name() { return "fsColorOut"; }
64inline const char* dual_source_output_name() { return "dualSourceOut"; }
65
66}
67
68GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl,
69                                 const Desc& desc,
70                                 const GrCustomStage** customStages) {
71    GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, customStages));
72    if (!program->succeeded()) {
73        delete program;
74        program = NULL;
75    }
76    return program;
77}
78
79GrGLProgram::GrGLProgram(const GrGLContextInfo& gl,
80                         const Desc& desc,
81                         const GrCustomStage** customStages)
82: fContextInfo(gl)
83, fUniformManager(gl) {
84    fDesc = desc;
85    fVShaderID = 0;
86    fGShaderID = 0;
87    fFShaderID = 0;
88    fProgramID = 0;
89
90    fViewMatrix = GrMatrix::InvalidMatrix();
91    fViewportSize.set(-1, -1);
92    fColor = GrColor_ILLEGAL;
93    fColorFilterColor = GrColor_ILLEGAL;
94
95    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
96        fProgramStage[s] = NULL;
97        fTextureMatrices[s] = GrMatrix::InvalidMatrix();
98        // this is arbitrary, just initialize to something
99        fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation;
100    }
101
102    this->genProgram(customStages);
103}
104
105GrGLProgram::~GrGLProgram() {
106    if (fVShaderID) {
107        GL_CALL(DeleteShader(fVShaderID));
108    }
109    if (fGShaderID) {
110        GL_CALL(DeleteShader(fGShaderID));
111    }
112    if (fFShaderID) {
113        GL_CALL(DeleteShader(fFShaderID));
114    }
115    if (fProgramID) {
116        GL_CALL(DeleteProgram(fProgramID));
117    }
118
119    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
120        delete fProgramStage[i];
121    }
122}
123
124void GrGLProgram::abandon() {
125    fVShaderID = 0;
126    fGShaderID = 0;
127    fFShaderID = 0;
128    fProgramID = 0;
129}
130
131void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
132                                GrBlendCoeff* dstCoeff) const {
133    switch (fDesc.fDualSrcOutput) {
134        case Desc::kNone_DualSrcOutput:
135            break;
136        // the prog will write a coverage value to the secondary
137        // output and the dst is blended by one minus that value.
138        case Desc::kCoverage_DualSrcOutput:
139        case Desc::kCoverageISA_DualSrcOutput:
140        case Desc::kCoverageISC_DualSrcOutput:
141        *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
142        break;
143        default:
144            GrCrash("Unexpected dual source blend output");
145            break;
146    }
147}
148
149// assigns modulation of two vars to an output var
150// vars can be vec4s or floats (or one of each)
151// result is always vec4
152// if either var is "" then assign to the other var
153// if both are "" then assign all ones
154static inline void modulate_helper(const char* outputVar,
155                                   const char* var0,
156                                   const char* var1,
157                                   SkString* code) {
158    GrAssert(NULL != outputVar);
159    GrAssert(NULL != var0);
160    GrAssert(NULL != var1);
161    GrAssert(NULL != code);
162
163    bool has0 = '\0' != *var0;
164    bool has1 = '\0' != *var1;
165
166    if (!has0 && !has1) {
167        code->appendf("\t%s = %s;\n", outputVar, all_ones_vec(4));
168    } else if (!has0) {
169        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
170    } else if (!has1) {
171        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
172    } else {
173        code->appendf("\t%s = vec4(%s * %s);\n", outputVar, var0, var1);
174    }
175}
176
177// assigns addition of two vars to an output var
178// vars can be vec4s or floats (or one of each)
179// result is always vec4
180// if either var is "" then assign to the other var
181// if both are "" then assign all zeros
182static inline void add_helper(const char* outputVar,
183                              const char* var0,
184                              const char* var1,
185                              SkString* code) {
186    GrAssert(NULL != outputVar);
187    GrAssert(NULL != var0);
188    GrAssert(NULL != var1);
189    GrAssert(NULL != code);
190
191    bool has0 = '\0' != *var0;
192    bool has1 = '\0' != *var1;
193
194    if (!has0 && !has1) {
195        code->appendf("\t%s = %s;\n", outputVar, all_zeros_vec(4));
196    } else if (!has0) {
197        code->appendf("\t%s = vec4(%s);\n", outputVar, var1);
198    } else if (!has1) {
199        code->appendf("\t%s = vec4(%s);\n", outputVar, var0);
200    } else {
201        code->appendf("\t%s = vec4(%s + %s);\n", outputVar, var0, var1);
202    }
203}
204
205// given two blend coeffecients determine whether the src
206// and/or dst computation can be omitted.
207static inline void needBlendInputs(SkXfermode::Coeff srcCoeff,
208                                   SkXfermode::Coeff dstCoeff,
209                                   bool* needSrcValue,
210                                   bool* needDstValue) {
211    if (SkXfermode::kZero_Coeff == srcCoeff) {
212        switch (dstCoeff) {
213            // these all read the src
214            case SkXfermode::kSC_Coeff:
215            case SkXfermode::kISC_Coeff:
216            case SkXfermode::kSA_Coeff:
217            case SkXfermode::kISA_Coeff:
218                *needSrcValue = true;
219                break;
220            default:
221                *needSrcValue = false;
222                break;
223        }
224    } else {
225        *needSrcValue = true;
226    }
227    if (SkXfermode::kZero_Coeff == dstCoeff) {
228        switch (srcCoeff) {
229            // these all read the dst
230            case SkXfermode::kDC_Coeff:
231            case SkXfermode::kIDC_Coeff:
232            case SkXfermode::kDA_Coeff:
233            case SkXfermode::kIDA_Coeff:
234                *needDstValue = true;
235                break;
236            default:
237                *needDstValue = false;
238                break;
239        }
240    } else {
241        *needDstValue = true;
242    }
243}
244
245/**
246 * Create a blend_coeff * value string to be used in shader code. Sets empty
247 * string if result is trivially zero.
248 */
249static void blendTermString(SkString* str, SkXfermode::Coeff coeff,
250                             const char* src, const char* dst,
251                             const char* value) {
252    switch (coeff) {
253    case SkXfermode::kZero_Coeff:    /** 0 */
254        *str = "";
255        break;
256    case SkXfermode::kOne_Coeff:     /** 1 */
257        *str = value;
258        break;
259    case SkXfermode::kSC_Coeff:
260        str->printf("(%s * %s)", src, value);
261        break;
262    case SkXfermode::kISC_Coeff:
263        str->printf("((%s - %s) * %s)", all_ones_vec(4), src, value);
264        break;
265    case SkXfermode::kDC_Coeff:
266        str->printf("(%s * %s)", dst, value);
267        break;
268    case SkXfermode::kIDC_Coeff:
269        str->printf("((%s - %s) * %s)", all_ones_vec(4), dst, value);
270        break;
271    case SkXfermode::kSA_Coeff:      /** src alpha */
272        str->printf("(%s.a * %s)", src, value);
273        break;
274    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
275        str->printf("((1.0 - %s.a) * %s)", src, value);
276        break;
277    case SkXfermode::kDA_Coeff:      /** dst alpha */
278        str->printf("(%s.a * %s)", dst, value);
279        break;
280    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
281        str->printf("((1.0 - %s.a) * %s)", dst, value);
282        break;
283    default:
284        GrCrash("Unexpected xfer coeff.");
285        break;
286    }
287}
288/**
289 * Adds a line to the fragment shader code which modifies the color by
290 * the specified color filter.
291 */
292static void addColorFilter(SkString* fsCode, const char * outputVar,
293                           SkXfermode::Coeff uniformCoeff,
294                           SkXfermode::Coeff colorCoeff,
295                           const char* filterColor,
296                           const char* inColor) {
297    SkString colorStr, constStr;
298    blendTermString(&colorStr, colorCoeff, filterColor, inColor, inColor);
299    blendTermString(&constStr, uniformCoeff, filterColor, inColor, filterColor);
300
301    add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode);
302}
303
304void GrGLProgram::genEdgeCoverage(SkString* coverageVar,
305                                  GrGLShaderBuilder* segments) const {
306    if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) {
307        const char *vsName, *fsName;
308        segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
309        segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
310            GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
311        segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
312        switch (fDesc.fVertexEdgeType) {
313        case GrDrawState::kHairLine_EdgeType:
314            segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
315            segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
316            break;
317        case GrDrawState::kQuad_EdgeType:
318            segments->fFSCode.append("\tfloat edgeAlpha;\n");
319            // keep the derivative instructions outside the conditional
320            segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
321            segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
322            segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
323            // today we know z and w are in device space. We could use derivatives
324            segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName);
325            segments->fFSCode.append ("\t} else {\n");
326            segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
327                                      "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
328                                      fsName, fsName);
329            segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
330            segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n"
331                                      "\t}\n");
332            if (kES2_GrGLBinding == fContextInfo.binding()) {
333                segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
334            }
335            break;
336        case GrDrawState::kHairQuad_EdgeType:
337            segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
338            segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
339            segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
340                                      "\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
341                                      fsName, fsName);
342            segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName);
343            segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
344            segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
345            if (kES2_GrGLBinding == fContextInfo.binding()) {
346                segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n");
347            }
348            break;
349        case GrDrawState::kCircle_EdgeType:
350            segments->fFSCode.append("\tfloat edgeAlpha;\n");
351            segments->fFSCode.appendf("\tfloat d = distance(gl_FragCoord.xy, %s.xy);\n", fsName);
352            segments->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
353            segments->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
354            segments->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n");
355            break;
356        default:
357            GrCrash("Unknown Edge Type!");
358            break;
359        }
360        *coverageVar = "edgeAlpha";
361    } else {
362        coverageVar->reset();
363    }
364}
365
366void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
367    switch (fDesc.fColorInput) {
368        case GrGLProgram::Desc::kAttribute_ColorInput: {
369            builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
370                GrGLShaderVar::kAttribute_TypeModifier,
371                COL_ATTR_NAME);
372            const char *vsName, *fsName;
373            builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
374            builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
375            *inColor = fsName;
376            } break;
377        case GrGLProgram::Desc::kUniform_ColorInput: {
378            const char* name;
379            fUniforms.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
380                                                      kVec4f_GrSLType, "Color", &name);
381            *inColor = name;
382            break;
383        }
384        case GrGLProgram::Desc::kTransBlack_ColorInput:
385            GrAssert(!"needComputedColor should be false.");
386            break;
387        case GrGLProgram::Desc::kSolidWhite_ColorInput:
388            break;
389        default:
390            GrCrash("Unknown color type.");
391            break;
392    }
393}
394
395void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
396    const char* covUniName;
397    fUniforms.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
398                                                 kVec4f_GrSLType, "Coverage", &covUniName);
399    if (inOutCoverage->size()) {
400        builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
401                                  covUniName, inOutCoverage->c_str());
402        *inOutCoverage = "uniCoverage";
403    } else {
404        *inOutCoverage = covUniName;
405    }
406}
407
408namespace {
409void gen_attribute_coverage(GrGLShaderBuilder* segments,
410                            SkString* inOutCoverage) {
411    segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
412                                       GrGLShaderVar::kAttribute_TypeModifier,
413                                       COV_ATTR_NAME);
414    const char *vsName, *fsName;
415    segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
416    segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
417    if (inOutCoverage->size()) {
418        segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n",
419                                  fsName, inOutCoverage->c_str());
420        *inOutCoverage = "attrCoverage";
421    } else {
422        *inOutCoverage = fsName;
423    }
424}
425}
426
427void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const {
428#if GR_GL_EXPERIMENTAL_GS
429    if (fDesc.fExperimentalGS) {
430        GrAssert(fContextInfo.glslGeneration() >= k150_GrGLSLGeneration);
431        segments->fGSHeader.append("layout(triangles) in;\n"
432                                   "layout(triangle_strip, max_vertices = 6) out;\n");
433        segments->fGSCode.append("void main() {\n"
434                                 "\tfor (int i = 0; i < 3; ++i) {\n"
435                                  "\t\tgl_Position = gl_in[i].gl_Position;\n");
436        if (fDesc.fEmitsPointSize) {
437            segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
438        }
439        GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
440        int count = segments->fGSInputs.count();
441        for (int i = 0; i < count; ++i) {
442            segments->fGSCode.appendf("\t\t%s = %s[i];\n",
443                                      segments->fGSOutputs[i].getName().c_str(),
444                                      segments->fGSInputs[i].getName().c_str());
445        }
446        segments->fGSCode.append("\t\tEmitVertex();\n"
447                                 "\t}\n"
448                                 "\tEndPrimitive();\n"
449                                 "}\n");
450    }
451#endif
452}
453
454const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
455    if (inColor.size()) {
456          return inColor.c_str();
457    } else {
458        if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
459            return all_ones_vec(4);
460        } else {
461            return all_zeros_vec(4);
462        }
463    }
464}
465
466namespace {
467// prints a shader using params similar to glShaderSource
468void print_shader(GrGLint stringCnt,
469                  const GrGLchar** strings,
470                  GrGLint* stringLengths) {
471    for (int i = 0; i < stringCnt; ++i) {
472        if (NULL == stringLengths || stringLengths[i] < 0) {
473            GrPrintf(strings[i]);
474        } else {
475            GrPrintf("%.*s", stringLengths[i], strings[i]);
476        }
477    }
478}
479
480// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
481GrGLuint compile_shader(const GrGLContextInfo& gl,
482                        GrGLenum type,
483                        int stringCnt,
484                        const char** strings,
485                        int* stringLengths) {
486    SK_TRACE_EVENT1("GrGLProgram::CompileShader",
487                    "stringCount", SkStringPrintf("%i", stringCnt).c_str());
488
489    GrGLuint shader;
490    GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type));
491    if (0 == shader) {
492        return 0;
493    }
494
495    const GrGLInterface* gli = gl.interface();
496    GrGLint compiled = GR_GL_INIT_ZERO;
497    GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths));
498    GR_GL_CALL(gli, CompileShader(shader));
499    GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
500
501    if (!compiled) {
502        GrGLint infoLen = GR_GL_INIT_ZERO;
503        GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen));
504        SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
505        if (infoLen > 0) {
506            // retrieve length even though we don't need it to workaround bug in chrome cmd buffer
507            // param validation.
508            GrGLsizei length = GR_GL_INIT_ZERO;
509            GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1,
510                                             &length, (char*)log.get()));
511            print_shader(stringCnt, strings, stringLengths);
512            GrPrintf("\n%s", log.get());
513        }
514        GrAssert(!"Shader compilation failed!");
515        GR_GL_CALL(gli, DeleteShader(shader));
516        return 0;
517    }
518    return shader;
519}
520
521// helper version of above for when shader is already flattened into a single SkString
522GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString& shader) {
523    const GrGLchar* str = shader.c_str();
524    int length = shader.size();
525    return compile_shader(gl, type, 1, &str, &length);
526}
527
528}
529
530// compiles all the shaders from builder and stores the shader IDs
531bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
532
533    SkString shader;
534
535    builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader);
536#if PRINT_SHADERS
537    GrPrintf(shader.c_str());
538    GrPrintf("\n");
539#endif
540    if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) {
541        return false;
542    }
543
544    if (builder.fUsesGS) {
545        builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader);
546#if PRINT_SHADERS
547        GrPrintf(shader.c_str());
548        GrPrintf("\n");
549#endif
550        if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) {
551            return false;
552        }
553    } else {
554        fGShaderID = 0;
555    }
556
557    builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
558#if PRINT_SHADERS
559    GrPrintf(shader.c_str());
560    GrPrintf("\n");
561#endif
562    if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) {
563        return false;
564    }
565
566    return true;
567}
568
569bool GrGLProgram::genProgram(const GrCustomStage** customStages) {
570    GrAssert(0 == fProgramID);
571
572    GrGLShaderBuilder builder(fContextInfo, fUniformManager);
573    const uint32_t& layout = fDesc.fVertexLayout;
574
575#if GR_GL_EXPERIMENTAL_GS
576    builder.fUsesGS = fDesc.fExperimentalGS;
577#endif
578
579    SkXfermode::Coeff colorCoeff, uniformCoeff;
580    bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled);
581    // The rest of transfer mode color filters have not been implemented
582    if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
583        GR_DEBUGCODE(bool success =)
584            SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
585                                    (fDesc.fColorFilterXfermode),
586                                    &uniformCoeff, &colorCoeff);
587        GR_DEBUGASSERT(success);
588    } else {
589        colorCoeff = SkXfermode::kOne_Coeff;
590        uniformCoeff = SkXfermode::kZero_Coeff;
591    }
592
593    // no need to do the color filter / matrix at all if coverage is 0. The
594    // output color is scaled by the coverage. All the dual source outputs are
595    // scaled by the coverage as well.
596    if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
597        colorCoeff = SkXfermode::kZero_Coeff;
598        uniformCoeff = SkXfermode::kZero_Coeff;
599        applyColorMatrix = false;
600    }
601
602    // If we know the final color is going to be all zeros then we can
603    // simplify the color filter coeffecients. needComputedColor will then
604    // come out false below.
605    if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
606        colorCoeff = SkXfermode::kZero_Coeff;
607        if (SkXfermode::kDC_Coeff == uniformCoeff ||
608            SkXfermode::kDA_Coeff == uniformCoeff) {
609            uniformCoeff = SkXfermode::kZero_Coeff;
610        } else if (SkXfermode::kIDC_Coeff == uniformCoeff ||
611                   SkXfermode::kIDA_Coeff == uniformCoeff) {
612            uniformCoeff = SkXfermode::kOne_Coeff;
613        }
614    }
615
616    bool needColorFilterUniform;
617    bool needComputedColor;
618    needBlendInputs(uniformCoeff, colorCoeff,
619                    &needColorFilterUniform, &needComputedColor);
620
621    // the dual source output has no canonical var name, have to
622    // declare an output, which is incompatible with gl_FragColor/gl_FragData.
623    bool dualSourceOutputWritten = false;
624    builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(),
625                                                fContextInfo.glslGeneration()));
626
627    GrGLShaderVar colorOutput;
628    bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(),
629                                                   declared_color_output_name(),
630                                                   &colorOutput);
631    if (isColorDeclared) {
632        builder.fFSOutputs.push_back(colorOutput);
633    }
634
635    const char* viewMName;
636    fUniforms.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
637                                                  kMat33f_GrSLType, "ViewM", &viewMName);
638
639    builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
640                                     GrGLShaderVar::kAttribute_TypeModifier,
641                                     POS_ATTR_NAME);
642
643    builder.fVSCode.appendf("void main() {\n"
644                              "\tvec3 pos3 = %s * vec3("POS_ATTR_NAME", 1);\n"
645                              "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
646                            viewMName);
647
648    // incoming color to current stage being processed.
649    SkString inColor;
650
651    if (needComputedColor) {
652        this->genInputColor(&builder, &inColor);
653    }
654
655    // we output point size in the GS if present
656    if (fDesc.fEmitsPointSize && !builder.fUsesGS){
657        builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
658    }
659
660    builder.fFSCode.append("void main() {\n");
661
662    // add texture coordinates that are used to the list of vertex attr decls
663    SkString texCoordAttrs[GrDrawState::kMaxTexCoords];
664    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
665        if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) {
666            tex_attr_name(t, texCoordAttrs + t);
667            builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
668                GrGLShaderVar::kAttribute_TypeModifier,
669                texCoordAttrs[t].c_str());
670        }
671    }
672
673    ///////////////////////////////////////////////////////////////////////////
674    // compute the final color
675
676    // if we have color stages string them together, feeding the output color
677    // of each to the next and generating code for each stage.
678    if (needComputedColor) {
679        SkString outColor;
680        for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
681            if (fDesc.fStages[s].isEnabled()) {
682                // create var to hold stage result
683                outColor = "color";
684                outColor.appendS32(s);
685                builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str());
686
687                const char* inCoords;
688                // figure out what our input coords are
689                int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout);
690                if (tcIdx < 0) {
691                    inCoords = POS_ATTR_NAME;
692                } else {
693                    // must have input tex coordinates if stage is enabled.
694                    GrAssert(texCoordAttrs[tcIdx].size());
695                    inCoords = texCoordAttrs[tcIdx].c_str();
696                }
697
698                if (NULL != customStages[s]) {
699                    const GrProgramStageFactory& factory = customStages[s]->getFactory();
700                    fProgramStage[s] = factory.createGLInstance(*customStages[s]);
701                }
702                this->genStageCode(s,
703                                   inColor.size() ? inColor.c_str() : NULL,
704                                   outColor.c_str(),
705                                   inCoords,
706                                   &builder);
707                inColor = outColor;
708            }
709        }
710    }
711
712    // if have all ones or zeros for the "dst" input to the color filter then we
713    // may be able to make additional optimizations.
714    if (needColorFilterUniform && needComputedColor && !inColor.size()) {
715        GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
716        bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
717                                  SkXfermode::kIDA_Coeff == uniformCoeff;
718        if (uniformCoeffIsZero) {
719            uniformCoeff = SkXfermode::kZero_Coeff;
720            bool bogus;
721            needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff,
722                            &needColorFilterUniform, &bogus);
723        }
724    }
725    const char* colorFilterColorUniName = NULL;
726    if (needColorFilterUniform) {
727        fUniforms.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
728                                                       kVec4f_GrSLType, "FilterColor",
729                                                       &colorFilterColorUniName);
730    }
731    bool wroteFragColorZero = false;
732    if (SkXfermode::kZero_Coeff == uniformCoeff &&
733        SkXfermode::kZero_Coeff == colorCoeff &&
734        !applyColorMatrix) {
735        builder.fFSCode.appendf("\t%s = %s;\n",
736                                colorOutput.getName().c_str(),
737                                all_zeros_vec(4));
738        wroteFragColorZero = true;
739    } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
740        builder.fFSCode.append("\tvec4 filteredColor;\n");
741        const char* color = adjustInColor(inColor);
742        addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
743                       colorCoeff, colorFilterColorUniName, color);
744        inColor = "filteredColor";
745    }
746    if (applyColorMatrix) {
747        const char* colMatrixName;
748        const char* colMatrixVecName;
749        fUniforms.fColorMatrixUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
750                                                       kMat44f_GrSLType, "ColorMatrix",
751                                                       &colMatrixName);
752        fUniforms.fColorMatrixVecUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
753                                                          kVec4f_GrSLType, "ColorMatrixVec",
754                                                          &colMatrixVecName);
755        const char* color = adjustInColor(inColor);
756        builder.fFSCode.appendf("\tvec4 matrixedColor = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n",
757                                colMatrixName, color, color, color, colMatrixVecName);
758        builder.fFSCode.append("\tmatrixedColor.rgb *= matrixedColor.a;\n");
759
760        inColor = "matrixedColor";
761    }
762
763    ///////////////////////////////////////////////////////////////////////////
764    // compute the partial coverage (coverage stages and edge aa)
765
766    SkString inCoverage;
767    bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput;
768    // we don't need to compute coverage at all if we know the final shader
769    // output will be zero and we don't have a dual src blend output.
770    if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
771
772        if (!coverageIsZero) {
773            this->genEdgeCoverage(&inCoverage, &builder);
774
775            switch (fDesc.fCoverageInput) {
776                case Desc::kSolidWhite_ColorInput:
777                    // empty string implies solid white
778                    break;
779                case Desc::kAttribute_ColorInput:
780                    gen_attribute_coverage(&builder, &inCoverage);
781                    break;
782                case Desc::kUniform_ColorInput:
783                    this->genUniformCoverage(&builder, &inCoverage);
784                    break;
785                default:
786                    GrCrash("Unexpected input coverage.");
787            }
788
789            SkString outCoverage;
790            const int& startStage = fDesc.fFirstCoverageStage;
791            for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
792                if (fDesc.fStages[s].isEnabled()) {
793                    // create var to hold stage output
794                    outCoverage = "coverage";
795                    outCoverage.appendS32(s);
796                    builder.fFSCode.appendf("\tvec4 %s;\n",
797                                            outCoverage.c_str());
798
799                    const char* inCoords;
800                    // figure out what our input coords are
801                    int tcIdx =
802                        GrDrawTarget::VertexTexCoordsForStage(s, layout);
803                    if (tcIdx < 0) {
804                        inCoords = POS_ATTR_NAME;
805                    } else {
806                        // must have input tex coordinates if stage is
807                        // enabled.
808                        GrAssert(texCoordAttrs[tcIdx].size());
809                        inCoords = texCoordAttrs[tcIdx].c_str();
810                    }
811
812                    if (NULL != customStages[s]) {
813                        const GrProgramStageFactory& factory = customStages[s]->getFactory();
814                        fProgramStage[s] = factory.createGLInstance(*customStages[s]);
815                    }
816                    this->genStageCode(s,
817                                       inCoverage.size() ? inCoverage.c_str() : NULL,
818                                       outCoverage.c_str(),
819                                       inCoords,
820                                       &builder);
821                    inCoverage = outCoverage;
822                }
823            }
824        }
825
826        if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
827            builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
828                                               GrGLShaderVar::kOut_TypeModifier,
829                                               dual_source_output_name());
830            bool outputIsZero = coverageIsZero;
831            SkString coeff;
832            if (!outputIsZero &&
833                Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
834                if (!inColor.size()) {
835                    outputIsZero = true;
836                } else {
837                    if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
838                        coeff.printf("(1 - %s.a)", inColor.c_str());
839                    } else {
840                        coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
841                    }
842                }
843            }
844            if (outputIsZero) {
845                builder.fFSCode.appendf("\t%s = %s;\n",
846                                        dual_source_output_name(),
847                                         all_zeros_vec(4));
848            } else {
849                modulate_helper(dual_source_output_name(),
850                                coeff.c_str(),
851                                inCoverage.c_str(),
852                                &builder.fFSCode);
853            }
854            dualSourceOutputWritten = true;
855        }
856    }
857
858    ///////////////////////////////////////////////////////////////////////////
859    // combine color and coverage as frag color
860
861    if (!wroteFragColorZero) {
862        if (coverageIsZero) {
863            builder.fFSCode.appendf("\t%s = %s;\n",
864                                    colorOutput.getName().c_str(),
865                                    all_zeros_vec(4));
866        } else {
867            modulate_helper(colorOutput.getName().c_str(),
868                            inColor.c_str(),
869                            inCoverage.c_str(),
870                            &builder.fFSCode);
871        }
872        if (Desc::kUnpremultiplied_RoundDown_OutputConfig == fDesc.fOutputConfig) {
873            builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
874                                    colorOutput.getName().c_str(),
875                                    colorOutput.getName().c_str(),
876                                    colorOutput.getName().c_str(),
877                                    colorOutput.getName().c_str(),
878                                    colorOutput.getName().c_str());
879        } else if (Desc::kUnpremultiplied_RoundUp_OutputConfig == fDesc.fOutputConfig) {
880            builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
881                                    colorOutput.getName().c_str(),
882                                    colorOutput.getName().c_str(),
883                                    colorOutput.getName().c_str(),
884                                    colorOutput.getName().c_str(),
885                                    colorOutput.getName().c_str());
886        }
887    }
888
889    builder.fVSCode.append("}\n");
890    builder.fFSCode.append("}\n");
891
892    ///////////////////////////////////////////////////////////////////////////
893    // insert GS
894#if GR_DEBUG
895    this->genGeometryShader(&builder);
896#endif
897
898    ///////////////////////////////////////////////////////////////////////////
899    // compile and setup attribs and unis
900
901    if (!this->compileShaders(builder)) {
902        return false;
903    }
904
905    if (!this->bindOutputsAttribsAndLinkProgram(texCoordAttrs,
906                                                isColorDeclared,
907                                                dualSourceOutputWritten)) {
908        return false;
909    }
910
911    builder.finished(fProgramID);
912    this->initSamplerUniforms();
913
914    return true;
915}
916
917bool GrGLProgram::bindOutputsAttribsAndLinkProgram(SkString texCoordAttrNames[],
918                                                   bool bindColorOut,
919                                                   bool bindDualSrcOut) {
920    GL_CALL_RET(fProgramID, CreateProgram());
921    if (!fProgramID) {
922        return false;
923    }
924
925    GL_CALL(AttachShader(fProgramID, fVShaderID));
926    if (fGShaderID) {
927        GL_CALL(AttachShader(fProgramID, fGShaderID));
928    }
929    GL_CALL(AttachShader(fProgramID, fFShaderID));
930
931    if (bindColorOut) {
932        GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
933    }
934    if (bindDualSrcOut) {
935        GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
936    }
937
938    // Bind the attrib locations to same values for all shaders
939    GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME));
940    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
941        if (texCoordAttrNames[t].size()) {
942            GL_CALL(BindAttribLocation(fProgramID,
943                                       TexCoordAttributeIdx(t),
944                                       texCoordAttrNames[t].c_str()));
945        }
946    }
947
948    GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
949    GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
950    GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
951
952    GL_CALL(LinkProgram(fProgramID));
953
954    GrGLint linked = GR_GL_INIT_ZERO;
955    GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
956    if (!linked) {
957        GrGLint infoLen = GR_GL_INIT_ZERO;
958        GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
959        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
960        if (infoLen > 0) {
961            // retrieve length even though we don't need it to workaround
962            // bug in chrome cmd buffer param validation.
963            GrGLsizei length = GR_GL_INIT_ZERO;
964            GL_CALL(GetProgramInfoLog(fProgramID,
965                                      infoLen+1,
966                                      &length,
967                                      (char*)log.get()));
968            GrPrintf((char*)log.get());
969        }
970        GrAssert(!"Error linking program");
971        GL_CALL(DeleteProgram(fProgramID));
972        fProgramID = 0;
973        return false;
974    }
975    return true;
976}
977
978void GrGLProgram::initSamplerUniforms() {
979    GL_CALL(UseProgram(fProgramID));
980    // init sampler unis and set bogus values for state tracking
981    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
982        if (GrGLUniformManager::kInvalidUniformHandle != fUniforms.fStages[s].fSamplerUni) {
983            fUniformManager.setSampler(fUniforms.fStages[s].fSamplerUni, s);
984        }
985    }
986}
987
988///////////////////////////////////////////////////////////////////////////////
989// Stage code generation
990
991void GrGLProgram::genStageCode(int stageNum,
992                               const char* fsInColor, // NULL means no incoming color
993                               const char* fsOutColor,
994                               const char* vsInCoord,
995                               GrGLShaderBuilder* builder) {
996    GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
997
998    const GrGLProgram::StageDesc& desc = fDesc.fStages[stageNum];
999    StageUniforms& uniforms = fUniforms.fStages[stageNum];
1000    GrGLProgramStage* customStage = fProgramStage[stageNum];
1001
1002    GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags);
1003
1004    builder->setCurrentStage(stageNum);
1005
1006    /// Vertex Shader Stuff
1007
1008    // decide whether we need a matrix to transform texture coords and whether the varying needs a
1009    // perspective coord.
1010    const char* matName = NULL;
1011    if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
1012        builder->fVaryingDims = builder->fCoordDims;
1013    } else {
1014        uniforms.fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType,
1015                                                         kMat33f_GrSLType, "TexM", &matName);
1016        const GrGLShaderVar& mat = builder->getUniformVariable(uniforms.fTextureMatrixUni);
1017
1018        if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
1019            builder->fVaryingDims = builder->fCoordDims;
1020        } else {
1021            builder->fVaryingDims = builder->fCoordDims + 1;
1022        }
1023    }
1024    GrAssert(builder->fVaryingDims > 0);
1025
1026    // Must setup variables after computing segments->fVaryingDims
1027    if (NULL != customStage) {
1028        customStage->setupVariables(builder);
1029    }
1030
1031    const char* samplerName;
1032    uniforms.fSamplerUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1033                                               kSampler2D_GrSLType, "Sampler", &samplerName);
1034
1035    const char *varyingVSName, *varyingFSName;
1036    builder->addVarying(GrSLFloatVectorType(builder->fVaryingDims),
1037                        "Stage",
1038                        &varyingVSName,
1039                        &varyingFSName);
1040
1041    if (!matName) {
1042        GrAssert(builder->fVaryingDims == builder->fCoordDims);
1043        builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord);
1044    } else {
1045        // varying = texMatrix * texCoord
1046        builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n",
1047                                  varyingVSName, matName, vsInCoord,
1048                                  vector_all_coords(builder->fVaryingDims));
1049    }
1050
1051    if (NULL != customStage) {
1052        builder->fVSCode.appendf("\t{ // stage %d %s\n",
1053                                 stageNum, customStage->name());
1054        customStage->emitVS(builder, varyingVSName);
1055        builder->fVSCode.appendf("\t}\n");
1056    }
1057
1058    /// Fragment Shader Stuff
1059
1060    builder->fSampleCoords = varyingFSName;
1061
1062    GrGLShaderBuilder::SamplerMode sampleMode =
1063        GrGLShaderBuilder::kExplicitDivide_SamplerMode;
1064    if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
1065                          StageDesc::kNoPerspective_OptFlagBit)) {
1066        sampleMode = GrGLShaderBuilder::kDefault_SamplerMode;
1067    } else if (NULL == customStage) {
1068        sampleMode = GrGLShaderBuilder::kProj_SamplerMode;
1069    }
1070    builder->setupTextureAccess(sampleMode, stageNum);
1071
1072    builder->computeSwizzle(desc.fInConfigFlags);
1073    builder->computeModulate(fsInColor);
1074
1075    static const uint32_t kMulByAlphaMask =
1076        (StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
1077         StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
1078
1079    // NOTE: GrGLProgramStages are now responsible for fetching
1080    if (NULL == customStage) {
1081        if (desc.fInConfigFlags & kMulByAlphaMask) {
1082            // only one of the mul by alpha flags should be set
1083            GrAssert(GrIsPow2(kMulByAlphaMask & desc.fInConfigFlags));
1084            GrAssert(!(desc.fInConfigFlags &
1085                       StageDesc::kSmearAlpha_InConfigFlag));
1086            GrAssert(!(desc.fInConfigFlags &
1087                       StageDesc::kSmearRed_InConfigFlag));
1088            builder->fFSCode.appendf("\t%s = %s(%s, %s)%s;\n",
1089                                     fsOutColor,
1090                                     builder->fTexFunc.c_str(),
1091                                     samplerName,
1092                                     builder->fSampleCoords.c_str(),
1093                                     builder->fSwizzle.c_str());
1094            if (desc.fInConfigFlags &
1095                StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag) {
1096                builder->fFSCode.appendf("\t%s = vec4(ceil(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
1097                                         fsOutColor, fsOutColor, fsOutColor,
1098                                         fsOutColor, builder->fModulate.c_str());
1099            } else {
1100                builder->fFSCode.appendf("\t%s = vec4(floor(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
1101                                         fsOutColor, fsOutColor, fsOutColor,
1102                                         fsOutColor, builder->fModulate.c_str());
1103            }
1104        } else {
1105            builder->emitDefaultFetch(fsOutColor, samplerName);
1106        }
1107    }
1108
1109    if (NULL != customStage) {
1110        // Enclose custom code in a block to avoid namespace conflicts
1111        builder->fFSCode.appendf("\t{ // stage %d %s \n",
1112                                 stageNum, customStage->name());
1113        customStage->emitFS(builder, fsOutColor, fsInColor,
1114                            samplerName);
1115        builder->fFSCode.appendf("\t}\n");
1116    }
1117    builder->setNonStage();
1118}
1119