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