| 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 |