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