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 "SkBenchmark.h"
9#include "SkFloatBits.h"
10#include "SkRandom.h"
11#include "SkRect.h"
12#include "SkString.h"
13
14class ScalarBench : public SkBenchmark {
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 SkBenchmark INHERITED;
42};
43
44// we want to stop the compiler from eliminating code that it thinks is a no-op
45// so we have a non-static global we increment, hoping that will convince the
46// compiler to execute everything
47int gScalarBench_NonStaticGlobal;
48
49#define always_do(pred)                     \
50    do {                                    \
51        if (pred) {                         \
52            ++gScalarBench_NonStaticGlobal; \
53        }                                   \
54    } while (0)
55
56// having unknown values in our arrays can throw off the timing a lot, perhaps
57// handling NaN values is a lot slower. Anyway, this guy is just meant to put
58// reasonable values in our arrays.
59template <typename T> void init9(T array[9]) {
60    SkRandom rand;
61    for (int i = 0; i < 9; i++) {
62        array[i] = rand.nextSScalar1();
63    }
64}
65
66class FloatComparisonBench : public ScalarBench {
67public:
68    FloatComparisonBench() : INHERITED("compare_float") {
69        init9(fArray);
70    }
71protected:
72    virtual int mulLoopCount() const { return 4; }
73    virtual void performTest() {
74        always_do(fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f);
75        always_do(fArray[2] != 0.0f || fArray[5] != 0.0f);
76    }
77private:
78    float fArray[9];
79    typedef ScalarBench INHERITED;
80};
81
82class ForcedIntComparisonBench : public ScalarBench {
83public:
84    ForcedIntComparisonBench()
85    : INHERITED("compare_forced_int") {
86        init9(fArray);
87    }
88protected:
89    virtual int mulLoopCount() const { return 4; }
90    virtual void performTest() {
91        always_do(SkScalarAs2sCompliment(fArray[6]) |
92                  SkScalarAs2sCompliment(fArray[7]) |
93                  (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int));
94        always_do(SkScalarAs2sCompliment(fArray[2]) |
95                  SkScalarAs2sCompliment(fArray[5]));
96    }
97private:
98    static const int32_t kPersp1Int = 0x3f800000;
99    SkScalar fArray[9];
100    typedef ScalarBench INHERITED;
101};
102
103class IsFiniteScalarBench : public ScalarBench {
104public:
105    IsFiniteScalarBench() : INHERITED("isfinite") {
106        SkRandom rand;
107        for (size_t i = 0; i < ARRAY_N; ++i) {
108            fArray[i] = rand.nextSScalar1();
109        }
110    }
111protected:
112    virtual int mulLoopCount() const { return 1; }
113    virtual void performTest() SK_OVERRIDE {
114        int sum = 0;
115        for (size_t i = 0; i < ARRAY_N; ++i) {
116            // We pass -fArray[i], so the compiler can't cheat and treat the
117            // value as an int (even though we tell it that it is a float)
118            sum += SkScalarIsFinite(-fArray[i]);
119        }
120        // we do this so the compiler won't optimize our loop away...
121        this->doSomething(fArray, sum);
122    }
123
124    virtual void doSomething(SkScalar array[], int sum) {}
125private:
126    enum {
127        ARRAY_N = 64
128    };
129    SkScalar fArray[ARRAY_N];
130
131    typedef ScalarBench INHERITED;
132};
133
134///////////////////////////////////////////////////////////////////////////////
135
136class RectBoundsBench : public SkBenchmark {
137    enum {
138        PTS = 100,
139    };
140    SkPoint fPts[PTS];
141
142public:
143    RectBoundsBench() {
144        SkRandom rand;
145        for (int i = 0; i < PTS; ++i) {
146            fPts[i].fX = rand.nextSScalar1();
147            fPts[i].fY = rand.nextSScalar1();
148        }
149    }
150
151    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
152        return backend == kNonRendering_Backend;
153    }
154
155protected:
156    virtual const char* onGetName() SK_OVERRIDE {
157        return "rect_bounds";
158    }
159
160    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
161        SkRect r;
162        for (int i = 0; i < loops; ++i) {
163            r.set(fPts, PTS);
164        }
165    }
166
167private:
168    typedef SkBenchmark INHERITED;
169};
170
171///////////////////////////////////////////////////////////////////////////////
172
173DEF_BENCH( return new FloatComparisonBench(); )
174DEF_BENCH( return new ForcedIntComparisonBench(); )
175DEF_BENCH( return new RectBoundsBench(); )
176DEF_BENCH( return new IsFiniteScalarBench(); )
177