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:
A()22 A() {};
setValues(int v)23 virtual void setValues(int v) {
24 fChar = static_cast<char>(v);
25 }
checkValues(int v)26 virtual bool checkValues(int v) {
27 return fChar == static_cast<char>(v);
28 }
~A()29 virtual ~A() {};
30
operator new(size_t size)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
operator delete(void * p)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(A);
48
49 static A* Create(SkRandom* r);
50
SetAllocator(size_t preallocSize,size_t minAllocSize)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
ResetAllocator()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:
B()75 B() {};
setValues(int v)76 virtual void setValues(int v) {
77 fDouble = static_cast<double>(v);
78 this->INHERITED::setValues(v);
79 }
checkValues(int v)80 virtual bool checkValues(int v) {
81 return fDouble == static_cast<double>(v) &&
82 this->INHERITED::checkValues(v);
83 }
~B()84 virtual ~B() {};
85
86 private:
87 double fDouble;
88
89 typedef A INHERITED;
90 };
91
92 class C : public A {
93 public:
C()94 C() {};
setValues(int v)95 virtual void setValues(int v) {
96 fInt64 = static_cast<int64_t>(v);
97 this->INHERITED::setValues(v);
98 }
checkValues(int v)99 virtual bool checkValues(int v) {
100 return fInt64 == static_cast<int64_t>(v) &&
101 this->INHERITED::checkValues(v);
102 }
~C()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:
D()114 D() {
115 fB = new B();
116 }
setValues(int v)117 virtual void setValues(int v) {
118 fVoidStar = reinterpret_cast<void*>(v);
119 this->INHERITED::setValues(v);
120 fB->setValues(v);
121 }
checkValues(int v)122 virtual bool checkValues(int v) {
123 return fVoidStar == reinterpret_cast<void*>(v) &&
124 fB->checkValues(v) &&
125 this->INHERITED::checkValues(v);
126 }
~D()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:
E()139 E() {}
setValues(int v)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 }
checkValues(int v)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 }
~E()155 virtual ~E() {}
156 private:
157 int fIntArray[20];
158
159 typedef A INHERITED;
160 };
161
Create(SkRandom * r)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
DEF_TEST(GrMemoryPool,reporter)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