| 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 |