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