Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2014 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 "SkMatrix.h"
      9 #include "SkRandom.h"
     10 #include "SkString.h"
     11 #include "Test.h"
     12 
     13 #if SK_SUPPORT_GPU
     14 
     15 #include "GrTRecorder.h"
     16 
     17 ////////////////////////////////////////////////////////////////////////////////
     18 
     19 static int activeRecorderItems = 0;
     20 
     21 class IntWrapper {
     22 public:
     23     IntWrapper() {}
     24     IntWrapper(int value) : fValue(value) {}
     25     operator int() { return fValue; }
     26 private:
     27     int fValue;
     28 };
     29 
     30 static void test_empty_back_and_pop(skiatest::Reporter* reporter) {
     31     SkRandom rand;
     32     for (int data = 0; data < 2; ++data) {
     33         // Do this with different starting sizes to have different alignment between blocks and pops.
     34         // pops. We want to test poping the first guy off, guys in the middle of the block, and the
     35         // first guy on a non-head block.
     36         for (int j = 0; j < 8; ++j) {
     37             GrTRecorder<IntWrapper, int> recorder(j);
     38 
     39             REPORTER_ASSERT(reporter, recorder.empty());
     40 
     41             for (int i = 0; i < 100; ++i) {
     42                 if (data) {
     43                     REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder,
     44                                                                              IntWrapper, (i)));
     45                 } else {
     46                     REPORTER_ASSERT(reporter, i ==
     47                                     *GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder,
     48                                                                         IntWrapper, (i),
     49                                                                         rand.nextULessThan(10)));
     50                 }
     51                 REPORTER_ASSERT(reporter, !recorder.empty());
     52                 REPORTER_ASSERT(reporter, i == recorder.back());
     53                 if (0 == (i % 7)) {
     54                     recorder.pop_back();
     55                     if (i > 0) {
     56                         REPORTER_ASSERT(reporter, !recorder.empty());
     57                         REPORTER_ASSERT(reporter, i-1 == recorder.back());
     58                     }
     59                 }
     60             }
     61 
     62             REPORTER_ASSERT(reporter, !recorder.empty());
     63             recorder.reset();
     64             REPORTER_ASSERT(reporter, recorder.empty());
     65         }
     66     }
     67 }
     68 
     69 struct ExtraData {
     70     typedef GrTRecorder<ExtraData, int> Recorder;
     71 
     72     ExtraData(int i) : fData(i) {
     73         int* extraData = this->extraData();
     74         for (int j = 0; j < i; j++) {
     75             extraData[j] = i;
     76         }
     77         ++activeRecorderItems;
     78     }
     79     ~ExtraData() {
     80         --activeRecorderItems;
     81     }
     82     int* extraData() {
     83         return reinterpret_cast<int*>(Recorder::GetDataForItem(this));
     84     }
     85     int fData;
     86 };
     87 
     88 static void test_extra_data(skiatest::Reporter* reporter) {
     89     ExtraData::Recorder recorder(0);
     90     for (int i = 0; i < 100; ++i) {
     91         GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int));
     92     }
     93     REPORTER_ASSERT(reporter, 100 == activeRecorderItems);
     94 
     95     ExtraData::Recorder::Iter iter(recorder);
     96     for (int i = 0; i < 100; ++i) {
     97         REPORTER_ASSERT(reporter, iter.next());
     98         REPORTER_ASSERT(reporter, i == iter->fData);
     99         for (int j = 0; j < i; j++) {
    100             REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
    101         }
    102     }
    103     REPORTER_ASSERT(reporter, !iter.next());
    104 
    105     ExtraData::Recorder::ReverseIter reverseIter(recorder);
    106     for (int i = 99; i >= 0; --i) {
    107         REPORTER_ASSERT(reporter, i == reverseIter->fData);
    108         for (int j = 0; j < i; j++) {
    109             REPORTER_ASSERT(reporter, i == reverseIter->extraData()[j]);
    110         }
    111         REPORTER_ASSERT(reporter, reverseIter.previous() == !!i);
    112     }
    113 
    114     recorder.reset();
    115     REPORTER_ASSERT(reporter, 0 == activeRecorderItems);
    116 }
    117 
    118 enum ClassType {
    119     kBase_ClassType,
    120     kSubclass_ClassType,
    121     kSubSubclass_ClassType,
    122     kSubclassExtraData_ClassType,
    123     kSubclassEmpty_ClassType,
    124 
    125     kNumClassTypes
    126 };
    127 
    128 class Base {
    129 public:
    130     typedef GrTRecorder<Base, void*> Recorder;
    131 
    132     Base() {
    133         fMatrix.reset();
    134         ++activeRecorderItems;
    135     }
    136 
    137     virtual ~Base() { --activeRecorderItems; }
    138 
    139     virtual ClassType getType() { return kBase_ClassType; }
    140 
    141     virtual void validate(skiatest::Reporter* reporter) const {
    142         REPORTER_ASSERT(reporter, fMatrix.isIdentity());
    143     }
    144 
    145 private:
    146     SkMatrix fMatrix;
    147 };
    148 
    149 class Subclass : public Base {
    150 public:
    151     Subclass() : fString("Lorem ipsum dolor sit amet") {}
    152 
    153     virtual ClassType getType() { return kSubclass_ClassType; }
    154 
    155     virtual void validate(skiatest::Reporter* reporter) const {
    156         Base::validate(reporter);
    157         REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str()));
    158     }
    159 
    160 private:
    161     SkString fString;
    162 };
    163 
    164 class SubSubclass : public Subclass {
    165 public:
    166     SubSubclass() : fInt(1234), fFloat(1.234f) {}
    167 
    168     virtual ClassType getType() { return kSubSubclass_ClassType; }
    169 
    170     virtual void validate(skiatest::Reporter* reporter) const {
    171         Subclass::validate(reporter);
    172         REPORTER_ASSERT(reporter, 1234 == fInt);
    173         REPORTER_ASSERT(reporter, 1.234f == fFloat);
    174     }
    175 
    176 private:
    177     int fInt;
    178     float fFloat;
    179 };
    180 
    181 class SubclassExtraData : public Base {
    182 public:
    183     SubclassExtraData(int length) : fLength(length) {
    184         int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this));
    185         for (int i = 0; i < fLength; ++i) {
    186             data[i] = ValueAt(i);
    187         }
    188     }
    189 
    190     virtual ClassType getType() { return kSubclassExtraData_ClassType; }
    191 
    192     virtual void validate(skiatest::Reporter* reporter) const {
    193         Base::validate(reporter);
    194         const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this));
    195         for (int i = 0; i < fLength; ++i) {
    196             REPORTER_ASSERT(reporter, ValueAt(i) == data[i]);
    197         }
    198     }
    199 
    200 private:
    201     static int ValueAt(uint64_t i) { return static_cast<int>(123456789 + 987654321 * i); }
    202     int fLength;
    203 };
    204 
    205 class SubclassEmpty : public Base {
    206 public:
    207     virtual ClassType getType() { return kSubclassEmpty_ClassType; }
    208 };
    209 
    210 class Order {
    211 public:
    212     Order() { this->reset(); }
    213     void reset() { fCurrent = 0; }
    214     ClassType next() {
    215         fCurrent = 1664525 * fCurrent + 1013904223;
    216         return static_cast<ClassType>(fCurrent % kNumClassTypes);
    217     }
    218 private:
    219     uint32_t fCurrent;
    220 };
    221 static void test_subclasses_iters(skiatest::Reporter*, Order&, Base::Recorder::Iter&,
    222                                   Base::Recorder::ReverseIter&, int = 0);
    223 static void test_subclasses(skiatest::Reporter* reporter) {
    224     Base::Recorder recorder(1024);
    225 
    226     Order order;
    227     for (int i = 0; i < 1000; i++) {
    228         switch (order.next()) {
    229             case kBase_ClassType:
    230                 GrNEW_APPEND_TO_RECORDER(recorder, Base, ());
    231                 break;
    232 
    233             case kSubclass_ClassType:
    234                 GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ());
    235                 break;
    236 
    237             case kSubSubclass_ClassType:
    238                 GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ());
    239                 break;
    240 
    241             case kSubclassExtraData_ClassType:
    242                 GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i);
    243                 break;
    244 
    245             case kSubclassEmpty_ClassType:
    246                 GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ());
    247                 break;
    248 
    249             default:
    250                 ERRORF(reporter, "Invalid class type");
    251                 break;
    252         }
    253     }
    254     REPORTER_ASSERT(reporter, 1000 == activeRecorderItems);
    255 
    256     order.reset();
    257     Base::Recorder::Iter iter(recorder);
    258     Base::Recorder::ReverseIter reverseIter(recorder);
    259 
    260     test_subclasses_iters(reporter, order, iter, reverseIter);
    261 
    262     REPORTER_ASSERT(reporter, !iter.next());
    263 
    264     // Don't reset the recorder. It should automatically destruct all its items.
    265 }
    266 static void test_subclasses_iters(skiatest::Reporter* reporter, Order& order,
    267                                   Base::Recorder::Iter& iter,
    268                                   Base::Recorder::ReverseIter& reverseIter, int i) {
    269     if (i >= 1000) {
    270         return;
    271     }
    272 
    273     ClassType classType = order.next();
    274 
    275     REPORTER_ASSERT(reporter, iter.next());
    276     REPORTER_ASSERT(reporter, classType == iter->getType());
    277     iter->validate(reporter);
    278 
    279     test_subclasses_iters(reporter, order, iter, reverseIter, i + 1);
    280 
    281     REPORTER_ASSERT(reporter, classType == reverseIter->getType());
    282     reverseIter->validate(reporter);
    283     REPORTER_ASSERT(reporter, reverseIter.previous() == !!i);
    284 }
    285 
    286 DEF_GPUTEST(GrTRecorder, reporter, /* options */) {
    287     test_empty_back_and_pop(reporter);
    288 
    289     test_extra_data(reporter);
    290     REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset().
    291 
    292     test_subclasses(reporter);
    293     REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors.
    294 }
    295 
    296 #endif
    297