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