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