1/*
2 * Copyright 2015 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 "Benchmark.h"
9#include "SkColorData.h"
10#include "SkFixed.h"
11#include "SkMatrix.h"
12#include "SkPaint.h"
13#include "SkRandom.h"
14#include "SkString.h"
15
16#define TILE(x, width)  (((x) & 0xFFFF) * width >> 16)
17
18class InterpBench : public Benchmark {
19    enum {
20        kBuffer = 128,
21        kLoop   = 20000
22    };
23    SkString    fName;
24    int16_t     fDst[kBuffer];
25    float       fFx, fDx;
26public:
27    InterpBench(const char name[])  {
28        fName.printf("interp_%s", name);
29        fFx = 3.3f;
30        fDx = 0.1257f;
31    }
32
33    bool isSuitableFor(Backend backend) override {
34        return backend == kNonRendering_Backend;
35    }
36
37    virtual void performTest(int16_t dst[], float x, float dx, int count) = 0;
38
39protected:
40    virtual int mulLoopCount() const { return 1; }
41
42    const char* onGetName() override {
43        return fName.c_str();
44    }
45
46    void onDraw(int loops, SkCanvas*) override {
47        int n = loops * this->mulLoopCount();
48        for (int i = 0; i < n; i++) {
49            this->performTest(fDst, fFx, fDx, kBuffer);
50        }
51    }
52
53private:
54    typedef Benchmark INHERITED;
55};
56
57class Fixed16D16Interp : public InterpBench {
58public:
59    Fixed16D16Interp() : INHERITED("16.16") {}
60
61protected:
62    void performTest(int16_t dst[], float fx, float dx, int count) override {
63        SkFixed curr = SkFloatToFixed(fx);
64        SkFixed step = SkFloatToFixed(dx);
65        for (int i = 0; i < count; i += 4) {
66            dst[i + 0] = TILE(curr, count); curr += step;
67            dst[i + 1] = TILE(curr, count); curr += step;
68            dst[i + 2] = TILE(curr, count); curr += step;
69            dst[i + 3] = TILE(curr, count); curr += step;
70        }
71    }
72private:
73    typedef InterpBench INHERITED;
74};
75
76class Fixed32D32Interp : public InterpBench {
77public:
78    Fixed32D32Interp() : INHERITED("32.32") {}
79
80protected:
81    void performTest(int16_t dst[], float fx, float dx, int count) override {
82        int64_t curr = (int64_t)(fx * 65536 * 655536);
83        int64_t step = (int64_t)(dx * 65536 * 655536);
84        SkFixed tmp;
85        for (int i = 0; i < count; i += 4) {
86            tmp = (SkFixed)(curr >> 16);
87            dst[i + 0] = TILE(tmp, count);
88            curr += step;
89
90            tmp = (SkFixed)(curr >> 16);
91            dst[i + 1] = TILE(tmp, count);
92            curr += step;
93
94            tmp = (SkFixed)(curr >> 16);
95            dst[i + 2] = TILE(tmp, count);
96            curr += step;
97
98            tmp = (SkFixed)(curr >> 16);
99            dst[i + 3] = TILE(tmp, count);
100            curr += step;
101        }
102    }
103private:
104    typedef InterpBench INHERITED;
105};
106
107class Fixed16D48Interp : public InterpBench {
108public:
109    Fixed16D48Interp() : INHERITED("16.48") {}
110
111protected:
112    void performTest(int16_t dst[], float fx, float dx, int count) override {
113        int64_t curr = (int64_t)(fx * 65536 * 655536 * 65536);
114        int64_t step = (int64_t)(dx * 65536 * 655536 * 65536);
115        SkFixed tmp;
116        for (int i = 0; i < count; i += 4) {
117            tmp = (SkFixed) (curr >> 32); dst[i + 0] = TILE(tmp, count); curr += step;
118            tmp = (SkFixed) (curr >> 32); dst[i + 1] = TILE(tmp, count); curr += step;
119            tmp = (SkFixed) (curr >> 32); dst[i + 2] = TILE(tmp, count); curr += step;
120            tmp = (SkFixed) (curr >> 32); dst[i + 3] = TILE(tmp, count); curr += step;
121        }
122    }
123private:
124    typedef InterpBench INHERITED;
125};
126
127class FloatInterp : public InterpBench {
128public:
129    FloatInterp() : INHERITED("float") {}
130
131protected:
132    void performTest(int16_t dst[], float fx, float dx, int count) override {
133        SkFixed tmp;
134        for (int i = 0; i < count; i += 4) {
135            tmp = SkFloatToFixed(fx); dst[i + 0] = TILE(tmp, count); fx += dx;
136            tmp = SkFloatToFixed(fx); dst[i + 1] = TILE(tmp, count); fx += dx;
137            tmp = SkFloatToFixed(fx); dst[i + 2] = TILE(tmp, count); fx += dx;
138            tmp = SkFloatToFixed(fx); dst[i + 3] = TILE(tmp, count); fx += dx;
139        }
140    }
141private:
142    typedef InterpBench INHERITED;
143};
144
145class DoubleInterp : public InterpBench {
146public:
147    DoubleInterp() : INHERITED("double") {}
148
149protected:
150    void performTest(int16_t dst[], float fx, float dx, int count) override {
151        double ffx = fx;
152        double ddx = dx;
153        SkFixed tmp;
154        for (int i = 0; i < count; i += 4) {
155            tmp = SkDoubleToFixed(ffx); dst[i + 0] = TILE(tmp, count); ffx += ddx;
156            tmp = SkDoubleToFixed(ffx); dst[i + 1] = TILE(tmp, count); ffx += ddx;
157            tmp = SkDoubleToFixed(ffx); dst[i + 2] = TILE(tmp, count); ffx += ddx;
158            tmp = SkDoubleToFixed(ffx); dst[i + 3] = TILE(tmp, count); ffx += ddx;
159        }
160    }
161private:
162    typedef InterpBench INHERITED;
163};
164
165///////////////////////////////////////////////////////////////////////////////
166
167DEF_BENCH( return new Fixed16D16Interp(); )
168DEF_BENCH( return new Fixed32D32Interp(); )
169DEF_BENCH( return new Fixed16D48Interp(); )
170DEF_BENCH( return new FloatInterp(); )
171DEF_BENCH( return new DoubleInterp(); )
172