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