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 
18 class InterpBench : public Benchmark {
19     enum {
20         kBuffer = 128,
21         kLoop   = 20000
22     };
23     SkString    fName;
24     int16_t     fDst[kBuffer];
25     float       fFx, fDx;
26 public:
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 
39 protected:
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 
53 private:
54     typedef Benchmark INHERITED;
55 };
56 
57 class Fixed16D16Interp : public InterpBench {
58 public:
59     Fixed16D16Interp() : INHERITED("16.16") {}
60 
61 protected:
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     }
72 private:
73     typedef InterpBench INHERITED;
74 };
75 
76 class Fixed32D32Interp : public InterpBench {
77 public:
78     Fixed32D32Interp() : INHERITED("32.32") {}
79 
80 protected:
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     }
103 private:
104     typedef InterpBench INHERITED;
105 };
106 
107 class Fixed16D48Interp : public InterpBench {
108 public:
109     Fixed16D48Interp() : INHERITED("16.48") {}
110 
111 protected:
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     }
123 private:
124     typedef InterpBench INHERITED;
125 };
126 
127 class FloatInterp : public InterpBench {
128 public:
129     FloatInterp() : INHERITED("float") {}
130 
131 protected:
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     }
141 private:
142     typedef InterpBench INHERITED;
143 };
144 
145 class DoubleInterp : public InterpBench {
146 public:
147     DoubleInterp() : INHERITED("double") {}
148 
149 protected:
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     }
161 private:
162     typedef InterpBench INHERITED;
163 };
164 
165 ///////////////////////////////////////////////////////////////////////////////
166 
167 DEF_BENCH( return new Fixed16D16Interp(); )
168 DEF_BENCH( return new Fixed32D32Interp(); )
169 DEF_BENCH( return new Fixed16D48Interp(); )
170 DEF_BENCH( return new FloatInterp(); )
171 DEF_BENCH( return new DoubleInterp(); )
172