GrGLProgram.cpp revision dbbf843dfe2a62ad341ebe4f946667204c64231d
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* declared_color_output_name() { return "fsColorOut"; } 50inline const char* dual_source_output_name() { return "dualSourceOut"; } 51 52} 53 54GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl, 55 const Desc& desc, 56 const GrCustomStage** customStages) { 57 GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, customStages)); 58 if (!program->succeeded()) { 59 delete program; 60 program = NULL; 61 } 62 return program; 63} 64 65GrGLProgram::GrGLProgram(const GrGLContextInfo& gl, 66 const Desc& desc, 67 const GrCustomStage** customStages) 68: fContextInfo(gl) 69, fUniformManager(gl) { 70 fDesc = desc; 71 fVShaderID = 0; 72 fGShaderID = 0; 73 fFShaderID = 0; 74 fProgramID = 0; 75 76 fViewMatrix = GrMatrix::InvalidMatrix(); 77 fViewportSize.set(-1, -1); 78 fColor = GrColor_ILLEGAL; 79 fColorFilterColor = GrColor_ILLEGAL; 80 81 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 82 fProgramStage[s] = NULL; 83 fTextureMatrices[s] = GrMatrix::InvalidMatrix(); 84 // this is arbitrary, just initialize to something 85 fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation; 86 } 87 88 this->genProgram(customStages); 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 fProgramStage[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* segments) const { 238 if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) { 239 const char *vsName, *fsName; 240 segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); 241 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 242 GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME); 243 segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); 244 switch (fDesc.fVertexEdgeType) { 245 case GrDrawState::kHairLine_EdgeType: 246 segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName); 247 segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 248 break; 249 case GrDrawState::kQuad_EdgeType: 250 segments->fFSCode.append("\tfloat edgeAlpha;\n"); 251 // keep the derivative instructions outside the conditional 252 segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 253 segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 254 segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 255 // today we know z and w are in device space. We could use derivatives 256 segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); 257 segments->fFSCode.append ("\t} else {\n"); 258 segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 259 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 260 fsName, fsName); 261 segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 262 segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" 263 "\t}\n"); 264 if (kES2_GrGLBinding == fContextInfo.binding()) { 265 segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 266 } 267 break; 268 case GrDrawState::kHairQuad_EdgeType: 269 segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 270 segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 271 segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 272 "\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 273 fsName, fsName); 274 segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 275 segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 276 segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 277 if (kES2_GrGLBinding == fContextInfo.binding()) { 278 segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 279 } 280 break; 281 case GrDrawState::kCircle_EdgeType: 282 segments->fFSCode.append("\tfloat edgeAlpha;\n"); 283 segments->fFSCode.appendf("\tfloat d = distance(gl_FragCoord.xy, %s.xy);\n", fsName); 284 segments->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 285 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); 286 segments->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n"); 287 break; 288 default: 289 GrCrash("Unknown Edge Type!"); 290 break; 291 } 292 *coverageVar = "edgeAlpha"; 293 return true; 294 } else { 295 coverageVar->reset(); 296 return false; 297 } 298} 299 300void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { 301 switch (fDesc.fColorInput) { 302 case GrGLProgram::Desc::kAttribute_ColorInput: { 303 builder->fVSAttrs.push_back().set(kVec4f_GrSLType, 304 GrGLShaderVar::kAttribute_TypeModifier, 305 COL_ATTR_NAME); 306 const char *vsName, *fsName; 307 builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 308 builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); 309 *inColor = fsName; 310 } break; 311 case GrGLProgram::Desc::kUniform_ColorInput: { 312 const char* name; 313 fUniforms.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 314 kVec4f_GrSLType, "Color", &name); 315 *inColor = name; 316 break; 317 } 318 case GrGLProgram::Desc::kTransBlack_ColorInput: 319 GrAssert(!"needComputedColor should be false."); 320 break; 321 case GrGLProgram::Desc::kSolidWhite_ColorInput: 322 break; 323 default: 324 GrCrash("Unknown color type."); 325 break; 326 } 327} 328 329void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { 330 const char* covUniName; 331 fUniforms.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 332 kVec4f_GrSLType, "Coverage", &covUniName); 333 if (inOutCoverage->size()) { 334 builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", 335 covUniName, inOutCoverage->c_str()); 336 *inOutCoverage = "uniCoverage"; 337 } else { 338 *inOutCoverage = covUniName; 339 } 340} 341 342namespace { 343void gen_attribute_coverage(GrGLShaderBuilder* segments, 344 SkString* inOutCoverage) { 345 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 346 GrGLShaderVar::kAttribute_TypeModifier, 347 COV_ATTR_NAME); 348 const char *vsName, *fsName; 349 segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 350 segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName); 351 if (inOutCoverage->size()) { 352 segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n", 353 fsName, inOutCoverage->c_str()); 354 *inOutCoverage = "attrCoverage"; 355 } else { 356 *inOutCoverage = fsName; 357 } 358} 359} 360 361void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const { 362#if GR_GL_EXPERIMENTAL_GS 363 if (fDesc.fExperimentalGS) { 364 GrAssert(fContextInfo.glslGeneration() >= k150_GrGLSLGeneration); 365 segments->fGSHeader.append("layout(triangles) in;\n" 366 "layout(triangle_strip, max_vertices = 6) out;\n"); 367 segments->fGSCode.append("void main() {\n" 368 "\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 "}\n"); 384 } 385#endif 386} 387 388const char* GrGLProgram::adjustInColor(const SkString& inColor) const { 389 if (inColor.size()) { 390 return inColor.c_str(); 391 } else { 392 if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) { 393 return GrGLSLOnesVecf(4); 394 } else { 395 return GrGLSLZerosVecf(4); 396 } 397 } 398} 399 400namespace { 401// prints a shader using params similar to glShaderSource 402void print_shader(GrGLint stringCnt, 403 const GrGLchar** strings, 404 GrGLint* stringLengths) { 405 for (int i = 0; i < stringCnt; ++i) { 406 if (NULL == stringLengths || stringLengths[i] < 0) { 407 GrPrintf(strings[i]); 408 } else { 409 GrPrintf("%.*s", stringLengths[i], strings[i]); 410 } 411 } 412} 413 414// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource 415GrGLuint compile_shader(const GrGLContextInfo& gl, 416 GrGLenum type, 417 int stringCnt, 418 const char** strings, 419 int* stringLengths) { 420 SK_TRACE_EVENT1("GrGLProgram::CompileShader", 421 "stringCount", SkStringPrintf("%i", stringCnt).c_str()); 422 423 GrGLuint shader; 424 GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type)); 425 if (0 == shader) { 426 return 0; 427 } 428 429 const GrGLInterface* gli = gl.interface(); 430 GrGLint compiled = GR_GL_INIT_ZERO; 431 GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths)); 432 GR_GL_CALL(gli, CompileShader(shader)); 433 GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); 434 435 if (!compiled) { 436 GrGLint infoLen = GR_GL_INIT_ZERO; 437 GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); 438 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 439 if (infoLen > 0) { 440 // retrieve length even though we don't need it to workaround bug in chrome cmd buffer 441 // param validation. 442 GrGLsizei length = GR_GL_INIT_ZERO; 443 GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1, 444 &length, (char*)log.get())); 445 print_shader(stringCnt, strings, stringLengths); 446 GrPrintf("\n%s", log.get()); 447 } 448 GrAssert(!"Shader compilation failed!"); 449 GR_GL_CALL(gli, DeleteShader(shader)); 450 return 0; 451 } 452 return shader; 453} 454 455// helper version of above for when shader is already flattened into a single SkString 456GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString& shader) { 457 const GrGLchar* str = shader.c_str(); 458 int length = shader.size(); 459 return compile_shader(gl, type, 1, &str, &length); 460} 461 462} 463 464// compiles all the shaders from builder and stores the shader IDs 465bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { 466 467 SkString shader; 468 469 builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader); 470#if PRINT_SHADERS 471 GrPrintf(shader.c_str()); 472 GrPrintf("\n"); 473#endif 474 if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) { 475 return false; 476 } 477 478 if (builder.fUsesGS) { 479 builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); 480#if PRINT_SHADERS 481 GrPrintf(shader.c_str()); 482 GrPrintf("\n"); 483#endif 484 if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) { 485 return false; 486 } 487 } else { 488 fGShaderID = 0; 489 } 490 491 builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); 492#if PRINT_SHADERS 493 GrPrintf(shader.c_str()); 494 GrPrintf("\n"); 495#endif 496 if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) { 497 return false; 498 } 499 500 return true; 501} 502 503bool GrGLProgram::genProgram(const GrCustomStage** customStages) { 504 GrAssert(0 == fProgramID); 505 506 GrGLShaderBuilder builder(fContextInfo, fUniformManager); 507 const uint32_t& layout = fDesc.fVertexLayout; 508 509#if GR_GL_EXPERIMENTAL_GS 510 builder.fUsesGS = fDesc.fExperimentalGS; 511#endif 512 513 SkXfermode::Coeff colorCoeff, uniformCoeff; 514 bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled); 515 // The rest of transfer mode color filters have not been implemented 516 if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 517 GR_DEBUGCODE(bool success =) 518 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 519 (fDesc.fColorFilterXfermode), 520 &uniformCoeff, &colorCoeff); 521 GR_DEBUGASSERT(success); 522 } else { 523 colorCoeff = SkXfermode::kOne_Coeff; 524 uniformCoeff = SkXfermode::kZero_Coeff; 525 } 526 527 // no need to do the color filter / matrix at all if coverage is 0. The 528 // output color is scaled by the coverage. All the dual source outputs are 529 // scaled by the coverage as well. 530 if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) { 531 colorCoeff = SkXfermode::kZero_Coeff; 532 uniformCoeff = SkXfermode::kZero_Coeff; 533 applyColorMatrix = false; 534 } 535 536 // If we know the final color is going to be all zeros then we can 537 // simplify the color filter coeffecients. needComputedColor will then 538 // come out false below. 539 if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) { 540 colorCoeff = SkXfermode::kZero_Coeff; 541 if (SkXfermode::kDC_Coeff == uniformCoeff || 542 SkXfermode::kDA_Coeff == uniformCoeff) { 543 uniformCoeff = SkXfermode::kZero_Coeff; 544 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 545 SkXfermode::kIDA_Coeff == uniformCoeff) { 546 uniformCoeff = SkXfermode::kOne_Coeff; 547 } 548 } 549 550 bool needColorFilterUniform; 551 bool needComputedColor; 552 needBlendInputs(uniformCoeff, colorCoeff, 553 &needColorFilterUniform, &needComputedColor); 554 555 // the dual source output has no canonical var name, have to 556 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 557 bool dualSourceOutputWritten = false; 558 builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(), 559 fContextInfo.glslGeneration())); 560 561 GrGLShaderVar colorOutput; 562 bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(), 563 declared_color_output_name(), 564 &colorOutput); 565 if (isColorDeclared) { 566 builder.fFSOutputs.push_back(colorOutput); 567 } 568 569 const char* viewMName; 570 fUniforms.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, 571 kMat33f_GrSLType, "ViewM", &viewMName); 572 573 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 574 GrGLShaderVar::kAttribute_TypeModifier, 575 POS_ATTR_NAME); 576 577 builder.fVSCode.appendf("void main() {\n" 578 "\tvec3 pos3 = %s * vec3("POS_ATTR_NAME", 1);\n" 579 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 580 viewMName); 581 582 // incoming color to current stage being processed. 583 SkString inColor; 584 585 if (needComputedColor) { 586 this->genInputColor(&builder, &inColor); 587 } 588 589 // we output point size in the GS if present 590 if (fDesc.fEmitsPointSize && !builder.fUsesGS){ 591 builder.fVSCode.append("\tgl_PointSize = 1.0;\n"); 592 } 593 594 builder.fFSCode.append("void main() {\n"); 595 596 // add texture coordinates that are used to the list of vertex attr decls 597 SkString texCoordAttrs[GrDrawState::kMaxTexCoords]; 598 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 599 if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) { 600 tex_attr_name(t, texCoordAttrs + t); 601 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 602 GrGLShaderVar::kAttribute_TypeModifier, 603 texCoordAttrs[t].c_str()); 604 } 605 } 606 607 /////////////////////////////////////////////////////////////////////////// 608 // compute the final color 609 610 // if we have color stages string them together, feeding the output color 611 // of each to the next and generating code for each stage. 612 if (needComputedColor) { 613 SkString outColor; 614 for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { 615 if (fDesc.fStages[s].isEnabled()) { 616 // create var to hold stage result 617 outColor = "color"; 618 outColor.appendS32(s); 619 builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); 620 621 const char* inCoords; 622 // figure out what our input coords are 623 int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); 624 if (tcIdx < 0) { 625 inCoords = POS_ATTR_NAME; 626 } else { 627 // must have input tex coordinates if stage is enabled. 628 GrAssert(texCoordAttrs[tcIdx].size()); 629 inCoords = texCoordAttrs[tcIdx].c_str(); 630 } 631 632 builder.setCurrentStage(s); 633 fProgramStage[s] = GenStageCode(customStages[s], 634 fDesc.fStages[s], 635 &fUniforms.fStages[s], 636 inColor.size() ? inColor.c_str() : NULL, 637 outColor.c_str(), 638 inCoords, 639 &builder); 640 builder.setNonStage(); 641 inColor = outColor; 642 } 643 } 644 } 645 646 // if have all ones or zeros for the "dst" input to the color filter then we 647 // may be able to make additional optimizations. 648 if (needColorFilterUniform && needComputedColor && !inColor.size()) { 649 GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput); 650 bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || 651 SkXfermode::kIDA_Coeff == uniformCoeff; 652 if (uniformCoeffIsZero) { 653 uniformCoeff = SkXfermode::kZero_Coeff; 654 bool bogus; 655 needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, 656 &needColorFilterUniform, &bogus); 657 } 658 } 659 const char* colorFilterColorUniName = NULL; 660 if (needColorFilterUniform) { 661 fUniforms.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, 662 kVec4f_GrSLType, "FilterColor", 663 &colorFilterColorUniName); 664 } 665 bool wroteFragColorZero = false; 666 if (SkXfermode::kZero_Coeff == uniformCoeff && 667 SkXfermode::kZero_Coeff == colorCoeff && 668 !applyColorMatrix) { 669 builder.fFSCode.appendf("\t%s = %s;\n", 670 colorOutput.getName().c_str(), 671 GrGLSLZerosVecf(4)); 672 wroteFragColorZero = true; 673 } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { 674 builder.fFSCode.append("\tvec4 filteredColor;\n"); 675 const char* color = adjustInColor(inColor); 676 addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, 677 colorCoeff, colorFilterColorUniName, color); 678 inColor = "filteredColor"; 679 } 680 if (applyColorMatrix) { 681 const char* colMatrixName; 682 const char* colMatrixVecName; 683 fUniforms.fColorMatrixUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, 684 kMat44f_GrSLType, "ColorMatrix", 685 &colMatrixName); 686 fUniforms.fColorMatrixVecUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, 687 kVec4f_GrSLType, "ColorMatrixVec", 688 &colMatrixVecName); 689 const char* color = adjustInColor(inColor); 690 builder.fFSCode.appendf("\tvec4 matrixedColor = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n", 691 colMatrixName, color, color, color, colMatrixVecName); 692 builder.fFSCode.append("\tmatrixedColor.rgb *= matrixedColor.a;\n"); 693 694 inColor = "matrixedColor"; 695 } 696 697 /////////////////////////////////////////////////////////////////////////// 698 // compute the partial coverage (coverage stages and edge aa) 699 700 SkString inCoverage; 701 bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput; 702 // we don't need to compute coverage at all if we know the final shader 703 // output will be zero and we don't have a dual src blend output. 704 if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 705 706 if (!coverageIsZero) { 707 bool inCoverageIsScalar = this->genEdgeCoverage(&inCoverage, &builder); 708 709 switch (fDesc.fCoverageInput) { 710 case Desc::kSolidWhite_ColorInput: 711 // empty string implies solid white 712 break; 713 case Desc::kAttribute_ColorInput: 714 gen_attribute_coverage(&builder, &inCoverage); 715 inCoverageIsScalar = false; 716 break; 717 case Desc::kUniform_ColorInput: 718 this->genUniformCoverage(&builder, &inCoverage); 719 inCoverageIsScalar = false; 720 break; 721 default: 722 GrCrash("Unexpected input coverage."); 723 } 724 725 SkString outCoverage; 726 const int& startStage = fDesc.fFirstCoverageStage; 727 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 728 if (fDesc.fStages[s].isEnabled()) { 729 // create var to hold stage output 730 outCoverage = "coverage"; 731 outCoverage.appendS32(s); 732 builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str()); 733 734 const char* inCoords; 735 // figure out what our input coords are 736 int tcIdx = 737 GrDrawTarget::VertexTexCoordsForStage(s, layout); 738 if (tcIdx < 0) { 739 inCoords = POS_ATTR_NAME; 740 } else { 741 // must have input tex coordinates if stage is 742 // enabled. 743 GrAssert(texCoordAttrs[tcIdx].size()); 744 inCoords = texCoordAttrs[tcIdx].c_str(); 745 } 746 747 // stages don't know how to deal with a scalar input. (Maybe they should. We 748 // could pass a GrGLShaderVar) 749 if (inCoverageIsScalar) { 750 builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n", 751 inCoverage.c_str(), inCoverage.c_str()); 752 inCoverage.append("4"); 753 } 754 builder.setCurrentStage(s); 755 fProgramStage[s] = GenStageCode(customStages[s], 756 fDesc.fStages[s], 757 &fUniforms.fStages[s], 758 inCoverage.size() ? inCoverage.c_str() : NULL, 759 outCoverage.c_str(), 760 inCoords, 761 &builder); 762 builder.setNonStage(); 763 inCoverage = outCoverage; 764 } 765 } 766 } 767 768 if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 769 builder.fFSOutputs.push_back().set(kVec4f_GrSLType, 770 GrGLShaderVar::kOut_TypeModifier, 771 dual_source_output_name()); 772 bool outputIsZero = coverageIsZero; 773 SkString coeff; 774 if (!outputIsZero && 775 Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { 776 if (!inColor.size()) { 777 outputIsZero = true; 778 } else { 779 if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { 780 coeff.printf("(1 - %s.a)", inColor.c_str()); 781 } else { 782 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 783 } 784 } 785 } 786 if (outputIsZero) { 787 builder.fFSCode.appendf("\t%s = %s;\n", 788 dual_source_output_name(), 789 GrGLSLZerosVecf(4)); 790 } else { 791 builder.fFSCode.appendf("\t%s =", dual_source_output_name()); 792 GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str()); 793 builder.fFSCode.append(";\n"); 794 } 795 dualSourceOutputWritten = true; 796 } 797 } 798 799 /////////////////////////////////////////////////////////////////////////// 800 // combine color and coverage as frag color 801 802 if (!wroteFragColorZero) { 803 if (coverageIsZero) { 804 builder.fFSCode.appendf("\t%s = %s;\n", 805 colorOutput.getName().c_str(), 806 GrGLSLZerosVecf(4)); 807 } else { 808 builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str()); 809 GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str()); 810 builder.fFSCode.append(";\n"); 811 } 812 } 813 814 builder.fVSCode.append("}\n"); 815 builder.fFSCode.append("}\n"); 816 817 /////////////////////////////////////////////////////////////////////////// 818 // insert GS 819#if GR_DEBUG 820 this->genGeometryShader(&builder); 821#endif 822 823 /////////////////////////////////////////////////////////////////////////// 824 // compile and setup attribs and unis 825 826 if (!this->compileShaders(builder)) { 827 return false; 828 } 829 830 if (!this->bindOutputsAttribsAndLinkProgram(texCoordAttrs, 831 isColorDeclared, 832 dualSourceOutputWritten)) { 833 return false; 834 } 835 836 builder.finished(fProgramID); 837 this->initSamplerUniforms(); 838 839 return true; 840} 841 842bool GrGLProgram::bindOutputsAttribsAndLinkProgram(SkString texCoordAttrNames[], 843 bool bindColorOut, 844 bool bindDualSrcOut) { 845 GL_CALL_RET(fProgramID, CreateProgram()); 846 if (!fProgramID) { 847 return false; 848 } 849 850 GL_CALL(AttachShader(fProgramID, fVShaderID)); 851 if (fGShaderID) { 852 GL_CALL(AttachShader(fProgramID, fGShaderID)); 853 } 854 GL_CALL(AttachShader(fProgramID, fFShaderID)); 855 856 if (bindColorOut) { 857 GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name())); 858 } 859 if (bindDualSrcOut) { 860 GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name())); 861 } 862 863 // Bind the attrib locations to same values for all shaders 864 GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME)); 865 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 866 if (texCoordAttrNames[t].size()) { 867 GL_CALL(BindAttribLocation(fProgramID, 868 TexCoordAttributeIdx(t), 869 texCoordAttrNames[t].c_str())); 870 } 871 } 872 873 GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME)); 874 GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME)); 875 GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); 876 877 GL_CALL(LinkProgram(fProgramID)); 878 879 GrGLint linked = GR_GL_INIT_ZERO; 880 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 881 if (!linked) { 882 GrGLint infoLen = GR_GL_INIT_ZERO; 883 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 884 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 885 if (infoLen > 0) { 886 // retrieve length even though we don't need it to workaround 887 // bug in chrome cmd buffer param validation. 888 GrGLsizei length = GR_GL_INIT_ZERO; 889 GL_CALL(GetProgramInfoLog(fProgramID, 890 infoLen+1, 891 &length, 892 (char*)log.get())); 893 GrPrintf((char*)log.get()); 894 } 895 GrAssert(!"Error linking program"); 896 GL_CALL(DeleteProgram(fProgramID)); 897 fProgramID = 0; 898 return false; 899 } 900 return true; 901} 902 903void GrGLProgram::initSamplerUniforms() { 904 GL_CALL(UseProgram(fProgramID)); 905 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 906 int count = fUniforms.fStages[s].fSamplerUniforms.count(); 907 // FIXME: We're still always reserving one texture per stage. After GrTextureParams are 908 // expressed by the custom stage rather than the GrSamplerState we can move texture binding 909 // into GrGLProgram and it should be easier to fix this. 910 GrAssert(count <= 1); 911 for (int t = 0; t < count; ++t) { 912 UniformHandle uh = fUniforms.fStages[s].fSamplerUniforms[t]; 913 if (GrGLUniformManager::kInvalidUniformHandle != uh) { 914 fUniformManager.setSampler(uh, s); 915 } 916 } 917 } 918} 919 920/////////////////////////////////////////////////////////////////////////////// 921// Stage code generation 922 923// TODO: Move this function to GrGLShaderBuilder 924GrGLProgramStage* GrGLProgram::GenStageCode(const GrCustomStage* stage, 925 const StageDesc& desc, 926 StageUniforms* uniforms, 927 const char* fsInColor, // NULL means no incoming color 928 const char* fsOutColor, 929 const char* vsInCoord, 930 GrGLShaderBuilder* builder) { 931 932 GrGLProgramStage* glStage = stage->getFactory().createGLInstance(*stage); 933 934 GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags); 935 936 /// Vertex Shader Stuff 937 938 // decide whether we need a matrix to transform texture coords and whether the varying needs a 939 // perspective coord. 940 const char* matName = NULL; 941 GrSLType texCoordVaryingType; 942 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) { 943 texCoordVaryingType = kVec2f_GrSLType; 944 } else { 945 uniforms->fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType, 946 kMat33f_GrSLType, "TexM", &matName); 947 builder->getUniformVariable(uniforms->fTextureMatrixUni); 948 949 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { 950 texCoordVaryingType = kVec2f_GrSLType; 951 } else { 952 texCoordVaryingType = kVec3f_GrSLType; 953 } 954 } 955 const char *varyingVSName, *varyingFSName; 956 builder->addVarying(texCoordVaryingType, 957 "Stage", 958 &varyingVSName, 959 &varyingFSName); 960 builder->setupTextureAccess(varyingFSName, texCoordVaryingType); 961 962 // Must setup variables after calling setupTextureAccess 963 glStage->setupVariables(builder); 964 965 int numTextures = stage->numTextures(); 966 SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; 967 // temporary until we force custom stages to provide their own texture access 968 SkSTArray<8, bool, true> deleteTextureAccess; 969 970 textureSamplers.push_back_n(numTextures); 971 deleteTextureAccess.push_back_n(numTextures); 972 973 for (int i = 0; i < numTextures; ++i) { 974 // Right now we don't require a texture access for every texture. This will change soon. 975 const GrTextureAccess* access = stage->textureAccess(i); 976 GrAssert(NULL != stage->texture(i)); 977 if (NULL == access) { 978 SkString swizzle; 979 if (desc.fInConfigFlags & StageDesc::kSmearAlpha_InConfigFlag) { 980 swizzle.printf("aaaa"); 981 } else { 982 swizzle.printf("rgba"); 983 } 984 access = SkNEW_ARGS(GrTextureAccess, (stage->texture(i), swizzle)); 985 deleteTextureAccess[i] = true; 986 } else { 987 GrAssert(access->getTexture() == stage->texture(i)); 988 deleteTextureAccess[i] = false; 989 } 990 textureSamplers[i].init(builder, access); 991 uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform); 992 } 993 994 if (!matName) { 995 GrAssert(kVec2f_GrSLType == texCoordVaryingType); 996 builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord); 997 } else { 998 // varying = texMatrix * texCoord 999 builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n", 1000 varyingVSName, matName, vsInCoord, 1001 vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType))); 1002 } 1003 1004 builder->fVSCode.appendf("\t{ // %s\n", glStage->name()); 1005 glStage->emitVS(builder, varyingVSName); 1006 builder->fVSCode.appendf("\t}\n"); 1007 1008 // Enclose custom code in a block to avoid namespace conflicts 1009 builder->fFSCode.appendf("\t{ // %s \n", glStage->name()); 1010 glStage->emitFS(builder, fsOutColor, fsInColor, textureSamplers); 1011 builder->fFSCode.appendf("\t}\n"); 1012 1013 for (int i = 0; i < numTextures; ++i) { 1014 if (deleteTextureAccess[i]) { 1015 SkDELETE(textureSamplers[i].textureAccess()); 1016 } 1017 } 1018 return glStage; 1019} 1020