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