• 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