Chromium Code Reviews| 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 { | |
|
robertphillips
2013/09/01 11:15:37
Why is it true that if it doesn't have perspective
bsalomon
2013/09/03 14:47:35
This path renderer renders in device space for non
| |
| 846 SkASSERT(drawState->getViewMatrix().isIdentity()); | |
| 847 } | |
| 834 SkRect actualBounds; | 848 SkRect actualBounds; |
| 835 | 849 |
| 836 VertexType* verts = reinterpret_cast<VertexType*>(vertices); | 850 VertexType* verts = reinterpret_cast<VertexType*>(vertices); |
| 837 bool first = true; | 851 bool first = true; |
| 838 for (int i = 0; i < vCount; ++i) { | 852 for (int i = 0; i < vCount; ++i) { |
| 839 SkPoint pos = verts[i].fPos; | 853 SkPoint pos = verts[i].fPos; |
| 840 // This is a hack to workaround the fact that we move some degenerate se gments offscreen. | 854 // This is a hack to workaround the fact that we move some degenerate se gments offscreen. |
| 841 if (SK_ScalarMax == pos.fX) { | 855 if (SK_ScalarMax == pos.fX) { |
| 842 continue; | 856 continue; |
| 843 } | 857 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 873 PREALLOC_PTARRAY(128) quads; | 887 PREALLOC_PTARRAY(128) quads; |
| 874 PREALLOC_PTARRAY(128) conics; | 888 PREALLOC_PTARRAY(128) conics; |
| 875 IntArray qSubdivs; | 889 IntArray qSubdivs; |
| 876 FloatArray cWeights; | 890 FloatArray cWeights; |
| 877 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip Bounds, | 891 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip Bounds, |
| 878 &lines, &quads, &conics, &qSubdivs, &cWei ghts); | 892 &lines, &quads, &conics, &qSubdivs, &cWei ghts); |
| 879 lineCnt = lines.count() / 2; | 893 lineCnt = lines.count() / 2; |
| 880 conicCnt = conics.count() / 3; | 894 conicCnt = conics.count() / 3; |
| 881 | 895 |
| 882 // do lines first | 896 // do lines first |
| 883 { | 897 if (lineCnt) { |
| 884 GrDrawTarget::AutoReleaseGeometry arg; | 898 GrDrawTarget::AutoReleaseGeometry arg; |
| 885 SkRect devBounds; | 899 SkRect devBounds; |
| 886 | 900 |
| 887 if (!this->createLineGeom(path, | 901 if (!this->createLineGeom(path, |
| 888 target, | 902 target, |
| 889 lines, | 903 lines, |
| 890 lineCnt, | 904 lineCnt, |
| 891 &arg, | 905 &arg, |
| 892 &devBounds)) { | 906 &devBounds)) { |
| 893 return false; | 907 return false; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 919 0, // startI | 933 0, // startI |
| 920 kVertsPerLineSeg*n, // vCount | 934 kVertsPerLineSeg*n, // vCount |
| 921 kIdxsPerLineSeg*n, | 935 kIdxsPerLineSeg*n, |
| 922 &devBounds); // iCount | 936 &devBounds); // iCount |
| 923 lines += n; | 937 lines += n; |
| 924 } | 938 } |
| 925 } | 939 } |
| 926 } | 940 } |
| 927 | 941 |
| 928 // then quadratics/conics | 942 // then quadratics/conics |
| 929 { | 943 if (quadCnt || conicCnt) { |
| 930 GrDrawTarget::AutoReleaseGeometry arg; | 944 GrDrawTarget::AutoReleaseGeometry arg; |
| 931 SkRect devBounds; | 945 SkRect devBounds; |
| 932 | 946 |
| 933 if (!this->createBezierGeom(path, | 947 if (!this->createBezierGeom(path, |
| 934 target, | 948 target, |
| 935 quads, | 949 quads, |
| 936 quadCnt, | 950 quadCnt, |
| 937 conics, | 951 conics, |
| 938 conicCnt, | 952 conicCnt, |
| 939 qSubdivs, | 953 qSubdivs, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 997 &devBounds); | 1011 &devBounds); |
| 998 conics += n; | 1012 conics += n; |
| 999 } | 1013 } |
| 1000 } | 1014 } |
| 1001 } | 1015 } |
| 1002 | 1016 |
| 1003 target->resetIndexSource(); | 1017 target->resetIndexSource(); |
| 1004 | 1018 |
| 1005 return true; | 1019 return true; |
| 1006 } | 1020 } |
| OLD | NEW |