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