xref: /aosp_15_r20/external/skia/tests/GrMemoryPoolTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrMemoryPool.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
13*c8dee2aaSAndroid Build Coastguard Worker 
14*c8dee2aaSAndroid Build Coastguard Worker #include <array>
15*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
16*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
17*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker // A is the top of an inheritance tree of classes that overload op new and
22*c8dee2aaSAndroid Build Coastguard Worker // and delete to use a GrMemoryPool. The objects have values of different types
23*c8dee2aaSAndroid Build Coastguard Worker // that can be set and checked.
24*c8dee2aaSAndroid Build Coastguard Worker class A {
25*c8dee2aaSAndroid Build Coastguard Worker public:
A()26*c8dee2aaSAndroid Build Coastguard Worker     A() {}
setValues(int v)27*c8dee2aaSAndroid Build Coastguard Worker     virtual void setValues(int v) {
28*c8dee2aaSAndroid Build Coastguard Worker         fChar = static_cast<char>(v & 0xFF);
29*c8dee2aaSAndroid Build Coastguard Worker     }
checkValues(int v)30*c8dee2aaSAndroid Build Coastguard Worker     virtual bool checkValues(int v) {
31*c8dee2aaSAndroid Build Coastguard Worker         return fChar == static_cast<char>(v & 0xFF);
32*c8dee2aaSAndroid Build Coastguard Worker     }
~A()33*c8dee2aaSAndroid Build Coastguard Worker     virtual ~A() {}
34*c8dee2aaSAndroid Build Coastguard Worker 
operator new(size_t size)35*c8dee2aaSAndroid Build Coastguard Worker     void* operator new(size_t size) {
36*c8dee2aaSAndroid Build Coastguard Worker         if (!gPool) {
37*c8dee2aaSAndroid Build Coastguard Worker             return ::operator new(size);
38*c8dee2aaSAndroid Build Coastguard Worker         } else {
39*c8dee2aaSAndroid Build Coastguard Worker             return gPool->allocate(size);
40*c8dee2aaSAndroid Build Coastguard Worker         }
41*c8dee2aaSAndroid Build Coastguard Worker     }
42*c8dee2aaSAndroid Build Coastguard Worker 
operator delete(void * p)43*c8dee2aaSAndroid Build Coastguard Worker     void operator delete(void* p) {
44*c8dee2aaSAndroid Build Coastguard Worker         if (!gPool) {
45*c8dee2aaSAndroid Build Coastguard Worker             ::operator delete(p);
46*c8dee2aaSAndroid Build Coastguard Worker         } else {
47*c8dee2aaSAndroid Build Coastguard Worker             return gPool->release(p);
48*c8dee2aaSAndroid Build Coastguard Worker         }
49*c8dee2aaSAndroid Build Coastguard Worker     }
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker     static A* Create(SkRandom* r);
52*c8dee2aaSAndroid Build Coastguard Worker 
SetAllocator(size_t preallocSize,size_t minAllocSize)53*c8dee2aaSAndroid Build Coastguard Worker     static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
54*c8dee2aaSAndroid Build Coastguard Worker         gPool = GrMemoryPool::Make(preallocSize, minAllocSize);
55*c8dee2aaSAndroid Build Coastguard Worker     }
56*c8dee2aaSAndroid Build Coastguard Worker 
ResetAllocator()57*c8dee2aaSAndroid Build Coastguard Worker     static void ResetAllocator() { gPool.reset(); }
58*c8dee2aaSAndroid Build Coastguard Worker 
ValidatePool()59*c8dee2aaSAndroid Build Coastguard Worker     static void ValidatePool() {
60*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
61*c8dee2aaSAndroid Build Coastguard Worker         gPool->validate();
62*c8dee2aaSAndroid Build Coastguard Worker #endif
63*c8dee2aaSAndroid Build Coastguard Worker     }
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker private:
66*c8dee2aaSAndroid Build Coastguard Worker     static std::unique_ptr<GrMemoryPool> gPool;
67*c8dee2aaSAndroid Build Coastguard Worker     char fChar;
68*c8dee2aaSAndroid Build Coastguard Worker };
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrMemoryPool> A::gPool;
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker class B : public A {
73*c8dee2aaSAndroid Build Coastguard Worker public:
B()74*c8dee2aaSAndroid Build Coastguard Worker     B() {}
setValues(int v)75*c8dee2aaSAndroid Build Coastguard Worker     void setValues(int v) override {
76*c8dee2aaSAndroid Build Coastguard Worker         fDouble = static_cast<double>(v);
77*c8dee2aaSAndroid Build Coastguard Worker         this->INHERITED::setValues(v);
78*c8dee2aaSAndroid Build Coastguard Worker     }
checkValues(int v)79*c8dee2aaSAndroid Build Coastguard Worker     bool checkValues(int v) override {
80*c8dee2aaSAndroid Build Coastguard Worker         return fDouble == static_cast<double>(v) &&
81*c8dee2aaSAndroid Build Coastguard Worker                this->INHERITED::checkValues(v);
82*c8dee2aaSAndroid Build Coastguard Worker     }
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker private:
85*c8dee2aaSAndroid Build Coastguard Worker     double fDouble;
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = A;
88*c8dee2aaSAndroid Build Coastguard Worker };
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker class C : public A {
91*c8dee2aaSAndroid Build Coastguard Worker public:
C()92*c8dee2aaSAndroid Build Coastguard Worker     C() {}
setValues(int v)93*c8dee2aaSAndroid Build Coastguard Worker     void setValues(int v) override {
94*c8dee2aaSAndroid Build Coastguard Worker         fInt64 = static_cast<int64_t>(v);
95*c8dee2aaSAndroid Build Coastguard Worker         this->INHERITED::setValues(v);
96*c8dee2aaSAndroid Build Coastguard Worker     }
checkValues(int v)97*c8dee2aaSAndroid Build Coastguard Worker     bool checkValues(int v) override {
98*c8dee2aaSAndroid Build Coastguard Worker         return fInt64 == static_cast<int64_t>(v) &&
99*c8dee2aaSAndroid Build Coastguard Worker                this->INHERITED::checkValues(v);
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker private:
103*c8dee2aaSAndroid Build Coastguard Worker     int64_t fInt64;
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = A;
106*c8dee2aaSAndroid Build Coastguard Worker };
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker // D derives from C and owns a dynamically created B
109*c8dee2aaSAndroid Build Coastguard Worker class D : public C {
110*c8dee2aaSAndroid Build Coastguard Worker public:
D()111*c8dee2aaSAndroid Build Coastguard Worker     D() {
112*c8dee2aaSAndroid Build Coastguard Worker         fB = new B();
113*c8dee2aaSAndroid Build Coastguard Worker     }
setValues(int v)114*c8dee2aaSAndroid Build Coastguard Worker     void setValues(int v) override {
115*c8dee2aaSAndroid Build Coastguard Worker         fVoidStar = reinterpret_cast<void*>(static_cast<intptr_t>(v));
116*c8dee2aaSAndroid Build Coastguard Worker         this->INHERITED::setValues(v);
117*c8dee2aaSAndroid Build Coastguard Worker         fB->setValues(v);
118*c8dee2aaSAndroid Build Coastguard Worker     }
checkValues(int v)119*c8dee2aaSAndroid Build Coastguard Worker     bool checkValues(int v) override {
120*c8dee2aaSAndroid Build Coastguard Worker         return fVoidStar == reinterpret_cast<void*>(static_cast<intptr_t>(v)) &&
121*c8dee2aaSAndroid Build Coastguard Worker                fB->checkValues(v) &&
122*c8dee2aaSAndroid Build Coastguard Worker                this->INHERITED::checkValues(v);
123*c8dee2aaSAndroid Build Coastguard Worker     }
~D()124*c8dee2aaSAndroid Build Coastguard Worker     ~D() override {
125*c8dee2aaSAndroid Build Coastguard Worker         delete fB;
126*c8dee2aaSAndroid Build Coastguard Worker     }
127*c8dee2aaSAndroid Build Coastguard Worker private:
128*c8dee2aaSAndroid Build Coastguard Worker     void*   fVoidStar;
129*c8dee2aaSAndroid Build Coastguard Worker     B*      fB;
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = C;
132*c8dee2aaSAndroid Build Coastguard Worker };
133*c8dee2aaSAndroid Build Coastguard Worker 
134*c8dee2aaSAndroid Build Coastguard Worker class E : public A {
135*c8dee2aaSAndroid Build Coastguard Worker public:
E()136*c8dee2aaSAndroid Build Coastguard Worker     E() {}
setValues(int v)137*c8dee2aaSAndroid Build Coastguard Worker     void setValues(int v) override {
138*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0; i < std::size(fIntArray); ++i) {
139*c8dee2aaSAndroid Build Coastguard Worker             fIntArray[i] = v;
140*c8dee2aaSAndroid Build Coastguard Worker         }
141*c8dee2aaSAndroid Build Coastguard Worker         this->INHERITED::setValues(v);
142*c8dee2aaSAndroid Build Coastguard Worker     }
checkValues(int v)143*c8dee2aaSAndroid Build Coastguard Worker     bool checkValues(int v) override {
144*c8dee2aaSAndroid Build Coastguard Worker         bool ok = true;
145*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0; ok && i < std::size(fIntArray); ++i) {
146*c8dee2aaSAndroid Build Coastguard Worker             if (fIntArray[i] != v) {
147*c8dee2aaSAndroid Build Coastguard Worker                 ok = false;
148*c8dee2aaSAndroid Build Coastguard Worker             }
149*c8dee2aaSAndroid Build Coastguard Worker         }
150*c8dee2aaSAndroid Build Coastguard Worker         return ok && this->INHERITED::checkValues(v);
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker private:
153*c8dee2aaSAndroid Build Coastguard Worker     int   fIntArray[20];
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = A;
156*c8dee2aaSAndroid Build Coastguard Worker };
157*c8dee2aaSAndroid Build Coastguard Worker 
Create(SkRandom * r)158*c8dee2aaSAndroid Build Coastguard Worker A* A::Create(SkRandom* r) {
159*c8dee2aaSAndroid Build Coastguard Worker     switch (r->nextRangeU(0, 4)) {
160*c8dee2aaSAndroid Build Coastguard Worker         case 0:
161*c8dee2aaSAndroid Build Coastguard Worker             return new A;
162*c8dee2aaSAndroid Build Coastguard Worker         case 1:
163*c8dee2aaSAndroid Build Coastguard Worker             return new B;
164*c8dee2aaSAndroid Build Coastguard Worker         case 2:
165*c8dee2aaSAndroid Build Coastguard Worker             return new C;
166*c8dee2aaSAndroid Build Coastguard Worker         case 3:
167*c8dee2aaSAndroid Build Coastguard Worker             return new D;
168*c8dee2aaSAndroid Build Coastguard Worker         case 4:
169*c8dee2aaSAndroid Build Coastguard Worker             return new E;
170*c8dee2aaSAndroid Build Coastguard Worker         default:
171*c8dee2aaSAndroid Build Coastguard Worker             // suppress warning
172*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
173*c8dee2aaSAndroid Build Coastguard Worker     }
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker struct Rec {
177*c8dee2aaSAndroid Build Coastguard Worker     A* fInstance;
178*c8dee2aaSAndroid Build Coastguard Worker     int fValue;
179*c8dee2aaSAndroid Build Coastguard Worker };
180*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(GrMemoryPool,reporter)181*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(GrMemoryPool, reporter) {
182*c8dee2aaSAndroid Build Coastguard Worker     // prealloc and min alloc sizes for the pool
183*c8dee2aaSAndroid Build Coastguard Worker     static const size_t gSizes[][2] = {
184*c8dee2aaSAndroid Build Coastguard Worker         {0, 0},
185*c8dee2aaSAndroid Build Coastguard Worker         {10 * sizeof(A), 20 * sizeof(A)},
186*c8dee2aaSAndroid Build Coastguard Worker         {100 * sizeof(A), 100 * sizeof(A)},
187*c8dee2aaSAndroid Build Coastguard Worker         {500 * sizeof(A), 500 * sizeof(A)},
188*c8dee2aaSAndroid Build Coastguard Worker         {10000 * sizeof(A), 0},
189*c8dee2aaSAndroid Build Coastguard Worker         {1, 100 * sizeof(A)},
190*c8dee2aaSAndroid Build Coastguard Worker     };
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     // different percentages of creation vs deletion
193*c8dee2aaSAndroid Build Coastguard Worker     static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
194*c8dee2aaSAndroid Build Coastguard Worker     // number of create/destroys per test
195*c8dee2aaSAndroid Build Coastguard Worker     static const int kNumIters = 20000;
196*c8dee2aaSAndroid Build Coastguard Worker     // check that all the values stored in A objects are correct after this
197*c8dee2aaSAndroid Build Coastguard Worker     // number of iterations
198*c8dee2aaSAndroid Build Coastguard Worker     static const int kCheckPeriod = 500;
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     SkRandom r;
201*c8dee2aaSAndroid Build Coastguard Worker     for (size_t s = 0; s < std::size(gSizes); ++s) {
202*c8dee2aaSAndroid Build Coastguard Worker         A::SetAllocator(gSizes[s][0], gSizes[s][1]);
203*c8dee2aaSAndroid Build Coastguard Worker         A::ValidatePool();
204*c8dee2aaSAndroid Build Coastguard Worker         for (size_t c = 0; c < std::size(gCreateFraction); ++c) {
205*c8dee2aaSAndroid Build Coastguard Worker             SkTDArray<Rec> instanceRecs;
206*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < kNumIters; ++i) {
207*c8dee2aaSAndroid Build Coastguard Worker                 float createOrDestroy = r.nextUScalar1();
208*c8dee2aaSAndroid Build Coastguard Worker                 if (createOrDestroy < gCreateFraction[c] ||
209*c8dee2aaSAndroid Build Coastguard Worker                     0 == instanceRecs.size()) {
210*c8dee2aaSAndroid Build Coastguard Worker                     Rec* rec = instanceRecs.append();
211*c8dee2aaSAndroid Build Coastguard Worker                     rec->fInstance = A::Create(&r);
212*c8dee2aaSAndroid Build Coastguard Worker                     rec->fValue = static_cast<int>(r.nextU());
213*c8dee2aaSAndroid Build Coastguard Worker                     rec->fInstance->setValues(rec->fValue);
214*c8dee2aaSAndroid Build Coastguard Worker                 } else {
215*c8dee2aaSAndroid Build Coastguard Worker                     int d = r.nextRangeU(0, instanceRecs.size() - 1);
216*c8dee2aaSAndroid Build Coastguard Worker                     Rec& rec = instanceRecs[d];
217*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
218*c8dee2aaSAndroid Build Coastguard Worker                     delete rec.fInstance;
219*c8dee2aaSAndroid Build Coastguard Worker                     instanceRecs.removeShuffle(d);
220*c8dee2aaSAndroid Build Coastguard Worker                 }
221*c8dee2aaSAndroid Build Coastguard Worker                 if (0 == i % kCheckPeriod) {
222*c8dee2aaSAndroid Build Coastguard Worker                     A::ValidatePool();
223*c8dee2aaSAndroid Build Coastguard Worker                     for (Rec& rec : instanceRecs) {
224*c8dee2aaSAndroid Build Coastguard Worker                         REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
225*c8dee2aaSAndroid Build Coastguard Worker                     }
226*c8dee2aaSAndroid Build Coastguard Worker                 }
227*c8dee2aaSAndroid Build Coastguard Worker             }
228*c8dee2aaSAndroid Build Coastguard Worker             for (Rec& rec : instanceRecs) {
229*c8dee2aaSAndroid Build Coastguard Worker                 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
230*c8dee2aaSAndroid Build Coastguard Worker                 delete rec.fInstance;
231*c8dee2aaSAndroid Build Coastguard Worker             }
232*c8dee2aaSAndroid Build Coastguard Worker         }
233*c8dee2aaSAndroid Build Coastguard Worker     }
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker 
236*c8dee2aaSAndroid Build Coastguard Worker // GrMemoryPool requires that it's empty at the point of destruction. This helps
237*c8dee2aaSAndroid Build Coastguard Worker // achieving that by releasing all added memory in the destructor.
238*c8dee2aaSAndroid Build Coastguard Worker class AutoPoolReleaser {
239*c8dee2aaSAndroid Build Coastguard Worker public:
AutoPoolReleaser(GrMemoryPool & pool)240*c8dee2aaSAndroid Build Coastguard Worker     AutoPoolReleaser(GrMemoryPool& pool): fPool(pool) {
241*c8dee2aaSAndroid Build Coastguard Worker     }
~AutoPoolReleaser()242*c8dee2aaSAndroid Build Coastguard Worker     ~AutoPoolReleaser() {
243*c8dee2aaSAndroid Build Coastguard Worker         for (void* ptr: fAllocated) {
244*c8dee2aaSAndroid Build Coastguard Worker             fPool.release(ptr);
245*c8dee2aaSAndroid Build Coastguard Worker         }
246*c8dee2aaSAndroid Build Coastguard Worker     }
add(void * ptr)247*c8dee2aaSAndroid Build Coastguard Worker     void add(void* ptr) {
248*c8dee2aaSAndroid Build Coastguard Worker         fAllocated.push_back(ptr);
249*c8dee2aaSAndroid Build Coastguard Worker     }
250*c8dee2aaSAndroid Build Coastguard Worker private:
251*c8dee2aaSAndroid Build Coastguard Worker     GrMemoryPool& fPool;
252*c8dee2aaSAndroid Build Coastguard Worker     TArray<void*> fAllocated;
253*c8dee2aaSAndroid Build Coastguard Worker };
254*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(GrMemoryPoolAPI,reporter)255*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(GrMemoryPoolAPI, reporter) {
256*c8dee2aaSAndroid Build Coastguard Worker     constexpr size_t kSmallestMinAllocSize = GrMemoryPool::kMinAllocationSize;
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker     // Allocates memory until pool adds a new block (pool->size() changes).
259*c8dee2aaSAndroid Build Coastguard Worker     auto allocateMemory = [](GrMemoryPool& pool, AutoPoolReleaser& r) {
260*c8dee2aaSAndroid Build Coastguard Worker         size_t origPoolSize = pool.size();
261*c8dee2aaSAndroid Build Coastguard Worker         while (pool.size() == origPoolSize) {
262*c8dee2aaSAndroid Build Coastguard Worker             r.add(pool.allocate(31));
263*c8dee2aaSAndroid Build Coastguard Worker         }
264*c8dee2aaSAndroid Build Coastguard Worker     };
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker     // Effective prealloc space capacity is >= kMinAllocationSize.
267*c8dee2aaSAndroid Build Coastguard Worker     {
268*c8dee2aaSAndroid Build Coastguard Worker         auto pool = GrMemoryPool::Make(0, 0);
269*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->preallocSize() == kSmallestMinAllocSize);
270*c8dee2aaSAndroid Build Coastguard Worker     }
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker     // Effective block size capacity >= kMinAllocationSize.
273*c8dee2aaSAndroid Build Coastguard Worker     {
274*c8dee2aaSAndroid Build Coastguard Worker         auto pool = GrMemoryPool::Make(kSmallestMinAllocSize, kSmallestMinAllocSize / 2);
275*c8dee2aaSAndroid Build Coastguard Worker         AutoPoolReleaser r(*pool);
276*c8dee2aaSAndroid Build Coastguard Worker 
277*c8dee2aaSAndroid Build Coastguard Worker         allocateMemory(*pool, r);
278*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == kSmallestMinAllocSize);
279*c8dee2aaSAndroid Build Coastguard Worker     }
280*c8dee2aaSAndroid Build Coastguard Worker 
281*c8dee2aaSAndroid Build Coastguard Worker     // Pool allocates exactly preallocSize on creation.
282*c8dee2aaSAndroid Build Coastguard Worker     {
283*c8dee2aaSAndroid Build Coastguard Worker         constexpr size_t kPreallocSize = kSmallestMinAllocSize * 5;
284*c8dee2aaSAndroid Build Coastguard Worker         auto pool = GrMemoryPool::Make(kPreallocSize, 0);
285*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->preallocSize() == kPreallocSize);
286*c8dee2aaSAndroid Build Coastguard Worker     }
287*c8dee2aaSAndroid Build Coastguard Worker 
288*c8dee2aaSAndroid Build Coastguard Worker     // Pool allocates exactly minAllocSize when it expands.
289*c8dee2aaSAndroid Build Coastguard Worker     {
290*c8dee2aaSAndroid Build Coastguard Worker         constexpr size_t kMinAllocSize = kSmallestMinAllocSize * 7;
291*c8dee2aaSAndroid Build Coastguard Worker         auto pool = GrMemoryPool::Make(0, kMinAllocSize);
292*c8dee2aaSAndroid Build Coastguard Worker         AutoPoolReleaser r(*pool);
293*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == 0);
294*c8dee2aaSAndroid Build Coastguard Worker 
295*c8dee2aaSAndroid Build Coastguard Worker         allocateMemory(*pool, r);
296*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == kMinAllocSize);
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker         allocateMemory(*pool, r);
299*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == 2 * kMinAllocSize);
300*c8dee2aaSAndroid Build Coastguard Worker     }
301*c8dee2aaSAndroid Build Coastguard Worker 
302*c8dee2aaSAndroid Build Coastguard Worker     // When asked to allocate amount > minAllocSize, pool allocates larger block
303*c8dee2aaSAndroid Build Coastguard Worker     // to accommodate all internal structures.
304*c8dee2aaSAndroid Build Coastguard Worker     {
305*c8dee2aaSAndroid Build Coastguard Worker         constexpr size_t kMinAllocSize = kSmallestMinAllocSize * 2;
306*c8dee2aaSAndroid Build Coastguard Worker         auto pool = GrMemoryPool::Make(kSmallestMinAllocSize, kMinAllocSize);
307*c8dee2aaSAndroid Build Coastguard Worker         AutoPoolReleaser r(*pool);
308*c8dee2aaSAndroid Build Coastguard Worker 
309*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == 0);
310*c8dee2aaSAndroid Build Coastguard Worker 
311*c8dee2aaSAndroid Build Coastguard Worker         constexpr size_t hugeSize = 10 * kMinAllocSize;
312*c8dee2aaSAndroid Build Coastguard Worker         r.add(pool->allocate(hugeSize));
313*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() > hugeSize);
314*c8dee2aaSAndroid Build Coastguard Worker 
315*c8dee2aaSAndroid Build Coastguard Worker         // Block size allocated to accommodate huge request doesn't include any extra
316*c8dee2aaSAndroid Build Coastguard Worker         // space, so next allocation request allocates a new block.
317*c8dee2aaSAndroid Build Coastguard Worker         size_t hugeBlockSize = pool->size();
318*c8dee2aaSAndroid Build Coastguard Worker         r.add(pool->allocate(0));
319*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, pool->size() == hugeBlockSize + kMinAllocSize);
320*c8dee2aaSAndroid Build Coastguard Worker     }
321*c8dee2aaSAndroid Build Coastguard Worker }
322