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 #if SK_SUPPORT_GPU 14 15 #include "GrTRecorder.h" 16 17 //////////////////////////////////////////////////////////////////////////////// 18 19 static int activeRecorderItems = 0; 20 21 class IntWrapper { 22 public: 23 IntWrapper() {} 24 IntWrapper(int value) : fValue(value) {} 25 operator int() { return fValue; } 26 private: 27 int fValue; 28 }; 29 30 static void test_empty_back_and_pop(skiatest::Reporter* reporter) { 31 SkRandom rand; 32 for (int data = 0; data < 2; ++data) { 33 // Do this with different starting sizes to have different alignment between blocks and pops. 34 // pops. We want to test poping the first guy off, guys in the middle of the block, and the 35 // first guy on a non-head block. 36 for (int j = 0; j < 8; ++j) { 37 GrTRecorder<IntWrapper, int> recorder(j); 38 39 REPORTER_ASSERT(reporter, recorder.empty()); 40 41 for (int i = 0; i < 100; ++i) { 42 if (data) { 43 REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder, 44 IntWrapper, (i))); 45 } else { 46 REPORTER_ASSERT(reporter, i == 47 *GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, 48 IntWrapper, (i), 49 rand.nextULessThan(10))); 50 } 51 REPORTER_ASSERT(reporter, !recorder.empty()); 52 REPORTER_ASSERT(reporter, i == recorder.back()); 53 if (0 == (i % 7)) { 54 recorder.pop_back(); 55 if (i > 0) { 56 REPORTER_ASSERT(reporter, !recorder.empty()); 57 REPORTER_ASSERT(reporter, i-1 == recorder.back()); 58 } 59 } 60 } 61 62 REPORTER_ASSERT(reporter, !recorder.empty()); 63 recorder.reset(); 64 REPORTER_ASSERT(reporter, recorder.empty()); 65 } 66 } 67 } 68 69 struct ExtraData { 70 typedef GrTRecorder<ExtraData, int> Recorder; 71 72 ExtraData(int i) : fData(i) { 73 int* extraData = this->extraData(); 74 for (int j = 0; j < i; j++) { 75 extraData[j] = i; 76 } 77 ++activeRecorderItems; 78 } 79 ~ExtraData() { 80 --activeRecorderItems; 81 } 82 int* extraData() { 83 return reinterpret_cast<int*>(Recorder::GetDataForItem(this)); 84 } 85 int fData; 86 }; 87 88 static void test_extra_data(skiatest::Reporter* reporter) { 89 ExtraData::Recorder recorder(0); 90 for (int i = 0; i < 100; ++i) { 91 GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int)); 92 } 93 REPORTER_ASSERT(reporter, 100 == activeRecorderItems); 94 95 ExtraData::Recorder::Iter iter(recorder); 96 for (int i = 0; i < 100; ++i) { 97 REPORTER_ASSERT(reporter, iter.next()); 98 REPORTER_ASSERT(reporter, i == iter->fData); 99 for (int j = 0; j < i; j++) { 100 REPORTER_ASSERT(reporter, i == iter->extraData()[j]); 101 } 102 } 103 REPORTER_ASSERT(reporter, !iter.next()); 104 105 ExtraData::Recorder::ReverseIter reverseIter(recorder); 106 for (int i = 99; i >= 0; --i) { 107 REPORTER_ASSERT(reporter, i == reverseIter->fData); 108 for (int j = 0; j < i; j++) { 109 REPORTER_ASSERT(reporter, i == reverseIter->extraData()[j]); 110 } 111 REPORTER_ASSERT(reporter, reverseIter.previous() == !!i); 112 } 113 114 recorder.reset(); 115 REPORTER_ASSERT(reporter, 0 == activeRecorderItems); 116 } 117 118 enum ClassType { 119 kBase_ClassType, 120 kSubclass_ClassType, 121 kSubSubclass_ClassType, 122 kSubclassExtraData_ClassType, 123 kSubclassEmpty_ClassType, 124 125 kNumClassTypes 126 }; 127 128 class Base { 129 public: 130 typedef GrTRecorder<Base, void*> Recorder; 131 132 Base() { 133 fMatrix.reset(); 134 ++activeRecorderItems; 135 } 136 137 virtual ~Base() { --activeRecorderItems; } 138 139 virtual ClassType getType() { return kBase_ClassType; } 140 141 virtual void validate(skiatest::Reporter* reporter) const { 142 REPORTER_ASSERT(reporter, fMatrix.isIdentity()); 143 } 144 145 private: 146 SkMatrix fMatrix; 147 }; 148 149 class Subclass : public Base { 150 public: 151 Subclass() : fString("Lorem ipsum dolor sit amet") {} 152 153 virtual ClassType getType() { return kSubclass_ClassType; } 154 155 virtual void validate(skiatest::Reporter* reporter) const { 156 Base::validate(reporter); 157 REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str())); 158 } 159 160 private: 161 SkString fString; 162 }; 163 164 class SubSubclass : public Subclass { 165 public: 166 SubSubclass() : fInt(1234), fFloat(1.234f) {} 167 168 virtual ClassType getType() { return kSubSubclass_ClassType; } 169 170 virtual void validate(skiatest::Reporter* reporter) const { 171 Subclass::validate(reporter); 172 REPORTER_ASSERT(reporter, 1234 == fInt); 173 REPORTER_ASSERT(reporter, 1.234f == fFloat); 174 } 175 176 private: 177 int fInt; 178 float fFloat; 179 }; 180 181 class SubclassExtraData : public Base { 182 public: 183 SubclassExtraData(int length) : fLength(length) { 184 int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this)); 185 for (int i = 0; i < fLength; ++i) { 186 data[i] = ValueAt(i); 187 } 188 } 189 190 virtual ClassType getType() { return kSubclassExtraData_ClassType; } 191 192 virtual void validate(skiatest::Reporter* reporter) const { 193 Base::validate(reporter); 194 const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this)); 195 for (int i = 0; i < fLength; ++i) { 196 REPORTER_ASSERT(reporter, ValueAt(i) == data[i]); 197 } 198 } 199 200 private: 201 static int ValueAt(uint64_t i) { return static_cast<int>(123456789 + 987654321 * i); } 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, factory) { 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 296 #endif 297