GrGLProgram.cpp revision c3a58f345de16c185db3a20578c7ddf52bc89d38
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 "gl/GrGLShaderBuilder.h" 14#include "GrGLShaderVar.h" 15#include "GrBackendEffectFactory.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 COL_ATTR_NAME "aColor" 29#define COV_ATTR_NAME "aCoverage" 30#define EDGE_ATTR_NAME "aEdge" 31 32namespace { 33inline void tex_attr_name(int coordIdx, SkString* s) { 34 *s = "aTexCoord"; 35 s->appendS32(coordIdx); 36} 37 38inline const char* float_vector_type_str(int count) { 39 return GrGLShaderVar::TypeString(GrSLFloatVectorType(count)); 40} 41 42inline const char* vector_all_coords(int count) { 43 static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"}; 44 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL)); 45 return ALL[count]; 46} 47 48inline const char* declared_color_output_name() { return "fsColorOut"; } 49inline const char* dual_source_output_name() { return "dualSourceOut"; } 50 51} 52 53GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl, 54 const Desc& desc, 55 const GrEffectStage* stages[]) { 56 GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages)); 57 if (!program->succeeded()) { 58 delete program; 59 program = NULL; 60 } 61 return program; 62} 63 64GrGLProgram::GrGLProgram(const GrGLContextInfo& gl, 65 const Desc& desc, 66 const GrEffectStage* stages[]) 67: fContextInfo(gl) 68, fUniformManager(gl) { 69 fDesc = desc; 70 fVShaderID = 0; 71 fGShaderID = 0; 72 fFShaderID = 0; 73 fProgramID = 0; 74 75 fViewMatrix = GrMatrix::InvalidMatrix(); 76 fViewportSize.set(-1, -1); 77 fColor = GrColor_ILLEGAL; 78 fColorFilterColor = GrColor_ILLEGAL; 79 fRTHeight = -1; 80 81 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 82 fEffects[s] = NULL; 83 fTextureMatrices[s] = GrMatrix::InvalidMatrix(); 84 // this is arbitrary, just initialize to something 85 fTextureOrigin[s] = GrSurface::kBottomLeft_Origin; 86 } 87 88 this->genProgram(stages); 89} 90 91GrGLProgram::~GrGLProgram() { 92 if (fVShaderID) { 93 GL_CALL(DeleteShader(fVShaderID)); 94 } 95 if (fGShaderID) { 96 GL_CALL(DeleteShader(fGShaderID)); 97 } 98 if (fFShaderID) { 99 GL_CALL(DeleteShader(fFShaderID)); 100 } 101 if (fProgramID) { 102 GL_CALL(DeleteProgram(fProgramID)); 103 } 104 105 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 106 delete fEffects[i]; 107 } 108} 109 110void GrGLProgram::abandon() { 111 fVShaderID = 0; 112 fGShaderID = 0; 113 fFShaderID = 0; 114 fProgramID = 0; 115} 116 117void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 118 GrBlendCoeff* dstCoeff) const { 119 switch (fDesc.fDualSrcOutput) { 120 case Desc::kNone_DualSrcOutput: 121 break; 122 // the prog will write a coverage value to the secondary 123 // output and the dst is blended by one minus that value. 124 case Desc::kCoverage_DualSrcOutput: 125 case Desc::kCoverageISA_DualSrcOutput: 126 case Desc::kCoverageISC_DualSrcOutput: 127 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; 128 break; 129 default: 130 GrCrash("Unexpected dual source blend output"); 131 break; 132 } 133} 134 135// given two blend coeffecients determine whether the src 136// and/or dst computation can be omitted. 137static inline void needBlendInputs(SkXfermode::Coeff srcCoeff, 138 SkXfermode::Coeff dstCoeff, 139 bool* needSrcValue, 140 bool* needDstValue) { 141 if (SkXfermode::kZero_Coeff == srcCoeff) { 142 switch (dstCoeff) { 143 // these all read the src 144 case SkXfermode::kSC_Coeff: 145 case SkXfermode::kISC_Coeff: 146 case SkXfermode::kSA_Coeff: 147 case SkXfermode::kISA_Coeff: 148 *needSrcValue = true; 149 break; 150 default: 151 *needSrcValue = false; 152 break; 153 } 154 } else { 155 *needSrcValue = true; 156 } 157 if (SkXfermode::kZero_Coeff == dstCoeff) { 158 switch (srcCoeff) { 159 // these all read the dst 160 case SkXfermode::kDC_Coeff: 161 case SkXfermode::kIDC_Coeff: 162 case SkXfermode::kDA_Coeff: 163 case SkXfermode::kIDA_Coeff: 164 *needDstValue = true; 165 break; 166 default: 167 *needDstValue = false; 168 break; 169 } 170 } else { 171 *needDstValue = true; 172 } 173} 174 175/** 176 * Create a blend_coeff * value string to be used in shader code. Sets empty 177 * string if result is trivially zero. 178 */ 179static void blendTermString(SkString* str, SkXfermode::Coeff coeff, 180 const char* src, const char* dst, 181 const char* value) { 182 switch (coeff) { 183 case SkXfermode::kZero_Coeff: /** 0 */ 184 *str = ""; 185 break; 186 case SkXfermode::kOne_Coeff: /** 1 */ 187 *str = value; 188 break; 189 case SkXfermode::kSC_Coeff: 190 str->printf("(%s * %s)", src, value); 191 break; 192 case SkXfermode::kISC_Coeff: 193 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value); 194 break; 195 case SkXfermode::kDC_Coeff: 196 str->printf("(%s * %s)", dst, value); 197 break; 198 case SkXfermode::kIDC_Coeff: 199 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value); 200 break; 201 case SkXfermode::kSA_Coeff: /** src alpha */ 202 str->printf("(%s.a * %s)", src, value); 203 break; 204 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 205 str->printf("((1.0 - %s.a) * %s)", src, value); 206 break; 207 case SkXfermode::kDA_Coeff: /** dst alpha */ 208 str->printf("(%s.a * %s)", dst, value); 209 break; 210 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 211 str->printf("((1.0 - %s.a) * %s)", dst, value); 212 break; 213 default: 214 GrCrash("Unexpected xfer coeff."); 215 break; 216 } 217} 218/** 219 * Adds a line to the fragment shader code which modifies the color by 220 * the specified color filter. 221 */ 222static void addColorFilter(SkString* fsCode, const char * outputVar, 223 SkXfermode::Coeff uniformCoeff, 224 SkXfermode::Coeff colorCoeff, 225 const char* filterColor, 226 const char* inColor) { 227 SkString colorStr, constStr; 228 blendTermString(&colorStr, colorCoeff, filterColor, inColor, inColor); 229 blendTermString(&constStr, uniformCoeff, filterColor, inColor, filterColor); 230 231 fsCode->appendf("\t%s = ", outputVar); 232 GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str()); 233 fsCode->append(";\n"); 234} 235 236bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, 237 GrGLShaderBuilder* builder) const { 238 if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) { 239 const char *vsName, *fsName; 240 builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); 241 builder->fVSAttrs.push_back().set(kVec4f_GrSLType, 242 GrGLShaderVar::kAttribute_TypeModifier, 243 EDGE_ATTR_NAME); 244 builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); 245 switch (fDesc.fVertexEdgeType) { 246 case GrDrawState::kHairLine_EdgeType: 247 builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName); 248 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 249 break; 250 case GrDrawState::kQuad_EdgeType: 251 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 252 // keep the derivative instructions outside the conditional 253 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 254 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 255 builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 256 // today we know z and w are in device space. We could use derivatives 257 builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); 258 builder->fFSCode.append ("\t} else {\n"); 259 builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 260 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 261 fsName, fsName); 262 builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 263 builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" 264 "\t}\n"); 265 if (kES2_GrGLBinding == fContextInfo.binding()) { 266 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 267 } 268 break; 269 case GrDrawState::kHairQuad_EdgeType: 270 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 271 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 272 builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 273 "\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 274 fsName, fsName); 275 builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 276 builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 277 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 278 if (kES2_GrGLBinding == fContextInfo.binding()) { 279 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 280 } 281 break; 282 case GrDrawState::kCircle_EdgeType: 283 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 284 builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName); 285 builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 286 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); 287 builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n"); 288 break; 289 default: 290 GrCrash("Unknown Edge Type!"); 291 break; 292 } 293 *coverageVar = "edgeAlpha"; 294 return true; 295 } else { 296 coverageVar->reset(); 297 return false; 298 } 299} 300 301void 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 fUniforms.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 330void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { 331 const char* covUniName; 332 fUniforms.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 343namespace { 344void 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 362void 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 387const 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 399namespace { 400// prints a shader using params similar to glShaderSource 401void 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 414GrGLuint 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 455GrGLuint 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 464bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { 465 466 SkString shader; 467 468 builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader); 469#if PRINT_SHADERS 470 GrPrintf(shader.c_str()); 471 GrPrintf("\n"); 472#endif 473 if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) { 474 return false; 475 } 476 477 if (builder.fUsesGS) { 478 builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); 479#if PRINT_SHADERS 480 GrPrintf(shader.c_str()); 481 GrPrintf("\n"); 482#endif 483 if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) { 484 return false; 485 } 486 } else { 487 fGShaderID = 0; 488 } 489 490 builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); 491#if PRINT_SHADERS 492 GrPrintf(shader.c_str()); 493 GrPrintf("\n"); 494#endif 495 if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) { 496 return false; 497 } 498 499 return true; 500} 501 502bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { 503 GrAssert(0 == fProgramID); 504 505 GrGLShaderBuilder builder(fContextInfo, fUniformManager); 506 const uint32_t& layout = fDesc.fVertexLayout; 507 508#if GR_GL_EXPERIMENTAL_GS 509 builder.fUsesGS = fDesc.fExperimentalGS; 510#endif 511 512 SkXfermode::Coeff colorCoeff, uniformCoeff; 513 // The rest of transfer mode color filters have not been implemented 514 if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 515 GR_DEBUGCODE(bool success =) 516 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 517 (fDesc.fColorFilterXfermode), 518 &uniformCoeff, &colorCoeff); 519 GR_DEBUGASSERT(success); 520 } else { 521 colorCoeff = SkXfermode::kOne_Coeff; 522 uniformCoeff = SkXfermode::kZero_Coeff; 523 } 524 525 // no need to do the color filter if coverage is 0. The output color is scaled by the coverage. 526 // All the dual source outputs are scaled by the coverage as well. 527 if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) { 528 colorCoeff = SkXfermode::kZero_Coeff; 529 uniformCoeff = SkXfermode::kZero_Coeff; 530 } 531 532 // If we know the final color is going to be all zeros then we can 533 // simplify the color filter coefficients. needComputedColor will then 534 // come out false below. 535 if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) { 536 colorCoeff = SkXfermode::kZero_Coeff; 537 if (SkXfermode::kDC_Coeff == uniformCoeff || 538 SkXfermode::kDA_Coeff == uniformCoeff) { 539 uniformCoeff = SkXfermode::kZero_Coeff; 540 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 541 SkXfermode::kIDA_Coeff == uniformCoeff) { 542 uniformCoeff = SkXfermode::kOne_Coeff; 543 } 544 } 545 546 bool needColorFilterUniform; 547 bool needComputedColor; 548 needBlendInputs(uniformCoeff, colorCoeff, 549 &needColorFilterUniform, &needComputedColor); 550 551 // the dual source output has no canonical var name, have to 552 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 553 bool dualSourceOutputWritten = false; 554 builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(), 555 fContextInfo.glslGeneration())); 556 557 GrGLShaderVar colorOutput; 558 bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(), 559 declared_color_output_name(), 560 &colorOutput); 561 if (isColorDeclared) { 562 builder.fFSOutputs.push_back(colorOutput); 563 } 564 565 const char* viewMName; 566 fUniforms.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, 567 kMat33f_GrSLType, "ViewM", &viewMName); 568 569 570 builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" 571 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 572 viewMName, builder.positionAttribute().getName().c_str()); 573 574 // incoming color to current stage being processed. 575 SkString inColor; 576 577 if (needComputedColor) { 578 this->genInputColor(&builder, &inColor); 579 } 580 581 // we output point size in the GS if present 582 if (fDesc.fEmitsPointSize && !builder.fUsesGS){ 583 builder.fVSCode.append("\tgl_PointSize = 1.0;\n"); 584 } 585 586 // add texture coordinates that are used to the list of vertex attr decls 587 SkString texCoordAttrs[GrDrawState::kMaxTexCoords]; 588 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 589 if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) { 590 tex_attr_name(t, texCoordAttrs + t); 591 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 592 GrGLShaderVar::kAttribute_TypeModifier, 593 texCoordAttrs[t].c_str()); 594 } 595 } 596 597 /////////////////////////////////////////////////////////////////////////// 598 // compute the final color 599 600 // if we have color stages string them together, feeding the output color 601 // of each to the next and generating code for each stage. 602 if (needComputedColor) { 603 SkString outColor; 604 for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { 605 if (fDesc.fStages[s].isEnabled()) { 606 // create var to hold stage result 607 outColor = "color"; 608 outColor.appendS32(s); 609 builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); 610 611 const char* inCoords; 612 // figure out what our input coords are 613 int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); 614 if (tcIdx < 0) { 615 inCoords = builder.positionAttribute().c_str(); 616 } else { 617 // must have input tex coordinates if stage is enabled. 618 GrAssert(texCoordAttrs[tcIdx].size()); 619 inCoords = texCoordAttrs[tcIdx].c_str(); 620 } 621 622 builder.setCurrentStage(s); 623 fEffects[s] = GenStageCode(*stages[s], 624 fDesc.fStages[s], 625 &fUniforms.fStages[s], 626 inColor.size() ? inColor.c_str() : NULL, 627 outColor.c_str(), 628 inCoords, 629 &builder); 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 needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, 646 &needColorFilterUniform, &bogus); 647 } 648 } 649 const char* colorFilterColorUniName = NULL; 650 if (needColorFilterUniform) { 651 fUniforms.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, 652 kVec4f_GrSLType, "FilterColor", 653 &colorFilterColorUniName); 654 } 655 bool wroteFragColorZero = false; 656 if (SkXfermode::kZero_Coeff == uniformCoeff && 657 SkXfermode::kZero_Coeff == colorCoeff) { 658 builder.fFSCode.appendf("\t%s = %s;\n", 659 colorOutput.getName().c_str(), 660 GrGLSLZerosVecf(4)); 661 wroteFragColorZero = true; 662 } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { 663 builder.fFSCode.append("\tvec4 filteredColor;\n"); 664 const char* color = adjustInColor(inColor); 665 addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, 666 colorCoeff, colorFilterColorUniName, color); 667 inColor = "filteredColor"; 668 } 669 670 /////////////////////////////////////////////////////////////////////////// 671 // compute the partial coverage (coverage stages and edge aa) 672 673 SkString inCoverage; 674 bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput; 675 // we don't need to compute coverage at all if we know the final shader 676 // output will be zero and we don't have a dual src blend output. 677 if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 678 679 if (!coverageIsZero) { 680 bool inCoverageIsScalar = this->genEdgeCoverage(&inCoverage, &builder); 681 682 switch (fDesc.fCoverageInput) { 683 case Desc::kSolidWhite_ColorInput: 684 // empty string implies solid white 685 break; 686 case Desc::kAttribute_ColorInput: 687 gen_attribute_coverage(&builder, &inCoverage); 688 inCoverageIsScalar = false; 689 break; 690 case Desc::kUniform_ColorInput: 691 this->genUniformCoverage(&builder, &inCoverage); 692 inCoverageIsScalar = false; 693 break; 694 default: 695 GrCrash("Unexpected input coverage."); 696 } 697 698 SkString outCoverage; 699 const int& startStage = fDesc.fFirstCoverageStage; 700 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 701 if (fDesc.fStages[s].isEnabled()) { 702 // create var to hold stage output 703 outCoverage = "coverage"; 704 outCoverage.appendS32(s); 705 builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str()); 706 707 const char* inCoords; 708 // figure out what our input coords are 709 int tcIdx = 710 GrDrawTarget::VertexTexCoordsForStage(s, layout); 711 if (tcIdx < 0) { 712 inCoords = builder.positionAttribute().c_str(); 713 } else { 714 // must have input tex coordinates if stage is 715 // enabled. 716 GrAssert(texCoordAttrs[tcIdx].size()); 717 inCoords = texCoordAttrs[tcIdx].c_str(); 718 } 719 720 // stages don't know how to deal with a scalar input. (Maybe they should. We 721 // could pass a GrGLShaderVar) 722 if (inCoverageIsScalar) { 723 builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n", 724 inCoverage.c_str(), inCoverage.c_str()); 725 inCoverage.append("4"); 726 } 727 builder.setCurrentStage(s); 728 fEffects[s] = GenStageCode(*stages[s], 729 fDesc.fStages[s], 730 &fUniforms.fStages[s], 731 inCoverage.size() ? inCoverage.c_str() : NULL, 732 outCoverage.c_str(), 733 inCoords, 734 &builder); 735 builder.setNonStage(); 736 inCoverage = outCoverage; 737 } 738 } 739 } 740 741 if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 742 builder.fFSOutputs.push_back().set(kVec4f_GrSLType, 743 GrGLShaderVar::kOut_TypeModifier, 744 dual_source_output_name()); 745 bool outputIsZero = coverageIsZero; 746 SkString coeff; 747 if (!outputIsZero && 748 Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { 749 if (!inColor.size()) { 750 outputIsZero = true; 751 } else { 752 if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { 753 coeff.printf("(1 - %s.a)", inColor.c_str()); 754 } else { 755 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 756 } 757 } 758 } 759 if (outputIsZero) { 760 builder.fFSCode.appendf("\t%s = %s;\n", 761 dual_source_output_name(), 762 GrGLSLZerosVecf(4)); 763 } else { 764 builder.fFSCode.appendf("\t%s =", dual_source_output_name()); 765 GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str()); 766 builder.fFSCode.append(";\n"); 767 } 768 dualSourceOutputWritten = true; 769 } 770 } 771 772 /////////////////////////////////////////////////////////////////////////// 773 // combine color and coverage as frag color 774 775 if (!wroteFragColorZero) { 776 if (coverageIsZero) { 777 builder.fFSCode.appendf("\t%s = %s;\n", 778 colorOutput.getName().c_str(), 779 GrGLSLZerosVecf(4)); 780 } else { 781 builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str()); 782 GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str()); 783 builder.fFSCode.append(";\n"); 784 } 785 } 786 787 /////////////////////////////////////////////////////////////////////////// 788 // insert GS 789#if GR_DEBUG 790 this->genGeometryShader(&builder); 791#endif 792 793 /////////////////////////////////////////////////////////////////////////// 794 // compile and setup attribs and unis 795 796 if (!this->compileShaders(builder)) { 797 return false; 798 } 799 800 if (!this->bindOutputsAttribsAndLinkProgram(builder, 801 texCoordAttrs, 802 isColorDeclared, 803 dualSourceOutputWritten)) { 804 return false; 805 } 806 807 builder.finished(fProgramID); 808 this->initSamplerUniforms(); 809 fUniforms.fRTHeight = builder.getRTHeightUniform(); 810 811 return true; 812} 813 814bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, 815 SkString texCoordAttrNames[], 816 bool bindColorOut, 817 bool bindDualSrcOut) { 818 GL_CALL_RET(fProgramID, CreateProgram()); 819 if (!fProgramID) { 820 return false; 821 } 822 823 GL_CALL(AttachShader(fProgramID, fVShaderID)); 824 if (fGShaderID) { 825 GL_CALL(AttachShader(fProgramID, fGShaderID)); 826 } 827 GL_CALL(AttachShader(fProgramID, fFShaderID)); 828 829 if (bindColorOut) { 830 GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name())); 831 } 832 if (bindDualSrcOut) { 833 GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name())); 834 } 835 836 // Bind the attrib locations to same values for all shaders 837 GL_CALL(BindAttribLocation(fProgramID, 838 PositionAttributeIdx(), 839 builder.positionAttribute().c_str())); 840 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 841 if (texCoordAttrNames[t].size()) { 842 GL_CALL(BindAttribLocation(fProgramID, 843 TexCoordAttributeIdx(t), 844 texCoordAttrNames[t].c_str())); 845 } 846 } 847 848 GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME)); 849 GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME)); 850 GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); 851 852 GL_CALL(LinkProgram(fProgramID)); 853 854 GrGLint linked = GR_GL_INIT_ZERO; 855 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 856 if (!linked) { 857 GrGLint infoLen = GR_GL_INIT_ZERO; 858 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 859 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 860 if (infoLen > 0) { 861 // retrieve length even though we don't need it to workaround 862 // bug in chrome cmd buffer param validation. 863 GrGLsizei length = GR_GL_INIT_ZERO; 864 GL_CALL(GetProgramInfoLog(fProgramID, 865 infoLen+1, 866 &length, 867 (char*)log.get())); 868 GrPrintf((char*)log.get()); 869 } 870 GrAssert(!"Error linking program"); 871 GL_CALL(DeleteProgram(fProgramID)); 872 fProgramID = 0; 873 return false; 874 } 875 return true; 876} 877 878void GrGLProgram::initSamplerUniforms() { 879 GL_CALL(UseProgram(fProgramID)); 880 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 881 int count = fUniforms.fStages[s].fSamplerUniforms.count(); 882 // FIXME: We're still always reserving one texture per stage. After GrTextureParams are 883 // expressed by the effect rather than the GrEffectStage we can move texture binding 884 // into GrGLProgram and it should be easier to fix this. 885 GrAssert(count <= 1); 886 for (int t = 0; t < count; ++t) { 887 UniformHandle uh = fUniforms.fStages[s].fSamplerUniforms[t]; 888 if (GrGLUniformManager::kInvalidUniformHandle != uh) { 889 fUniformManager.setSampler(uh, s); 890 } 891 } 892 } 893} 894 895/////////////////////////////////////////////////////////////////////////////// 896// Stage code generation 897 898// TODO: Move this function to GrGLShaderBuilder 899GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage, 900 const StageDesc& desc, 901 StageUniforms* uniforms, 902 const char* fsInColor, // NULL means no incoming color 903 const char* fsOutColor, 904 const char* vsInCoord, 905 GrGLShaderBuilder* builder) { 906 907 const GrEffect* effect = stage.getEffect(); 908 GrGLEffect* glEffect = effect->getFactory().createGLInstance(*effect); 909 910 /// Vertex Shader Stuff 911 912 const char* vertexCoords; 913 914 // Has the effect not yet been updated to insert its own texture matrix if necessary. 915 if (glEffect->requiresTextureMatrix()) { 916 // Decide whether we need a matrix to transform texture coords and whether the varying needs 917 // a perspective coord. 918 const char* matName = NULL; 919 GrSLType texCoordVaryingType; 920 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) { 921 texCoordVaryingType = kVec2f_GrSLType; 922 } else { 923 uniforms->fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType, 924 kMat33f_GrSLType, "TexM", &matName); 925 builder->getUniformVariable(uniforms->fTextureMatrixUni); 926 927 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { 928 texCoordVaryingType = kVec2f_GrSLType; 929 } else { 930 texCoordVaryingType = kVec3f_GrSLType; 931 } 932 } 933 const char *varyingVSName, *varyingFSName; 934 builder->addVarying(texCoordVaryingType, 935 "Stage", 936 &varyingVSName, 937 &varyingFSName); 938 builder->setupTextureAccess(varyingFSName, texCoordVaryingType); 939 940 if (!matName) { 941 GrAssert(kVec2f_GrSLType == texCoordVaryingType); 942 builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord); 943 } else { 944 // varying = texMatrix * texCoord 945 builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n", 946 varyingVSName, matName, vsInCoord, 947 vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType))); 948 } 949 vertexCoords = varyingVSName; 950 } else { 951 vertexCoords = vsInCoord; 952 } 953 954 // setup texture samplers for gl effect 955 int numTextures = effect->numTextures(); 956 SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; 957 textureSamplers.push_back_n(numTextures); 958 for (int i = 0; i < numTextures; ++i) { 959 textureSamplers[i].init(builder, &effect->textureAccess(i)); 960 uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform); 961 } 962 963 // Enclose custom code in a block to avoid namespace conflicts 964 builder->fVSCode.appendf("\t{ // %s\n", glEffect->name()); 965 builder->fFSCode.appendf("\t{ // %s \n", glEffect->name()); 966 glEffect->emitCode(builder, 967 stage, 968 desc.fEffectKey, 969 vertexCoords, 970 fsOutColor, 971 fsInColor, 972 textureSamplers); 973 builder->fVSCode.appendf("\t}\n"); 974 builder->fFSCode.appendf("\t}\n"); 975 976 return glEffect; 977} 978 979void GrGLProgram::setData(const GrDrawState& drawState) { 980 int rtHeight = drawState.getRenderTarget()->height(); 981 if (GrGLUniformManager::kInvalidUniformHandle != fUniforms.fRTHeight && fRTHeight != rtHeight) { 982 fUniformManager.set1f(fUniforms.fRTHeight, GrIntToScalar(rtHeight)); 983 fRTHeight = rtHeight; 984 } 985 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 986 if (NULL != fEffects[s]) { 987 const GrEffectStage& stage = drawState.getStage(s); 988 GrAssert(NULL != stage.getEffect()); 989 fEffects[s]->setData(fUniformManager, stage); 990 } 991 } 992} 993