1 /* 2 * Copyright 2011 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 "Test.h" 9 // This is a GPU-backend specific test 10 #if SK_SUPPORT_GPU 11 #include "GrMemoryPool.h" 12 #include "SkRandom.h" 13 #include "SkTDArray.h" 14 #include "SkTemplates.h" 15 16 // A is the top of an inheritance tree of classes that overload op new and 17 // and delete to use a GrMemoryPool. The objects have values of different types 18 // that can be set and checked. 19 class A { 20 public: 21 A() {}; 22 virtual void setValues(int v) { 23 fChar = static_cast<char>(v); 24 } 25 virtual bool checkValues(int v) { 26 return fChar == static_cast<char>(v); 27 } 28 virtual ~A() {}; 29 30 void* operator new(size_t size) { 31 if (!gPool.get()) { 32 return ::operator new(size); 33 } else { 34 return gPool->allocate(size); 35 } 36 } 37 38 void operator delete(void* p) { 39 if (!gPool.get()) { 40 ::operator delete(p); 41 } else { 42 return gPool->release(p); 43 } 44 } 45 46 static A* Create(SkRandom* r); 47 48 static void SetAllocator(size_t preallocSize, size_t minAllocSize) { 49 GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize); 50 gPool.reset(pool); 51 } 52 53 static void ResetAllocator() { 54 gPool.reset(nullptr); 55 } 56 57 private: 58 static SkAutoTDelete<GrMemoryPool> gPool; 59 char fChar; 60 }; 61 62 SkAutoTDelete<GrMemoryPool> A::gPool; 63 64 class B : public A { 65 public: 66 B() {}; 67 virtual void setValues(int v) { 68 fDouble = static_cast<double>(v); 69 this->INHERITED::setValues(v); 70 } 71 virtual bool checkValues(int v) { 72 return fDouble == static_cast<double>(v) && 73 this->INHERITED::checkValues(v); 74 } 75 virtual ~B() {}; 76 77 private: 78 double fDouble; 79 80 typedef A INHERITED; 81 }; 82 83 class C : public A { 84 public: 85 C() {}; 86 virtual void setValues(int v) { 87 fInt64 = static_cast<int64_t>(v); 88 this->INHERITED::setValues(v); 89 } 90 virtual bool checkValues(int v) { 91 return fInt64 == static_cast<int64_t>(v) && 92 this->INHERITED::checkValues(v); 93 } 94 virtual ~C() {}; 95 96 private: 97 int64_t fInt64; 98 99 typedef A INHERITED; 100 }; 101 102 // D derives from C and owns a dynamically created B 103 class D : public C { 104 public: 105 D() { 106 fB = new B(); 107 } 108 virtual void setValues(int v) { 109 fVoidStar = reinterpret_cast<void*>(static_cast<intptr_t>(v)); 110 this->INHERITED::setValues(v); 111 fB->setValues(v); 112 } 113 virtual bool checkValues(int v) { 114 return fVoidStar == reinterpret_cast<void*>(static_cast<intptr_t>(v)) && 115 fB->checkValues(v) && 116 this->INHERITED::checkValues(v); 117 } 118 virtual ~D() { 119 delete fB; 120 } 121 private: 122 void* fVoidStar; 123 B* fB; 124 125 typedef C INHERITED; 126 }; 127 128 class E : public A { 129 public: 130 E() {} 131 virtual void setValues(int v) { 132 for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) { 133 fIntArray[i] = v; 134 } 135 this->INHERITED::setValues(v); 136 } 137 virtual bool checkValues(int v) { 138 bool ok = true; 139 for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) { 140 if (fIntArray[i] != v) { 141 ok = false; 142 } 143 } 144 return ok && this->INHERITED::checkValues(v); 145 } 146 virtual ~E() {} 147 private: 148 int fIntArray[20]; 149 150 typedef A INHERITED; 151 }; 152 153 A* A::Create(SkRandom* r) { 154 switch (r->nextRangeU(0, 4)) { 155 case 0: 156 return new A; 157 case 1: 158 return new B; 159 case 2: 160 return new C; 161 case 3: 162 return new D; 163 case 4: 164 return new E; 165 default: 166 // suppress warning 167 return nullptr; 168 } 169 } 170 171 struct Rec { 172 A* fInstance; 173 int fValue; 174 }; 175 176 DEF_TEST(GrMemoryPool, reporter) { 177 // prealloc and min alloc sizes for the pool 178 static const size_t gSizes[][2] = { 179 {0, 0}, 180 {10 * sizeof(A), 20 * sizeof(A)}, 181 {100 * sizeof(A), 100 * sizeof(A)}, 182 {500 * sizeof(A), 500 * sizeof(A)}, 183 {10000 * sizeof(A), 0}, 184 {1, 100 * sizeof(A)}, 185 }; 186 // different percentages of creation vs deletion 187 static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f}; 188 // number of create/destroys per test 189 static const int kNumIters = 20000; 190 // check that all the values stored in A objects are correct after this 191 // number of iterations 192 static const int kCheckPeriod = 500; 193 194 SkRandom r; 195 for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) { 196 A::SetAllocator(gSizes[s][0], gSizes[s][1]); 197 for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) { 198 SkTDArray<Rec> instanceRecs; 199 for (int i = 0; i < kNumIters; ++i) { 200 float createOrDestroy = r.nextUScalar1(); 201 if (createOrDestroy < gCreateFraction[c] || 202 0 == instanceRecs.count()) { 203 Rec* rec = instanceRecs.append(); 204 rec->fInstance = A::Create(&r); 205 rec->fValue = static_cast<int>(r.nextU()); 206 rec->fInstance->setValues(rec->fValue); 207 } else { 208 int d = r.nextRangeU(0, instanceRecs.count() - 1); 209 Rec& rec = instanceRecs[d]; 210 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); 211 delete rec.fInstance; 212 instanceRecs.removeShuffle(d); 213 } 214 if (0 == i % kCheckPeriod) { 215 for (int r = 0; r < instanceRecs.count(); ++r) { 216 Rec& rec = instanceRecs[r]; 217 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); 218 } 219 } 220 } 221 for (int i = 0; i < instanceRecs.count(); ++i) { 222 Rec& rec = instanceRecs[i]; 223 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); 224 delete rec.fInstance; 225 } 226 } 227 } 228 } 229 230 #endif 231