1 /* 2 * Copyright 2013 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 "GrBezierEffect.h" 9 10 #include "gl/GrGLEffect.h" 11 #include "gl/GrGLSL.h" 12 #include "gl/GrGLVertexEffect.h" 13 #include "GrTBackendEffectFactory.h" 14 15 class GrGLConicEffect : public GrGLVertexEffect { 16 public: 17 GrGLConicEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 18 19 virtual void emitCode(GrGLFullShaderBuilder* builder, 20 const GrDrawEffect& drawEffect, 21 EffectKey key, 22 const char* outputColor, 23 const char* inputColor, 24 const TransformedCoordsArray&, 25 const TextureSamplerArray&) SK_OVERRIDE; 26 27 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 28 29 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 30 31 private: 32 GrBezierEdgeType fEdgeType; 33 34 typedef GrGLVertexEffect INHERITED; 35 }; 36 37 GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory, 38 const GrDrawEffect& drawEffect) 39 : INHERITED (factory) { 40 const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>(); 41 fEdgeType = ce.getEdgeType(); 42 } 43 44 void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder, 45 const GrDrawEffect& drawEffect, 46 EffectKey key, 47 const char* outputColor, 48 const char* inputColor, 49 const TransformedCoordsArray&, 50 const TextureSamplerArray& samplers) { 51 const char *vsName, *fsName; 52 53 builder->addVarying(kVec4f_GrSLType, "ConicCoeffs", 54 &vsName, &fsName); 55 const SkString* attr0Name = 56 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 57 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); 58 59 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); 60 61 switch (fEdgeType) { 62 case kHairAA_GrBezierEdgeType: { 63 SkAssertResult(builder->enableFeature( 64 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 65 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 66 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 67 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 68 "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 69 fsName, fsName, fsName); 70 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 71 "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 72 fsName, fsName, fsName); 73 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 74 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 75 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, 76 fsName, fsName); 77 builder->fsCodeAppend("\t\tfunc = abs(func);\n"); 78 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 79 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 80 // Add line below for smooth cubic ramp 81 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 82 break; 83 } 84 case kFillAA_GrBezierEdgeType: { 85 SkAssertResult(builder->enableFeature( 86 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 87 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 88 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 89 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 90 "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 91 fsName, fsName, fsName); 92 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 93 "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 94 fsName, fsName, fsName); 95 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 96 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 97 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, 98 fsName, fsName); 99 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 100 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); 101 // Add line below for smooth cubic ramp 102 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 103 break; 104 } 105 case kFillNoAA_GrBezierEdgeType: { 106 builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName, 107 fsName, fsName); 108 builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); 109 break; 110 } 111 } 112 113 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 114 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 115 } 116 117 GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 118 const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>(); 119 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 120 } 121 122 ////////////////////////////////////////////////////////////////////////////// 123 124 GrConicEffect::~GrConicEffect() {} 125 126 const GrBackendEffectFactory& GrConicEffect::getFactory() const { 127 return GrTBackendEffectFactory<GrConicEffect>::getInstance(); 128 } 129 130 GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { 131 this->addVertexAttrib(kVec4f_GrSLType); 132 fEdgeType = edgeType; 133 } 134 135 bool GrConicEffect::onIsEqual(const GrEffect& other) const { 136 const GrConicEffect& ce = CastEffect<GrConicEffect>(other); 137 return (ce.fEdgeType == fEdgeType); 138 } 139 140 ////////////////////////////////////////////////////////////////////////////// 141 142 GR_DEFINE_EFFECT_TEST(GrConicEffect); 143 144 GrEffectRef* GrConicEffect::TestCreate(SkRandom* random, 145 GrContext*, 146 const GrDrawTargetCaps& caps, 147 GrTexture*[]) { 148 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3)); 149 return GrConicEffect::Create(edgeType, caps); 150 } 151 152 ////////////////////////////////////////////////////////////////////////////// 153 // Quad 154 ////////////////////////////////////////////////////////////////////////////// 155 156 class GrGLQuadEffect : public GrGLVertexEffect { 157 public: 158 GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 159 160 virtual void emitCode(GrGLFullShaderBuilder* builder, 161 const GrDrawEffect& drawEffect, 162 EffectKey key, 163 const char* outputColor, 164 const char* inputColor, 165 const TransformedCoordsArray&, 166 const TextureSamplerArray&) SK_OVERRIDE; 167 168 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 169 170 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 171 172 private: 173 GrBezierEdgeType fEdgeType; 174 175 typedef GrGLVertexEffect INHERITED; 176 }; 177 178 GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory, 179 const GrDrawEffect& drawEffect) 180 : INHERITED (factory) { 181 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>(); 182 fEdgeType = ce.getEdgeType(); 183 } 184 185 void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder, 186 const GrDrawEffect& drawEffect, 187 EffectKey key, 188 const char* outputColor, 189 const char* inputColor, 190 const TransformedCoordsArray&, 191 const TextureSamplerArray& samplers) { 192 const char *vsName, *fsName; 193 194 const SkString* attrName = 195 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 196 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 197 198 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); 199 200 switch (fEdgeType) { 201 case kHairAA_GrBezierEdgeType: { 202 SkAssertResult(builder->enableFeature( 203 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 204 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 205 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 206 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 207 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 208 fsName, fsName); 209 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 210 fsName); 211 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 212 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 213 // Add line below for smooth cubic ramp 214 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 215 break; 216 } 217 case kFillAA_GrBezierEdgeType: { 218 SkAssertResult(builder->enableFeature( 219 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 220 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 221 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 222 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 223 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 224 fsName, fsName); 225 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 226 fsName); 227 builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n"); 228 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); 229 // Add line below for smooth cubic ramp 230 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 231 break; 232 } 233 case kFillNoAA_GrBezierEdgeType: { 234 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 235 fsName); 236 builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); 237 break; 238 } 239 } 240 241 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 242 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 243 244 245 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 246 } 247 248 GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 249 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>(); 250 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 251 } 252 253 ////////////////////////////////////////////////////////////////////////////// 254 255 GrQuadEffect::~GrQuadEffect() {} 256 257 const GrBackendEffectFactory& GrQuadEffect::getFactory() const { 258 return GrTBackendEffectFactory<GrQuadEffect>::getInstance(); 259 } 260 261 GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { 262 this->addVertexAttrib(kVec4f_GrSLType); 263 fEdgeType = edgeType; 264 } 265 266 bool GrQuadEffect::onIsEqual(const GrEffect& other) const { 267 const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other); 268 return (ce.fEdgeType == fEdgeType); 269 } 270 271 ////////////////////////////////////////////////////////////////////////////// 272 273 GR_DEFINE_EFFECT_TEST(GrQuadEffect); 274 275 GrEffectRef* GrQuadEffect::TestCreate(SkRandom* random, 276 GrContext*, 277 const GrDrawTargetCaps& caps, 278 GrTexture*[]) { 279 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3)); 280 return GrQuadEffect::Create(edgeType, caps); 281 } 282 283 ////////////////////////////////////////////////////////////////////////////// 284 // Cubic 285 ////////////////////////////////////////////////////////////////////////////// 286 287 class GrGLCubicEffect : public GrGLVertexEffect { 288 public: 289 GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 290 291 virtual void emitCode(GrGLFullShaderBuilder* builder, 292 const GrDrawEffect& drawEffect, 293 EffectKey key, 294 const char* outputColor, 295 const char* inputColor, 296 const TransformedCoordsArray&, 297 const TextureSamplerArray&) SK_OVERRIDE; 298 299 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 300 301 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 302 303 private: 304 GrBezierEdgeType fEdgeType; 305 306 typedef GrGLVertexEffect INHERITED; 307 }; 308 309 GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory, 310 const GrDrawEffect& drawEffect) 311 : INHERITED (factory) { 312 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>(); 313 fEdgeType = ce.getEdgeType(); 314 } 315 316 void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder, 317 const GrDrawEffect& drawEffect, 318 EffectKey key, 319 const char* outputColor, 320 const char* inputColor, 321 const TransformedCoordsArray&, 322 const TextureSamplerArray& samplers) { 323 const char *vsName, *fsName; 324 325 builder->addVarying(kVec4f_GrSLType, "CubicCoeffs", 326 &vsName, &fsName); 327 const SkString* attr0Name = 328 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 329 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); 330 331 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); 332 333 switch (fEdgeType) { 334 case kHairAA_GrBezierEdgeType: { 335 SkAssertResult(builder->enableFeature( 336 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 337 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 338 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 339 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 340 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 341 fsName, fsName, fsName, fsName); 342 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 343 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 344 fsName, fsName, fsName, fsName); 345 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 346 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 347 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 348 fsName, fsName, fsName, fsName, fsName); 349 builder->fsCodeAppend("\t\tfunc = abs(func);\n"); 350 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 351 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 352 // Add line below for smooth cubic ramp 353 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 354 break; 355 } 356 case kFillAA_GrBezierEdgeType: { 357 SkAssertResult(builder->enableFeature( 358 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 359 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 360 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 361 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 362 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 363 fsName, fsName, fsName, fsName); 364 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 365 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 366 fsName, fsName, fsName, fsName); 367 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 368 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 369 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 370 fsName, fsName, fsName, fsName, fsName); 371 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 372 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); 373 // Add line below for smooth cubic ramp 374 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 375 break; 376 } 377 case kFillNoAA_GrBezierEdgeType: { 378 builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 379 fsName, fsName, fsName, fsName, fsName); 380 builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); 381 break; 382 } 383 } 384 385 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 386 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 387 } 388 389 GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 390 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>(); 391 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 392 } 393 394 ////////////////////////////////////////////////////////////////////////////// 395 396 GrCubicEffect::~GrCubicEffect() {} 397 398 const GrBackendEffectFactory& GrCubicEffect::getFactory() const { 399 return GrTBackendEffectFactory<GrCubicEffect>::getInstance(); 400 } 401 402 GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { 403 this->addVertexAttrib(kVec4f_GrSLType); 404 fEdgeType = edgeType; 405 } 406 407 bool GrCubicEffect::onIsEqual(const GrEffect& other) const { 408 const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other); 409 return (ce.fEdgeType == fEdgeType); 410 } 411 412 ////////////////////////////////////////////////////////////////////////////// 413 414 GR_DEFINE_EFFECT_TEST(GrCubicEffect); 415 416 GrEffectRef* GrCubicEffect::TestCreate(SkRandom* random, 417 GrContext*, 418 const GrDrawTargetCaps& caps, 419 GrTexture*[]) { 420 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3)); 421 return GrCubicEffect::Create(edgeType, caps); 422 } 423