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 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 /////////////////////////////////////////////////////////////////////////////// | 643 /////////////////////////////////////////////////////////////////////////////// |
644 | 644 |
645 namespace { | 645 namespace { |
646 // position + edge | 646 // position + edge |
647 extern const GrVertexAttrib gHairlineBezierAttribs[] = { | 647 extern const GrVertexAttrib gHairlineBezierAttribs[] = { |
648 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing}, | 648 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing}, |
649 {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding} | 649 {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding} |
650 }; | 650 }; |
651 }; | 651 }; |
652 | 652 |
653 bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, | 653 bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target, |
654 GrDrawTarget* target, | 654 GrDrawState* drawState, |
| 655 GrDrawTarget::AutoReleaseGeometry*
arg, |
| 656 SkRect* devBounds, |
| 657 const SkPath& path, |
655 const PtArray& lines, | 658 const PtArray& lines, |
656 int lineCnt, | 659 int lineCnt) { |
657 GrDrawTarget::AutoReleaseGeometry*
arg, | |
658 SkRect* devBounds) { | |
659 GrDrawState* drawState = target->drawState(); | |
660 | |
661 const SkMatrix& viewM = drawState->getViewMatrix(); | 660 const SkMatrix& viewM = drawState->getViewMatrix(); |
662 | 661 |
663 int vertCnt = kLineSegNumVertices * lineCnt; | 662 int vertCnt = kLineSegNumVertices * lineCnt; |
664 | 663 |
665 GrDefaultGeoProcFactory::SetAttribs(drawState, GrDefaultGeoProcFactory::kPos
ition_GPType | | 664 GrDefaultGeoProcFactory::SetAttribs(drawState, GrDefaultGeoProcFactory::kPos
ition_GPType | |
666 GrDefaultGeoProcFactory::kCov
erage_GPType); | 665 GrDefaultGeoProcFactory::kCov
erage_GPType); |
667 | 666 |
668 if (!arg->set(target, vertCnt, 0)) { | 667 if (!arg->set(target, vertCnt, drawState->getVertexStride(), 0)) { |
669 return false; | 668 return false; |
670 } | 669 } |
671 | 670 |
672 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); | 671 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices()); |
673 | 672 |
674 const SkMatrix* toSrc = NULL; | 673 const SkMatrix* toSrc = NULL; |
675 SkMatrix ivm; | 674 SkMatrix ivm; |
676 | 675 |
677 if (viewM.hasPerspective()) { | 676 if (viewM.hasPerspective()) { |
678 if (viewM.invert(&ivm)) { | 677 if (viewM.invert(&ivm)) { |
679 toSrc = &ivm; | 678 toSrc = &ivm; |
680 } | 679 } |
681 } | 680 } |
682 devBounds->set(lines.begin(), lines.count()); | 681 devBounds->set(lines.begin(), lines.count()); |
683 for (int i = 0; i < lineCnt; ++i) { | 682 for (int i = 0; i < lineCnt; ++i) { |
684 add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts); | 683 add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts); |
685 } | 684 } |
686 // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the en
d points. | 685 // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the en
d points. |
687 static const SkScalar kSqrtOfOneAndAQuarter = 1.118f; | 686 static const SkScalar kSqrtOfOneAndAQuarter = 1.118f; |
688 // Add a little extra to account for vector normalization precision. | 687 // Add a little extra to account for vector normalization precision. |
689 static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20; | 688 static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20; |
690 devBounds->outset(kOutset, kOutset); | 689 devBounds->outset(kOutset, kOutset); |
691 | 690 |
692 return true; | 691 return true; |
693 } | 692 } |
694 | 693 |
695 bool GrAAHairLinePathRenderer::createBezierGeom( | 694 bool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target, |
696 const SkPath& path, | 695 GrDrawState* drawState, |
697 GrDrawTarget* target, | 696 GrDrawTarget::AutoReleaseGeometr
y* arg, |
698 const PtArray& quads, | 697 SkRect* devBounds, |
699 int quadCnt, | 698 const SkPath& path, |
700 const PtArray& conics, | 699 const PtArray& quads, |
701 int conicCnt, | 700 int quadCnt, |
702 const IntArray& qSubdivs, | 701 const PtArray& conics, |
703 const FloatArray& cWeights, | 702 int conicCnt, |
704 GrDrawTarget::AutoReleaseGeometry* arg
, | 703 const IntArray& qSubdivs, |
705 SkRect* devBounds) { | 704 const FloatArray& cWeights) { |
706 GrDrawState* drawState = target->drawState(); | |
707 | |
708 const SkMatrix& viewM = drawState->getViewMatrix(); | 705 const SkMatrix& viewM = drawState->getViewMatrix(); |
709 | 706 |
710 int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt; | 707 int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt; |
711 | 708 |
712 int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs); | 709 int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs); |
713 target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, si
zeof(BezierVertex)); | 710 drawState->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(Bezie
rVertex)); |
714 | 711 |
715 if (!arg->set(target, vertCnt, 0)) { | 712 if (!arg->set(target, vertCnt, drawState->getVertexStride(), 0)) { |
716 return false; | 713 return false; |
717 } | 714 } |
718 | 715 |
719 BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); | 716 BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); |
720 | 717 |
721 const SkMatrix* toDevice = NULL; | 718 const SkMatrix* toDevice = NULL; |
722 const SkMatrix* toSrc = NULL; | 719 const SkMatrix* toSrc = NULL; |
723 SkMatrix ivm; | 720 SkMatrix ivm; |
724 | 721 |
725 if (viewM.hasPerspective()) { | 722 if (viewM.hasPerspective()) { |
(...skipping 24 matching lines...) Expand all Loading... |
750 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); | 747 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); |
751 } | 748 } |
752 | 749 |
753 // Start Conics | 750 // Start Conics |
754 for (int i = 0; i < conicCnt; ++i) { | 751 for (int i = 0; i < conicCnt; ++i) { |
755 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds
); | 752 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds
); |
756 } | 753 } |
757 return true; | 754 return true; |
758 } | 755 } |
759 | 756 |
760 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, | 757 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, |
| 758 const GrDrawState* drawState, |
| 759 const SkPath& path, |
761 const SkStrokeRec& stroke, | 760 const SkStrokeRec& stroke, |
762 const GrDrawTarget* target, | |
763 bool antiAlias) const { | 761 bool antiAlias) const { |
764 if (!antiAlias) { | 762 if (!antiAlias) { |
765 return false; | 763 return false; |
766 } | 764 } |
767 | 765 |
768 if (!IsStrokeHairlineOrEquivalent(stroke, | 766 if (!IsStrokeHairlineOrEquivalent(stroke, |
769 target->getDrawState().getViewMatrix(), | 767 drawState->getViewMatrix(), |
770 NULL)) { | 768 NULL)) { |
771 return false; | 769 return false; |
772 } | 770 } |
773 | 771 |
774 if (SkPath::kLine_SegmentMask == path.getSegmentMasks() || | 772 if (SkPath::kLine_SegmentMask == path.getSegmentMasks() || |
775 target->caps()->shaderDerivativeSupport()) { | 773 target->caps()->shaderDerivativeSupport()) { |
776 return true; | 774 return true; |
777 } | 775 } |
778 return false; | 776 return false; |
779 } | 777 } |
(...skipping 28 matching lines...) Expand all Loading... |
808 actualBounds.growToInclude(pos.fX, pos.fY); | 806 actualBounds.growToInclude(pos.fX, pos.fY); |
809 } | 807 } |
810 } | 808 } |
811 if (!first) { | 809 if (!first) { |
812 return tolDevBounds.contains(actualBounds); | 810 return tolDevBounds.contains(actualBounds); |
813 } | 811 } |
814 | 812 |
815 return true; | 813 return true; |
816 } | 814 } |
817 | 815 |
818 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, | 816 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, |
| 817 GrDrawState* drawState, |
| 818 const SkPath& path, |
819 const SkStrokeRec& stroke, | 819 const SkStrokeRec& stroke, |
820 GrDrawTarget* target, | |
821 bool antiAlias) { | 820 bool antiAlias) { |
822 GrDrawState* drawState = target->drawState(); | |
823 | |
824 SkScalar hairlineCoverage; | 821 SkScalar hairlineCoverage; |
825 if (IsStrokeHairlineOrEquivalent(stroke, | 822 if (IsStrokeHairlineOrEquivalent(stroke, drawState->getViewMatrix(), |
826 target->getDrawState().getViewMatrix(), | |
827 &hairlineCoverage)) { | 823 &hairlineCoverage)) { |
828 uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * | 824 uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * drawState->g
etCoverage()); |
829 target->getDrawState().getCover
age()); | 825 drawState->setCoverage(newCoverage); |
830 target->drawState()->setCoverage(newCoverage); | |
831 } | 826 } |
832 | 827 |
833 SkIRect devClipBounds; | 828 SkIRect devClipBounds; |
834 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devC
lipBounds); | 829 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devC
lipBounds); |
835 | 830 |
836 int lineCnt; | 831 int lineCnt; |
837 int quadCnt; | 832 int quadCnt; |
838 int conicCnt; | 833 int conicCnt; |
839 PREALLOC_PTARRAY(128) lines; | 834 PREALLOC_PTARRAY(128) lines; |
840 PREALLOC_PTARRAY(128) quads; | 835 PREALLOC_PTARRAY(128) quads; |
841 PREALLOC_PTARRAY(128) conics; | 836 PREALLOC_PTARRAY(128) conics; |
842 IntArray qSubdivs; | 837 IntArray qSubdivs; |
843 FloatArray cWeights; | 838 FloatArray cWeights; |
844 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip
Bounds, | 839 quadCnt = generate_lines_and_quads(path, drawState->getViewMatrix(), devClip
Bounds, |
845 &lines, &quads, &conics, &qSubdivs, &cWei
ghts); | 840 &lines, &quads, &conics, &qSubdivs, &cWei
ghts); |
846 lineCnt = lines.count() / 2; | 841 lineCnt = lines.count() / 2; |
847 conicCnt = conics.count() / 3; | 842 conicCnt = conics.count() / 3; |
848 | 843 |
849 // do lines first | 844 // do lines first |
850 if (lineCnt) { | 845 if (lineCnt) { |
851 GrDrawTarget::AutoReleaseGeometry arg; | 846 GrDrawTarget::AutoReleaseGeometry arg; |
852 SkRect devBounds; | 847 SkRect devBounds; |
853 | 848 |
854 if (!this->createLineGeom(path, | 849 if (!this->createLineGeom(target, |
855 target, | 850 drawState, |
| 851 &arg, |
| 852 &devBounds, |
| 853 path, |
856 lines, | 854 lines, |
857 lineCnt, | 855 lineCnt)) { |
858 &arg, | |
859 &devBounds)) { | |
860 return false; | 856 return false; |
861 } | 857 } |
862 | 858 |
863 GrDrawTarget::AutoStateRestore asr; | |
864 | |
865 // createLineGeom transforms the geometry to device space when the matri
x does not have | 859 // createLineGeom transforms the geometry to device space when the matri
x does not have |
866 // perspective. | 860 // perspective. |
867 if (target->getDrawState().getViewMatrix().hasPerspective()) { | 861 GrDrawState::AutoViewMatrixRestore avmr; |
868 asr.set(target, GrDrawTarget::kPreserve_ASRInit); | 862 if (!drawState->getViewMatrix().hasPerspective() && !avmr.setIdentity(dr
awState)) { |
869 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { | |
870 return false; | 863 return false; |
871 } | 864 } |
872 GrDrawState* drawState = target->drawState(); | |
873 | 865 |
874 // Check devBounds | 866 // Check devBounds |
875 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), | 867 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), |
876 kLineSegNumVertices * lineCnt)); | 868 kLineSegNumVertices * lineCnt)); |
877 | 869 |
878 { | 870 { |
879 GrDrawState::AutoRestoreEffects are(drawState); | 871 GrDrawState::AutoRestoreEffects are(drawState); |
880 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(fals
e))->unref(); | 872 drawState->setGeometryProcessor(GrDefaultGeoProcFactory::Create(fals
e))->unref(); |
881 target->setIndexSourceToBuffer(fLinesIndexBuffer); | 873 target->setIndexSourceToBuffer(fLinesIndexBuffer); |
882 int lines = 0; | 874 int lines = 0; |
883 while (lines < lineCnt) { | 875 while (lines < lineCnt) { |
884 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer); | 876 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer); |
885 target->drawIndexed(kTriangles_GrPrimitiveType, | 877 target->drawIndexed(drawState, |
| 878 kTriangles_GrPrimitiveType, |
886 kLineSegNumVertices*lines, // startV | 879 kLineSegNumVertices*lines, // startV |
887 0, // startI | 880 0, // startI |
888 kLineSegNumVertices*n, // vCount | 881 kLineSegNumVertices*n, // vCount |
889 kIdxsPerLineSeg*n, // iCount | 882 kIdxsPerLineSeg*n, // iCount |
890 &devBounds); | 883 &devBounds); |
891 lines += n; | 884 lines += n; |
892 } | 885 } |
893 } | 886 } |
894 } | 887 } |
895 | 888 |
896 // then quadratics/conics | 889 // then quadratics/conics |
897 if (quadCnt || conicCnt) { | 890 if (quadCnt || conicCnt) { |
898 GrDrawTarget::AutoReleaseGeometry arg; | 891 GrDrawTarget::AutoReleaseGeometry arg; |
899 SkRect devBounds; | 892 SkRect devBounds; |
900 | 893 |
901 if (!this->createBezierGeom(path, | 894 if (!this->createBezierGeom(target, |
902 target, | 895 drawState, |
| 896 &arg, |
| 897 &devBounds, |
| 898 path, |
903 quads, | 899 quads, |
904 quadCnt, | 900 quadCnt, |
905 conics, | 901 conics, |
906 conicCnt, | 902 conicCnt, |
907 qSubdivs, | 903 qSubdivs, |
908 cWeights, | 904 cWeights)) { |
909 &arg, | |
910 &devBounds)) { | |
911 return false; | 905 return false; |
912 } | 906 } |
913 | 907 |
914 GrDrawTarget::AutoStateRestore asr; | |
915 | |
916 // createGeom transforms the geometry to device space when the matrix do
es not have | 908 // createGeom transforms the geometry to device space when the matrix do
es not have |
917 // perspective. | 909 // perspective. |
918 if (target->getDrawState().getViewMatrix().hasPerspective()) { | 910 GrDrawState::AutoViewMatrixRestore avmr; |
919 asr.set(target, GrDrawTarget::kPreserve_ASRInit); | 911 if (!drawState->getViewMatrix().hasPerspective() && !avmr.setIdentity(dr
awState)) { |
920 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { | |
921 return false; | 912 return false; |
922 } | 913 } |
923 GrDrawState* drawState = target->drawState(); | 914 |
924 | 915 |
925 // Check devBounds | 916 // Check devBounds |
926 SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices()
, | 917 SkASSERT(check_bounds<BezierVertex>(drawState, devBounds, arg.vertices()
, |
927 kQuadNumVertices * quadCnt + kQuadNu
mVertices * conicCnt)); | 918 kQuadNumVertices * quadCnt + kQuadNu
mVertices * conicCnt)); |
928 | 919 |
929 if (quadCnt > 0) { | 920 if (quadCnt > 0) { |
930 GrGeometryProcessor* hairQuadProcessor = | 921 GrGeometryProcessor* hairQuadProcessor = |
931 GrQuadEffect::Create(kHairlineAA_GrProcessorEdgeType, *targe
t->caps()); | 922 GrQuadEffect::Create(kHairlineAA_GrProcessorEdgeType, *targe
t->caps()); |
932 SkASSERT(hairQuadProcessor); | 923 SkASSERT(hairQuadProcessor); |
933 GrDrawState::AutoRestoreEffects are(drawState); | 924 GrDrawState::AutoRestoreEffects are(drawState); |
934 target->setIndexSourceToBuffer(fQuadsIndexBuffer); | 925 target->setIndexSourceToBuffer(fQuadsIndexBuffer); |
935 drawState->setGeometryProcessor(hairQuadProcessor)->unref(); | 926 drawState->setGeometryProcessor(hairQuadProcessor)->unref(); |
936 int quads = 0; | 927 int quads = 0; |
937 while (quads < quadCnt) { | 928 while (quads < quadCnt) { |
938 int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer); | 929 int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer); |
939 target->drawIndexed(kTriangles_GrPrimitiveType, | 930 target->drawIndexed(drawState, |
| 931 kTriangles_GrPrimitiveType, |
940 kQuadNumVertices*quads, // sta
rtV | 932 kQuadNumVertices*quads, // sta
rtV |
941 0, // sta
rtI | 933 0, // sta
rtI |
942 kQuadNumVertices*n, // vCo
unt | 934 kQuadNumVertices*n, // vCo
unt |
943 kIdxsPerQuad*n, // iCo
unt | 935 kIdxsPerQuad*n, // iCo
unt |
944 &devBounds); | 936 &devBounds); |
945 quads += n; | 937 quads += n; |
946 } | 938 } |
947 } | 939 } |
948 | 940 |
949 if (conicCnt > 0) { | 941 if (conicCnt > 0) { |
950 GrDrawState::AutoRestoreEffects are(drawState); | 942 GrDrawState::AutoRestoreEffects are(drawState); |
951 GrGeometryProcessor* hairConicProcessor = GrConicEffect::Create( | 943 GrGeometryProcessor* hairConicProcessor = GrConicEffect::Create( |
952 kHairlineAA_GrProcessorEdgeType, *target->caps()); | 944 kHairlineAA_GrProcessorEdgeType, *target->caps()); |
953 SkASSERT(hairConicProcessor); | 945 SkASSERT(hairConicProcessor); |
954 drawState->setGeometryProcessor(hairConicProcessor)->unref(); | 946 drawState->setGeometryProcessor(hairConicProcessor)->unref(); |
955 int conics = 0; | 947 int conics = 0; |
956 while (conics < conicCnt) { | 948 while (conics < conicCnt) { |
957 int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer); | 949 int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer); |
958 target->drawIndexed(kTriangles_GrPrimitiveType, | 950 target->drawIndexed(drawState, |
| 951 kTriangles_GrPrimitiveType, |
959 kQuadNumVertices*(quadCnt + conics), // sta
rtV | 952 kQuadNumVertices*(quadCnt + conics), // sta
rtV |
960 0, // sta
rtI | 953 0, // sta
rtI |
961 kQuadNumVertices*n, // vCo
unt | 954 kQuadNumVertices*n, // vCo
unt |
962 kIdxsPerQuad*n, // iCo
unt | 955 kIdxsPerQuad*n, // iCo
unt |
963 &devBounds); | 956 &devBounds); |
964 conics += n; | 957 conics += n; |
965 } | 958 } |
966 } | 959 } |
967 } | 960 } |
968 | 961 |
969 target->resetIndexSource(); | 962 target->resetIndexSource(); |
970 | 963 |
971 return true; | 964 return true; |
972 } | 965 } |
OLD | NEW |