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 "SkInstCnt.h"
     13 #include "SkRandom.h"
     14 #include "SkTDArray.h"
     15 #include "SkTemplates.h"
     16 
     17 // 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.
     20 class A {
     21 public:
     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 
     49     static A* Create(SkRandom* r);
     50 
     51     static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
     52 #if SK_ENABLE_INST_COUNT
     53         SkASSERT(0 == GetInstanceCount());
     54 #endif
     55         GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
     56         gPool.reset(pool);
     57     }
     58 
     59     static void ResetAllocator() {
     60 #if SK_ENABLE_INST_COUNT
     61         SkASSERT(0 == GetInstanceCount());
     62 #endif
     63         gPool.reset(NULL);
     64     }
     65 
     66 private:
     67     static SkAutoTDelete<GrMemoryPool> gPool;
     68     char fChar;
     69 };
     70 
     71 SkAutoTDelete<GrMemoryPool> A::gPool;
     72 
     73 class B : public A {
     74 public:
     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 
     86 private:
     87     double fDouble;
     88 
     89     typedef A INHERITED;
     90 };
     91 
     92 class C : public A {
     93 public:
     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 
    105 private:
    106     int64_t fInt64;
    107 
    108     typedef A INHERITED;
    109 };
    110 
    111 // D derives from C and owns a dynamically created B
    112 class D : public C {
    113 public:
    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     }
    130 private:
    131     void*   fVoidStar;
    132     B*      fB;
    133 
    134     typedef C INHERITED;
    135 };
    136 
    137 class E : public A {
    138 public:
    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() {}
    156 private:
    157     int   fIntArray[20];
    158 
    159     typedef A INHERITED;
    160 };
    161 
    162 A* A::Create(SkRandom* r) {
    163     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 }
    179 
    180 struct Rec {
    181     A* fInstance;
    182     int fValue;
    183 };
    184 
    185 DEF_TEST(GrMemoryPool, reporter) {
    186     // 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 
    203     SkRandom r;
    204     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             }
    235 #if SK_ENABLE_INST_COUNT
    236             REPORTER_ASSERT(reporter, !A::GetInstanceCount());
    237 #endif
    238         }
    239     }
    240 }
    241 
    242 #endif
    243