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

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

Issue 23708036: "Fix" for hairline corner bugs (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Folded new GM into hairlines GM 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 | « gm/hairlines.cpp ('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 10 matching lines...) Expand all
21 21
22 #include "effects/GrBezierEffect.h" 22 #include "effects/GrBezierEffect.h"
23 23
24 namespace { 24 namespace {
25 // quadratics are rendered as 5-sided polys in order to bound the 25 // quadratics are rendered as 5-sided polys in order to bound the
26 // AA stroke around the center-curve. See comments in push_quad_index_buffer and 26 // AA stroke around the center-curve. See comments in push_quad_index_buffer and
27 // bloat_quad. Quadratics and conics share an index buffer 27 // bloat_quad. Quadratics and conics share an index buffer
28 static const int kVertsPerQuad = 5; 28 static const int kVertsPerQuad = 5;
29 static const int kIdxsPerQuad = 9; 29 static const int kIdxsPerQuad = 9;
30 30
31 // lines are rendered as:
32 // *______________*
33 // |\ -_______ /|
34 // | \ \ / |
35 // | *--------* |
36 // | / ______/ \ |
37 // */_-__________\*
38 // For: 6 vertices and 18 indices (for 6 triangles)
31 static const int kVertsPerLineSeg = 6; 39 static const int kVertsPerLineSeg = 6;
32 static const int kIdxsPerLineSeg = 12; 40 static const int kIdxsPerLineSeg = 18;
33 41
34 static const int kNumQuadsInIdxBuffer = 256; 42 static const int kNumQuadsInIdxBuffer = 256;
35 static const size_t kQuadIdxSBufize = kIdxsPerQuad * 43 static const size_t kQuadIdxSBufize = kIdxsPerQuad *
36 sizeof(uint16_t) * 44 sizeof(uint16_t) *
37 kNumQuadsInIdxBuffer; 45 kNumQuadsInIdxBuffer;
38 46
39 static const int kNumLineSegsInIdxBuffer = 256; 47 static const int kNumLineSegsInIdxBuffer = 256;
40 static const size_t kLineSegIdxSBufize = kIdxsPerLineSeg * 48 static const size_t kLineSegIdxSBufize = kIdxsPerLineSeg *
41 sizeof(uint16_t) * 49 sizeof(uint16_t) *
42 kNumLineSegsInIdxBuffer; 50 kNumLineSegsInIdxBuffer;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 } 91 }
84 } 92 }
85 93
86 static bool push_line_index_data(GrIndexBuffer* lIdxBuffer) { 94 static bool push_line_index_data(GrIndexBuffer* lIdxBuffer) {
87 uint16_t* data = (uint16_t*) lIdxBuffer->lock(); 95 uint16_t* data = (uint16_t*) lIdxBuffer->lock();
88 bool tempData = NULL == data; 96 bool tempData = NULL == data;
89 if (tempData) { 97 if (tempData) {
90 data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg); 98 data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg);
91 } 99 }
92 for (int i = 0; i < kNumLineSegsInIdxBuffer; ++i) { 100 for (int i = 0; i < kNumLineSegsInIdxBuffer; ++i) {
93 // Each line segment is rendered as two quads, with alpha = 1 along the 101 // Each line segment is rendered as two quads and two triangles.
94 // spine of the segment, and alpha = 0 along the outer edges, represente d 102 // p0 and p1 have alpha = 1 while all other points have alpha = 0.
95 // horizontally (i.e., the line equation is t*(p1-p0) + p0) 103 // The four external points are offset 1 pixel perpendicular to the
104 // line and half a pixel parallel to the line.
96 // 105 //
97 // p4 p5 106 // p4 p5
98 // p0 p1 107 // p0 p1
99 // p2 p3 108 // p2 p3
100 // 109 //
101 // Each is drawn as four triangles specified by these 12 indices: 110 // Each is drawn as six triangles specified by these 18 indices:
102 int baseIdx = i * kIdxsPerLineSeg; 111 int baseIdx = i * kIdxsPerLineSeg;
103 uint16_t baseVert = (uint16_t)(i * kVertsPerLineSeg); 112 uint16_t baseVert = (uint16_t)(i * kVertsPerLineSeg);
104 data[0 + baseIdx] = baseVert + 0; // p0 113 data[0 + baseIdx] = baseVert + 0;
105 data[1 + baseIdx] = baseVert + 1; // p1 114 data[1 + baseIdx] = baseVert + 1;
106 data[2 + baseIdx] = baseVert + 2; // p2 115 data[2 + baseIdx] = baseVert + 3;
107 116
108 data[3 + baseIdx] = baseVert + 2; // p2 117 data[3 + baseIdx] = baseVert + 0;
109 data[4 + baseIdx] = baseVert + 1; // p1 118 data[4 + baseIdx] = baseVert + 3;
110 data[5 + baseIdx] = baseVert + 3; // p3 119 data[5 + baseIdx] = baseVert + 2;
111 120
112 data[6 + baseIdx] = baseVert + 0; // p0 121 data[6 + baseIdx] = baseVert + 0;
113 data[7 + baseIdx] = baseVert + 5; // p5 122 data[7 + baseIdx] = baseVert + 4;
114 data[8 + baseIdx] = baseVert + 1; // p1 123 data[8 + baseIdx] = baseVert + 5;
115 124
116 data[9 + baseIdx] = baseVert + 0; // p0 125 data[9 + baseIdx] = baseVert + 0;
117 data[10+ baseIdx] = baseVert + 4; // p4 126 data[10+ baseIdx] = baseVert + 5;
118 data[11+ baseIdx] = baseVert + 5; // p5 127 data[11+ baseIdx] = baseVert + 1;
128
129 data[12 + baseIdx] = baseVert + 0;
130 data[13 + baseIdx] = baseVert + 2;
131 data[14 + baseIdx] = baseVert + 4;
132
133 data[15 + baseIdx] = baseVert + 1;
134 data[16 + baseIdx] = baseVert + 5;
135 data[17 + baseIdx] = baseVert + 3;
119 } 136 }
120 if (tempData) { 137 if (tempData) {
121 bool ret = lIdxBuffer->updateData(data, kLineSegIdxSBufize); 138 bool ret = lIdxBuffer->updateData(data, kLineSegIdxSBufize);
122 delete[] data; 139 delete[] data;
123 return ret; 140 return ret;
124 } else { 141 } else {
125 lIdxBuffer->unlock(); 142 lIdxBuffer->unlock();
126 return true; 143 return true;
127 } 144 }
128 } 145 }
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); 659 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds);
643 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); 660 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds);
644 } else { 661 } else {
645 bloat_quad(p, toDevice, toSrc, *vert, devBounds); 662 bloat_quad(p, toDevice, toSrc, *vert, devBounds);
646 set_uv_quad(p, *vert); 663 set_uv_quad(p, *vert);
647 *vert += kVertsPerQuad; 664 *vert += kVertsPerQuad;
648 } 665 }
649 } 666 }
650 667
651 void add_line(const SkPoint p[2], 668 void add_line(const SkPoint p[2],
652 int rtHeight,
653 const SkMatrix* toSrc, 669 const SkMatrix* toSrc,
654 GrColor coverage, 670 GrColor coverage,
655 LineVertex** vert) { 671 LineVertex** vert) {
656 const SkPoint& a = p[0]; 672 const SkPoint& a = p[0];
657 const SkPoint& b = p[1]; 673 const SkPoint& b = p[1];
658 674
659 SkVector orthVec = b; 675 SkVector ortho, vec = b;
660 orthVec -= a; 676 vec -= a;
661 677
662 if (orthVec.setLength(SK_Scalar1)) { 678 if (vec.setLength(SK_ScalarHalf)) {
663 orthVec.setOrthog(orthVec); 679 // Create a vector orthogonal to 'vec' and of unit length
680 ortho.fX = 2.0f * vec.fY;
681 ortho.fY = -2.0f * vec.fX;
664 682
665 for (int i = 0; i < kVertsPerLineSeg; ++i) { 683 (*vert)[0].fPos = a;
666 (*vert)[i].fPos = (i & 0x1) ? b : a; 684 (*vert)[0].fCoverage = coverage;
667 if (i & 0x2) { 685 (*vert)[1].fPos = b;
668 (*vert)[i].fPos += orthVec; 686 (*vert)[1].fCoverage = coverage;
669 (*vert)[i].fCoverage = 0; 687 (*vert)[2].fPos = a - vec + ortho;
670 } else if (i & 0x4) { 688 (*vert)[2].fCoverage = 0;
671 (*vert)[i].fPos -= orthVec; 689 (*vert)[3].fPos = b + vec + ortho;
672 (*vert)[i].fCoverage = 0; 690 (*vert)[3].fCoverage = 0;
673 } else { 691 (*vert)[4].fPos = a - vec - ortho;
674 (*vert)[i].fCoverage = coverage; 692 (*vert)[4].fCoverage = 0;
675 } 693 (*vert)[5].fPos = b + vec - ortho;
676 } 694 (*vert)[5].fCoverage = 0;
695
677 if (NULL != toSrc) { 696 if (NULL != toSrc) {
678 toSrc->mapPointsWithStride(&(*vert)->fPos, 697 toSrc->mapPointsWithStride(&(*vert)->fPos,
679 sizeof(LineVertex), 698 sizeof(LineVertex),
680 kVertsPerLineSeg); 699 kVertsPerLineSeg);
681 } 700 }
682 } else { 701 } else {
683 // just make it degenerate and likely offscreen 702 // just make it degenerate and likely offscreen
684 for (int i = 0; i < kVertsPerLineSeg; ++i) { 703 for (int i = 0; i < kVertsPerLineSeg; ++i) {
685 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax); 704 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
686 } 705 }
(...skipping 15 matching lines...) Expand all
702 }; 721 };
703 722
704 // position + coverage 723 // position + coverage
705 extern const GrVertexAttrib gHairlineLineAttribs[] = { 724 extern const GrVertexAttrib gHairlineLineAttribs[] = {
706 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindin g}, 725 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindin g},
707 {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBindin g}, 726 {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBindin g},
708 }; 727 };
709 728
710 }; 729 };
711 730
712 bool GrAAHairLinePathRenderer::createLineGeom( 731 bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path,
713 const SkPath& path, 732 GrDrawTarget* target,
714 GrDrawTarget* target, 733 const PtArray& lines,
715 const PtArray& lines, 734 int lineCnt,
716 int lineCnt, 735 GrDrawTarget::AutoReleaseGeometry* arg,
717 GrDrawTarget::AutoReleaseGeometry* arg, 736 SkRect* devBounds) {
718 SkRect* devBounds) {
719 GrDrawState* drawState = target->drawState(); 737 GrDrawState* drawState = target->drawState();
720 int rtHeight = drawState->getRenderTarget()->height();
721 738
722 const SkMatrix& viewM = drawState->getViewMatrix(); 739 const SkMatrix& viewM = drawState->getViewMatrix();
723 740
724 devBounds->outset(SK_Scalar1, SK_Scalar1); 741 devBounds->outset(SK_Scalar1, SK_Scalar1);
725 742
726 int vertCnt = kVertsPerLineSeg * lineCnt; 743 int vertCnt = kVertsPerLineSeg * lineCnt;
727 744
728 target->drawState()->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(g HairlineLineAttribs)); 745 drawState->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(gHairlineLi neAttribs));
729 SkASSERT(sizeof(LineVertex) == target->getDrawState().getVertexSize()); 746 SkASSERT(sizeof(LineVertex) == drawState->getVertexSize());
730 747
731 if (!arg->set(target, vertCnt, 0)) { 748 if (!arg->set(target, vertCnt, 0)) {
732 return false; 749 return false;
733 } 750 }
734 751
735 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); 752 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices());
736 753
737 const SkMatrix* toSrc = NULL; 754 const SkMatrix* toSrc = NULL;
738 SkMatrix ivm; 755 SkMatrix ivm;
739 756
740 if (viewM.hasPerspective()) { 757 if (viewM.hasPerspective()) {
741 if (viewM.invert(&ivm)) { 758 if (viewM.invert(&ivm)) {
742 toSrc = &ivm; 759 toSrc = &ivm;
743 } 760 }
744 } 761 }
745 devBounds->set(lines.begin(), lines.count()); 762 devBounds->set(lines.begin(), lines.count());
746 for (int i = 0; i < lineCnt; ++i) { 763 for (int i = 0; i < lineCnt; ++i) {
747 add_line(&lines[2*i], rtHeight, toSrc, drawState->getCoverage(), &verts) ; 764 add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts);
748 } 765 }
749 // All the verts computed by add_line are within unit distance of the end po ints. Add a little 766 // 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. 767 // extra to account for vector normalization precision.
751 static const SkScalar kOutset = SK_Scalar1 + SK_Scalar1 / 20; 768 static const SkScalar kOutset = SK_Scalar1 + SK_Scalar1 / 20;
752 devBounds->outset(kOutset, kOutset); 769 devBounds->outset(kOutset, kOutset);
753 770
754 return true; 771 return true;
755 } 772 }
756 773
757 bool GrAAHairLinePathRenderer::createBezierGeom( 774 bool GrAAHairLinePathRenderer::createBezierGeom(
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 target, 920 target,
904 lines, 921 lines,
905 lineCnt, 922 lineCnt,
906 &arg, 923 &arg,
907 &devBounds)) { 924 &devBounds)) {
908 return false; 925 return false;
909 } 926 }
910 927
911 GrDrawTarget::AutoStateRestore asr; 928 GrDrawTarget::AutoStateRestore asr;
912 929
913 // createGeom transforms the geometry to device space when the matrix do es not have 930 // createLineGeom transforms the geometry to device space when the matri x does not have
914 // perspective. 931 // perspective.
915 if (target->getDrawState().getViewMatrix().hasPerspective()) { 932 if (target->getDrawState().getViewMatrix().hasPerspective()) {
916 asr.set(target, GrDrawTarget::kPreserve_ASRInit); 933 asr.set(target, GrDrawTarget::kPreserve_ASRInit);
917 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 934 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
918 return false; 935 return false;
919 } 936 }
920 GrDrawState* drawState = target->drawState(); 937 GrDrawState* drawState = target->drawState();
921 938
922 // Check devBounds 939 // Check devBounds
923 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), 940 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(),
924 kVertsPerLineSeg * lineCnt)); 941 kVertsPerLineSeg * lineCnt));
925 942
926 { 943 {
927 GrDrawState::AutoRestoreEffects are(drawState); 944 GrDrawState::AutoRestoreEffects are(drawState);
928 target->setIndexSourceToBuffer(fLinesIndexBuffer); 945 target->setIndexSourceToBuffer(fLinesIndexBuffer);
929 int lines = 0; 946 int lines = 0;
930 while (lines < lineCnt) { 947 while (lines < lineCnt) {
931 int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer); 948 int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer);
932 target->drawIndexed(kTriangles_GrPrimitiveType, 949 target->drawIndexed(kTriangles_GrPrimitiveType,
933 kVertsPerLineSeg*lines, // startV 950 kVertsPerLineSeg*lines, // startV
934 0, // startI 951 0, // startI
935 kVertsPerLineSeg*n, // vCount 952 kVertsPerLineSeg*n, // vCount
936 kIdxsPerLineSeg*n, 953 kIdxsPerLineSeg*n, // iCount
937 &devBounds); // iCount 954 &devBounds);
938 lines += n; 955 lines += n;
939 } 956 }
940 } 957 }
941 } 958 }
942 959
943 // then quadratics/conics 960 // then quadratics/conics
944 if (quadCnt || conicCnt) { 961 if (quadCnt || conicCnt) {
945 GrDrawTarget::AutoReleaseGeometry arg; 962 GrDrawTarget::AutoReleaseGeometry arg;
946 SkRect devBounds; 963 SkRect devBounds;
947 964
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 &devBounds); 1029 &devBounds);
1013 conics += n; 1030 conics += n;
1014 } 1031 }
1015 } 1032 }
1016 } 1033 }
1017 1034
1018 target->resetIndexSource(); 1035 target->resetIndexSource();
1019 1036
1020 return true; 1037 return true;
1021 } 1038 }
OLDNEW
« no previous file with comments | « gm/hairlines.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698