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