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

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: Fix for Ubuntu-32 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
« no previous file with comments | « 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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 291
286 GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, 292 GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random,
287 GrContext* context, 293 GrContext* context,
288 const GrDrawTargetCaps&, 294 const GrDrawTargetCaps&,
289 GrTexture* textures[]) { 295 GrTexture* textures[]) {
290 return EllipseEdgeEffect::Create(random->nextBool()); 296 return EllipseEdgeEffect::Create(random->nextBool());
291 } 297 }
292 298
293 /////////////////////////////////////////////////////////////////////////////// 299 ///////////////////////////////////////////////////////////////////////////////
294 300
301 /**
302 * The output of this effect is a modulation of the input color and coverage for an ellipse,
303 * specified as a 2D offset from center for both the outer and inner paths (if s troked). The
304 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c orrected by
305 * using differentials.
306 *
307 * The result is device-independent and can be used with any affine matrix.
308 */
309
310 class DIEllipseEdgeEffect : public GrEffect {
311 public:
312 enum Mode { kStroke = 0, kHairline, kFill };
313
314 static GrEffectRef* Create(Mode mode) {
315 GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStrok e));
316 GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHai rline));
317 GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill));
318
319 if (kStroke == mode) {
320 gEllipseStrokeEdge->ref();
321 return gEllipseStrokeEdge;
322 } else if (kHairline == mode) {
323 gEllipseHairlineEdge->ref();
324 return gEllipseHairlineEdge;
325 } else {
326 gEllipseFillEdge->ref();
327 return gEllipseFillEdge;
328 }
329 }
330
331 virtual void getConstantColorComponents(GrColor* color,
332 uint32_t* validFlags) const SK_OVERR IDE {
333 *validFlags = 0;
334 }
335
336 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
337 return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance();
338 }
339
340 virtual ~DIEllipseEdgeEffect() {}
341
342 static const char* Name() { return "DIEllipseEdge"; }
343
344 inline Mode getMode() const { return fMode; }
345
346 class GLEffect : public GrGLEffect {
347 public:
348 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
349 : INHERITED (factory) {}
350
351 virtual void emitCode(GrGLShaderBuilder* builder,
352 const GrDrawEffect& drawEffect,
353 EffectKey key,
354 const char* outputColor,
355 const char* inputColor,
356 const TextureSamplerArray& samplers) SK_OVERRIDE {
357 GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertex Builder();
358 SkASSERT(NULL != vertexBuilder);
359
360 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE llipseEdgeEffect>();
361
362 const char *vsOffsetName, *fsOffsetName;
363
364 vertexBuilder->addVarying(kVec4f_GrSLType, "EllipseOffsets", &vsOffs etName, &fsOffsetName);
365 const SkString* attr0Name =
366 vertexBuilder->getEffectAttributeName(drawEffect.getVertexAttrib Indices()[0]);
367 vertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name ->c_str());
368
369 // for outer curve
370 builder->fsCodeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetNam e);
371 builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset ) - 1.0;\n");
372 builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s.xy);\n", fsOffsetName );
373 builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s.xy);\n", fsOffsetName );
374 builder->fsCodeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s .y*duvdx.y,\n"
375 "\t 2.0*%s.x*duvdy.x + 2.0*%s .y*duvdy.y);\n",
376 fsOffsetName, fsOffsetName, fsOffsetName, fsO ffsetName);
377
378 builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
379 // we need to clamp the length^2 of the gradiant vector to a non-zer o value, because
380 // on the Nexus 4 the undefined result of inversesqrt(0) drops out a n entire tile
381 // TODO: restrict this to Adreno-only
382 builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
383 builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
384 if (kHairline == ellipseEffect.getMode()) {
385 // can probably do this with one step
386 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen , 0.0, 1.0);\n");
387 builder->fsCodeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0 , 1.0);\n");
388 } else {
389 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen , 0.0, 1.0);\n");
390 }
391
392 // for inner curve
393 if (kStroke == ellipseEffect.getMode()) {
394 builder->fsCodeAppendf("\tscaledOffset = %s.wz;\n", fsOffsetName );
395 builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n");
396 builder->fsCodeAppendf("\tduvdx = dFdx(%s.wz);\n", fsOffsetName) ;
397 builder->fsCodeAppendf("\tduvdy = dFdy(%s.wz);\n", fsOffsetName) ;
398 builder->fsCodeAppendf("\tgrad = vec2(2.0*%s.w*duvdx.x + 2.0*%s. z*duvdx.y,\n"
399 "\t 2.0*%s.w*duvdy.x + 2.0*%s. z*duvdy.y);\n",
400 fsOffsetName, fsOffsetName, fsOffsetName, fsOffsetName);
401 builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\ n");
402 builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);\n");
403 }
404
405 SkString modulate;
406 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
407 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
408 }
409
410 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
411 const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIE llipseEdgeEffect>();
412
413 return ellipseEffect.getMode();
414 }
415
416 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {
417 }
418
419 private:
420 typedef GrGLEffect INHERITED;
421 };
422
423 private:
424 DIEllipseEdgeEffect(Mode mode) : GrEffect() {
425 this->addVertexAttrib(kVec4f_GrSLType);
426 fMode = mode;
427 }
428
429 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
430 const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other);
431 return eee.fMode == fMode;
432 }
433
434 Mode fMode;
435
436 GR_DECLARE_EFFECT_TEST;
437
438 typedef GrEffect INHERITED;
439 };
440
441 GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect);
442
443 GrEffectRef* DIEllipseEdgeEffect::TestCreate(SkMWCRandom* random,
444 GrContext* context,
445 const GrDrawTargetCaps&,
446 GrTexture* textures[]) {
447 return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2)));
448 }
449
450 ///////////////////////////////////////////////////////////////////////////////
451
295 void GrOvalRenderer::reset() { 452 void GrOvalRenderer::reset() {
296 GrSafeSetNull(fRRectIndexBuffer); 453 GrSafeSetNull(fRRectIndexBuffer);
297 } 454 }
298 455
299 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo ol useAA, 456 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo ol useAA,
300 const SkRect& oval, const SkStrokeRec& stroke) 457 const SkRect& oval, const SkStrokeRec& stroke)
301 { 458 {
302 if (!useAA) { 459 if (!useAA) {
303 return false; 460 return false;
304 } 461 }
305 462
306 const SkMatrix& vm = context->getMatrix(); 463 const SkMatrix& vm = context->getMatrix();
307 464
308 // we can draw circles 465 // we can draw circles
309 if (SkScalarNearlyEqual(oval.width(), oval.height()) 466 if (SkScalarNearlyEqual(oval.width(), oval.height())
310 && circle_stays_circle(vm)) { 467 && circle_stays_circle(vm)) {
311 this->drawCircle(target, useAA, oval, stroke); 468 this->drawCircle(target, useAA, oval, stroke);
312 469 // if we have shader derivative support, render as device-independent
313 // and axis-aligned ellipses only 470 } else if (target->caps()->shaderDerivativeSupport()) {
471 return this->drawDIEllipse(target, useAA, oval, stroke);
472 // otherwise axis-aligned ellipses only
314 } else if (vm.rectStaysRect()) { 473 } else if (vm.rectStaysRect()) {
315 return this->drawEllipse(target, useAA, oval, stroke); 474 return this->drawEllipse(target, useAA, oval, stroke);
316
317 } else { 475 } else {
318 return false; 476 return false;
319 } 477 }
320 478
321 return true; 479 return true;
322 } 480 }
323 481
324 namespace {
325
326 /////////////////////////////////////////////////////////////////////////////// 482 ///////////////////////////////////////////////////////////////////////////////
327 483
328 // position + edge 484 // position + edge
329 extern const GrVertexAttrib gCircleVertexAttribs[] = { 485 extern const GrVertexAttrib gCircleVertexAttribs[] = {
330 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 486 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
331 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 487 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
332 }; 488 };
333 489
334 };
335
336 void GrOvalRenderer::drawCircle(GrDrawTarget* target, 490 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
337 bool useAA, 491 bool useAA,
338 const SkRect& circle, 492 const SkRect& circle,
339 const SkStrokeRec& stroke) 493 const SkStrokeRec& stroke)
340 { 494 {
341 GrDrawState* drawState = target->drawState(); 495 GrDrawState* drawState = target->drawState();
342 496
343 const SkMatrix& vm = drawState->getViewMatrix(); 497 const SkMatrix& vm = drawState->getViewMatrix();
344 GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY()); 498 GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY());
345 vm.mapPoints(&center, 1); 499 vm.mapPoints(&center, 1);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 571 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
418 verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius); 572 verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius);
419 verts[3].fOuterRadius = outerRadius; 573 verts[3].fOuterRadius = outerRadius;
420 verts[3].fInnerRadius = innerRadius; 574 verts[3].fInnerRadius = innerRadius;
421 575
422 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 576 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
423 } 577 }
424 578
425 /////////////////////////////////////////////////////////////////////////////// 579 ///////////////////////////////////////////////////////////////////////////////
426 580
427 namespace { 581 // position + offset + 1/radii
428
429 // position + edge
430 extern const GrVertexAttrib gEllipseVertexAttribs[] = { 582 extern const GrVertexAttrib gEllipseVertexAttribs[] = {
431 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng}, 583 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng},
432 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, 584 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
433 {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding } 585 {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
434 }; 586 };
435 587
588 // position + offsets
589 extern const GrVertexAttrib gDIEllipseVertexAttribs[] = {
590 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindi ng},
591 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
436 }; 592 };
437 593
438 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, 594 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
439 bool useAA, 595 bool useAA,
440 const SkRect& ellipse, 596 const SkRect& ellipse,
441 const SkStrokeRec& stroke) 597 const SkStrokeRec& stroke)
442 { 598 {
443 GrDrawState* drawState = target->drawState(); 599 GrDrawState* drawState = target->drawState();
444 #ifdef SK_DEBUG 600 #ifdef SK_DEBUG
445 { 601 {
(...skipping 16 matching lines...) Expand all
462 618
463 // do (potentially) anisotropic mapping of stroke 619 // do (potentially) anisotropic mapping of stroke
464 SkVector scaledStroke; 620 SkVector scaledStroke;
465 SkScalar strokeWidth = stroke.getWidth(); 621 SkScalar strokeWidth = stroke.getWidth();
466 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY])); 622 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY]));
467 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY])); 623 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY]));
468 624
469 SkStrokeRec::Style style = stroke.getStyle(); 625 SkStrokeRec::Style style = stroke.getStyle();
470 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); 626 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style);
471 627
472 SkScalar innerXRadius = 0.0f; 628 SkScalar innerXRadius = 0;
473 SkScalar innerYRadius = 0.0f; 629 SkScalar innerYRadius = 0;
474 if (SkStrokeRec::kFill_Style != style) { 630 if (SkStrokeRec::kFill_Style != style) {
475 if (SkScalarNearlyZero(scaledStroke.length())) { 631 if (SkScalarNearlyZero(scaledStroke.length())) {
476 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 632 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
477 } else { 633 } else {
478 scaledStroke.scale(SK_ScalarHalf); 634 scaledStroke.scale(SK_ScalarHalf);
479 } 635 }
480 636
481 // we only handle thick strokes for near-circular ellipses 637 // we only handle thick strokes for near-circular ellipses
482 if (scaledStroke.length() > SK_ScalarHalf && 638 if (scaledStroke.length() > SK_ScalarHalf &&
483 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { 639 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 716 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
561 verts[3].fOffset = SkPoint::Make(xRadius, yRadius); 717 verts[3].fOffset = SkPoint::Make(xRadius, yRadius);
562 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 718 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
563 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 719 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
564 720
565 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 721 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
566 722
567 return true; 723 return true;
568 } 724 }
569 725
726 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
727 bool useAA,
728 const SkRect& ellipse,
729 const SkStrokeRec& stroke)
730 {
731 GrDrawState* drawState = target->drawState();
732 const SkMatrix& vm = drawState->getViewMatrix();
733
734 GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
735 SkScalar xRadius = SkScalarHalf(ellipse.width());
736 SkScalar yRadius = SkScalarHalf(ellipse.height());
737
738 SkStrokeRec::Style style = stroke.getStyle();
739 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ?
740 DIEllipseEdgeEffect::kStroke :
741 (SkStrokeRec::kHairline_Style == style) ?
742 DIEllipseEdgeEffect::kHairline : DIEllipseEd geEffect::kFill;
743
744 SkScalar innerXRadius = 0;
745 SkScalar innerYRadius = 0;
746 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) {
747 SkScalar strokeWidth = stroke.getWidth();
748
749 if (SkScalarNearlyZero(strokeWidth)) {
750 strokeWidth = SK_ScalarHalf;
751 } else {
752 strokeWidth *= SK_ScalarHalf;
753 }
754
755 // we only handle thick strokes for near-circular ellipses
756 if (strokeWidth > SK_ScalarHalf &&
757 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) {
758 return false;
759 }
760
761 // we don't handle it if curvature of the stroke is less than curvature of the ellipse
762 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius ||
763 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) {
764 return false;
765 }
766
767 // set inner radius (if needed)
768 if (SkStrokeRec::kStroke_Style == style) {
769 innerXRadius = xRadius - strokeWidth;
770 innerYRadius = yRadius - strokeWidth;
771 }
772
773 xRadius += strokeWidth;
774 yRadius += strokeWidth;
775 }
776 if (DIEllipseEdgeEffect::kStroke == mode) {
777 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt roke :
778 DIEllipseEdgeEffect::kFi ll;
779 }
780 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius);
781 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius);
782
783 drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllip seVertexAttribs));
784 SkASSERT(sizeof(DIEllipseVertex) == drawState->getVertexSize());
785
786 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
787 if (!geo.succeeded()) {
788 GrPrintf("Failed to get space for vertices!\n");
789 return false;
790 }
791
792 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices());
793
794 GrEffectRef* effect = DIEllipseEdgeEffect::Create(mode);
795
796 static const int kEllipseOffsetAttrIndex = 1;
797 drawState->addCoverageEffect(effect, kEllipseOffsetAttrIndex)->unref();
798
799 // This expands the outer rect so that after CTM we end up with a half-pixel border
800 SkScalar a = vm[SkMatrix::kMScaleX];
801 SkScalar b = vm[SkMatrix::kMSkewX];
802 SkScalar c = vm[SkMatrix::kMSkewY];
803 SkScalar d = vm[SkMatrix::kMScaleY];
804 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c));
805 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d));
806 // This adjusts the "radius" to include the half-pixel border
807 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius);
808 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius);
809
810 SkRect bounds = SkRect::MakeLTRB(
811 center.fX - xRadius - geoDx,
812 center.fY - yRadius - geoDy,
813 center.fX + xRadius + geoDx,
814 center.fY + yRadius + geoDy
815 );
816
817 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
818 verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy);
819 verts[0].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, -innerRatioY - offsetDy);
820
821 verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
822 verts[1].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy);
823 verts[1].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy);
824
825 verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
826 verts[2].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy);
827 verts[2].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, innerRatioY + offsetDy);
828
829 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
830 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy);
831 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, innerRatioY + offsetDy);
832
833 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
834
835 return true;
836 }
837
570 /////////////////////////////////////////////////////////////////////////////// 838 ///////////////////////////////////////////////////////////////////////////////
571 839
572 static const uint16_t gRRectIndices[] = { 840 static const uint16_t gRRectIndices[] = {
573 // corners 841 // corners
574 0, 1, 5, 0, 5, 4, 842 0, 1, 5, 0, 5, 4,
575 2, 3, 7, 2, 7, 6, 843 2, 3, 7, 2, 7, 6,
576 8, 9, 13, 8, 13, 12, 844 8, 9, 13, 8, 13, 12,
577 10, 11, 15, 10, 15, 14, 845 10, 11, 15, 10, 15, 14,
578 846
579 // edges 847 // edges
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 halfWidth = SkScalarHalf(scaledStroke.fX); 954 halfWidth = SkScalarHalf(scaledStroke.fX);
687 } 955 }
688 956
689 if (isStroked) { 957 if (isStroked) {
690 innerRadius = xRadius - halfWidth; 958 innerRadius = xRadius - halfWidth;
691 } 959 }
692 outerRadius += halfWidth; 960 outerRadius += halfWidth;
693 bounds.outset(halfWidth, halfWidth); 961 bounds.outset(halfWidth, halfWidth);
694 } 962 }
695 963
696 isStroked = (isStroked && innerRadius > 0); 964 isStroked = (isStroked && innerRadius > 0);
697 965
698 GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); 966 GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
699 static const int kCircleEdgeAttrIndex = 1; 967 static const int kCircleEdgeAttrIndex = 1;
700 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref(); 968 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
701 969
702 // The radii are outset for two reasons. First, it allows the shader to simply perform 970 // The radii are outset for two reasons. First, it allows the shader to simply perform
703 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the 971 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
704 // verts of the bounding box that is rendered and the outset ensures the box will cover all 972 // verts of the bounding box that is rendered and the outset ensures the box will cover all
705 // pixels partially covered by the circle. 973 // pixels partially covered by the circle.
706 outerRadius += SK_ScalarHalf; 974 outerRadius += SK_ScalarHalf;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 if (isStroked) { 1050 if (isStroked) {
783 innerXRadius = xRadius - scaledStroke.fX; 1051 innerXRadius = xRadius - scaledStroke.fX;
784 innerYRadius = yRadius - scaledStroke.fY; 1052 innerYRadius = yRadius - scaledStroke.fY;
785 } 1053 }
786 1054
787 xRadius += scaledStroke.fX; 1055 xRadius += scaledStroke.fX;
788 yRadius += scaledStroke.fY; 1056 yRadius += scaledStroke.fY;
789 bounds.outset(scaledStroke.fX, scaledStroke.fY); 1057 bounds.outset(scaledStroke.fX, scaledStroke.fY);
790 } 1058 }
791 1059
792 isStroked = (isStroked && innerXRadius > 0 && innerYRadius > 0); 1060 isStroked = (isStroked && innerXRadius > 0 && innerYRadius > 0);
793 1061
794 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); 1062 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
795 if (!geo.succeeded()) { 1063 if (!geo.succeeded()) {
796 GrPrintf("Failed to get space for vertices!\n"); 1064 GrPrintf("Failed to get space for vertices!\n");
797 return false; 1065 return false;
798 } 1066 }
799 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); 1067 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
800 1068
801 GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); 1069 GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
802 static const int kEllipseOffsetAttrIndex = 1; 1070 static const int kEllipseOffsetAttrIndex = 1;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 } 1125 }
858 1126
859 // drop out the middle quad if we're stroked 1127 // drop out the middle quad if we're stroked
860 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO UNT(gRRectIndices); 1128 int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_CO UNT(gRRectIndices);
861 target->setIndexSourceToBuffer(indexBuffer); 1129 target->setIndexSourceToBuffer(indexBuffer);
862 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds); 1130 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds);
863 } 1131 }
864 1132
865 return true; 1133 return true;
866 } 1134 }
OLDNEW
« no previous file with comments | « include/gpu/GrOvalRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698