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

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

Issue 220233011: Implement drawDRRect for GPU (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rebase Created 6 years, 8 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 | « src/gpu/GrOvalRenderer.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | 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"
11 #include "gl/GrGLEffect.h" 11 #include "gl/GrGLEffect.h"
12 #include "gl/GrGLSL.h" 12 #include "gl/GrGLSL.h"
13 #include "gl/GrGLVertexEffect.h" 13 #include "gl/GrGLVertexEffect.h"
14 #include "GrTBackendEffectFactory.h" 14 #include "GrTBackendEffectFactory.h"
15 15
16 #include "GrDrawState.h" 16 #include "GrDrawState.h"
17 #include "GrDrawTarget.h" 17 #include "GrDrawTarget.h"
18 #include "GrGpu.h" 18 #include "GrGpu.h"
19 19
20 #include "SkRRect.h" 20 #include "SkRRect.h"
21 #include "SkStrokeRec.h" 21 #include "SkStrokeRec.h"
22 #include "SkTLazy.h"
22 23
23 #include "effects/GrVertexEffect.h" 24 #include "effects/GrVertexEffect.h"
25 #include "effects/GrRRectEffect.h"
24 26
25 namespace { 27 namespace {
26 28
27 struct CircleVertex { 29 struct CircleVertex {
28 SkPoint fPos; 30 SkPoint fPos;
29 SkPoint fOffset; 31 SkPoint fOffset;
30 SkScalar fOuterRadius; 32 SkScalar fOuterRadius;
31 SkScalar fInnerRadius; 33 SkScalar fInnerRadius;
32 }; 34 };
33 35
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 514
513 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 515 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
514 if (!geo.succeeded()) { 516 if (!geo.succeeded()) {
515 GrPrintf("Failed to get space for vertices!\n"); 517 GrPrintf("Failed to get space for vertices!\n");
516 return; 518 return;
517 } 519 }
518 520
519 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); 521 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
520 522
521 SkStrokeRec::Style style = stroke.getStyle(); 523 SkStrokeRec::Style style = stroke.getStyle();
522 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); 524 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
525 SkStrokeRec::kHairline_Style == style;
526 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
523 527
524 SkScalar innerRadius = 0.0f; 528 SkScalar innerRadius = 0.0f;
525 SkScalar outerRadius = radius; 529 SkScalar outerRadius = radius;
526 SkScalar halfWidth = 0; 530 SkScalar halfWidth = 0;
527 if (style != SkStrokeRec::kFill_Style) { 531 if (hasStroke) {
528 if (SkScalarNearlyZero(strokeWidth)) { 532 if (SkScalarNearlyZero(strokeWidth)) {
529 halfWidth = SK_ScalarHalf; 533 halfWidth = SK_ScalarHalf;
530 } else { 534 } else {
531 halfWidth = SkScalarHalf(strokeWidth); 535 halfWidth = SkScalarHalf(strokeWidth);
532 } 536 }
533 537
534 outerRadius += halfWidth; 538 outerRadius += halfWidth;
535 if (isStroked) { 539 if (isStrokeOnly) {
536 innerRadius = radius - halfWidth; 540 innerRadius = radius - halfWidth;
537 } 541 }
538 } 542 }
539 543
540 GrEffectRef* effect = CircleEdgeEffect::Create(isStroked && innerRadius > 0) ; 544 GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
541 static const int kCircleEdgeAttrIndex = 1; 545 static const int kCircleEdgeAttrIndex = 1;
542 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref(); 546 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
543 547
544 // The radii are outset for two reasons. First, it allows the shader to simp ly perform 548 // The radii are outset for two reasons. First, it allows the shader to simp ly perform
545 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use d to compute the 549 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use d to compute the
546 // verts of the bounding box that is rendered and the outset ensures the box will cover all 550 // verts of the bounding box that is rendered and the outset ensures the box will cover all
547 // pixels partially covered by the circle. 551 // pixels partially covered by the circle.
548 outerRadius += SK_ScalarHalf; 552 outerRadius += SK_ScalarHalf;
549 innerRadius -= SK_ScalarHalf; 553 innerRadius -= SK_ScalarHalf;
550 554
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*ellipseXRadius + 623 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*ellipseXRadius +
620 vm[SkMatrix::kMScaleY]*ellipseYRadius); 624 vm[SkMatrix::kMScaleY]*ellipseYRadius);
621 625
622 // do (potentially) anisotropic mapping of stroke 626 // do (potentially) anisotropic mapping of stroke
623 SkVector scaledStroke; 627 SkVector scaledStroke;
624 SkScalar strokeWidth = stroke.getWidth(); 628 SkScalar strokeWidth = stroke.getWidth();
625 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY])); 629 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY]));
626 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY])); 630 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY]));
627 631
628 SkStrokeRec::Style style = stroke.getStyle(); 632 SkStrokeRec::Style style = stroke.getStyle();
629 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); 633 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
634 SkStrokeRec::kHairline_Style == style;
635 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
630 636
631 SkScalar innerXRadius = 0; 637 SkScalar innerXRadius = 0;
632 SkScalar innerYRadius = 0; 638 SkScalar innerYRadius = 0;
633 if (SkStrokeRec::kFill_Style != style) { 639 if (hasStroke) {
634 if (SkScalarNearlyZero(scaledStroke.length())) { 640 if (SkScalarNearlyZero(scaledStroke.length())) {
635 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 641 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
636 } else { 642 } else {
637 scaledStroke.scale(SK_ScalarHalf); 643 scaledStroke.scale(SK_ScalarHalf);
638 } 644 }
639 645
640 // we only handle thick strokes for near-circular ellipses 646 // we only handle thick strokes for near-circular ellipses
641 if (scaledStroke.length() > SK_ScalarHalf && 647 if (scaledStroke.length() > SK_ScalarHalf &&
642 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) { 648 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius) ) {
643 return false; 649 return false;
644 } 650 }
645 651
646 // we don't handle it if curvature of the stroke is less than curvature of the ellipse 652 // we don't handle it if curvature of the stroke is less than curvature of the ellipse
647 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY )*xRadius || 653 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY )*xRadius ||
648 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX )*yRadius) { 654 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX )*yRadius) {
649 return false; 655 return false;
650 } 656 }
651 657
652 // this is legit only if scale & translation (which should be the case a t the moment) 658 // this is legit only if scale & translation (which should be the case a t the moment)
653 if (isStroked) { 659 if (isStrokeOnly) {
654 innerXRadius = xRadius - scaledStroke.fX; 660 innerXRadius = xRadius - scaledStroke.fX;
655 innerYRadius = yRadius - scaledStroke.fY; 661 innerYRadius = yRadius - scaledStroke.fY;
656 } 662 }
657 663
658 xRadius += scaledStroke.fX; 664 xRadius += scaledStroke.fX;
659 yRadius += scaledStroke.fY; 665 yRadius += scaledStroke.fY;
660 } 666 }
661 667
662 GrDrawState::AutoViewMatrixRestore avmr; 668 GrDrawState::AutoViewMatrixRestore avmr;
663 if (!avmr.setIdentity(drawState)) { 669 if (!avmr.setIdentity(drawState)) {
664 return false; 670 return false;
665 } 671 }
666 672
667 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVe rtexAttribs)); 673 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVe rtexAttribs));
668 SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize()); 674 SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize());
669 675
670 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 676 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
671 if (!geo.succeeded()) { 677 if (!geo.succeeded()) {
672 GrPrintf("Failed to get space for vertices!\n"); 678 GrPrintf("Failed to get space for vertices!\n");
673 return false; 679 return false;
674 } 680 }
675 681
676 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); 682 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
677 683
678 GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked && 684 GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly &&
679 innerXRadius > 0 && innerYRa dius > 0); 685 innerXRadius > 0 && innerYRa dius > 0);
680 686
681 static const int kEllipseCenterAttrIndex = 1; 687 static const int kEllipseCenterAttrIndex = 1;
682 static const int kEllipseEdgeAttrIndex = 2; 688 static const int kEllipseEdgeAttrIndex = 2;
683 drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAt trIndex)->unref(); 689 drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAt trIndex)->unref();
684 690
685 // Compute the reciprocals of the radii here to save time in the shader 691 // Compute the reciprocals of the radii here to save time in the shader
686 SkScalar xRadRecip = SkScalarInvert(xRadius); 692 SkScalar xRadRecip = SkScalarInvert(xRadius);
687 SkScalar yRadRecip = SkScalarInvert(yRadius); 693 SkScalar yRadRecip = SkScalarInvert(yRadius);
688 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); 694 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius);
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 bool updated = 876 bool updated =
871 #endif 877 #endif
872 fRRectIndexBuffer->updateData(gRRectIndices, 878 fRRectIndexBuffer->updateData(gRRectIndices,
873 sizeof(gRRectIndices)); 879 sizeof(gRRectIndices));
874 GR_DEBUGASSERT(updated); 880 GR_DEBUGASSERT(updated);
875 } 881 }
876 } 882 }
877 return fRRectIndexBuffer; 883 return fRRectIndexBuffer;
878 } 884 }
879 885
880 bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b ool useAA, 886 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrContext* context, bool u seAA,
881 const SkRRect& rrect, const SkStrokeRec& st roke) 887 const SkRRect& outer, const SkRRect& origInner) {
882 { 888 GrDrawState::AutoRestoreEffects are;
889 if (!origInner.isEmpty()) {
890 SkTCopyOnFirstWrite<SkRRect> inner(origInner);
891 if (!context->getMatrix().isIdentity()) {
892 if (!origInner.transform(context->getMatrix(), inner.writable())) {
893 return false;
894 }
895 }
896 bool applyAA = useAA &&
897 !target->getDrawState().getRenderTarget()->isMultisampled () &&
898 !target->shouldDisableCoverageAAForBlend();
899 GrEffectEdgeType edgeType = applyAA ? kInverseFillAA_GrEffectEdgeType :
900 kInverseFillBW_GrEffectEdgeType;
901 GrEffectRef* effect = GrRRectEffect::Create(edgeType, *inner);
902 if (NULL == effect) {
903 return false;
904 }
905 are.set(target->drawState());
906 target->drawState()->addCoverageEffect(effect)->unref();
907 }
908
909 SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
910 return this->drawRRect(target, context, useAA, outer, fillRec);
911 }
912
913 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool us eAA,
914 const SkRRect& rrect, const SkStrokeRec& stroke) {
915 if (rrect.isOval()) {
916 return this->drawOval(target, context, useAA, rrect.getBounds(), stroke) ;
917 }
918
883 bool useCoverageAA = useAA && 919 bool useCoverageAA = useAA &&
884 !target->getDrawState().getRenderTarget()->isMultisampled() && 920 !target->getDrawState().getRenderTarget()->isMultisampled() &&
885 !target->shouldDisableCoverageAAForBlend(); 921 !target->shouldDisableCoverageAAForBlend();
886 922
887 // only anti-aliased rrects for now 923 // only anti-aliased rrects for now
888 if (!useCoverageAA) { 924 if (!useCoverageAA) {
889 return false; 925 return false;
890 } 926 }
891 927
892 const SkMatrix& vm = context->getMatrix(); 928 const SkMatrix& vm = context->getMatrix();
893 #ifdef SK_DEBUG 929
894 { 930 if (!vm.rectStaysRect() || !rrect.isSimple()) {
895 // we should have checked for this previously 931 return false;
896 SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple());
897 } 932 }
898 #endif
899 933
900 // do any matrix crunching before we reset the draw state for device coords 934 // do any matrix crunching before we reset the draw state for device coords
901 const SkRect& rrectBounds = rrect.getBounds(); 935 const SkRect& rrectBounds = rrect.getBounds();
902 SkRect bounds; 936 SkRect bounds;
903 vm.mapRect(&bounds, rrectBounds); 937 vm.mapRect(&bounds, rrectBounds);
904 938
905 SkVector radii = rrect.getSimpleRadii(); 939 SkVector radii = rrect.getSimpleRadii();
906 SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*radii.fX + 940 SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*radii.fX +
907 vm[SkMatrix::kMSkewY]*radii.fY); 941 vm[SkMatrix::kMSkewY]*radii.fY);
908 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX + 942 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX +
909 vm[SkMatrix::kMScaleY]*radii.fY); 943 vm[SkMatrix::kMScaleY]*radii.fY);
910 944
911 // if hairline stroke is greater than radius, we don't handle that right now
912 SkStrokeRec::Style style = stroke.getStyle(); 945 SkStrokeRec::Style style = stroke.getStyle();
913 if (SkStrokeRec::kHairline_Style == style &&
914 (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
915 return false;
916 }
917 946
918 // do (potentially) anisotropic mapping of stroke 947 // do (potentially) anisotropic mapping of stroke
919 SkVector scaledStroke; 948 SkVector scaledStroke;
920 SkScalar strokeWidth = stroke.getWidth(); 949 SkScalar strokeWidth = stroke.getWidth();
921 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat rix::kMSkewY]));
922 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr ix::kMScaleY]));
923 950
924 // if half of strokewidth is greater than radius, we don't handle that right now 951 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
925 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) { 952 SkStrokeRec::kHairline_Style == style;
953 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
954
955 if (hasStroke) {
956 if (SkStrokeRec::kHairline_Style == style) {
957 scaledStroke.set(1, 1);
958 } else {
959 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] +
960 vm[SkMatrix::kMSkewY]));
961 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] +
962 vm[SkMatrix::kMScaleY]));
963 }
964
965 // if half of strokewidth is greater than radius, we don't handle that r ight now
966 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok e.fY > yRadius) {
967 return false;
968 }
969 }
970
971 // The way the effect interpolates the offset-to-ellipse/circle-center attri bute only works on
972 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r ect of the nine-
973 // patch will have fractional coverage. This only matters when the interior is actually filled.
974 // We could consider falling back to rect rendering here, since a tiny radiu s is
975 // indistinguishable from a square corner.
976 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
926 return false; 977 return false;
927 } 978 }
928 979
929 // reset to device coordinates 980 // reset to device coordinates
930 GrDrawState* drawState = target->drawState(); 981 GrDrawState* drawState = target->drawState();
931 GrDrawState::AutoViewMatrixRestore avmr; 982 GrDrawState::AutoViewMatrixRestore avmr;
932 if (!avmr.setIdentity(drawState)) { 983 if (!avmr.setIdentity(drawState)) {
933 return false; 984 return false;
934 } 985 }
935 986
936 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style);
937
938 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu()); 987 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu());
939 if (NULL == indexBuffer) { 988 if (NULL == indexBuffer) {
940 GrPrintf("Failed to create index buffer!\n"); 989 GrPrintf("Failed to create index buffer!\n");
941 return false; 990 return false;
942 } 991 }
943 992
944 // if the corners are circles, use the circle renderer 993 // if the corners are circles, use the circle renderer
945 if ((!isStroked || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius ) { 994 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius ) {
946 drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircle VertexAttribs)); 995 drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircle VertexAttribs));
947 SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize()); 996 SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize());
948 997
949 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); 998 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
950 if (!geo.succeeded()) { 999 if (!geo.succeeded()) {
951 GrPrintf("Failed to get space for vertices!\n"); 1000 GrPrintf("Failed to get space for vertices!\n");
952 return false; 1001 return false;
953 } 1002 }
954 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); 1003 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
955 1004
956 SkScalar innerRadius = 0.0f; 1005 SkScalar innerRadius = 0.0f;
957 SkScalar outerRadius = xRadius; 1006 SkScalar outerRadius = xRadius;
958 SkScalar halfWidth = 0; 1007 SkScalar halfWidth = 0;
959 if (style != SkStrokeRec::kFill_Style) { 1008 if (hasStroke) {
960 if (SkScalarNearlyZero(scaledStroke.fX)) { 1009 if (SkScalarNearlyZero(scaledStroke.fX)) {
961 halfWidth = SK_ScalarHalf; 1010 halfWidth = SK_ScalarHalf;
962 } else { 1011 } else {
963 halfWidth = SkScalarHalf(scaledStroke.fX); 1012 halfWidth = SkScalarHalf(scaledStroke.fX);
964 } 1013 }
965 1014
966 if (isStroked) { 1015 if (isStrokeOnly) {
967 innerRadius = xRadius - halfWidth; 1016 innerRadius = xRadius - halfWidth;
968 } 1017 }
969 outerRadius += halfWidth; 1018 outerRadius += halfWidth;
970 bounds.outset(halfWidth, halfWidth); 1019 bounds.outset(halfWidth, halfWidth);
971 } 1020 }
972 1021
973 isStroked = (isStroked && innerRadius >= 0); 1022 isStrokeOnly = (isStrokeOnly && innerRadius >= 0);
974 1023
975 GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); 1024 GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly);
976 static const int kCircleEdgeAttrIndex = 1; 1025 static const int kCircleEdgeAttrIndex = 1;
977 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref(); 1026 drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
978 1027
979 // The radii are outset for two reasons. First, it allows the shader to simply perform 1028 // The radii are outset for two reasons. First, it allows the shader to simply perform
980 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the 1029 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
981 // verts of the bounding box that is rendered and the outset ensures the box will cover all 1030 // verts of the bounding box that is rendered and the outset ensures the box will cover all
982 // pixels partially covered by the circle. 1031 // pixels partially covered by the circle.
983 outerRadius += SK_ScalarHalf; 1032 outerRadius += SK_ScalarHalf;
984 innerRadius -= SK_ScalarHalf; 1033 innerRadius -= SK_ScalarHalf;
985 1034
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 verts++; 1067 verts++;
1019 1068
1020 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 1069 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
1021 verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]); 1070 verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]);
1022 verts->fOuterRadius = outerRadius; 1071 verts->fOuterRadius = outerRadius;
1023 verts->fInnerRadius = innerRadius; 1072 verts->fInnerRadius = innerRadius;
1024 verts++; 1073 verts++;
1025 } 1074 }
1026 1075
1027 // drop out the middle quad if we're stroked 1076 // drop out the middle quad if we're stroked
1028 int indexCnt = isStroked ? SK_ARRAY_COUNT(gRRectIndices)-6 : SK_ARRAY_CO UNT(gRRectIndices); 1077 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
1078 SK_ARRAY_COUNT(gRRectIndices);
1029 target->setIndexSourceToBuffer(indexBuffer); 1079 target->setIndexSourceToBuffer(indexBuffer);
1030 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds); 1080 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds);
1031 1081
1032 // otherwise we use the ellipse renderer 1082 // otherwise we use the ellipse renderer
1033 } else { 1083 } else {
1034 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllip seVertexAttribs)); 1084 drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllip seVertexAttribs));
1035 SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize()); 1085 SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize());
1036 1086
1037 SkScalar innerXRadius = 0.0f; 1087 SkScalar innerXRadius = 0.0f;
1038 SkScalar innerYRadius = 0.0f; 1088 SkScalar innerYRadius = 0.0f;
1039 if (SkStrokeRec::kFill_Style != style) { 1089 if (hasStroke) {
1040 if (SkScalarNearlyZero(scaledStroke.length())) { 1090 if (SkScalarNearlyZero(scaledStroke.length())) {
1041 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 1091 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
1042 } else { 1092 } else {
1043 scaledStroke.scale(SK_ScalarHalf); 1093 scaledStroke.scale(SK_ScalarHalf);
1044 } 1094 }
1045 1095
1046 // we only handle thick strokes for near-circular ellipses 1096 // we only handle thick strokes for near-circular ellipses
1047 if (scaledStroke.length() > SK_ScalarHalf && 1097 if (scaledStroke.length() > SK_ScalarHalf &&
1048 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad ius)) { 1098 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad ius)) {
1049 return false; 1099 return false;
1050 } 1100 }
1051 1101
1052 // we don't handle it if curvature of the stroke is less than curvat ure of the ellipse 1102 // we don't handle it if curvature of the stroke is less than curvat ure of the ellipse
1053 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok e.fY)*xRadius || 1103 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok e.fY)*xRadius ||
1054 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok e.fX)*yRadius) { 1104 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok e.fX)*yRadius) {
1055 return false; 1105 return false;
1056 } 1106 }
1057 1107
1058 // this is legit only if scale & translation (which should be the ca se at the moment) 1108 // this is legit only if scale & translation (which should be the ca se at the moment)
1059 if (isStroked) { 1109 if (isStrokeOnly) {
1060 innerXRadius = xRadius - scaledStroke.fX; 1110 innerXRadius = xRadius - scaledStroke.fX;
1061 innerYRadius = yRadius - scaledStroke.fY; 1111 innerYRadius = yRadius - scaledStroke.fY;
1062 } 1112 }
1063 1113
1064 xRadius += scaledStroke.fX; 1114 xRadius += scaledStroke.fX;
1065 yRadius += scaledStroke.fY; 1115 yRadius += scaledStroke.fY;
1066 bounds.outset(scaledStroke.fX, scaledStroke.fY); 1116 bounds.outset(scaledStroke.fX, scaledStroke.fY);
1067 } 1117 }
1068 1118
1069 isStroked = (isStroked && innerXRadius >= 0 && innerYRadius >= 0); 1119 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
1070 1120
1071 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); 1121 GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
1072 if (!geo.succeeded()) { 1122 if (!geo.succeeded()) {
1073 GrPrintf("Failed to get space for vertices!\n"); 1123 GrPrintf("Failed to get space for vertices!\n");
1074 return false; 1124 return false;
1075 } 1125 }
1076 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); 1126 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
1077 1127
1078 GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); 1128 GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly);
1079 static const int kEllipseOffsetAttrIndex = 1; 1129 static const int kEllipseOffsetAttrIndex = 1;
1080 static const int kEllipseRadiiAttrIndex = 2; 1130 static const int kEllipseRadiiAttrIndex = 2;
1081 drawState->addCoverageEffect(effect, 1131 drawState->addCoverageEffect(effect,
1082 kEllipseOffsetAttrIndex, kEllipseRadiiAttrI ndex)->unref(); 1132 kEllipseOffsetAttrIndex, kEllipseRadiiAttrI ndex)->unref();
1083 1133
1084 // Compute the reciprocals of the radii here to save time in the shader 1134 // Compute the reciprocals of the radii here to save time in the shader
1085 SkScalar xRadRecip = SkScalarInvert(xRadius); 1135 SkScalar xRadRecip = SkScalarInvert(xRadius);
1086 SkScalar yRadRecip = SkScalarInvert(yRadius); 1136 SkScalar yRadRecip = SkScalarInvert(yRadius);
1087 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); 1137 SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius);
1088 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); 1138 SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 verts++; 1177 verts++;
1128 1178
1129 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 1179 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
1130 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 1180 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]);
1131 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 1181 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
1132 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 1182 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
1133 verts++; 1183 verts++;
1134 } 1184 }
1135 1185
1136 // drop out the middle quad if we're stroked 1186 // drop out the middle quad if we're stroked
1137 int indexCnt = isStroked ? SK_ARRAY_COUNT(gRRectIndices)-6 : SK_ARRAY_CO UNT(gRRectIndices); 1187 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
1188 SK_ARRAY_COUNT(gRRectIndices);
1138 target->setIndexSourceToBuffer(indexBuffer); 1189 target->setIndexSourceToBuffer(indexBuffer);
1139 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds); 1190 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bou nds);
1140 } 1191 }
1141 1192
1142 return true; 1193 return true;
1143 } 1194 }
OLDNEW
« no previous file with comments | « src/gpu/GrOvalRenderer.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698