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 "SkTScopedPtr.h"
     15 #include "SkInstCnt.h"
     16 
     17 namespace {
     18 // A is the top of an inheritance tree of classes that overload op new and
     19 // and delete to use a GrMemoryPool. The objects have values of different types
     20 // that can be set and checked.
     21 class A {
     22 public:
     23     A() {};
     24     virtual void setValues(int v) {
     25         fChar = static_cast<char>(v);
     26     }
     27     virtual bool checkValues(int v) {
     28         return fChar == static_cast<char>(v);
     29     }
     30     virtual ~A() {};
     31 
     32     void* operator new(size_t size) {
     33         if (!gPool.get()) {
     34             return ::operator new(size);
     35         } else {
     36             return gPool->allocate(size);
     37         }
     38     }
     39 
     40     void operator delete(void* p) {
     41         if (!gPool.get()) {
     42             ::operator delete(p);
     43         } else {
     44             return gPool->release(p);
     45         }
     46     }
     47 
     48     SK_DECLARE_INST_COUNT_ROOT(A);
     49 
     50     static A* Create(SkRandom* r);
     51 
     52     static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
     53 #if SK_ENABLE_INST_COUNT
     54         SkASSERT(0 == GetInstanceCount());
     55 #endif
     56         GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
     57         gPool.reset(pool);
     58     }
     59 
     60     static void ResetAllocator() {
     61 #if SK_ENABLE_INST_COUNT
     62         SkASSERT(0 == GetInstanceCount());
     63 #endif
     64         gPool.reset(NULL);
     65     }
     66 
     67 private:
     68     static SkTScopedPtr<GrMemoryPool> gPool;
     69     char fChar;
     70 };
     71 SK_DEFINE_INST_COUNT(A);
     72 SkTScopedPtr<GrMemoryPool> A::gPool;
     73 
     74 class B : public A {
     75 public:
     76     B() {};
     77     virtual void setValues(int v) {
     78         fDouble = static_cast<double>(v);
     79         this->INHERITED::setValues(v);
     80     }
     81     virtual bool checkValues(int v) {
     82         return fDouble == static_cast<double>(v) &&
     83                this->INHERITED::checkValues(v);
     84     }
     85     virtual ~B() {};
     86 
     87 private:
     88     double fDouble;
     89 
     90     typedef A INHERITED;
     91 };
     92 
     93 class C : public A {
     94 public:
     95     C() {};
     96     virtual void setValues(int v) {
     97         fInt64 = static_cast<int64_t>(v);
     98         this->INHERITED::setValues(v);
     99     }
    100     virtual bool checkValues(int v) {
    101         return fInt64 == static_cast<int64_t>(v) &&
    102                this->INHERITED::checkValues(v);
    103     }
    104     virtual ~C() {};
    105 
    106 private:
    107     int64_t fInt64;
    108 
    109     typedef A INHERITED;
    110 };
    111 
    112 // D derives from C and owns a dynamically created B
    113 class D : public C {
    114 public:
    115     D() {
    116         fB = new B();
    117     }
    118     virtual void setValues(int v) {
    119         fVoidStar = reinterpret_cast<void*>(v);
    120         this->INHERITED::setValues(v);
    121         fB->setValues(v);
    122     }
    123     virtual bool checkValues(int v) {
    124         return fVoidStar == reinterpret_cast<void*>(v) &&
    125                fB->checkValues(v) &&
    126                this->INHERITED::checkValues(v);
    127     }
    128     virtual ~D() {
    129         delete fB;
    130     }
    131 private:
    132     void*   fVoidStar;
    133     B*      fB;
    134 
    135     typedef C INHERITED;
    136 };
    137 
    138 class E : public A {
    139 public:
    140     E() {}
    141     virtual void setValues(int v) {
    142         for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) {
    143             fIntArray[i] = v;
    144         }
    145         this->INHERITED::setValues(v);
    146     }
    147     virtual bool checkValues(int v) {
    148         bool ok = true;
    149         for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) {
    150             if (fIntArray[i] != v) {
    151                 ok = false;
    152             }
    153         }
    154         return ok && this->INHERITED::checkValues(v);
    155     }
    156     virtual ~E() {}
    157 private:
    158     int   fIntArray[20];
    159 
    160     typedef A INHERITED;
    161 };
    162 
    163 A* A::Create(SkRandom* r) {
    164     switch (r->nextRangeU(0, 4)) {
    165         case 0:
    166             return new A;
    167         case 1:
    168             return new B;
    169         case 2:
    170             return new C;
    171         case 3:
    172             return new D;
    173         case 4:
    174             return new E;
    175         default:
    176             // suppress warning
    177             return NULL;
    178     }
    179 }
    180 }
    181 struct Rec {
    182     A* fInstance;
    183     int fValue;
    184 };
    185 
    186 static void test_memory_pool(skiatest::Reporter* reporter) {
    187     // prealloc and min alloc sizes for the pool
    188     static const size_t gSizes[][2] = {
    189         {0, 0},
    190         {10 * sizeof(A), 20 * sizeof(A)},
    191         {100 * sizeof(A), 100 * sizeof(A)},
    192         {500 * sizeof(A), 500 * sizeof(A)},
    193         {10000 * sizeof(A), 0},
    194         {1, 100 * sizeof(A)},
    195     };
    196     // different percentages of creation vs deletion
    197     static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
    198     // number of create/destroys per test
    199     static const int kNumIters = 20000;
    200     // check that all the values stored in A objects are correct after this
    201     // number of iterations
    202     static const int kCheckPeriod = 500;
    203 
    204     SkRandom r;
    205     for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) {
    206         A::SetAllocator(gSizes[s][0], gSizes[s][1]);
    207         for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) {
    208             SkTDArray<Rec> instanceRecs;
    209             for (int i = 0; i < kNumIters; ++i) {
    210                 float createOrDestroy = r.nextUScalar1();
    211                 if (createOrDestroy < gCreateFraction[c] ||
    212                     0 == instanceRecs.count()) {
    213                     Rec* rec = instanceRecs.append();
    214                     rec->fInstance = A::Create(&r);
    215                     rec->fValue = static_cast<int>(r.nextU());
    216                     rec->fInstance->setValues(rec->fValue);
    217                 } else {
    218                     int d = r.nextRangeU(0, instanceRecs.count() - 1);
    219                     Rec& rec = instanceRecs[d];
    220                     REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
    221                     delete rec.fInstance;
    222                     instanceRecs.removeShuffle(d);
    223                 }
    224                 if (0 == i % kCheckPeriod) {
    225                     for (int r = 0; r < instanceRecs.count(); ++r) {
    226                         Rec& rec = instanceRecs[r];
    227                         REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
    228                     }
    229                 }
    230             }
    231             for (int i = 0; i < instanceRecs.count(); ++i) {
    232                 Rec& rec = instanceRecs[i];
    233                 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
    234                 delete rec.fInstance;
    235             }
    236 #if SK_ENABLE_INST_COUNT
    237             REPORTER_ASSERT(reporter, !A::GetInstanceCount());
    238 #endif
    239         }
    240     }
    241 }
    242 
    243 #include "TestClassDef.h"
    244 DEFINE_TESTCLASS("GrMemoryPool", GrMemoryPoolClass, test_memory_pool)
    245 
    246 #endif
    247