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

Side by Side Diff: src/gpu/GrOvalRenderer.cpp

Issue 23719004: Add device-independent rendering of ovals. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Remove unneeded #include Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« include/gpu/GrOvalRenderer.h ('K') | « include/gpu/GrOvalRenderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 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 "GrEffect.h" 10 #include "GrEffect.h"
(...skipping 19 matching lines...) Expand all
30 SkScalar fInnerRadius; 30 SkScalar fInnerRadius;
31 }; 31 };
32 32
33 struct EllipseVertex { 33 struct EllipseVertex {
34 GrPoint fPos; 34 GrPoint fPos;
35 GrPoint fOffset; 35 GrPoint fOffset;
36 GrPoint fOuterRadii; 36 GrPoint fOuterRadii;
37 GrPoint fInnerRadii; 37 GrPoint fInnerRadii;
38 }; 38 };
39 39
40 struct DIEllipseVertex {
41 GrPoint fPos;
42 GrPoint fOuterOffset;
43 GrPoint fInnerOffset;
44 };
45
40 inline bool circle_stays_circle(const SkMatrix& m) { 46 inline bool circle_stays_circle(const SkMatrix& m) {
41 return m.isSimilarity(); 47 return m.isSimilarity();
42 } 48 }
43 49
44 } 50 }
45 51
46 /////////////////////////////////////////////////////////////////////////////// 52 ///////////////////////////////////////////////////////////////////////////////
47 53
48 /** 54 /**
49 * The output of this effect is a modulation of the input color and coverage for a circle, 55 * The output of this effect is a modulation of the input color and coverage for a circle,
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 285
280 GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, 286 GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random,
281 GrContext* context, 287 GrContext* context,
282 const GrDrawTargetCaps&, 288 const GrDrawTargetCaps&,
283 GrTexture* textures[]) { 289 GrTexture* textures[]) {
284 return EllipseEdgeEffect::Create(random->nextBool()); 290 return EllipseEdgeEffect::Create(random->nextBool());
285 } 291 }
286 292
287 /////////////////////////////////////////////////////////////////////////////// 293 ///////////////////////////////////////////////////////////////////////////////
288 294
295 /**
296 * The output of this effect is a modulation of the input color and coverage for an ellipse,
297 * specified as a 2D offset from center for both the outer and inner paths (if s troked). The
298 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c orrected by
299 * using differentials.
300 *
301 * The result is device-independent and can be used with any affine matrix.
302 */
303
304 class DIEllipseEdgeEffect : public GrEffect {
305 public:
306 enum Mode { kFill = 0, kStroke, kHairline };
307
308 static GrEffectRef* Create(Mode mode) {
robertphillips 2013/09/03 18:19:57 My OC side wants the kFill one first.
jvanverth1 2013/09/04 13:11:25 Done.
309 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStrok e));
310 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill));
311 GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHai rline));
312
robertphillips 2013/09/03 18:19:57 Haha - same here.
jvanverth1 2013/09/04 13:11:25 Done.
313 if (kStroke == mode) {
314 gEllipseStrokeEdge->ref();
315 return gEllipseStrokeEdge;
316 } else if (kHairline == mode) {
317 gEllipseHairlineEdge->ref();
318 return gEllipseHairlineEdge;
319 } else {
320 gEllipseFillEdge->ref();
321 return gEllipseFillEdge;
322 }
323 }
324
325 virtual void getConstantColorComponents(GrColor* color,
326 uint32_t* validFlags) const SK_OVERR IDE {
327 *validFlags = 0;
328 }
329
330 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
331 return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance();
332 }
333
334 virtual ~DIEllipseEdgeEffect() {}
335
336 static const char* Name() { return "DIEllipseEdge"; }
337
338 inline Mode getMode() const { return fMode; }
339
340 class GLEffect : public GrGLEffect {
341 public:
342 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
343 : INHERITED (factory) {}
344
345 virtual void emitCode(GrGLShaderBuilder* builder,
346 const GrDrawEffect& drawEffect,
347 EffectKey key,
348 const char* outputColor,
349 const char* inputColor,
350 const TextureSamplerArray& samplers) SK_OVERRIDE {
351 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE llipseEdgeEffect>();
352
353 const char *vsOffsetName, *fsOffsetName;
354
355 builder->addVarying(kVec4f_GrSLType, "EllipseOffsets", &vsOffsetName , &fsOffsetName);
356 const SkString* attr0Name =
robertphillips 2013/09/03 18:19:57 tab this line in a bit?
jvanverth1 2013/09/04 13:11:25 Done.
357 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[ 0]);
358 builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_st r());
359
360 // for outer curve
361 builder->fsCodeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetNam e);
362 builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset ) - 1.0;\n");
363 builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsOffsetName );
364 builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsOffsetName );
365 builder->fsCodeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s .y*duvdx.y,\n"
366 "\t 2.0*%s.x*duvdy.x + 2.0*%s .y*duvdy.y);\n",
367 fsOffsetName, fsOffsetName, fsOffsetName, fsO ffsetName);
368
369 builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
370 // we need to clamp the length^2 of the gradiant vector to a non-zer o value, because
371 // on the Nexus 4 the undefined result of inversesqrt(0) drops out a n entire tile
372 // TODO: restrict this to Adreno-only
373 builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
374 builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
375 if (kHairline == ellipseEffect.getMode()) {
376 // can probably do this with one step
377 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen , 0.0, 1.0);\n");
378 builder->fsCodeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0 , 1.0);\n");
379 } else {
380 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen , 0.0, 1.0);\n");
381 }
382
383 // for inner curve
384 if (kStroke == ellipseEffect.getMode()) {
385 builder->fsCodeAppendf("\tscaledOffset = %s.wz;\n", fsOffsetName );
386 builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n");
387 builder->fsCodeAppendf("\tduvdx = dFdx(%s.wz);\n", fsOffsetName) ;
388 builder->fsCodeAppendf("\tduvdy = dFdy(%s.wz);\n", fsOffsetName) ;
389 builder->fsCodeAppendf("\tgrad = vec2(2.0*%s.w*duvdx.x + 2.0*%s. z*duvdx.y,\n"
robertphillips 2013/09/03 18:19:57 line this up with prior line?
jvanverth1 2013/09/04 13:11:25 Done.
390 "\t 2.0*%s.w*duvdy.x + 2. 0*%s.z*duvdy.y);\n",
391 fsOffsetName, fsOffsetName, fsOffsetName, fsOffsetName);
392 builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\ n");
393 builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);\n");
394 }
395
396 SkString modulate;
397 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
398 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
399 }
400
401 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
402 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE llipseEdgeEffect>();
403
404 return ellipseEffect.getMode();
405 }
406
407 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {
408 }
409
410 private:
411 typedef GrGLEffect INHERITED;
412 };
413
414 private:
415 DIEllipseEdgeEffect(Mode mode) : GrEffect() {
416 this->addVertexAttrib(kVec4f_GrSLType);
417 fMode = mode;
418 }
419
420 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
421 const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other);
422 return eee.fMode == fMode;
423 }
424
425 Mode fMode;
426
427 GR_DECLARE_EFFECT_TEST;
428
429 typedef GrEffect INHERITED;
430 };
431
432 GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect);
433
434 GrEffectRef* DIEllipseEdgeEffect::TestCreate(SkMWCRandom* random,
robertphillips 2013/09/03 18:19:57 spaces
jvanverth1 2013/09/04 13:11:25 Done.
435 GrContext* context,
436 const GrDrawTargetCaps&,
437 GrTexture* textures[]) {
438 return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2)));
439 }
440
441 ///////////////////////////////////////////////////////////////////////////////
442
289 void GrOvalRenderer::reset() { 443 void GrOvalRenderer::reset() {
290 GrSafeSetNull(fRRectIndexBuffer); 444 GrSafeSetNull(fRRectIndexBuffer);
291 } 445 }
292 446
293 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo ol useAA, 447 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo ol useAA,
294 const SkRect& oval, const SkStrokeRec& stroke) 448 const SkRect& oval, const SkStrokeRec& stroke)
295 { 449 {
296 if (!useAA) { 450 if (!useAA) {
297 return false; 451 return false;
298 } 452 }
299 453
300 const SkMatrix& vm = context->getMatrix(); 454 const SkMatrix& vm = context->getMatrix();
301 455
302 // we can draw circles 456 // we can draw circles
303 if (SkScalarNearlyEqual(oval.width(), oval.height()) 457 if (SkScalarNearlyEqual(oval.width(), oval.height())
304 && circle_stays_circle(vm)) { 458 && circle_stays_circle(vm)) {
305 this->drawCircle(target, useAA, oval, stroke); 459 this->drawCircle(target, useAA, oval, stroke);
306 460 // if we have shader derivative support, render as device-independent
307 // and axis-aligned ellipses only 461 } else if (target->caps()->shaderDerivativeSupport()) {
462 return this->drawDIEllipse(target, useAA, oval, stroke);
463 // otherwise axis-aligned ellipses only
308 } else if (vm.rectStaysRect()) { 464 } else if (vm.rectStaysRect()) {
309 return this->drawEllipse(target, useAA, oval, stroke); 465 return this->drawEllipse(target, useAA, oval, stroke);
310
311 } else { 466 } else {
312 return false; 467 return false;
313 } 468 }
314 469
315 return true; 470 return true;
316 } 471 }
317 472
318 namespace {
319
320 /////////////////////////////////////////////////////////////////////////////// 473 ///////////////////////////////////////////////////////////////////////////////
321 474
322 // position + edge 475 // position + edge
323 extern const GrVertexAttrib gCircleVertexAttribs[] = { 476 extern const GrVertexAttrib gCircleVertexAttribs[] = {
324 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 477 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
325 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 478 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
326 }; 479 };
327 480
328 };
329
330 void GrOvalRenderer::drawCircle(GrDrawTarget* target, 481 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
331 bool useAA, 482 bool useAA,
332 const SkRect& circle, 483 const SkRect& circle,
333 const SkStrokeRec& stroke) 484 const SkStrokeRec& stroke)
334 { 485 {
335 GrDrawState* drawState = target->drawState(); 486 GrDrawState* drawState = target->drawState();
336 487
337 const SkMatrix& vm = drawState->getViewMatrix(); 488 const SkMatrix& vm = drawState->getViewMatrix();
338 GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY()); 489 GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY());
339 vm.mapPoints(&center, 1); 490 vm.mapPoints(&center, 1);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 563 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
413 verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius); 564 verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius);
414 verts[3].fOuterRadius = outerRadius; 565 verts[3].fOuterRadius = outerRadius;
415 verts[3].fInnerRadius = innerRadius; 566 verts[3].fInnerRadius = innerRadius;
416 567
417 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 568 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
418 } 569 }
419 570
420 /////////////////////////////////////////////////////////////////////////////// 571 ///////////////////////////////////////////////////////////////////////////////
421 572
422 namespace { 573 // position + offset + 1/radii
423
424 // position + edge
425 extern const GrVertexAttrib gEllipseVertexAttribs[] = { 574 extern const GrVertexAttrib gEllipseVertexAttribs[] = {
426 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng}, 575 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng},
427 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, 576 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
428 {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding } 577 {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
429 }; 578 };
430 579
580 // position + offsets
581 extern const GrVertexAttrib gDIEllipseVertexAttribs[] = {
582 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng},
583 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
431 }; 584 };
432 585
433 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, 586 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
434 bool useAA, 587 bool useAA,
435 const SkRect& ellipse, 588 const SkRect& ellipse,
436 const SkStrokeRec& stroke) 589 const SkStrokeRec& stroke)
437 { 590 {
438 GrDrawState* drawState = target->drawState(); 591 GrDrawState* drawState = target->drawState();
439 #ifdef SK_DEBUG 592 #ifdef SK_DEBUG
440 { 593 {
(...skipping 16 matching lines...) Expand all
457 610
458 // do (potentially) anisotropic mapping of stroke 611 // do (potentially) anisotropic mapping of stroke
459 SkVector scaledStroke; 612 SkVector scaledStroke;
460 SkScalar strokeWidth = stroke.getWidth(); 613 SkScalar strokeWidth = stroke.getWidth();
461 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY])); 614 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY]));
462 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY])); 615 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY]));
463 616
464 SkStrokeRec::Style style = stroke.getStyle(); 617 SkStrokeRec::Style style = stroke.getStyle();
465 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); 618 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style);
466 619
467 SkScalar innerXRadius = 0.0f; 620 SkScalar innerXRadius = 0;
468 SkScalar innerYRadius = 0.0f; 621 SkScalar innerYRadius = 0;
469 if (SkStrokeRec::kFill_Style != style) { 622 if (SkStrokeRec::kFill_Style != style) {
470 if (SkScalarNearlyZero(scaledStroke.length())) { 623 if (SkScalarNearlyZero(scaledStroke.length())) {
471 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 624 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
472 } else { 625 } else {
473 scaledStroke.scale(SK_ScalarHalf); 626 scaledStroke.scale(SK_ScalarHalf);
474 } 627 }
475 628
476 // we only handle thick strokes for near-circular ellipses 629 // we only handle thick strokes for near-circular ellipses
477 if (scaledStroke.length() > SK_ScalarHalf && 630 if (scaledStroke.length() > SK_ScalarHalf &&
478 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { 631 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 708 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
556 verts[3].fOffset = SkPoint::Make(xRadius, yRadius); 709 verts[3].fOffset = SkPoint::Make(xRadius, yRadius);
557 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 710 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
558 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 711 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
559 712
560 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 713 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
561 714
562 return true; 715 return true;
563 } 716 }
564 717
718 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
robertphillips 2013/09/03 18:19:57 spaces
jvanverth1 2013/09/04 13:11:25 Done.
719 bool useAA,
720 const SkRect& ellipse,
721 const SkStrokeRec& stroke)
722 {
723 GrDrawState* drawState = target->drawState();
724 const SkMatrix& vm = drawState->getViewMatrix();
725
726 GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
727 SkScalar xRadius = SkScalarHalf(ellipse.width());
728 SkScalar yRadius = SkScalarHalf(ellipse.height());
729
730 SkStrokeRec::Style style = stroke.getStyle();
731 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ?
732 DIEllipseEdgeEffect::kStroke :
733 (SkStrokeRec::kHairline_Style == style) ?
734 DIEllipseEdgeEffect::kHairline : DIEllipseEd geEffect::kFill;
735
736 SkScalar innerXRadius = 0;
737 SkScalar innerYRadius = 0;
738 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) {
739 SkScalar strokeWidth = stroke.getWidth();
740
741 if (SkScalarNearlyZero(strokeWidth)) {
742 strokeWidth = SK_ScalarHalf;
743 } else {
744 strokeWidth *= SK_ScalarHalf;
745 }
746
747 // we only handle thick strokes for near-circular ellipses
748 if (strokeWidth > SK_ScalarHalf &&
749 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) {
750 return false;
751 }
752
753 // we don't handle it if curvature of the stroke is less than curvature of the ellipse
754 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius ||
755 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) {
756 return false;
757 }
758
759 // set inner radius (if needed)
760 if (SkStrokeRec::kStroke_Style == style) {
761 innerXRadius = xRadius - strokeWidth;
762 innerYRadius = yRadius - strokeWidth;
763 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect: :kStroke :
764 DIEllipseEdgeEffect: :kFill;
765 }
766
767 xRadius += strokeWidth;
768 yRadius += strokeWidth;
769 }
770 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius);
771 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius);
772
773 drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllip seVertexAttribs));
774 SkASSERT(sizeof(DIEllipseVertex) == drawState->getVertexSize());
775
776 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
777 if (!geo.succeeded()) {
778 GrPrintf("Failed to get space for vertices!\n");
779 return false;
780 }
781
782 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices());
783
784 GrEffectRef* effect = DIEllipseEdgeEffect::Create(mode);
785
786 static const int kEllipseOffsetAttrIndex = 1;
787 drawState->addCoverageEffect(effect, kEllipseOffsetAttrIndex)->unref();
788
789 // This expands the outer rect so that after CTM we end up with a half-pixel border
790 SkScalar a = vm[SkMatrix::kMScaleX];
791 SkScalar b = vm[SkMatrix::kMSkewX];
792 SkScalar c = vm[SkMatrix::kMSkewY];
793 SkScalar d = vm[SkMatrix::kMScaleY];
794 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c));
795 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d));
796 // This adjusts the "radius" to include the half-pixel border
797 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius);
798 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius);
799
800 SkRect bounds = SkRect::MakeLTRB(
801 center.fX - xRadius - geoDx,
802 center.fY - yRadius - geoDy,
803 center.fX + xRadius + geoDx,
804 center.fY + yRadius + geoDy
805 );
806
807 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
808 verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy);
809 verts[0].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, -innerRatioY - offsetDy);
810
811 verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
812 verts[1].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy);
813 verts[1].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy);
814
815 verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
816 verts[2].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy);
817 verts[2].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, innerRatioY + offsetDy);
818
819 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
820 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy);
821 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, innerRatioY + offsetDy);
822
823 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
824
825 return true;
826 }
827
565 /////////////////////////////////////////////////////////////////////////////// 828 ///////////////////////////////////////////////////////////////////////////////
566 829
567 static const uint16_t gRRectIndices[] = { 830 static const uint16_t gRRectIndices[] = {
568 // corners 831 // corners
569 0, 1, 5, 0, 5, 4, 832 0, 1, 5, 0, 5, 4,
570 2, 3, 7, 2, 7, 6, 833 2, 3, 7, 2, 7, 6,
571 8, 9, 13, 8, 13, 12, 834 8, 9, 13, 8, 13, 12,
572 10, 11, 15, 10, 15, 14, 835 10, 11, 15, 10, 15, 14,
573 836
574 // edges 837 // edges
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 } 1113 }
851 1114
852 // drop out the middle quad if we're stroked 1115 // drop out the middle quad if we're stroked
853 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO UNT(gRRectIndices); 1116 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO UNT(gRRectIndices);
854 target->setIndexSourceToBuffer(indexBuffer); 1117 target->setIndexSourceToBuffer(indexBuffer);
855 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds); 1118 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds);
856 } 1119 }
857 1120
858 return true; 1121 return true;
859 } 1122 }
OLDNEW
« include/gpu/GrOvalRenderer.h ('K') | « include/gpu/GrOvalRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698