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