OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "gl/builders/GrGLProgramBuilder.h" | 8 #include "gl/builders/GrGLProgramBuilder.h" |
9 #include "GrOvalRenderer.h" | 9 #include "GrOvalRenderer.h" |
10 | 10 |
11 #include "GrEffect.h" | 11 #include "GrEffect.h" |
12 #include "gl/GrGLEffect.h" | 12 #include "gl/GrGLEffect.h" |
13 #include "gl/GrGLSL.h" | 13 #include "gl/GrGLSL.h" |
14 #include "gl/GrGLVertexEffect.h" | 14 #include "gl/GrGLGeometryProcessor.h" |
15 #include "GrTBackendEffectFactory.h" | 15 #include "GrTBackendEffectFactory.h" |
16 | 16 |
17 #include "GrDrawState.h" | 17 #include "GrDrawState.h" |
18 #include "GrDrawTarget.h" | 18 #include "GrDrawTarget.h" |
19 #include "GrGpu.h" | 19 #include "GrGpu.h" |
20 | 20 |
21 #include "SkRRect.h" | 21 #include "SkRRect.h" |
22 #include "SkStrokeRec.h" | 22 #include "SkStrokeRec.h" |
23 #include "SkTLazy.h" | 23 #include "SkTLazy.h" |
24 | 24 |
25 #include "effects/GrVertexEffect.h" | 25 #include "effects/GrGeometryProcessor.h" |
26 #include "effects/GrRRectEffect.h" | 26 #include "effects/GrRRectEffect.h" |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 struct CircleVertex { | 30 struct CircleVertex { |
31 SkPoint fPos; | 31 SkPoint fPos; |
32 SkPoint fOffset; | 32 SkPoint fOffset; |
33 SkScalar fOuterRadius; | 33 SkScalar fOuterRadius; |
34 SkScalar fInnerRadius; | 34 SkScalar fInnerRadius; |
35 }; | 35 }; |
(...skipping 17 matching lines...) Expand all Loading... |
53 | 53 |
54 } | 54 } |
55 | 55 |
56 /////////////////////////////////////////////////////////////////////////////// | 56 /////////////////////////////////////////////////////////////////////////////// |
57 | 57 |
58 /** | 58 /** |
59 * The output of this effect is a modulation of the input color and coverage for
a circle, | 59 * The output of this effect is a modulation of the input color and coverage for
a circle, |
60 * specified as offset_x, offset_y (both from center point), outer radius and in
ner radius. | 60 * specified as offset_x, offset_y (both from center point), outer radius and in
ner radius. |
61 */ | 61 */ |
62 | 62 |
63 class CircleEdgeEffect : public GrVertexEffect { | 63 class CircleEdgeEffect : public GrGeometryProcessor { |
64 public: | 64 public: |
65 static GrEffect* Create(bool stroke) { | 65 static GrEffect* Create(bool stroke) { |
66 GR_CREATE_STATIC_EFFECT(gCircleStrokeEdge, CircleEdgeEffect, (true)); | 66 GR_CREATE_STATIC_EFFECT(gCircleStrokeEdge, CircleEdgeEffect, (true)); |
67 GR_CREATE_STATIC_EFFECT(gCircleFillEdge, CircleEdgeEffect, (false)); | 67 GR_CREATE_STATIC_EFFECT(gCircleFillEdge, CircleEdgeEffect, (false)); |
68 | 68 |
69 if (stroke) { | 69 if (stroke) { |
70 gCircleStrokeEdge->ref(); | 70 gCircleStrokeEdge->ref(); |
71 return gCircleStrokeEdge; | 71 return gCircleStrokeEdge; |
72 } else { | 72 } else { |
73 gCircleFillEdge->ref(); | 73 gCircleFillEdge->ref(); |
74 return gCircleFillEdge; | 74 return gCircleFillEdge; |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
78 virtual void getConstantColorComponents(GrColor* color, | 78 virtual void getConstantColorComponents(GrColor* color, |
79 uint32_t* validFlags) const SK_OVERR
IDE { | 79 uint32_t* validFlags) const SK_OVERR
IDE { |
80 *validFlags = 0; | 80 *validFlags = 0; |
81 } | 81 } |
82 | 82 |
| 83 const GrShaderVar& inCircleEdge() const { return fInCircleEdge; } |
| 84 |
83 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | 85 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
84 return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance(); | 86 return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance(); |
85 } | 87 } |
86 | 88 |
87 virtual ~CircleEdgeEffect() {} | 89 virtual ~CircleEdgeEffect() {} |
88 | 90 |
89 static const char* Name() { return "CircleEdge"; } | 91 static const char* Name() { return "CircleEdge"; } |
90 | 92 |
91 inline bool isStroked() const { return fStroke; } | 93 inline bool isStroked() const { return fStroke; } |
92 | 94 |
93 class GLEffect : public GrGLVertexEffect { | 95 class GLEffect : public GrGLGeometryProcessor { |
94 public: | 96 public: |
95 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | 97 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
96 : INHERITED (factory) {} | 98 : INHERITED (factory) {} |
97 | 99 |
98 virtual void emitCode(GrGLFullProgramBuilder* builder, | 100 virtual void emitCode(GrGLFullProgramBuilder* builder, |
99 const GrDrawEffect& drawEffect, | 101 const GrDrawEffect& drawEffect, |
100 const GrEffectKey& key, | 102 const GrEffectKey& key, |
101 const char* outputColor, | 103 const char* outputColor, |
102 const char* inputColor, | 104 const char* inputColor, |
103 const TransformedCoordsArray&, | 105 const TransformedCoordsArray&, |
104 const TextureSamplerArray& samplers) SK_OVERRIDE { | 106 const TextureSamplerArray& samplers) SK_OVERRIDE { |
105 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE
dgeEffect>(); | 107 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE
dgeEffect>(); |
106 const char *vsName, *fsName; | 108 const char *vsName, *fsName; |
107 builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName)
; | 109 builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName)
; |
108 | 110 |
109 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
(); | 111 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
();; |
110 const SkString* attr0Name = | 112 vsBuilder->codeAppendf("\t%s = %s;\n", vsName, circleEffect.inCircle
Edge().c_str()); |
111 vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndi
ces()[0]); | |
112 vsBuilder->codeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str()); | |
113 | 113 |
114 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); | 114 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); |
115 fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName); | 115 fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName); |
116 fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0
);\n", fsName); | 116 fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0
);\n", fsName); |
117 if (circleEffect.isStroked()) { | 117 if (circleEffect.isStroked()) { |
118 fsBuilder->codeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0
, 1.0);\n", fsName); | 118 fsBuilder->codeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0
, 1.0);\n", fsName); |
119 fsBuilder->codeAppend("\tedgeAlpha *= innerAlpha;\n"); | 119 fsBuilder->codeAppend("\tedgeAlpha *= innerAlpha;\n"); |
120 } | 120 } |
121 | 121 |
122 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, | 122 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, |
123 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeA
lpha")).c_str()); | 123 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeA
lpha")).c_str()); |
124 } | 124 } |
125 | 125 |
126 static void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, | 126 static void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, |
127 GrEffectKeyBuilder* b) { | 127 GrEffectKeyBuilder* b) { |
128 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE
dgeEffect>(); | 128 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE
dgeEffect>(); |
129 b->add32(circleEffect.isStroked()); | 129 b->add32(circleEffect.isStroked()); |
130 } | 130 } |
131 | 131 |
132 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE {} | 132 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE {} |
133 | 133 |
134 private: | 134 private: |
135 typedef GrGLVertexEffect INHERITED; | 135 typedef GrGLGeometryProcessor INHERITED; |
136 }; | 136 }; |
137 | 137 |
138 | 138 |
139 private: | 139 private: |
140 CircleEdgeEffect(bool stroke) : GrVertexEffect() { | 140 CircleEdgeEffect(bool stroke) |
141 this->addVertexAttrib(kVec4f_GrSLType); | 141 : fInCircleEdge(this->addVertexAttrib( |
| 142 GrShaderVar("inCircleEdge", |
| 143 kVec4f_GrSLType, |
| 144 GrShaderVar::kAttribute_TypeModifier))) { |
142 fStroke = stroke; | 145 fStroke = stroke; |
143 } | 146 } |
144 | 147 |
145 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | 148 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
146 const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other); | 149 const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other); |
147 return cee.fStroke == fStroke; | 150 return cee.fStroke == fStroke; |
148 } | 151 } |
149 | 152 |
| 153 const GrShaderVar& fInCircleEdge; |
150 bool fStroke; | 154 bool fStroke; |
151 | 155 |
152 GR_DECLARE_EFFECT_TEST; | 156 GR_DECLARE_EFFECT_TEST; |
153 | 157 |
154 typedef GrVertexEffect INHERITED; | 158 typedef GrGeometryProcessor INHERITED; |
155 }; | 159 }; |
156 | 160 |
157 GR_DEFINE_EFFECT_TEST(CircleEdgeEffect); | 161 GR_DEFINE_EFFECT_TEST(CircleEdgeEffect); |
158 | 162 |
159 GrEffect* CircleEdgeEffect::TestCreate(SkRandom* random, | 163 GrEffect* CircleEdgeEffect::TestCreate(SkRandom* random, |
160 GrContext* context, | 164 GrContext* context, |
161 const GrDrawTargetCaps&, | 165 const GrDrawTargetCaps&, |
162 GrTexture* textures[]) { | 166 GrTexture* textures[]) { |
163 return CircleEdgeEffect::Create(random->nextBool()); | 167 return CircleEdgeEffect::Create(random->nextBool()); |
164 } | 168 } |
165 | 169 |
166 /////////////////////////////////////////////////////////////////////////////// | 170 /////////////////////////////////////////////////////////////////////////////// |
167 | 171 |
168 /** | 172 /** |
169 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned | 173 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned |
170 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, | 174 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, |
171 * in both x and y directions. | 175 * in both x and y directions. |
172 * | 176 * |
173 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. | 177 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. |
174 */ | 178 */ |
175 | 179 |
176 class EllipseEdgeEffect : public GrVertexEffect { | 180 class EllipseEdgeEffect : public GrGeometryProcessor { |
177 public: | 181 public: |
178 static GrEffect* Create(bool stroke) { | 182 static GrEffect* Create(bool stroke) { |
179 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, EllipseEdgeEffect, (true)); | 183 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, EllipseEdgeEffect, (true)); |
180 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, EllipseEdgeEffect, (false)); | 184 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, EllipseEdgeEffect, (false)); |
181 | 185 |
182 if (stroke) { | 186 if (stroke) { |
183 gEllipseStrokeEdge->ref(); | 187 gEllipseStrokeEdge->ref(); |
184 return gEllipseStrokeEdge; | 188 return gEllipseStrokeEdge; |
185 } else { | 189 } else { |
186 gEllipseFillEdge->ref(); | 190 gEllipseFillEdge->ref(); |
187 return gEllipseFillEdge; | 191 return gEllipseFillEdge; |
188 } | 192 } |
189 } | 193 } |
190 | 194 |
191 virtual void getConstantColorComponents(GrColor* color, | 195 virtual void getConstantColorComponents(GrColor* color, |
192 uint32_t* validFlags) const SK_OVERR
IDE { | 196 uint32_t* validFlags) const SK_OVERR
IDE { |
193 *validFlags = 0; | 197 *validFlags = 0; |
194 } | 198 } |
195 | 199 |
196 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | 200 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
197 return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance(); | 201 return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance(); |
198 } | 202 } |
199 | 203 |
200 virtual ~EllipseEdgeEffect() {} | 204 virtual ~EllipseEdgeEffect() {} |
201 | 205 |
202 static const char* Name() { return "EllipseEdge"; } | 206 static const char* Name() { return "EllipseEdge"; } |
203 | 207 |
| 208 const GrShaderVar& inEllipseOffset() const { return fInEllipseOffset; } |
| 209 const GrShaderVar& inEllipseRadii() const { return fInEllipseRadii; } |
| 210 |
204 inline bool isStroked() const { return fStroke; } | 211 inline bool isStroked() const { return fStroke; } |
205 | 212 |
206 class GLEffect : public GrGLVertexEffect { | 213 class GLEffect : public GrGLGeometryProcessor { |
207 public: | 214 public: |
208 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | 215 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
209 : INHERITED (factory) {} | 216 : INHERITED (factory) {} |
210 | 217 |
211 virtual void emitCode(GrGLFullProgramBuilder* builder, | 218 virtual void emitCode(GrGLFullProgramBuilder* builder, |
212 const GrDrawEffect& drawEffect, | 219 const GrDrawEffect& drawEffect, |
213 const GrEffectKey& key, | 220 const GrEffectKey& key, |
214 const char* outputColor, | 221 const char* outputColor, |
215 const char* inputColor, | 222 const char* inputColor, |
216 const TransformedCoordsArray&, | 223 const TransformedCoordsArray&, |
217 const TextureSamplerArray& samplers) SK_OVERRIDE { | 224 const TextureSamplerArray& samplers) SK_OVERRIDE { |
218 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip
seEdgeEffect>(); | 225 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip
seEdgeEffect>(); |
219 | 226 |
220 const char *vsOffsetName, *fsOffsetName; | 227 const char *vsOffsetName, *fsOffsetName; |
221 const char *vsRadiiName, *fsRadiiName; | 228 const char *vsRadiiName, *fsRadiiName; |
222 | 229 |
223 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName
, &fsOffsetName); | 230 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName
, &fsOffsetName); |
224 | 231 |
225 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
(); | 232 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
(); |
226 const SkString* attr0Name = | 233 vsBuilder->codeAppendf("%s = %s;", vsOffsetName, |
227 vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndi
ces()[0]); | 234 ellipseEffect.inEllipseOffset().c_str()); |
228 vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_st
r()); | |
229 | 235 |
230 builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &
fsRadiiName); | 236 builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &
fsRadiiName); |
231 const SkString* attr1Name = | 237 vsBuilder->codeAppendf("%s = %s;", vsRadiiName, ellipseEffect.inElli
pseRadii().c_str()); |
232 vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndi
ces()[1]); | |
233 vsBuilder->codeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str
()); | |
234 | 238 |
235 // for outer curve | 239 // for outer curve |
236 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); | 240 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); |
237 fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffset
Name, fsRadiiName); | 241 fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffset
Name, fsRadiiName); |
238 fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset
) - 1.0;\n"); | 242 fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset
) - 1.0;\n"); |
239 fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fs
RadiiName); | 243 fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fs
RadiiName); |
240 fsBuilder->codeAppend("\tfloat grad_dot = dot(grad, grad);\n"); | 244 fsBuilder->codeAppend("\tfloat grad_dot = dot(grad, grad);\n"); |
241 // avoid calling inversesqrt on zero. | 245 // avoid calling inversesqrt on zero. |
242 fsBuilder->codeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); | 246 fsBuilder->codeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); |
243 fsBuilder->codeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); | 247 fsBuilder->codeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); |
(...skipping 15 matching lines...) Expand all Loading... |
259 static void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, | 263 static void GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&, |
260 GrEffectKeyBuilder* b) { | 264 GrEffectKeyBuilder* b) { |
261 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip
seEdgeEffect>(); | 265 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip
seEdgeEffect>(); |
262 b->add32(ellipseEffect.isStroked()); | 266 b->add32(ellipseEffect.isStroked()); |
263 } | 267 } |
264 | 268 |
265 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE { | 269 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE { |
266 } | 270 } |
267 | 271 |
268 private: | 272 private: |
269 typedef GrGLVertexEffect INHERITED; | 273 typedef GrGLGeometryProcessor INHERITED; |
270 }; | 274 }; |
271 | 275 |
272 private: | 276 private: |
273 EllipseEdgeEffect(bool stroke) : GrVertexEffect() { | 277 EllipseEdgeEffect(bool stroke) |
274 this->addVertexAttrib(kVec2f_GrSLType); | 278 : fInEllipseOffset(this->addVertexAttrib( |
275 this->addVertexAttrib(kVec4f_GrSLType); | 279 GrShaderVar("inEllipseOffset", |
| 280 kVec2f_GrSLType, |
| 281 GrShaderVar::kAttribute_TypeModifier))) |
| 282 , fInEllipseRadii(this->addVertexAttrib( |
| 283 GrShaderVar("inEllipseRadii", |
| 284 kVec4f_GrSLType, |
| 285 GrShaderVar::kAttribute_TypeModifier))) { |
276 fStroke = stroke; | 286 fStroke = stroke; |
277 } | 287 } |
278 | 288 |
279 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | 289 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
280 const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other); | 290 const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other); |
281 return eee.fStroke == fStroke; | 291 return eee.fStroke == fStroke; |
282 } | 292 } |
283 | 293 |
| 294 const GrShaderVar& fInEllipseOffset; |
| 295 const GrShaderVar& fInEllipseRadii; |
284 bool fStroke; | 296 bool fStroke; |
285 | 297 |
286 GR_DECLARE_EFFECT_TEST; | 298 GR_DECLARE_EFFECT_TEST; |
287 | 299 |
288 typedef GrVertexEffect INHERITED; | 300 typedef GrGeometryProcessor INHERITED; |
289 }; | 301 }; |
290 | 302 |
291 GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); | 303 GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); |
292 | 304 |
293 GrEffect* EllipseEdgeEffect::TestCreate(SkRandom* random, | 305 GrEffect* EllipseEdgeEffect::TestCreate(SkRandom* random, |
294 GrContext* context, | 306 GrContext* context, |
295 const GrDrawTargetCaps&, | 307 const GrDrawTargetCaps&, |
296 GrTexture* textures[]) { | 308 GrTexture* textures[]) { |
297 return EllipseEdgeEffect::Create(random->nextBool()); | 309 return EllipseEdgeEffect::Create(random->nextBool()); |
298 } | 310 } |
299 | 311 |
300 /////////////////////////////////////////////////////////////////////////////// | 312 /////////////////////////////////////////////////////////////////////////////// |
301 | 313 |
302 /** | 314 /** |
303 * The output of this effect is a modulation of the input color and coverage for
an ellipse, | 315 * The output of this effect is a modulation of the input color and coverage for
an ellipse, |
304 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The | 316 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The |
305 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by | 317 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by |
306 * using differentials. | 318 * using differentials. |
307 * | 319 * |
308 * The result is device-independent and can be used with any affine matrix. | 320 * The result is device-independent and can be used with any affine matrix. |
309 */ | 321 */ |
310 | 322 |
311 class DIEllipseEdgeEffect : public GrVertexEffect { | 323 class DIEllipseEdgeEffect : public GrGeometryProcessor { |
312 public: | 324 public: |
313 enum Mode { kStroke = 0, kHairline, kFill }; | 325 enum Mode { kStroke = 0, kHairline, kFill }; |
314 | 326 |
315 static GrEffect* Create(Mode mode) { | 327 static GrEffect* Create(Mode mode) { |
316 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStrok
e)); | 328 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStrok
e)); |
317 GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHai
rline)); | 329 GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHai
rline)); |
318 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill)); | 330 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill)); |
319 | 331 |
320 if (kStroke == mode) { | 332 if (kStroke == mode) { |
321 gEllipseStrokeEdge->ref(); | 333 gEllipseStrokeEdge->ref(); |
(...skipping 13 matching lines...) Expand all Loading... |
335 } | 347 } |
336 | 348 |
337 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | 349 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
338 return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance(); | 350 return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance(); |
339 } | 351 } |
340 | 352 |
341 virtual ~DIEllipseEdgeEffect() {} | 353 virtual ~DIEllipseEdgeEffect() {} |
342 | 354 |
343 static const char* Name() { return "DIEllipseEdge"; } | 355 static const char* Name() { return "DIEllipseEdge"; } |
344 | 356 |
| 357 const GrShaderVar& inEllipseOffsets0() const { return fInEllipseOffsets0; } |
| 358 const GrShaderVar& inEllipseOffsets1() const { return fInEllipseOffsets1; } |
| 359 |
345 inline Mode getMode() const { return fMode; } | 360 inline Mode getMode() const { return fMode; } |
346 | 361 |
347 class GLEffect : public GrGLVertexEffect { | 362 class GLEffect : public GrGLGeometryProcessor { |
348 public: | 363 public: |
349 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | 364 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
350 : INHERITED (factory) {} | 365 : INHERITED (factory) {} |
351 | 366 |
352 virtual void emitCode(GrGLFullProgramBuilder* builder, | 367 virtual void emitCode(GrGLFullProgramBuilder* builder, |
353 const GrDrawEffect& drawEffect, | 368 const GrDrawEffect& drawEffect, |
354 const GrEffectKey& key, | 369 const GrEffectKey& key, |
355 const char* outputColor, | 370 const char* outputColor, |
356 const char* inputColor, | 371 const char* inputColor, |
357 const TransformedCoordsArray&, | 372 const TransformedCoordsArray&, |
358 const TextureSamplerArray& samplers) SK_OVERRIDE { | 373 const TextureSamplerArray& samplers) SK_OVERRIDE { |
359 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE
llipseEdgeEffect>(); | 374 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE
llipseEdgeEffect>(); |
360 | 375 |
361 const char *vsOffsetName0, *fsOffsetName0; | 376 const char *vsOffsetName0, *fsOffsetName0; |
362 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0", | 377 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0", |
363 &vsOffsetName0, &fsOffsetName0); | 378 &vsOffsetName0, &fsOffsetName0); |
364 | 379 |
365 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
(); | 380 GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder
(); |
366 const SkString* attr0Name = | 381 vsBuilder->codeAppendf("%s = %s;", vsOffsetName0, |
367 vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndi
ces()[0]); | 382 ellipseEffect.inEllipseOffsets0().c_str()); |
368 vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName0, attr0Name->c_s
tr()); | |
369 const char *vsOffsetName1, *fsOffsetName1; | 383 const char *vsOffsetName1, *fsOffsetName1; |
370 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets1", | 384 builder->addVarying(kVec2f_GrSLType, "EllipseOffsets1", |
371 &vsOffsetName1, &fsOffsetName1); | 385 &vsOffsetName1, &fsOffsetName1); |
372 const SkString* attr1Name = | 386 vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1, |
373 vsBuilder->getEffectAttributeName(drawEffect.getVertexAttribIndi
ces()[1]); | 387 ellipseEffect.inEllipseOffsets1().c_str()); |
374 vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1, attr1Name->c_s
tr()); | |
375 | 388 |
376 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); | 389 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBui
lder(); |
377 SkAssertResult(fsBuilder->enableFeature( | 390 SkAssertResult(fsBuilder->enableFeature( |
378 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); | 391 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); |
379 // for outer curve | 392 // for outer curve |
380 fsBuilder->codeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetNam
e0); | 393 fsBuilder->codeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetNam
e0); |
381 fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset
) - 1.0;\n"); | 394 fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset
) - 1.0;\n"); |
382 fsBuilder->codeAppendf("\tvec2 duvdx = dFdx(%s);\n", fsOffsetName0); | 395 fsBuilder->codeAppendf("\tvec2 duvdx = dFdx(%s);\n", fsOffsetName0); |
383 fsBuilder->codeAppendf("\tvec2 duvdy = dFdy(%s);\n", fsOffsetName0); | 396 fsBuilder->codeAppendf("\tvec2 duvdy = dFdy(%s);\n", fsOffsetName0); |
384 fsBuilder->codeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s
.y*duvdx.y,\n" | 397 fsBuilder->codeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s
.y*duvdx.y,\n" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 const DIEllipseEdgeEffect& ellipseEffect = | 432 const DIEllipseEdgeEffect& ellipseEffect = |
420 drawEffect.castEffect<DIEllipseEdgeEffect>(); | 433 drawEffect.castEffect<DIEllipseEdgeEffect>(); |
421 | 434 |
422 b->add32(ellipseEffect.getMode()); | 435 b->add32(ellipseEffect.getMode()); |
423 } | 436 } |
424 | 437 |
425 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE { | 438 virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&)
SK_OVERRIDE { |
426 } | 439 } |
427 | 440 |
428 private: | 441 private: |
429 typedef GrGLVertexEffect INHERITED; | 442 typedef GrGLGeometryProcessor INHERITED; |
430 }; | 443 }; |
431 | 444 |
432 private: | 445 private: |
433 DIEllipseEdgeEffect(Mode mode) : GrVertexEffect() { | 446 DIEllipseEdgeEffect(Mode mode) |
434 this->addVertexAttrib(kVec2f_GrSLType); | 447 : fInEllipseOffsets0(this->addVertexAttrib( |
435 this->addVertexAttrib(kVec2f_GrSLType); | 448 GrShaderVar("inEllipseOffsets0", |
| 449 kVec2f_GrSLType, |
| 450 GrShaderVar::kAttribute_TypeModifier))) |
| 451 , fInEllipseOffsets1(this->addVertexAttrib( |
| 452 GrShaderVar("inEllipseOffsets1", |
| 453 kVec2f_GrSLType, |
| 454 GrShaderVar::kAttribute_TypeModifier))) { |
436 fMode = mode; | 455 fMode = mode; |
437 } | 456 } |
438 | 457 |
439 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | 458 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
440 const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other); | 459 const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other); |
441 return eee.fMode == fMode; | 460 return eee.fMode == fMode; |
442 } | 461 } |
443 | 462 |
| 463 const GrShaderVar& fInEllipseOffsets0; |
| 464 const GrShaderVar& fInEllipseOffsets1; |
444 Mode fMode; | 465 Mode fMode; |
445 | 466 |
446 GR_DECLARE_EFFECT_TEST; | 467 GR_DECLARE_EFFECT_TEST; |
447 | 468 |
448 typedef GrVertexEffect INHERITED; | 469 typedef GrGeometryProcessor INHERITED; |
449 }; | 470 }; |
450 | 471 |
451 GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect); | 472 GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect); |
452 | 473 |
453 GrEffect* DIEllipseEdgeEffect::TestCreate(SkRandom* random, | 474 GrEffect* DIEllipseEdgeEffect::TestCreate(SkRandom* random, |
454 GrContext* context, | 475 GrContext* context, |
455 const GrDrawTargetCaps&, | 476 const GrDrawTargetCaps&, |
456 GrTexture* textures[]) { | 477 GrTexture* textures[]) { |
457 return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2))); | 478 return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2))); |
458 } | 479 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 halfWidth = SkScalarHalf(strokeWidth); | 566 halfWidth = SkScalarHalf(strokeWidth); |
546 } | 567 } |
547 | 568 |
548 outerRadius += halfWidth; | 569 outerRadius += halfWidth; |
549 if (isStrokeOnly) { | 570 if (isStrokeOnly) { |
550 innerRadius = radius - halfWidth; | 571 innerRadius = radius - halfWidth; |
551 } | 572 } |
552 } | 573 } |
553 | 574 |
554 GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0)
; | 575 GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0)
; |
555 static const int kCircleEdgeAttrIndex = 1; | 576 drawState->setGeometryProcessor(effect)->unref(); |
556 drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref(); | |
557 | 577 |
558 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform | 578 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform |
559 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use
d to compute the | 579 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use
d to compute the |
560 // verts of the bounding box that is rendered and the outset ensures the box
will cover all | 580 // verts of the bounding box that is rendered and the outset ensures the box
will cover all |
561 // pixels partially covered by the circle. | 581 // pixels partially covered by the circle. |
562 outerRadius += SK_ScalarHalf; | 582 outerRadius += SK_ScalarHalf; |
563 innerRadius -= SK_ScalarHalf; | 583 innerRadius -= SK_ScalarHalf; |
564 | 584 |
565 SkRect bounds = SkRect::MakeLTRB( | 585 SkRect bounds = SkRect::MakeLTRB( |
566 center.fX - outerRadius, | 586 center.fX - outerRadius, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 if (!geo.succeeded()) { | 707 if (!geo.succeeded()) { |
688 GrPrintf("Failed to get space for vertices!\n"); | 708 GrPrintf("Failed to get space for vertices!\n"); |
689 return false; | 709 return false; |
690 } | 710 } |
691 | 711 |
692 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 712 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
693 | 713 |
694 GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly && | 714 GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly && |
695 innerXRadius > 0 && innerYRadiu
s > 0); | 715 innerXRadius > 0 && innerYRadiu
s > 0); |
696 | 716 |
697 static const int kEllipseCenterAttrIndex = 1; | 717 drawState->setGeometryProcessor(effect)->unref(); |
698 static const int kEllipseEdgeAttrIndex = 2; | |
699 drawState->setGeometryProcessor(effect, kEllipseCenterAttrIndex, kEllipseEdg
eAttrIndex)->unref(); | |
700 | 718 |
701 // Compute the reciprocals of the radii here to save time in the shader | 719 // Compute the reciprocals of the radii here to save time in the shader |
702 SkScalar xRadRecip = SkScalarInvert(xRadius); | 720 SkScalar xRadRecip = SkScalarInvert(xRadius); |
703 SkScalar yRadRecip = SkScalarInvert(yRadius); | 721 SkScalar yRadRecip = SkScalarInvert(yRadius); |
704 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); | 722 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); |
705 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); | 723 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); |
706 | 724 |
707 // We've extended the outer x radius out half a pixel to antialias. | 725 // We've extended the outer x radius out half a pixel to antialias. |
708 // This will also expand the rect so all the pixels will be captured. | 726 // This will also expand the rect so all the pixels will be captured. |
709 // TODO: Consider if we should use sqrt(2)/2 instead | 727 // TODO: Consider if we should use sqrt(2)/2 instead |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); | 823 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); |
806 if (!geo.succeeded()) { | 824 if (!geo.succeeded()) { |
807 GrPrintf("Failed to get space for vertices!\n"); | 825 GrPrintf("Failed to get space for vertices!\n"); |
808 return false; | 826 return false; |
809 } | 827 } |
810 | 828 |
811 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); | 829 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); |
812 | 830 |
813 GrEffect* effect = DIEllipseEdgeEffect::Create(mode); | 831 GrEffect* effect = DIEllipseEdgeEffect::Create(mode); |
814 | 832 |
815 static const int kEllipseOuterOffsetAttrIndex = 1; | 833 drawState->setGeometryProcessor(effect)->unref(); |
816 static const int kEllipseInnerOffsetAttrIndex = 2; | |
817 drawState->setGeometryProcessor(effect, kEllipseOuterOffsetAttrIndex, | |
818 kEllipseInnerOffsetAttrIndex)->unref(); | |
819 | 834 |
820 // This expands the outer rect so that after CTM we end up with a half-pixel
border | 835 // This expands the outer rect so that after CTM we end up with a half-pixel
border |
821 SkScalar a = vm[SkMatrix::kMScaleX]; | 836 SkScalar a = vm[SkMatrix::kMScaleX]; |
822 SkScalar b = vm[SkMatrix::kMSkewX]; | 837 SkScalar b = vm[SkMatrix::kMSkewX]; |
823 SkScalar c = vm[SkMatrix::kMSkewY]; | 838 SkScalar c = vm[SkMatrix::kMSkewY]; |
824 SkScalar d = vm[SkMatrix::kMScaleY]; | 839 SkScalar d = vm[SkMatrix::kMScaleY]; |
825 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); | 840 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); |
826 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); | 841 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); |
827 // This adjusts the "radius" to include the half-pixel border | 842 // This adjusts the "radius" to include the half-pixel border |
828 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); | 843 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 if (isStrokeOnly) { | 1070 if (isStrokeOnly) { |
1056 innerRadius = xRadius - halfWidth; | 1071 innerRadius = xRadius - halfWidth; |
1057 } | 1072 } |
1058 outerRadius += halfWidth; | 1073 outerRadius += halfWidth; |
1059 bounds.outset(halfWidth, halfWidth); | 1074 bounds.outset(halfWidth, halfWidth); |
1060 } | 1075 } |
1061 | 1076 |
1062 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 1077 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
1063 | 1078 |
1064 GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly); | 1079 GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly); |
1065 static const int kCircleEdgeAttrIndex = 1; | 1080 drawState->setGeometryProcessor(effect)->unref(); |
1066 drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref(); | |
1067 | 1081 |
1068 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 1082 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
1069 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is
used to compute the | 1083 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is
used to compute the |
1070 // verts of the bounding box that is rendered and the outset ensures the
box will cover all | 1084 // verts of the bounding box that is rendered and the outset ensures the
box will cover all |
1071 // pixels partially covered by the circle. | 1085 // pixels partially covered by the circle. |
1072 outerRadius += SK_ScalarHalf; | 1086 outerRadius += SK_ScalarHalf; |
1073 innerRadius -= SK_ScalarHalf; | 1087 innerRadius -= SK_ScalarHalf; |
1074 | 1088 |
1075 // Expand the rect so all the pixels will be captured. | 1089 // Expand the rect so all the pixels will be captured. |
1076 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1090 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 1173 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
1160 | 1174 |
1161 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); | 1175 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); |
1162 if (!geo.succeeded()) { | 1176 if (!geo.succeeded()) { |
1163 GrPrintf("Failed to get space for vertices!\n"); | 1177 GrPrintf("Failed to get space for vertices!\n"); |
1164 return false; | 1178 return false; |
1165 } | 1179 } |
1166 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 1180 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
1167 | 1181 |
1168 GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly); | 1182 GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly); |
1169 static const int kEllipseOffsetAttrIndex = 1; | 1183 drawState->setGeometryProcessor(effect)->unref(); |
1170 static const int kEllipseRadiiAttrIndex = 2; | |
1171 drawState->setGeometryProcessor(effect, | |
1172 kEllipseOffsetAttrIndex, | |
1173 kEllipseRadiiAttrIndex)->unref(); | |
1174 | 1184 |
1175 // Compute the reciprocals of the radii here to save time in the shader | 1185 // Compute the reciprocals of the radii here to save time in the shader |
1176 SkScalar xRadRecip = SkScalarInvert(xRadius); | 1186 SkScalar xRadRecip = SkScalarInvert(xRadius); |
1177 SkScalar yRadRecip = SkScalarInvert(yRadius); | 1187 SkScalar yRadRecip = SkScalarInvert(yRadius); |
1178 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); | 1188 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); |
1179 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); | 1189 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); |
1180 | 1190 |
1181 // Extend the radii out half a pixel to antialias. | 1191 // Extend the radii out half a pixel to antialias. |
1182 SkScalar xOuterRadius = xRadius + SK_ScalarHalf; | 1192 SkScalar xOuterRadius = xRadius + SK_ScalarHalf; |
1183 SkScalar yOuterRadius = yRadius + SK_ScalarHalf; | 1193 SkScalar yOuterRadius = yRadius + SK_ScalarHalf; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1226 | 1236 |
1227 // drop out the middle quad if we're stroked | 1237 // drop out the middle quad if we're stroked |
1228 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1238 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
1229 SK_ARRAY_COUNT(gRRectIndices); | 1239 SK_ARRAY_COUNT(gRRectIndices); |
1230 target->setIndexSourceToBuffer(indexBuffer); | 1240 target->setIndexSourceToBuffer(indexBuffer); |
1231 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou
nds); | 1241 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou
nds); |
1232 } | 1242 } |
1233 | 1243 |
1234 return true; | 1244 return true; |
1235 } | 1245 } |
OLD | NEW |