GrGLProgram.cpp revision a469c28c3c16214733a25201a286970f57b3d944
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 "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 GrEffect** 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 GrEffect** 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 fRTHeight = -1; 81 82 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 83 fProgramStage[s] = NULL; 84 fTextureMatrices[s] = GrMatrix::InvalidMatrix(); 85 // this is arbitrary, just initialize to something 86 fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation; 87 } 88 89 this->genProgram(customStages); 90} 91 92GrGLProgram::~GrGLProgram() { 93 if (fVShaderID) { 94 GL_CALL(DeleteShader(fVShaderID)); 95 } 96 if (fGShaderID) { 97 GL_CALL(DeleteShader(fGShaderID)); 98 } 99 if (fFShaderID) { 100 GL_CALL(DeleteShader(fFShaderID)); 101 } 102 if (fProgramID) { 103 GL_CALL(DeleteProgram(fProgramID)); 104 } 105 106 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 107 delete fProgramStage[i]; 108 } 109} 110 111void GrGLProgram::abandon() { 112 fVShaderID = 0; 113 fGShaderID = 0; 114 fFShaderID = 0; 115 fProgramID = 0; 116} 117 118void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 119 GrBlendCoeff* dstCoeff) const { 120 switch (fDesc.fDualSrcOutput) { 121 case Desc::kNone_DualSrcOutput: 122 break; 123 // the prog will write a coverage value to the secondary 124 // output and the dst is blended by one minus that value. 125 case Desc::kCoverage_DualSrcOutput: 126 case Desc::kCoverageISA_DualSrcOutput: 127 case Desc::kCoverageISC_DualSrcOutput: 128 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; 129 break; 130 default: 131 GrCrash("Unexpected dual source blend output"); 132 break; 133 } 134} 135 136// given two blend coeffecients determine whether the src 137// and/or dst computation can be omitted. 138static inline void needBlendInputs(SkXfermode::Coeff srcCoeff, 139 SkXfermode::Coeff dstCoeff, 140 bool* needSrcValue, 141 bool* needDstValue) { 142 if (SkXfermode::kZero_Coeff == srcCoeff) { 143 switch (dstCoeff) { 144 // these all read the src 145 case SkXfermode::kSC_Coeff: 146 case SkXfermode::kISC_Coeff: 147 case SkXfermode::kSA_Coeff: 148 case SkXfermode::kISA_Coeff: 149 *needSrcValue = true; 150 break; 151 default: 152 *needSrcValue = false; 153 break; 154 } 155 } else { 156 *needSrcValue = true; 157 } 158 if (SkXfermode::kZero_Coeff == dstCoeff) { 159 switch (srcCoeff) { 160 // these all read the dst 161 case SkXfermode::kDC_Coeff: 162 case SkXfermode::kIDC_Coeff: 163 case SkXfermode::kDA_Coeff: 164 case SkXfermode::kIDA_Coeff: 165 *needDstValue = true; 166 break; 167 default: 168 *needDstValue = false; 169 break; 170 } 171 } else { 172 *needDstValue = true; 173 } 174} 175 176/** 177 * Create a blend_coeff * value string to be used in shader code. Sets empty 178 * string if result is trivially zero. 179 */ 180static void blendTermString(SkString* str, SkXfermode::Coeff coeff, 181 const char* src, const char* dst, 182 const char* value) { 183 switch (coeff) { 184 case SkXfermode::kZero_Coeff: /** 0 */ 185 *str = ""; 186 break; 187 case SkXfermode::kOne_Coeff: /** 1 */ 188 *str = value; 189 break; 190 case SkXfermode::kSC_Coeff: 191 str->printf("(%s * %s)", src, value); 192 break; 193 case SkXfermode::kISC_Coeff: 194 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value); 195 break; 196 case SkXfermode::kDC_Coeff: 197 str->printf("(%s * %s)", dst, value); 198 break; 199 case SkXfermode::kIDC_Coeff: 200 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value); 201 break; 202 case SkXfermode::kSA_Coeff: /** src alpha */ 203 str->printf("(%s.a * %s)", src, value); 204 break; 205 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 206 str->printf("((1.0 - %s.a) * %s)", src, value); 207 break; 208 case SkXfermode::kDA_Coeff: /** dst alpha */ 209 str->printf("(%s.a * %s)", dst, value); 210 break; 211 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 212 str->printf("((1.0 - %s.a) * %s)", dst, value); 213 break; 214 default: 215 GrCrash("Unexpected xfer coeff."); 216 break; 217 } 218} 219/** 220 * Adds a line to the fragment shader code which modifies the color by 221 * the specified color filter. 222 */ 223static void addColorFilter(SkString* fsCode, const char * outputVar, 224 SkXfermode::Coeff uniformCoeff, 225 SkXfermode::Coeff colorCoeff, 226 const char* filterColor, 227 const char* inColor) { 228 SkString colorStr, constStr; 229 blendTermString(&colorStr, colorCoeff, filterColor, inColor, inColor); 230 blendTermString(&constStr, uniformCoeff, filterColor, inColor, filterColor); 231 232 fsCode->appendf("\t%s = ", outputVar); 233 GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str()); 234 fsCode->append(";\n"); 235} 236 237bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, 238 GrGLShaderBuilder* builder) const { 239 if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) { 240 const char *vsName, *fsName; 241 builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); 242 builder->fVSAttrs.push_back().set(kVec4f_GrSLType, 243 GrGLShaderVar::kAttribute_TypeModifier, 244 EDGE_ATTR_NAME); 245 builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); 246 switch (fDesc.fVertexEdgeType) { 247 case GrDrawState::kHairLine_EdgeType: 248 builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName); 249 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 250 break; 251 case GrDrawState::kQuad_EdgeType: 252 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 253 // keep the derivative instructions outside the conditional 254 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 255 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 256 builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 257 // today we know z and w are in device space. We could use derivatives 258 builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); 259 builder->fFSCode.append ("\t} else {\n"); 260 builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 261 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 262 fsName, fsName); 263 builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 264 builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" 265 "\t}\n"); 266 if (kES2_GrGLBinding == fContextInfo.binding()) { 267 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 268 } 269 break; 270 case GrDrawState::kHairQuad_EdgeType: 271 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 272 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 273 builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 274 "\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 275 fsName, fsName); 276 builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 277 builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 278 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 279 if (kES2_GrGLBinding == fContextInfo.binding()) { 280 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 281 } 282 break; 283 case GrDrawState::kCircle_EdgeType: 284 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 285 builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName); 286 builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 287 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); 288 builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n"); 289 break; 290 default: 291 GrCrash("Unknown Edge Type!"); 292 break; 293 } 294 *coverageVar = "edgeAlpha"; 295 return true; 296 } else { 297 coverageVar->reset(); 298 return false; 299 } 300} 301 302void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { 303 switch (fDesc.fColorInput) { 304 case GrGLProgram::Desc::kAttribute_ColorInput: { 305 builder->fVSAttrs.push_back().set(kVec4f_GrSLType, 306 GrGLShaderVar::kAttribute_TypeModifier, 307 COL_ATTR_NAME); 308 const char *vsName, *fsName; 309 builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 310 builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); 311 *inColor = fsName; 312 } break; 313 case GrGLProgram::Desc::kUniform_ColorInput: { 314 const char* name; 315 fUniforms.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 316 kVec4f_GrSLType, "Color", &name); 317 *inColor = name; 318 break; 319 } 320 case GrGLProgram::Desc::kTransBlack_ColorInput: 321 GrAssert(!"needComputedColor should be false."); 322 break; 323 case GrGLProgram::Desc::kSolidWhite_ColorInput: 324 break; 325 default: 326 GrCrash("Unknown color type."); 327 break; 328 } 329} 330 331void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { 332 const char* covUniName; 333 fUniforms.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 334 kVec4f_GrSLType, "Coverage", &covUniName); 335 if (inOutCoverage->size()) { 336 builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", 337 covUniName, inOutCoverage->c_str()); 338 *inOutCoverage = "uniCoverage"; 339 } else { 340 *inOutCoverage = covUniName; 341 } 342} 343 344namespace { 345void gen_attribute_coverage(GrGLShaderBuilder* segments, 346 SkString* inOutCoverage) { 347 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 348 GrGLShaderVar::kAttribute_TypeModifier, 349 COV_ATTR_NAME); 350 const char *vsName, *fsName; 351 segments->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 352 segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName); 353 if (inOutCoverage->size()) { 354 segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n", 355 fsName, inOutCoverage->c_str()); 356 *inOutCoverage = "attrCoverage"; 357 } else { 358 *inOutCoverage = fsName; 359 } 360} 361} 362 363void GrGLProgram::genGeometryShader(GrGLShaderBuilder* segments) const { 364#if GR_GL_EXPERIMENTAL_GS 365 if (fDesc.fExperimentalGS) { 366 GrAssert(fContextInfo.glslGeneration() >= k150_GrGLSLGeneration); 367 segments->fGSHeader.append("layout(triangles) in;\n" 368 "layout(triangle_strip, max_vertices = 6) out;\n"); 369 segments->fGSCode.append("\tfor (int i = 0; i < 3; ++i) {\n" 370 "\t\tgl_Position = gl_in[i].gl_Position;\n"); 371 if (fDesc.fEmitsPointSize) { 372 segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n"); 373 } 374 GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count()); 375 int count = segments->fGSInputs.count(); 376 for (int i = 0; i < count; ++i) { 377 segments->fGSCode.appendf("\t\t%s = %s[i];\n", 378 segments->fGSOutputs[i].getName().c_str(), 379 segments->fGSInputs[i].getName().c_str()); 380 } 381 segments->fGSCode.append("\t\tEmitVertex();\n" 382 "\t}\n" 383 "\tEndPrimitive();\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 GrEffect** 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 // The rest of transfer mode color filters have not been implemented 515 if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 516 GR_DEBUGCODE(bool success =) 517 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 518 (fDesc.fColorFilterXfermode), 519 &uniformCoeff, &colorCoeff); 520 GR_DEBUGASSERT(success); 521 } else { 522 colorCoeff = SkXfermode::kOne_Coeff; 523 uniformCoeff = SkXfermode::kZero_Coeff; 524 } 525 526 // no need to do the color filter if coverage is 0. The output color is scaled by the coverage. 527 // All the dual source outputs are scaled by the coverage as well. 528 if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) { 529 colorCoeff = SkXfermode::kZero_Coeff; 530 uniformCoeff = SkXfermode::kZero_Coeff; 531 } 532 533 // If we know the final color is going to be all zeros then we can 534 // simplify the color filter coefficients. needComputedColor will then 535 // come out false below. 536 if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) { 537 colorCoeff = SkXfermode::kZero_Coeff; 538 if (SkXfermode::kDC_Coeff == uniformCoeff || 539 SkXfermode::kDA_Coeff == uniformCoeff) { 540 uniformCoeff = SkXfermode::kZero_Coeff; 541 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 542 SkXfermode::kIDA_Coeff == uniformCoeff) { 543 uniformCoeff = SkXfermode::kOne_Coeff; 544 } 545 } 546 547 bool needColorFilterUniform; 548 bool needComputedColor; 549 needBlendInputs(uniformCoeff, colorCoeff, 550 &needColorFilterUniform, &needComputedColor); 551 552 // the dual source output has no canonical var name, have to 553 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 554 bool dualSourceOutputWritten = false; 555 builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(), 556 fContextInfo.glslGeneration())); 557 558 GrGLShaderVar colorOutput; 559 bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(), 560 declared_color_output_name(), 561 &colorOutput); 562 if (isColorDeclared) { 563 builder.fFSOutputs.push_back(colorOutput); 564 } 565 566 const char* viewMName; 567 fUniforms.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, 568 kMat33f_GrSLType, "ViewM", &viewMName); 569 570 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 571 GrGLShaderVar::kAttribute_TypeModifier, 572 POS_ATTR_NAME); 573 574 builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3("POS_ATTR_NAME", 1);\n" 575 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 576 viewMName); 577 578 // incoming color to current stage being processed. 579 SkString inColor; 580 581 if (needComputedColor) { 582 this->genInputColor(&builder, &inColor); 583 } 584 585 // we output point size in the GS if present 586 if (fDesc.fEmitsPointSize && !builder.fUsesGS){ 587 builder.fVSCode.append("\tgl_PointSize = 1.0;\n"); 588 } 589 590 // add texture coordinates that are used to the list of vertex attr decls 591 SkString texCoordAttrs[GrDrawState::kMaxTexCoords]; 592 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 593 if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) { 594 tex_attr_name(t, texCoordAttrs + t); 595 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 596 GrGLShaderVar::kAttribute_TypeModifier, 597 texCoordAttrs[t].c_str()); 598 } 599 } 600 601 /////////////////////////////////////////////////////////////////////////// 602 // compute the final color 603 604 // if we have color stages string them together, feeding the output color 605 // of each to the next and generating code for each stage. 606 if (needComputedColor) { 607 SkString outColor; 608 for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { 609 if (fDesc.fStages[s].isEnabled()) { 610 // create var to hold stage result 611 outColor = "color"; 612 outColor.appendS32(s); 613 builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); 614 615 const char* inCoords; 616 // figure out what our input coords are 617 int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); 618 if (tcIdx < 0) { 619 inCoords = POS_ATTR_NAME; 620 } else { 621 // must have input tex coordinates if stage is enabled. 622 GrAssert(texCoordAttrs[tcIdx].size()); 623 inCoords = texCoordAttrs[tcIdx].c_str(); 624 } 625 626 builder.setCurrentStage(s); 627 fProgramStage[s] = GenStageCode(customStages[s], 628 fDesc.fStages[s], 629 &fUniforms.fStages[s], 630 inColor.size() ? inColor.c_str() : NULL, 631 outColor.c_str(), 632 inCoords, 633 &builder); 634 builder.setNonStage(); 635 inColor = outColor; 636 } 637 } 638 } 639 640 // if have all ones or zeros for the "dst" input to the color filter then we 641 // may be able to make additional optimizations. 642 if (needColorFilterUniform && needComputedColor && !inColor.size()) { 643 GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput); 644 bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || 645 SkXfermode::kIDA_Coeff == uniformCoeff; 646 if (uniformCoeffIsZero) { 647 uniformCoeff = SkXfermode::kZero_Coeff; 648 bool bogus; 649 needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, 650 &needColorFilterUniform, &bogus); 651 } 652 } 653 const char* colorFilterColorUniName = NULL; 654 if (needColorFilterUniform) { 655 fUniforms.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, 656 kVec4f_GrSLType, "FilterColor", 657 &colorFilterColorUniName); 658 } 659 bool wroteFragColorZero = false; 660 if (SkXfermode::kZero_Coeff == uniformCoeff && 661 SkXfermode::kZero_Coeff == colorCoeff) { 662 builder.fFSCode.appendf("\t%s = %s;\n", 663 colorOutput.getName().c_str(), 664 GrGLSLZerosVecf(4)); 665 wroteFragColorZero = true; 666 } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { 667 builder.fFSCode.append("\tvec4 filteredColor;\n"); 668 const char* color = adjustInColor(inColor); 669 addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, 670 colorCoeff, colorFilterColorUniName, color); 671 inColor = "filteredColor"; 672 } 673 674 /////////////////////////////////////////////////////////////////////////// 675 // compute the partial coverage (coverage stages and edge aa) 676 677 SkString inCoverage; 678 bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput; 679 // we don't need to compute coverage at all if we know the final shader 680 // output will be zero and we don't have a dual src blend output. 681 if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 682 683 if (!coverageIsZero) { 684 bool inCoverageIsScalar = this->genEdgeCoverage(&inCoverage, &builder); 685 686 switch (fDesc.fCoverageInput) { 687 case Desc::kSolidWhite_ColorInput: 688 // empty string implies solid white 689 break; 690 case Desc::kAttribute_ColorInput: 691 gen_attribute_coverage(&builder, &inCoverage); 692 inCoverageIsScalar = false; 693 break; 694 case Desc::kUniform_ColorInput: 695 this->genUniformCoverage(&builder, &inCoverage); 696 inCoverageIsScalar = false; 697 break; 698 default: 699 GrCrash("Unexpected input coverage."); 700 } 701 702 SkString outCoverage; 703 const int& startStage = fDesc.fFirstCoverageStage; 704 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 705 if (fDesc.fStages[s].isEnabled()) { 706 // create var to hold stage output 707 outCoverage = "coverage"; 708 outCoverage.appendS32(s); 709 builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str()); 710 711 const char* inCoords; 712 // figure out what our input coords are 713 int tcIdx = 714 GrDrawTarget::VertexTexCoordsForStage(s, layout); 715 if (tcIdx < 0) { 716 inCoords = POS_ATTR_NAME; 717 } else { 718 // must have input tex coordinates if stage is 719 // enabled. 720 GrAssert(texCoordAttrs[tcIdx].size()); 721 inCoords = texCoordAttrs[tcIdx].c_str(); 722 } 723 724 // stages don't know how to deal with a scalar input. (Maybe they should. We 725 // could pass a GrGLShaderVar) 726 if (inCoverageIsScalar) { 727 builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n", 728 inCoverage.c_str(), inCoverage.c_str()); 729 inCoverage.append("4"); 730 } 731 builder.setCurrentStage(s); 732 fProgramStage[s] = GenStageCode(customStages[s], 733 fDesc.fStages[s], 734 &fUniforms.fStages[s], 735 inCoverage.size() ? inCoverage.c_str() : NULL, 736 outCoverage.c_str(), 737 inCoords, 738 &builder); 739 builder.setNonStage(); 740 inCoverage = outCoverage; 741 } 742 } 743 } 744 745 if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 746 builder.fFSOutputs.push_back().set(kVec4f_GrSLType, 747 GrGLShaderVar::kOut_TypeModifier, 748 dual_source_output_name()); 749 bool outputIsZero = coverageIsZero; 750 SkString coeff; 751 if (!outputIsZero && 752 Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { 753 if (!inColor.size()) { 754 outputIsZero = true; 755 } else { 756 if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { 757 coeff.printf("(1 - %s.a)", inColor.c_str()); 758 } else { 759 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 760 } 761 } 762 } 763 if (outputIsZero) { 764 builder.fFSCode.appendf("\t%s = %s;\n", 765 dual_source_output_name(), 766 GrGLSLZerosVecf(4)); 767 } else { 768 builder.fFSCode.appendf("\t%s =", dual_source_output_name()); 769 GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str()); 770 builder.fFSCode.append(";\n"); 771 } 772 dualSourceOutputWritten = true; 773 } 774 } 775 776 /////////////////////////////////////////////////////////////////////////// 777 // combine color and coverage as frag color 778 779 if (!wroteFragColorZero) { 780 if (coverageIsZero) { 781 builder.fFSCode.appendf("\t%s = %s;\n", 782 colorOutput.getName().c_str(), 783 GrGLSLZerosVecf(4)); 784 } else { 785 builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str()); 786 GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str()); 787 builder.fFSCode.append(";\n"); 788 } 789 } 790 791 /////////////////////////////////////////////////////////////////////////// 792 // insert GS 793#if GR_DEBUG 794 this->genGeometryShader(&builder); 795#endif 796 797 /////////////////////////////////////////////////////////////////////////// 798 // compile and setup attribs and unis 799 800 if (!this->compileShaders(builder)) { 801 return false; 802 } 803 804 if (!this->bindOutputsAttribsAndLinkProgram(texCoordAttrs, 805 isColorDeclared, 806 dualSourceOutputWritten)) { 807 return false; 808 } 809 810 builder.finished(fProgramID); 811 this->initSamplerUniforms(); 812 fUniforms.fRTHeight = builder.getRTHeightUniform(); 813 814 return true; 815} 816 817bool GrGLProgram::bindOutputsAttribsAndLinkProgram(SkString texCoordAttrNames[], 818 bool bindColorOut, 819 bool bindDualSrcOut) { 820 GL_CALL_RET(fProgramID, CreateProgram()); 821 if (!fProgramID) { 822 return false; 823 } 824 825 GL_CALL(AttachShader(fProgramID, fVShaderID)); 826 if (fGShaderID) { 827 GL_CALL(AttachShader(fProgramID, fGShaderID)); 828 } 829 GL_CALL(AttachShader(fProgramID, fFShaderID)); 830 831 if (bindColorOut) { 832 GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name())); 833 } 834 if (bindDualSrcOut) { 835 GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name())); 836 } 837 838 // Bind the attrib locations to same values for all shaders 839 GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME)); 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 custom stage rather than the GrSamplerState 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 899GrGLProgramStage* GrGLProgram::GenStageCode(const GrEffect* 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 GrGLProgramStage* glStage = stage->getFactory().createGLInstance(*stage); 908 909 /// Vertex Shader Stuff 910 911 // decide whether we need a matrix to transform texture coords and whether the varying needs a 912 // perspective coord. 913 const char* matName = NULL; 914 GrSLType texCoordVaryingType; 915 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) { 916 texCoordVaryingType = kVec2f_GrSLType; 917 } else { 918 uniforms->fTextureMatrixUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType, 919 kMat33f_GrSLType, "TexM", &matName); 920 builder->getUniformVariable(uniforms->fTextureMatrixUni); 921 922 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { 923 texCoordVaryingType = kVec2f_GrSLType; 924 } else { 925 texCoordVaryingType = kVec3f_GrSLType; 926 } 927 } 928 const char *varyingVSName, *varyingFSName; 929 builder->addVarying(texCoordVaryingType, 930 "Stage", 931 &varyingVSName, 932 &varyingFSName); 933 builder->setupTextureAccess(varyingFSName, texCoordVaryingType); 934 935 int numTextures = stage->numTextures(); 936 SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; 937 938 textureSamplers.push_back_n(numTextures); 939 940 for (int i = 0; i < numTextures; ++i) { 941 textureSamplers[i].init(builder, &stage->textureAccess(i)); 942 uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform); 943 } 944 945 if (!matName) { 946 GrAssert(kVec2f_GrSLType == texCoordVaryingType); 947 builder->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord); 948 } else { 949 // varying = texMatrix * texCoord 950 builder->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n", 951 varyingVSName, matName, vsInCoord, 952 vector_all_coords(GrSLTypeToVecLength(texCoordVaryingType))); 953 } 954 955 // Enclose custom code in a block to avoid namespace conflicts 956 builder->fVSCode.appendf("\t{ // %s\n", glStage->name()); 957 builder->fFSCode.appendf("\t{ // %s \n", glStage->name()); 958 glStage->emitCode(builder, 959 *stage, 960 desc.fCustomStageKey, 961 varyingVSName, 962 fsOutColor, 963 fsInColor, 964 textureSamplers); 965 builder->fVSCode.appendf("\t}\n"); 966 builder->fFSCode.appendf("\t}\n"); 967 968 return glStage; 969} 970 971void GrGLProgram::setData(const GrDrawState& drawState) { 972 int rtHeight = drawState.getRenderTarget()->height(); 973 if (GrGLUniformManager::kInvalidUniformHandle != fUniforms.fRTHeight && fRTHeight != rtHeight) { 974 fUniformManager.set1f(fUniforms.fRTHeight, GrIntToScalar(rtHeight)); 975 fRTHeight = rtHeight; 976 } 977 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 978 if (NULL != fProgramStage[s]) { 979 const GrSamplerState& sampler = drawState.getSampler(s); 980 GrAssert(NULL != sampler.getCustomStage()); 981 fProgramStage[s]->setData(fUniformManager, *sampler.getCustomStage()); 982 } 983 } 984} 985