• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bench/Benchmark.h"
9 #include "include/core/SkRRect.h"
10 #include "include/core/SkRect.h"
11 #include "src/base/SkRandom.h"
12 #include "src/core/SkGeometry.h"
13 #include "src/core/SkPathPriv.h"
14 
15 class GeometryBench : public Benchmark {
16 public:
GeometryBench(const char suffix[])17     GeometryBench(const char suffix[]) : fVolatileInt(0) {
18         fName.printf("geo_%s", suffix);
19     }
20 
onGetName()21     const char* onGetName() override {
22         return fName.c_str();
23     }
24 
isSuitableFor(Backend backend)25     bool isSuitableFor(Backend backend) override {
26         return kNonRendering_Backend == backend;
27     }
28 
29 protected:
30     volatile int fVolatileInt;
31 
32     /**
33      *  Subclasses can call this to try to defeat the optimizer (with some result of their
34      *  inner loop), since it will fool the compiler into assuming that "n" is actually
35      *  needed somewhere, and since this method is not const, the member fields cannot
36      *  be assumed to be const before and after the call.
37      */
virtualCallToFoilOptimizers(int n)38     virtual void virtualCallToFoilOptimizers(int n) { fVolatileInt += n; }
39 
40 private:
41     SkString fName;
42 };
43 
44 class GeoRectBench : public GeometryBench {
45 public:
GeoRectBench(const char suffix[])46     GeoRectBench(const char suffix[]) : GeometryBench(suffix) {}
47 
48 protected:
49     SkRect fRects[2048];
50 
onDelayedSetup()51     void onDelayedSetup() override {
52         const SkScalar min = -100;
53         const SkScalar max = 100;
54         SkRandom rand;
55         for (size_t i = 0; i < std::size(fRects); ++i) {
56             SkScalar x = rand.nextRangeScalar(min, max);
57             SkScalar y = rand.nextRangeScalar(min, max);
58             SkScalar w = rand.nextRangeScalar(min, max);
59             SkScalar h = rand.nextRangeScalar(min, max);
60             fRects[i].setXYWH(x, y, w, h);
61         }
62     }
63 };
64 
65 class GeoRectBench_intersect : public GeoRectBench {
66 public:
GeoRectBench_intersect()67     GeoRectBench_intersect() : GeoRectBench("rect_intersect") {}
68 
69 protected:
onDraw(int loops,SkCanvas * canvas)70     void onDraw(int loops, SkCanvas* canvas) override {
71         for (int outer = 0; outer < loops; ++outer) {
72             int count = 0;
73             for (size_t i = 0; i < std::size(fRects); ++i) {
74                 SkRect r = fRects[0];
75                 count += r.intersect(fRects[i]);
76             }
77             this->virtualCallToFoilOptimizers(count);
78         }
79     }
80 };
81 
82 class GeoRectBench_intersect_rect : public GeoRectBench {
83 public:
GeoRectBench_intersect_rect()84     GeoRectBench_intersect_rect() : GeoRectBench("rect_intersect_rect") {}
85 
86 protected:
onDraw(int loops,SkCanvas * canvas)87     void onDraw(int loops, SkCanvas* canvas) override {
88         for (int outer = 0; outer < loops; ++outer) {
89             int count = 0;
90             SkRect r;
91             for (size_t i = 0; i < std::size(fRects); ++i) {
92                 count += r.intersect(fRects[0], fRects[i]);
93             }
94             this->virtualCallToFoilOptimizers(count);
95         }
96     }
97 };
98 
99 class GeoRectBench_Intersects : public GeoRectBench {
100 public:
GeoRectBench_Intersects()101     GeoRectBench_Intersects() : GeoRectBench("rect_Intersects") {}
102 
103 protected:
onDraw(int loops,SkCanvas * canvas)104     void onDraw(int loops, SkCanvas* canvas) override {
105         for (int outer = 0; outer < loops; ++outer) {
106             int count = 0;
107             for (size_t i = 0; i < std::size(fRects); ++i) {
108                 count += SkRect::Intersects(fRects[0], fRects[i]);
109             }
110             this->virtualCallToFoilOptimizers(count);
111         }
112     }
113 };
114 
115 class GeoRectBench_sort : public GeoRectBench {
116 public:
GeoRectBench_sort()117     GeoRectBench_sort() : GeoRectBench("rect_sort") {}
118 
119 protected:
onDraw(int loops,SkCanvas * canvas)120     void onDraw(int loops, SkCanvas* canvas) override {
121         for (int outer = 0; outer < loops; ++outer) {
122             for (size_t i = 0; i < std::size(fRects); ++i) {
123                 fRects[i].sort();
124             }
125         }
126     }
127 };
128 
129 DEF_BENCH( return new GeoRectBench_intersect; )
130 DEF_BENCH( return new GeoRectBench_intersect_rect; )
131 DEF_BENCH( return new GeoRectBench_Intersects; )
132 
133 DEF_BENCH( return new GeoRectBench_sort; )
134 
135 ///////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 class QuadBenchBase : public GeometryBench {
138 protected:
139     SkPoint fPts[4];
140 public:
QuadBenchBase(const char name[])141     QuadBenchBase(const char name[]) : GeometryBench(name) {
142         SkRandom rand;
143         for (int i = 0; i < 4; ++i) {
144             fPts[i].set(rand.nextUScalar1(), rand.nextUScalar1());
145         }
146     }
147 };
148 
149 class EvalQuadAt0 : public QuadBenchBase {
150 public:
EvalQuadAt0()151     EvalQuadAt0() : QuadBenchBase("evalquadat0") {}
152 protected:
onDraw(int loops,SkCanvas * canvas)153     void onDraw(int loops, SkCanvas* canvas) override {
154         SkPoint result;
155         for (int outer = 0; outer < loops; ++outer) {
156             SkEvalQuadAt(fPts, 0.5f, &result);
157             SkEvalQuadAt(fPts, 0.5f, &result);
158             SkEvalQuadAt(fPts, 0.5f, &result);
159             SkEvalQuadAt(fPts, 0.5f, &result);
160         }
161     }
162 };
163 DEF_BENCH( return new EvalQuadAt0; )
164 
165 class EvalQuadAt1 : public QuadBenchBase {
166 public:
EvalQuadAt1()167     EvalQuadAt1() : QuadBenchBase("evalquadat1") {}
168 protected:
onDraw(int loops,SkCanvas * canvas)169     void onDraw(int loops, SkCanvas* canvas) override {
170         SkPoint result;
171         for (int outer = 0; outer < loops; ++outer) {
172             result = SkEvalQuadAt(fPts, 0.5f);
173             result = SkEvalQuadAt(fPts, 0.5f);
174             result = SkEvalQuadAt(fPts, 0.5f);
175             result = SkEvalQuadAt(fPts, 0.5f);
176         }
177     }
178 };
179 DEF_BENCH( return new EvalQuadAt1; )
180 
181 ////////
182 
183 class EvalQuadTangentAt0 : public QuadBenchBase {
184 public:
EvalQuadTangentAt0()185     EvalQuadTangentAt0() : QuadBenchBase("evalquadtangentat0") {}
186 protected:
onDraw(int loops,SkCanvas * canvas)187     void onDraw(int loops, SkCanvas* canvas) override {
188         SkPoint result;
189         for (int outer = 0; outer < loops; ++outer) {
190             SkEvalQuadAt(fPts, 0.5f, nullptr, &result);
191             SkEvalQuadAt(fPts, 0.5f, nullptr, &result);
192             SkEvalQuadAt(fPts, 0.5f, nullptr, &result);
193             SkEvalQuadAt(fPts, 0.5f, nullptr, &result);
194         }
195     }
196 };
197 DEF_BENCH( return new EvalQuadTangentAt0; )
198 
199 class EvalQuadTangentAt1 : public QuadBenchBase {
200 public:
EvalQuadTangentAt1()201     EvalQuadTangentAt1() : QuadBenchBase("evalquadtangentat1") {}
202 protected:
onDraw(int loops,SkCanvas * canvas)203     void onDraw(int loops, SkCanvas* canvas) override {
204         SkPoint result;
205         for (int outer = 0; outer < loops; ++outer) {
206             result = SkEvalQuadTangentAt(fPts, 0.5f);
207             result = SkEvalQuadTangentAt(fPts, 0.5f);
208             result = SkEvalQuadTangentAt(fPts, 0.5f);
209             result = SkEvalQuadTangentAt(fPts, 0.5f);
210         }
211     }
212 };
213 DEF_BENCH( return new EvalQuadTangentAt1; )
214 
215 ////////
216 
217 class ChopQuadAt : public QuadBenchBase {
218 public:
ChopQuadAt()219     ChopQuadAt() : QuadBenchBase("chopquadat") {}
220 protected:
onDraw(int loops,SkCanvas * canvas)221     void onDraw(int loops, SkCanvas* canvas) override {
222         SkPoint dst[5];
223         for (int outer = 0; outer < loops; ++outer) {
224             SkChopQuadAt(fPts, dst, 0.5f);
225             SkChopQuadAt(fPts, dst, 0.5f);
226             SkChopQuadAt(fPts, dst, 0.5f);
227             SkChopQuadAt(fPts, dst, 0.5f);
228         }
229     }
230 };
231 DEF_BENCH( return new ChopQuadAt; )
232 
233 class ChopCubicAt : public QuadBenchBase {
234 public:
ChopCubicAt()235     ChopCubicAt() : QuadBenchBase("chopcubicat0") {}
236 protected:
onDraw(int loops,SkCanvas * canvas)237     void onDraw(int loops, SkCanvas* canvas) override {
238         SkPoint dst[7];
239         for (int outer = 0; outer < loops; ++outer) {
240             SkChopCubicAt(fPts, dst, 0.5f);
241             SkChopCubicAt(fPts, dst, 0.5f);
242             SkChopCubicAt(fPts, dst, 0.5f);
243             SkChopCubicAt(fPts, dst, 0.5f);
244         }
245     }
246 };
247 DEF_BENCH( return new ChopCubicAt; )
248 
249 #include "include/core/SkPath.h"
250 
251 class ConvexityBench : public Benchmark {
252     SkPath fPath;
253 
254 public:
ConvexityBench(const char suffix[])255     ConvexityBench(const char suffix[]) {
256         fName.printf("convexity_%s", suffix);
257     }
258 
onGetName()259     const char* onGetName() override {
260         return fName.c_str();
261     }
262 
isSuitableFor(Backend backend)263     bool isSuitableFor(Backend backend) override {
264         return kNonRendering_Backend == backend;
265     }
266 
267     virtual void preparePath(SkPath*) = 0;
268 
269 protected:
onPreDraw(SkCanvas *)270     void onPreDraw(SkCanvas*) override {
271         this->preparePath(&fPath);
272     }
273 
onDraw(int loops,SkCanvas * canvas)274     void onDraw(int loops, SkCanvas* canvas) override {
275         for (int i = 0; i < loops; ++i) {
276             SkPathPriv::ForceComputeConvexity(fPath);
277         }
278     }
279 
280 private:
281     SkString fName;
282 };
283 
284 class RRectConvexityBench : public ConvexityBench {
285 public:
RRectConvexityBench()286     RRectConvexityBench() : ConvexityBench("rrect") {}
287 
preparePath(SkPath * path)288     void preparePath(SkPath* path) override {
289         SkRRect rr;
290         rr.setRectXY({0, 0, 100, 100}, 20, 30);
291         path->addRRect(rr);
292     }
293 };
294 DEF_BENCH( return new RRectConvexityBench; )
295 
296