OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrAAHairLinePathRenderer.h" | 8 #include "GrAAHairLinePathRenderer.h" |
9 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 a0.fPos = a; | 582 a0.fPos = a; |
583 a0.fPos += abN; | 583 a0.fPos += abN; |
584 a1.fPos = a; | 584 a1.fPos = a; |
585 a1.fPos -= abN; | 585 a1.fPos -= abN; |
586 | 586 |
587 c0.fPos = c; | 587 c0.fPos = c; |
588 c0.fPos += cbN; | 588 c0.fPos += cbN; |
589 c1.fPos = c; | 589 c1.fPos = c; |
590 c1.fPos -= cbN; | 590 c1.fPos -= cbN; |
591 | 591 |
592 // This point may not be within 1 pixel of a control point. We update the bo
unding box to | |
593 // include it. | |
594 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); | 592 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); |
595 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); | 593 devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kVertsPerQuad
); |
596 | 594 |
597 if (toSrc) { | 595 if (toSrc) { |
598 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kVertsP
erQuad); | 596 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kVertsP
erQuad); |
599 } | 597 } |
600 } | 598 } |
601 | 599 |
602 // Equations based off of Loop-Blinn Quadratic GPU Rendering | 600 // Equations based off of Loop-Blinn Quadratic GPU Rendering |
603 // Input Parametric: | 601 // Input Parametric: |
604 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) | 602 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) |
605 // Output Implicit: | 603 // Output Implicit: |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 GrDrawTarget* target, | 714 GrDrawTarget* target, |
717 const PtArray& lines, | 715 const PtArray& lines, |
718 int lineCnt, | 716 int lineCnt, |
719 GrDrawTarget::AutoReleaseGeometry* arg, | 717 GrDrawTarget::AutoReleaseGeometry* arg, |
720 SkRect* devBounds) { | 718 SkRect* devBounds) { |
721 GrDrawState* drawState = target->drawState(); | 719 GrDrawState* drawState = target->drawState(); |
722 int rtHeight = drawState->getRenderTarget()->height(); | 720 int rtHeight = drawState->getRenderTarget()->height(); |
723 | 721 |
724 const SkMatrix& viewM = drawState->getViewMatrix(); | 722 const SkMatrix& viewM = drawState->getViewMatrix(); |
725 | 723 |
726 *devBounds = path.getBounds(); | |
727 viewM.mapRect(devBounds); | |
728 devBounds->outset(SK_Scalar1, SK_Scalar1); | 724 devBounds->outset(SK_Scalar1, SK_Scalar1); |
729 | 725 |
730 int vertCnt = kVertsPerLineSeg * lineCnt; | 726 int vertCnt = kVertsPerLineSeg * lineCnt; |
731 | 727 |
732 target->drawState()->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(g
HairlineLineAttribs)); | 728 target->drawState()->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(g
HairlineLineAttribs)); |
733 SkASSERT(sizeof(LineVertex) == target->getDrawState().getVertexSize()); | 729 SkASSERT(sizeof(LineVertex) == target->getDrawState().getVertexSize()); |
734 | 730 |
735 if (!arg->set(target, vertCnt, 0)) { | 731 if (!arg->set(target, vertCnt, 0)) { |
736 return false; | 732 return false; |
737 } | 733 } |
738 | 734 |
739 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); | 735 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); |
740 | 736 |
741 const SkMatrix* toSrc = NULL; | 737 const SkMatrix* toSrc = NULL; |
742 SkMatrix ivm; | 738 SkMatrix ivm; |
743 | 739 |
744 if (viewM.hasPerspective()) { | 740 if (viewM.hasPerspective()) { |
745 if (viewM.invert(&ivm)) { | 741 if (viewM.invert(&ivm)) { |
746 toSrc = &ivm; | 742 toSrc = &ivm; |
747 } | 743 } |
748 } | 744 } |
749 | 745 devBounds->set(lines.begin(), lines.count()); |
750 for (int i = 0; i < lineCnt; ++i) { | 746 for (int i = 0; i < lineCnt; ++i) { |
751 add_line(&lines[2*i], rtHeight, toSrc, drawState->getCoverage(), &verts)
; | 747 add_line(&lines[2*i], rtHeight, toSrc, drawState->getCoverage(), &verts)
; |
752 } | 748 } |
| 749 // All the verts computed by add_line are within unit distance of the end po
ints. Add a little |
| 750 // extra to account for vector normalization precision. |
| 751 static const SkScalar kOutset = SK_Scalar1 + SK_Scalar1 / 20; |
| 752 devBounds->outset(kOutset, kOutset); |
753 | 753 |
754 return true; | 754 return true; |
755 } | 755 } |
756 | 756 |
757 bool GrAAHairLinePathRenderer::createBezierGeom( | 757 bool GrAAHairLinePathRenderer::createBezierGeom( |
758 const SkPath& path, | 758 const SkPath& path, |
759 GrDrawTarget* target, | 759 GrDrawTarget* target, |
760 const PtArray& quads, | 760 const PtArray& quads, |
761 int quadCnt, | 761 int quadCnt, |
762 const PtArray& conics, | 762 const PtArray& conics, |
763 int conicCnt, | 763 int conicCnt, |
764 const IntArray& qSubdivs, | 764 const IntArray& qSubdivs, |
765 const FloatArray& cWeights, | 765 const FloatArray& cWeights, |
766 GrDrawTarget::AutoReleaseGeometry* arg
, | 766 GrDrawTarget::AutoReleaseGeometry* arg
, |
767 SkRect* devBounds) { | 767 SkRect* devBounds) { |
768 GrDrawState* drawState = target->drawState(); | 768 GrDrawState* drawState = target->drawState(); |
769 | 769 |
770 const SkMatrix& viewM = drawState->getViewMatrix(); | 770 const SkMatrix& viewM = drawState->getViewMatrix(); |
771 | 771 |
772 // All the vertices that we compute are within 1 of path control points with
the exception of | |
773 // one of the bounding vertices for each quad. The add_quads() function will
update the bounds | |
774 // for each quad added. | |
775 *devBounds = path.getBounds(); | |
776 viewM.mapRect(devBounds); | |
777 devBounds->outset(SK_Scalar1, SK_Scalar1); | |
778 | |
779 int vertCnt = kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt; | 772 int vertCnt = kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt; |
780 | 773 |
781 target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(SK_ARRAY_COUNT
(gHairlineBezierAttribs)); | 774 target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(SK_ARRAY_COUNT
(gHairlineBezierAttribs)); |
782 SkASSERT(sizeof(BezierVertex) == target->getDrawState().getVertexSize()); | 775 SkASSERT(sizeof(BezierVertex) == target->getDrawState().getVertexSize()); |
783 | 776 |
784 if (!arg->set(target, vertCnt, 0)) { | 777 if (!arg->set(target, vertCnt, 0)) { |
785 return false; | 778 return false; |
786 } | 779 } |
787 | 780 |
788 BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); | 781 BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); |
789 | 782 |
790 const SkMatrix* toDevice = NULL; | 783 const SkMatrix* toDevice = NULL; |
791 const SkMatrix* toSrc = NULL; | 784 const SkMatrix* toSrc = NULL; |
792 SkMatrix ivm; | 785 SkMatrix ivm; |
793 | 786 |
794 if (viewM.hasPerspective()) { | 787 if (viewM.hasPerspective()) { |
795 if (viewM.invert(&ivm)) { | 788 if (viewM.invert(&ivm)) { |
796 toDevice = &viewM; | 789 toDevice = &viewM; |
797 toSrc = &ivm; | 790 toSrc = &ivm; |
798 } | 791 } |
799 } | 792 } |
800 | 793 |
| 794 // Seed the dev bounds with some pts known to be inside. Each quad and conic
grows the bounding |
| 795 // box to include its vertices. |
| 796 SkPoint seedPts[2]; |
| 797 if (quadCnt) { |
| 798 seedPts[0] = quads[0]; |
| 799 seedPts[1] = quads[2]; |
| 800 } else if (conicCnt) { |
| 801 seedPts[0] = conics[0]; |
| 802 seedPts[1] = conics[2]; |
| 803 } |
| 804 if (NULL != toDevice) { |
| 805 toDevice->mapPoints(seedPts, 2); |
| 806 } |
| 807 devBounds->set(seedPts[0], seedPts[1]); |
| 808 |
801 int unsubdivQuadCnt = quads.count() / 3; | 809 int unsubdivQuadCnt = quads.count() / 3; |
802 for (int i = 0; i < unsubdivQuadCnt; ++i) { | 810 for (int i = 0; i < unsubdivQuadCnt; ++i) { |
803 SkASSERT(qSubdivs[i] >= 0); | 811 SkASSERT(qSubdivs[i] >= 0); |
804 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); | 812 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); |
805 } | 813 } |
806 | 814 |
807 // Start Conics | 815 // Start Conics |
808 for (int i = 0; i < conicCnt; ++i) { | 816 for (int i = 0; i < conicCnt; ++i) { |
809 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds
); | 817 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds
); |
810 } | 818 } |
(...skipping 12 matching lines...) Expand all Loading... |
823 target->caps()->shaderDerivativeSupport()) { | 831 target->caps()->shaderDerivativeSupport()) { |
824 return true; | 832 return true; |
825 } | 833 } |
826 return false; | 834 return false; |
827 } | 835 } |
828 | 836 |
829 template <class VertexType> | 837 template <class VertexType> |
830 bool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertice
s, int vCount) | 838 bool check_bounds(GrDrawState* drawState, const SkRect& devBounds, void* vertice
s, int vCount) |
831 { | 839 { |
832 SkRect tolDevBounds = devBounds; | 840 SkRect tolDevBounds = devBounds; |
833 tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); | 841 // The bounds ought to be tight, but in perspective the below code runs the
verts |
| 842 // through the view matrix to get back to dev coords, which can introduce im
precision. |
| 843 if (drawState->getViewMatrix().hasPerspective()) { |
| 844 tolDevBounds.outset(SK_Scalar1 / 1000, SK_Scalar1 / 1000); |
| 845 } else { |
| 846 // Non-persp matrices cause this path renderer to draw in device space. |
| 847 SkASSERT(drawState->getViewMatrix().isIdentity()); |
| 848 } |
834 SkRect actualBounds; | 849 SkRect actualBounds; |
835 | 850 |
836 VertexType* verts = reinterpret_cast<VertexType*>(vertices); | 851 VertexType* verts = reinterpret_cast<VertexType*>(vertices); |
837 bool first = true; | 852 bool first = true; |
838 for (int i = 0; i < vCount; ++i) { | 853 for (int i = 0; i < vCount; ++i) { |
839 SkPoint pos = verts[i].fPos; | 854 SkPoint pos = verts[i].fPos; |
840 // This is a hack to workaround the fact that we move some degenerate se
gments offscreen. | 855 // This is a hack to workaround the fact that we move some degenerate se
gments offscreen. |
841 if (SK_ScalarMax == pos.fX) { | 856 if (SK_ScalarMax == pos.fX) { |
842 continue; | 857 continue; |
843 } | 858 } |
(...skipping 29 matching lines...) Expand all Loading... |
873 PREALLOC_PTARRAY(128) quads; | 888 PREALLOC_PTARRAY(128) quads; |
874 PREALLOC_PTARRAY(128) conics; | 889 PREALLOC_PTARRAY(128) conics; |
875 IntArray qSubdivs; | 890 IntArray qSubdivs; |
876 FloatArray cWeights; | 891 FloatArray cWeights; |
877 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip
Bounds, | 892 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip
Bounds, |
878 &lines, &quads, &conics, &qSubdivs, &cWei
ghts); | 893 &lines, &quads, &conics, &qSubdivs, &cWei
ghts); |
879 lineCnt = lines.count() / 2; | 894 lineCnt = lines.count() / 2; |
880 conicCnt = conics.count() / 3; | 895 conicCnt = conics.count() / 3; |
881 | 896 |
882 // do lines first | 897 // do lines first |
883 { | 898 if (lineCnt) { |
884 GrDrawTarget::AutoReleaseGeometry arg; | 899 GrDrawTarget::AutoReleaseGeometry arg; |
885 SkRect devBounds; | 900 SkRect devBounds; |
886 | 901 |
887 if (!this->createLineGeom(path, | 902 if (!this->createLineGeom(path, |
888 target, | 903 target, |
889 lines, | 904 lines, |
890 lineCnt, | 905 lineCnt, |
891 &arg, | 906 &arg, |
892 &devBounds)) { | 907 &devBounds)) { |
893 return false; | 908 return false; |
(...skipping 25 matching lines...) Expand all Loading... |
919 0, // startI | 934 0, // startI |
920 kVertsPerLineSeg*n, // vCount | 935 kVertsPerLineSeg*n, // vCount |
921 kIdxsPerLineSeg*n, | 936 kIdxsPerLineSeg*n, |
922 &devBounds); // iCount | 937 &devBounds); // iCount |
923 lines += n; | 938 lines += n; |
924 } | 939 } |
925 } | 940 } |
926 } | 941 } |
927 | 942 |
928 // then quadratics/conics | 943 // then quadratics/conics |
929 { | 944 if (quadCnt || conicCnt) { |
930 GrDrawTarget::AutoReleaseGeometry arg; | 945 GrDrawTarget::AutoReleaseGeometry arg; |
931 SkRect devBounds; | 946 SkRect devBounds; |
932 | 947 |
933 if (!this->createBezierGeom(path, | 948 if (!this->createBezierGeom(path, |
934 target, | 949 target, |
935 quads, | 950 quads, |
936 quadCnt, | 951 quadCnt, |
937 conics, | 952 conics, |
938 conicCnt, | 953 conicCnt, |
939 qSubdivs, | 954 qSubdivs, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 &devBounds); | 1012 &devBounds); |
998 conics += n; | 1013 conics += n; |
999 } | 1014 } |
1000 } | 1015 } |
1001 } | 1016 } |
1002 | 1017 |
1003 target->resetIndexSource(); | 1018 target->resetIndexSource(); |
1004 | 1019 |
1005 return true; | 1020 return true; |
1006 } | 1021 } |
OLD | NEW |