Home | History | Annotate | Download | only in tests
      1 /*
      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 
      8 #include "Test.h"
      9 // This is a GPU-backend specific test
     10 #if SK_SUPPORT_GPU
     11 #include "GrMemoryPool.h"
     12 #include "SkRandom.h"
     13 #include "SkTDArray.h"
     14 #include "SkTemplates.h"
     15 
     16 // 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.
     19 class A {
     20 public:
     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 
     46     static A* Create(SkRandom* r);
     47 
     48     static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
     49         GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
     50         gPool.reset(pool);
     51     }
     52 
     53     static void ResetAllocator() {
     54         gPool.reset(nullptr);
     55     }
     56 
     57 private:
     58     static SkAutoTDelete<GrMemoryPool> gPool;
     59     char fChar;
     60 };
     61 
     62 SkAutoTDelete<GrMemoryPool> A::gPool;
     63 
     64 class B : public A {
     65 public:
     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 
     77 private:
     78     double fDouble;
     79 
     80     typedef A INHERITED;
     81 };
     82 
     83 class C : public A {
     84 public:
     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 
     96 private:
     97     int64_t fInt64;
     98 
     99     typedef A INHERITED;
    100 };
    101 
    102 // D derives from C and owns a dynamically created B
    103 class D : public C {
    104 public:
    105     D() {
    106         fB = new B();
    107     }
    108     virtual void setValues(int v) {
    109         fVoidStar = reinterpret_cast<void*>(static_cast<intptr_t>(v));
    110         this->INHERITED::setValues(v);
    111         fB->setValues(v);
    112     }
    113     virtual bool checkValues(int v) {
    114         return fVoidStar == reinterpret_cast<void*>(static_cast<intptr_t>(v)) &&
    115                fB->checkValues(v) &&
    116                this->INHERITED::checkValues(v);
    117     }
    118     virtual ~D() {
    119         delete fB;
    120     }
    121 private:
    122     void*   fVoidStar;
    123     B*      fB;
    124 
    125     typedef C INHERITED;
    126 };
    127 
    128 class E : public A {
    129 public:
    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() {}
    147 private:
    148     int   fIntArray[20];
    149 
    150     typedef A INHERITED;
    151 };
    152 
    153 A* A::Create(SkRandom* r) {
    154     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
    167             return nullptr;
    168     }
    169 }
    170 
    171 struct Rec {
    172     A* fInstance;
    173     int fValue;
    174 };
    175 
    176 DEF_TEST(GrMemoryPool, reporter) {
    177     // 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 
    194     SkRandom r;
    195     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             }
    226         }
    227     }
    228 }
    229 
    230 #endif
    231