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 "SkMatrix.h" 9 #include "SkRandom.h" 10 #include "SkString.h" 11 #include "Test.h" 12 13 #include "GrTRecorder.h" 14 15 //////////////////////////////////////////////////////////////////////////////// 16 17 static int activeRecorderItems = 0; 18 19 class IntWrapper { 20 public: 21 IntWrapper() {} 22 IntWrapper(int value) : fValue(value) {} 23 operator int() { return fValue; } 24 private: 25 int fValue; 26 }; 27 28 static 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); 36 37 REPORTER_ASSERT(reporter, recorder.empty()); 38 39 for (int i = 0; i < 100; ++i) { 40 if (data) { 41 REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder, 42 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 } 64 } 65 } 66 67 struct 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 86 static 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 103 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 112 recorder.reset(); 113 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); 114 } 115 116 enum ClassType { 117 kBase_ClassType, 118 kSubclass_ClassType, 119 kSubSubclass_ClassType, 120 kSubclassExtraData_ClassType, 121 kSubclassEmpty_ClassType, 122 123 kNumClassTypes 124 }; 125 126 class Base { 127 public: 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 143 private: 144 SkMatrix fMatrix; 145 }; 146 147 class Subclass : public Base { 148 public: 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 158 private: 159 SkString fString; 160 }; 161 162 class SubSubclass : public Subclass { 163 public: 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 174 private: 175 int fInt; 176 float fFloat; 177 }; 178 179 class SubclassExtraData : public Base { 180 public: 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 198 private: 199 static int ValueAt(uint64_t i) { 200 return static_cast<int>((123456789 + 987654321 * i) & 0xFFFFFFFF); 201 } 202 int fLength; 203 }; 204 205 class SubclassEmpty : public Base { 206 public: 207 virtual ClassType getType() { return kSubclassEmpty_ClassType; } 208 }; 209 210 class Order { 211 public: 212 Order() { this->reset(); } 213 void reset() { fCurrent = 0; } 214 ClassType next() { 215 fCurrent = 1664525 * fCurrent + 1013904223; 216 return static_cast<ClassType>(fCurrent % kNumClassTypes); 217 } 218 private: 219 uint32_t fCurrent; 220 }; 221 static void test_subclasses_iters(skiatest::Reporter*, Order&, Base::Recorder::Iter&, 222 Base::Recorder::ReverseIter&, int = 0); 223 static void test_subclasses(skiatest::Reporter* reporter) { 224 Base::Recorder recorder(1024); 225 226 Order order; 227 for (int i = 0; i < 1000; i++) { 228 switch (order.next()) { 229 case kBase_ClassType: 230 GrNEW_APPEND_TO_RECORDER(recorder, Base, ()); 231 break; 232 233 case kSubclass_ClassType: 234 GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ()); 235 break; 236 237 case kSubSubclass_ClassType: 238 GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ()); 239 break; 240 241 case kSubclassExtraData_ClassType: 242 GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i); 243 break; 244 245 case kSubclassEmpty_ClassType: 246 GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ()); 247 break; 248 249 default: 250 ERRORF(reporter, "Invalid class type"); 251 break; 252 } 253 } 254 REPORTER_ASSERT(reporter, 1000 == activeRecorderItems); 255 256 order.reset(); 257 Base::Recorder::Iter iter(recorder); 258 Base::Recorder::ReverseIter reverseIter(recorder); 259 260 test_subclasses_iters(reporter, order, iter, reverseIter); 261 262 REPORTER_ASSERT(reporter, !iter.next()); 263 264 // Don't reset the recorder. It should automatically destruct all its items. 265 } 266 static void test_subclasses_iters(skiatest::Reporter* reporter, Order& order, 267 Base::Recorder::Iter& iter, 268 Base::Recorder::ReverseIter& reverseIter, int i) { 269 if (i >= 1000) { 270 return; 271 } 272 273 ClassType classType = order.next(); 274 275 REPORTER_ASSERT(reporter, iter.next()); 276 REPORTER_ASSERT(reporter, classType == iter->getType()); 277 iter->validate(reporter); 278 279 test_subclasses_iters(reporter, order, iter, reverseIter, i + 1); 280 281 REPORTER_ASSERT(reporter, classType == reverseIter->getType()); 282 reverseIter->validate(reporter); 283 REPORTER_ASSERT(reporter, reverseIter.previous() == !!i); 284 } 285 286 DEF_GPUTEST(GrTRecorder, reporter, /* options */) { 287 test_empty_back_and_pop(reporter); 288 289 test_extra_data(reporter); 290 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset(). 291 292 test_subclasses(reporter); 293 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors. 294 } 295