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

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: Rob's comments 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
« no previous file with comments | « 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 {
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
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
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
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 }
OLDNEW
« no previous file with comments | « include/core/SkRect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698