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

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

Issue 23684008: Fix bounds computation in GrAAHairlineRenderer (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 3 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
« include/core/SkRect.h ('K') | « include/core/SkRect.h ('k') | no next file » | 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 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
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
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
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
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
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
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 }
OLDNEW
« include/core/SkRect.h ('K') | « include/core/SkRect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698