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 "Test.h" | 8 #include "Test.h" |
9 #if SK_SUPPORT_GPU | |
10 #include "GrReducedClip.h" | |
11 #endif | |
12 #include "SkClipStack.h" | 9 #include "SkClipStack.h" |
13 #include "SkPath.h" | 10 #include "SkPath.h" |
14 #include "SkRandom.h" | 11 #include "SkRandom.h" |
15 #include "SkRect.h" | 12 #include "SkRect.h" |
16 #include "SkRegion.h" | 13 #include "SkRegion.h" |
17 | 14 |
| 15 #if SK_SUPPORT_GPU |
| 16 #include "GrReducedClip.h" |
| 17 typedef GrReducedClip::ElementList ElementList; |
| 18 typedef GrReducedClip::InitialState InitialState; |
| 19 #endif |
| 20 |
18 static void test_assign_and_comparison(skiatest::Reporter* reporter) { | 21 static void test_assign_and_comparison(skiatest::Reporter* reporter) { |
19 SkClipStack s; | 22 SkClipStack s; |
20 bool doAA = false; | 23 bool doAA = false; |
21 | 24 |
22 REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); | 25 REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); |
23 | 26 |
24 // Build up a clip stack with a path, an empty clip, and a rect. | 27 // Build up a clip stack with a path, an empty clip, and a rect. |
25 s.save(); | 28 s.save(); |
26 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); | 29 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); |
27 | 30 |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 800 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
798 | 801 |
799 #if SK_SUPPORT_GPU | 802 #if SK_SUPPORT_GPU |
800 // Functions that add a shape to the clip stack. The shape is computed from a re
ctangle. | 803 // Functions that add a shape to the clip stack. The shape is computed from a re
ctangle. |
801 // AA is always disabled since the clip stack reducer can cause changes in aa ra
sterization of the | 804 // AA is always disabled since the clip stack reducer can cause changes in aa ra
sterization of the |
802 // stack. A fractional edge repeated in different elements may be rasterized few
er times using the | 805 // stack. A fractional edge repeated in different elements may be rasterized few
er times using the |
803 // reduced stack. | 806 // reduced stack. |
804 typedef void (*AddElementFunc) (const SkRect& rect, | 807 typedef void (*AddElementFunc) (const SkRect& rect, |
805 bool invert, | 808 bool invert, |
806 SkRegion::Op op, | 809 SkRegion::Op op, |
807 SkClipStack* stack); | 810 SkClipStack* stack, |
| 811 bool doAA); |
808 | 812 |
809 static void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkC
lipStack* stack) { | 813 static void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkC
lipStack* stack, |
| 814 bool doAA) { |
810 SkScalar rx = rect.width() / 10; | 815 SkScalar rx = rect.width() / 10; |
811 SkScalar ry = rect.height() / 20; | 816 SkScalar ry = rect.height() / 20; |
812 if (invert) { | 817 if (invert) { |
813 SkPath path; | 818 SkPath path; |
814 path.addRoundRect(rect, rx, ry); | 819 path.addRoundRect(rect, rx, ry); |
815 path.setFillType(SkPath::kInverseWinding_FillType); | 820 path.setFillType(SkPath::kInverseWinding_FillType); |
816 stack->clipDevPath(path, op, false); | 821 stack->clipDevPath(path, op, doAA); |
817 } else { | 822 } else { |
818 SkRRect rrect; | 823 SkRRect rrect; |
819 rrect.setRectXY(rect, rx, ry); | 824 rrect.setRectXY(rect, rx, ry); |
820 stack->clipDevRRect(rrect, op, false); | 825 stack->clipDevRRect(rrect, op, doAA); |
821 } | 826 } |
822 }; | 827 }; |
823 | 828 |
824 static void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack) { | 829 static void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack, |
| 830 bool doAA) { |
825 if (invert) { | 831 if (invert) { |
826 SkPath path; | 832 SkPath path; |
827 path.addRect(rect); | 833 path.addRect(rect); |
828 path.setFillType(SkPath::kInverseWinding_FillType); | 834 path.setFillType(SkPath::kInverseWinding_FillType); |
829 stack->clipDevPath(path, op, false); | 835 stack->clipDevPath(path, op, doAA); |
830 } else { | 836 } else { |
831 stack->clipDevRect(rect, op, false); | 837 stack->clipDevRect(rect, op, doAA); |
832 } | 838 } |
833 }; | 839 }; |
834 | 840 |
835 static void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack) { | 841 static void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack, |
| 842 bool doAA) { |
836 SkPath path; | 843 SkPath path; |
837 path.addOval(rect); | 844 path.addOval(rect); |
838 if (invert) { | 845 if (invert) { |
839 path.setFillType(SkPath::kInverseWinding_FillType); | 846 path.setFillType(SkPath::kInverseWinding_FillType); |
840 } | 847 } |
841 stack->clipDevPath(path, op, false); | 848 stack->clipDevPath(path, op, doAA); |
842 }; | 849 }; |
843 | 850 |
844 static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack*
stack) { | 851 static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack*
stack) { |
845 switch (element.getType()) { | 852 switch (element.getType()) { |
846 case SkClipStack::Element::kRect_Type: | 853 case SkClipStack::Element::kRect_Type: |
847 stack->clipDevRect(element.getRect(), element.getOp(), element.isAA(
)); | 854 stack->clipDevRect(element.getRect(), element.getOp(), element.isAA(
)); |
848 break; | 855 break; |
849 case SkClipStack::Element::kRRect_Type: | 856 case SkClipStack::Element::kRRect_Type: |
850 stack->clipDevRRect(element.getRRect(), element.getOp(), element.isA
A()); | 857 stack->clipDevRRect(element.getRRect(), element.getOp(), element.isA
A()); |
851 break; | 858 break; |
(...skipping 27 matching lines...) Expand all Loading... |
879 } | 886 } |
880 | 887 |
881 static void test_reduced_clip_stack(skiatest::Reporter* reporter) { | 888 static void test_reduced_clip_stack(skiatest::Reporter* reporter) { |
882 // We construct random clip stacks, reduce them, and then rasterize both ver
sions to verify that | 889 // We construct random clip stacks, reduce them, and then rasterize both ver
sions to verify that |
883 // they are equal. | 890 // they are equal. |
884 | 891 |
885 // All the clip elements will be contained within these bounds. | 892 // All the clip elements will be contained within these bounds. |
886 static const SkRect kBounds = SkRect::MakeWH(100, 100); | 893 static const SkRect kBounds = SkRect::MakeWH(100, 100); |
887 | 894 |
888 enum { | 895 enum { |
889 kNumTests = 200, | 896 kNumTests = 250, |
890 kMinElemsPerTest = 1, | 897 kMinElemsPerTest = 1, |
891 kMaxElemsPerTest = 50, | 898 kMaxElemsPerTest = 50, |
892 }; | 899 }; |
893 | 900 |
894 // min/max size of a clip element as a fraction of kBounds. | 901 // min/max size of a clip element as a fraction of kBounds. |
895 static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5; | 902 static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5; |
896 static const SkScalar kMaxElemSizeFrac = SK_Scalar1; | 903 static const SkScalar kMaxElemSizeFrac = SK_Scalar1; |
897 | 904 |
898 static const SkRegion::Op kOps[] = { | 905 static const SkRegion::Op kOps[] = { |
899 SkRegion::kDifference_Op, | 906 SkRegion::kDifference_Op, |
900 SkRegion::kIntersect_Op, | 907 SkRegion::kIntersect_Op, |
901 SkRegion::kUnion_Op, | 908 SkRegion::kUnion_Op, |
902 SkRegion::kXOR_Op, | 909 SkRegion::kXOR_Op, |
903 SkRegion::kReverseDifference_Op, | 910 SkRegion::kReverseDifference_Op, |
904 SkRegion::kReplace_Op, | 911 SkRegion::kReplace_Op, |
905 }; | 912 }; |
906 | 913 |
907 // Replace operations short-circuit the optimizer. We want to make sure that
we test this code | 914 // Replace operations short-circuit the optimizer. We want to make sure that
we test this code |
908 // path a little bit but we don't want it to prevent us from testing many lo
nger traversals in | 915 // path a little bit but we don't want it to prevent us from testing many lo
nger traversals in |
909 // the optimizer. | 916 // the optimizer. |
910 static const int kReplaceDiv = 4 * kMaxElemsPerTest; | 917 static const int kReplaceDiv = 4 * kMaxElemsPerTest; |
911 | 918 |
912 // We want to test inverse fills. However, they are quite rare in practice s
o don't over do it. | 919 // We want to test inverse fills. However, they are quite rare in practice s
o don't over do it. |
913 static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest; | 920 static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest; |
914 | 921 |
| 922 static const SkScalar kFractionAntialiased = 0.25; |
| 923 |
915 static const AddElementFunc kElementFuncs[] = { | 924 static const AddElementFunc kElementFuncs[] = { |
916 add_rect, | 925 add_rect, |
917 add_round_rect, | 926 add_round_rect, |
918 add_oval, | 927 add_oval, |
919 }; | 928 }; |
920 | 929 |
921 SkRandom r; | 930 SkRandom r; |
922 | 931 |
923 for (int i = 0; i < kNumTests; ++i) { | 932 for (int i = 0; i < kNumTests; ++i) { |
| 933 SkString testCase; |
| 934 testCase.printf("Iteration %d", i); |
| 935 |
924 // Randomly generate a clip stack. | 936 // Randomly generate a clip stack. |
925 SkClipStack stack; | 937 SkClipStack stack; |
926 int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest); | 938 int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest); |
| 939 bool doAA = r.nextBiasedBool(kFractionAntialiased); |
927 for (int e = 0; e < numElems; ++e) { | 940 for (int e = 0; e < numElems; ++e) { |
928 SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))]; | 941 SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))]; |
929 if (op == SkRegion::kReplace_Op) { | 942 if (op == SkRegion::kReplace_Op) { |
930 if (r.nextU() % kReplaceDiv) { | 943 if (r.nextU() % kReplaceDiv) { |
931 --e; | 944 --e; |
932 continue; | 945 continue; |
933 } | 946 } |
934 } | 947 } |
935 | 948 |
936 // saves can change the clip stack behavior when an element is added
. | 949 // saves can change the clip stack behavior when an element is added
. |
937 bool doSave = r.nextBool(); | 950 bool doSave = r.nextBool(); |
938 | 951 |
939 SkSize size = SkSize::Make( | 952 SkSize size = SkSize::Make( |
940 SkScalarFloorToScalar(SkScalarMul(kBounds.width(), r.nextRangeSc
alar(kMinElemSizeFrac, kMaxElemSizeFrac))), | 953 SkScalarMul(kBounds.width(), r.nextRangeScalar(kMinElemSizeFrac,
kMaxElemSizeFrac)), |
941 SkScalarFloorToScalar(SkScalarMul(kBounds.height(), r.nextRangeS
calar(kMinElemSizeFrac, kMaxElemSizeFrac)))); | 954 SkScalarMul(kBounds.height(), r.nextRangeScalar(kMinElemSizeFrac
, kMaxElemSizeFrac))); |
942 | 955 |
943 SkPoint xy = {SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fLeft,
kBounds.fRight - size.fWidth)), | 956 SkPoint xy = {r.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size
.fWidth), |
944 SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fTop,
kBounds.fBottom - size.fHeight))}; | 957 r.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size
.fHeight)}; |
945 | 958 |
946 SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeig
ht); | 959 SkRect rect; |
| 960 if (doAA) { |
| 961 rect.setXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight); |
| 962 if (GrClip::IsPixelAligned(rect)) { |
| 963 // Don't create an element that may accidentally become not
antialiased. |
| 964 rect.outset(0.5f, 0.5f); |
| 965 } |
| 966 SkASSERT(!GrClip::IsPixelAligned(rect)); |
| 967 } else { |
| 968 rect.setXYWH(SkScalarFloorToScalar(xy.fX), |
| 969 SkScalarFloorToScalar(xy.fY), |
| 970 SkScalarCeilToScalar(size.fWidth), |
| 971 SkScalarCeilToScalar(size.fHeight)); |
| 972 } |
947 | 973 |
948 bool invert = r.nextBiasedBool(kFractionInverted); | 974 bool invert = r.nextBiasedBool(kFractionInverted); |
949 | 975 |
950 kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect,
invert, op, &stack); | 976 kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect,
invert, op, &stack, |
| 977 doAA); |
951 if (doSave) { | 978 if (doSave) { |
952 stack.save(); | 979 stack.save(); |
953 } | 980 } |
954 } | 981 } |
955 | 982 |
956 SkRect inflatedBounds = kBounds; | 983 SkRect queryBounds = kBounds; |
957 inflatedBounds.outset(kBounds.width() / 2, kBounds.height() / 2); | 984 queryBounds.outset(kBounds.width() / 2, kBounds.height() / 2); |
958 SkIRect inflatedIBounds; | |
959 inflatedBounds.roundOut(&inflatedIBounds); | |
960 | 985 |
961 typedef GrReducedClip::ElementList ElementList; | |
962 // Get the reduced version of the stack. | 986 // Get the reduced version of the stack. |
963 ElementList reducedClips; | 987 ElementList reducedClips; |
964 int32_t reducedGenID; | 988 int32_t reducedGenID; |
965 GrReducedClip::InitialState initial; | 989 SkIRect clipIBounds; |
966 SkIRect tighterBounds; | |
967 bool requiresAA; | 990 bool requiresAA; |
968 GrReducedClip::ReduceClipStack(stack, | 991 InitialState initial = GrReducedClip::ReduceClipStack(stack, |
969 inflatedIBounds, | 992 queryBounds, |
970 &reducedClips, | 993 &reducedClips, |
971 &reducedGenID, | 994 &reducedGenID, |
972 &initial, | 995 &clipIBounds, |
973 &tighterBounds, | 996 &requiresAA); |
974 &requiresAA); | |
975 | 997 |
976 REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reducedGenID); | 998 REPORTER_ASSERT_MESSAGE(reporter, SkClipStack::kInvalidGenID != reducedG
enID, |
| 999 testCase.c_str()); |
| 1000 |
| 1001 if (!reducedClips.isEmpty()) { |
| 1002 SkRect stackBounds; |
| 1003 SkClipStack::BoundsType stackBoundsType; |
| 1004 stack.getBounds(&stackBounds, &stackBoundsType); |
| 1005 if (SkClipStack::kNormal_BoundsType == stackBoundsType) { |
| 1006 // Unless GrReducedClip starts doing some heroic tightening of t
he clip bounds, this |
| 1007 // will be true since the stack bounds are completely contained
inside the query. |
| 1008 REPORTER_ASSERT_MESSAGE(reporter, GrClip::IsInsideClip(clipIBoun
ds, stackBounds), |
| 1009 testCase.c_str()); |
| 1010 } |
| 1011 REPORTER_ASSERT_MESSAGE(reporter, requiresAA == doAA, testCase.c_str
()); |
| 1012 } |
977 | 1013 |
978 // Build a new clip stack based on the reduced clip elements | 1014 // Build a new clip stack based on the reduced clip elements |
979 SkClipStack reducedStack; | 1015 SkClipStack reducedStack; |
980 if (GrReducedClip::kAllOut_InitialState == initial) { | 1016 if (GrReducedClip::kAllOut_InitialState == initial) { |
981 // whether the result is bounded or not, the whole plane should star
t outside the clip. | 1017 // whether the result is bounded or not, the whole plane should star
t outside the clip. |
982 reducedStack.clipEmpty(); | 1018 reducedStack.clipEmpty(); |
983 } | 1019 } |
984 for (ElementList::Iter iter = reducedClips.headIter(); iter.get(); iter.
next()) { | 1020 for (ElementList::Iter iter = reducedClips.headIter(); iter.get(); iter.
next()) { |
985 add_elem_to_stack(*iter.get(), &reducedStack); | 1021 add_elem_to_stack(*iter.get(), &reducedStack); |
986 } | 1022 } |
987 | 1023 |
988 // GrReducedClipStack assumes that the final result is clipped to the re
turned bounds | 1024 // GrReducedClipStack assumes that the final result is clipped to the re
turned bounds |
989 reducedStack.clipDevRect(tighterBounds, SkRegion::kIntersect_Op); | 1025 reducedStack.clipDevRect(clipIBounds, SkRegion::kIntersect_Op); |
990 stack.clipDevRect(tighterBounds, SkRegion::kIntersect_Op); | 1026 stack.clipDevRect(clipIBounds, SkRegion::kIntersect_Op); |
991 | 1027 |
992 // convert both the original stack and reduced stack to SkRegions and se
e if they're equal | 1028 // convert both the original stack and reduced stack to SkRegions and se
e if they're equal |
993 SkRegion region; | 1029 SkRegion region; |
994 SkRegion reducedRegion; | 1030 SkRegion reducedRegion; |
995 | 1031 |
996 region.setRect(inflatedIBounds); | 1032 region.setRect(clipIBounds); |
997 const SkClipStack::Element* element; | 1033 const SkClipStack::Element* element; |
998 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); | 1034 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); |
999 while ((element = iter.next())) { | 1035 while ((element = iter.next())) { |
1000 add_elem_to_region(*element, inflatedIBounds, ®ion); | 1036 add_elem_to_region(*element, clipIBounds, ®ion); |
1001 } | 1037 } |
1002 | 1038 |
1003 reducedRegion.setRect(inflatedIBounds); | 1039 reducedRegion.setRect(clipIBounds); |
1004 iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart); | 1040 iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart); |
1005 while ((element = iter.next())) { | 1041 while ((element = iter.next())) { |
1006 add_elem_to_region(*element, inflatedIBounds, &reducedRegion); | 1042 add_elem_to_region(*element, clipIBounds, &reducedRegion); |
1007 } | 1043 } |
1008 SkString testCase; | |
1009 testCase.printf("Iteration %d", i); | |
1010 REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_st
r()); | 1044 REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_st
r()); |
1011 } | 1045 } |
1012 } | 1046 } |
1013 | 1047 |
1014 #ifdef SK_BUILD_FOR_WIN | 1048 #ifdef SK_BUILD_FOR_WIN |
1015 #define SUPPRESS_VISIBILITY_WARNING | 1049 #define SUPPRESS_VISIBILITY_WARNING |
1016 #else | 1050 #else |
1017 #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden"))) | 1051 #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden"))) |
1018 #endif | 1052 #endif |
1019 | 1053 |
1020 static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { | 1054 static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { |
1021 { | 1055 { |
1022 SkClipStack stack; | 1056 SkClipStack stack; |
1023 stack.clipDevRect(SkRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_O
p, true); | 1057 stack.clipDevRect(SkRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_O
p, true); |
1024 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3))
, SkRegion::kReplace_Op, true); | 1058 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3))
, SkRegion::kReplace_Op, true); |
1025 SkIRect inflatedIBounds = SkIRect::MakeXYWH(0, 0, 100, 100); | 1059 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); |
1026 | 1060 |
1027 GrReducedClip::ElementList reducedClips; | 1061 ElementList reducedClips; |
1028 int32_t reducedGenID; | 1062 int32_t reducedGenID; |
1029 GrReducedClip::InitialState initial; | |
1030 SkIRect tightBounds; | 1063 SkIRect tightBounds; |
1031 bool requiresAA; | 1064 bool requiresAA; |
1032 | 1065 |
1033 GrReducedClip::ReduceClipStack(stack, | 1066 GrReducedClip::ReduceClipStack(stack, |
1034 inflatedIBounds, | 1067 bounds, |
1035 &reducedClips, | 1068 &reducedClips, |
1036 &reducedGenID, | 1069 &reducedGenID, |
1037 &initial, | |
1038 &tightBounds, | 1070 &tightBounds, |
1039 &requiresAA); | 1071 &requiresAA); |
1040 | 1072 |
1041 REPORTER_ASSERT(reporter, reducedClips.count() == 1); | 1073 REPORTER_ASSERT(reporter, reducedClips.count() == 1); |
1042 // Clips will be cached based on the generation id. Make sure the gen id
is valid. | 1074 // Clips will be cached based on the generation id. Make sure the gen id
is valid. |
1043 REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reducedGenID); | 1075 REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reducedGenID); |
1044 } | 1076 } |
1045 { | 1077 { |
1046 SkClipStack stack; | 1078 SkClipStack stack; |
1047 | 1079 |
1048 // Create a clip with following 25.3, 25.3 boxes which are 25 apart: | 1080 // Create a clip with following 25.3, 25.3 boxes which are 25 apart: |
1049 // A B | 1081 // A B |
1050 // C D | 1082 // C D |
1051 | 1083 |
1052 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3))
, SkRegion::kReplace_Op, true); | 1084 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3))
, SkRegion::kReplace_Op, true); |
1053 int32_t genIDA = stack.getTopmostGenID(); | 1085 int32_t genIDA = stack.getTopmostGenID(); |
1054 stack.clipDevRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); | 1086 stack.clipDevRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); |
1055 int32_t genIDB = stack.getTopmostGenID(); | 1087 int32_t genIDB = stack.getTopmostGenID(); |
1056 stack.clipDevRect(SkRect::MakeXYWH(0, 50, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); | 1088 stack.clipDevRect(SkRect::MakeXYWH(0, 50, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); |
1057 int32_t genIDC = stack.getTopmostGenID(); | 1089 int32_t genIDC = stack.getTopmostGenID(); |
1058 stack.clipDevRect(SkRect::MakeXYWH(50, 50, SkScalar(25.3), SkScalar(25.3
)), SkRegion::kUnion_Op, true); | 1090 stack.clipDevRect(SkRect::MakeXYWH(50, 50, SkScalar(25.3), SkScalar(25.3
)), SkRegion::kUnion_Op, true); |
1059 int32_t genIDD = stack.getTopmostGenID(); | 1091 int32_t genIDD = stack.getTopmostGenID(); |
1060 | 1092 |
1061 | 1093 |
1062 #define XYWH SkIRect::MakeXYWH | 1094 #define IXYWH SkIRect::MakeXYWH |
| 1095 #define XYWH SkRect::MakeXYWH |
1063 | 1096 |
1064 SkIRect stackBounds = XYWH(0, 0, 76, 76); | 1097 SkIRect stackBounds = IXYWH(0, 0, 76, 76); |
1065 | 1098 |
1066 // The base test is to test each rect in two ways: | 1099 // The base test is to test each rect in two ways: |
1067 // 1) The box dimensions. (Should reduce to "all in", no elements). | 1100 // 1) The box dimensions. (Should reduce to "all in", no elements). |
1068 // 2) A bit over the box dimensions. | 1101 // 2) A bit over the box dimensions. |
1069 // In the case 2, test that the generation id is what is expected. | 1102 // In the case 2, test that the generation id is what is expected. |
1070 // The rects are of fractional size so that case 2 never gets optimized
to an empty element | 1103 // The rects are of fractional size so that case 2 never gets optimized
to an empty element |
1071 // list. | 1104 // list. |
1072 | 1105 |
1073 // Not passing in tighter bounds is tested for consistency. | 1106 // Not passing in tighter bounds is tested for consistency. |
1074 static const struct SUPPRESS_VISIBILITY_WARNING { | 1107 static const struct SUPPRESS_VISIBILITY_WARNING { |
1075 SkIRect testBounds; | 1108 SkRect testBounds; |
1076 int reducedClipCount; | 1109 int reducedClipCount; |
1077 int32_t reducedGenID; | 1110 int32_t reducedGenID; |
1078 GrReducedClip::InitialState initialState; | 1111 InitialState initialState; |
1079 SkIRect tighterBounds; // If this is empty, the query will not pass
tighter bounds | 1112 SkIRect clipIRect; |
1080 // parameter. | 1113 // parameter. |
1081 } testCases[] = { | 1114 } testCases[] = { |
1082 // Rect A. | 1115 // Rect A. |
1083 { XYWH(0, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip:
:kAllIn_InitialState, XYWH(0, 0, 25, 25) }, | 1116 { XYWH(0, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip:
:kAllIn_InitialState, IXYWH(0, 0, 25, 25) }, |
1084 { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::kAllOut_InitialState
, XYWH(0, 0, 27, 27)}, | 1117 { XYWH(0.1, 0.1, 25.1, 25.1), 0, SkClipStack::kWideOpenGenID, GrRedu
cedClip::kAllIn_InitialState, IXYWH(0, 0, 26, 26) }, |
| 1118 { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::kAllOut_InitialState
, IXYWH(0, 0, 27, 27)}, |
1085 | 1119 |
1086 // Rect B. | 1120 // Rect B. |
1087 { XYWH(50, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip
::kAllIn_InitialState, XYWH(50, 0, 25, 25) }, | 1121 { XYWH(50, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip
::kAllIn_InitialState, IXYWH(50, 0, 25, 25) }, |
1088 { XYWH(50, 0, 27, 27), 1, genIDB, GrReducedClip::kAllOut_InitialStat
e, XYWH(50, 0, 26, 27) }, | 1122 { XYWH(50, 0, 25.3, 25.3), 0, SkClipStack::kWideOpenGenID, GrReduced
Clip::kAllIn_InitialState, IXYWH(50, 0, 26, 26) }, |
| 1123 { XYWH(50, 0, 27, 27), 1, genIDB, GrReducedClip::kAllOut_InitialStat
e, IXYWH(50, 0, 26, 27) }, |
1089 | 1124 |
1090 // Rect C. | 1125 // Rect C. |
1091 { XYWH(0, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip
::kAllIn_InitialState, XYWH(0, 50, 25, 25) }, | 1126 { XYWH(0, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip
::kAllIn_InitialState, IXYWH(0, 50, 25, 25) }, |
1092 { XYWH(0, 50, 27, 27), 1, genIDC, GrReducedClip::kAllOut_InitialStat
e, XYWH(0, 50, 27, 26) }, | 1127 { XYWH(0.2, 50.1, 25.1, 25.2), 0, SkClipStack::kWideOpenGenID, GrRed
ucedClip::kAllIn_InitialState, IXYWH(0, 50, 26, 26) }, |
| 1128 { XYWH(0, 50, 27, 27), 1, genIDC, GrReducedClip::kAllOut_InitialStat
e, IXYWH(0, 50, 27, 26) }, |
1093 | 1129 |
1094 // Rect D. | 1130 // Rect D. |
1095 { XYWH(50, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedCli
p::kAllIn_InitialState, XYWH(50, 50, 25, 25)}, | 1131 { XYWH(50, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedCli
p::kAllIn_InitialState, IXYWH(50, 50, 25, 25)}, |
1096 { XYWH(50, 50, 27, 27), 1, genIDD, GrReducedClip::kAllOut_InitialSta
te, XYWH(50, 50, 26, 26)}, | 1132 { XYWH(50.3, 50.3, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReduce
dClip::kAllIn_InitialState, IXYWH(50, 50, 26, 26)}, |
| 1133 { XYWH(50, 50, 27, 27), 1, genIDD, GrReducedClip::kAllOut_InitialSta
te, IXYWH(50, 50, 26, 26)}, |
1097 | 1134 |
1098 // Other tests: | 1135 // Other tests: |
1099 { XYWH(0, 0, 100, 100), 4, genIDD, GrReducedClip::kAllOut_InitialSta
te, stackBounds }, | 1136 { XYWH(0, 0, 100, 100), 4, genIDD, GrReducedClip::kAllOut_InitialSta
te, stackBounds }, |
1100 | 1137 |
1101 // Rect in the middle, touches none. | 1138 // Rect in the middle, touches none. |
1102 { XYWH(26, 26, 24, 24), 0, SkClipStack::kEmptyGenID, GrReducedClip::
kAllOut_InitialState, XYWH(26, 26, 24, 24) }, | 1139 { XYWH(26, 26, 24, 24), 0, SkClipStack::kEmptyGenID, GrReducedClip::
kAllOut_InitialState, IXYWH(26, 26, 24, 24) }, |
1103 | 1140 |
1104 // Rect in the middle, touches all the rects. GenID is the last rect
. | 1141 // Rect in the middle, touches all the rects. GenID is the last rect
. |
1105 { XYWH(24, 24, 27, 27), 4, genIDD, GrReducedClip::kAllOut_InitialSta
te, XYWH(24, 24, 27, 27) }, | 1142 { XYWH(24, 24, 27, 27), 4, genIDD, GrReducedClip::kAllOut_InitialSta
te, IXYWH(24, 24, 27, 27) }, |
1106 }; | 1143 }; |
1107 | 1144 |
1108 #undef XYWH | 1145 #undef XYWH |
| 1146 #undef IXYWH |
1109 | 1147 |
1110 for (size_t i = 0; i < SK_ARRAY_COUNT(testCases); ++i) { | 1148 for (size_t i = 0; i < SK_ARRAY_COUNT(testCases); ++i) { |
1111 GrReducedClip::ElementList reducedClips; | 1149 ElementList reducedClips; |
1112 int32_t reducedGenID; | 1150 int32_t reducedGenID; |
1113 GrReducedClip::InitialState initial; | 1151 SkIRect clipIRect; |
1114 SkIRect tightBounds; | |
1115 bool requiresAA; | 1152 bool requiresAA; |
1116 | 1153 |
1117 GrReducedClip::ReduceClipStack(stack, | 1154 InitialState initial = GrReducedClip::ReduceClipStack(stack, |
1118 testCases[i].testBounds, | 1155 testCases[i].t
estBounds, |
1119 &reducedClips, | 1156 &reducedClips, |
1120 &reducedGenID, | 1157 &reducedGenID, |
1121 &initial, | 1158 &clipIRect, |
1122 &tightBounds, | 1159 &requiresAA); |
1123 &requiresAA); | |
1124 | 1160 |
1125 REPORTER_ASSERT(reporter, reducedClips.count() == testCases[i].reduc
edClipCount); | 1161 REPORTER_ASSERT(reporter, reducedClips.count() == testCases[i].reduc
edClipCount); |
1126 SkASSERT(reducedClips.count() == testCases[i].reducedClipCount); | 1162 SkASSERT(reducedClips.count() == testCases[i].reducedClipCount); |
1127 REPORTER_ASSERT(reporter, reducedGenID == testCases[i].reducedGenID)
; | 1163 REPORTER_ASSERT(reporter, reducedGenID == testCases[i].reducedGenID)
; |
1128 SkASSERT(reducedGenID == testCases[i].reducedGenID); | 1164 SkASSERT(reducedGenID == testCases[i].reducedGenID); |
1129 REPORTER_ASSERT(reporter, initial == testCases[i].initialState); | 1165 REPORTER_ASSERT(reporter, initial == testCases[i].initialState); |
1130 SkASSERT(initial == testCases[i].initialState); | 1166 SkASSERT(initial == testCases[i].initialState); |
1131 REPORTER_ASSERT(reporter, tightBounds == testCases[i].tighterBounds)
; | 1167 REPORTER_ASSERT(reporter, clipIRect == testCases[i].clipIRect); |
1132 SkASSERT(tightBounds == testCases[i].tighterBounds); | 1168 SkASSERT(clipIRect == testCases[i].clipIRect); |
1133 } | 1169 } |
1134 } | 1170 } |
1135 } | 1171 } |
1136 | 1172 |
1137 static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) { | 1173 static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) { |
1138 SkClipStack stack; | 1174 SkClipStack stack; |
1139 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_Op); | 1175 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_Op); |
1140 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkRegion::kReplace_Op); | 1176 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkRegion::kReplace_Op); |
1141 SkIRect inflatedIBounds = SkIRect::MakeXYWH(0, 0, 100, 100); | 1177 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); |
1142 | 1178 |
1143 GrReducedClip::ElementList reducedClips; | 1179 ElementList reducedClips; |
1144 int32_t reducedGenID; | 1180 int32_t reducedGenID; |
1145 GrReducedClip::InitialState initial; | |
1146 SkIRect tightBounds; | 1181 SkIRect tightBounds; |
1147 bool requiresAA; | 1182 bool requiresAA; |
1148 | 1183 |
1149 // At the time, this would crash. | 1184 // At the time, this would crash. |
1150 GrReducedClip::ReduceClipStack(stack, | 1185 GrReducedClip::ReduceClipStack(stack, |
1151 inflatedIBounds, | 1186 bounds, |
1152 &reducedClips, | 1187 &reducedClips, |
1153 &reducedGenID, | 1188 &reducedGenID, |
1154 &initial, | |
1155 &tightBounds, | 1189 &tightBounds, |
1156 &requiresAA); | 1190 &requiresAA); |
1157 | 1191 |
1158 REPORTER_ASSERT(reporter, 0 == reducedClips.count()); | 1192 REPORTER_ASSERT(reporter, 0 == reducedClips.count()); |
1159 } | 1193 } |
1160 | 1194 |
| 1195 enum class ClipMethod { |
| 1196 kSkipDraw, |
| 1197 kIgnoreClip, |
| 1198 kScissor, |
| 1199 kAAElements |
| 1200 }; |
| 1201 |
| 1202 static void test_aa_query(skiatest::Reporter* reporter, const SkString& testName
, |
| 1203 const SkClipStack& stack, const SkMatrix& queryXform, |
| 1204 const SkRect& preXformQuery, ClipMethod expectedMethod
, |
| 1205 int numExpectedElems = 0) { |
| 1206 ElementList reducedElems; |
| 1207 int32_t reducedGenID; |
| 1208 SkIRect clipIBounds; |
| 1209 bool requiresAA; |
| 1210 |
| 1211 SkRect queryBounds; |
| 1212 queryXform.mapRect(&queryBounds, preXformQuery); |
| 1213 |
| 1214 InitialState initialState = GrReducedClip::ReduceClipStack(stack, |
| 1215 queryBounds, |
| 1216 &reducedElems, |
| 1217 &reducedGenID, |
| 1218 &clipIBounds, |
| 1219 &requiresAA); |
| 1220 |
| 1221 SkClipStack::BoundsType stackBoundsType; |
| 1222 SkRect stackBounds; |
| 1223 stack.getBounds(&stackBounds, &stackBoundsType); |
| 1224 |
| 1225 switch (expectedMethod) { |
| 1226 case ClipMethod::kSkipDraw: |
| 1227 SkASSERT(0 == numExpectedElems); |
| 1228 REPORTER_ASSERT_MESSAGE(reporter, reducedElems.isEmpty(), testName.c
_str()); |
| 1229 REPORTER_ASSERT_MESSAGE(reporter, GrReducedClip::kAllOut_InitialStat
e == initialState, |
| 1230 testName.c_str()); |
| 1231 return; |
| 1232 case ClipMethod::kIgnoreClip: |
| 1233 SkASSERT(0 == numExpectedElems); |
| 1234 REPORTER_ASSERT_MESSAGE(reporter, reducedElems.isEmpty(), testName.c
_str()); |
| 1235 REPORTER_ASSERT_MESSAGE(reporter, GrClip::IsInsideClip(clipIBounds,
queryBounds), |
| 1236 testName.c_str()); |
| 1237 REPORTER_ASSERT_MESSAGE(reporter, GrReducedClip::kAllIn_InitialState
== initialState, |
| 1238 testName.c_str()); |
| 1239 return; |
| 1240 case ClipMethod::kScissor: { |
| 1241 SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType); |
| 1242 SkASSERT(0 == numExpectedElems); |
| 1243 SkIRect expectedScissor; |
| 1244 stackBounds.round(&expectedScissor); |
| 1245 REPORTER_ASSERT_MESSAGE(reporter, reducedElems.isEmpty(), testName.c
_str()); |
| 1246 REPORTER_ASSERT_MESSAGE(reporter, expectedScissor == clipIBounds, te
stName.c_str()); |
| 1247 REPORTER_ASSERT_MESSAGE(reporter, GrReducedClip::kAllIn_InitialState
== initialState, |
| 1248 testName.c_str()); |
| 1249 return; |
| 1250 } |
| 1251 case ClipMethod::kAAElements: { |
| 1252 SkIRect expectedClipIBounds = GrClip::GetPixelIBounds(queryBounds); |
| 1253 if (SkClipStack::kNormal_BoundsType == stackBoundsType) { |
| 1254 SkAssertResult(expectedClipIBounds.intersect(GrClip::GetPixelIBo
unds(stackBounds))); |
| 1255 } |
| 1256 REPORTER_ASSERT_MESSAGE(reporter, numExpectedElems == reducedElems.c
ount(), |
| 1257 testName.c_str()); |
| 1258 REPORTER_ASSERT_MESSAGE(reporter, expectedClipIBounds == clipIBounds
, testName.c_str()); |
| 1259 REPORTER_ASSERT_MESSAGE(reporter, requiresAA, testName.c_str()); |
| 1260 break; |
| 1261 } |
| 1262 } |
| 1263 } |
| 1264 |
| 1265 static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) { |
| 1266 constexpr SkScalar IL = 2, IT = 1, IR = 6, IB = 7; // Pixel aligned rect
. |
| 1267 constexpr SkScalar L = 2.2, T = 1.7, R = 5.8, B = 7.3; // Generic rect. |
| 1268 constexpr SkScalar l = 3.3, t = 2.8, r = 4.7, b = 6.2; // Small rect contain
ed in R. |
| 1269 |
| 1270 SkRect alignedRect = {IL, IT, IR, IB}; |
| 1271 SkRect rect = {L, T, R, B}; |
| 1272 SkRect innerRect = {l, t, r, b}; |
| 1273 |
| 1274 SkMatrix m; |
| 1275 m.setIdentity(); |
| 1276 |
| 1277 constexpr SkScalar kMinScale = 2.0001; |
| 1278 constexpr SkScalar kMaxScale = 3; |
| 1279 constexpr int kNumIters = 8; |
| 1280 |
| 1281 SkString name; |
| 1282 SkRandom rand; |
| 1283 |
| 1284 for (int i = 0; i < kNumIters; ++i) { |
| 1285 // Pixel-aligned rect (iior=true). |
| 1286 name.printf("Pixel-aligned rect test, iter %i", i); |
| 1287 SkClipStack stack; |
| 1288 stack.clipDevRect(alignedRect, SkRegion::kIntersect_Op, true); |
| 1289 test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kI
gnoreClip); |
| 1290 test_aa_query(reporter, name, stack, m, {IL, IT-1, IR, IT}, ClipMethod::
kSkipDraw); |
| 1291 test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kS
cissor); |
| 1292 test_aa_query(reporter, name, stack, m, {IL, IT+2, IR, IB-3}, ClipMethod
::kScissor); |
| 1293 |
| 1294 // Rect (iior=true). |
| 1295 name.printf("Rect test, iter %i", i); |
| 1296 stack.reset(); |
| 1297 stack.clipDevRect(rect, SkRegion::kIntersect_Op, true); |
| 1298 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kIgno
reClip); |
| 1299 test_aa_query(reporter, name, stack, m, {L-.1, T, L, B}, ClipMethod::kSk
ipDraw); |
| 1300 test_aa_query(reporter, name, stack, m, {L-.1, T, L+.1, B}, ClipMethod::
kAAElements, 1); |
| 1301 |
| 1302 // Difference rect (iior=false, inside-out bounds). |
| 1303 name.printf("Difference rect test, iter %i", i); |
| 1304 stack.reset(); |
| 1305 stack.clipDevRect(rect, SkRegion::kDifference_Op, true); |
| 1306 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kSkipD
raw); |
| 1307 test_aa_query(reporter, name, stack, m, {L, T-.1, R, T}, ClipMethod::kIg
noreClip); |
| 1308 test_aa_query(reporter, name, stack, m, {L, T-.1, R, T+.1}, ClipMethod::
kAAElements, 1); |
| 1309 |
| 1310 // Complex clip (iior=false, normal bounds). |
| 1311 name.printf("Complex clip test, iter %i", i); |
| 1312 stack.reset(); |
| 1313 stack.clipDevRect(rect, SkRegion::kIntersect_Op, true); |
| 1314 stack.clipDevRect(innerRect, SkRegion::kXOR_Op, true); |
| 1315 test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipD
raw); |
| 1316 test_aa_query(reporter, name, stack, m, {r-.1, t, R, b}, ClipMethod::kAA
Elements, 1); |
| 1317 test_aa_query(reporter, name, stack, m, {r-.1, t, R+.1, b}, ClipMethod::
kAAElements, 2); |
| 1318 test_aa_query(reporter, name, stack, m, {r, t, R+.1, b}, ClipMethod::kAA
Elements, 1); |
| 1319 test_aa_query(reporter, name, stack, m, {r, t, R, b}, ClipMethod::kIgnor
eClip); |
| 1320 test_aa_query(reporter, name, stack, m, {R, T, R+.1, B}, ClipMethod::kSk
ipDraw); |
| 1321 |
| 1322 // TODO: Complex clip where outer rect is pixel aligned? Could be optimi
zed to use scissor. |
| 1323 |
| 1324 // Apply random transforms and try again. This ensures the clip stack re
duction is hardened |
| 1325 // against FP rounding error. |
| 1326 SkScalar sx = rand.nextRangeScalar(kMinScale, kMaxScale); |
| 1327 sx = SkScalarFloorToScalar(sx * alignedRect.width()) / alignedRect.width
(); |
| 1328 SkScalar sy = rand.nextRangeScalar(kMinScale, kMaxScale); |
| 1329 sy = SkScalarFloorToScalar(sy * alignedRect.height()) / alignedRect.heig
ht(); |
| 1330 SkScalar tx = SkScalarRoundToScalar(sx * alignedRect.x()) - sx * aligned
Rect.x(); |
| 1331 SkScalar ty = SkScalarRoundToScalar(sy * alignedRect.y()) - sy * aligned
Rect.y(); |
| 1332 |
| 1333 SkMatrix xform = SkMatrix::MakeScale(sx, sy); |
| 1334 xform.postTranslate(tx, ty); |
| 1335 xform.mapRect(&alignedRect); |
| 1336 xform.mapRect(&rect); |
| 1337 xform.mapRect(&innerRect); |
| 1338 m.postConcat(xform); |
| 1339 } |
| 1340 } |
| 1341 |
1161 #endif | 1342 #endif |
1162 | 1343 |
1163 DEF_TEST(ClipStack, reporter) { | 1344 DEF_TEST(ClipStack, reporter) { |
1164 SkClipStack stack; | 1345 SkClipStack stack; |
1165 | 1346 |
1166 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); | 1347 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); |
1167 assert_count(reporter, stack, 0); | 1348 assert_count(reporter, stack, 0); |
1168 | 1349 |
1169 static const SkIRect gRects[] = { | 1350 static const SkIRect gRects[] = { |
1170 { 0, 0, 100, 100 }, | 1351 { 0, 0, 100, 100 }, |
(...skipping 30 matching lines...) Expand all Loading... |
1201 test_isWideOpen(reporter); | 1382 test_isWideOpen(reporter); |
1202 test_rect_merging(reporter); | 1383 test_rect_merging(reporter); |
1203 test_rect_replace(reporter); | 1384 test_rect_replace(reporter); |
1204 test_rect_inverse_fill(reporter); | 1385 test_rect_inverse_fill(reporter); |
1205 test_path_replace(reporter); | 1386 test_path_replace(reporter); |
1206 test_quickContains(reporter); | 1387 test_quickContains(reporter); |
1207 #if SK_SUPPORT_GPU | 1388 #if SK_SUPPORT_GPU |
1208 test_reduced_clip_stack(reporter); | 1389 test_reduced_clip_stack(reporter); |
1209 test_reduced_clip_stack_genid(reporter); | 1390 test_reduced_clip_stack_genid(reporter); |
1210 test_reduced_clip_stack_no_aa_crash(reporter); | 1391 test_reduced_clip_stack_no_aa_crash(reporter); |
| 1392 test_reduced_clip_stack_aa(reporter); |
1211 #endif | 1393 #endif |
1212 } | 1394 } |
OLD | NEW |