blob: a4d9b1fedd52f728aa45556f34f42f77764ed5c9 [file] [log] [blame]
cdalton6819df32014-10-15 13:43:48 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
bsalomon77d77f42014-11-21 14:38:06 -08008#include "SkMatrix.h"
9#include "SkRandom.h"
10#include "SkString.h"
cdalton6819df32014-10-15 13:43:48 -070011#include "Test.h"
12
cdalton72badbd2015-04-16 10:42:49 -070013#include "GrTRecorder.h"
14
cdalton6819df32014-10-15 13:43:48 -070015////////////////////////////////////////////////////////////////////////////////
16
17static int activeRecorderItems = 0;
18
19class IntWrapper {
20public:
21 IntWrapper() {}
22 IntWrapper(int value) : fValue(value) {}
23 operator int() { return fValue; }
24private:
25 int fValue;
26};
27
bsalomon77d77f42014-11-21 14:38:06 -080028static void test_empty_back_and_pop(skiatest::Reporter* reporter) {
29 SkRandom rand;
30 for (int data = 0; data < 2; ++data) {
31 // Do this with different starting sizes to have different alignment between blocks and pops.
32 // pops. We want to test poping the first guy off, guys in the middle of the block, and the
33 // first guy on a non-head block.
34 for (int j = 0; j < 8; ++j) {
35 GrTRecorder<IntWrapper, int> recorder(j);
cdalton6819df32014-10-15 13:43:48 -070036
bsalomon77d77f42014-11-21 14:38:06 -080037 REPORTER_ASSERT(reporter, recorder.empty());
cdalton6819df32014-10-15 13:43:48 -070038
bsalomon77d77f42014-11-21 14:38:06 -080039 for (int i = 0; i < 100; ++i) {
40 if (data) {
halcanary9d524f22016-03-29 09:03:52 -070041 REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder,
bsalomon77d77f42014-11-21 14:38:06 -080042 IntWrapper, (i)));
43 } else {
44 REPORTER_ASSERT(reporter, i ==
45 *GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder,
46 IntWrapper, (i),
47 rand.nextULessThan(10)));
48 }
49 REPORTER_ASSERT(reporter, !recorder.empty());
50 REPORTER_ASSERT(reporter, i == recorder.back());
51 if (0 == (i % 7)) {
52 recorder.pop_back();
53 if (i > 0) {
54 REPORTER_ASSERT(reporter, !recorder.empty());
55 REPORTER_ASSERT(reporter, i-1 == recorder.back());
56 }
57 }
58 }
59
60 REPORTER_ASSERT(reporter, !recorder.empty());
61 recorder.reset();
62 REPORTER_ASSERT(reporter, recorder.empty());
63 }
cdalton6819df32014-10-15 13:43:48 -070064 }
cdalton6819df32014-10-15 13:43:48 -070065}
66
67struct ExtraData {
68 typedef GrTRecorder<ExtraData, int> Recorder;
69
70 ExtraData(int i) : fData(i) {
71 int* extraData = this->extraData();
72 for (int j = 0; j < i; j++) {
73 extraData[j] = i;
74 }
75 ++activeRecorderItems;
76 }
77 ~ExtraData() {
78 --activeRecorderItems;
79 }
80 int* extraData() {
81 return reinterpret_cast<int*>(Recorder::GetDataForItem(this));
82 }
83 int fData;
84};
85
86static void test_extra_data(skiatest::Reporter* reporter) {
87 ExtraData::Recorder recorder(0);
88 for (int i = 0; i < 100; ++i) {
89 GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int));
90 }
91 REPORTER_ASSERT(reporter, 100 == activeRecorderItems);
92
93 ExtraData::Recorder::Iter iter(recorder);
94 for (int i = 0; i < 100; ++i) {
95 REPORTER_ASSERT(reporter, iter.next());
96 REPORTER_ASSERT(reporter, i == iter->fData);
97 for (int j = 0; j < i; j++) {
98 REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
99 }
100 }
101 REPORTER_ASSERT(reporter, !iter.next());
102
cdalton72badbd2015-04-16 10:42:49 -0700103 ExtraData::Recorder::ReverseIter reverseIter(recorder);
104 for (int i = 99; i >= 0; --i) {
105 REPORTER_ASSERT(reporter, i == reverseIter->fData);
106 for (int j = 0; j < i; j++) {
107 REPORTER_ASSERT(reporter, i == reverseIter->extraData()[j]);
108 }
109 REPORTER_ASSERT(reporter, reverseIter.previous() == !!i);
110 }
111
cdalton6819df32014-10-15 13:43:48 -0700112 recorder.reset();
113 REPORTER_ASSERT(reporter, 0 == activeRecorderItems);
114}
115
116enum ClassType {
117 kBase_ClassType,
118 kSubclass_ClassType,
119 kSubSubclass_ClassType,
120 kSubclassExtraData_ClassType,
121 kSubclassEmpty_ClassType,
122
123 kNumClassTypes
124};
125
126class Base {
127public:
128 typedef GrTRecorder<Base, void*> Recorder;
129
130 Base() {
131 fMatrix.reset();
132 ++activeRecorderItems;
133 }
134
135 virtual ~Base() { --activeRecorderItems; }
136
137 virtual ClassType getType() { return kBase_ClassType; }
138
139 virtual void validate(skiatest::Reporter* reporter) const {
140 REPORTER_ASSERT(reporter, fMatrix.isIdentity());
141 }
142
143private:
144 SkMatrix fMatrix;
145};
146
147class Subclass : public Base {
148public:
149 Subclass() : fString("Lorem ipsum dolor sit amet") {}
150
151 virtual ClassType getType() { return kSubclass_ClassType; }
152
153 virtual void validate(skiatest::Reporter* reporter) const {
154 Base::validate(reporter);
155 REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str()));
156 }
157
158private:
159 SkString fString;
160};
161
162class SubSubclass : public Subclass {
163public:
164 SubSubclass() : fInt(1234), fFloat(1.234f) {}
165
166 virtual ClassType getType() { return kSubSubclass_ClassType; }
167
168 virtual void validate(skiatest::Reporter* reporter) const {
169 Subclass::validate(reporter);
170 REPORTER_ASSERT(reporter, 1234 == fInt);
171 REPORTER_ASSERT(reporter, 1.234f == fFloat);
172 }
173
174private:
175 int fInt;
176 float fFloat;
177};
178
179class SubclassExtraData : public Base {
180public:
181 SubclassExtraData(int length) : fLength(length) {
182 int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this));
183 for (int i = 0; i < fLength; ++i) {
184 data[i] = ValueAt(i);
185 }
186 }
187
188 virtual ClassType getType() { return kSubclassExtraData_ClassType; }
189
190 virtual void validate(skiatest::Reporter* reporter) const {
191 Base::validate(reporter);
192 const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this));
193 for (int i = 0; i < fLength; ++i) {
194 REPORTER_ASSERT(reporter, ValueAt(i) == data[i]);
195 }
196 }
197
198private:
199 static int ValueAt(uint64_t i) { return static_cast<int>(123456789 + 987654321 * i); }
200 int fLength;
201};
202
203class SubclassEmpty : public Base {
204public:
205 virtual ClassType getType() { return kSubclassEmpty_ClassType; }
206};
207
cdalton72badbd2015-04-16 10:42:49 -0700208class Order {
209public:
210 Order() { this->reset(); }
211 void reset() { fCurrent = 0; }
212 ClassType next() {
213 fCurrent = 1664525 * fCurrent + 1013904223;
214 return static_cast<ClassType>(fCurrent % kNumClassTypes);
215 }
216private:
217 uint32_t fCurrent;
218};
219static void test_subclasses_iters(skiatest::Reporter*, Order&, Base::Recorder::Iter&,
220 Base::Recorder::ReverseIter&, int = 0);
cdalton6819df32014-10-15 13:43:48 -0700221static void test_subclasses(skiatest::Reporter* reporter) {
cdalton6819df32014-10-15 13:43:48 -0700222 Base::Recorder recorder(1024);
223
224 Order order;
225 for (int i = 0; i < 1000; i++) {
226 switch (order.next()) {
227 case kBase_ClassType:
228 GrNEW_APPEND_TO_RECORDER(recorder, Base, ());
229 break;
230
231 case kSubclass_ClassType:
232 GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ());
233 break;
234
235 case kSubSubclass_ClassType:
236 GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ());
237 break;
238
239 case kSubclassExtraData_ClassType:
240 GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i);
241 break;
242
243 case kSubclassEmpty_ClassType:
244 GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ());
245 break;
246
247 default:
scroggo0ee26272014-11-07 06:07:32 -0800248 ERRORF(reporter, "Invalid class type");
cdalton6819df32014-10-15 13:43:48 -0700249 break;
250 }
251 }
252 REPORTER_ASSERT(reporter, 1000 == activeRecorderItems);
253
254 order.reset();
255 Base::Recorder::Iter iter(recorder);
cdalton72badbd2015-04-16 10:42:49 -0700256 Base::Recorder::ReverseIter reverseIter(recorder);
257
258 test_subclasses_iters(reporter, order, iter, reverseIter);
259
cdalton6819df32014-10-15 13:43:48 -0700260 REPORTER_ASSERT(reporter, !iter.next());
261
262 // Don't reset the recorder. It should automatically destruct all its items.
263}
cdalton72badbd2015-04-16 10:42:49 -0700264static void test_subclasses_iters(skiatest::Reporter* reporter, Order& order,
265 Base::Recorder::Iter& iter,
266 Base::Recorder::ReverseIter& reverseIter, int i) {
267 if (i >= 1000) {
268 return;
269 }
270
271 ClassType classType = order.next();
272
273 REPORTER_ASSERT(reporter, iter.next());
274 REPORTER_ASSERT(reporter, classType == iter->getType());
275 iter->validate(reporter);
276
277 test_subclasses_iters(reporter, order, iter, reverseIter, i + 1);
278
279 REPORTER_ASSERT(reporter, classType == reverseIter->getType());
280 reverseIter->validate(reporter);
281 REPORTER_ASSERT(reporter, reverseIter.previous() == !!i);
282}
cdalton6819df32014-10-15 13:43:48 -0700283
Brian Salomondcfca432017-11-15 15:48:03 -0500284DEF_GPUTEST(GrTRecorder, reporter, /* options */) {
bsalomon77d77f42014-11-21 14:38:06 -0800285 test_empty_back_and_pop(reporter);
cdalton6819df32014-10-15 13:43:48 -0700286
287 test_extra_data(reporter);
288 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset().
289
290 test_subclasses(reporter);
291 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors.
292}