blob: b62954c0653db9b3da2d51b2a199b22b183118c3 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkMatrix.h"
9#include "include/core/SkString.h"
10#include "include/utils/SkRandom.h"
11#include "tests/Test.h"
cdalton6819df32014-10-15 13:43:48 -070012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrTRecorder.h"
cdalton72badbd2015-04-16 10:42:49 -070014
cdalton6819df32014-10-15 13:43:48 -070015////////////////////////////////////////////////////////////////////////////////
16
Brian Salomon24d377e2019-04-23 15:24:31 -040017static int gActiveRecorderItems = 0;
cdalton6819df32014-10-15 13:43:48 -070018
19class IntWrapper {
20public:
21 IntWrapper() {}
22 IntWrapper(int value) : fValue(value) {}
23 operator int() { return fValue; }
24private:
25 int fValue;
26};
27
cdalton6819df32014-10-15 13:43:48 -070028struct ExtraData {
Brian Salomon24d377e2019-04-23 15:24:31 -040029 typedef GrTRecorder<ExtraData> Recorder;
cdalton6819df32014-10-15 13:43:48 -070030
31 ExtraData(int i) : fData(i) {
32 int* extraData = this->extraData();
33 for (int j = 0; j < i; j++) {
34 extraData[j] = i;
35 }
Brian Salomon24d377e2019-04-23 15:24:31 -040036 ++gActiveRecorderItems;
cdalton6819df32014-10-15 13:43:48 -070037 }
Brian Salomon24d377e2019-04-23 15:24:31 -040038 ~ExtraData() { --gActiveRecorderItems; }
39 int* extraData() { return reinterpret_cast<int*>(this + 1); }
cdalton6819df32014-10-15 13:43:48 -070040 int fData;
41};
42
43static void test_extra_data(skiatest::Reporter* reporter) {
44 ExtraData::Recorder recorder(0);
Brian Salomon24d377e2019-04-23 15:24:31 -040045 REPORTER_ASSERT(reporter, recorder.empty());
cdalton6819df32014-10-15 13:43:48 -070046 for (int i = 0; i < 100; ++i) {
Brian Salomon24d377e2019-04-23 15:24:31 -040047 recorder.emplaceWithData<ExtraData>(i * sizeof(int), i);
48 REPORTER_ASSERT(reporter, !recorder.empty());
cdalton6819df32014-10-15 13:43:48 -070049 }
Brian Salomon24d377e2019-04-23 15:24:31 -040050 REPORTER_ASSERT(reporter, 100 == gActiveRecorderItems);
cdalton6819df32014-10-15 13:43:48 -070051
Brian Salomon24d377e2019-04-23 15:24:31 -040052 auto iter = recorder.begin();
53 for (int i = 0; i < 100; ++i, ++iter) {
cdalton6819df32014-10-15 13:43:48 -070054 REPORTER_ASSERT(reporter, i == iter->fData);
55 for (int j = 0; j < i; j++) {
56 REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
57 }
58 }
Brian Salomon24d377e2019-04-23 15:24:31 -040059 REPORTER_ASSERT(reporter, iter == recorder.end());
cdalton72badbd2015-04-16 10:42:49 -070060
cdalton6819df32014-10-15 13:43:48 -070061 recorder.reset();
Brian Salomon24d377e2019-04-23 15:24:31 -040062 REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems);
63 REPORTER_ASSERT(reporter, recorder.begin() == recorder.end());
64 REPORTER_ASSERT(reporter, recorder.empty());
cdalton6819df32014-10-15 13:43:48 -070065}
66
67enum ClassType {
68 kBase_ClassType,
69 kSubclass_ClassType,
70 kSubSubclass_ClassType,
71 kSubclassExtraData_ClassType,
72 kSubclassEmpty_ClassType,
73
74 kNumClassTypes
75};
76
77class Base {
78public:
Brian Salomon24d377e2019-04-23 15:24:31 -040079 typedef GrTRecorder<Base> Recorder;
cdalton6819df32014-10-15 13:43:48 -070080
81 Base() {
82 fMatrix.reset();
Brian Salomon24d377e2019-04-23 15:24:31 -040083 ++gActiveRecorderItems;
cdalton6819df32014-10-15 13:43:48 -070084 }
85
Brian Salomon24d377e2019-04-23 15:24:31 -040086 virtual ~Base() { --gActiveRecorderItems; }
cdalton6819df32014-10-15 13:43:48 -070087
88 virtual ClassType getType() { return kBase_ClassType; }
89
90 virtual void validate(skiatest::Reporter* reporter) const {
91 REPORTER_ASSERT(reporter, fMatrix.isIdentity());
92 }
93
94private:
95 SkMatrix fMatrix;
96};
97
98class Subclass : public Base {
99public:
100 Subclass() : fString("Lorem ipsum dolor sit amet") {}
101
102 virtual ClassType getType() { return kSubclass_ClassType; }
103
104 virtual void validate(skiatest::Reporter* reporter) const {
105 Base::validate(reporter);
106 REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str()));
107 }
108
109private:
110 SkString fString;
111};
112
113class SubSubclass : public Subclass {
114public:
115 SubSubclass() : fInt(1234), fFloat(1.234f) {}
116
117 virtual ClassType getType() { return kSubSubclass_ClassType; }
118
119 virtual void validate(skiatest::Reporter* reporter) const {
120 Subclass::validate(reporter);
121 REPORTER_ASSERT(reporter, 1234 == fInt);
122 REPORTER_ASSERT(reporter, 1.234f == fFloat);
123 }
124
125private:
126 int fInt;
127 float fFloat;
128};
129
130class SubclassExtraData : public Base {
131public:
132 SubclassExtraData(int length) : fLength(length) {
Brian Salomon24d377e2019-04-23 15:24:31 -0400133 int* data = reinterpret_cast<int*>(this + 1);
cdalton6819df32014-10-15 13:43:48 -0700134 for (int i = 0; i < fLength; ++i) {
135 data[i] = ValueAt(i);
136 }
137 }
138
139 virtual ClassType getType() { return kSubclassExtraData_ClassType; }
140
141 virtual void validate(skiatest::Reporter* reporter) const {
142 Base::validate(reporter);
Brian Salomon24d377e2019-04-23 15:24:31 -0400143 const int* data = reinterpret_cast<const int*>(this + 1);
cdalton6819df32014-10-15 13:43:48 -0700144 for (int i = 0; i < fLength; ++i) {
145 REPORTER_ASSERT(reporter, ValueAt(i) == data[i]);
146 }
147 }
148
149private:
Brian Osman50ea3c02019-02-04 10:01:53 -0500150 static int ValueAt(uint64_t i) {
151 return static_cast<int>((123456789 + 987654321 * i) & 0xFFFFFFFF);
152 }
cdalton6819df32014-10-15 13:43:48 -0700153 int fLength;
154};
155
156class SubclassEmpty : public Base {
157public:
158 virtual ClassType getType() { return kSubclassEmpty_ClassType; }
159};
160
cdalton72badbd2015-04-16 10:42:49 -0700161class Order {
162public:
163 Order() { this->reset(); }
164 void reset() { fCurrent = 0; }
165 ClassType next() {
166 fCurrent = 1664525 * fCurrent + 1013904223;
167 return static_cast<ClassType>(fCurrent % kNumClassTypes);
168 }
169private:
170 uint32_t fCurrent;
171};
Brian Salomon24d377e2019-04-23 15:24:31 -0400172
173static void test_subclasses_iter(skiatest::Reporter*, Order&, Base::Recorder::iterator&, int = 0);
174
cdalton6819df32014-10-15 13:43:48 -0700175static void test_subclasses(skiatest::Reporter* reporter) {
cdalton6819df32014-10-15 13:43:48 -0700176 Base::Recorder recorder(1024);
177
178 Order order;
179 for (int i = 0; i < 1000; i++) {
180 switch (order.next()) {
181 case kBase_ClassType:
Brian Salomon24d377e2019-04-23 15:24:31 -0400182 recorder.emplace<Base>();
cdalton6819df32014-10-15 13:43:48 -0700183 break;
184
185 case kSubclass_ClassType:
Brian Salomon24d377e2019-04-23 15:24:31 -0400186 recorder.emplace<Subclass>();
cdalton6819df32014-10-15 13:43:48 -0700187 break;
188
189 case kSubSubclass_ClassType:
Brian Salomon24d377e2019-04-23 15:24:31 -0400190 recorder.emplace<SubSubclass>();
cdalton6819df32014-10-15 13:43:48 -0700191 break;
192
193 case kSubclassExtraData_ClassType:
Brian Salomon24d377e2019-04-23 15:24:31 -0400194 recorder.emplaceWithData<SubclassExtraData>(sizeof(int) * i, i);
cdalton6819df32014-10-15 13:43:48 -0700195 break;
196
197 case kSubclassEmpty_ClassType:
Brian Salomon24d377e2019-04-23 15:24:31 -0400198 recorder.emplace<SubclassEmpty>();
cdalton6819df32014-10-15 13:43:48 -0700199 break;
200
201 default:
scroggo0ee26272014-11-07 06:07:32 -0800202 ERRORF(reporter, "Invalid class type");
cdalton6819df32014-10-15 13:43:48 -0700203 break;
204 }
205 }
Brian Salomon24d377e2019-04-23 15:24:31 -0400206 REPORTER_ASSERT(reporter, 1000 == gActiveRecorderItems);
cdalton6819df32014-10-15 13:43:48 -0700207
208 order.reset();
Brian Salomon24d377e2019-04-23 15:24:31 -0400209 auto iter = recorder.begin();
cdalton72badbd2015-04-16 10:42:49 -0700210
Brian Salomon24d377e2019-04-23 15:24:31 -0400211 test_subclasses_iter(reporter, order, iter);
cdalton72badbd2015-04-16 10:42:49 -0700212
Brian Salomon24d377e2019-04-23 15:24:31 -0400213 REPORTER_ASSERT(reporter, iter == recorder.end());
cdalton6819df32014-10-15 13:43:48 -0700214 // Don't reset the recorder. It should automatically destruct all its items.
215}
Brian Salomon24d377e2019-04-23 15:24:31 -0400216static void test_subclasses_iter(skiatest::Reporter* reporter, Order& order,
217 Base::Recorder::iterator& iter, int i) {
cdalton72badbd2015-04-16 10:42:49 -0700218 if (i >= 1000) {
219 return;
220 }
221
222 ClassType classType = order.next();
223
cdalton72badbd2015-04-16 10:42:49 -0700224 REPORTER_ASSERT(reporter, classType == iter->getType());
225 iter->validate(reporter);
226
Brian Salomon24d377e2019-04-23 15:24:31 -0400227 ++iter;
228 test_subclasses_iter(reporter, order, iter, i + 1);
229}
cdalton72badbd2015-04-16 10:42:49 -0700230
Brian Salomon24d377e2019-04-23 15:24:31 -0400231struct AlignBase {
232 AlignBase() { ++gActiveRecorderItems; }
233 ~AlignBase() { --gActiveRecorderItems; }
234 char fValue;
235};
236struct alignas(16) Align16 : public AlignBase {};
237struct alignas(32) Align32 : public AlignBase {};
238struct alignas(64) Align64 : public AlignBase {};
239struct alignas(128) Align128 : public AlignBase {};
240
241static void test_alignment(skiatest::Reporter* reporter) {
242 GrTRecorder<AlignBase> recorder(0);
243 SkTArray<size_t> expectedAlignments;
244 SkRandom random;
245 for (int i = 0; i < 100; ++i) {
246 size_t dataSize = random.nextULessThan(20);
247 switch (random.nextULessThan(5)) {
248 case 0:
249 recorder.emplaceWithData<AlignBase>(dataSize);
250 expectedAlignments.push_back(alignof(AlignBase));
251 break;
252 case 1:
253 recorder.emplaceWithData<Align16>(dataSize);
254 expectedAlignments.push_back(16);
255 break;
256 case 2:
257 recorder.emplaceWithData<Align32>(dataSize);
258 expectedAlignments.push_back(32);
259 break;
260 case 3:
261 recorder.emplaceWithData<Align64>(dataSize);
262 expectedAlignments.push_back(64);
263 break;
264 case 4:
265 recorder.emplaceWithData<Align128>(dataSize);
266 expectedAlignments.push_back(128);
267 break;
268 }
269 recorder.back().fValue = i;
270 }
271 int i = 0;
272 for (const auto& x : recorder) {
273 REPORTER_ASSERT(reporter, x.fValue == i);
274 auto pointer = reinterpret_cast<uintptr_t>(&x);
275 auto mask = static_cast<uintptr_t>(expectedAlignments[i]) - 1;
276 REPORTER_ASSERT(reporter, !(pointer & mask));
277 i++;
278 }
279 REPORTER_ASSERT(reporter, i == 100);
cdalton72badbd2015-04-16 10:42:49 -0700280}
cdalton6819df32014-10-15 13:43:48 -0700281
Brian Salomondcfca432017-11-15 15:48:03 -0500282DEF_GPUTEST(GrTRecorder, reporter, /* options */) {
cdalton6819df32014-10-15 13:43:48 -0700283 test_extra_data(reporter);
Brian Salomon24d377e2019-04-23 15:24:31 -0400284 REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems); // test_extra_data should call reset().
cdalton6819df32014-10-15 13:43:48 -0700285
286 test_subclasses(reporter);
Brian Salomon24d377e2019-04-23 15:24:31 -0400287 REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems); // Ensure ~GrTRecorder invokes dtors.
288
289 test_alignment(reporter);
290 REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems); // Ensure ~GrTRecorder invokes dtors.
cdalton6819df32014-10-15 13:43:48 -0700291}