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 "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
9 | 9 |
10 #include "gl/builders/GrGLProgramBuilder.h" | 10 #include "gl/builders/GrGLProgramBuilder.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 | 69 |
70 if (stroke) { | 70 if (stroke) { |
71 gCircleStrokeEdge->ref(); | 71 gCircleStrokeEdge->ref(); |
72 return gCircleStrokeEdge; | 72 return gCircleStrokeEdge; |
73 } else { | 73 } else { |
74 gCircleFillEdge->ref(); | 74 gCircleFillEdge->ref(); |
75 return gCircleFillEdge; | 75 return gCircleFillEdge; |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 const GrShaderVar& inCircleEdge() const { return fInCircleEdge; } | 79 const GrAttribute* inPosition() const { return fInPosition; } |
| 80 const GrAttribute* inCircleEdge() const { return fInCircleEdge; } |
80 | 81 |
81 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | 82 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { |
82 return GrTBackendGeometryProcessorFactory<CircleEdgeEffect>::getInstance
(); | 83 return GrTBackendGeometryProcessorFactory<CircleEdgeEffect>::getInstance
(); |
83 } | 84 } |
84 | 85 |
85 virtual ~CircleEdgeEffect() {} | 86 virtual ~CircleEdgeEffect() {} |
86 | 87 |
87 static const char* Name() { return "CircleEdge"; } | 88 static const char* Name() { return "CircleEdge"; } |
88 | 89 |
89 inline bool isStroked() const { return fStroke; } | 90 inline bool isStroked() const { return fStroke; } |
90 | 91 |
91 class GLProcessor : public GrGLGeometryProcessor { | 92 class GLProcessor : public GrGLGeometryProcessor { |
92 public: | 93 public: |
93 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | 94 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) |
94 : INHERITED (factory) {} | 95 : INHERITED (factory) {} |
95 | 96 |
96 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | 97 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
97 const CircleEdgeEffect& circleEffect = args.fGP.cast<CircleEdgeEffec
t>(); | 98 const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>(); |
| 99 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
| 100 |
98 GrGLVertToFrag v(kVec4f_GrSLType); | 101 GrGLVertToFrag v(kVec4f_GrSLType); |
99 args.fPB->addVarying("CircleEdge", &v); | 102 args.fPB->addVarying("CircleEdge", &v); |
| 103 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->fNa
me); |
100 | 104 |
101 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();; | 105 // setup coord outputs |
102 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), circleEffect.inCircleE
dge().c_str()); | 106 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.i
nPosition()->fName); |
| 107 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPo
sition()->fName); |
103 | 108 |
104 // setup position varying | 109 // setup position varying |
105 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), | 110 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), |
106 vsBuilder->uViewM(), vsBuilder->inPosition())
; | 111 vsBuilder->uViewM(), ce.inPosition()->fName); |
107 | 112 |
108 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | 113 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); |
109 fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); | 114 fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); |
110 fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);
", v.fsIn()); | 115 fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);
", v.fsIn()); |
111 if (circleEffect.isStroked()) { | 116 if (ce.isStroked()) { |
112 fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0,
1.0);", | 117 fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0,
1.0);", |
113 v.fsIn()); | 118 v.fsIn()); |
114 fsBuilder->codeAppend("edgeAlpha *= innerAlpha;"); | 119 fsBuilder->codeAppend("edgeAlpha *= innerAlpha;"); |
115 } | 120 } |
116 | 121 |
117 fsBuilder->codeAppendf("%s = %s;\n", args.fOutput, | 122 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); |
118 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edge
Alpha")).c_str()); | |
119 } | 123 } |
120 | 124 |
121 static void GenKey(const GrProcessor& processor, const GrGLCaps&, | 125 static void GenKey(const GrProcessor& processor, const GrGLCaps&, |
122 GrProcessorKeyBuilder* b) { | 126 GrProcessorKeyBuilder* b) { |
123 const CircleEdgeEffect& circleEffect = processor.cast<CircleEdgeEffe
ct>(); | 127 const CircleEdgeEffect& circleEffect = processor.cast<CircleEdgeEffe
ct>(); |
124 b->add32(circleEffect.isStroked()); | 128 b->add32(circleEffect.isStroked()); |
125 } | 129 } |
126 | 130 |
127 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE {} | 131 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE {} |
128 | 132 |
129 private: | 133 private: |
130 typedef GrGLGeometryProcessor INHERITED; | 134 typedef GrGLGeometryProcessor INHERITED; |
131 }; | 135 }; |
132 | 136 |
133 | 137 |
134 private: | 138 private: |
135 CircleEdgeEffect(bool stroke) | 139 CircleEdgeEffect(bool stroke) { |
136 : fInCircleEdge(this->addVertexAttrib( | 140 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
137 GrShaderVar("inCircleEdge", | 141 fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", |
138 kVec4f_GrSLType, | 142 kVec4f_GrVertexAttrib
Type)); |
139 GrShaderVar::kAttribute_TypeModifier))) { | |
140 fStroke = stroke; | 143 fStroke = stroke; |
141 } | 144 } |
142 | 145 |
143 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 146 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
144 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); | 147 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); |
145 return cee.fStroke == fStroke; | 148 return cee.fStroke == fStroke; |
146 } | 149 } |
147 | 150 |
148 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { | 151 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { |
149 inout->mulByUnknownAlpha(); | 152 inout->mulByUnknownAlpha(); |
150 } | 153 } |
151 | 154 |
152 const GrShaderVar& fInCircleEdge; | 155 const GrAttribute* fInPosition; |
| 156 const GrAttribute* fInCircleEdge; |
153 bool fStroke; | 157 bool fStroke; |
154 | 158 |
155 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 159 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
156 | 160 |
157 typedef GrGeometryProcessor INHERITED; | 161 typedef GrGeometryProcessor INHERITED; |
158 }; | 162 }; |
159 | 163 |
160 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); | 164 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); |
161 | 165 |
162 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, | 166 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, |
(...skipping 29 matching lines...) Expand all Loading... |
192 } | 196 } |
193 | 197 |
194 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | 198 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { |
195 return GrTBackendGeometryProcessorFactory<EllipseEdgeEffect>::getInstanc
e(); | 199 return GrTBackendGeometryProcessorFactory<EllipseEdgeEffect>::getInstanc
e(); |
196 } | 200 } |
197 | 201 |
198 virtual ~EllipseEdgeEffect() {} | 202 virtual ~EllipseEdgeEffect() {} |
199 | 203 |
200 static const char* Name() { return "EllipseEdge"; } | 204 static const char* Name() { return "EllipseEdge"; } |
201 | 205 |
202 const GrShaderVar& inEllipseOffset() const { return fInEllipseOffset; } | 206 |
203 const GrShaderVar& inEllipseRadii() const { return fInEllipseRadii; } | 207 const GrAttribute* inPosition() const { return fInPosition; } |
| 208 const GrAttribute* inEllipseOffset() const { return fInEllipseOffset; } |
| 209 const GrAttribute* inEllipseRadii() const { return fInEllipseRadii; } |
204 | 210 |
205 inline bool isStroked() const { return fStroke; } | 211 inline bool isStroked() const { return fStroke; } |
206 | 212 |
207 class GLProcessor : public GrGLGeometryProcessor { | 213 class GLProcessor : public GrGLGeometryProcessor { |
208 public: | 214 public: |
209 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | 215 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) |
210 : INHERITED (factory) {} | 216 : INHERITED (factory) {} |
211 | 217 |
212 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | 218 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
213 const EllipseEdgeEffect& ellipseEffect = args.fGP.cast<EllipseEdgeEf
fect>(); | 219 const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>(); |
| 220 |
| 221 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
214 | 222 |
215 GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType); | 223 GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType); |
216 args.fPB->addVarying("EllipseOffsets", &ellipseOffsets); | 224 args.fPB->addVarying("EllipseOffsets", &ellipseOffsets); |
217 | |
218 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
219 vsBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), | 225 vsBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), |
220 ellipseEffect.inEllipseOffset().c_str()); | 226 ee.inEllipseOffset()->fName); |
221 | 227 |
222 GrGLVertToFrag ellipseRadii(kVec4f_GrSLType); | 228 GrGLVertToFrag ellipseRadii(kVec4f_GrSLType); |
223 args.fPB->addVarying("EllipseRadii", &ellipseRadii); | 229 args.fPB->addVarying("EllipseRadii", &ellipseRadii); |
224 vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), | 230 vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), |
225 ellipseEffect.inEllipseRadii().c_str()); | 231 ee.inEllipseRadii()->fName); |
| 232 |
| 233 // setup coord outputs |
| 234 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.i
nPosition()->fName); |
| 235 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPo
sition()->fName); |
226 | 236 |
227 // setup position varying | 237 // setup position varying |
228 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), | 238 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), |
229 vsBuilder->uViewM(), vsBuilder->inPosition())
; | 239 vsBuilder->uViewM(), ee.inPosition()->fName); |
230 | 240 |
231 // for outer curve | 241 // for outer curve |
232 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | 242 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); |
233 fsBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOffse
ts.fsIn(), | 243 fsBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOffse
ts.fsIn(), |
234 ellipseRadii.fsIn()); | 244 ellipseRadii.fsIn()); |
235 fsBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset)
- 1.0;"); | 245 fsBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset)
- 1.0;"); |
236 fsBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", ellips
eRadii.fsIn()); | 246 fsBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", ellips
eRadii.fsIn()); |
237 fsBuilder->codeAppend("float grad_dot = dot(grad, grad);"); | 247 fsBuilder->codeAppend("float grad_dot = dot(grad, grad);"); |
238 | 248 |
239 // avoid calling inversesqrt on zero. | 249 // avoid calling inversesqrt on zero. |
240 fsBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); | 250 fsBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); |
241 fsBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); | 251 fsBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); |
242 fsBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0,
1.0);"); | 252 fsBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0,
1.0);"); |
243 | 253 |
244 // for inner curve | 254 // for inner curve |
245 if (ellipseEffect.isStroked()) { | 255 if (ee.isStroked()) { |
246 fsBuilder->codeAppendf("scaledOffset = %s*%s.zw;", | 256 fsBuilder->codeAppendf("scaledOffset = %s*%s.zw;", |
247 ellipseOffsets.fsIn(), ellipseRadii.fsIn(
)); | 257 ellipseOffsets.fsIn(), ellipseRadii.fsIn(
)); |
248 fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) -
1.0;"); | 258 fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) -
1.0;"); |
249 fsBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", | 259 fsBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", |
250 ellipseRadii.fsIn()); | 260 ellipseRadii.fsIn()); |
251 fsBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); | 261 fsBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); |
252 fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0,
1.0);"); | 262 fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0,
1.0);"); |
253 } | 263 } |
254 | 264 |
255 fsBuilder->codeAppendf("%s = %s;", args.fOutput, | 265 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); |
256 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edge
Alpha")).c_str()); | |
257 } | 266 } |
258 | 267 |
259 static void GenKey(const GrProcessor& processor, const GrGLCaps&, | 268 static void GenKey(const GrProcessor& processor, const GrGLCaps&, |
260 GrProcessorKeyBuilder* b) { | 269 GrProcessorKeyBuilder* b) { |
261 const EllipseEdgeEffect& ellipseEffect = processor.cast<EllipseEdgeE
ffect>(); | 270 const EllipseEdgeEffect& ellipseEffect = processor.cast<EllipseEdgeE
ffect>(); |
262 b->add32(ellipseEffect.isStroked()); | 271 b->add32(ellipseEffect.isStroked()); |
263 } | 272 } |
264 | 273 |
265 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE { | 274 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE { |
266 } | 275 } |
267 | 276 |
268 private: | 277 private: |
269 typedef GrGLGeometryProcessor INHERITED; | 278 typedef GrGLGeometryProcessor INHERITED; |
270 }; | 279 }; |
271 | 280 |
272 private: | 281 private: |
273 EllipseEdgeEffect(bool stroke) | 282 EllipseEdgeEffect(bool stroke) { |
274 : fInEllipseOffset(this->addVertexAttrib( | 283 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
275 GrShaderVar("inEllipseOffset", | 284 fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", |
276 kVec2f_GrSLType, | 285 kVec2f_GrVertexAtt
ribType)); |
277 GrShaderVar::kAttribute_TypeModifier))) | 286 fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", |
278 , fInEllipseRadii(this->addVertexAttrib( | 287 kVec4f_GrVertexAttr
ibType)); |
279 GrShaderVar("inEllipseRadii", | |
280 kVec4f_GrSLType, | |
281 GrShaderVar::kAttribute_TypeModifier))) { | |
282 fStroke = stroke; | 288 fStroke = stroke; |
283 } | 289 } |
284 | 290 |
285 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 291 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
286 const EllipseEdgeEffect& eee = other.cast<EllipseEdgeEffect>(); | 292 const EllipseEdgeEffect& eee = other.cast<EllipseEdgeEffect>(); |
287 return eee.fStroke == fStroke; | 293 return eee.fStroke == fStroke; |
288 } | 294 } |
289 | 295 |
290 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { | 296 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { |
291 inout->mulByUnknownAlpha(); | 297 inout->mulByUnknownAlpha(); |
292 } | 298 } |
293 | 299 |
294 const GrShaderVar& fInEllipseOffset; | 300 const GrAttribute* fInPosition; |
295 const GrShaderVar& fInEllipseRadii; | 301 const GrAttribute* fInEllipseOffset; |
| 302 const GrAttribute* fInEllipseRadii; |
296 bool fStroke; | 303 bool fStroke; |
297 | 304 |
298 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 305 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
299 | 306 |
300 typedef GrGeometryProcessor INHERITED; | 307 typedef GrGeometryProcessor INHERITED; |
301 }; | 308 }; |
302 | 309 |
303 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); | 310 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); |
304 | 311 |
305 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, | 312 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 } | 349 } |
343 | 350 |
344 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | 351 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { |
345 return GrTBackendGeometryProcessorFactory<DIEllipseEdgeEffect>::getInsta
nce(); | 352 return GrTBackendGeometryProcessorFactory<DIEllipseEdgeEffect>::getInsta
nce(); |
346 } | 353 } |
347 | 354 |
348 virtual ~DIEllipseEdgeEffect() {} | 355 virtual ~DIEllipseEdgeEffect() {} |
349 | 356 |
350 static const char* Name() { return "DIEllipseEdge"; } | 357 static const char* Name() { return "DIEllipseEdge"; } |
351 | 358 |
352 const GrShaderVar& inEllipseOffsets0() const { return fInEllipseOffsets0; } | 359 const GrAttribute* inPosition() const { return fInPosition; } |
353 const GrShaderVar& inEllipseOffsets1() const { return fInEllipseOffsets1; } | 360 const GrAttribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } |
| 361 const GrAttribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } |
354 | 362 |
355 inline Mode getMode() const { return fMode; } | 363 inline Mode getMode() const { return fMode; } |
356 | 364 |
357 class GLProcessor : public GrGLGeometryProcessor { | 365 class GLProcessor : public GrGLGeometryProcessor { |
358 public: | 366 public: |
359 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | 367 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) |
360 : INHERITED (factory) {} | 368 : INHERITED (factory) {} |
361 | 369 |
362 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | 370 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
363 const DIEllipseEdgeEffect& ellipseEffect = args.fGP.cast<DIEllipseEd
geEffect>(); | 371 const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>()
; |
| 372 |
| 373 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
364 | 374 |
365 GrGLVertToFrag offsets0(kVec2f_GrSLType); | 375 GrGLVertToFrag offsets0(kVec2f_GrSLType); |
366 args.fPB->addVarying("EllipseOffsets0", &offsets0); | 376 args.fPB->addVarying("EllipseOffsets0", &offsets0); |
367 | |
368 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
369 vsBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), | 377 vsBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), |
370 ellipseEffect.inEllipseOffsets0().c_str()); | 378 ee.inEllipseOffsets0()->fName); |
371 | 379 |
372 GrGLVertToFrag offsets1(kVec2f_GrSLType); | 380 GrGLVertToFrag offsets1(kVec2f_GrSLType); |
373 args.fPB->addVarying("EllipseOffsets1", &offsets1); | 381 args.fPB->addVarying("EllipseOffsets1", &offsets1); |
374 vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), | 382 vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), |
375 ellipseEffect.inEllipseOffsets1().c_str()); | 383 ee.inEllipseOffsets1()->fName); |
| 384 |
| 385 // setup coord outputs |
| 386 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.i
nPosition()->fName); |
| 387 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPo
sition()->fName); |
376 | 388 |
377 // setup position varying | 389 // setup position varying |
378 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), | 390 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), |
379 vsBuilder->uViewM(), vsBuilder->inPosition())
; | 391 vsBuilder->uViewM(), ee.inPosition()->fName); |
380 | 392 |
381 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | 393 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); |
382 SkAssertResult(fsBuilder->enableFeature( | 394 SkAssertResult(fsBuilder->enableFeature( |
383 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); | 395 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); |
384 // for outer curve | 396 // for outer curve |
385 fsBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn()
); | 397 fsBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn()
); |
386 fsBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset)
- 1.0;"); | 398 fsBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset)
- 1.0;"); |
387 fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); | 399 fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); |
388 fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); | 400 fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); |
389 fsBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y
*duvdx.y," | 401 fsBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y
*duvdx.y," |
390 " 2.0*%s.x*duvdy.x + 2.0*%s.y
*duvdy.y);", | 402 " 2.0*%s.x*duvdy.x + 2.0*%s.y
*duvdy.y);", |
391 offsets0.fsIn(), offsets0.fsIn(), offsets0.fs
In(), offsets0.fsIn()); | 403 offsets0.fsIn(), offsets0.fsIn(), offsets0.fs
In(), offsets0.fsIn()); |
392 | 404 |
393 fsBuilder->codeAppend("float grad_dot = dot(grad, grad);"); | 405 fsBuilder->codeAppend("float grad_dot = dot(grad, grad);"); |
394 // avoid calling inversesqrt on zero. | 406 // avoid calling inversesqrt on zero. |
395 fsBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); | 407 fsBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); |
396 fsBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); | 408 fsBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); |
397 if (kHairline == ellipseEffect.getMode()) { | 409 if (kHairline == ee.getMode()) { |
398 // can probably do this with one step | 410 // can probably do this with one step |
399 fsBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen,
0.0, 1.0);"); | 411 fsBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen,
0.0, 1.0);"); |
400 fsBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0,
1.0);"); | 412 fsBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0,
1.0);"); |
401 } else { | 413 } else { |
402 fsBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen,
0.0, 1.0);"); | 414 fsBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen,
0.0, 1.0);"); |
403 } | 415 } |
404 | 416 |
405 // for inner curve | 417 // for inner curve |
406 if (kStroke == ellipseEffect.getMode()) { | 418 if (kStroke == ee.getMode()) { |
407 fsBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn())
; | 419 fsBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn())
; |
408 fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) -
1.0;"); | 420 fsBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) -
1.0;"); |
409 fsBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); | 421 fsBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); |
410 fsBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); | 422 fsBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); |
411 fsBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*
duvdx.y," | 423 fsBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*
duvdx.y," |
412 " 2.0*%s.x*duvdy.x + 2.0*%s.y*
duvdy.y);", | 424 " 2.0*%s.x*duvdy.x + 2.0*%s.y*
duvdy.y);", |
413 offsets1.fsIn(), offsets1.fsIn(), offsets
1.fsIn(), | 425 offsets1.fsIn(), offsets1.fsIn(), offsets
1.fsIn(), |
414 offsets1.fsIn()); | 426 offsets1.fsIn()); |
415 fsBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); | 427 fsBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); |
416 fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0,
1.0);"); | 428 fsBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0,
1.0);"); |
417 } | 429 } |
418 | 430 |
419 fsBuilder->codeAppendf("%s = %s;", args.fOutput, | 431 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); |
420 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edge
Alpha")).c_str()); | |
421 } | 432 } |
422 | 433 |
423 static void GenKey(const GrProcessor& processor, const GrGLCaps&, | 434 static void GenKey(const GrProcessor& processor, const GrGLCaps&, |
424 GrProcessorKeyBuilder* b) { | 435 GrProcessorKeyBuilder* b) { |
425 const DIEllipseEdgeEffect& ellipseEffect = processor.cast<DIEllipseE
dgeEffect>(); | 436 const DIEllipseEdgeEffect& ellipseEffect = processor.cast<DIEllipseE
dgeEffect>(); |
426 | 437 |
427 b->add32(ellipseEffect.getMode()); | 438 b->add32(ellipseEffect.getMode()); |
428 } | 439 } |
429 | 440 |
430 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE { | 441 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE { |
431 } | 442 } |
432 | 443 |
433 private: | 444 private: |
434 typedef GrGLGeometryProcessor INHERITED; | 445 typedef GrGLGeometryProcessor INHERITED; |
435 }; | 446 }; |
436 | 447 |
437 private: | 448 private: |
438 DIEllipseEdgeEffect(Mode mode) | 449 DIEllipseEdgeEffect(Mode mode) { |
439 : fInEllipseOffsets0(this->addVertexAttrib( | 450 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
440 GrShaderVar("inEllipseOffsets0", | 451 fInEllipseOffsets0 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s0", |
441 kVec2f_GrSLType, | 452 kVec2f_GrVertexA
ttribType)); |
442 GrShaderVar::kAttribute_TypeModifier))) | 453 fInEllipseOffsets1 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s1", |
443 , fInEllipseOffsets1(this->addVertexAttrib( | 454 kVec2f_GrVertexA
ttribType)); |
444 GrShaderVar("inEllipseOffsets1", | |
445 kVec2f_GrSLType, | |
446 GrShaderVar::kAttribute_TypeModifier))) { | |
447 fMode = mode; | 455 fMode = mode; |
448 } | 456 } |
449 | 457 |
450 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 458 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
451 const DIEllipseEdgeEffect& eee = other.cast<DIEllipseEdgeEffect>(); | 459 const DIEllipseEdgeEffect& eee = other.cast<DIEllipseEdgeEffect>(); |
452 return eee.fMode == fMode; | 460 return eee.fMode == fMode; |
453 } | 461 } |
454 | 462 |
455 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { | 463 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { |
456 inout->mulByUnknownAlpha(); | 464 inout->mulByUnknownAlpha(); |
457 } | 465 } |
458 | 466 |
459 const GrShaderVar& fInEllipseOffsets0; | 467 const GrAttribute* fInPosition; |
460 const GrShaderVar& fInEllipseOffsets1; | 468 const GrAttribute* fInEllipseOffsets0; |
| 469 const GrAttribute* fInEllipseOffsets1; |
461 Mode fMode; | 470 Mode fMode; |
462 | 471 |
463 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 472 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
464 | 473 |
465 typedef GrGeometryProcessor INHERITED; | 474 typedef GrGeometryProcessor INHERITED; |
466 }; | 475 }; |
467 | 476 |
468 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); | 477 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); |
469 | 478 |
470 GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random, | 479 GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 return this->drawEllipse(target, drawState, context, useCoverageAA, oval
, stroke); | 519 return this->drawEllipse(target, drawState, context, useCoverageAA, oval
, stroke); |
511 } else { | 520 } else { |
512 return false; | 521 return false; |
513 } | 522 } |
514 | 523 |
515 return true; | 524 return true; |
516 } | 525 } |
517 | 526 |
518 /////////////////////////////////////////////////////////////////////////////// | 527 /////////////////////////////////////////////////////////////////////////////// |
519 | 528 |
520 // position + edge | |
521 extern const GrVertexAttrib gCircleVertexAttribs[] = { | |
522 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | |
523 {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttr
ibBinding} | |
524 }; | |
525 | |
526 void GrOvalRenderer::drawCircle(GrDrawTarget* target, | 529 void GrOvalRenderer::drawCircle(GrDrawTarget* target, |
527 GrDrawState* drawState, | 530 GrDrawState* drawState, |
528 const GrContext* context, | 531 const GrContext* context, |
529 bool useCoverageAA, | 532 bool useCoverageAA, |
530 const SkRect& circle, | 533 const SkRect& circle, |
531 const SkStrokeRec& stroke) | 534 const SkStrokeRec& stroke) |
532 { | 535 { |
533 const SkMatrix& vm = drawState->getViewMatrix(); | 536 const SkMatrix& vm = drawState->getViewMatrix(); |
534 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 537 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
535 vm.mapPoints(¢er, 1); | 538 vm.mapPoints(¢er, 1); |
536 SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); | 539 SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); |
537 SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); | 540 SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); |
538 | 541 |
539 GrDrawState::AutoViewMatrixRestore avmr; | 542 GrDrawState::AutoViewMatrixRestore avmr; |
540 if (!avmr.setIdentity(drawState)) { | 543 if (!avmr.setIdentity(drawState)) { |
541 return; | 544 return; |
542 } | 545 } |
543 | 546 |
544 drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVert
exAttribs), | |
545 sizeof(CircleVertex)); | |
546 | |
547 GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(
), 0); | |
548 if (!geo.succeeded()) { | |
549 SkDebugf("Failed to get space for vertices!\n"); | |
550 return; | |
551 } | |
552 | |
553 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | |
554 | |
555 SkStrokeRec::Style style = stroke.getStyle(); | 547 SkStrokeRec::Style style = stroke.getStyle(); |
556 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 548 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
557 SkStrokeRec::kHairline_Style == style; | 549 SkStrokeRec::kHairline_Style == style; |
558 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 550 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
559 | 551 |
560 SkScalar innerRadius = 0.0f; | 552 SkScalar innerRadius = 0.0f; |
561 SkScalar outerRadius = radius; | 553 SkScalar outerRadius = radius; |
562 SkScalar halfWidth = 0; | 554 SkScalar halfWidth = 0; |
563 if (hasStroke) { | 555 if (hasStroke) { |
564 if (SkScalarNearlyZero(strokeWidth)) { | 556 if (SkScalarNearlyZero(strokeWidth)) { |
565 halfWidth = SK_ScalarHalf; | 557 halfWidth = SK_ScalarHalf; |
566 } else { | 558 } else { |
567 halfWidth = SkScalarHalf(strokeWidth); | 559 halfWidth = SkScalarHalf(strokeWidth); |
568 } | 560 } |
569 | 561 |
570 outerRadius += halfWidth; | 562 outerRadius += halfWidth; |
571 if (isStrokeOnly) { | 563 if (isStrokeOnly) { |
572 innerRadius = radius - halfWidth; | 564 innerRadius = radius - halfWidth; |
573 } | 565 } |
574 } | 566 } |
575 | 567 |
576 GrGeometryProcessor* gp = CircleEdgeEffect::Create(isStrokeOnly && innerRadi
us > 0); | 568 GrGeometryProcessor* gp = CircleEdgeEffect::Create(isStrokeOnly && innerRadi
us > 0); |
577 drawState->setGeometryProcessor(gp)->unref(); | 569 drawState->setGeometryProcessor(gp)->unref(); |
578 | 570 |
| 571 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 572 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); |
| 573 if (!geo.succeeded()) { |
| 574 SkDebugf("Failed to get space for vertices!\n"); |
| 575 return; |
| 576 } |
| 577 |
| 578 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 579 |
579 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform | 580 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform |
580 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use
d to compute the | 581 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use
d to compute the |
581 // verts of the bounding box that is rendered and the outset ensures the box
will cover all | 582 // verts of the bounding box that is rendered and the outset ensures the box
will cover all |
582 // pixels partially covered by the circle. | 583 // pixels partially covered by the circle. |
583 outerRadius += SK_ScalarHalf; | 584 outerRadius += SK_ScalarHalf; |
584 innerRadius -= SK_ScalarHalf; | 585 innerRadius -= SK_ScalarHalf; |
585 | 586 |
586 SkRect bounds = SkRect::MakeLTRB( | 587 SkRect bounds = SkRect::MakeLTRB( |
587 center.fX - outerRadius, | 588 center.fX - outerRadius, |
588 center.fY - outerRadius, | 589 center.fY - outerRadius, |
(...skipping 21 matching lines...) Expand all Loading... |
610 verts[3].fOuterRadius = outerRadius; | 611 verts[3].fOuterRadius = outerRadius; |
611 verts[3].fInnerRadius = innerRadius; | 612 verts[3].fInnerRadius = innerRadius; |
612 | 613 |
613 target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer()); | 614 target->setIndexSourceToBuffer(context->getGpu()->getQuadIndexBuffer()); |
614 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6,
&bounds); | 615 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 4, 6,
&bounds); |
615 target->resetIndexSource(); | 616 target->resetIndexSource(); |
616 } | 617 } |
617 | 618 |
618 /////////////////////////////////////////////////////////////////////////////// | 619 /////////////////////////////////////////////////////////////////////////////// |
619 | 620 |
620 // position + offset + 1/radii | |
621 extern const GrVertexAttrib gEllipseVertexAttribs[] = { | |
622 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi
ng}, | |
623 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAt
tribBinding}, | |
624 {kVec4f_GrVertexAttribType, 2*sizeof(SkPoint), kGeometryProcessor_GrVertexAt
tribBinding} | |
625 }; | |
626 | |
627 // position + offsets | |
628 extern const GrVertexAttrib gDIEllipseVertexAttribs[] = { | |
629 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi
ng}, | |
630 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAt
tribBinding}, | |
631 {kVec2f_GrVertexAttribType, 2*sizeof(SkPoint), kGeometryProcessor_GrVertexAt
tribBinding}, | |
632 }; | |
633 | |
634 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, | 621 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, |
635 GrDrawState* drawState, | 622 GrDrawState* drawState, |
636 const GrContext* context, | 623 const GrContext* context, |
637 bool useCoverageAA, | 624 bool useCoverageAA, |
638 const SkRect& ellipse, | 625 const SkRect& ellipse, |
639 const SkStrokeRec& stroke) | 626 const SkStrokeRec& stroke) |
640 { | 627 { |
641 #ifdef SK_DEBUG | 628 #ifdef SK_DEBUG |
642 { | 629 { |
643 // we should have checked for this previously | 630 // we should have checked for this previously |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 | 684 |
698 xRadius += scaledStroke.fX; | 685 xRadius += scaledStroke.fX; |
699 yRadius += scaledStroke.fY; | 686 yRadius += scaledStroke.fY; |
700 } | 687 } |
701 | 688 |
702 GrDrawState::AutoViewMatrixRestore avmr; | 689 GrDrawState::AutoViewMatrixRestore avmr; |
703 if (!avmr.setIdentity(drawState)) { | 690 if (!avmr.setIdentity(drawState)) { |
704 return false; | 691 return false; |
705 } | 692 } |
706 | 693 |
707 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVe
rtexAttribs), | 694 GrGeometryProcessor* gp = EllipseEdgeEffect::Create(isStrokeOnly && |
708 sizeof(EllipseVertex)); | 695 innerXRadius > 0 && inne
rYRadius > 0); |
709 | 696 |
710 GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(
), 0); | 697 drawState->setGeometryProcessor(gp)->unref(); |
| 698 |
| 699 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 700 SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); |
711 if (!geo.succeeded()) { | 701 if (!geo.succeeded()) { |
712 SkDebugf("Failed to get space for vertices!\n"); | 702 SkDebugf("Failed to get space for vertices!\n"); |
713 return false; | 703 return false; |
714 } | 704 } |
715 | 705 |
716 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 706 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
717 | 707 |
718 GrGeometryProcessor* gp = EllipseEdgeEffect::Create(isStrokeOnly && | |
719 innerXRadius > 0 && inne
rYRadius > 0); | |
720 | |
721 drawState->setGeometryProcessor(gp)->unref(); | |
722 | |
723 // Compute the reciprocals of the radii here to save time in the shader | 708 // Compute the reciprocals of the radii here to save time in the shader |
724 SkScalar xRadRecip = SkScalarInvert(xRadius); | 709 SkScalar xRadRecip = SkScalarInvert(xRadius); |
725 SkScalar yRadRecip = SkScalarInvert(yRadius); | 710 SkScalar yRadRecip = SkScalarInvert(yRadius); |
726 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); | 711 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); |
727 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); | 712 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); |
728 | 713 |
729 // We've extended the outer x radius out half a pixel to antialias. | 714 // We've extended the outer x radius out half a pixel to antialias. |
730 // This will also expand the rect so all the pixels will be captured. | 715 // This will also expand the rect so all the pixels will be captured. |
731 // TODO: Consider if we should use sqrt(2)/2 instead | 716 // TODO: Consider if we should use sqrt(2)/2 instead |
732 xRadius += SK_ScalarHalf; | 717 xRadius += SK_ScalarHalf; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 xRadius += strokeWidth; | 802 xRadius += strokeWidth; |
818 yRadius += strokeWidth; | 803 yRadius += strokeWidth; |
819 } | 804 } |
820 if (DIEllipseEdgeEffect::kStroke == mode) { | 805 if (DIEllipseEdgeEffect::kStroke == mode) { |
821 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : | 806 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : |
822 DIEllipseEdgeEffect::kFi
ll; | 807 DIEllipseEdgeEffect::kFi
ll; |
823 } | 808 } |
824 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); | 809 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); |
825 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); | 810 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); |
826 | 811 |
827 drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllip
seVertexAttribs), | 812 GrGeometryProcessor* gp = DIEllipseEdgeEffect::Create(mode); |
828 sizeof(DIEllipseVertex)
); | |
829 | 813 |
830 GrDrawTarget::AutoReleaseGeometry geo(target, 4, drawState->getVertexStride(
), 0); | 814 drawState->setGeometryProcessor(gp)->unref(); |
| 815 |
| 816 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 817 SkASSERT(gp->getVertexStride() == sizeof(DIEllipseVertex)); |
831 if (!geo.succeeded()) { | 818 if (!geo.succeeded()) { |
832 SkDebugf("Failed to get space for vertices!\n"); | 819 SkDebugf("Failed to get space for vertices!\n"); |
833 return false; | 820 return false; |
834 } | 821 } |
835 | 822 |
836 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); | 823 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); |
837 | 824 |
838 GrGeometryProcessor* gp = DIEllipseEdgeEffect::Create(mode); | |
839 | |
840 drawState->setGeometryProcessor(gp)->unref(); | |
841 | |
842 // This expands the outer rect so that after CTM we end up with a half-pixel
border | 825 // This expands the outer rect so that after CTM we end up with a half-pixel
border |
843 SkScalar a = vm[SkMatrix::kMScaleX]; | 826 SkScalar a = vm[SkMatrix::kMScaleX]; |
844 SkScalar b = vm[SkMatrix::kMSkewX]; | 827 SkScalar b = vm[SkMatrix::kMSkewX]; |
845 SkScalar c = vm[SkMatrix::kMSkewY]; | 828 SkScalar c = vm[SkMatrix::kMSkewY]; |
846 SkScalar d = vm[SkMatrix::kMScaleY]; | 829 SkScalar d = vm[SkMatrix::kMScaleY]; |
847 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); | 830 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); |
848 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); | 831 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); |
849 // This adjusts the "radius" to include the half-pixel border | 832 // This adjusts the "radius" to include the half-pixel border |
850 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); | 833 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); |
851 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius); | 834 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 } | 1048 } |
1066 | 1049 |
1067 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly, context->g
etGpu()); | 1050 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly, context->g
etGpu()); |
1068 if (NULL == indexBuffer) { | 1051 if (NULL == indexBuffer) { |
1069 SkDebugf("Failed to create index buffer!\n"); | 1052 SkDebugf("Failed to create index buffer!\n"); |
1070 return false; | 1053 return false; |
1071 } | 1054 } |
1072 | 1055 |
1073 // if the corners are circles, use the circle renderer | 1056 // if the corners are circles, use the circle renderer |
1074 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { | 1057 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { |
1075 drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircle
VertexAttribs), | |
1076 sizeof(CircleVertex)); | |
1077 | |
1078 GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexSt
ride(), 0); | |
1079 if (!geo.succeeded()) { | |
1080 SkDebugf("Failed to get space for vertices!\n"); | |
1081 return false; | |
1082 } | |
1083 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | |
1084 | |
1085 SkScalar innerRadius = 0.0f; | 1058 SkScalar innerRadius = 0.0f; |
1086 SkScalar outerRadius = xRadius; | 1059 SkScalar outerRadius = xRadius; |
1087 SkScalar halfWidth = 0; | 1060 SkScalar halfWidth = 0; |
1088 if (hasStroke) { | 1061 if (hasStroke) { |
1089 if (SkScalarNearlyZero(scaledStroke.fX)) { | 1062 if (SkScalarNearlyZero(scaledStroke.fX)) { |
1090 halfWidth = SK_ScalarHalf; | 1063 halfWidth = SK_ScalarHalf; |
1091 } else { | 1064 } else { |
1092 halfWidth = SkScalarHalf(scaledStroke.fX); | 1065 halfWidth = SkScalarHalf(scaledStroke.fX); |
1093 } | 1066 } |
1094 | 1067 |
1095 if (isStrokeOnly) { | 1068 if (isStrokeOnly) { |
1096 innerRadius = xRadius - halfWidth; | 1069 innerRadius = xRadius - halfWidth; |
1097 } | 1070 } |
1098 outerRadius += halfWidth; | 1071 outerRadius += halfWidth; |
1099 bounds.outset(halfWidth, halfWidth); | 1072 bounds.outset(halfWidth, halfWidth); |
1100 } | 1073 } |
1101 | 1074 |
1102 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 1075 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
1103 | 1076 |
1104 GrGeometryProcessor* effect = CircleEdgeEffect::Create(isStrokeOnly); | 1077 GrGeometryProcessor* effect = CircleEdgeEffect::Create(isStrokeOnly); |
1105 drawState->setGeometryProcessor(effect)->unref(); | 1078 drawState->setGeometryProcessor(effect)->unref(); |
1106 | 1079 |
| 1080 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1081 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); |
| 1082 if (!geo.succeeded()) { |
| 1083 SkDebugf("Failed to get space for vertices!\n"); |
| 1084 return false; |
| 1085 } |
| 1086 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 1087 |
1107 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 1088 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
1108 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is
used to compute the | 1089 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is
used to compute the |
1109 // verts of the bounding box that is rendered and the outset ensures the
box will cover all | 1090 // verts of the bounding box that is rendered and the outset ensures the
box will cover all |
1110 // pixels partially covered by the circle. | 1091 // pixels partially covered by the circle. |
1111 outerRadius += SK_ScalarHalf; | 1092 outerRadius += SK_ScalarHalf; |
1112 innerRadius -= SK_ScalarHalf; | 1093 innerRadius -= SK_ScalarHalf; |
1113 | 1094 |
1114 // Expand the rect so all the pixels will be captured. | 1095 // Expand the rect so all the pixels will be captured. |
1115 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1096 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
1116 | 1097 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 | 1135 |
1155 // drop out the middle quad if we're stroked | 1136 // drop out the middle quad if we're stroked |
1156 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1137 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
1157 SK_ARRAY_COUNT(gRRectIndices); | 1138 SK_ARRAY_COUNT(gRRectIndices); |
1158 target->setIndexSourceToBuffer(indexBuffer); | 1139 target->setIndexSourceToBuffer(indexBuffer); |
1159 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, | 1140 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, |
1160 &bounds); | 1141 &bounds); |
1161 | 1142 |
1162 // otherwise we use the ellipse renderer | 1143 // otherwise we use the ellipse renderer |
1163 } else { | 1144 } else { |
1164 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllip
seVertexAttribs), | |
1165 sizeof(EllipseVertex)
); | |
1166 | |
1167 SkScalar innerXRadius = 0.0f; | 1145 SkScalar innerXRadius = 0.0f; |
1168 SkScalar innerYRadius = 0.0f; | 1146 SkScalar innerYRadius = 0.0f; |
1169 if (hasStroke) { | 1147 if (hasStroke) { |
1170 if (SkScalarNearlyZero(scaledStroke.length())) { | 1148 if (SkScalarNearlyZero(scaledStroke.length())) { |
1171 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1149 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
1172 } else { | 1150 } else { |
1173 scaledStroke.scale(SK_ScalarHalf); | 1151 scaledStroke.scale(SK_ScalarHalf); |
1174 } | 1152 } |
1175 | 1153 |
1176 // we only handle thick strokes for near-circular ellipses | 1154 // we only handle thick strokes for near-circular ellipses |
(...skipping 14 matching lines...) Expand all Loading... |
1191 innerYRadius = yRadius - scaledStroke.fY; | 1169 innerYRadius = yRadius - scaledStroke.fY; |
1192 } | 1170 } |
1193 | 1171 |
1194 xRadius += scaledStroke.fX; | 1172 xRadius += scaledStroke.fX; |
1195 yRadius += scaledStroke.fY; | 1173 yRadius += scaledStroke.fY; |
1196 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 1174 bounds.outset(scaledStroke.fX, scaledStroke.fY); |
1197 } | 1175 } |
1198 | 1176 |
1199 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 1177 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
1200 | 1178 |
1201 GrDrawTarget::AutoReleaseGeometry geo(target, 16, drawState->getVertexSt
ride(), 0); | 1179 GrGeometryProcessor* effect = EllipseEdgeEffect::Create(isStrokeOnly); |
| 1180 drawState->setGeometryProcessor(effect)->unref(); |
| 1181 |
| 1182 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1183 SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); |
1202 if (!geo.succeeded()) { | 1184 if (!geo.succeeded()) { |
1203 SkDebugf("Failed to get space for vertices!\n"); | 1185 SkDebugf("Failed to get space for vertices!\n"); |
1204 return false; | 1186 return false; |
1205 } | 1187 } |
| 1188 |
1206 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 1189 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
1207 | 1190 |
1208 GrGeometryProcessor* effect = EllipseEdgeEffect::Create(isStrokeOnly); | |
1209 drawState->setGeometryProcessor(effect)->unref(); | |
1210 | |
1211 // Compute the reciprocals of the radii here to save time in the shader | 1191 // Compute the reciprocals of the radii here to save time in the shader |
1212 SkScalar xRadRecip = SkScalarInvert(xRadius); | 1192 SkScalar xRadRecip = SkScalarInvert(xRadius); |
1213 SkScalar yRadRecip = SkScalarInvert(yRadius); | 1193 SkScalar yRadRecip = SkScalarInvert(yRadius); |
1214 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); | 1194 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); |
1215 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); | 1195 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); |
1216 | 1196 |
1217 // Extend the radii out half a pixel to antialias. | 1197 // Extend the radii out half a pixel to antialias. |
1218 SkScalar xOuterRadius = xRadius + SK_ScalarHalf; | 1198 SkScalar xOuterRadius = xRadius + SK_ScalarHalf; |
1219 SkScalar yOuterRadius = yRadius + SK_ScalarHalf; | 1199 SkScalar yOuterRadius = yRadius + SK_ScalarHalf; |
1220 | 1200 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1244 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
1265 SK_ARRAY_COUNT(gRRectIndices); | 1245 SK_ARRAY_COUNT(gRRectIndices); |
1266 target->setIndexSourceToBuffer(indexBuffer); | 1246 target->setIndexSourceToBuffer(indexBuffer); |
1267 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, | 1247 target->drawIndexedInstances(drawState, kTriangles_GrPrimitiveType, 1, 1
6, indexCnt, |
1268 &bounds); | 1248 &bounds); |
1269 } | 1249 } |
1270 | 1250 |
1271 target->resetIndexSource(); | 1251 target->resetIndexSource(); |
1272 return true; | 1252 return true; |
1273 } | 1253 } |
OLD | NEW |