blob: 1aecce328c794e5cb723d15b83b9e1cca5235210 [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"
reed@google.com9d1cff12013-04-18 18:43:26 +000014#include "SkTemplates.h"
bsalomon@google.com4da34e32012-06-19 15:40:27 +000015
bsalomon@google.com4da34e32012-06-19 15:40:27 +000016// A is the top of an inheritance tree of classes that overload op new and
17// and delete to use a GrMemoryPool. The objects have values of different types
18// that can be set and checked.
19class A {
20public:
21 A() {};
22 virtual void setValues(int v) {
23 fChar = static_cast<char>(v);
24 }
25 virtual bool checkValues(int v) {
26 return fChar == static_cast<char>(v);
27 }
28 virtual ~A() {};
29
30 void* operator new(size_t size) {
31 if (!gPool.get()) {
32 return ::operator new(size);
33 } else {
34 return gPool->allocate(size);
35 }
36 }
37
38 void operator delete(void* p) {
39 if (!gPool.get()) {
40 ::operator delete(p);
41 } else {
42 return gPool->release(p);
43 }
44 }
45
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000046 static A* Create(SkRandom* r);
bsalomon@google.com4da34e32012-06-19 15:40:27 +000047
48 static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
bsalomon@google.com4da34e32012-06-19 15:40:27 +000049 GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
50 gPool.reset(pool);
51 }
52
53 static void ResetAllocator() {
halcanary96fcdcc2015-08-27 07:41:13 -070054 gPool.reset(nullptr);
bsalomon@google.com4da34e32012-06-19 15:40:27 +000055 }
56
57private:
reed@google.com9d1cff12013-04-18 18:43:26 +000058 static SkAutoTDelete<GrMemoryPool> gPool;
bsalomon@google.com4da34e32012-06-19 15:40:27 +000059 char fChar;
60};
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000061
reed@google.com9d1cff12013-04-18 18:43:26 +000062SkAutoTDelete<GrMemoryPool> A::gPool;
bsalomon@google.com4da34e32012-06-19 15:40:27 +000063
64class B : public A {
65public:
66 B() {};
67 virtual void setValues(int v) {
68 fDouble = static_cast<double>(v);
69 this->INHERITED::setValues(v);
70 }
71 virtual bool checkValues(int v) {
72 return fDouble == static_cast<double>(v) &&
73 this->INHERITED::checkValues(v);
74 }
75 virtual ~B() {};
76
77private:
78 double fDouble;
79
80 typedef A INHERITED;
81};
82
83class C : public A {
84public:
85 C() {};
86 virtual void setValues(int v) {
87 fInt64 = static_cast<int64_t>(v);
88 this->INHERITED::setValues(v);
89 }
90 virtual bool checkValues(int v) {
91 return fInt64 == static_cast<int64_t>(v) &&
92 this->INHERITED::checkValues(v);
93 }
94 virtual ~C() {};
95
96private:
97 int64_t fInt64;
98
99 typedef A INHERITED;
100};
101
102// D derives from C and owns a dynamically created B
103class D : public C {
104public:
105 D() {
106 fB = new B();
107 }
108 virtual void setValues(int v) {
bsalomonebc1c102015-08-06 17:33:16 -0700109 fVoidStar = reinterpret_cast<void*>(static_cast<intptr_t>(v));
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000110 this->INHERITED::setValues(v);
111 fB->setValues(v);
112 }
113 virtual bool checkValues(int v) {
bsalomonebc1c102015-08-06 17:33:16 -0700114 return fVoidStar == reinterpret_cast<void*>(static_cast<intptr_t>(v)) &&
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000115 fB->checkValues(v) &&
116 this->INHERITED::checkValues(v);
117 }
118 virtual ~D() {
119 delete fB;
120 }
121private:
122 void* fVoidStar;
123 B* fB;
124
125 typedef C INHERITED;
126};
127
128class E : public A {
129public:
130 E() {}
131 virtual void setValues(int v) {
132 for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) {
133 fIntArray[i] = v;
134 }
135 this->INHERITED::setValues(v);
136 }
137 virtual bool checkValues(int v) {
138 bool ok = true;
139 for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) {
140 if (fIntArray[i] != v) {
141 ok = false;
142 }
143 }
144 return ok && this->INHERITED::checkValues(v);
145 }
146 virtual ~E() {}
147private:
148 int fIntArray[20];
149
150 typedef A INHERITED;
151};
152
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000153A* A::Create(SkRandom* r) {
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000154 switch (r->nextRangeU(0, 4)) {
155 case 0:
156 return new A;
157 case 1:
158 return new B;
159 case 2:
160 return new C;
161 case 3:
162 return new D;
163 case 4:
164 return new E;
165 default:
166 // suppress warning
halcanary96fcdcc2015-08-27 07:41:13 -0700167 return nullptr;
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000168 }
169}
commit-bot@chromium.orgddf94cf2013-10-12 17:25:17 +0000170
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000171struct Rec {
172 A* fInstance;
173 int fValue;
174};
175
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000176DEF_TEST(GrMemoryPool, reporter) {
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000177 // prealloc and min alloc sizes for the pool
178 static const size_t gSizes[][2] = {
179 {0, 0},
180 {10 * sizeof(A), 20 * sizeof(A)},
181 {100 * sizeof(A), 100 * sizeof(A)},
182 {500 * sizeof(A), 500 * sizeof(A)},
183 {10000 * sizeof(A), 0},
184 {1, 100 * sizeof(A)},
185 };
186 // different percentages of creation vs deletion
187 static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
188 // number of create/destroys per test
189 static const int kNumIters = 20000;
190 // check that all the values stored in A objects are correct after this
191 // number of iterations
192 static const int kCheckPeriod = 500;
193
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000194 SkRandom r;
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000195 for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) {
196 A::SetAllocator(gSizes[s][0], gSizes[s][1]);
197 for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) {
198 SkTDArray<Rec> instanceRecs;
199 for (int i = 0; i < kNumIters; ++i) {
200 float createOrDestroy = r.nextUScalar1();
201 if (createOrDestroy < gCreateFraction[c] ||
202 0 == instanceRecs.count()) {
203 Rec* rec = instanceRecs.append();
204 rec->fInstance = A::Create(&r);
205 rec->fValue = static_cast<int>(r.nextU());
206 rec->fInstance->setValues(rec->fValue);
207 } else {
208 int d = r.nextRangeU(0, instanceRecs.count() - 1);
209 Rec& rec = instanceRecs[d];
210 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
211 delete rec.fInstance;
212 instanceRecs.removeShuffle(d);
213 }
214 if (0 == i % kCheckPeriod) {
215 for (int r = 0; r < instanceRecs.count(); ++r) {
216 Rec& rec = instanceRecs[r];
217 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
218 }
219 }
220 }
221 for (int i = 0; i < instanceRecs.count(); ++i) {
222 Rec& rec = instanceRecs[i];
223 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
224 delete rec.fInstance;
225 }
bsalomon@google.com4da34e32012-06-19 15:40:27 +0000226 }
227 }
228}
229
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000230#endif