OLD | NEW |
(Empty) | |
| 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* validFla
gs) 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& crre = CastEffect<CircleEffect>(other); |
| 77 return fEdgeType == crre.fEdgeType && fCenter == crre.fCenter && fRadius ==
crre.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_OVER
RIDE; |
| 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) |
| 141 fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility
, |
| 142 kVec3f_GrSLType, |
| 143 "circle", |
| 144 &circleName); |
| 145 const char* fragmentPos = builder->fragmentPosition(); |
| 146 |
| 147 SkASSERT(kHairlineAA_GrEffectEdgeType != ce.getEdgeType()); |
| 148 if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) { |
| 149 builder->fsCodeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n", |
| 150 circleName, fragmentPos, circleName); |
| 151 } else { |
| 152 builder->fsCodeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n", |
| 153 circleName, fragmentPos, circleName); |
| 154 } |
| 155 if (GrEffectEdgeTypeIsAA(ce.getEdgeType())) { |
| 156 builder->fsCodeAppend("\t\td = clamp(d, 0.0, 1.0);\n"); |
| 157 } else { |
| 158 builder->fsCodeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n"); |
| 159 } |
| 160 |
| 161 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 162 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str())
; |
| 163 } |
| 164 |
| 165 GrGLEffect::EffectKey GLCircleEffect::GenKey(const GrDrawEffect& drawEffect, |
| 166 const GrGLCaps&) { |
| 167 const CircleEffect& ce = drawEffect.castEffect<CircleEffect>(); |
| 168 return ce.getEdgeType(); |
| 169 } |
| 170 |
| 171 void GLCircleEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { |
| 172 const CircleEffect& ce = drawEffect.castEffect<CircleEffect>(); |
| 173 if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) { |
| 174 uman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, ce.getR
adius() + 0.5f); |
| 175 fPrevCenter = ce.getCenter(); |
| 176 fPrevRadius = ce.getRadius(); |
| 177 } |
| 178 } |
| 179 ////////////////////////////////////////////////////////////////////////////// |
| 180 |
| 181 GrEffectRef* GrOvalEffect::Create(GrEffectEdgeType edgeType, const SkRect& oval)
{ |
| 182 if (kHairlineAA_GrEffectEdgeType == edgeType) { |
| 183 return NULL; |
| 184 } |
| 185 SkScalar w = oval.width(); |
| 186 SkScalar h = oval.height(); |
| 187 if (SkScalarNearlyEqual(w, h)) { |
| 188 w /= 2; |
| 189 return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval
.fTop + w), w); |
| 190 } |
| 191 |
| 192 return NULL; |
| 193 } |
OLD | NEW |