GrGLProgram.cpp revision ed8659b51d9f2bad3f004df6033d72cc32d71c0d
1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrGLProgram.h" 9 10#include "GrAllocator.h" 11#include "GrEffect.h" 12#include "GrGLEffect.h" 13#include "GrGpuGL.h" 14#include "GrGLShaderVar.h" 15#include "GrBackendEffectFactory.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(fContextInfo.interface(), X) 24#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContextInfo.interface(), R, X) 25 26SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, "Print the source code for all shaders generated."); 27 28#define COL_ATTR_NAME "aColor" 29#define COV_ATTR_NAME "aCoverage" 30#define EDGE_ATTR_NAME "aEdge" 31 32namespace { 33inline void tex_attr_name(int coordIdx, SkString* s) { 34 *s = "aTexCoord"; 35 s->appendS32(coordIdx); 36} 37 38inline const char* declared_color_output_name() { return "fsColorOut"; } 39inline const char* dual_source_output_name() { return "dualSourceOut"; } 40 41} 42 43GrGLProgram* GrGLProgram::Create(const GrGLContextInfo& gl, 44 const Desc& desc, 45 const GrEffectStage* stages[]) { 46 GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages)); 47 if (!program->succeeded()) { 48 delete program; 49 program = NULL; 50 } 51 return program; 52} 53 54GrGLProgram::GrGLProgram(const GrGLContextInfo& gl, 55 const Desc& desc, 56 const GrEffectStage* stages[]) 57: fContextInfo(gl) 58, fUniformManager(gl) { 59 fDesc = desc; 60 fVShaderID = 0; 61 fGShaderID = 0; 62 fFShaderID = 0; 63 fProgramID = 0; 64 65 fViewMatrix = SkMatrix::InvalidMatrix(); 66 fViewportSize.set(-1, -1); 67 fOrigin = (GrSurfaceOrigin) -1; 68 fColor = GrColor_ILLEGAL; 69 fColorFilterColor = GrColor_ILLEGAL; 70 fRTHeight = -1; 71 72 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 73 fEffects[s] = NULL; 74 } 75 76 this->genProgram(stages); 77} 78 79GrGLProgram::~GrGLProgram() { 80 if (fVShaderID) { 81 GL_CALL(DeleteShader(fVShaderID)); 82 } 83 if (fGShaderID) { 84 GL_CALL(DeleteShader(fGShaderID)); 85 } 86 if (fFShaderID) { 87 GL_CALL(DeleteShader(fFShaderID)); 88 } 89 if (fProgramID) { 90 GL_CALL(DeleteProgram(fProgramID)); 91 } 92 93 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 94 delete fEffects[i]; 95 } 96} 97 98void GrGLProgram::abandon() { 99 fVShaderID = 0; 100 fGShaderID = 0; 101 fFShaderID = 0; 102 fProgramID = 0; 103} 104 105void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 106 GrBlendCoeff* dstCoeff) const { 107 switch (fDesc.fDualSrcOutput) { 108 case Desc::kNone_DualSrcOutput: 109 break; 110 // the prog will write a coverage value to the secondary 111 // output and the dst is blended by one minus that value. 112 case Desc::kCoverage_DualSrcOutput: 113 case Desc::kCoverageISA_DualSrcOutput: 114 case Desc::kCoverageISC_DualSrcOutput: 115 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; 116 break; 117 default: 118 GrCrash("Unexpected dual source blend output"); 119 break; 120 } 121} 122 123namespace { 124 125// given two blend coeffecients determine whether the src 126// and/or dst computation can be omitted. 127inline void need_blend_inputs(SkXfermode::Coeff srcCoeff, 128 SkXfermode::Coeff dstCoeff, 129 bool* needSrcValue, 130 bool* needDstValue) { 131 if (SkXfermode::kZero_Coeff == srcCoeff) { 132 switch (dstCoeff) { 133 // these all read the src 134 case SkXfermode::kSC_Coeff: 135 case SkXfermode::kISC_Coeff: 136 case SkXfermode::kSA_Coeff: 137 case SkXfermode::kISA_Coeff: 138 *needSrcValue = true; 139 break; 140 default: 141 *needSrcValue = false; 142 break; 143 } 144 } else { 145 *needSrcValue = true; 146 } 147 if (SkXfermode::kZero_Coeff == dstCoeff) { 148 switch (srcCoeff) { 149 // these all read the dst 150 case SkXfermode::kDC_Coeff: 151 case SkXfermode::kIDC_Coeff: 152 case SkXfermode::kDA_Coeff: 153 case SkXfermode::kIDA_Coeff: 154 *needDstValue = true; 155 break; 156 default: 157 *needDstValue = false; 158 break; 159 } 160 } else { 161 *needDstValue = true; 162 } 163} 164 165/** 166 * Create a blend_coeff * value string to be used in shader code. Sets empty 167 * string if result is trivially zero. 168 */ 169inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff, 170 const char* src, const char* dst, 171 const char* value) { 172 switch (coeff) { 173 case SkXfermode::kZero_Coeff: /** 0 */ 174 *str = ""; 175 break; 176 case SkXfermode::kOne_Coeff: /** 1 */ 177 *str = value; 178 break; 179 case SkXfermode::kSC_Coeff: 180 str->printf("(%s * %s)", src, value); 181 break; 182 case SkXfermode::kISC_Coeff: 183 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value); 184 break; 185 case SkXfermode::kDC_Coeff: 186 str->printf("(%s * %s)", dst, value); 187 break; 188 case SkXfermode::kIDC_Coeff: 189 str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value); 190 break; 191 case SkXfermode::kSA_Coeff: /** src alpha */ 192 str->printf("(%s.a * %s)", src, value); 193 break; 194 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 195 str->printf("((1.0 - %s.a) * %s)", src, value); 196 break; 197 case SkXfermode::kDA_Coeff: /** dst alpha */ 198 str->printf("(%s.a * %s)", dst, value); 199 break; 200 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 201 str->printf("((1.0 - %s.a) * %s)", dst, value); 202 break; 203 default: 204 GrCrash("Unexpected xfer coeff."); 205 break; 206 } 207} 208/** 209 * Adds a line to the fragment shader code which modifies the color by 210 * the specified color filter. 211 */ 212void add_color_filter(SkString* fsCode, const char * outputVar, 213 SkXfermode::Coeff uniformCoeff, 214 SkXfermode::Coeff colorCoeff, 215 const char* filterColor, 216 const char* inColor) { 217 SkString colorStr, constStr; 218 blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor); 219 blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor); 220 221 fsCode->appendf("\t%s = ", outputVar); 222 GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str()); 223 fsCode->append(";\n"); 224} 225} 226 227bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, 228 GrGLShaderBuilder* builder) const { 229 if (fDesc.fVertexLayout & GrDrawState::kEdge_VertexLayoutBit) { 230 const char *vsName, *fsName; 231 builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); 232 builder->fVSAttrs.push_back().set(kVec4f_GrSLType, 233 GrGLShaderVar::kAttribute_TypeModifier, 234 EDGE_ATTR_NAME); 235 builder->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); 236 switch (fDesc.fVertexEdgeType) { 237 case GrDrawState::kHairLine_EdgeType: 238 builder->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", builder->fragmentPosition(), fsName); 239 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 240 break; 241 case GrDrawState::kQuad_EdgeType: 242 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 243 // keep the derivative instructions outside the conditional 244 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 245 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 246 builder->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 247 // today we know z and w are in device space. We could use derivatives 248 builder->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); 249 builder->fFSCode.append ("\t} else {\n"); 250 builder->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 251 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 252 fsName, fsName); 253 builder->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 254 builder->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" 255 "\t}\n"); 256 if (kES2_GrGLBinding == fContextInfo.binding()) { 257 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 258 } 259 break; 260 case GrDrawState::kHairQuad_EdgeType: 261 builder->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 262 builder->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 263 builder->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 264 "\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 265 fsName, fsName); 266 builder->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 267 builder->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 268 builder->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 269 if (kES2_GrGLBinding == fContextInfo.binding()) { 270 builder->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 271 } 272 break; 273 case GrDrawState::kCircle_EdgeType: 274 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 275 builder->fFSCode.appendf("\tfloat d = distance(%s.xy, %s.xy);\n", builder->fragmentPosition(), fsName); 276 builder->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 277 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); 278 builder->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n"); 279 break; 280 case GrDrawState::kEllipse_EdgeType: 281 builder->fFSCode.append("\tfloat edgeAlpha;\n"); 282 builder->fFSCode.appendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName); 283 builder->fFSCode.appendf("\toffset.y *= %s.w;\n", fsName); 284 builder->fFSCode.append("\tfloat d = length(offset);\n"); 285 builder->fFSCode.appendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 286 break; 287 default: 288 GrCrash("Unknown Edge Type!"); 289 break; 290 } 291 if (fDesc.fDiscardIfOutsideEdge) { 292 builder->fFSCode.appendf("\tif (edgeAlpha <= 0.0) {\n\t\tdiscard;\n\t}\n"); 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 fUniformHandles.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 fUniformHandles.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 (c_PrintShaders) { 471 GrPrintf(shader.c_str()); 472 GrPrintf("\n"); 473 } 474 475 if (!(fVShaderID = compile_shader(fContextInfo, GR_GL_VERTEX_SHADER, shader))) { 476 return false; 477 } 478 479 if (builder.fUsesGS) { 480 builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); 481 if (c_PrintShaders) { 482 GrPrintf(shader.c_str()); 483 GrPrintf("\n"); 484 } 485 if (!(fGShaderID = compile_shader(fContextInfo, GR_GL_GEOMETRY_SHADER, shader))) { 486 return false; 487 } 488 } else { 489 fGShaderID = 0; 490 } 491 492 builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); 493 if (c_PrintShaders) { 494 GrPrintf(shader.c_str()); 495 GrPrintf("\n"); 496 } 497 if (!(fFShaderID = compile_shader(fContextInfo, GR_GL_FRAGMENT_SHADER, shader))) { 498 return false; 499 } 500 501 return true; 502} 503 504bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { 505 GrAssert(0 == fProgramID); 506 507 GrGLShaderBuilder builder(fContextInfo, fUniformManager); 508 const uint32_t& layout = fDesc.fVertexLayout; 509 510#if GR_GL_EXPERIMENTAL_GS 511 builder.fUsesGS = fDesc.fExperimentalGS; 512#endif 513 514 SkXfermode::Coeff colorCoeff, uniformCoeff; 515 // The rest of transfer mode color filters have not been implemented 516 if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 517 GR_DEBUGCODE(bool success =) 518 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 519 (fDesc.fColorFilterXfermode), 520 &uniformCoeff, &colorCoeff); 521 GR_DEBUGASSERT(success); 522 } else { 523 colorCoeff = SkXfermode::kOne_Coeff; 524 uniformCoeff = SkXfermode::kZero_Coeff; 525 } 526 527 // no need to do the color filter if coverage is 0. The output color is scaled by the coverage. 528 // All the dual source outputs are scaled by the coverage as well. 529 if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) { 530 colorCoeff = SkXfermode::kZero_Coeff; 531 uniformCoeff = SkXfermode::kZero_Coeff; 532 } 533 534 // If we know the final color is going to be all zeros then we can 535 // simplify the color filter coefficients. needComputedColor will then 536 // come out false below. 537 if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) { 538 colorCoeff = SkXfermode::kZero_Coeff; 539 if (SkXfermode::kDC_Coeff == uniformCoeff || 540 SkXfermode::kDA_Coeff == uniformCoeff) { 541 uniformCoeff = SkXfermode::kZero_Coeff; 542 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 543 SkXfermode::kIDA_Coeff == uniformCoeff) { 544 uniformCoeff = SkXfermode::kOne_Coeff; 545 } 546 } 547 548 bool needColorFilterUniform; 549 bool needComputedColor; 550 need_blend_inputs(uniformCoeff, colorCoeff, 551 &needColorFilterUniform, &needComputedColor); 552 553 // the dual source output has no canonical var name, have to 554 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 555 bool dualSourceOutputWritten = false; 556 builder.fHeader.append(GrGetGLSLVersionDecl(fContextInfo.binding(), 557 fContextInfo.glslGeneration())); 558 559 GrGLShaderVar colorOutput; 560 bool isColorDeclared = GrGLSLSetupFSColorOuput(fContextInfo.glslGeneration(), 561 declared_color_output_name(), 562 &colorOutput); 563 if (isColorDeclared) { 564 builder.fFSOutputs.push_back(colorOutput); 565 } 566 567 const char* viewMName; 568 fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, 569 kMat33f_GrSLType, "ViewM", &viewMName); 570 571 572 builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" 573 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", 574 viewMName, builder.positionAttribute().getName().c_str()); 575 576 // incoming color to current stage being processed. 577 SkString inColor; 578 579 if (needComputedColor) { 580 this->genInputColor(&builder, &inColor); 581 } 582 583 // we output point size in the GS if present 584 if (fDesc.fEmitsPointSize && !builder.fUsesGS){ 585 builder.fVSCode.append("\tgl_PointSize = 1.0;\n"); 586 } 587 588 // add texture coordinates that are used to the list of vertex attr decls 589 SkString texCoordAttrs[GrDrawState::kMaxTexCoords]; 590 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 591 if (GrDrawState::VertexUsesTexCoordIdx(t, layout)) { 592 tex_attr_name(t, texCoordAttrs + t); 593 builder.fVSAttrs.push_back().set(kVec2f_GrSLType, 594 GrGLShaderVar::kAttribute_TypeModifier, 595 texCoordAttrs[t].c_str()); 596 } 597 } 598 599 /////////////////////////////////////////////////////////////////////////// 600 // compute the final color 601 602 // if we have color stages string them together, feeding the output color 603 // of each to the next and generating code for each stage. 604 if (needComputedColor) { 605 SkString outColor; 606 for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { 607 if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) { 608 // create var to hold stage result 609 outColor = "color"; 610 outColor.appendS32(s); 611 builder.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); 612 613 const char* inCoords; 614 // figure out what our input coords are 615 int tcIdx = GrDrawState::VertexTexCoordsForStage(s, layout); 616 if (tcIdx < 0) { 617 inCoords = builder.positionAttribute().c_str(); 618 } else { 619 // must have input tex coordinates if stage is enabled. 620 GrAssert(texCoordAttrs[tcIdx].size()); 621 inCoords = texCoordAttrs[tcIdx].c_str(); 622 } 623 624 builder.setCurrentStage(s); 625 fEffects[s] = builder.createAndEmitGLEffect(*stages[s], 626 fDesc.fEffectKeys[s], 627 inColor.size() ? inColor.c_str() : NULL, 628 outColor.c_str(), 629 inCoords, 630 &fUniformHandles.fSamplerUnis[s]); 631 builder.setNonStage(); 632 inColor = outColor; 633 } 634 } 635 } 636 637 // if have all ones or zeros for the "dst" input to the color filter then we 638 // may be able to make additional optimizations. 639 if (needColorFilterUniform && needComputedColor && !inColor.size()) { 640 GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput); 641 bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || 642 SkXfermode::kIDA_Coeff == uniformCoeff; 643 if (uniformCoeffIsZero) { 644 uniformCoeff = SkXfermode::kZero_Coeff; 645 bool bogus; 646 need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff, 647 &needColorFilterUniform, &bogus); 648 } 649 } 650 const char* colorFilterColorUniName = NULL; 651 if (needColorFilterUniform) { 652 fUniformHandles.fColorFilterUni = builder.addUniform( 653 GrGLShaderBuilder::kFragment_ShaderType, 654 kVec4f_GrSLType, "FilterColor", 655 &colorFilterColorUniName); 656 } 657 bool wroteFragColorZero = false; 658 if (SkXfermode::kZero_Coeff == uniformCoeff && 659 SkXfermode::kZero_Coeff == colorCoeff) { 660 builder.fFSCode.appendf("\t%s = %s;\n", 661 colorOutput.getName().c_str(), 662 GrGLSLZerosVecf(4)); 663 wroteFragColorZero = true; 664 } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { 665 builder.fFSCode.append("\tvec4 filteredColor;\n"); 666 const char* color = adjustInColor(inColor); 667 add_color_filter(&builder.fFSCode, "filteredColor", uniformCoeff, 668 colorCoeff, colorFilterColorUniName, color); 669 inColor = "filteredColor"; 670 } 671 672 /////////////////////////////////////////////////////////////////////////// 673 // compute the partial coverage (coverage stages and edge aa) 674 675 SkString inCoverage; 676 bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput; 677 // we don't need to compute coverage at all if we know the final shader 678 // output will be zero and we don't have a dual src blend output. 679 if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 680 681 if (!coverageIsZero) { 682 bool inCoverageIsScalar = this->genEdgeCoverage(&inCoverage, &builder); 683 684 switch (fDesc.fCoverageInput) { 685 case Desc::kSolidWhite_ColorInput: 686 // empty string implies solid white 687 break; 688 case Desc::kAttribute_ColorInput: 689 gen_attribute_coverage(&builder, &inCoverage); 690 inCoverageIsScalar = false; 691 break; 692 case Desc::kUniform_ColorInput: 693 this->genUniformCoverage(&builder, &inCoverage); 694 inCoverageIsScalar = false; 695 break; 696 default: 697 GrCrash("Unexpected input coverage."); 698 } 699 700 SkString outCoverage; 701 const int& startStage = fDesc.fFirstCoverageStage; 702 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 703 if (fDesc.fEffectKeys[s]) { 704 // create var to hold stage output 705 outCoverage = "coverage"; 706 outCoverage.appendS32(s); 707 builder.fFSCode.appendf("\tvec4 %s;\n", outCoverage.c_str()); 708 709 const char* inCoords; 710 // figure out what our input coords are 711 int tcIdx = 712 GrDrawState::VertexTexCoordsForStage(s, layout); 713 if (tcIdx < 0) { 714 inCoords = builder.positionAttribute().c_str(); 715 } else { 716 // must have input tex coordinates if stage is 717 // enabled. 718 GrAssert(texCoordAttrs[tcIdx].size()); 719 inCoords = texCoordAttrs[tcIdx].c_str(); 720 } 721 722 // stages don't know how to deal with a scalar input. (Maybe they should. We 723 // could pass a GrGLShaderVar) 724 if (inCoverageIsScalar) { 725 builder.fFSCode.appendf("\tvec4 %s4 = vec4(%s);\n", 726 inCoverage.c_str(), inCoverage.c_str()); 727 inCoverage.append("4"); 728 } 729 builder.setCurrentStage(s); 730 fEffects[s] = builder.createAndEmitGLEffect( 731 *stages[s], 732 fDesc.fEffectKeys[s], 733 inCoverage.size() ? inCoverage.c_str() : NULL, 734 outCoverage.c_str(), 735 inCoords, 736 &fUniformHandles.fSamplerUnis[s]); 737 builder.setNonStage(); 738 inCoverage = outCoverage; 739 } 740 } 741 } 742 743 if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { 744 builder.fFSOutputs.push_back().set(kVec4f_GrSLType, 745 GrGLShaderVar::kOut_TypeModifier, 746 dual_source_output_name()); 747 bool outputIsZero = coverageIsZero; 748 SkString coeff; 749 if (!outputIsZero && 750 Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { 751 if (!inColor.size()) { 752 outputIsZero = true; 753 } else { 754 if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { 755 coeff.printf("(1 - %s.a)", inColor.c_str()); 756 } else { 757 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 758 } 759 } 760 } 761 if (outputIsZero) { 762 builder.fFSCode.appendf("\t%s = %s;\n", 763 dual_source_output_name(), 764 GrGLSLZerosVecf(4)); 765 } else { 766 builder.fFSCode.appendf("\t%s =", dual_source_output_name()); 767 GrGLSLModulate4f(&builder.fFSCode, coeff.c_str(), inCoverage.c_str()); 768 builder.fFSCode.append(";\n"); 769 } 770 dualSourceOutputWritten = true; 771 } 772 } 773 774 /////////////////////////////////////////////////////////////////////////// 775 // combine color and coverage as frag color 776 777 if (!wroteFragColorZero) { 778 if (coverageIsZero) { 779 builder.fFSCode.appendf("\t%s = %s;\n", 780 colorOutput.getName().c_str(), 781 GrGLSLZerosVecf(4)); 782 } else { 783 builder.fFSCode.appendf("\t%s = ", colorOutput.getName().c_str()); 784 GrGLSLModulate4f(&builder.fFSCode, inColor.c_str(), inCoverage.c_str()); 785 builder.fFSCode.append(";\n"); 786 } 787 } 788 789 /////////////////////////////////////////////////////////////////////////// 790 // insert GS 791#if GR_DEBUG 792 this->genGeometryShader(&builder); 793#endif 794 795 /////////////////////////////////////////////////////////////////////////// 796 // compile and setup attribs and unis 797 798 if (!this->compileShaders(builder)) { 799 return false; 800 } 801 802 if (!this->bindOutputsAttribsAndLinkProgram(builder, 803 texCoordAttrs, 804 isColorDeclared, 805 dualSourceOutputWritten)) { 806 return false; 807 } 808 809 builder.finished(fProgramID); 810 this->initSamplerUniforms(); 811 fUniformHandles.fRTHeightUni = builder.getRTHeightUniform(); 812 813 return true; 814} 815 816bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, 817 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, 840 PositionAttributeIdx(), 841 builder.positionAttribute().c_str())); 842 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 843 if (texCoordAttrNames[t].size()) { 844 GL_CALL(BindAttribLocation(fProgramID, 845 TexCoordAttributeIdx(t), 846 texCoordAttrNames[t].c_str())); 847 } 848 } 849 850 GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME)); 851 GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME)); 852 GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); 853 854 GL_CALL(LinkProgram(fProgramID)); 855 856 GrGLint linked = GR_GL_INIT_ZERO; 857 GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); 858 if (!linked) { 859 GrGLint infoLen = GR_GL_INIT_ZERO; 860 GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 861 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 862 if (infoLen > 0) { 863 // retrieve length even though we don't need it to workaround 864 // bug in chrome cmd buffer param validation. 865 GrGLsizei length = GR_GL_INIT_ZERO; 866 GL_CALL(GetProgramInfoLog(fProgramID, 867 infoLen+1, 868 &length, 869 (char*)log.get())); 870 GrPrintf((char*)log.get()); 871 } 872 GrAssert(!"Error linking program"); 873 GL_CALL(DeleteProgram(fProgramID)); 874 fProgramID = 0; 875 return false; 876 } 877 return true; 878} 879 880void GrGLProgram::initSamplerUniforms() { 881 GL_CALL(UseProgram(fProgramID)); 882 // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes this 883 // behavior. 884 GrGLint texUnitIdx = 0; 885 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 886 int numSamplers = fUniformHandles.fSamplerUnis[s].count(); 887 for (int u = 0; u < numSamplers; ++u) { 888 UniformHandle handle = fUniformHandles.fSamplerUnis[s][u]; 889 if (GrGLUniformManager::kInvalidUniformHandle != handle) { 890 fUniformManager.setSampler(handle, texUnitIdx); 891 ++texUnitIdx; 892 } 893 } 894 } 895} 896 897/////////////////////////////////////////////////////////////////////////////// 898 899void GrGLProgram::setData(GrGpuGL* gpu) { 900 const GrDrawState& drawState = gpu->getDrawState(); 901 902 int rtHeight = drawState.getRenderTarget()->height(); 903 if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni && 904 fRTHeight != rtHeight) { 905 fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(rtHeight)); 906 fRTHeight = rtHeight; 907 } 908 GrGLint texUnitIdx = 0; 909 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 910 if (NULL != fEffects[s]) { 911 const GrEffectStage& stage = drawState.getStage(s); 912 GrAssert(NULL != stage.getEffect()); 913 fEffects[s]->setData(fUniformManager, stage); 914 int numSamplers = fUniformHandles.fSamplerUnis[s].count(); 915 for (int u = 0; u < numSamplers; ++u) { 916 UniformHandle handle = fUniformHandles.fSamplerUnis[s][u]; 917 if (GrGLUniformManager::kInvalidUniformHandle != handle) { 918 const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u); 919 GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture()); 920 gpu->bindTexture(texUnitIdx, access.getParams(), texture); 921 ++texUnitIdx; 922 } 923 } 924 } 925 } 926} 927