1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "Benchmark.h"
9#include "SkFloatBits.h"
10#include "SkRandom.h"
11#include "SkRect.h"
12#include "SkString.h"
13
14class ScalarBench : public Benchmark {
15    SkString    fName;
16public:
17    ScalarBench(const char name[])  {
18        fName.printf("scalar_%s", name);
19    }
20
21    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
22        return backend == kNonRendering_Backend;
23    }
24
25    virtual void performTest() = 0;
26
27protected:
28    virtual int mulLoopCount() const { return 1; }
29
30    virtual const char* onGetName() SK_OVERRIDE {
31        return fName.c_str();
32    }
33
34    virtual void onDraw(const int loops, SkCanvas* canvas) {
35        for (int i = 0; i < loops; i++) {
36            this->performTest();
37        }
38    }
39
40private:
41    typedef Benchmark INHERITED;
42};
43
44// having unknown values in our arrays can throw off the timing a lot, perhaps
45// handling NaN values is a lot slower. Anyway, this guy is just meant to put
46// reasonable values in our arrays.
47template <typename T> void init9(T array[9]) {
48    SkRandom rand;
49    for (int i = 0; i < 9; i++) {
50        array[i] = rand.nextSScalar1();
51    }
52}
53
54class FloatComparisonBench : public ScalarBench {
55public:
56    FloatComparisonBench() : INHERITED("compare_float") {
57        init9(fArray);
58    }
59protected:
60    virtual int mulLoopCount() const { return 4; }
61    virtual void performTest() {
62        // xoring into a volatile prevents the compiler from optimizing these checks away.
63        volatile bool junk = false;
64        junk ^= (fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f);
65        junk ^= (fArray[2] != 0.0f || fArray[5] != 0.0f);
66    }
67private:
68    float fArray[9];
69    typedef ScalarBench INHERITED;
70};
71
72class ForcedIntComparisonBench : public ScalarBench {
73public:
74    ForcedIntComparisonBench()
75    : INHERITED("compare_forced_int") {
76        init9(fArray);
77    }
78protected:
79    virtual int mulLoopCount() const { return 4; }
80    virtual void performTest() {
81        // xoring into a volatile prevents the compiler from optimizing these checks away.
82        volatile int32_t junk = 0;
83        junk ^= (SkScalarAs2sCompliment(fArray[6]) |
84                 SkScalarAs2sCompliment(fArray[7]) |
85                (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int));
86        junk ^= (SkScalarAs2sCompliment(fArray[2]) |
87                 SkScalarAs2sCompliment(fArray[5]));
88    }
89private:
90    static const int32_t kPersp1Int = 0x3f800000;
91    SkScalar fArray[9];
92    typedef ScalarBench INHERITED;
93};
94
95class IsFiniteScalarBench : public ScalarBench {
96public:
97    IsFiniteScalarBench() : INHERITED("isfinite") {
98        SkRandom rand;
99        for (size_t i = 0; i < ARRAY_N; ++i) {
100            fArray[i] = rand.nextSScalar1();
101        }
102    }
103protected:
104    virtual int mulLoopCount() const { return 1; }
105    virtual void performTest() SK_OVERRIDE {
106        int sum = 0;
107        for (size_t i = 0; i < ARRAY_N; ++i) {
108            // We pass -fArray[i], so the compiler can't cheat and treat the
109            // value as an int (even though we tell it that it is a float)
110            sum += SkScalarIsFinite(-fArray[i]);
111        }
112        // we do this so the compiler won't optimize our loop away...
113        this->doSomething(fArray, sum);
114    }
115
116    virtual void doSomething(SkScalar array[], int sum) {}
117private:
118    enum {
119        ARRAY_N = 64
120    };
121    SkScalar fArray[ARRAY_N];
122
123    typedef ScalarBench INHERITED;
124};
125
126///////////////////////////////////////////////////////////////////////////////
127
128class RectBoundsBench : public Benchmark {
129    enum {
130        PTS = 100,
131    };
132    SkPoint fPts[PTS];
133
134public:
135    RectBoundsBench() {
136        SkRandom rand;
137        for (int i = 0; i < PTS; ++i) {
138            fPts[i].fX = rand.nextSScalar1();
139            fPts[i].fY = rand.nextSScalar1();
140        }
141    }
142
143    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
144        return backend == kNonRendering_Backend;
145    }
146
147protected:
148    virtual const char* onGetName() SK_OVERRIDE {
149        return "rect_bounds";
150    }
151
152    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
153        SkRect r;
154        for (int i = 0; i < loops; ++i) {
155            r.set(fPts, PTS);
156        }
157    }
158
159private:
160    typedef Benchmark INHERITED;
161};
162
163///////////////////////////////////////////////////////////////////////////////
164
165DEF_BENCH( return new FloatComparisonBench(); )
166DEF_BENCH( return new ForcedIntComparisonBench(); )
167DEF_BENCH( return new RectBoundsBench(); )
168DEF_BENCH( return new IsFiniteScalarBench(); )
169