• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "include/core/SkMatrix.h"
9 #include "include/core/SkString.h"
10 #include "include/utils/SkRandom.h"
11 #include "tests/Test.h"
12 
13 #include "src/gpu/GrTRecorder.h"
14 
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 static int gActiveRecorderItems = 0;
18 
19 class IntWrapper {
20 public:
IntWrapper()21     IntWrapper() {}
IntWrapper(int value)22     IntWrapper(int value) : fValue(value) {}
operator int()23     operator int() { return fValue; }
24 private:
25     int fValue;
26 };
27 
28 struct ExtraData {
29     typedef GrTRecorder<ExtraData> Recorder;
30 
ExtraDataExtraData31     ExtraData(int i) : fData(i) {
32         int* extraData = this->extraData();
33         for (int j = 0; j < i; j++) {
34             extraData[j] = i;
35         }
36         ++gActiveRecorderItems;
37     }
~ExtraDataExtraData38     ~ExtraData() { --gActiveRecorderItems; }
extraDataExtraData39     int* extraData() { return reinterpret_cast<int*>(this + 1); }
40     int fData;
41 };
42 
test_extra_data(skiatest::Reporter * reporter)43 static void test_extra_data(skiatest::Reporter* reporter) {
44     ExtraData::Recorder recorder(0);
45     REPORTER_ASSERT(reporter, recorder.empty());
46     for (int i = 0; i < 100; ++i) {
47         recorder.emplaceWithData<ExtraData>(i * sizeof(int), i);
48         REPORTER_ASSERT(reporter, !recorder.empty());
49     }
50     REPORTER_ASSERT(reporter, 100 == gActiveRecorderItems);
51 
52     auto iter = recorder.begin();
53     for (int i = 0; i < 100; ++i, ++iter) {
54         REPORTER_ASSERT(reporter, i == iter->fData);
55         for (int j = 0; j < i; j++) {
56             REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
57         }
58     }
59     REPORTER_ASSERT(reporter, iter == recorder.end());
60 
61     recorder.reset();
62     REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems);
63     REPORTER_ASSERT(reporter, recorder.begin() == recorder.end());
64     REPORTER_ASSERT(reporter, recorder.empty());
65 }
66 
67 enum ClassType {
68     kBase_ClassType,
69     kSubclass_ClassType,
70     kSubSubclass_ClassType,
71     kSubclassExtraData_ClassType,
72     kSubclassEmpty_ClassType,
73 
74     kNumClassTypes
75 };
76 
77 class Base {
78 public:
79     typedef GrTRecorder<Base> Recorder;
80 
Base()81     Base() {
82         fMatrix.reset();
83         ++gActiveRecorderItems;
84     }
85 
~Base()86     virtual ~Base() { --gActiveRecorderItems; }
87 
getType()88     virtual ClassType getType() { return kBase_ClassType; }
89 
validate(skiatest::Reporter * reporter) const90     virtual void validate(skiatest::Reporter* reporter) const {
91         REPORTER_ASSERT(reporter, fMatrix.isIdentity());
92     }
93 
94 private:
95     SkMatrix fMatrix;
96 };
97 
98 class Subclass : public Base {
99 public:
Subclass()100     Subclass() : fString("Lorem ipsum dolor sit amet") {}
101 
getType()102     virtual ClassType getType() { return kSubclass_ClassType; }
103 
validate(skiatest::Reporter * reporter) const104     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 
109 private:
110     SkString fString;
111 };
112 
113 class SubSubclass : public Subclass {
114 public:
SubSubclass()115     SubSubclass() : fInt(1234), fFloat(1.234f) {}
116 
getType()117     virtual ClassType getType() { return kSubSubclass_ClassType; }
118 
validate(skiatest::Reporter * reporter) const119     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 
125 private:
126     int fInt;
127     float fFloat;
128 };
129 
130 class SubclassExtraData : public Base {
131 public:
SubclassExtraData(int length)132     SubclassExtraData(int length) : fLength(length) {
133         int* data = reinterpret_cast<int*>(this + 1);
134         for (int i = 0; i < fLength; ++i) {
135             data[i] = ValueAt(i);
136         }
137     }
138 
getType()139     virtual ClassType getType() { return kSubclassExtraData_ClassType; }
140 
validate(skiatest::Reporter * reporter) const141     virtual void validate(skiatest::Reporter* reporter) const {
142         Base::validate(reporter);
143         const int* data = reinterpret_cast<const int*>(this + 1);
144         for (int i = 0; i < fLength; ++i) {
145             REPORTER_ASSERT(reporter, ValueAt(i) == data[i]);
146         }
147     }
148 
149 private:
ValueAt(uint64_t i)150     static int ValueAt(uint64_t i) {
151         return static_cast<int>((123456789 + 987654321 * i) & 0xFFFFFFFF);
152     }
153     int fLength;
154 };
155 
156 class SubclassEmpty : public Base {
157 public:
getType()158     virtual ClassType getType() { return kSubclassEmpty_ClassType; }
159 };
160 
161 class Order {
162 public:
Order()163     Order() { this->reset(); }
reset()164     void reset() { fCurrent = 0; }
next()165     ClassType next() {
166         fCurrent = 1664525 * fCurrent + 1013904223;
167         return static_cast<ClassType>(fCurrent % kNumClassTypes);
168     }
169 private:
170     uint32_t fCurrent;
171 };
172 
173 static void test_subclasses_iter(skiatest::Reporter*, Order&, Base::Recorder::iterator&, int = 0);
174 
test_subclasses(skiatest::Reporter * reporter)175 static void test_subclasses(skiatest::Reporter* reporter) {
176     Base::Recorder recorder(1024);
177 
178     Order order;
179     for (int i = 0; i < 1000; i++) {
180         switch (order.next()) {
181             case kBase_ClassType:
182                 recorder.emplace<Base>();
183                 break;
184 
185             case kSubclass_ClassType:
186                 recorder.emplace<Subclass>();
187                 break;
188 
189             case kSubSubclass_ClassType:
190                 recorder.emplace<SubSubclass>();
191                 break;
192 
193             case kSubclassExtraData_ClassType:
194                 recorder.emplaceWithData<SubclassExtraData>(sizeof(int) * i, i);
195                 break;
196 
197             case kSubclassEmpty_ClassType:
198                 recorder.emplace<SubclassEmpty>();
199                 break;
200 
201             default:
202                 ERRORF(reporter, "Invalid class type");
203                 break;
204         }
205     }
206     REPORTER_ASSERT(reporter, 1000 == gActiveRecorderItems);
207 
208     order.reset();
209     auto iter = recorder.begin();
210 
211     test_subclasses_iter(reporter, order, iter);
212 
213     REPORTER_ASSERT(reporter, iter == recorder.end());
214     // Don't reset the recorder. It should automatically destruct all its items.
215 }
test_subclasses_iter(skiatest::Reporter * reporter,Order & order,Base::Recorder::iterator & iter,int i)216 static void test_subclasses_iter(skiatest::Reporter* reporter, Order& order,
217                                  Base::Recorder::iterator& iter, int i) {
218     if (i >= 1000) {
219         return;
220     }
221 
222     ClassType classType = order.next();
223 
224     REPORTER_ASSERT(reporter, classType == iter->getType());
225     iter->validate(reporter);
226 
227     ++iter;
228     test_subclasses_iter(reporter, order, iter, i + 1);
229 }
230 
231 struct AlignBase {
AlignBaseAlignBase232     AlignBase() { ++gActiveRecorderItems; }
~AlignBaseAlignBase233     ~AlignBase() { --gActiveRecorderItems; }
234     char fValue;
235 };
236 struct alignas(16) Align16 : public AlignBase {};
237 struct alignas(32) Align32 : public AlignBase {};
238 struct alignas(64) Align64 : public AlignBase {};
239 struct alignas(128) Align128 : public AlignBase {};
240 
test_alignment(skiatest::Reporter * reporter)241 static 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);
280 }
281 
282 DEF_GPUTEST(GrTRecorder, reporter, /* options */) {
283     test_extra_data(reporter);
284     REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems);  // test_extra_data should call reset().
285 
286     test_subclasses(reporter);
287     REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems);  // Ensure ~GrTRecorder invokes dtors.
288 
289     test_alignment(reporter);
290     REPORTER_ASSERT(reporter, 0 == gActiveRecorderItems);  // Ensure ~GrTRecorder invokes dtors.
291 }
292