GrGLProgram.cpp revision 054ae99d93711c26e40682a0e3a03a47ea605c53
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 fGShaderID = 0; 393#if GR_GL_EXPERIMENTAL_GS 394 if (fDesc.fExperimentalGS) { 395 builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); 396 if (c_PrintShaders) { 397 GrPrintf(shader.c_str()); 398 GrPrintf("\n"); 399 } 400 if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) { 401 return false; 402 } 403 } 404#endif 405 406 builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); 407 if (c_PrintShaders) { 408 GrPrintf(shader.c_str()); 409 GrPrintf("\n"); 410 } 411 if (!(fFShaderID = compile_shader(fContext, GR_GL_FRAGMENT_SHADER, shader))) { 412 return false; 413 } 414 415 return true; 416} 417 418bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { 419 GrAssert(0 == fProgramID); 420 421 GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc); 422 423 SkXfermode::Coeff colorCoeff, uniformCoeff; 424 // The rest of transfer mode color filters have not been implemented 425 if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 426 GR_DEBUGCODE(bool success =) 427 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 428 (fDesc.fColorFilterXfermode), 429 &uniformCoeff, &colorCoeff); 430 GR_DEBUGASSERT(success); 431 } else { 432 colorCoeff = SkXfermode::kOne_Coeff; 433 uniformCoeff = SkXfermode::kZero_Coeff; 434 } 435 436 // no need to do the color filter if coverage is 0. The output color is scaled by the coverage. 437 // All the dual source outputs are scaled by the coverage as well. 438 if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput) { 439 colorCoeff = SkXfermode::kZero_Coeff; 440 uniformCoeff = SkXfermode::kZero_Coeff; 441 } 442 443 // If we know the final color is going to be all zeros then we can 444 // simplify the color filter coefficients. needComputedColor will then 445 // come out false below. 446 if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fColorInput) { 447 colorCoeff = SkXfermode::kZero_Coeff; 448 if (SkXfermode::kDC_Coeff == uniformCoeff || 449 SkXfermode::kDA_Coeff == uniformCoeff) { 450 uniformCoeff = SkXfermode::kZero_Coeff; 451 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 452 SkXfermode::kIDA_Coeff == uniformCoeff) { 453 uniformCoeff = SkXfermode::kOne_Coeff; 454 } 455 } 456 457 bool needColorFilterUniform; 458 bool needComputedColor; 459 need_blend_inputs(uniformCoeff, colorCoeff, 460 &needColorFilterUniform, &needComputedColor); 461 462 // the dual source output has no canonical var name, have to 463 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 464 bool dualSourceOutputWritten = false; 465 466 GrGLShaderVar colorOutput; 467 bool isColorDeclared = GrGLSLSetupFSColorOuput(fContext.info().glslGeneration(), 468 declared_color_output_name(), 469 &colorOutput); 470 if (isColorDeclared) { 471 builder.fFSOutputs.push_back(colorOutput); 472 } 473 474 const char* viewMName; 475 fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, 476 kMat33f_GrSLType, "ViewM", &viewMName); 477 478 479 builder.vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" 480 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 481 viewMName, builder.positionAttribute().getName().c_str()); 482 483 // incoming color to current stage being processed. 484 SkString inColor; 485 486 if (needComputedColor) { 487 this->genInputColor(&builder, &inColor); 488 } 489 490 // we output point size in the GS if present 491 if (fDesc.fEmitsPointSize 492#if GR_GL_EXPERIMENTAL_GS 493 && !fDesc.fExperimentalGS 494#endif 495 ) { 496 builder.vsCodeAppend("\tgl_PointSize = 1.0;\n"); 497 } 498 499 /////////////////////////////////////////////////////////////////////////// 500 // compute the final color 501 502 // if we have color stages string them together, feeding the output color 503 // of each to the next and generating code for each stage. 504 if (needComputedColor) { 505 SkString outColor; 506 for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { 507 if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) { 508 // create var to hold stage result 509 outColor = "color"; 510 outColor.appendS32(s); 511 builder.fsCodeAppendf("\tvec4 %s;\n", outColor.c_str()); 512 513 builder.setCurrentStage(s); 514 fEffects[s] = builder.createAndEmitGLEffect(*stages[s], 515 fDesc.fEffectKeys[s], 516 inColor.size() ? inColor.c_str() : NULL, 517 outColor.c_str(), 518 &fUniformHandles.fEffectSamplerUnis[s]); 519 builder.setNonStage(); 520 inColor = outColor; 521 } 522 } 523 } 524 525 // if have all ones or zeros for the "dst" input to the color filter then we 526 // may be able to make additional optimizations. 527 if (needColorFilterUniform && needComputedColor && !inColor.size()) { 528 GrAssert(GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.fColorInput); 529 bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || 530 SkXfermode::kIDA_Coeff == uniformCoeff; 531 if (uniformCoeffIsZero) { 532 uniformCoeff = SkXfermode::kZero_Coeff; 533 bool bogus; 534 need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff, 535 &needColorFilterUniform, &bogus); 536 } 537 } 538 const char* colorFilterColorUniName = NULL; 539 if (needColorFilterUniform) { 540 fUniformHandles.fColorFilterUni = builder.addUniform( 541 GrGLShaderBuilder::kFragment_ShaderType, 542 kVec4f_GrSLType, "FilterColor", 543 &colorFilterColorUniName); 544 } 545 bool wroteFragColorZero = false; 546 if (SkXfermode::kZero_Coeff == uniformCoeff && 547 SkXfermode::kZero_Coeff == colorCoeff) { 548 builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4)); 549 wroteFragColorZero = true; 550 } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { 551 builder.fsCodeAppend("\tvec4 filteredColor;\n"); 552 const char* color = adjustInColor(inColor); 553 add_color_filter(&builder, "filteredColor", uniformCoeff, 554 colorCoeff, colorFilterColorUniName, color); 555 inColor = "filteredColor"; 556 } 557 558 /////////////////////////////////////////////////////////////////////////// 559 // compute the partial coverage (coverage stages and edge aa) 560 561 SkString inCoverage; 562 bool coverageIsZero = GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput; 563 // we don't need to compute coverage at all if we know the final shader 564 // output will be zero and we don't have a dual src blend output. 565 if (!wroteFragColorZero || GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 566 567 if (!coverageIsZero) { 568 switch (fDesc.fCoverageInput) { 569 case GrGLProgramDesc::kSolidWhite_ColorInput: 570 // empty string implies solid white 571 break; 572 case GrGLProgramDesc::kAttribute_ColorInput: 573 gen_attribute_coverage(&builder, &inCoverage); 574 break; 575 case GrGLProgramDesc::kUniform_ColorInput: 576 this->genUniformCoverage(&builder, &inCoverage); 577 break; 578 default: 579 GrCrash("Unexpected input coverage."); 580 } 581 582 SkString outCoverage; 583 const int& startStage = fDesc.fFirstCoverageStage; 584 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 585 if (fDesc.fEffectKeys[s]) { 586 // create var to hold stage output 587 outCoverage = "coverage"; 588 outCoverage.appendS32(s); 589 builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str()); 590 591 builder.setCurrentStage(s); 592 fEffects[s] = builder.createAndEmitGLEffect( 593 *stages[s], 594 fDesc.fEffectKeys[s], 595 inCoverage.size() ? inCoverage.c_str() : NULL, 596 outCoverage.c_str(), 597 &fUniformHandles.fEffectSamplerUnis[s]); 598 builder.setNonStage(); 599 inCoverage = outCoverage; 600 } 601 } 602 603 // discard if coverage is zero 604 if (fDesc.fDiscardIfZeroCoverage && !outCoverage.isEmpty()) { 605 builder.fsCodeAppendf( 606 "\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n", 607 outCoverage.c_str()); 608 } 609 } 610 611 if (GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 612 builder.fFSOutputs.push_back().set(kVec4f_GrSLType, 613 GrGLShaderVar::kOut_TypeModifier, 614 dual_source_output_name()); 615 bool outputIsZero = coverageIsZero; 616 SkString coeff; 617 if (!outputIsZero && 618 GrGLProgramDesc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { 619 if (!inColor.size()) { 620 outputIsZero = true; 621 } else { 622 if (GrGLProgramDesc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { 623 coeff.printf("(1 - %s.a)", inColor.c_str()); 624 } else { 625 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 626 } 627 } 628 } 629 if (outputIsZero) { 630 builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), GrGLSLZerosVecf(4)); 631 } else { 632 SkString modulate; 633 GrGLSLModulate4f(&modulate, coeff.c_str(), inCoverage.c_str()); 634 builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str()); 635 } 636 dualSourceOutputWritten = true; 637 } 638 } 639 640 /////////////////////////////////////////////////////////////////////////// 641 // combine color and coverage as frag color 642 643 if (!wroteFragColorZero) { 644 if (coverageIsZero) { 645 builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4)); 646 } else { 647 SkString modulate; 648 GrGLSLModulate4f(&modulate, inColor.c_str(), inCoverage.c_str()); 649 builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str()); 650 } 651 } 652 653 /////////////////////////////////////////////////////////////////////////// 654 // insert GS 655#if GR_DEBUG 656 this->genGeometryShader(&builder); 657#endif 658 659 /////////////////////////////////////////////////////////////////////////// 660 // compile and setup attribs and unis 661 662 if (!this->compileShaders(builder)) { 663 return false; 664 } 665 666 if (!this->bindOutputsAttribsAndLinkProgram(builder, 667 isColorDeclared, 668 dualSourceOutputWritten)) { 669 return false; 670 } 671 672 builder.finished(fProgramID); 673 fUniformHandles.fRTHeightUni = builder.getRTHeightUniform(); 674 fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform(); 675 fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform(); 676 fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform(); 677 // This must be called after we set fDstCopySamplerUni above. 678 this->initSamplerUniforms(); 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 if (-1 != fDesc.fLocalCoordAttributeIndex) { 709 GL_CALL(BindAttribLocation(fProgramID, 710 fDesc.fLocalCoordAttributeIndex, 711 builder.localCoordsAttribute().c_str())); 712 } 713 if (-1 != fDesc.fColorAttributeIndex) { 714 GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME)); 715 } 716 if (-1 != fDesc.fCoverageAttributeIndex) { 717 GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME)); 718 } 719 720 const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end(); 721 for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin(); 722 attrib != attribEnd; 723 ++attrib) { 724 GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str())); 725 } 726 727 GL_CALL(LinkProgram(fProgramID)); 728 729 GrGLint linked = GR_GL_INIT_ZERO; 730 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 731 if (!linked) { 732 GrGLint infoLen = GR_GL_INIT_ZERO; 733 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 734 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 735 if (infoLen > 0) { 736 // retrieve length even though we don't need it to workaround 737 // bug in chrome cmd buffer param validation. 738 GrGLsizei length = GR_GL_INIT_ZERO; 739 GL_CALL(GetProgramInfoLog(fProgramID, 740 infoLen+1, 741 &length, 742 (char*)log.get())); 743 GrPrintf((char*)log.get()); 744 } 745 GrAssert(!"Error linking program"); 746 GL_CALL(DeleteProgram(fProgramID)); 747 fProgramID = 0; 748 return false; 749 } 750 return true; 751} 752 753void GrGLProgram::initSamplerUniforms() { 754 GL_CALL(UseProgram(fProgramID)); 755 // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes 756 // this behavior. 757 GrGLint texUnitIdx = 0; 758 if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopySamplerUni) { 759 fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx); 760 ++texUnitIdx; 761 } 762 763 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 764 int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count(); 765 for (int u = 0; u < numSamplers; ++u) { 766 UniformHandle handle = fUniformHandles.fEffectSamplerUnis[s][u]; 767 if (GrGLUniformManager::kInvalidUniformHandle != handle) { 768 fUniformManager.setSampler(handle, texUnitIdx); 769 ++texUnitIdx; 770 } 771 } 772 } 773} 774 775/////////////////////////////////////////////////////////////////////////////// 776 777void GrGLProgram::setData(GrGpuGL* gpu, 778 GrColor color, 779 GrColor coverage, 780 const GrDeviceCoordTexture* dstCopy, 781 SharedGLState* sharedState) { 782 const GrDrawState& drawState = gpu->getDrawState(); 783 784 this->setColor(drawState, color, sharedState); 785 this->setCoverage(drawState, coverage, sharedState); 786 this->setMatrixAndRenderTargetHeight(drawState); 787 788 // Setup the SkXfermode::Mode-based colorfilter uniform if necessary 789 if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fColorFilterUni && 790 fColorFilterColor != drawState.getColorFilterColor()) { 791 GrGLfloat c[4]; 792 GrColorToRGBAFloat(drawState.getColorFilterColor(), c); 793 fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c); 794 fColorFilterColor = drawState.getColorFilterColor(); 795 } 796 797 GrGLint texUnitIdx = 0; 798 if (NULL != dstCopy) { 799 if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopyTopLeftUni) { 800 GrAssert(GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopyScaleUni); 801 GrAssert(GrGLUniformManager::kInvalidUniformHandle != 802 fUniformHandles.fDstCopySamplerUni); 803 fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, 804 static_cast<GrGLfloat>(dstCopy->offset().fX), 805 static_cast<GrGLfloat>(dstCopy->offset().fY)); 806 fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, 807 1.f / dstCopy->texture()->width(), 808 1.f / dstCopy->texture()->height()); 809 GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture()); 810 static GrTextureParams kParams; // the default is clamp, nearest filtering. 811 gpu->bindTexture(texUnitIdx, kParams, texture); 812 ++texUnitIdx; 813 } else { 814 GrAssert(GrGLUniformManager::kInvalidUniformHandle == 815 fUniformHandles.fDstCopyScaleUni); 816 GrAssert(GrGLUniformManager::kInvalidUniformHandle == 817 fUniformHandles.fDstCopySamplerUni); 818 } 819 } else { 820 GrAssert(GrGLUniformManager::kInvalidUniformHandle == 821 fUniformHandles.fDstCopyTopLeftUni); 822 GrAssert(GrGLUniformManager::kInvalidUniformHandle == 823 fUniformHandles.fDstCopyScaleUni); 824 GrAssert(GrGLUniformManager::kInvalidUniformHandle == 825 fUniformHandles.fDstCopySamplerUni); 826 } 827 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 828 if (NULL != fEffects[s]) { 829 const GrEffectStage& stage = drawState.getStage(s); 830 GrAssert(NULL != stage.getEffect()); 831 832 bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex; 833 GrDrawEffect drawEffect(stage, explicitLocalCoords); 834 fEffects[s]->setData(fUniformManager, drawEffect); 835 int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count(); 836 for (int u = 0; u < numSamplers; ++u) { 837 UniformHandle handle = fUniformHandles.fEffectSamplerUnis[s][u]; 838 if (GrGLUniformManager::kInvalidUniformHandle != handle) { 839 const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u); 840 GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture()); 841 gpu->bindTexture(texUnitIdx, access.getParams(), texture); 842 ++texUnitIdx; 843 } 844 } 845 } 846 } 847} 848 849void GrGLProgram::setColor(const GrDrawState& drawState, 850 GrColor color, 851 SharedGLState* sharedState) { 852 if (!drawState.hasColorVertexAttribute()) { 853 switch (fDesc.fColorInput) { 854 case GrGLProgramDesc::kAttribute_ColorInput: 855 GrAssert(-1 != fDesc.fColorAttributeIndex); 856 if (sharedState->fConstAttribColor != color || 857 sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) { 858 // OpenGL ES only supports the float varieties of glVertexAttrib 859 GrGLfloat c[4]; 860 GrColorToRGBAFloat(color, c); 861 GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c)); 862 sharedState->fConstAttribColor = color; 863 sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex; 864 } 865 break; 866 case GrGLProgramDesc::kUniform_ColorInput: 867 if (fColor != color) { 868 // OpenGL ES doesn't support unsigned byte varieties of glUniform 869 GrGLfloat c[4]; 870 GrColorToRGBAFloat(color, c); 871 GrAssert(GrGLUniformManager::kInvalidUniformHandle != 872 fUniformHandles.fColorUni); 873 fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c); 874 fColor = color; 875 } 876 sharedState->fConstAttribColorIndex = -1; 877 break; 878 case GrGLProgramDesc::kSolidWhite_ColorInput: 879 case GrGLProgramDesc::kTransBlack_ColorInput: 880 sharedState->fConstAttribColorIndex = -1; 881 break; 882 default: 883 GrCrash("Unknown color type."); 884 } 885 } else { 886 sharedState->fConstAttribColorIndex = -1; 887 } 888} 889 890void GrGLProgram::setCoverage(const GrDrawState& drawState, 891 GrColor coverage, 892 SharedGLState* sharedState) { 893 if (!drawState.hasCoverageVertexAttribute()) { 894 switch (fDesc.fCoverageInput) { 895 case GrGLProgramDesc::kAttribute_ColorInput: 896 if (sharedState->fConstAttribCoverage != coverage || 897 sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) { 898 // OpenGL ES only supports the float varieties of glVertexAttrib 899 GrGLfloat c[4]; 900 GrColorToRGBAFloat(coverage, c); 901 GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c)); 902 sharedState->fConstAttribCoverage = coverage; 903 sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex; 904 } 905 break; 906 case GrGLProgramDesc::kUniform_ColorInput: 907 if (fCoverage != coverage) { 908 // OpenGL ES doesn't support unsigned byte varieties of glUniform 909 GrGLfloat c[4]; 910 GrColorToRGBAFloat(coverage, c); 911 GrAssert(GrGLUniformManager::kInvalidUniformHandle != 912 fUniformHandles.fCoverageUni); 913 fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c); 914 fCoverage = coverage; 915 } 916 sharedState->fConstAttribCoverageIndex = -1; 917 break; 918 case GrGLProgramDesc::kSolidWhite_ColorInput: 919 case GrGLProgramDesc::kTransBlack_ColorInput: 920 sharedState->fConstAttribCoverageIndex = -1; 921 break; 922 default: 923 GrCrash("Unknown coverage type."); 924 } 925 } else { 926 sharedState->fConstAttribCoverageIndex = -1; 927 } 928} 929 930void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { 931 const GrRenderTarget* rt = drawState.getRenderTarget(); 932 SkISize size; 933 size.set(rt->width(), rt->height()); 934 935 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 936 if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni && 937 fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { 938 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight)); 939 } 940 941 if (fMatrixState.fRenderTargetOrigin != rt->origin() || 942 !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) || 943 fMatrixState.fRenderTargetSize != size) { 944 SkMatrix m; 945 if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { 946 m.setAll( 947 SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1, 948 0,-SkIntToScalar(2) / size.fHeight, SK_Scalar1, 949 0, 0, SkMatrix::I()[8]); 950 } else { 951 m.setAll( 952 SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1, 953 0, SkIntToScalar(2) / size.fHeight,-SK_Scalar1, 954 0, 0, SkMatrix::I()[8]); 955 } 956 m.setConcat(m, drawState.getViewMatrix()); 957 958 // ES doesn't allow you to pass true to the transpose param so we do our own transpose. 959 GrGLfloat mt[] = { 960 SkScalarToFloat(m[SkMatrix::kMScaleX]), 961 SkScalarToFloat(m[SkMatrix::kMSkewY]), 962 SkScalarToFloat(m[SkMatrix::kMPersp0]), 963 SkScalarToFloat(m[SkMatrix::kMSkewX]), 964 SkScalarToFloat(m[SkMatrix::kMScaleY]), 965 SkScalarToFloat(m[SkMatrix::kMPersp1]), 966 SkScalarToFloat(m[SkMatrix::kMTransX]), 967 SkScalarToFloat(m[SkMatrix::kMTransY]), 968 SkScalarToFloat(m[SkMatrix::kMPersp2]) 969 }; 970 fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, mt); 971 fMatrixState.fViewMatrix = drawState.getViewMatrix(); 972 fMatrixState.fRenderTargetSize = size; 973 fMatrixState.fRenderTargetOrigin = rt->origin(); 974 } 975} 976