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 "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
548 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); | 548 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); |
549 | 549 |
550 sk_sp<GrGeometryProcessor> DIEllipseGeometryProcessor::TestCreate(GrProcessorTes tData* d) { | 550 sk_sp<GrGeometryProcessor> DIEllipseGeometryProcessor::TestCreate(GrProcessorTes tData* d) { |
551 return sk_sp<GrGeometryProcessor>( | 551 return sk_sp<GrGeometryProcessor>( |
552 new DIEllipseGeometryProcessor(GrTest::TestMatrix(d->fRandom), | 552 new DIEllipseGeometryProcessor(GrTest::TestMatrix(d->fRandom), |
553 (DIEllipseStyle)(d->fRandom->nextRangeU(0 ,2)))); | 553 (DIEllipseStyle)(d->fRandom->nextRangeU(0 ,2)))); |
554 } | 554 } |
555 | 555 |
556 /////////////////////////////////////////////////////////////////////////////// | 556 /////////////////////////////////////////////////////////////////////////////// |
557 | 557 |
558 // We have two possible cases for geometry for a circle: | |
559 | |
560 // In the case of a normal fill, we draw geometry for the circle as an octagon. | |
561 static const uint16_t gFillCircleIndices[] = { | |
562 // enter the octagon | |
563 0, 1, 8, 1, 2, 8, | |
564 2, 3, 8, 3, 4, 8, | |
565 4, 5, 8, 5, 6, 8, | |
566 6, 7, 8, 7, 0, 8, | |
567 }; | |
568 | |
569 // For stroked circles, we use two nested octagons. | |
570 static const uint16_t gStrokeCircleIndices[] = { | |
571 // enter the octagon | |
572 0, 1, 9, 0, 9, 8, | |
573 1, 2, 10, 1, 10, 9, | |
574 2, 3, 11, 2, 11, 10, | |
575 3, 4, 12, 3, 12, 11, | |
576 4, 5, 13, 4, 13, 12, | |
577 5, 6, 14, 5, 14, 13, | |
578 6, 7, 15, 6, 15, 14, | |
579 7, 0, 8, 7, 8, 15, | |
580 }; | |
581 | |
582 static const int kIndicesPerFillCircle = SK_ARRAY_COUNT(gFillCircleIndices); | |
583 static const int kIndicesPerStrokeCircle = SK_ARRAY_COUNT(gStrokeCircleIndices); | |
584 static const int kVertsPerStrokeCircle = 16; | |
585 static const int kVertsPerFillCircle = 9; | |
586 | |
587 static int circle_type_to_vert_count(bool stroked) { | |
588 return stroked ? kVertsPerStrokeCircle : kVertsPerFillCircle; | |
589 } | |
590 | |
591 static int circle_type_to_index_count(bool stroked) { | |
592 return stroked ? kIndicesPerStrokeCircle : kIndicesPerFillCircle; | |
593 } | |
594 | |
595 static const uint16_t* circle_type_to_indices(bool stroked) { | |
596 return stroked ? gStrokeCircleIndices : gFillCircleIndices; | |
597 } | |
598 | |
599 /////////////////////////////////////////////////////////////////////////////// | |
600 | |
558 class CircleBatch : public GrVertexBatch { | 601 class CircleBatch : public GrVertexBatch { |
559 public: | 602 public: |
560 DEFINE_BATCH_CLASS_ID | 603 DEFINE_BATCH_CLASS_ID |
561 | 604 |
562 /** Optional extra params to render a partial arc rather than a full circle. */ | 605 /** Optional extra params to render a partial arc rather than a full circle. */ |
563 struct ArcParams { | 606 struct ArcParams { |
564 SkScalar fStartAngleRadians; | 607 SkScalar fStartAngleRadians; |
565 SkScalar fSweepAngleRadians; | 608 SkScalar fSweepAngleRadians; |
566 bool fUseCenter; | 609 bool fUseCenter; |
567 }; | 610 }; |
(...skipping 26 matching lines...) Expand all Loading... | |
594 } | 637 } |
595 | 638 |
596 viewMatrix.mapPoints(¢er, 1); | 639 viewMatrix.mapPoints(¢er, 1); |
597 radius = viewMatrix.mapRadius(radius); | 640 radius = viewMatrix.mapRadius(radius); |
598 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); | 641 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); |
599 | 642 |
600 bool isStrokeOnly = SkStrokeRec::kStroke_Style == recStyle || | 643 bool isStrokeOnly = SkStrokeRec::kStroke_Style == recStyle || |
601 SkStrokeRec::kHairline_Style == recStyle; | 644 SkStrokeRec::kHairline_Style == recStyle; |
602 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == re cStyle; | 645 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == re cStyle; |
603 | 646 |
604 SkScalar innerRadius = 0.0f; | 647 SkScalar innerRadius = -SK_ScalarHalf; |
605 SkScalar outerRadius = radius; | 648 SkScalar outerRadius = radius; |
606 SkScalar halfWidth = 0; | 649 SkScalar halfWidth = 0; |
607 if (hasStroke) { | 650 if (hasStroke) { |
608 if (SkScalarNearlyZero(strokeWidth)) { | 651 if (SkScalarNearlyZero(strokeWidth)) { |
609 halfWidth = SK_ScalarHalf; | 652 halfWidth = SK_ScalarHalf; |
610 } else { | 653 } else { |
611 halfWidth = SkScalarHalf(strokeWidth); | 654 halfWidth = SkScalarHalf(strokeWidth); |
612 } | 655 } |
613 | 656 |
614 outerRadius += halfWidth; | 657 outerRadius += halfWidth; |
615 if (isStrokeOnly) { | 658 if (isStrokeOnly) { |
616 innerRadius = radius - halfWidth; | 659 innerRadius = radius - halfWidth; |
617 } | 660 } |
618 } | 661 } |
619 | 662 |
620 // The radii are outset for two reasons. First, it allows the shader to simply perform | 663 // The radii are outset for two reasons. First, it allows the shader to simply perform |
621 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. | 664 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. |
622 // Second, the outer radius is used to compute the verts of the bounding box that is | 665 // Second, the outer radius is used to compute the verts of the bounding box that is |
623 // rendered and the outset ensures the box will cover all partially cove red by the circle. | 666 // rendered and the outset ensures the box will cover all partially cove red by the circle. |
624 outerRadius += SK_ScalarHalf; | 667 outerRadius += SK_ScalarHalf; |
625 innerRadius -= SK_ScalarHalf; | 668 innerRadius -= SK_ScalarHalf; |
669 bool stroked = isStrokeOnly && innerRadius > 0.0f; | |
626 CircleBatch* batch = new CircleBatch(); | 670 CircleBatch* batch = new CircleBatch(); |
627 batch->fViewMatrixIfUsingLocalCoords = viewMatrix; | 671 batch->fViewMatrixIfUsingLocalCoords = viewMatrix; |
628 | 672 |
629 // This makes every point fully inside the intersection plane. | 673 // This makes every point fully inside the intersection plane. |
630 static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f}; | 674 static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f}; |
631 // This makes every point fully outside the union plane. | 675 // This makes every point fully outside the union plane. |
632 static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f}; | 676 static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f}; |
633 SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, | 677 SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, |
634 center.fX + outerRadius, center.fY + outerRadius); | 678 center.fX + outerRadius, center.fY + outerRadius); |
635 | |
636 if (arcParams) { | 679 if (arcParams) { |
637 // The shader operates in a space where the circle is translated to be centered at the | 680 // The shader operates in a space where the circle is translated to be centered at the |
638 // origin. Here we compute points on the unit circle at the starting and ending angles. | 681 // origin. Here we compute points on the unit circle at the starting and ending angles. |
639 SkPoint startPoint, stopPoint; | 682 SkPoint startPoint, stopPoint; |
640 startPoint.fY = SkScalarSinCos(arcParams->fStartAngleRadians, &start Point.fX); | 683 startPoint.fY = SkScalarSinCos(arcParams->fStartAngleRadians, &start Point.fX); |
641 SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSwee pAngleRadians; | 684 SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSwee pAngleRadians; |
642 stopPoint.fY = SkScalarSinCos(endAngle, &stopPoint.fX); | 685 stopPoint.fY = SkScalarSinCos(endAngle, &stopPoint.fX); |
643 // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against | 686 // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against |
644 // radial lines. However, in both cases we have to be careful about the half-circle. | 687 // radial lines. However, in both cases we have to be careful about the half-circle. |
645 // case. In that case the two radial lines are equal and so that edg e gets clipped | 688 // case. In that case the two radial lines are equal and so that edg e gets clipped |
(...skipping 12 matching lines...) Expand all Loading... | |
658 } | 701 } |
659 batch->fClipPlane = true; | 702 batch->fClipPlane = true; |
660 if (SkScalarAbs(arcParams->fSweepAngleRadians) > SK_ScalarPI) { | 703 if (SkScalarAbs(arcParams->fSweepAngleRadians) > SK_ScalarPI) { |
661 batch->fGeoData.emplace_back(Geometry { | 704 batch->fGeoData.emplace_back(Geometry { |
662 color, | 705 color, |
663 innerRadius, | 706 innerRadius, |
664 outerRadius, | 707 outerRadius, |
665 {norm0.fX, norm0.fY, 0.5f}, | 708 {norm0.fX, norm0.fY, 0.5f}, |
666 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnused IsectPlane[2]}, | 709 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnused IsectPlane[2]}, |
667 {norm1.fX, norm1.fY, 0.5f}, | 710 {norm1.fX, norm1.fY, 0.5f}, |
668 devBounds | 711 devBounds, |
712 stroked | |
669 }); | 713 }); |
670 batch->fClipPlaneIsect = false; | 714 batch->fClipPlaneIsect = false; |
671 batch->fClipPlaneUnion = true; | 715 batch->fClipPlaneUnion = true; |
672 } else { | 716 } else { |
673 batch->fGeoData.emplace_back(Geometry { | 717 batch->fGeoData.emplace_back(Geometry { |
674 color, | 718 color, |
675 innerRadius, | 719 innerRadius, |
676 outerRadius, | 720 outerRadius, |
677 {norm0.fX, norm0.fY, 0.5f}, | 721 {norm0.fX, norm0.fY, 0.5f}, |
678 {norm1.fX, norm1.fY, 0.5f}, | 722 {norm1.fX, norm1.fY, 0.5f}, |
679 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnused UnionPlane[2]}, | 723 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnused UnionPlane[2]}, |
680 devBounds | 724 devBounds, |
725 stroked | |
681 }); | 726 }); |
682 batch->fClipPlaneIsect = true; | 727 batch->fClipPlaneIsect = true; |
683 batch->fClipPlaneUnion = false; | 728 batch->fClipPlaneUnion = false; |
684 } | 729 } |
685 } else { | 730 } else { |
686 // We clip to a secant of the original circle. | 731 // We clip to a secant of the original circle. |
687 startPoint.scale(radius); | 732 startPoint.scale(radius); |
688 stopPoint.scale(radius); | 733 stopPoint.scale(radius); |
689 SkVector norm = {startPoint.fY - stopPoint.fY, stopPoint.fX - st artPoint.fX}; | 734 SkVector norm = {startPoint.fY - stopPoint.fY, stopPoint.fX - st artPoint.fX}; |
690 norm.normalize(); | 735 norm.normalize(); |
691 if (arcParams->fSweepAngleRadians > 0) { | 736 if (arcParams->fSweepAngleRadians > 0) { |
692 norm.negate(); | 737 norm.negate(); |
693 } | 738 } |
694 SkScalar d = -norm.dot(startPoint) + 0.5f; | 739 SkScalar d = -norm.dot(startPoint) + 0.5f; |
695 | 740 |
696 batch->fGeoData.emplace_back(Geometry { | 741 batch->fGeoData.emplace_back(Geometry { |
697 color, | 742 color, |
698 innerRadius, | 743 innerRadius, |
699 outerRadius, | 744 outerRadius, |
700 {norm.fX, norm.fY, d}, | 745 {norm.fX, norm.fY, d}, |
701 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsec tPlane[2]}, | 746 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsec tPlane[2]}, |
702 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnio nPlane[2]}, | 747 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnio nPlane[2]}, |
703 devBounds | 748 devBounds, |
749 stroked | |
704 }); | 750 }); |
705 batch->fClipPlane = true; | 751 batch->fClipPlane = true; |
706 batch->fClipPlaneIsect = false; | 752 batch->fClipPlaneIsect = false; |
707 batch->fClipPlaneUnion = false; | 753 batch->fClipPlaneUnion = false; |
708 } | 754 } |
709 } else { | 755 } else { |
710 batch->fGeoData.emplace_back(Geometry { | 756 batch->fGeoData.emplace_back(Geometry { |
711 color, | 757 color, |
712 innerRadius, | 758 innerRadius, |
713 outerRadius, | 759 outerRadius, |
714 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]}, | 760 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]}, |
715 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]}, | 761 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]}, |
716 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2 ]}, | 762 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2 ]}, |
717 devBounds | 763 devBounds, |
764 stroked | |
718 }); | 765 }); |
719 batch->fClipPlane = false; | 766 batch->fClipPlane = false; |
720 batch->fClipPlaneIsect = false; | 767 batch->fClipPlaneIsect = false; |
721 batch->fClipPlaneUnion = false; | 768 batch->fClipPlaneUnion = false; |
722 } | 769 } |
723 // Use the original radius and stroke radius for the bounds so that it d oes not include the | 770 // Use the original radius and stroke radius for the bounds so that it d oes not include the |
724 // AA bloat. | 771 // AA bloat. |
725 radius += halfWidth; | 772 radius += halfWidth; |
726 batch->setBounds({center.fX - radius, center.fY - radius, | 773 batch->setBounds({center.fX - radius, center.fY - radius, |
727 center.fX + radius, center.fY + radius}, | 774 center.fX + radius, center.fY + radius}, |
728 HasAABloat::kYes, IsZeroArea::kNo); | 775 HasAABloat::kYes, IsZeroArea::kNo); |
729 batch->fStroked = isStrokeOnly && innerRadius > 0; | 776 batch->fVertCount = circle_type_to_vert_count(stroked); |
777 batch->fIndexCount = circle_type_to_index_count(stroked); | |
778 batch->fAllFill = !stroked; | |
730 return batch; | 779 return batch; |
731 } | 780 } |
732 | 781 |
733 const char* name() const override { return "CircleBatch"; } | 782 const char* name() const override { return "CircleBatch"; } |
734 | 783 |
735 SkString dumpInfo() const override { | 784 SkString dumpInfo() const override { |
736 SkString string; | 785 SkString string; |
737 for (int i = 0; i < fGeoData.count(); ++i) { | 786 for (int i = 0; i < fGeoData.count(); ++i) { |
738 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," | 787 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," |
739 "InnerRad: %.2f, OuterRad: %.2f\n", | 788 "InnerRad: %.2f, OuterRad: %.2f\n", |
(...skipping 25 matching lines...) Expand all Loading... | |
765 } | 814 } |
766 } | 815 } |
767 | 816 |
768 void onPrepareDraws(Target* target) const override { | 817 void onPrepareDraws(Target* target) const override { |
769 SkMatrix localMatrix; | 818 SkMatrix localMatrix; |
770 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { | 819 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
771 return; | 820 return; |
772 } | 821 } |
773 | 822 |
774 // Setup geometry processor | 823 // Setup geometry processor |
775 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, fClipPlane, | 824 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(!fAllFi ll, fClipPlane, |
776 fClipPl aneIsect, | 825 fClipPl aneIsect, |
777 fClipPl aneUnion, | 826 fClipPl aneUnion, |
778 localMa trix)); | 827 localMa trix)); |
779 | 828 |
780 struct CircleVertex { | 829 struct CircleVertex { |
781 SkPoint fPos; | 830 SkPoint fPos; |
782 GrColor fColor; | 831 GrColor fColor; |
783 SkPoint fOffset; | 832 SkPoint fOffset; |
784 SkScalar fOuterRadius; | 833 SkScalar fOuterRadius; |
785 SkScalar fInnerRadius; | 834 SkScalar fInnerRadius; |
786 // These planes may or may not be present in the vertex buffer. | 835 // These planes may or may not be present in the vertex buffer. |
787 SkScalar fHalfPlanes[3][3]; | 836 SkScalar fHalfPlanes[3][3]; |
788 }; | 837 }; |
789 | 838 |
790 int instanceCount = fGeoData.count(); | 839 int instanceCount = fGeoData.count(); |
791 size_t vertexStride = gp->getVertexStride(); | 840 size_t vertexStride = gp->getVertexStride(); |
792 SkASSERT(vertexStride == sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * si zeof(SkScalar)) | 841 SkASSERT(vertexStride == sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * si zeof(SkScalar)) |
793 - (fClipPlaneIsect? 0 : 3 * sizeof(SkScalar)) | 842 - (fClipPlaneIsect? 0 : 3 * sizeof(SkScalar)) |
794 - (fClipPlaneUnion? 0 : 3 * sizeof(SkScalar))); | 843 - (fClipPlaneUnion? 0 : 3 * sizeof(SkScalar))); |
795 QuadHelper helper; | 844 |
796 char* vertices = reinterpret_cast<char*>(helper.init(target, vertexStrid e, instanceCount)); | 845 const GrBuffer* vertexBuffer; |
846 int firstVertex; | |
847 char* vertices = (char*)target->makeVertexSpace(vertexStride, fVertCount , | |
848 &vertexBuffer, &firstVer tex); | |
797 if (!vertices) { | 849 if (!vertices) { |
850 SkDebugf("Could not allocate vertices\n"); | |
798 return; | 851 return; |
799 } | 852 } |
800 | 853 |
854 const GrBuffer* indexBuffer = nullptr; | |
855 int firstIndex = 0; | |
856 uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &f irstIndex); | |
857 if (!indices) { | |
858 SkDebugf("Could not allocate indices\n"); | |
859 return; | |
860 } | |
861 | |
862 int currStartVertex = 0; | |
801 for (int i = 0; i < instanceCount; i++) { | 863 for (int i = 0; i < instanceCount; i++) { |
802 const Geometry& geom = fGeoData[i]; | 864 const Geometry& geom = fGeoData[i]; |
803 | 865 |
804 GrColor color = geom.fColor; | 866 GrColor color = geom.fColor; |
805 SkScalar innerRadius = geom.fInnerRadius; | 867 SkScalar innerRadius = geom.fInnerRadius; |
806 SkScalar outerRadius = geom.fOuterRadius; | 868 SkScalar outerRadius = geom.fOuterRadius; |
807 | 869 |
808 const SkRect& bounds = geom.fDevBounds; | 870 const SkRect& bounds = geom.fDevBounds; |
809 CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 0)*vertexStride); | 871 CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 0*vert exStride); |
810 CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 1)*vertexStride); | 872 CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 1*vert exStride); |
811 CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 2)*vertexStride); | 873 CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + 2*vert exStride); |
812 CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 3)*vertexStride); | 874 CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + 3*vert exStride); |
875 CircleVertex* v4 = reinterpret_cast<CircleVertex*>(vertices + 4*vert exStride); | |
876 CircleVertex* v5 = reinterpret_cast<CircleVertex*>(vertices + 5*vert exStride); | |
877 CircleVertex* v6 = reinterpret_cast<CircleVertex*>(vertices + 6*vert exStride); | |
878 CircleVertex* v7 = reinterpret_cast<CircleVertex*>(vertices + 7*vert exStride); | |
813 | 879 |
814 // The inner radius in the vertex data must be specified in normaliz ed space. | 880 // The inner radius in the vertex data must be specified in normaliz ed space. |
815 innerRadius = innerRadius / outerRadius; | 881 innerRadius = innerRadius / outerRadius; |
816 v0->fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); | 882 |
883 SkPoint center = SkPoint::Make(bounds.centerX(), bounds.centerY()); | |
884 SkScalar halfWidth = 0.5f*bounds.width(); | |
885 SkScalar octOffset = 0.41421356237f; // sqrt(2) - 1 | |
886 | |
887 v0->fPos = center + SkPoint::Make(-octOffset*halfWidth, -halfWidth); | |
817 v0->fColor = color; | 888 v0->fColor = color; |
818 v0->fOffset = SkPoint::Make(-1, -1); | 889 v0->fOffset = SkPoint::Make(-octOffset, -1); |
819 v0->fOuterRadius = outerRadius; | 890 v0->fOuterRadius = outerRadius; |
820 v0->fInnerRadius = innerRadius; | 891 v0->fInnerRadius = innerRadius; |
821 | 892 |
822 v1->fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); | 893 v1->fPos = center + SkPoint::Make(octOffset*halfWidth, -halfWidth); |
823 v1->fColor = color; | 894 v1->fColor = color; |
824 v1->fOffset = SkPoint::Make(-1, 1); | 895 v1->fOffset = SkPoint::Make(octOffset, -1); |
825 v1->fOuterRadius = outerRadius; | 896 v1->fOuterRadius = outerRadius; |
826 v1->fInnerRadius = innerRadius; | 897 v1->fInnerRadius = innerRadius; |
827 | 898 |
828 v2->fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); | 899 v2->fPos = center + SkPoint::Make(halfWidth, -octOffset*halfWidth); |
829 v2->fColor = color; | 900 v2->fColor = color; |
830 v2->fOffset = SkPoint::Make(1, 1); | 901 v2->fOffset = SkPoint::Make(1, -octOffset); |
831 v2->fOuterRadius = outerRadius; | 902 v2->fOuterRadius = outerRadius; |
832 v2->fInnerRadius = innerRadius; | 903 v2->fInnerRadius = innerRadius; |
833 | 904 |
834 v3->fPos = SkPoint::Make(bounds.fRight, bounds.fTop); | 905 v3->fPos = center + SkPoint::Make(halfWidth, octOffset*halfWidth); |
835 v3->fColor = color; | 906 v3->fColor = color; |
836 v3->fOffset = SkPoint::Make(1, -1); | 907 v3->fOffset = SkPoint::Make(1, octOffset); |
837 v3->fOuterRadius = outerRadius; | 908 v3->fOuterRadius = outerRadius; |
838 v3->fInnerRadius = innerRadius; | 909 v3->fInnerRadius = innerRadius; |
839 | 910 |
911 v4->fPos = center + SkPoint::Make(octOffset*halfWidth, halfWidth); | |
912 v4->fColor = color; | |
913 v4->fOffset = SkPoint::Make(octOffset, 1); | |
914 v4->fOuterRadius = outerRadius; | |
915 v4->fInnerRadius = innerRadius; | |
916 | |
917 v5->fPos = center + SkPoint::Make(-octOffset*halfWidth, halfWidth); | |
918 v5->fColor = color; | |
919 v5->fOffset = SkPoint::Make(-octOffset, 1); | |
920 v5->fOuterRadius = outerRadius; | |
921 v5->fInnerRadius = innerRadius; | |
922 | |
923 v6->fPos = center + SkPoint::Make(-halfWidth, octOffset*halfWidth); | |
924 v6->fColor = color; | |
925 v6->fOffset = SkPoint::Make(-1, octOffset); | |
926 v6->fOuterRadius = outerRadius; | |
927 v6->fInnerRadius = innerRadius; | |
928 | |
929 v7->fPos = center + SkPoint::Make(-halfWidth, -octOffset*halfWidth); | |
930 v7->fColor = color; | |
931 v7->fOffset = SkPoint::Make(-1, -octOffset); | |
932 v7->fOuterRadius = outerRadius; | |
933 v7->fInnerRadius = innerRadius; | |
934 | |
840 if (fClipPlane) { | 935 if (fClipPlane) { |
841 memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | 936 memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); |
842 memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | 937 memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); |
843 memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | 938 memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); |
844 memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | 939 memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); |
940 memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | |
941 memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | |
942 memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | |
943 memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) ); | |
845 } | 944 } |
846 int unionIdx = 1; | 945 int unionIdx = 1; |
847 if (fClipPlaneIsect) { | 946 if (fClipPlaneIsect) { |
848 memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | 947 memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); |
849 memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | 948 memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); |
850 memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | 949 memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); |
851 memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | 950 memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); |
951 memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | |
952 memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | |
953 memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | |
954 memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar )); | |
852 unionIdx = 2; | 955 unionIdx = 2; |
853 } | 956 } |
854 if (fClipPlaneUnion) { | 957 if (fClipPlaneUnion) { |
855 memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | 958 memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); |
856 memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | 959 memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); |
857 memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | 960 memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); |
858 memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | 961 memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); |
962 memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | |
963 memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | |
964 memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | |
965 memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar)); | |
859 } | 966 } |
967 | |
968 if (geom.fStroked) { | |
robertphillips
2016/10/06 20:09:56
Could this path share a "FillInOctVerts" subroutin
jvanverth1
2016/10/06 21:46:19
I tried that but got stymied -- I'll take another
robertphillips
2016/10/06 21:51:22
It should probably be a follow up CL.
| |
969 // compute the inner ring | |
970 CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); | |
971 CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 9 * vertexStride); | |
972 CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + 10 * vertexStride); | |
973 CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + 11 * vertexStride); | |
974 CircleVertex* v4 = reinterpret_cast<CircleVertex*>(vertices + 12 * vertexStride); | |
975 CircleVertex* v5 = reinterpret_cast<CircleVertex*>(vertices + 13 * vertexStride); | |
976 CircleVertex* v6 = reinterpret_cast<CircleVertex*>(vertices + 14 * vertexStride); | |
977 CircleVertex* v7 = reinterpret_cast<CircleVertex*>(vertices + 15 * vertexStride); | |
978 | |
979 // cosine and sine of pi/8 | |
980 SkScalar c = 0.923579533f; | |
981 SkScalar s = 0.382683432f; | |
982 SkScalar r = geom.fInnerRadius; | |
983 | |
984 v0->fPos = center + SkPoint::Make(-s*r, -c*r); | |
985 v0->fColor = color; | |
986 v0->fOffset = SkPoint::Make(-s*innerRadius, -c*innerRadius); | |
987 v0->fOuterRadius = outerRadius; | |
988 v0->fInnerRadius = innerRadius; | |
989 | |
990 v1->fPos = center + SkPoint::Make(s*r, -c*r); | |
991 v1->fColor = color; | |
992 v1->fOffset = SkPoint::Make(s*innerRadius, -c*innerRadius); | |
993 v1->fOuterRadius = outerRadius; | |
994 v1->fInnerRadius = innerRadius; | |
995 | |
996 v2->fPos = center + SkPoint::Make(c*r, -s*r); | |
997 v2->fColor = color; | |
998 v2->fOffset = SkPoint::Make(c*innerRadius, -s*innerRadius); | |
999 v2->fOuterRadius = outerRadius; | |
1000 v2->fInnerRadius = innerRadius; | |
1001 | |
1002 v3->fPos = center + SkPoint::Make(c*r, s*r); | |
1003 v3->fColor = color; | |
1004 v3->fOffset = SkPoint::Make(c*innerRadius, s*innerRadius); | |
1005 v3->fOuterRadius = outerRadius; | |
1006 v3->fInnerRadius = innerRadius; | |
1007 | |
1008 v4->fPos = center + SkPoint::Make(s*r, c*r); | |
1009 v4->fColor = color; | |
1010 v4->fOffset = SkPoint::Make(s*innerRadius, c*innerRadius); | |
1011 v4->fOuterRadius = outerRadius; | |
1012 v4->fInnerRadius = innerRadius; | |
1013 | |
1014 v5->fPos = center + SkPoint::Make(-s*r, c*r); | |
1015 v5->fColor = color; | |
1016 v5->fOffset = SkPoint::Make(-s*innerRadius, c*innerRadius); | |
1017 v5->fOuterRadius = outerRadius; | |
1018 v5->fInnerRadius = innerRadius; | |
1019 | |
1020 v6->fPos = center + SkPoint::Make(-c*r, s*r); | |
1021 v6->fColor = color; | |
1022 v6->fOffset = SkPoint::Make(-c*innerRadius, s*innerRadius); | |
1023 v6->fOuterRadius = outerRadius; | |
1024 v6->fInnerRadius = innerRadius; | |
1025 | |
1026 v7->fPos = center + SkPoint::Make(-c*r, -s*r); | |
1027 v7->fColor = color; | |
1028 v7->fOffset = SkPoint::Make(-c*innerRadius, -s*innerRadius); | |
1029 v7->fOuterRadius = outerRadius; | |
1030 v7->fInnerRadius = innerRadius; | |
1031 | |
1032 if (fClipPlane) { | |
1033 memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1034 memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1035 memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1036 memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1037 memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1038 memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1039 memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1040 memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1041 } | |
1042 int unionIdx = 1; | |
1043 if (fClipPlaneIsect) { | |
1044 memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1045 memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1046 memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1047 memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1048 memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1049 memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1050 memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1051 memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1052 unionIdx = 2; | |
1053 } | |
1054 if (fClipPlaneUnion) { | |
1055 memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1056 memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1057 memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1058 memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1059 memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1060 memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1061 memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1062 memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1063 } | |
1064 } else { | |
1065 // filled | |
1066 CircleVertex* v8 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); | |
1067 v8->fPos = center; | |
1068 v8->fColor = color; | |
1069 v8->fOffset = SkPoint::Make(0, 0); | |
1070 v8->fOuterRadius = outerRadius; | |
1071 v8->fInnerRadius = innerRadius; | |
1072 if (fClipPlane) { | |
1073 memcpy(v8->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkSca lar)); | |
1074 } | |
1075 int unionIdx = 1; | |
1076 if (fClipPlaneIsect) { | |
1077 memcpy(v8->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkSc alar)); | |
1078 unionIdx = 2; | |
1079 } | |
1080 if (fClipPlaneUnion) { | |
1081 memcpy(v8->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * size of(SkScalar)); | |
1082 } | |
1083 } | |
1084 | |
1085 const uint16_t* primIndices = circle_type_to_indices(geom.fStroked); | |
1086 const int primIndexCount = circle_type_to_index_count(geom.fStroked) ; | |
1087 for (int i = 0; i < primIndexCount; ++i) { | |
1088 *indices++ = primIndices[i] + currStartVertex; | |
1089 } | |
1090 | |
1091 currStartVertex += circle_type_to_vert_count(geom.fStroked); | |
1092 vertices += circle_type_to_vert_count(geom.fStroked)*vertexStride; | |
860 } | 1093 } |
861 helper.recordDraw(target, gp); | 1094 |
1095 GrMesh mesh; | |
1096 mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, | |
1097 firstIndex, fVertCount, fIndexCount); | |
1098 target->draw(gp.get(), mesh); | |
862 } | 1099 } |
863 | 1100 |
864 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1101 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
865 CircleBatch* that = t->cast<CircleBatch>(); | 1102 CircleBatch* that = t->cast<CircleBatch>(); |
866 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), | 1103 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), |
867 that->bounds(), caps)) { | 1104 that->bounds(), caps)) { |
868 return false; | 1105 return false; |
869 } | 1106 } |
870 | 1107 |
871 if (this->fStroked != that->fStroked) { | 1108 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) { |
872 return false; | 1109 return false; |
873 } | 1110 } |
874 | 1111 |
875 // Because we've set up the batches that don't use the planes with noop values | 1112 // Because we've set up the batches that don't use the planes with noop values |
876 // we can just accumulate used planes by later batches. | 1113 // we can just accumulate used planes by later batches. |
877 fClipPlane |= that->fClipPlane; | 1114 fClipPlane |= that->fClipPlane; |
878 fClipPlaneIsect |= that->fClipPlaneIsect; | 1115 fClipPlaneIsect |= that->fClipPlaneIsect; |
879 fClipPlaneUnion |= that->fClipPlaneUnion; | 1116 fClipPlaneUnion |= that->fClipPlaneUnion; |
880 | 1117 |
881 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) { | |
882 return false; | |
883 } | |
884 | |
885 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); | 1118 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
886 this->joinBounds(*that); | 1119 this->joinBounds(*that); |
1120 fVertCount += that->fVertCount; | |
1121 fIndexCount += that->fIndexCount; | |
1122 fAllFill = fAllFill && that->fAllFill; | |
887 return true; | 1123 return true; |
888 } | 1124 } |
889 | 1125 |
890 struct Geometry { | 1126 struct Geometry { |
891 GrColor fColor; | 1127 GrColor fColor; |
892 SkScalar fInnerRadius; | 1128 SkScalar fInnerRadius; |
893 SkScalar fOuterRadius; | 1129 SkScalar fOuterRadius; |
894 SkScalar fClipPlane[3]; | 1130 SkScalar fClipPlane[3]; |
895 SkScalar fIsectPlane[3]; | 1131 SkScalar fIsectPlane[3]; |
896 SkScalar fUnionPlane[3]; | 1132 SkScalar fUnionPlane[3]; |
897 SkRect fDevBounds; | 1133 SkRect fDevBounds; |
1134 bool fStroked; | |
898 }; | 1135 }; |
899 | 1136 |
900 bool fStroked; | 1137 SkSTArray<1, Geometry, true> fGeoData; |
1138 SkMatrix fViewMatrixIfUsingLocalCoords; | |
1139 int fVertCount; | |
1140 int fIndexCount; | |
1141 bool fAllFill; | |
901 bool fClipPlane; | 1142 bool fClipPlane; |
902 bool fClipPlaneIsect; | 1143 bool fClipPlaneIsect; |
903 bool fClipPlaneUnion; | 1144 bool fClipPlaneUnion; |
904 SkMatrix fViewMatrixIfUsingLocalCoords; | |
905 SkSTArray<1, Geometry, true> fGeoData; | |
906 | 1145 |
907 typedef GrVertexBatch INHERITED; | 1146 typedef GrVertexBatch INHERITED; |
908 }; | 1147 }; |
909 | 1148 |
910 /////////////////////////////////////////////////////////////////////////////// | 1149 /////////////////////////////////////////////////////////////////////////////// |
911 | 1150 |
912 class EllipseBatch : public GrVertexBatch { | 1151 class EllipseBatch : public GrVertexBatch { |
913 public: | 1152 public: |
914 DEFINE_BATCH_CLASS_ID | 1153 DEFINE_BATCH_CLASS_ID |
915 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& ellipse, | 1154 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& ellipse, |
(...skipping 1246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2162 } | 2401 } |
2163 | 2402 |
2164 DRAW_BATCH_TEST_DEFINE(RRectBatch) { | 2403 DRAW_BATCH_TEST_DEFINE(RRectBatch) { |
2165 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | 2404 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
2166 GrColor color = GrRandomColor(random); | 2405 GrColor color = GrRandomColor(random); |
2167 const SkRRect& rrect = GrTest::TestRRectSimple(random); | 2406 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
2168 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); | 2407 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); |
2169 } | 2408 } |
2170 | 2409 |
2171 #endif | 2410 #endif |
OLD | NEW |