Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: src/gpu/effects/GrRRectEffect.cpp

Issue 194603004: Add elliptical-corner rrect clip effect. Currently only handles the case where all corners have the… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rename rr effect vars Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrRRectEffect.h" 8 #include "GrRRectEffect.h"
9 9
10 #include "gl/GrGLEffect.h" 10 #include "gl/GrGLEffect.h"
11 #include "gl/GrGLSL.h" 11 #include "gl/GrGLSL.h"
12 #include "GrTBackendEffectFactory.h" 12 #include "GrTBackendEffectFactory.h"
13 13
14 #include "SkRRect.h" 14 #include "SkRRect.h"
15 15
16 using namespace GrRRectEffect; 16 class GLCircularRRectEffect;
17 17
18 class GLRRectEffect; 18 class CircularRRectEffect : public GrEffect {
19
20 class RRectEffect : public GrEffect {
21 public: 19 public:
22 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. 20 // This effect only supports circular corner rrects where the radius is >= k RadiusMin.
23 static const SkScalar kRadiusMin; 21 static const SkScalar kRadiusMin;
24 22
25 enum CornerFlags { 23 enum CornerFlags {
26 kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner), 24 kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner),
27 kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner), 25 kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner),
28 kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner), 26 kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner),
29 kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner), 27 kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner),
30 28
31 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag, 29 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag,
32 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag, 30 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag,
33 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag, 31 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag,
34 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag, 32 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
35 33
36 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag | 34 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag |
37 kBottomLeft_CornerFlag | kBottomRight_CornerFlag, 35 kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
38 36
39 }; 37 };
40 38
41 // The flags are used to indicate which corners are circluar (unflagged corn ers are assumed to 39 // The flags are used to indicate which corners are circluar (unflagged corn ers are assumed to
42 // be square). 40 // be square).
43 static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, c onst SkRRect&); 41 static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, c onst SkRRect&);
44 42
45 virtual ~RRectEffect() {}; 43 virtual ~CircularRRectEffect() {};
46 static const char* Name() { return "RRect"; } 44 static const char* Name() { return "CircularRRect"; }
47 45
48 const SkRRect& getRRect() const { return fRRect; } 46 const SkRRect& getRRect() const { return fRRect; }
49 47
50 uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; } 48 uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; }
51 49
52 GrEffectEdgeType getEdgeType() const { return fEdgeType; } 50 GrEffectEdgeType getEdgeType() const { return fEdgeType; }
53 51
54 typedef GLRRectEffect GLEffect; 52 typedef GLCircularRRectEffect GLEffect;
55 53
56 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; 54 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
57 55
58 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 56 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
59 57
60 private: 58 private:
61 RRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const SkRRect&); 59 CircularRRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const Sk RRect&);
62 60
63 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; 61 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
64 62
65 SkRRect fRRect; 63 SkRRect fRRect;
66 GrEffectEdgeType fEdgeType; 64 GrEffectEdgeType fEdgeType;
67 uint32_t fCircularCornerFlags; 65 uint32_t fCircularCornerFlags;
68 66
69 GR_DECLARE_EFFECT_TEST; 67 GR_DECLARE_EFFECT_TEST;
70 68
71 typedef GrEffect INHERITED; 69 typedef GrEffect INHERITED;
72 }; 70 };
73 71
74 const SkScalar RRectEffect::kRadiusMin = 0.5f; 72 const SkScalar CircularRRectEffect::kRadiusMin = 0.5f;
75 73
76 GrEffectRef* RRectEffect::Create(GrEffectEdgeType edgeType, 74 GrEffectRef* CircularRRectEffect::Create(GrEffectEdgeType edgeType,
77 uint32_t circularCornerFlags, 75 uint32_t circularCornerFlags,
78 const SkRRect& rrect) { 76 const SkRRect& rrect) {
79 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); 77 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType);
80 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, 78 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircularRRectEffect,
81 (edgeType, circularCornerF lags, rrect)))); 79 (edgeType, circularCornerF lags, rrect))));
82 } 80 }
83 81
84 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag s) const { 82 void CircularRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* v alidFlags) const {
85 *validFlags = 0; 83 *validFlags = 0;
86 } 84 }
87 85
88 const GrBackendEffectFactory& RRectEffect::getFactory() const { 86 const GrBackendEffectFactory& CircularRRectEffect::getFactory() const {
89 return GrTBackendEffectFactory<RRectEffect>::getInstance(); 87 return GrTBackendEffectFactory<CircularRRectEffect>::getInstance();
90 } 88 }
91 89
92 RRectEffect::RRectEffect(GrEffectEdgeType edgeType, uint32_t circularCornerFlags , 90 CircularRRectEffect::CircularRRectEffect(GrEffectEdgeType edgeType, uint32_t cir cularCornerFlags,
93 const SkRRect& rrect) 91 const SkRRect& rrect)
94 : fRRect(rrect) 92 : fRRect(rrect)
95 , fEdgeType(edgeType) 93 , fEdgeType(edgeType)
96 , fCircularCornerFlags(circularCornerFlags) { 94 , fCircularCornerFlags(circularCornerFlags) {
97 this->setWillReadFragmentPosition(); 95 this->setWillReadFragmentPosition();
98 } 96 }
99 97
100 bool RRectEffect::onIsEqual(const GrEffect& other) const { 98 bool CircularRRectEffect::onIsEqual(const GrEffect& other) const {
101 const RRectEffect& rre = CastEffect<RRectEffect>(other); 99 const CircularRRectEffect& crre = CastEffect<CircularRRectEffect>(other);
102 // type is derived from fRRect, so no need to check it. 100 // The corner flags are derived from fRRect, so no need to check them.
103 return fEdgeType == rre.fEdgeType && fRRect == rre.fRRect; 101 return fEdgeType == crre.fEdgeType && fRRect == crre.fRRect;
104 } 102 }
105 103
106 ////////////////////////////////////////////////////////////////////////////// 104 //////////////////////////////////////////////////////////////////////////////
107 105
108 GR_DEFINE_EFFECT_TEST(RRectEffect); 106 GR_DEFINE_EFFECT_TEST(CircularRRectEffect);
109 107
110 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, 108 GrEffectRef* CircularRRectEffect::TestCreate(SkRandom* random,
111 GrContext*, 109 GrContext*,
112 const GrDrawTargetCaps& caps, 110 const GrDrawTargetCaps& caps,
113 GrTexture*[]) { 111 GrTexture*[]) {
114 SkScalar w = random->nextRangeScalar(20.f, 1000.f); 112 SkScalar w = random->nextRangeScalar(20.f, 1000.f);
115 SkScalar h = random->nextRangeScalar(20.f, 1000.f); 113 SkScalar h = random->nextRangeScalar(20.f, 1000.f);
116 SkScalar r = random->nextRangeF(kRadiusMin, 9.f); 114 SkScalar r = random->nextRangeF(kRadiusMin, 9.f);
117 SkRRect rrect; 115 SkRRect rrect;
118 rrect.setRectXY(SkRect::MakeWH(w, h), r, r); 116 rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
119 GrEffectRef* effect; 117 GrEffectRef* effect;
120 do { 118 do {
121 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); 119 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt);
122 effect = GrRRectEffect::Create(et, rrect); 120 effect = GrRRectEffect::Create(et, rrect);
123 } while (NULL == effect); 121 } while (NULL == effect);
124 return effect; 122 return effect;
125 } 123 }
126 124
127 ////////////////////////////////////////////////////////////////////////////// 125 //////////////////////////////////////////////////////////////////////////////
128 126
129 class GLRRectEffect : public GrGLEffect { 127 class GLCircularRRectEffect : public GrGLEffect {
130 public: 128 public:
131 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 129 GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
132 130
133 virtual void emitCode(GrGLShaderBuilder* builder, 131 virtual void emitCode(GrGLShaderBuilder* builder,
134 const GrDrawEffect& drawEffect, 132 const GrDrawEffect& drawEffect,
135 EffectKey key, 133 EffectKey key,
136 const char* outputColor, 134 const char* outputColor,
137 const char* inputColor, 135 const char* inputColor,
138 const TransformedCoordsArray&, 136 const TransformedCoordsArray&,
139 const TextureSamplerArray&) SK_OVERRIDE; 137 const TextureSamplerArray&) SK_OVERRIDE;
140 138
141 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 139 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
142 140
143 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; 141 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
144 142
145 private: 143 private:
146 GrGLUniformManager::UniformHandle fInnerRectUniform; 144 GrGLUniformManager::UniformHandle fInnerRectUniform;
147 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform; 145 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform;
148 SkRRect fPrevRRect; 146 SkRRect fPrevRRect;
149 typedef GrGLEffect INHERITED; 147 typedef GrGLEffect INHERITED;
150 }; 148 };
151 149
152 GLRRectEffect::GLRRectEffect(const GrBackendEffectFactory& factory, 150 GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& facto ry,
153 const GrDrawEffect& drawEffect) 151 const GrDrawEffect& drawEffect)
154 : INHERITED (factory) { 152 : INHERITED (factory) {
155 fPrevRRect.setEmpty(); 153 fPrevRRect.setEmpty();
156 } 154 }
157 155
158 void GLRRectEffect::emitCode(GrGLShaderBuilder* builder, 156 void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder,
159 const GrDrawEffect& drawEffect, 157 const GrDrawEffect& drawEffect,
160 EffectKey key, 158 EffectKey key,
161 const char* outputColor, 159 const char* outputColor,
162 const char* inputColor, 160 const char* inputColor,
163 const TransformedCoordsArray&, 161 const TransformedCoordsArray&,
164 const TextureSamplerArray& samplers) { 162 const TextureSamplerArray& samplers) {
165 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); 163 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> ();
166 const char *rectName; 164 const char *rectName;
167 const char *radiusPlusHalfName; 165 const char *radiusPlusHalfName;
168 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom 166 // The inner rect is the rrect bounds inset by the radius. Its left, top, ri ght, and bottom
169 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has 167 // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
170 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by 168 // only rectangular corners, that side's value corresponds to the rect edge' s value outset by
171 // half a pixel. 169 // half a pixel.
172 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, 170 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
173 kVec4f_GrSLType, 171 kVec4f_GrSLType,
174 "innerRect", 172 "innerRect",
175 &rectName); 173 &rectName);
(...skipping 10 matching lines...) Expand all
186 // fragments near the other three edges will get the correct AA. Fragments i n the interior of 184 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
187 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will 185 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will
188 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. 186 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
189 // The code below is a simplified version of the above that performs maxs on the vector 187 // The code below is a simplified version of the above that performs maxs on the vector
190 // components before computing distances and alpha values so that only one d istance computation 188 // components before computing distances and alpha values so that only one d istance computation
191 // need be computed to determine the min alpha. 189 // need be computed to determine the min alpha.
192 // 190 //
193 // For the cases where one half of the rrect is rectangular we drop one of t he x or y 191 // For the cases where one half of the rrect is rectangular we drop one of t he x or y
194 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed 192 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed
195 // alphas together. 193 // alphas together.
196 switch (rre.getCircularCornerFlags()) { 194 switch (crre.getCircularCornerFlags()) {
197 case RRectEffect::kAll_CornerFlags: 195 case CircularRRectEffect::kAll_CornerFlags:
198 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); 196 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
199 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); 197 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName);
200 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; 198 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ;
201 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0. 0, 1.0);\n", 199 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0. 0, 1.0);\n",
202 radiusPlusHalfName); 200 radiusPlusHalfName);
203 break; 201 break;
204 case RRectEffect::kTopLeft_CornerFlag: 202 case CircularRRectEffect::kTopLeft_CornerFlag:
205 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n", rectName, fragmentPos); 203 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n",
204 rectName, fragmentPos);
206 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", 205 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n",
207 rectName, fragmentPos); 206 rectName, fragmentPos);
208 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", 207 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n",
209 rectName, fragmentPos); 208 rectName, fragmentPos);
210 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", 209 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
211 radiusPlusHalfName); 210 radiusPlusHalfName);
212 break; 211 break;
213 case RRectEffect::kTopRight_CornerFlag: 212 case CircularRRectEffect::kTopRight_CornerFlag:
214 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n", 213 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n",
215 fragmentPos, rectName, rectName, fragmentPos) ; 214 fragmentPos, rectName, rectName, fragmentPos) ;
216 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", 215 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n",
217 fragmentPos, rectName); 216 fragmentPos, rectName);
218 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", 217 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n",
219 rectName, fragmentPos); 218 rectName, fragmentPos);
220 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n", 219 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
221 radiusPlusHalfName); 220 radiusPlusHalfName);
222 break; 221 break;
223 case RRectEffect::kBottomRight_CornerFlag: 222 case CircularRRectEffect::kBottomRight_CornerFlag:
224 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n", 223 builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n",
225 fragmentPos, rectName); 224 fragmentPos, rectName);
226 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", 225 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n",
227 fragmentPos, rectName); 226 fragmentPos, rectName);
228 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", 227 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
229 fragmentPos, rectName); 228 fragmentPos, rectName);
230 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla mp(%s - length(dxy), 0.0, 1.0);\n", 229 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * cla mp(%s - length(dxy), 0.0, 1.0);\n",
231 radiusPlusHalfName); 230 radiusPlusHalfName);
232 break; 231 break;
233 case RRectEffect::kBottomLeft_CornerFlag: 232 case CircularRRectEffect::kBottomLeft_CornerFlag:
234 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n", 233 builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n",
235 rectName, fragmentPos, fragmentPos, rectName) ; 234 rectName, fragmentPos, fragmentPos, rectName) ;
236 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", 235 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n",
237 rectName, fragmentPos); 236 rectName, fragmentPos);
238 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", 237 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
239 fragmentPos, rectName); 238 fragmentPos, rectName);
240 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl amp(%s - length(dxy), 0.0, 1.0);\n", 239 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * cl amp(%s - length(dxy), 0.0, 1.0);\n",
241 radiusPlusHalfName); 240 radiusPlusHalfName);
242 break; 241 break;
243 case RRectEffect::kLeft_CornerFlags: 242 case CircularRRectEffect::kLeft_CornerFlags:
244 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); 243 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
245 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos , rectName); 244 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos , rectName);
246 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d y1)), 0.0);\n"); 245 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d y1)), 0.0);\n");
247 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", 246 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n",
248 rectName, fragmentPos); 247 rectName, fragmentPos);
249 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le ngth(dxy), 0.0, 1.0);\n", 248 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le ngth(dxy), 0.0, 1.0);\n",
250 radiusPlusHalfName); 249 radiusPlusHalfName);
251 break; 250 break;
252 case RRectEffect::kTop_CornerFlags: 251 case CircularRRectEffect::kTop_CornerFlags:
253 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); 252 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
254 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos , rectName); 253 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos , rectName);
255 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy 0.y), 0.0);\n"); 254 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy 0.y), 0.0);\n");
256 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", 255 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n",
257 rectName, fragmentPos); 256 rectName, fragmentPos);
258 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l ength(dxy), 0.0, 1.0);\n", 257 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l ength(dxy), 0.0, 1.0);\n",
259 radiusPlusHalfName); 258 radiusPlusHalfName);
260 break; 259 break;
261 case RRectEffect::kRight_CornerFlags: 260 case CircularRRectEffect::kRight_CornerFlags:
262 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f ragmentPos); 261 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f ragmentPos);
263 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); 262 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName);
264 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1 .y)), 0.0);\n"); 263 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1 .y)), 0.0);\n");
265 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", 264 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n",
266 fragmentPos, rectName); 265 fragmentPos, rectName);
267 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len gth(dxy), 0.0, 1.0);\n", 266 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len gth(dxy), 0.0, 1.0);\n",
268 radiusPlusHalfName); 267 radiusPlusHalfName);
269 break; 268 break;
270 case RRectEffect::kBottom_CornerFlags: 269 case CircularRRectEffect::kBottom_CornerFlags:
271 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f ragmentPos); 270 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f ragmentPos);
272 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); 271 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName);
273 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy 1.y), 0.0);\n"); 272 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy 1.y), 0.0);\n");
274 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", 273 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
275 fragmentPos, rectName); 274 fragmentPos, rectName);
276 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n", 275 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n",
277 radiusPlusHalfName); 276 radiusPlusHalfName);
278 break; 277 break;
279 } 278 }
280 279
281 if (kInverseFillAA_GrEffectEdgeType == rre.getEdgeType()) { 280 if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) {
282 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); 281 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
283 } 282 }
284 283
285 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, 284 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
286 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); 285 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r());
287 } 286 }
288 287
289 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons t GrGLCaps&) { 288 GrGLEffect::EffectKey GLCircularRRectEffect::GenKey(const GrDrawEffect& drawEffe ct,
290 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); 289 const GrGLCaps&) {
290 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> ();
291 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); 291 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8);
292 return (rre.getCircularCornerFlags() << 3) | rre.getEdgeType(); 292 return (crre.getCircularCornerFlags() << 3) | crre.getEdgeType();
293 } 293 }
294 294
295 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { 295 void GLCircularRRectEffect::setData(const GrGLUniformManager& uman,
296 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); 296 const GrDrawEffect& drawEffect) {
297 const SkRRect& rrect = rre.getRRect(); 297 const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect> ();
298 const SkRRect& rrect = crre.getRRect();
298 if (rrect != fPrevRRect) { 299 if (rrect != fPrevRRect) {
299 SkRect rect = rrect.getBounds(); 300 SkRect rect = rrect.getBounds();
300 SkScalar radius = 0; 301 SkScalar radius = 0;
301 switch (rre.getCircularCornerFlags()) { 302 switch (crre.getCircularCornerFlags()) {
302 case RRectEffect::kAll_CornerFlags: 303 case CircularRRectEffect::kAll_CornerFlags:
303 SkASSERT(rrect.isSimpleCircular()); 304 SkASSERT(rrect.isSimpleCircular());
304 radius = rrect.getSimpleRadii().fX; 305 radius = rrect.getSimpleRadii().fX;
305 SkASSERT(radius >= RRectEffect::kRadiusMin); 306 SkASSERT(radius >= CircularRRectEffect::kRadiusMin);
306 rect.inset(radius, radius); 307 rect.inset(radius, radius);
307 break; 308 break;
308 case RRectEffect::kTopLeft_CornerFlag: 309 case CircularRRectEffect::kTopLeft_CornerFlag:
309 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 310 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
310 rect.fLeft += radius; 311 rect.fLeft += radius;
311 rect.fTop += radius; 312 rect.fTop += radius;
312 rect.fRight += 0.5f; 313 rect.fRight += 0.5f;
313 rect.fBottom += 0.5f; 314 rect.fBottom += 0.5f;
314 break; 315 break;
315 case RRectEffect::kTopRight_CornerFlag: 316 case CircularRRectEffect::kTopRight_CornerFlag:
316 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; 317 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
317 rect.fLeft -= 0.5; 318 rect.fLeft -= 0.5;
318 rect.fTop += radius; 319 rect.fTop += radius;
319 rect.fRight -= radius; 320 rect.fRight -= radius;
320 rect.fBottom += 0.5f; 321 rect.fBottom += 0.5f;
321 break; 322 break;
322 case RRectEffect::kBottomRight_CornerFlag: 323 case CircularRRectEffect::kBottomRight_CornerFlag:
323 radius = rrect.radii(SkRRect::kLowerRight_Corner).fX; 324 radius = rrect.radii(SkRRect::kLowerRight_Corner).fX;
324 rect.fLeft -= 0.5; 325 rect.fLeft -= 0.5;
325 rect.fTop -= 0.5; 326 rect.fTop -= 0.5;
326 rect.fRight -= radius; 327 rect.fRight -= radius;
327 rect.fBottom -= radius; 328 rect.fBottom -= radius;
328 break; 329 break;
329 case RRectEffect::kBottomLeft_CornerFlag: 330 case CircularRRectEffect::kBottomLeft_CornerFlag:
330 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; 331 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
331 rect.fLeft += radius; 332 rect.fLeft += radius;
332 rect.fTop -= 0.5; 333 rect.fTop -= 0.5;
333 rect.fRight += 0.5; 334 rect.fRight += 0.5;
334 rect.fBottom -= radius; 335 rect.fBottom -= radius;
335 break; 336 break;
336 case RRectEffect::kLeft_CornerFlags: 337 case CircularRRectEffect::kLeft_CornerFlags:
337 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 338 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
338 rect.fLeft += radius; 339 rect.fLeft += radius;
339 rect.fTop += radius; 340 rect.fTop += radius;
340 rect.fRight += 0.5f; 341 rect.fRight += 0.5f;
341 rect.fBottom -= radius; 342 rect.fBottom -= radius;
342 break; 343 break;
343 case RRectEffect::kTop_CornerFlags: 344 case CircularRRectEffect::kTop_CornerFlags:
344 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; 345 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
345 rect.fLeft += radius; 346 rect.fLeft += radius;
346 rect.fTop += radius; 347 rect.fTop += radius;
347 rect.fRight -= radius; 348 rect.fRight -= radius;
348 rect.fBottom += 0.5f; 349 rect.fBottom += 0.5f;
349 break; 350 break;
350 case RRectEffect::kRight_CornerFlags: 351 case CircularRRectEffect::kRight_CornerFlags:
351 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; 352 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
352 rect.fLeft -= 0.5f; 353 rect.fLeft -= 0.5f;
353 rect.fTop += radius; 354 rect.fTop += radius;
354 rect.fRight -= radius; 355 rect.fRight -= radius;
355 rect.fBottom -= radius; 356 rect.fBottom -= radius;
356 break; 357 break;
357 case RRectEffect::kBottom_CornerFlags: 358 case CircularRRectEffect::kBottom_CornerFlags:
358 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; 359 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
359 rect.fLeft += radius; 360 rect.fLeft += radius;
360 rect.fTop -= 0.5f; 361 rect.fTop -= 0.5f;
361 rect.fRight -= radius; 362 rect.fRight -= radius;
362 rect.fBottom -= radius; 363 rect.fBottom -= radius;
363 break; 364 break;
364 default: 365 default:
365 GrCrash("Should have been one of the above cases."); 366 GrCrash("Should have been one of the above cases.");
366 } 367 }
367 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); 368 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom);
368 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); 369 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f);
369 fPrevRRect = rrect; 370 fPrevRRect = rrect;
370 } 371 }
371 } 372 }
372 373
373 ////////////////////////////////////////////////////////////////////////////// 374 //////////////////////////////////////////////////////////////////////////////
374 375
376 class GLEllipticalRRectEffect;
377
378 class EllipticalRRectEffect : public GrEffect {
379 public:
380 // This effect only supports circular corner rrects where the radius is >= k RadiusMin.
jvanverth1 2014/03/12 13:44:28 Fix comment? It might also be worth mentioning tha
bsalomon 2014/03/12 14:20:15 Done.
381 static const SkScalar kRadiusMin;
382
383 static GrEffectRef* Create(GrEffectEdgeType, const SkRRect&);
384
385 virtual ~EllipticalRRectEffect() {};
386 static const char* Name() { return "EllipticalRRect"; }
387
388 const SkRRect& getRRect() const { return fRRect; }
389
390 GrEffectEdgeType getEdgeType() const { return fEdgeType; }
391
392 typedef GLEllipticalRRectEffect GLEffect;
393
394 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
395
396 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
397
398 private:
399 EllipticalRRectEffect(GrEffectEdgeType, const SkRRect&);
400
401 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
402
403 SkRRect fRRect;
404 GrEffectEdgeType fEdgeType;
405
406 GR_DECLARE_EFFECT_TEST;
407
408 typedef GrEffect INHERITED;
409 };
410
411 const SkScalar EllipticalRRectEffect::kRadiusMin = 0.5f;
412
413 GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType,
414 const SkRRect& rrect) {
415 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType);
416 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (ed geType, rrect))));
417 }
418
419 void EllipticalRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
420 *validFlags = 0;
421 }
422
423 const GrBackendEffectFactory& EllipticalRRectEffect::getFactory() const {
424 return GrTBackendEffectFactory<EllipticalRRectEffect>::getInstance();
425 }
426
427 EllipticalRRectEffect::EllipticalRRectEffect(GrEffectEdgeType edgeType, const Sk RRect& rrect)
428 : fRRect(rrect)
429 , fEdgeType(edgeType){
430 this->setWillReadFragmentPosition();
431 }
432
433 bool EllipticalRRectEffect::onIsEqual(const GrEffect& other) const {
434 const EllipticalRRectEffect& erre = CastEffect<EllipticalRRectEffect>(other) ;
435 return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect;
436 }
437
438 //////////////////////////////////////////////////////////////////////////////
439
440 GR_DEFINE_EFFECT_TEST(EllipticalRRectEffect);
441
442 GrEffectRef* EllipticalRRectEffect::TestCreate(SkRandom* random,
443 GrContext*,
444 const GrDrawTargetCaps& caps,
445 GrTexture*[]) {
446 SkScalar w = random->nextRangeScalar(20.f, 1000.f);
447 SkScalar h = random->nextRangeScalar(20.f, 1000.f);
448 SkScalar rx = random->nextRangeF(kRadiusMin, 9.f);
449 SkScalar ry = random->nextRangeF(kRadiusMin, 9.f);
450 SkRRect rrect;
451 rrect.setRectXY(SkRect::MakeWH(w, h), rx, ry);
452 GrEffectRef* effect;
453 do {
454 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt);
455 effect = EllipticalRRectEffect::Create(et, rrect);
456 } while (NULL == effect);
457 return effect;
458 }
459
460 //////////////////////////////////////////////////////////////////////////////
461
462 class GLEllipticalRRectEffect : public GrGLEffect {
463 public:
464 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
465
466 virtual void emitCode(GrGLShaderBuilder* builder,
467 const GrDrawEffect& drawEffect,
468 EffectKey key,
469 const char* outputColor,
470 const char* inputColor,
471 const TransformedCoordsArray&,
472 const TextureSamplerArray&) SK_OVERRIDE;
473
474 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
475
476 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
477
478 private:
479 GrGLUniformManager::UniformHandle fInnerRectUniform;
480 GrGLUniformManager::UniformHandle fInvRadiusXYSqdUniform;
481 SkRRect fPrevRRect;
482 typedef GrGLEffect INHERITED;
483 };
484
485 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f actory,
486 const GrDrawEffect& drawEffect)
487 : INHERITED (factory) {
488 fPrevRRect.setEmpty();
489 }
490
491 void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder,
492 const GrDrawEffect& drawEffect,
493 EffectKey key,
494 const char* outputColor,
495 const char* inputColor,
496 const TransformedCoordsArray&,
497 const TextureSamplerArray& samplers) {
498 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>();
499 const char *rectName;
500 const char *invRadiusXYSqdName;
501 // The inner rect is the rrect bounds inset by the x/y radii
502 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity,
503 kVec4f_GrSLType,
504 "innerRect",
505 &rectName);
506 fInvRadiusXYSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi sibility,
507 kVec2f_GrSLType,
508 "invRadiusXY",
509 &invRadiusXYSqdName);
510 const char* fragmentPos = builder->fragmentPosition();
511 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
512 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant
513 // to that corner. This means that points near the interior near the rrect t op edge will have
514 // a vector that points straight up for both the TL left and TR corners. Com puting an
515 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly,
516 // fragments near the other three edges will get the correct AA. Fragments i n the interior of
517 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will
518 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas.
519 // The code below is a simplified version of the above that performs maxs on the vector
520 // components before computing distances and alpha values so that only one d istance computation
521 // need be computed to determine the min alpha.
522 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos);
523 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name);
524 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
525 // Z is the x/y offsets divided by squared radii.
526 builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiusXYSqdName);
527 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
528 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
529 // grad_dot is the squared length of the gradient of the implicit.
530 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n", fragmentPo s);
531 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
532 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n",
533 fragmentPos);
534
535 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) {
536 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n");
537 } else {
538 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n");
539 }
540
541 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
542 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r());
543 }
544
545 GrGLEffect::EffectKey GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEf fect,
546 const GrGLCaps&) {
547 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>();
548 return erre.getEdgeType();
549 }
550
551 void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman,
552 const GrDrawEffect& drawEffect) {
553 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>();
554 const SkRRect& rrect = erre.getRRect();
555 if (rrect != fPrevRRect) {
556 SkRect rect = rrect.getBounds();
557 SkASSERT(rrect.isSimple());
558 const SkVector& radius = rrect.getSimpleRadii();
559 SkASSERT(radius.fX >= EllipticalRRectEffect::kRadiusMin);
560 SkASSERT(radius.fY >= EllipticalRRectEffect::kRadiusMin);
561 rect.inset(radius.fX, radius.fY);
562 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom);
563 uman.set2f(fInvRadiusXYSqdUniform, 1.f / (radius.fX * radius.fX),
564 1.f / (radius.fY * radius.fY));
565 fPrevRRect = rrect;
566 }
567 }
568
569 //////////////////////////////////////////////////////////////////////////////
570
375 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) { 571 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) {
376 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) { 572 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) {
377 return NULL; 573 return NULL;
378 } 574 }
379 uint32_t cornerFlags; 575 uint32_t cornerFlags;
380 if (rrect.isSimpleCircular()) { 576 if (rrect.isSimple()) {
381 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { 577 if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) {
382 return NULL; 578 if (rrect.getSimpleRadii().fX < CircularRRectEffect::kRadiusMin) {
579 return NULL;
580 }
581 cornerFlags = CircularRRectEffect::kAll_CornerFlags;
582 } else {
583 if (rrect.getSimpleRadii().fX < EllipticalRRectEffect::kRadiusMin ||
584 rrect.getSimpleRadii().fY < EllipticalRRectEffect::kRadiusMin) {
585 return NULL;
586 }
587 return EllipticalRRectEffect::Create(edgeType, rrect);
383 } 588 }
384 cornerFlags = RRectEffect::kAll_CornerFlags;
385 } else if (rrect.isComplex()) { 589 } else if (rrect.isComplex()) {
386 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. 590 // Check for the "tab" cases - two adjacent circular corners and two squ are corners.
387 SkScalar radius = 0; 591 SkScalar radius = 0;
388 cornerFlags = 0; 592 cornerFlags = 0;
389 for (int c = 0; c < 4; ++c) { 593 for (int c = 0; c < 4; ++c) {
390 const SkVector& r = rrect.radii((SkRRect::Corner)c); 594 const SkVector& r = rrect.radii((SkRRect::Corner)c);
391 SkASSERT((0 == r.fX) == (0 == r.fY)); 595 SkASSERT((0 == r.fX) == (0 == r.fY));
392 if (0 == r.fX) { 596 if (0 == r.fX) {
393 continue; 597 continue;
394 } 598 }
395 if (r.fX != r.fY) { 599 if (r.fX != r.fY) {
396 return NULL; 600 return NULL;
397 } 601 }
398 if (!cornerFlags) { 602 if (!cornerFlags) {
399 radius = r.fX; 603 radius = r.fX;
400 if (radius < RRectEffect::kRadiusMin) { 604 if (radius < CircularRRectEffect::kRadiusMin) {
401 return NULL; 605 return NULL;
402 } 606 }
403 cornerFlags = 1 << c; 607 cornerFlags = 1 << c;
404 } else { 608 } else {
405 if (r.fX != radius) { 609 if (r.fX != radius) {
406 return NULL; 610 return NULL;
407 } 611 }
408 cornerFlags |= 1 << c; 612 cornerFlags |= 1 << c;
409 } 613 }
410 } 614 }
411 615
412 switch (cornerFlags) { 616 switch (cornerFlags) {
413 case RRectEffect::kTopLeft_CornerFlag: 617 case CircularRRectEffect::kTopLeft_CornerFlag:
414 case RRectEffect::kTopRight_CornerFlag: 618 case CircularRRectEffect::kTopRight_CornerFlag:
415 case RRectEffect::kBottomRight_CornerFlag: 619 case CircularRRectEffect::kBottomRight_CornerFlag:
416 case RRectEffect::kBottomLeft_CornerFlag: 620 case CircularRRectEffect::kBottomLeft_CornerFlag:
417 case RRectEffect::kLeft_CornerFlags: 621 case CircularRRectEffect::kLeft_CornerFlags:
418 case RRectEffect::kTop_CornerFlags: 622 case CircularRRectEffect::kTop_CornerFlags:
419 case RRectEffect::kRight_CornerFlags: 623 case CircularRRectEffect::kRight_CornerFlags:
420 case RRectEffect::kBottom_CornerFlags: 624 case CircularRRectEffect::kBottom_CornerFlags:
421 case RRectEffect::kAll_CornerFlags: 625 case CircularRRectEffect::kAll_CornerFlags:
422 break; 626 break;
423 default: 627 default:
424 return NULL; 628 return NULL;
425 } 629 }
426 } else { 630 } else {
427 return NULL; 631 return NULL;
428 } 632 }
429 return RRectEffect::Create(edgeType, cornerFlags, rrect); 633 return CircularRRectEffect::Create(edgeType, cornerFlags, rrect);
430 } 634 }
OLDNEW
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698