blob: b77bfa3219a14142c20705a742c4917caf026c77 [file] [log] [blame]
reed1119c872014-10-09 14:29:01 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "bench/Benchmark.h"
9#include "include/core/SkRect.h"
10#include "include/utils/SkRandom.h"
11#include "src/core/SkGeometry.h"
Mike Reed6052c0b2020-08-28 11:49:56 -040012#include "src/core/SkPathPriv.h"
reed1119c872014-10-09 14:29:01 -070013
14class GeometryBench : public Benchmark {
15public:
16 GeometryBench(const char suffix[]) : fVolatileInt(0) {
17 fName.printf("geo_%s", suffix);
18 }
19
mtklein36352bf2015-03-25 18:17:31 -070020 const char* onGetName() override {
reed1119c872014-10-09 14:29:01 -070021 return fName.c_str();
22 }
23
mtklein36352bf2015-03-25 18:17:31 -070024 bool isSuitableFor(Backend backend) override {
reed1119c872014-10-09 14:29:01 -070025 return kNonRendering_Backend == backend;
26 }
27
28protected:
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 */
37 virtual void virtualCallToFoilOptimizers(int n) { fVolatileInt += n; }
38
39private:
40 SkString fName;
41};
42
43class GeoRectBench : public GeometryBench {
44public:
45 GeoRectBench(const char suffix[]) : GeometryBench(suffix) {}
46
47protected:
48 SkRect fRects[2048];
49
Brian Salomond0072812020-07-21 17:03:56 -040050 void onDelayedSetup() override {
reed1119c872014-10-09 14:29:01 -070051 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
64class GeoRectBench_intersect : public GeoRectBench {
65public:
66 GeoRectBench_intersect() : GeoRectBench("rect_intersect") {}
67
68protected:
mtkleina1ebeb22015-10-01 09:43:39 -070069 void onDraw(int loops, SkCanvas* canvas) override {
reed1119c872014-10-09 14:29:01 -070070 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
81class GeoRectBench_intersect_rect : public GeoRectBench {
82public:
83 GeoRectBench_intersect_rect() : GeoRectBench("rect_intersect_rect") {}
84
85protected:
mtkleina1ebeb22015-10-01 09:43:39 -070086 void onDraw(int loops, SkCanvas* canvas) override {
reed1119c872014-10-09 14:29:01 -070087 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
98class GeoRectBench_Intersects : public GeoRectBench {
99public:
100 GeoRectBench_Intersects() : GeoRectBench("rect_Intersects") {}
halcanary9d524f22016-03-29 09:03:52 -0700101
reed1119c872014-10-09 14:29:01 -0700102protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700103 void onDraw(int loops, SkCanvas* canvas) override {
reed1119c872014-10-09 14:29:01 -0700104 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
reed40636a52014-10-10 05:50:15 -0700114class GeoRectBench_sort : public GeoRectBench {
115public:
116 GeoRectBench_sort() : GeoRectBench("rect_sort") {}
halcanary9d524f22016-03-29 09:03:52 -0700117
reed40636a52014-10-10 05:50:15 -0700118protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700119 void onDraw(int loops, SkCanvas* canvas) override {
reed40636a52014-10-10 05:50:15 -0700120 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
reed1119c872014-10-09 14:29:01 -0700128DEF_BENCH( return new GeoRectBench_intersect; )
129DEF_BENCH( return new GeoRectBench_intersect_rect; )
130DEF_BENCH( return new GeoRectBench_Intersects; )
reed40636a52014-10-10 05:50:15 -0700131
132DEF_BENCH( return new GeoRectBench_sort; )
reed65cb2cd2015-03-19 10:18:47 -0700133
134///////////////////////////////////////////////////////////////////////////////////////////////////
135
reed40b7dd52015-03-20 06:01:08 -0700136class QuadBenchBase : public GeometryBench {
137protected:
reed6b9ef902015-03-24 19:24:34 -0700138 SkPoint fPts[4];
reed65cb2cd2015-03-19 10:18:47 -0700139public:
reed40b7dd52015-03-20 06:01:08 -0700140 QuadBenchBase(const char name[]) : GeometryBench(name) {
reed65cb2cd2015-03-19 10:18:47 -0700141 SkRandom rand;
reed6b9ef902015-03-24 19:24:34 -0700142 for (int i = 0; i < 4; ++i) {
reed65cb2cd2015-03-19 10:18:47 -0700143 fPts[i].set(rand.nextUScalar1(), rand.nextUScalar1());
144 }
145 }
reed40b7dd52015-03-20 06:01:08 -0700146};
147
148class EvalQuadAt0 : public QuadBenchBase {
149public:
150 EvalQuadAt0() : QuadBenchBase("evalquadat0") {}
reed65cb2cd2015-03-19 10:18:47 -0700151protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700152 void onDraw(int loops, SkCanvas* canvas) override {
reed65cb2cd2015-03-19 10:18:47 -0700153 SkPoint result;
154 for (int outer = 0; outer < loops; ++outer) {
reed40b7dd52015-03-20 06:01:08 -0700155 SkEvalQuadAt(fPts, 0.5f, &result);
156 SkEvalQuadAt(fPts, 0.5f, &result);
157 SkEvalQuadAt(fPts, 0.5f, &result);
158 SkEvalQuadAt(fPts, 0.5f, &result);
reed65cb2cd2015-03-19 10:18:47 -0700159 }
160 }
161};
162DEF_BENCH( return new EvalQuadAt0; )
163
reed40b7dd52015-03-20 06:01:08 -0700164class EvalQuadAt1 : public QuadBenchBase {
reed65cb2cd2015-03-19 10:18:47 -0700165public:
reed40b7dd52015-03-20 06:01:08 -0700166 EvalQuadAt1() : QuadBenchBase("evalquadat1") {}
reed65cb2cd2015-03-19 10:18:47 -0700167protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700168 void onDraw(int loops, SkCanvas* canvas) override {
reed40b7dd52015-03-20 06:01:08 -0700169 SkPoint result;
reed65cb2cd2015-03-19 10:18:47 -0700170 for (int outer = 0; outer < loops; ++outer) {
reed40b7dd52015-03-20 06:01:08 -0700171 result = SkEvalQuadAt(fPts, 0.5f);
172 result = SkEvalQuadAt(fPts, 0.5f);
173 result = SkEvalQuadAt(fPts, 0.5f);
174 result = SkEvalQuadAt(fPts, 0.5f);
reed65cb2cd2015-03-19 10:18:47 -0700175 }
176 }
177};
178DEF_BENCH( return new EvalQuadAt1; )
179
reed40b7dd52015-03-20 06:01:08 -0700180////////
181
182class EvalQuadTangentAt0 : public QuadBenchBase {
183public:
184 EvalQuadTangentAt0() : QuadBenchBase("evalquadtangentat0") {}
185protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700186 void onDraw(int loops, SkCanvas* canvas) override {
reed40b7dd52015-03-20 06:01:08 -0700187 SkPoint result;
188 for (int outer = 0; outer < loops; ++outer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700189 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);
reed40b7dd52015-03-20 06:01:08 -0700193 }
194 }
195};
196DEF_BENCH( return new EvalQuadTangentAt0; )
197
198class EvalQuadTangentAt1 : public QuadBenchBase {
199public:
200 EvalQuadTangentAt1() : QuadBenchBase("evalquadtangentat1") {}
201protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700202 void onDraw(int loops, SkCanvas* canvas) override {
reed40b7dd52015-03-20 06:01:08 -0700203 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};
212DEF_BENCH( return new EvalQuadTangentAt1; )
213
214////////
215
reedc08330f2015-03-26 07:26:08 -0700216class ChopQuadAt : public QuadBenchBase {
reed40b7dd52015-03-20 06:01:08 -0700217public:
reedc08330f2015-03-26 07:26:08 -0700218 ChopQuadAt() : QuadBenchBase("chopquadat") {}
reed40b7dd52015-03-20 06:01:08 -0700219protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700220 void onDraw(int loops, SkCanvas* canvas) override {
reed40b7dd52015-03-20 06:01:08 -0700221 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};
reedc08330f2015-03-26 07:26:08 -0700230DEF_BENCH( return new ChopQuadAt; )
reed40b7dd52015-03-20 06:01:08 -0700231
reedc08330f2015-03-26 07:26:08 -0700232class ChopCubicAt : public QuadBenchBase {
reed40b7dd52015-03-20 06:01:08 -0700233public:
reedc08330f2015-03-26 07:26:08 -0700234 ChopCubicAt() : QuadBenchBase("chopcubicat0") {}
reed6b9ef902015-03-24 19:24:34 -0700235protected:
mtkleina1ebeb22015-10-01 09:43:39 -0700236 void onDraw(int loops, SkCanvas* canvas) override {
reed6b9ef902015-03-24 19:24:34 -0700237 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};
reedc08330f2015-03-26 07:26:08 -0700246DEF_BENCH( return new ChopCubicAt; )
Mike Reedef4047d2018-11-28 11:45:44 -0500247
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500248#include "include/core/SkPath.h"
Mike Reedef4047d2018-11-28 11:45:44 -0500249
250class ConvexityBench : public Benchmark {
251 SkPath fPath;
252
253public:
254 ConvexityBench(const char suffix[]) {
255 fName.printf("convexity_%s", suffix);
256 }
257
258 const char* onGetName() override {
259 return fName.c_str();
260 }
261
262 bool isSuitableFor(Backend backend) override {
263 return kNonRendering_Backend == backend;
264 }
265
266 virtual void preparePath(SkPath*) = 0;
267
268protected:
269 void onPreDraw(SkCanvas*) override {
270 this->preparePath(&fPath);
271 }
272
273 void onDraw(int loops, SkCanvas* canvas) override {
274 for (int i = 0; i < loops; ++i) {
Mike Reed6052c0b2020-08-28 11:49:56 -0400275 SkPathPriv::ForceComputeConvexity(fPath);
Mike Reedef4047d2018-11-28 11:45:44 -0500276 }
277 }
278
279private:
280 SkString fName;
281};
282
283class RRectConvexityBench : public ConvexityBench {
284public:
285 RRectConvexityBench() : ConvexityBench("rrect") {}
286
287 void preparePath(SkPath* path) override {
288 SkRRect rr;
289 rr.setRectXY({0, 0, 100, 100}, 20, 30);
290 path->addRRect(rr);
291 }
292};
293DEF_BENCH( return new RRectConvexityBench; )
294