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