1 /* 2 * Copyright 2014 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 "GrOvalEffect.h" 9 10 #include "gl/GrGLEffect.h" 11 #include "gl/GrGLSL.h" 12 #include "GrTBackendEffectFactory.h" 13 14 #include "SkRect.h" 15 16 ////////////////////////////////////////////////////////////////////////////// 17 18 class GLCircleEffect; 19 20 class CircleEffect : public GrEffect { 21 public: 22 static GrEffectRef* Create(GrEffectEdgeType, const SkPoint& center, SkScalar radius); 23 24 virtual ~CircleEffect() {}; 25 static const char* Name() { return "Circle"; } 26 27 const SkPoint& getCenter() const { return fCenter; } 28 SkScalar getRadius() const { return fRadius; } 29 30 GrEffectEdgeType getEdgeType() const { return fEdgeType; } 31 32 typedef GLCircleEffect GLEffect; 33 34 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 35 36 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 37 38 private: 39 CircleEffect(GrEffectEdgeType, const SkPoint& center, SkScalar radius); 40 41 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 42 43 SkPoint fCenter; 44 SkScalar fRadius; 45 GrEffectEdgeType fEdgeType; 46 47 GR_DECLARE_EFFECT_TEST; 48 49 typedef GrEffect INHERITED; 50 }; 51 52 GrEffectRef* CircleEffect::Create(GrEffectEdgeType edgeType, 53 const SkPoint& center, 54 SkScalar radius) { 55 SkASSERT(radius >= 0); 56 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEffect, 57 (edgeType, center, radius)))); 58 } 59 60 void CircleEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 61 *validFlags = 0; 62 } 63 64 const GrBackendEffectFactory& CircleEffect::getFactory() const { 65 return GrTBackendEffectFactory<CircleEffect>::getInstance(); 66 } 67 68 CircleEffect::CircleEffect(GrEffectEdgeType edgeType, const SkPoint& c, SkScalar r) 69 : fCenter(c) 70 , fRadius(r) 71 , fEdgeType(edgeType) { 72 this->setWillReadFragmentPosition(); 73 } 74 75 bool CircleEffect::onIsEqual(const GrEffect& other) const { 76 const CircleEffect& ce = CastEffect<CircleEffect>(other); 77 return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius; 78 } 79 80 ////////////////////////////////////////////////////////////////////////////// 81 82 GR_DEFINE_EFFECT_TEST(CircleEffect); 83 84 GrEffectRef* CircleEffect::TestCreate(SkRandom* random, 85 GrContext*, 86 const GrDrawTargetCaps& caps, 87 GrTexture*[]) { 88 SkPoint center; 89 center.fX = random->nextRangeScalar(0.f, 1000.f); 90 center.fY = random->nextRangeScalar(0.f, 1000.f); 91 SkScalar radius = random->nextRangeF(0.f, 1000.f); 92 GrEffectEdgeType et; 93 do { 94 et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt); 95 } while (kHairlineAA_GrEffectEdgeType == et); 96 return CircleEffect::Create(et, center, radius); 97 } 98 99 ////////////////////////////////////////////////////////////////////////////// 100 101 class GLCircleEffect : public GrGLEffect { 102 public: 103 GLCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 104 105 virtual void emitCode(GrGLShaderBuilder* builder, 106 const GrDrawEffect& drawEffect, 107 EffectKey key, 108 const char* outputColor, 109 const char* inputColor, 110 const TransformedCoordsArray&, 111 const TextureSamplerArray&) SK_OVERRIDE; 112 113 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 114 115 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 116 117 private: 118 GrGLUniformManager::UniformHandle fCircleUniform; 119 SkPoint fPrevCenter; 120 SkScalar fPrevRadius; 121 122 typedef GrGLEffect INHERITED; 123 }; 124 125 GLCircleEffect::GLCircleEffect(const GrBackendEffectFactory& factory, 126 const GrDrawEffect& drawEffect) 127 : INHERITED (factory) { 128 fPrevRadius = -1.f; 129 } 130 131 void GLCircleEffect::emitCode(GrGLShaderBuilder* builder, 132 const GrDrawEffect& drawEffect, 133 EffectKey key, 134 const char* outputColor, 135 const char* inputColor, 136 const TransformedCoordsArray&, 137 const TextureSamplerArray& samplers) { 138 const CircleEffect& ce = drawEffect.castEffect<CircleEffect>(); 139 const char *circleName; 140 // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and 141 // (... ,radius - 0.5) for inverse fills. 142 fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 143 kVec3f_GrSLType, 144 "circle", 145 &circleName); 146 const char* fragmentPos = builder->fragmentPosition(); 147 148 SkASSERT(kHairlineAA_GrEffectEdgeType != ce.getEdgeType()); 149 if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) { 150 builder->fsCodeAppendf("\t\tfloat d = length(%s.xy - %s) - %s.z;\n", 151 circleName, fragmentPos, circleName); 152 } else { 153 builder->fsCodeAppendf("\t\tfloat d = %s.z - length(%s - %s.xy);\n", 154 circleName, fragmentPos, circleName); 155 } 156 if (GrEffectEdgeTypeIsAA(ce.getEdgeType())) { 157 builder->fsCodeAppend("\t\td = clamp(d, 0.0, 1.0);\n"); 158 } else { 159 builder->fsCodeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n"); 160 } 161 162 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, 163 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str()); 164 } 165 166 GrGLEffect::EffectKey GLCircleEffect::GenKey(const GrDrawEffect& drawEffect, 167 const GrGLCaps&) { 168 const CircleEffect& ce = drawEffect.castEffect<CircleEffect>(); 169 return ce.getEdgeType(); 170 } 171 172 void GLCircleEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { 173 const CircleEffect& ce = drawEffect.castEffect<CircleEffect>(); 174 if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) { 175 SkScalar radius = ce.getRadius(); 176 if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) { 177 radius -= 0.5f; 178 } else { 179 radius += 0.5f; 180 } 181 uman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius); 182 fPrevCenter = ce.getCenter(); 183 fPrevRadius = ce.getRadius(); 184 } 185 } 186 187 ////////////////////////////////////////////////////////////////////////////// 188 189 class GLEllipseEffect; 190 191 class EllipseEffect : public GrEffect { 192 public: 193 static GrEffectRef* Create(GrEffectEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry); 194 195 virtual ~EllipseEffect() {}; 196 static const char* Name() { return "Ellipse"; } 197 198 const SkPoint& getCenter() const { return fCenter; } 199 SkVector getRadii() const { return fRadii; } 200 201 GrEffectEdgeType getEdgeType() const { return fEdgeType; } 202 203 typedef GLEllipseEffect GLEffect; 204 205 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 206 207 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 208 209 private: 210 EllipseEffect(GrEffectEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry); 211 212 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 213 214 SkPoint fCenter; 215 SkVector fRadii; 216 GrEffectEdgeType fEdgeType; 217 218 GR_DECLARE_EFFECT_TEST; 219 220 typedef GrEffect INHERITED; 221 }; 222 223 GrEffectRef* EllipseEffect::Create(GrEffectEdgeType edgeType, 224 const SkPoint& center, 225 SkScalar rx, 226 SkScalar ry) { 227 SkASSERT(rx >= 0 && ry >= 0); 228 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEffect, 229 (edgeType, center, rx, ry)))); 230 } 231 232 void EllipseEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 233 *validFlags = 0; 234 } 235 236 const GrBackendEffectFactory& EllipseEffect::getFactory() const { 237 return GrTBackendEffectFactory<EllipseEffect>::getInstance(); 238 } 239 240 EllipseEffect::EllipseEffect(GrEffectEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry) 241 : fCenter(c) 242 , fRadii(SkVector::Make(rx, ry)) 243 , fEdgeType(edgeType) { 244 this->setWillReadFragmentPosition(); 245 } 246 247 bool EllipseEffect::onIsEqual(const GrEffect& other) const { 248 const EllipseEffect& ee = CastEffect<EllipseEffect>(other); 249 return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii; 250 } 251 252 ////////////////////////////////////////////////////////////////////////////// 253 254 GR_DEFINE_EFFECT_TEST(EllipseEffect); 255 256 GrEffectRef* EllipseEffect::TestCreate(SkRandom* random, 257 GrContext*, 258 const GrDrawTargetCaps& caps, 259 GrTexture*[]) { 260 SkPoint center; 261 center.fX = random->nextRangeScalar(0.f, 1000.f); 262 center.fY = random->nextRangeScalar(0.f, 1000.f); 263 SkScalar rx = random->nextRangeF(0.f, 1000.f); 264 SkScalar ry = random->nextRangeF(0.f, 1000.f); 265 GrEffectEdgeType et; 266 do { 267 et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt); 268 } while (kHairlineAA_GrEffectEdgeType == et); 269 return EllipseEffect::Create(et, center, rx, ry); 270 } 271 272 ////////////////////////////////////////////////////////////////////////////// 273 274 class GLEllipseEffect : public GrGLEffect { 275 public: 276 GLEllipseEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 277 278 virtual void emitCode(GrGLShaderBuilder* builder, 279 const GrDrawEffect& drawEffect, 280 EffectKey key, 281 const char* outputColor, 282 const char* inputColor, 283 const TransformedCoordsArray&, 284 const TextureSamplerArray&) SK_OVERRIDE; 285 286 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 287 288 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 289 290 private: 291 GrGLUniformManager::UniformHandle fEllipseUniform; 292 SkPoint fPrevCenter; 293 SkVector fPrevRadii; 294 295 typedef GrGLEffect INHERITED; 296 }; 297 298 GLEllipseEffect::GLEllipseEffect(const GrBackendEffectFactory& factory, 299 const GrDrawEffect& drawEffect) 300 : INHERITED (factory) { 301 fPrevRadii.fX = -1.f; 302 } 303 304 void GLEllipseEffect::emitCode(GrGLShaderBuilder* builder, 305 const GrDrawEffect& drawEffect, 306 EffectKey key, 307 const char* outputColor, 308 const char* inputColor, 309 const TransformedCoordsArray&, 310 const TextureSamplerArray& samplers) { 311 const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>(); 312 const char *ellipseName; 313 // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) 314 fEllipseUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 315 kVec4f_GrSLType, 316 "ellipse", 317 &ellipseName); 318 const char* fragmentPos = builder->fragmentPosition(); 319 320 // d is the offset to the ellipse center 321 builder->fsCodeAppendf("\t\tvec2 d = %s - %s.xy;\n", fragmentPos, ellipseName); 322 builder->fsCodeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName); 323 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. 324 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n"); 325 // grad_dot is the squared length of the gradient of the implicit. 326 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n"); 327 // avoid calling inversesqrt on zero. 328 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); 329 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n"); 330 331 switch (ee.getEdgeType()) { 332 case kFillAA_GrEffectEdgeType: 333 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n"); 334 break; 335 case kInverseFillAA_GrEffectEdgeType: 336 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n"); 337 break; 338 case kFillBW_GrEffectEdgeType: 339 builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n"); 340 break; 341 case kInverseFillBW_GrEffectEdgeType: 342 builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n"); 343 break; 344 case kHairlineAA_GrEffectEdgeType: 345 SkFAIL("Hairline not expected here."); 346 } 347 348 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, 349 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); 350 } 351 352 GrGLEffect::EffectKey GLEllipseEffect::GenKey(const GrDrawEffect& drawEffect, 353 const GrGLCaps&) { 354 const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>(); 355 return ee.getEdgeType(); 356 } 357 358 void GLEllipseEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { 359 const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>(); 360 if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) { 361 SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX); 362 SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY); 363 uman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd); 364 fPrevCenter = ee.getCenter(); 365 fPrevRadii = ee.getRadii(); 366 } 367 } 368 369 ////////////////////////////////////////////////////////////////////////////// 370 371 GrEffectRef* GrOvalEffect::Create(GrEffectEdgeType edgeType, const SkRect& oval) { 372 if (kHairlineAA_GrEffectEdgeType == edgeType) { 373 return NULL; 374 } 375 SkScalar w = oval.width(); 376 SkScalar h = oval.height(); 377 if (SkScalarNearlyEqual(w, h)) { 378 w /= 2; 379 return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w); 380 } else { 381 w /= 2; 382 h /= 2; 383 return EllipseEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h); 384 } 385 386 return NULL; 387 } 388