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