GrGLProgram.cpp revision 5259814305e3290dea3b197301f7824a14c5fa6f
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 "GrCustomStage.h" 12#include "GrGLProgramStage.h" 13#include "gl/GrGLShaderBuilder.h" 14#include "GrGLShaderVar.h" 15#include "GrProgramStageFactory.h" 16#include "SkTrace.h" 17#include "SkXfermode.h" 18 19namespace { 20 21enum { 22 /// Used to mark a StageUniLocation field that should be bound 23 /// to a uniform during getUniformLocationsAndInitCache(). 24 kUseUniform = 2000 25}; 26 27} // namespace 28 29#define PRINT_SHADERS 0 30 31typedef GrGLProgram::ProgramDesc::StageDesc StageDesc; 32 33#define VIEW_MATRIX_NAME "uViewM" 34 35#define POS_ATTR_NAME "aPosition" 36#define COL_ATTR_NAME "aColor" 37#define COV_ATTR_NAME "aCoverage" 38#define EDGE_ATTR_NAME "aEdge" 39#define COL_UNI_NAME "uColor" 40#define COV_UNI_NAME "uCoverage" 41#define EDGES_UNI_NAME "uEdges" 42#define COL_FILTER_UNI_NAME "uColorFilter" 43#define COL_MATRIX_UNI_NAME "uColorMatrix" 44#define COL_MATRIX_VEC_UNI_NAME "uColorMatrixVec" 45 46namespace { 47inline void tex_attr_name(int coordIdx, GrStringBuilder* s) { 48 *s = "aTexCoord"; 49 s->appendS32(coordIdx); 50} 51 52inline const char* float_vector_type_str(int count) { 53 return GrGLShaderVar::TypeString(GrSLFloatVectorType(count)); 54} 55 56inline const char* vector_all_coords(int count) { 57 static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"}; 58 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL)); 59 return ALL[count]; 60} 61 62inline const char* all_ones_vec(int count) { 63 static const char* ONESVEC[] = {"ERROR", "1.0", "vec2(1,1)", 64 "vec3(1,1,1)", "vec4(1,1,1,1)"}; 65 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ONESVEC)); 66 return ONESVEC[count]; 67} 68 69inline const char* all_zeros_vec(int count) { 70 static const char* ZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)", 71 "vec3(0,0,0)", "vec4(0,0,0,0)"}; 72 GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ZEROSVEC)); 73 return ZEROSVEC[count]; 74} 75 76inline const char* declared_color_output_name() { return "fsColorOut"; } 77inline const char* dual_source_output_name() { return "dualSourceOut"; } 78 79inline void tex_matrix_name(int stage, GrStringBuilder* s) { 80 *s = "uTexM"; 81 s->appendS32(stage); 82} 83 84inline void normalized_texel_size_name(int stage, GrStringBuilder* s) { 85 *s = "uTexelSize"; 86 s->appendS32(stage); 87} 88 89inline void sampler_name(int stage, GrStringBuilder* s) { 90 *s = "uSampler"; 91 s->appendS32(stage); 92} 93 94inline void radial2_param_name(int stage, GrStringBuilder* s) { 95 *s = "uRadial2Params"; 96 s->appendS32(stage); 97} 98 99inline void convolve_param_names(int stage, GrStringBuilder* k, GrStringBuilder* i) { 100 *k = "uKernel"; 101 k->appendS32(stage); 102 *i = "uImageIncrement"; 103 i->appendS32(stage); 104} 105 106inline void image_increment_param_name(int stage, GrStringBuilder* i) { 107 *i = "uImageIncrement"; 108 i->appendS32(stage); 109} 110 111inline void tex_domain_name(int stage, GrStringBuilder* s) { 112 *s = "uTexDom"; 113 s->appendS32(stage); 114} 115} 116 117GrGLProgram::GrGLProgram() { 118} 119 120GrGLProgram::~GrGLProgram() { 121} 122 123void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, 124 GrBlendCoeff* dstCoeff) const { 125 switch (fProgramDesc.fDualSrcOutput) { 126 case ProgramDesc::kNone_DualSrcOutput: 127 break; 128 // the prog will write a coverage value to the secondary 129 // output and the dst is blended by one minus that value. 130 case ProgramDesc::kCoverage_DualSrcOutput: 131 case ProgramDesc::kCoverageISA_DualSrcOutput: 132 case ProgramDesc::kCoverageISC_DualSrcOutput: 133 *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_BlendCoeff; 134 break; 135 default: 136 GrCrash("Unexpected dual source blend output"); 137 break; 138 } 139} 140 141// assigns modulation of two vars to an output var 142// vars can be vec4s or floats (or one of each) 143// result is always vec4 144// if either var is "" then assign to the other var 145// if both are "" then assign all ones 146static inline void modulate_helper(const char* outputVar, 147 const char* var0, 148 const char* var1, 149 GrStringBuilder* code) { 150 GrAssert(NULL != outputVar); 151 GrAssert(NULL != var0); 152 GrAssert(NULL != var1); 153 GrAssert(NULL != code); 154 155 bool has0 = '\0' != *var0; 156 bool has1 = '\0' != *var1; 157 158 if (!has0 && !has1) { 159 code->appendf("\t%s = %s;\n", outputVar, all_ones_vec(4)); 160 } else if (!has0) { 161 code->appendf("\t%s = vec4(%s);\n", outputVar, var1); 162 } else if (!has1) { 163 code->appendf("\t%s = vec4(%s);\n", outputVar, var0); 164 } else { 165 code->appendf("\t%s = vec4(%s * %s);\n", outputVar, var0, var1); 166 } 167} 168 169// assigns addition of two vars to an output var 170// vars can be vec4s or floats (or one of each) 171// result is always vec4 172// if either var is "" then assign to the other var 173// if both are "" then assign all zeros 174static inline void add_helper(const char* outputVar, 175 const char* var0, 176 const char* var1, 177 GrStringBuilder* code) { 178 GrAssert(NULL != outputVar); 179 GrAssert(NULL != var0); 180 GrAssert(NULL != var1); 181 GrAssert(NULL != code); 182 183 bool has0 = '\0' != *var0; 184 bool has1 = '\0' != *var1; 185 186 if (!has0 && !has1) { 187 code->appendf("\t%s = %s;\n", outputVar, all_zeros_vec(4)); 188 } else if (!has0) { 189 code->appendf("\t%s = vec4(%s);\n", outputVar, var1); 190 } else if (!has1) { 191 code->appendf("\t%s = vec4(%s);\n", outputVar, var0); 192 } else { 193 code->appendf("\t%s = vec4(%s + %s);\n", outputVar, var0, var1); 194 } 195} 196 197// given two blend coeffecients determine whether the src 198// and/or dst computation can be omitted. 199static inline void needBlendInputs(SkXfermode::Coeff srcCoeff, 200 SkXfermode::Coeff dstCoeff, 201 bool* needSrcValue, 202 bool* needDstValue) { 203 if (SkXfermode::kZero_Coeff == srcCoeff) { 204 switch (dstCoeff) { 205 // these all read the src 206 case SkXfermode::kSC_Coeff: 207 case SkXfermode::kISC_Coeff: 208 case SkXfermode::kSA_Coeff: 209 case SkXfermode::kISA_Coeff: 210 *needSrcValue = true; 211 break; 212 default: 213 *needSrcValue = false; 214 break; 215 } 216 } else { 217 *needSrcValue = true; 218 } 219 if (SkXfermode::kZero_Coeff == dstCoeff) { 220 switch (srcCoeff) { 221 // these all read the dst 222 case SkXfermode::kDC_Coeff: 223 case SkXfermode::kIDC_Coeff: 224 case SkXfermode::kDA_Coeff: 225 case SkXfermode::kIDA_Coeff: 226 *needDstValue = true; 227 break; 228 default: 229 *needDstValue = false; 230 break; 231 } 232 } else { 233 *needDstValue = true; 234 } 235} 236 237/** 238 * Create a blend_coeff * value string to be used in shader code. Sets empty 239 * string if result is trivially zero. 240 */ 241static void blendTermString(GrStringBuilder* str, SkXfermode::Coeff coeff, 242 const char* src, const char* dst, 243 const char* value) { 244 switch (coeff) { 245 case SkXfermode::kZero_Coeff: /** 0 */ 246 *str = ""; 247 break; 248 case SkXfermode::kOne_Coeff: /** 1 */ 249 *str = value; 250 break; 251 case SkXfermode::kSC_Coeff: 252 str->printf("(%s * %s)", src, value); 253 break; 254 case SkXfermode::kISC_Coeff: 255 str->printf("((%s - %s) * %s)", all_ones_vec(4), src, value); 256 break; 257 case SkXfermode::kDC_Coeff: 258 str->printf("(%s * %s)", dst, value); 259 break; 260 case SkXfermode::kIDC_Coeff: 261 str->printf("((%s - %s) * %s)", all_ones_vec(4), dst, value); 262 break; 263 case SkXfermode::kSA_Coeff: /** src alpha */ 264 str->printf("(%s.a * %s)", src, value); 265 break; 266 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 267 str->printf("((1.0 - %s.a) * %s)", src, value); 268 break; 269 case SkXfermode::kDA_Coeff: /** dst alpha */ 270 str->printf("(%s.a * %s)", dst, value); 271 break; 272 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 273 str->printf("((1.0 - %s.a) * %s)", dst, value); 274 break; 275 default: 276 GrCrash("Unexpected xfer coeff."); 277 break; 278 } 279} 280/** 281 * Adds a line to the fragment shader code which modifies the color by 282 * the specified color filter. 283 */ 284static void addColorFilter(GrStringBuilder* fsCode, const char * outputVar, 285 SkXfermode::Coeff uniformCoeff, 286 SkXfermode::Coeff colorCoeff, 287 const char* inColor) { 288 GrStringBuilder colorStr, constStr; 289 blendTermString(&colorStr, colorCoeff, COL_FILTER_UNI_NAME, 290 inColor, inColor); 291 blendTermString(&constStr, uniformCoeff, COL_FILTER_UNI_NAME, 292 inColor, COL_FILTER_UNI_NAME); 293 294 add_helper(outputVar, colorStr.c_str(), constStr.c_str(), fsCode); 295} 296/** 297 * Adds code to the fragment shader code which modifies the color by 298 * the specified color matrix. 299 */ 300static void addColorMatrix(GrStringBuilder* fsCode, const char * outputVar, 301 const char* inColor) { 302 fsCode->appendf("\t%s = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n", outputVar, COL_MATRIX_UNI_NAME, inColor, inColor, inColor, COL_MATRIX_VEC_UNI_NAME); 303 fsCode->appendf("\t%s.rgb *= %s.a;\n", outputVar, outputVar); 304} 305 306void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, 307 GrVertexLayout layout, 308 CachedData* programData, 309 GrStringBuilder* coverageVar, 310 GrGLShaderBuilder* segments) const { 311 if (layout & GrDrawTarget::kEdge_VertexLayoutBit) { 312 const char *vsName, *fsName; 313 segments->appendVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); 314 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 315 GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME); 316 segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); 317 switch (fProgramDesc.fVertexEdgeType) { 318 case GrDrawState::kHairLine_EdgeType: 319 segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName); 320 segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 321 break; 322 case GrDrawState::kQuad_EdgeType: 323 segments->fFSCode.append("\tfloat edgeAlpha;\n"); 324 // keep the derivative instructions outside the conditional 325 segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 326 segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 327 segments->fFSCode.appendf("\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 328 // today we know z and w are in device space. We could use derivatives 329 segments->fFSCode.appendf("\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, fsName); 330 segments->fFSCode.append ("\t} else {\n"); 331 segments->fFSCode.appendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 332 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 333 fsName, fsName); 334 segments->fFSCode.appendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 335 segments->fFSCode.append("\t\tedgeAlpha = clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n" 336 "\t}\n"); 337 if (kES2_GrGLBinding == gl.binding()) { 338 segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 339 } 340 break; 341 case GrDrawState::kHairQuad_EdgeType: 342 segments->fFSCode.appendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 343 segments->fFSCode.appendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 344 segments->fFSCode.appendf("\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 345 "\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 346 fsName, fsName); 347 segments->fFSCode.appendf("\tfloat edgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, fsName); 348 segments->fFSCode.append("\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 349 segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 350 if (kES2_GrGLBinding == gl.binding()) { 351 segments->fHeader.printf("#extension GL_OES_standard_derivatives: enable\n"); 352 } 353 break; 354 case GrDrawState::kCircle_EdgeType: 355 segments->fFSCode.append("\tfloat edgeAlpha;\n"); 356 segments->fFSCode.appendf("\tfloat d = distance(gl_FragCoord.xy, %s.xy);\n", fsName); 357 segments->fFSCode.appendf("\tfloat outerAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName); 358 segments->fFSCode.appendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName); 359 segments->fFSCode.append("\tedgeAlpha = outerAlpha * innerAlpha;\n"); 360 break; 361 default: 362 GrCrash("Unknown Edge Type!"); 363 break; 364 } 365 *coverageVar = "edgeAlpha"; 366 } else { 367 coverageVar->reset(); 368 } 369} 370 371namespace { 372 373void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, 374 GrGLProgram::CachedData* programData, 375 GrGLShaderBuilder* segments, 376 GrStringBuilder* inColor) { 377 switch (colorInput) { 378 case GrGLProgram::ProgramDesc::kAttribute_ColorInput: { 379 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 380 GrGLShaderVar::kAttribute_TypeModifier, 381 COL_ATTR_NAME); 382 const char *vsName, *fsName; 383 segments->appendVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); 384 segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); 385 *inColor = fsName; 386 } break; 387 case GrGLProgram::ProgramDesc::kUniform_ColorInput: 388 segments->fFSUnis.push_back().set(kVec4f_GrSLType, 389 GrGLShaderVar::kUniform_TypeModifier, 390 COL_UNI_NAME); 391 programData->fUniLocations.fColorUni = kUseUniform; 392 *inColor = COL_UNI_NAME; 393 break; 394 case GrGLProgram::ProgramDesc::kTransBlack_ColorInput: 395 GrAssert(!"needComputedColor should be false."); 396 break; 397 case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput: 398 break; 399 default: 400 GrCrash("Unknown color type."); 401 break; 402 } 403} 404 405void genAttributeCoverage(GrGLShaderBuilder* segments, 406 GrStringBuilder* inOutCoverage) { 407 segments->fVSAttrs.push_back().set(kVec4f_GrSLType, 408 GrGLShaderVar::kAttribute_TypeModifier, 409 COV_ATTR_NAME); 410 const char *vsName, *fsName; 411 segments->appendVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); 412 segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName); 413 if (inOutCoverage->size()) { 414 segments->fFSCode.appendf("\tvec4 attrCoverage = %s * %s;\n", 415 fsName, inOutCoverage->c_str()); 416 *inOutCoverage = "attrCoverage"; 417 } else { 418 *inOutCoverage = fsName; 419 } 420} 421 422void genUniformCoverage(GrGLShaderBuilder* segments, 423 GrGLProgram::CachedData* programData, 424 GrStringBuilder* inOutCoverage) { 425 segments->fFSUnis.push_back().set(kVec4f_GrSLType, 426 GrGLShaderVar::kUniform_TypeModifier, 427 COV_UNI_NAME); 428 programData->fUniLocations.fCoverageUni = kUseUniform; 429 if (inOutCoverage->size()) { 430 segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", 431 COV_UNI_NAME, inOutCoverage->c_str()); 432 *inOutCoverage = "uniCoverage"; 433 } else { 434 *inOutCoverage = COV_UNI_NAME; 435 } 436} 437 438} 439 440void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl, 441 GrGLShaderBuilder* segments) const { 442#if GR_GL_EXPERIMENTAL_GS 443 if (fProgramDesc.fExperimentalGS) { 444 GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration); 445 segments->fGSHeader.append("layout(triangles) in;\n" 446 "layout(triangle_strip, max_vertices = 6) out;\n"); 447 segments->fGSCode.append("void main() {\n" 448 "\tfor (int i = 0; i < 3; ++i) {\n" 449 "\t\tgl_Position = gl_in[i].gl_Position;\n"); 450 if (this->fProgramDesc.fEmitsPointSize) { 451 segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n"); 452 } 453 GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count()); 454 int count = segments->fGSInputs.count(); 455 for (int i = 0; i < count; ++i) { 456 segments->fGSCode.appendf("\t\t%s = %s[i];\n", 457 segments->fGSOutputs[i].getName().c_str(), 458 segments->fGSInputs[i].getName().c_str()); 459 } 460 segments->fGSCode.append("\t\tEmitVertex();\n" 461 "\t}\n" 462 "\tEndPrimitive();\n" 463 "}\n"); 464 } 465#endif 466} 467 468const char* GrGLProgram::adjustInColor(const GrStringBuilder& inColor) const { 469 if (inColor.size()) { 470 return inColor.c_str(); 471 } else { 472 if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) { 473 return all_ones_vec(4); 474 } else { 475 return all_zeros_vec(4); 476 } 477 } 478} 479 480// If this destructor is in the header file, we must include GrGLProgramStage 481// instead of just forward-declaring it. 482GrGLProgram::CachedData::~CachedData() { 483 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 484 delete fCustomStage[i]; 485 } 486} 487 488 489bool GrGLProgram::genProgram(const GrGLContextInfo& gl, 490 GrCustomStage** customStages, 491 GrGLProgram::CachedData* programData) const { 492 GrGLShaderBuilder segments; 493 const uint32_t& layout = fProgramDesc.fVertexLayout; 494 495 programData->fUniLocations.reset(); 496 497#if GR_GL_EXPERIMENTAL_GS 498 segments.fUsesGS = fProgramDesc.fExperimentalGS; 499#endif 500 501 SkXfermode::Coeff colorCoeff, uniformCoeff; 502 bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled); 503 // The rest of transfer mode color filters have not been implemented 504 if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { 505 GR_DEBUGCODE(bool success =) 506 SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> 507 (fProgramDesc.fColorFilterXfermode), 508 &uniformCoeff, &colorCoeff); 509 GR_DEBUGASSERT(success); 510 } else { 511 colorCoeff = SkXfermode::kOne_Coeff; 512 uniformCoeff = SkXfermode::kZero_Coeff; 513 } 514 515 // no need to do the color filter / matrix at all if coverage is 0. The 516 // output color is scaled by the coverage. All the dual source outputs are 517 // scaled by the coverage as well. 518 if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) { 519 colorCoeff = SkXfermode::kZero_Coeff; 520 uniformCoeff = SkXfermode::kZero_Coeff; 521 applyColorMatrix = false; 522 } 523 524 // If we know the final color is going to be all zeros then we can 525 // simplify the color filter coeffecients. needComputedColor will then 526 // come out false below. 527 if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) { 528 colorCoeff = SkXfermode::kZero_Coeff; 529 if (SkXfermode::kDC_Coeff == uniformCoeff || 530 SkXfermode::kDA_Coeff == uniformCoeff) { 531 uniformCoeff = SkXfermode::kZero_Coeff; 532 } else if (SkXfermode::kIDC_Coeff == uniformCoeff || 533 SkXfermode::kIDA_Coeff == uniformCoeff) { 534 uniformCoeff = SkXfermode::kOne_Coeff; 535 } 536 } 537 538 bool needColorFilterUniform; 539 bool needComputedColor; 540 needBlendInputs(uniformCoeff, colorCoeff, 541 &needColorFilterUniform, &needComputedColor); 542 543 // the dual source output has no canonical var name, have to 544 // declare an output, which is incompatible with gl_FragColor/gl_FragData. 545 bool dualSourceOutputWritten = false; 546 segments.fHeader.printf(GrGetGLSLVersionDecl(gl.binding(), 547 gl.glslGeneration())); 548 549 GrGLShaderVar colorOutput; 550 bool isColorDeclared = GrGLSLSetupFSColorOuput(gl.glslGeneration(), 551 declared_color_output_name(), 552 &colorOutput); 553 if (isColorDeclared) { 554 segments.fFSOutputs.push_back(colorOutput); 555 } 556 557 segments.fVSUnis.push_back().set(kMat33f_GrSLType, 558 GrGLShaderVar::kUniform_TypeModifier, VIEW_MATRIX_NAME); 559 programData->fUniLocations.fViewMatrixUni = kUseUniform; 560 561 segments.fVSAttrs.push_back().set(kVec2f_GrSLType, 562 GrGLShaderVar::kAttribute_TypeModifier, POS_ATTR_NAME); 563 564 segments.fVSCode.append( 565 "void main() {\n" 566 "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3("POS_ATTR_NAME", 1);\n" 567 "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n"); 568 569 // incoming color to current stage being processed. 570 GrStringBuilder inColor; 571 572 if (needComputedColor) { 573 genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput, 574 programData, &segments, &inColor); 575 } 576 577 // we output point size in the GS if present 578 if (fProgramDesc.fEmitsPointSize && !segments.fUsesGS){ 579 segments.fVSCode.append("\tgl_PointSize = 1.0;\n"); 580 } 581 582 segments.fFSCode.append("void main() {\n"); 583 584 // add texture coordinates that are used to the list of vertex attr decls 585 GrStringBuilder texCoordAttrs[GrDrawState::kMaxTexCoords]; 586 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 587 if (GrDrawTarget::VertexUsesTexCoordIdx(t, layout)) { 588 tex_attr_name(t, texCoordAttrs + t); 589 segments.fVSAttrs.push_back().set(kVec2f_GrSLType, 590 GrGLShaderVar::kAttribute_TypeModifier, 591 texCoordAttrs[t].c_str()); 592 } 593 } 594 595 /////////////////////////////////////////////////////////////////////////// 596 // We need to convert generic effect representations to GL-specific 597 // backends so they can be accesseed in genStageCode() and in subsequent, 598 // uses of programData, but it's safest to do so below when we're *sure* 599 // we need them. 600 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 601 programData->fCustomStage[s] = NULL; 602 } 603 604 /////////////////////////////////////////////////////////////////////////// 605 // compute the final color 606 607 // if we have color stages string them together, feeding the output color 608 // of each to the next and generating code for each stage. 609 if (needComputedColor) { 610 GrStringBuilder outColor; 611 for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) { 612 if (fProgramDesc.fStages[s].isEnabled()) { 613 // create var to hold stage result 614 outColor = "color"; 615 outColor.appendS32(s); 616 segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); 617 618 const char* inCoords; 619 // figure out what our input coords are 620 if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & 621 layout) { 622 inCoords = POS_ATTR_NAME; 623 } else { 624 int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); 625 // we better have input tex coordinates if stage is enabled. 626 GrAssert(tcIdx >= 0); 627 GrAssert(texCoordAttrs[tcIdx].size()); 628 inCoords = texCoordAttrs[tcIdx].c_str(); 629 } 630 631 if (NULL != customStages[s]) { 632 const GrProgramStageFactory& factory = 633 customStages[s]->getFactory(); 634 programData->fCustomStage[s] = 635 factory.createGLInstance(customStages[s]); 636 } 637 this->genStageCode(gl, 638 s, 639 fProgramDesc.fStages[s], 640 inColor.size() ? inColor.c_str() : NULL, 641 outColor.c_str(), 642 inCoords, 643 &segments, 644 &programData->fUniLocations.fStages[s], 645 programData->fCustomStage[s]); 646 inColor = outColor; 647 } 648 } 649 } 650 651 // if have all ones or zeros for the "dst" input to the color filter then we 652 // may be able to make additional optimizations. 653 if (needColorFilterUniform && needComputedColor && !inColor.size()) { 654 GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput); 655 bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || 656 SkXfermode::kIDA_Coeff == uniformCoeff; 657 if (uniformCoeffIsZero) { 658 uniformCoeff = SkXfermode::kZero_Coeff; 659 bool bogus; 660 needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, 661 &needColorFilterUniform, &bogus); 662 } 663 } 664 if (needColorFilterUniform) { 665 segments.fFSUnis.push_back().set(kVec4f_GrSLType, 666 GrGLShaderVar::kUniform_TypeModifier, 667 COL_FILTER_UNI_NAME); 668 programData->fUniLocations.fColorFilterUni = kUseUniform; 669 } 670 bool wroteFragColorZero = false; 671 if (SkXfermode::kZero_Coeff == uniformCoeff && 672 SkXfermode::kZero_Coeff == colorCoeff && 673 !applyColorMatrix) { 674 segments.fFSCode.appendf("\t%s = %s;\n", 675 colorOutput.getName().c_str(), 676 all_zeros_vec(4)); 677 wroteFragColorZero = true; 678 } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) { 679 segments.fFSCode.append("\tvec4 filteredColor;\n"); 680 const char* color = adjustInColor(inColor); 681 addColorFilter(&segments.fFSCode, "filteredColor", uniformCoeff, 682 colorCoeff, color); 683 inColor = "filteredColor"; 684 } 685 if (applyColorMatrix) { 686 segments.fFSUnis.push_back().set(kMat44f_GrSLType, 687 GrGLShaderVar::kUniform_TypeModifier, 688 COL_MATRIX_UNI_NAME); 689 segments.fFSUnis.push_back().set(kVec4f_GrSLType, 690 GrGLShaderVar::kUniform_TypeModifier, 691 COL_MATRIX_VEC_UNI_NAME); 692 programData->fUniLocations.fColorMatrixUni = kUseUniform; 693 programData->fUniLocations.fColorMatrixVecUni = kUseUniform; 694 segments.fFSCode.append("\tvec4 matrixedColor;\n"); 695 const char* color = adjustInColor(inColor); 696 addColorMatrix(&segments.fFSCode, "matrixedColor", color); 697 inColor = "matrixedColor"; 698 } 699 700 /////////////////////////////////////////////////////////////////////////// 701 // compute the partial coverage (coverage stages and edge aa) 702 703 GrStringBuilder inCoverage; 704 bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput == 705 fProgramDesc.fCoverageInput; 706 // we don't need to compute coverage at all if we know the final shader 707 // output will be zero and we don't have a dual src blend output. 708 if (!wroteFragColorZero || 709 ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) { 710 711 if (!coverageIsZero) { 712 this->genEdgeCoverage(gl, 713 layout, 714 programData, 715 &inCoverage, 716 &segments); 717 718 switch (fProgramDesc.fCoverageInput) { 719 case ProgramDesc::kSolidWhite_ColorInput: 720 // empty string implies solid white 721 break; 722 case ProgramDesc::kAttribute_ColorInput: 723 genAttributeCoverage(&segments, &inCoverage); 724 break; 725 case ProgramDesc::kUniform_ColorInput: 726 genUniformCoverage(&segments, programData, &inCoverage); 727 break; 728 default: 729 GrCrash("Unexpected input coverage."); 730 } 731 732 GrStringBuilder outCoverage; 733 const int& startStage = fProgramDesc.fFirstCoverageStage; 734 for (int s = startStage; s < GrDrawState::kNumStages; ++s) { 735 if (fProgramDesc.fStages[s].isEnabled()) { 736 // create var to hold stage output 737 outCoverage = "coverage"; 738 outCoverage.appendS32(s); 739 segments.fFSCode.appendf("\tvec4 %s;\n", 740 outCoverage.c_str()); 741 742 const char* inCoords; 743 // figure out what our input coords are 744 if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & 745 layout) { 746 inCoords = POS_ATTR_NAME; 747 } else { 748 int tcIdx = 749 GrDrawTarget::VertexTexCoordsForStage(s, layout); 750 // we better have input tex coordinates if stage is 751 // enabled. 752 GrAssert(tcIdx >= 0); 753 GrAssert(texCoordAttrs[tcIdx].size()); 754 inCoords = texCoordAttrs[tcIdx].c_str(); 755 } 756 757 if (NULL != customStages[s]) { 758 const GrProgramStageFactory& factory = 759 customStages[s]->getFactory(); 760 programData->fCustomStage[s] = 761 factory.createGLInstance(customStages[s]); 762 } 763 this->genStageCode(gl, s, 764 fProgramDesc.fStages[s], 765 inCoverage.size() ? inCoverage.c_str() : NULL, 766 outCoverage.c_str(), 767 inCoords, 768 &segments, 769 &programData->fUniLocations.fStages[s], 770 programData->fCustomStage[s]); 771 inCoverage = outCoverage; 772 } 773 } 774 } 775 if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) { 776 segments.fFSOutputs.push_back().set(kVec4f_GrSLType, 777 GrGLShaderVar::kOut_TypeModifier, 778 dual_source_output_name()); 779 bool outputIsZero = coverageIsZero; 780 GrStringBuilder coeff; 781 if (!outputIsZero && 782 ProgramDesc::kCoverage_DualSrcOutput != 783 fProgramDesc.fDualSrcOutput && !wroteFragColorZero) { 784 if (!inColor.size()) { 785 outputIsZero = true; 786 } else { 787 if (fProgramDesc.fDualSrcOutput == 788 ProgramDesc::kCoverageISA_DualSrcOutput) { 789 coeff.printf("(1 - %s.a)", inColor.c_str()); 790 } else { 791 coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); 792 } 793 } 794 } 795 if (outputIsZero) { 796 segments.fFSCode.appendf("\t%s = %s;\n", 797 dual_source_output_name(), 798 all_zeros_vec(4)); 799 } else { 800 modulate_helper(dual_source_output_name(), 801 coeff.c_str(), 802 inCoverage.c_str(), 803 &segments.fFSCode); 804 } 805 dualSourceOutputWritten = true; 806 } 807 } 808 809 /////////////////////////////////////////////////////////////////////////// 810 // combine color and coverage as frag color 811 812 if (!wroteFragColorZero) { 813 if (coverageIsZero) { 814 segments.fFSCode.appendf("\t%s = %s;\n", 815 colorOutput.getName().c_str(), 816 all_zeros_vec(4)); 817 } else { 818 modulate_helper(colorOutput.getName().c_str(), 819 inColor.c_str(), 820 inCoverage.c_str(), 821 &segments.fFSCode); 822 } 823 if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig == 824 fProgramDesc.fOutputConfig) { 825 segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n", 826 colorOutput.getName().c_str(), 827 colorOutput.getName().c_str(), 828 colorOutput.getName().c_str(), 829 colorOutput.getName().c_str(), 830 colorOutput.getName().c_str()); 831 } else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig == 832 fProgramDesc.fOutputConfig) { 833 segments.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n", 834 colorOutput.getName().c_str(), 835 colorOutput.getName().c_str(), 836 colorOutput.getName().c_str(), 837 colorOutput.getName().c_str(), 838 colorOutput.getName().c_str()); 839 } 840 } 841 842 segments.fVSCode.append("}\n"); 843 segments.fFSCode.append("}\n"); 844 845 /////////////////////////////////////////////////////////////////////////// 846 // insert GS 847#if GR_DEBUG 848 this->genGeometryShader(gl, &segments); 849#endif 850 851 /////////////////////////////////////////////////////////////////////////// 852 // compile and setup attribs and unis 853 854 if (!CompileShaders(gl, segments, programData)) { 855 return false; 856 } 857 858 if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs, 859 isColorDeclared, 860 dualSourceOutputWritten, 861 programData)) { 862 return false; 863 } 864 865 this->getUniformLocationsAndInitCache(gl, programData); 866 867 return true; 868} 869 870namespace { 871 872inline void expand_decls(const VarArray& vars, 873 const GrGLContextInfo& gl, 874 GrStringBuilder* string) { 875 const int count = vars.count(); 876 for (int i = 0; i < count; ++i) { 877 vars[i].appendDecl(gl, string); 878 } 879} 880 881inline void print_shader(int stringCnt, 882 const char** strings, 883 int* stringLengths) { 884 for (int i = 0; i < stringCnt; ++i) { 885 if (NULL == stringLengths || stringLengths[i] < 0) { 886 GrPrintf(strings[i]); 887 } else { 888 GrPrintf("%.*s", stringLengths[i], strings[i]); 889 } 890 } 891} 892 893typedef SkTArray<const char*, true> StrArray; 894#define PREALLOC_STR_ARRAY(N) SkSTArray<(N), const char*, true> 895 896typedef SkTArray<int, true> LengthArray; 897#define PREALLOC_LENGTH_ARRAY(N) SkSTArray<(N), int, true> 898 899// these shouldn't relocate 900typedef GrTAllocator<GrStringBuilder> TempArray; 901#define PREALLOC_TEMP_ARRAY(N) GrSTAllocator<(N), GrStringBuilder> 902 903inline void append_string(const GrStringBuilder& str, 904 StrArray* strings, 905 LengthArray* lengths) { 906 int length = (int) str.size(); 907 if (length) { 908 strings->push_back(str.c_str()); 909 lengths->push_back(length); 910 } 911 GrAssert(strings->count() == lengths->count()); 912} 913 914inline void append_decls(const VarArray& vars, 915 const GrGLContextInfo& gl, 916 StrArray* strings, 917 LengthArray* lengths, 918 TempArray* temp) { 919 expand_decls(vars, gl, &temp->push_back()); 920 append_string(temp->back(), strings, lengths); 921} 922 923} 924 925bool GrGLProgram::CompileShaders(const GrGLContextInfo& gl, 926 const GrGLShaderBuilder& segments, 927 CachedData* programData) { 928 enum { kPreAllocStringCnt = 8 }; 929 930 PREALLOC_STR_ARRAY(kPreAllocStringCnt) strs; 931 PREALLOC_LENGTH_ARRAY(kPreAllocStringCnt) lengths; 932 PREALLOC_TEMP_ARRAY(kPreAllocStringCnt) temps; 933 934 GrStringBuilder unis; 935 GrStringBuilder inputs; 936 GrStringBuilder outputs; 937 938 append_string(segments.fHeader, &strs, &lengths); 939 append_decls(segments.fVSUnis, gl, &strs, &lengths, &temps); 940 append_decls(segments.fVSAttrs, gl, &strs, &lengths, &temps); 941 append_decls(segments.fVSOutputs, gl, &strs, &lengths, &temps); 942 append_string(segments.fVSCode, &strs, &lengths); 943 944#if PRINT_SHADERS 945 print_shader(strs.count(), &strs[0], &lengths[0]); 946 GrPrintf("\n"); 947#endif 948 949 programData->fVShaderID = 950 CompileShader(gl, GR_GL_VERTEX_SHADER, strs.count(), 951 &strs[0], &lengths[0]); 952 953 if (!programData->fVShaderID) { 954 return false; 955 } 956 if (segments.fUsesGS) { 957 strs.reset(); 958 lengths.reset(); 959 temps.reset(); 960 append_string(segments.fHeader, &strs, &lengths); 961 append_string(segments.fGSHeader, &strs, &lengths); 962 append_decls(segments.fGSInputs, gl, &strs, &lengths, &temps); 963 append_decls(segments.fGSOutputs, gl, &strs, &lengths, &temps); 964 append_string(segments.fGSCode, &strs, &lengths); 965#if PRINT_SHADERS 966 print_shader(strs.count(), &strs[0], &lengths[0]); 967 GrPrintf("\n"); 968#endif 969 programData->fGShaderID = 970 CompileShader(gl, GR_GL_GEOMETRY_SHADER, strs.count(), 971 &strs[0], &lengths[0]); 972 } else { 973 programData->fGShaderID = 0; 974 } 975 976 strs.reset(); 977 lengths.reset(); 978 temps.reset(); 979 980 append_string(segments.fHeader, &strs, &lengths); 981 GrStringBuilder precisionStr(GrGetGLSLShaderPrecisionDecl(gl.binding())); 982 append_string(precisionStr, &strs, &lengths); 983 append_decls(segments.fFSUnis, gl, &strs, &lengths, &temps); 984 append_decls(segments.fFSInputs, gl, &strs, &lengths, &temps); 985 // We shouldn't have declared outputs on 1.10 986 GrAssert(k110_GrGLSLGeneration != gl.glslGeneration() || 987 segments.fFSOutputs.empty()); 988 append_decls(segments.fFSOutputs, gl, &strs, &lengths, &temps); 989 append_string(segments.fFSFunctions, &strs, &lengths); 990 append_string(segments.fFSCode, &strs, &lengths); 991 992#if PRINT_SHADERS 993 print_shader(strs.count(), &strs[0], &lengths[0]); 994 GrPrintf("\n"); 995#endif 996 997 programData->fFShaderID = 998 CompileShader(gl, GR_GL_FRAGMENT_SHADER, strs.count(), 999 &strs[0], &lengths[0]); 1000 1001 if (!programData->fFShaderID) { 1002 return false; 1003 } 1004 1005 return true; 1006} 1007 1008#define GL_CALL(X) GR_GL_CALL(gl.interface(), X) 1009#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X) 1010 1011GrGLuint GrGLProgram::CompileShader(const GrGLContextInfo& gl, 1012 GrGLenum type, 1013 int stringCnt, 1014 const char** strings, 1015 int* stringLengths) { 1016 SK_TRACE_EVENT1("GrGLProgram::CompileShader", 1017 "stringCount", SkStringPrintf("%i", stringCnt).c_str()); 1018 1019 GrGLuint shader; 1020 GL_CALL_RET(shader, CreateShader(type)); 1021 if (0 == shader) { 1022 return 0; 1023 } 1024 1025 GrGLint compiled = GR_GL_INIT_ZERO; 1026 GL_CALL(ShaderSource(shader, stringCnt, strings, stringLengths)); 1027 GL_CALL(CompileShader(shader)); 1028 GL_CALL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); 1029 1030 if (!compiled) { 1031 GrGLint infoLen = GR_GL_INIT_ZERO; 1032 GL_CALL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); 1033 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 1034 if (infoLen > 0) { 1035 // retrieve length even though we don't need it to workaround 1036 // bug in chrome cmd buffer param validation. 1037 GrGLsizei length = GR_GL_INIT_ZERO; 1038 GL_CALL(GetShaderInfoLog(shader, infoLen+1, 1039 &length, (char*)log.get())); 1040 print_shader(stringCnt, strings, stringLengths); 1041 GrPrintf("\n%s", log.get()); 1042 } 1043 GrAssert(!"Shader compilation failed!"); 1044 GL_CALL(DeleteShader(shader)); 1045 return 0; 1046 } 1047 return shader; 1048} 1049 1050bool GrGLProgram::bindOutputsAttribsAndLinkProgram( 1051 const GrGLContextInfo& gl, 1052 GrStringBuilder texCoordAttrNames[], 1053 bool bindColorOut, 1054 bool bindDualSrcOut, 1055 CachedData* programData) const { 1056 GL_CALL_RET(programData->fProgramID, CreateProgram()); 1057 if (!programData->fProgramID) { 1058 return false; 1059 } 1060 const GrGLint& progID = programData->fProgramID; 1061 1062 GL_CALL(AttachShader(progID, programData->fVShaderID)); 1063 if (programData->fGShaderID) { 1064 GL_CALL(AttachShader(progID, programData->fGShaderID)); 1065 } 1066 GL_CALL(AttachShader(progID, programData->fFShaderID)); 1067 1068 if (bindColorOut) { 1069 GL_CALL(BindFragDataLocation(programData->fProgramID, 1070 0, declared_color_output_name())); 1071 } 1072 if (bindDualSrcOut) { 1073 GL_CALL(BindFragDataLocationIndexed(programData->fProgramID, 1074 0, 1, dual_source_output_name())); 1075 } 1076 1077 // Bind the attrib locations to same values for all shaders 1078 GL_CALL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME)); 1079 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 1080 if (texCoordAttrNames[t].size()) { 1081 GL_CALL(BindAttribLocation(progID, 1082 TexCoordAttributeIdx(t), 1083 texCoordAttrNames[t].c_str())); 1084 } 1085 } 1086 1087 GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME)); 1088 GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME)); 1089 GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); 1090 1091 GL_CALL(LinkProgram(progID)); 1092 1093 GrGLint linked = GR_GL_INIT_ZERO; 1094 GL_CALL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); 1095 if (!linked) { 1096 GrGLint infoLen = GR_GL_INIT_ZERO; 1097 GL_CALL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); 1098 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger 1099 if (infoLen > 0) { 1100 // retrieve length even though we don't need it to workaround 1101 // bug in chrome cmd buffer param validation. 1102 GrGLsizei length = GR_GL_INIT_ZERO; 1103 GL_CALL(GetProgramInfoLog(progID, 1104 infoLen+1, 1105 &length, 1106 (char*)log.get())); 1107 GrPrintf((char*)log.get()); 1108 } 1109 GrAssert(!"Error linking program"); 1110 GL_CALL(DeleteProgram(progID)); 1111 programData->fProgramID = 0; 1112 return false; 1113 } 1114 return true; 1115} 1116 1117void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl, 1118 CachedData* programData) const { 1119 const GrGLint& progID = programData->fProgramID; 1120 1121 if (kUseUniform == programData->fUniLocations.fViewMatrixUni) { 1122 GL_CALL_RET(programData->fUniLocations.fViewMatrixUni, 1123 GetUniformLocation(progID, VIEW_MATRIX_NAME)); 1124 GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni); 1125 } 1126 if (kUseUniform == programData->fUniLocations.fColorUni) { 1127 GL_CALL_RET(programData->fUniLocations.fColorUni, 1128 GetUniformLocation(progID, COL_UNI_NAME)); 1129 GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni); 1130 } 1131 if (kUseUniform == programData->fUniLocations.fColorFilterUni) { 1132 GL_CALL_RET(programData->fUniLocations.fColorFilterUni, 1133 GetUniformLocation(progID, COL_FILTER_UNI_NAME)); 1134 GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni); 1135 } 1136 1137 if (kUseUniform == programData->fUniLocations.fColorMatrixUni) { 1138 GL_CALL_RET(programData->fUniLocations.fColorMatrixUni, 1139 GetUniformLocation(progID, COL_MATRIX_UNI_NAME)); 1140 } 1141 1142 if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) { 1143 GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni, 1144 GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME)); 1145 } 1146 if (kUseUniform == programData->fUniLocations.fCoverageUni) { 1147 GL_CALL_RET(programData->fUniLocations.fCoverageUni, 1148 GetUniformLocation(progID, COV_UNI_NAME)); 1149 GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni); 1150 } 1151 1152 if (kUseUniform == programData->fUniLocations.fEdgesUni) { 1153 GL_CALL_RET(programData->fUniLocations.fEdgesUni, 1154 GetUniformLocation(progID, EDGES_UNI_NAME)); 1155 GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni); 1156 } else { 1157 programData->fUniLocations.fEdgesUni = kUnusedUniform; 1158 } 1159 1160 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 1161 StageUniLocations& locations = programData->fUniLocations.fStages[s]; 1162 if (fProgramDesc.fStages[s].isEnabled()) { 1163 if (kUseUniform == locations.fTextureMatrixUni) { 1164 GrStringBuilder texMName; 1165 tex_matrix_name(s, &texMName); 1166 GL_CALL_RET(locations.fTextureMatrixUni, 1167 GetUniformLocation(progID, texMName.c_str())); 1168 GrAssert(kUnusedUniform != locations.fTextureMatrixUni); 1169 } 1170 1171 if (kUseUniform == locations.fSamplerUni) { 1172 GrStringBuilder samplerName; 1173 sampler_name(s, &samplerName); 1174 GL_CALL_RET(locations.fSamplerUni, 1175 GetUniformLocation(progID,samplerName.c_str())); 1176 GrAssert(kUnusedUniform != locations.fSamplerUni); 1177 } 1178 1179 if (kUseUniform == locations.fNormalizedTexelSizeUni) { 1180 GrStringBuilder texelSizeName; 1181 normalized_texel_size_name(s, &texelSizeName); 1182 GL_CALL_RET(locations.fNormalizedTexelSizeUni, 1183 GetUniformLocation(progID, texelSizeName.c_str())); 1184 GrAssert(kUnusedUniform != locations.fNormalizedTexelSizeUni); 1185 } 1186 1187 if (kUseUniform == locations.fRadial2Uni) { 1188 GrStringBuilder radial2ParamName; 1189 radial2_param_name(s, &radial2ParamName); 1190 GL_CALL_RET(locations.fRadial2Uni, 1191 GetUniformLocation(progID, radial2ParamName.c_str())); 1192 GrAssert(kUnusedUniform != locations.fRadial2Uni); 1193 } 1194 1195 if (kUseUniform == locations.fTexDomUni) { 1196 GrStringBuilder texDomName; 1197 tex_domain_name(s, &texDomName); 1198 GL_CALL_RET(locations.fTexDomUni, 1199 GetUniformLocation(progID, texDomName.c_str())); 1200 GrAssert(kUnusedUniform != locations.fTexDomUni); 1201 } 1202 1203 GrStringBuilder kernelName, imageIncrementName; 1204 convolve_param_names(s, &kernelName, &imageIncrementName); 1205 if (kUseUniform == locations.fKernelUni) { 1206 GL_CALL_RET(locations.fKernelUni, 1207 GetUniformLocation(progID, kernelName.c_str())); 1208 GrAssert(kUnusedUniform != locations.fKernelUni); 1209 } 1210 1211 if (kUseUniform == locations.fImageIncrementUni) { 1212 GL_CALL_RET(locations.fImageIncrementUni, 1213 GetUniformLocation(progID, 1214 imageIncrementName.c_str())); 1215 GrAssert(kUnusedUniform != locations.fImageIncrementUni); 1216 } 1217 1218 if (NULL != programData->fCustomStage[s]) { 1219 programData->fCustomStage[s]-> 1220 initUniforms(gl.interface(), progID); 1221 } 1222 } 1223 } 1224 GL_CALL(UseProgram(progID)); 1225 1226 // init sampler unis and set bogus values for state tracking 1227 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 1228 if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) { 1229 GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); 1230 } 1231 programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); 1232 programData->fRadial2CenterX1[s] = GR_ScalarMax; 1233 programData->fRadial2Radius0[s] = -GR_ScalarMax; 1234 programData->fTextureWidth[s] = -1; 1235 programData->fTextureHeight[s] = -1; 1236 programData->fTextureDomain[s].setEmpty(); 1237 // Must not reset fStageOverride[] here. 1238 } 1239 programData->fViewMatrix = GrMatrix::InvalidMatrix(); 1240 programData->fColor = GrColor_ILLEGAL; 1241 programData->fColorFilterColor = GrColor_ILLEGAL; 1242} 1243 1244//============================================================================ 1245// Stage code generation 1246//============================================================================ 1247 1248namespace { 1249 1250bool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) { 1251 return 1252 (GrGLProgram::StageDesc::kRadial2Gradient_CoordMapping == mapping || 1253 GrGLProgram::StageDesc::kRadial2GradientDegenerate_CoordMapping == mapping); 1254} 1255 1256GrGLShaderVar* genRadialVS(int stageNum, 1257 GrGLShaderBuilder* segments, 1258 GrGLProgram::StageUniLocations* locations, 1259 const char** radial2VaryingVSName, 1260 const char** radial2VaryingFSName, 1261 const char* varyingVSName) { 1262 1263 GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back(); 1264 radial2FSParams->setType(kFloat_GrSLType); 1265 radial2FSParams->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 1266 radial2FSParams->setArrayCount(6); 1267 radial2_param_name(stageNum, radial2FSParams->accessName()); 1268 segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true); 1269 1270 locations->fRadial2Uni = kUseUniform; 1271 1272 // for radial grads without perspective we can pass the linear 1273 // part of the quadratic as a varying. 1274 if (segments->fVaryingDims == segments->fCoordDims) { 1275 GrAssert(2 == segments->fCoordDims); 1276 segments->appendVarying(kFloat_GrSLType, 1277 "Radial2BCoeff", 1278 stageNum, 1279 radial2VaryingVSName, 1280 radial2VaryingFSName); 1281 1282 GrStringBuilder radial2p2; 1283 GrStringBuilder radial2p3; 1284 radial2FSParams->appendArrayAccess(2, &radial2p2); 1285 radial2FSParams->appendArrayAccess(3, &radial2p3); 1286 1287 // r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3]) 1288 const char* r2ParamName = radial2FSParams->getName().c_str(); 1289 segments->fVSCode.appendf("\t%s = 2.0 *(%s * %s.x - %s);\n", 1290 *radial2VaryingVSName, radial2p2.c_str(), 1291 varyingVSName, radial2p3.c_str()); 1292 } 1293 1294 return radial2FSParams; 1295} 1296 1297void genRadial2GradientCoordMapping(int stageNum, 1298 GrGLShaderBuilder* segments, 1299 const char* radial2VaryingFSName, 1300 GrGLShaderVar* radial2Params) { 1301 GrStringBuilder cName("c"); 1302 GrStringBuilder ac4Name("ac4"); 1303 GrStringBuilder rootName("root"); 1304 1305 cName.appendS32(stageNum); 1306 ac4Name.appendS32(stageNum); 1307 rootName.appendS32(stageNum); 1308 1309 GrStringBuilder radial2p0; 1310 GrStringBuilder radial2p1; 1311 GrStringBuilder radial2p2; 1312 GrStringBuilder radial2p3; 1313 GrStringBuilder radial2p4; 1314 GrStringBuilder radial2p5; 1315 radial2Params->appendArrayAccess(0, &radial2p0); 1316 radial2Params->appendArrayAccess(1, &radial2p1); 1317 radial2Params->appendArrayAccess(2, &radial2p2); 1318 radial2Params->appendArrayAccess(3, &radial2p3); 1319 radial2Params->appendArrayAccess(4, &radial2p4); 1320 radial2Params->appendArrayAccess(5, &radial2p5); 1321 1322 // if we were able to interpolate the linear component bVar is the varying 1323 // otherwise compute it 1324 GrStringBuilder bVar; 1325 if (segments->fCoordDims == segments->fVaryingDims) { 1326 bVar = radial2VaryingFSName; 1327 GrAssert(2 == segments->fVaryingDims); 1328 } else { 1329 GrAssert(3 == segments->fVaryingDims); 1330 bVar = "b"; 1331 bVar.appendS32(stageNum); 1332 segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", 1333 bVar.c_str(), radial2p2.c_str(), 1334 segments->fSampleCoords.c_str(), radial2p3.c_str()); 1335 } 1336 1337 // c = (x^2)+(y^2) - params[4] 1338 segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n", 1339 cName.c_str(), segments->fSampleCoords.c_str(), 1340 segments->fSampleCoords.c_str(), 1341 radial2p4.c_str()); 1342 // ac4 = 4.0 * params[0] * c 1343 segments->fFSCode.appendf("\tfloat %s = %s * 4.0 * %s;\n", 1344 ac4Name.c_str(), radial2p0.c_str(), 1345 cName.c_str()); 1346 1347 // root = sqrt(b^2-4ac) 1348 // (abs to avoid exception due to fp precision) 1349 segments->fFSCode.appendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", 1350 rootName.c_str(), bVar.c_str(), bVar.c_str(), 1351 ac4Name.c_str()); 1352 1353 // x coord is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] 1354 // y coord is 0.5 (texture is effectively 1D) 1355 segments->fSampleCoords.printf("vec2((-%s + %s * %s) * %s, 0.5)", 1356 bVar.c_str(), radial2p5.c_str(), 1357 rootName.c_str(), radial2p1.c_str()); 1358 segments->fComplexCoord = true; 1359} 1360 1361void genRadial2GradientDegenerateCoordMapping(int stageNum, 1362 GrGLShaderBuilder* segments, 1363 const char* radial2VaryingFSName, 1364 GrGLShaderVar* radial2Params) { 1365 GrStringBuilder cName("c"); 1366 1367 cName.appendS32(stageNum); 1368 1369 GrStringBuilder radial2p2; 1370 GrStringBuilder radial2p3; 1371 GrStringBuilder radial2p4; 1372 radial2Params->appendArrayAccess(2, &radial2p2); 1373 radial2Params->appendArrayAccess(3, &radial2p3); 1374 radial2Params->appendArrayAccess(4, &radial2p4); 1375 1376 // if we were able to interpolate the linear component bVar is the varying 1377 // otherwise compute it 1378 GrStringBuilder bVar; 1379 if (segments->fCoordDims == segments->fVaryingDims) { 1380 bVar = radial2VaryingFSName; 1381 GrAssert(2 == segments->fVaryingDims); 1382 } else { 1383 GrAssert(3 == segments->fVaryingDims); 1384 bVar = "b"; 1385 bVar.appendS32(stageNum); 1386 segments->fFSCode.appendf("\tfloat %s = 2.0 * (%s * %s.x - %s);\n", 1387 bVar.c_str(), radial2p2.c_str(), 1388 segments->fSampleCoords.c_str(), radial2p3.c_str()); 1389 } 1390 1391 // c = (x^2)+(y^2) - params[4] 1392 segments->fFSCode.appendf("\tfloat %s = dot(%s, %s) - %s;\n", 1393 cName.c_str(), segments->fSampleCoords.c_str(), 1394 segments->fSampleCoords.c_str(), 1395 radial2p4.c_str()); 1396 1397 // x coord is: -c/b 1398 // y coord is 0.5 (texture is effectively 1D) 1399 segments->fSampleCoords.printf("vec2((-%s / %s), 0.5)", cName.c_str(), bVar.c_str()); 1400 segments->fComplexCoord = true; 1401} 1402 1403void gen2x2FS(int stageNum, 1404 GrGLShaderBuilder* segments, 1405 GrGLProgram::StageUniLocations* locations, 1406 const char* samplerName, 1407 const char* texelSizeName, 1408 const char* fsOutColor, 1409 GrStringBuilder& texFunc) { 1410 locations->fNormalizedTexelSizeUni = kUseUniform; 1411 if (segments->fComplexCoord) { 1412 // assign the coord to a var rather than compute 4x. 1413 GrStringBuilder coordVar("tCoord"); 1414 coordVar.appendS32(stageNum); 1415 segments->fFSCode.appendf("\t%s %s = %s;\n", 1416 float_vector_type_str(segments->fCoordDims), 1417 coordVar.c_str(), segments->fSampleCoords.c_str()); 1418 segments->fSampleCoords = coordVar; 1419 } 1420 GrAssert(2 == segments->fCoordDims); 1421 GrStringBuilder accumVar("accum"); 1422 accumVar.appendS32(stageNum); 1423 segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, segments->fSampleCoords.c_str(), texelSizeName, texelSizeName, segments->fSwizzle.c_str()); 1424 segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, segments->fSampleCoords.c_str(), texelSizeName, texelSizeName, segments->fSwizzle.c_str()); 1425 segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, segments->fSampleCoords.c_str(), texelSizeName, texelSizeName, segments->fSwizzle.c_str()); 1426 segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, segments->fSampleCoords.c_str(), texelSizeName, texelSizeName, segments->fSwizzle.c_str()); 1427 segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), segments->fModulate.c_str()); 1428 1429} 1430 1431void genMorphologyVS(int stageNum, 1432 const StageDesc& desc, 1433 GrGLShaderBuilder* segments, 1434 GrGLProgram::StageUniLocations* locations, 1435 const char** imageIncrementName, 1436 const char* varyingVSName) { 1437 GrGLShaderVar* imgInc = &segments->fFSUnis.push_back(); 1438 imgInc->setType(kVec2f_GrSLType); 1439 imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 1440 1441 image_increment_param_name(stageNum, imgInc->accessName()); 1442 *imageIncrementName = imgInc->getName().c_str(); 1443 1444 // need image increment in both VS and FS 1445 segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true); 1446 1447 locations->fImageIncrementUni = kUseUniform; 1448 segments->fVSCode.appendf("\t%s -= vec2(%d, %d) * %s;\n", 1449 varyingVSName, desc.fKernelWidth, 1450 desc.fKernelWidth, *imageIncrementName); 1451} 1452 1453void genMorphologyFS(int stageNum, 1454 const StageDesc& desc, 1455 GrGLShaderBuilder* segments, 1456 const char* samplerName, 1457 const char* imageIncrementName, 1458 const char* fsOutColor, 1459 GrStringBuilder& texFunc) { 1460 GrStringBuilder valueVar("value"); 1461 valueVar.appendS32(stageNum); 1462 GrStringBuilder coordVar("coord"); 1463 coordVar.appendS32(stageNum); 1464 bool isDilate = StageDesc::kDilate_FetchMode == desc.fFetchMode; 1465 1466 if (isDilate) { 1467 segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n", 1468 valueVar.c_str()); 1469 } else { 1470 segments->fFSCode.appendf("\tvec4 %s = vec4(1, 1, 1, 1);\n", 1471 valueVar.c_str()); 1472 } 1473 segments->fFSCode.appendf("\tvec2 %s = %s;\n", 1474 coordVar.c_str(), 1475 segments->fSampleCoords.c_str()); 1476 segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n", 1477 desc.fKernelWidth * 2 + 1); 1478 segments->fFSCode.appendf("\t\t%s = %s(%s, %s(%s, %s)%s);\n", 1479 valueVar.c_str(), isDilate ? "max" : "min", 1480 valueVar.c_str(), texFunc.c_str(), 1481 samplerName, coordVar.c_str(), 1482 segments->fSwizzle.c_str()); 1483 segments->fFSCode.appendf("\t\t%s += %s;\n", 1484 coordVar.c_str(), 1485 imageIncrementName); 1486 segments->fFSCode.appendf("\t}\n"); 1487 segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor, 1488 valueVar.c_str(), segments->fModulate.c_str()); 1489} 1490 1491} 1492 1493void GrGLProgram::genStageCode(const GrGLContextInfo& gl, 1494 int stageNum, 1495 const GrGLProgram::StageDesc& desc, 1496 const char* fsInColor, // NULL means no incoming color 1497 const char* fsOutColor, 1498 const char* vsInCoord, 1499 GrGLShaderBuilder* segments, 1500 StageUniLocations* locations, 1501 GrGLProgramStage* customStage) const { 1502 1503 GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages); 1504 GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == 1505 desc.fInConfigFlags); 1506 1507 /// Vertex Shader Stuff 1508 1509 if (NULL != customStage) { 1510 customStage->setupVSUnis(&segments->fVSUnis, stageNum); 1511 } 1512 1513 // decide whether we need a matrix to transform texture coords 1514 // and whether the varying needs a perspective coord. 1515 const char* matName = NULL; 1516 if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) { 1517 segments->fVaryingDims = segments->fCoordDims; 1518 } else { 1519 GrGLShaderVar* mat; 1520 mat = &segments->fVSUnis.push_back(); 1521 mat->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 1522 locations->fTextureMatrixUni = kUseUniform; 1523 1524 tex_matrix_name(stageNum, mat->accessName()); 1525 mat->setType(kMat33f_GrSLType); 1526 matName = mat->getName().c_str(); 1527 1528 if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { 1529 segments->fVaryingDims = segments->fCoordDims; 1530 } else { 1531 segments->fVaryingDims = segments->fCoordDims + 1; 1532 } 1533 } 1534 GrAssert(segments->fVaryingDims > 0); 1535 1536 segments->fFSUnis.push_back().set(kSampler2D_GrSLType, 1537 GrGLShaderVar::kUniform_TypeModifier, ""); 1538 sampler_name(stageNum, segments->fFSUnis.back().accessName()); 1539 locations->fSamplerUni = kUseUniform; 1540 const char* samplerName = segments->fFSUnis.back().getName().c_str(); 1541 1542 const char* texelSizeName = NULL; 1543 if (StageDesc::k2x2_FetchMode == desc.fFetchMode) { 1544 segments->fFSUnis.push_back().set(kVec2f_GrSLType, 1545 GrGLShaderVar::kUniform_TypeModifier, ""); 1546 normalized_texel_size_name(stageNum, segments->fFSUnis.back().accessName()); 1547 texelSizeName = segments->fFSUnis.back().getName().c_str(); 1548 } 1549 1550 const char *varyingVSName, *varyingFSName; 1551 segments->appendVarying(GrSLFloatVectorType(segments->fVaryingDims), 1552 "Stage", 1553 stageNum, 1554 &varyingVSName, 1555 &varyingFSName); 1556 1557 if (!matName) { 1558 GrAssert(segments->fVaryingDims == segments->fCoordDims); 1559 segments->fVSCode.appendf("\t%s = %s;\n", varyingVSName, vsInCoord); 1560 } else { 1561 // varying = texMatrix * texCoord 1562 segments->fVSCode.appendf("\t%s = (%s * vec3(%s, 1))%s;\n", 1563 varyingVSName, matName, vsInCoord, 1564 vector_all_coords(segments->fVaryingDims)); 1565 } 1566 1567 GrGLShaderVar* radial2Params = NULL; 1568 const char* radial2VaryingVSName = NULL; 1569 const char* radial2VaryingFSName = NULL; 1570 1571 if (isRadialMapping((StageDesc::CoordMapping) desc.fCoordMapping)) { 1572 radial2Params = genRadialVS(stageNum, segments, 1573 locations, 1574 &radial2VaryingVSName, 1575 &radial2VaryingFSName, 1576 varyingVSName); 1577 } 1578 1579 GrGLShaderVar* kernel = NULL; 1580 const char* imageIncrementName = NULL; 1581 if (StageDesc::kDilate_FetchMode == desc.fFetchMode || 1582 StageDesc::kErode_FetchMode == desc.fFetchMode) { 1583 genMorphologyVS(stageNum, desc, segments, locations, 1584 &imageIncrementName, varyingVSName); 1585 } 1586 1587 if (NULL != customStage) { 1588 segments->fVSCode.appendf("\t{ // stage %d %s\n", 1589 stageNum, customStage->name()); 1590 customStage->emitVS(segments, varyingVSName); 1591 segments->fVSCode.appendf("\t}\n"); 1592 } 1593 1594 /// Fragment Shader Stuff 1595 1596 if (NULL != customStage) { 1597 customStage->setupFSUnis(&segments->fFSUnis, stageNum); 1598 } 1599 1600 // Function used to access the shader, may be made projective. 1601 GrStringBuilder texFunc("texture2D"); 1602 if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit | 1603 StageDesc::kNoPerspective_OptFlagBit)) { 1604 GrAssert(segments->fVaryingDims == segments->fCoordDims); 1605 segments->fSampleCoords = varyingFSName; 1606 } else { 1607 // If we have to do some special op on the varyings to get 1608 // our final tex coords then when in perspective we have to 1609 // do an explicit divide. Otherwise, we can use a Proj func. 1610 if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping && 1611 StageDesc::kSingle_FetchMode == desc.fFetchMode) { 1612 texFunc.append("Proj"); 1613 segments->fSampleCoords = varyingFSName; 1614 } else { 1615 // This block is replicated in GrGLProgramStage::emitTextureLookup() 1616 segments->fSampleCoords = "inCoord"; 1617 segments->fSampleCoords.appendS32(stageNum); 1618 segments->fFSCode.appendf("\t%s %s = %s%s / %s%s;\n", 1619 GrGLShaderVar::TypeString(GrSLFloatVectorType(segments->fCoordDims)), 1620 segments->fSampleCoords.c_str(), 1621 varyingFSName, 1622 GrGLSLVectorNonhomogCoords(segments->fVaryingDims), 1623 varyingFSName, 1624 GrGLSLVectorHomogCoord(segments->fVaryingDims)); 1625 } 1626 } 1627 1628 segments->fComplexCoord = false; 1629 // NOTE: GrGLProgramStages will soon responsible for mapping 1630 //if (NULL == customStage) { 1631 switch (desc.fCoordMapping) { 1632 case StageDesc::kIdentity_CoordMapping: 1633 // Do nothing 1634 break; 1635 case StageDesc::kSweepGradient_CoordMapping: 1636 segments->fSampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", segments->fSampleCoords.c_str(), segments->fSampleCoords.c_str()); 1637 segments->fComplexCoord = true; 1638 break; 1639 case StageDesc::kRadialGradient_CoordMapping: 1640 segments->fSampleCoords.printf("vec2(length(%s.xy), 0.5)", segments->fSampleCoords.c_str()); 1641 segments->fComplexCoord = true; 1642 break; 1643 case StageDesc::kRadial2Gradient_CoordMapping: 1644 genRadial2GradientCoordMapping( 1645 stageNum, segments, 1646 radial2VaryingFSName, radial2Params); 1647 break; 1648 case StageDesc::kRadial2GradientDegenerate_CoordMapping: 1649 genRadial2GradientDegenerateCoordMapping( 1650 stageNum, segments, 1651 radial2VaryingFSName, radial2Params); 1652 break; 1653 } 1654 //} 1655 1656 static const uint32_t kMulByAlphaMask = 1657 (StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | 1658 StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag); 1659 1660 segments->computeSwizzle(desc.fInConfigFlags); 1661 segments->computeModulate(fsInColor); 1662 1663 if (desc.fOptFlags & 1664 StageDesc::kCustomTextureDomain_OptFlagBit) { 1665 GrStringBuilder texDomainName; 1666 tex_domain_name(stageNum, &texDomainName); 1667 segments->fFSUnis.push_back().set(kVec4f_GrSLType, 1668 GrGLShaderVar::kUniform_TypeModifier, texDomainName); 1669 GrStringBuilder coordVar("clampCoord"); 1670 segments->fFSCode.appendf("\t%s %s = clamp(%s, %s.xy, %s.zw);\n", 1671 float_vector_type_str(segments->fCoordDims), 1672 coordVar.c_str(), 1673 segments->fSampleCoords.c_str(), 1674 texDomainName.c_str(), 1675 texDomainName.c_str()); 1676 segments->fSampleCoords = coordVar; 1677 locations->fTexDomUni = kUseUniform; 1678 } 1679 1680 if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit | 1681 StageDesc::kNoPerspective_OptFlagBit)) { 1682 segments->setSamplerMode(GrGLShaderBuilder::kDefault_SamplerMode); 1683 } else if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping && 1684 StageDesc::kSingle_FetchMode == desc.fFetchMode) { 1685 segments->setSamplerMode(GrGLShaderBuilder::kProj_SamplerMode); 1686 } else { 1687 segments->setSamplerMode( 1688 GrGLShaderBuilder::kExplicitDivide_SamplerMode); 1689 } 1690 1691 // NOTE: GrGLProgramStages are now responsible for fetching 1692 if (NULL == customStage) { 1693 switch (desc.fFetchMode) { 1694 case StageDesc::k2x2_FetchMode: 1695 GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask)); 1696 gen2x2FS(stageNum, segments, locations, 1697 samplerName, texelSizeName, fsOutColor, texFunc); 1698 break; 1699 case StageDesc::kConvolution_FetchMode: 1700 GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask)); 1701 break; 1702 case StageDesc::kDilate_FetchMode: 1703 case StageDesc::kErode_FetchMode: 1704 GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask)); 1705 genMorphologyFS(stageNum, desc, segments, 1706 samplerName, imageIncrementName, fsOutColor, texFunc); 1707 break; 1708 default: 1709 if (desc.fInConfigFlags & kMulByAlphaMask) { 1710 // only one of the mul by alpha flags should be set 1711 GrAssert(GrIsPow2(kMulByAlphaMask & desc.fInConfigFlags)); 1712 GrAssert(!(desc.fInConfigFlags & 1713 StageDesc::kSmearAlpha_InConfigFlag)); 1714 GrAssert(!(desc.fInConfigFlags & 1715 StageDesc::kSmearRed_InConfigFlag)); 1716 segments->fFSCode.appendf("\t%s = %s(%s, %s)%s;\n", 1717 fsOutColor, texFunc.c_str(), 1718 samplerName, 1719 segments->fSampleCoords.c_str(), 1720 segments->fSwizzle.c_str()); 1721 if (desc.fInConfigFlags & 1722 StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag) { 1723 segments->fFSCode.appendf("\t%s = vec4(ceil(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n", 1724 fsOutColor, fsOutColor, fsOutColor, 1725 fsOutColor, segments->fModulate.c_str()); 1726 } else { 1727 segments->fFSCode.appendf("\t%s = vec4(floor(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n", 1728 fsOutColor, fsOutColor, fsOutColor, 1729 fsOutColor, segments->fModulate.c_str()); 1730 } 1731 } else { 1732 segments->emitDefaultFetch(fsOutColor, samplerName); 1733 } 1734 } 1735 } 1736 1737 if (NULL != customStage) { 1738 // Enclose custom code in a block to avoid namespace conflicts 1739 segments->fFSCode.appendf("\t{ // stage %d %s \n", 1740 stageNum, customStage->name()); 1741 segments->emitTextureSetup(); 1742 customStage->emitFS(segments, fsOutColor, fsInColor, samplerName); 1743 segments->fFSCode.appendf("\t}\n"); 1744 } 1745} 1746 1747 1748