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

Side by Side Diff: tests/ClipStackTest.cpp

Issue 2160093002: Allow GrReducedClip to take non-integer query bounds (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Allow GrReducedClip to take non-integer query bounds Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/utils/SkLua.cpp ('K') | « src/utils/SkLua.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "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
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
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, &region); 1036 add_elem_to_region(*element, clipIBounds, &region);
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
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 }
OLDNEW
« src/utils/SkLua.cpp ('K') | « src/utils/SkLua.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698