blob: 0848d97f747bdde5f5ad991964888a000884214c [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"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000012#include "SkInstCnt.h"
bsalomon@google.com4da34e32012-06-19 15:40:27 +000013#include "SkRandom.h"
14#include "SkTDArray.h"
reed@google.com9d1cff12013-04-18 18:43:26 +000015#include "SkTemplates.h"
bsalomon@google.com4da34e32012-06-19 15:40:27 +000016
bsalomon@google.com4da34e32012-06-19 15:40:27 +000017// 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.
20class A {
21public:
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
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000049 static A* Create(SkRandom* r);
bsalomon@google.com4da34e32012-06-19 15:40:27 +000050
51 static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
bsalomon@google.com4e230682013-01-15 20:37:04 +000052#if SK_ENABLE_INST_COUNT
bsalomon@google.com4da34e32012-06-19 15:40:27 +000053 SkASSERT(0 == GetInstanceCount());
robertphillips@google.comb74af872012-06-27 19:41:42 +000054#endif
bsalomon@google.com4da34e32012-06-19 15:40:27 +000055 GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
56 gPool.reset(pool);
57 }
58
59 static void ResetAllocator() {
bsalomon@google.com4e230682013-01-15 20:37:04 +000060#if SK_ENABLE_INST_COUNT
bsalomon@google.com4da34e32012-06-19 15:40:27 +000061 SkASSERT(0 == GetInstanceCount());
robertphillips@google.comb74af872012-06-27 19:41:42 +000062#endif
bsalomon@google.com4da34e32012-06-19 15:40:27 +000063 gPool.reset(NULL);
64 }
65
66private:
reed@google.com9d1cff12013-04-18 18:43:26 +000067 static SkAutoTDelete<GrMemoryPool> gPool;
bsalomon@google.com4da34e32012-06-19 15:40:27 +000068 char fChar;
69};
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000070
reed@google.com9d1cff12013-04-18 18:43:26 +000071SkAutoTDelete<GrMemoryPool> A::gPool;
bsalomon@google.com4da34e32012-06-19 15:40:27 +000072
73class B : public A {
74public:
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
86private:
87 double fDouble;
88
89 typedef A INHERITED;
90};
91
92class C : public A {
93public:
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
105private:
106 int64_t fInt64;
107
108 typedef A INHERITED;
109};
110
111// D derives from C and owns a dynamically created B
112class D : public C {
113public:
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 }
130private:
131 void* fVoidStar;
132 B* fB;
133
134 typedef C INHERITED;
135};
136
137class E : public A {
138public:
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() {}
156private:
157 int fIntArray[20];
158
159 typedef A INHERITED;
160};
161
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000162A* A::Create(SkRandom* r) {
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000163 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}
commit-bot@chromium.orgddf94cf2013-10-12 17:25:17 +0000179
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000180struct Rec {
181 A* fInstance;
182 int fValue;
183};
184
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000185DEF_TEST(GrMemoryPool, reporter) {
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000186 // 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
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000203 SkRandom r;
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000204 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 }
bsalomon@google.com4e230682013-01-15 20:37:04 +0000235#if SK_ENABLE_INST_COUNT
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000236 REPORTER_ASSERT(reporter, !A::GetInstanceCount());
237#endif
238 }
239 }
240}
241
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000242#endif