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 GrEffectEdgeType 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 kHairlineAA_GrEffectEdgeType: { 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_GrEffectEdgeType: { 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 kFillBW_GrEffectEdgeType: { 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 default: 112 SkFAIL("Shouldn't get here"); 113 } 114 115 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 116 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 117 } 118 119 GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 120 const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>(); 121 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 122 } 123 124 ////////////////////////////////////////////////////////////////////////////// 125 126 GrConicEffect::~GrConicEffect() {} 127 128 const GrBackendEffectFactory& GrConicEffect::getFactory() const { 129 return GrTBackendEffectFactory<GrConicEffect>::getInstance(); 130 } 131 132 GrConicEffect::GrConicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() { 133 this->addVertexAttrib(kVec4f_GrSLType); 134 fEdgeType = edgeType; 135 } 136 137 bool GrConicEffect::onIsEqual(const GrEffect& other) const { 138 const GrConicEffect& ce = CastEffect<GrConicEffect>(other); 139 return (ce.fEdgeType == fEdgeType); 140 } 141 142 ////////////////////////////////////////////////////////////////////////////// 143 144 GR_DEFINE_EFFECT_TEST(GrConicEffect); 145 146 GrEffectRef* GrConicEffect::TestCreate(SkRandom* random, 147 GrContext*, 148 const GrDrawTargetCaps& caps, 149 GrTexture*[]) { 150 GrEffectRef* effect; 151 do { 152 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>( 153 random->nextULessThan(kGrEffectEdgeTypeCnt)); 154 effect = GrConicEffect::Create(edgeType, caps); 155 } while (NULL == effect); 156 return effect; 157 } 158 159 ////////////////////////////////////////////////////////////////////////////// 160 // Quad 161 ////////////////////////////////////////////////////////////////////////////// 162 163 class GrGLQuadEffect : public GrGLVertexEffect { 164 public: 165 GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 166 167 virtual void emitCode(GrGLFullShaderBuilder* builder, 168 const GrDrawEffect& drawEffect, 169 EffectKey key, 170 const char* outputColor, 171 const char* inputColor, 172 const TransformedCoordsArray&, 173 const TextureSamplerArray&) SK_OVERRIDE; 174 175 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 176 177 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 178 179 private: 180 GrEffectEdgeType fEdgeType; 181 182 typedef GrGLVertexEffect INHERITED; 183 }; 184 185 GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory, 186 const GrDrawEffect& drawEffect) 187 : INHERITED (factory) { 188 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>(); 189 fEdgeType = ce.getEdgeType(); 190 } 191 192 void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder, 193 const GrDrawEffect& drawEffect, 194 EffectKey key, 195 const char* outputColor, 196 const char* inputColor, 197 const TransformedCoordsArray&, 198 const TextureSamplerArray& samplers) { 199 const char *vsName, *fsName; 200 201 const SkString* attrName = 202 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 203 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 204 205 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); 206 207 switch (fEdgeType) { 208 case kHairlineAA_GrEffectEdgeType: { 209 SkAssertResult(builder->enableFeature( 210 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 211 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 212 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 213 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 214 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 215 fsName, fsName); 216 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 217 fsName); 218 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 219 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 220 // Add line below for smooth cubic ramp 221 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 222 break; 223 } 224 case kFillAA_GrEffectEdgeType: { 225 SkAssertResult(builder->enableFeature( 226 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 227 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 228 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 229 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 230 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 231 fsName, fsName); 232 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 233 fsName); 234 builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n"); 235 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); 236 // Add line below for smooth cubic ramp 237 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 238 break; 239 } 240 case kFillBW_GrEffectEdgeType: { 241 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 242 fsName); 243 builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); 244 break; 245 } 246 default: 247 SkFAIL("Shouldn't get here"); 248 } 249 250 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 251 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 252 253 254 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 255 } 256 257 GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 258 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>(); 259 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 260 } 261 262 ////////////////////////////////////////////////////////////////////////////// 263 264 GrQuadEffect::~GrQuadEffect() {} 265 266 const GrBackendEffectFactory& GrQuadEffect::getFactory() const { 267 return GrTBackendEffectFactory<GrQuadEffect>::getInstance(); 268 } 269 270 GrQuadEffect::GrQuadEffect(GrEffectEdgeType edgeType) : GrVertexEffect() { 271 this->addVertexAttrib(kVec4f_GrSLType); 272 fEdgeType = edgeType; 273 } 274 275 bool GrQuadEffect::onIsEqual(const GrEffect& other) const { 276 const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other); 277 return (ce.fEdgeType == fEdgeType); 278 } 279 280 ////////////////////////////////////////////////////////////////////////////// 281 282 GR_DEFINE_EFFECT_TEST(GrQuadEffect); 283 284 GrEffectRef* GrQuadEffect::TestCreate(SkRandom* random, 285 GrContext*, 286 const GrDrawTargetCaps& caps, 287 GrTexture*[]) { 288 GrEffectRef* effect; 289 do { 290 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>( 291 random->nextULessThan(kGrEffectEdgeTypeCnt)); 292 effect = GrQuadEffect::Create(edgeType, caps); 293 } while (NULL == effect); 294 return effect; 295 } 296 297 ////////////////////////////////////////////////////////////////////////////// 298 // Cubic 299 ////////////////////////////////////////////////////////////////////////////// 300 301 class GrGLCubicEffect : public GrGLVertexEffect { 302 public: 303 GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 304 305 virtual void emitCode(GrGLFullShaderBuilder* builder, 306 const GrDrawEffect& drawEffect, 307 EffectKey key, 308 const char* outputColor, 309 const char* inputColor, 310 const TransformedCoordsArray&, 311 const TextureSamplerArray&) SK_OVERRIDE; 312 313 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 314 315 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 316 317 private: 318 GrEffectEdgeType fEdgeType; 319 320 typedef GrGLVertexEffect INHERITED; 321 }; 322 323 GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory, 324 const GrDrawEffect& drawEffect) 325 : INHERITED (factory) { 326 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>(); 327 fEdgeType = ce.getEdgeType(); 328 } 329 330 void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder, 331 const GrDrawEffect& drawEffect, 332 EffectKey key, 333 const char* outputColor, 334 const char* inputColor, 335 const TransformedCoordsArray&, 336 const TextureSamplerArray& samplers) { 337 const char *vsName, *fsName; 338 339 builder->addVarying(kVec4f_GrSLType, "CubicCoeffs", 340 &vsName, &fsName); 341 const SkString* attr0Name = 342 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 343 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); 344 345 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n"); 346 347 switch (fEdgeType) { 348 case kHairlineAA_GrEffectEdgeType: { 349 SkAssertResult(builder->enableFeature( 350 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 351 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 352 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 353 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 354 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 355 fsName, fsName, fsName, fsName); 356 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 357 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 358 fsName, fsName, fsName, fsName); 359 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 360 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 361 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 362 fsName, fsName, fsName, fsName, fsName); 363 builder->fsCodeAppend("\t\tfunc = abs(func);\n"); 364 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 365 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 366 // Add line below for smooth cubic ramp 367 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 368 break; 369 } 370 case kFillAA_GrEffectEdgeType: { 371 SkAssertResult(builder->enableFeature( 372 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 373 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName); 374 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName); 375 builder->fsCodeAppendf("\t\tfloat dfdx =\n" 376 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n", 377 fsName, fsName, fsName, fsName); 378 builder->fsCodeAppendf("\t\tfloat dfdy =\n" 379 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n", 380 fsName, fsName, fsName, fsName); 381 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n"); 382 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n"); 383 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 384 fsName, fsName, fsName, fsName, fsName); 385 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n"); 386 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n"); 387 // Add line below for smooth cubic ramp 388 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n"); 389 break; 390 } 391 case kFillBW_GrEffectEdgeType: { 392 builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n", 393 fsName, fsName, fsName, fsName, fsName); 394 builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n"); 395 break; 396 } 397 default: 398 SkFAIL("Shouldn't get here"); 399 } 400 401 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 402 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str()); 403 } 404 405 GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 406 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>(); 407 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2; 408 } 409 410 ////////////////////////////////////////////////////////////////////////////// 411 412 GrCubicEffect::~GrCubicEffect() {} 413 414 const GrBackendEffectFactory& GrCubicEffect::getFactory() const { 415 return GrTBackendEffectFactory<GrCubicEffect>::getInstance(); 416 } 417 418 GrCubicEffect::GrCubicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() { 419 this->addVertexAttrib(kVec4f_GrSLType); 420 fEdgeType = edgeType; 421 } 422 423 bool GrCubicEffect::onIsEqual(const GrEffect& other) const { 424 const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other); 425 return (ce.fEdgeType == fEdgeType); 426 } 427 428 ////////////////////////////////////////////////////////////////////////////// 429 430 GR_DEFINE_EFFECT_TEST(GrCubicEffect); 431 432 GrEffectRef* GrCubicEffect::TestCreate(SkRandom* random, 433 GrContext*, 434 const GrDrawTargetCaps& caps, 435 GrTexture*[]) { 436 GrEffectRef* effect; 437 do { 438 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>( 439 random->nextULessThan(kGrEffectEdgeTypeCnt)); 440 effect = GrCubicEffect::Create(edgeType, caps); 441 } while (NULL == effect); 442 return effect; 443 } 444