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