xref: /third_party/skia/bench/PolyUtilsBench.cpp (revision cb93a386)
1/*
2 * Copyright 2018 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/private/SkTemplates.h"
11#include "src/utils/SkPolyUtils.h"
12
13class PolyUtilsBench : public Benchmark {
14public:
15    // Evaluate SkTriangulateSimplePolygon's performance (via derived classes) on:
16    //   a non-self-intersecting star, a circle of tiny line segments and a self-intersecting star
17    enum class Type { kConvexCheck, kSimpleCheck, kInsetConvex, kOffsetSimple, kTessellateSimple };
18
19    PolyUtilsBench(Type type) : fType(type) {}
20
21    virtual void appendName(SkString*) = 0;
22    virtual void makePoly(SkTDArray<SkPoint>* poly) = 0;
23    virtual int complexity() { return 0; }
24
25protected:
26    const char* onGetName() override {
27        fName = "poly_utils_";
28        this->appendName(&fName);
29        switch (fType) {
30        case Type::kConvexCheck:
31            fName.append("_c");
32            break;
33        case Type::kSimpleCheck:
34            fName.append("_s");
35            break;
36        case Type::kInsetConvex:
37            fName.append("_i");
38            break;
39        case Type::kOffsetSimple:
40            fName.append("_o");
41            break;
42        case Type::kTessellateSimple:
43            fName.append("_t");
44            break;
45        }
46        return fName.c_str();
47    }
48
49    void onDraw(int loops, SkCanvas* canvas) override {
50        SkTDArray<SkPoint> poly;
51        this->makePoly(&poly);
52        switch (fType) {
53            case Type::kConvexCheck:
54                for (int i = 0; i < loops; i++) {
55                    (void)SkIsConvexPolygon(poly.begin(), poly.count());
56                }
57                break;
58            case Type::kSimpleCheck:
59                for (int i = 0; i < loops; i++) {
60                    (void)SkIsSimplePolygon(poly.begin(), poly.count());
61                }
62                break;
63            case Type::kInsetConvex:
64                if (SkIsConvexPolygon(poly.begin(), poly.count())) {
65                    SkTDArray<SkPoint> result;
66                    for (int i = 0; i < loops; i++) {
67                        (void)SkInsetConvexPolygon(poly.begin(), poly.count(), 10, &result);
68                        (void)SkInsetConvexPolygon(poly.begin(), poly.count(), 40, &result);
69                    }
70                }
71                break;
72            case Type::kOffsetSimple:
73                if (SkIsSimplePolygon(poly.begin(), poly.count())) {
74                    SkTDArray<SkPoint> result;
75                    SkRect bounds;
76                    bounds.setBounds(poly.begin(), poly.count());
77                    for (int i = 0; i < loops; i++) {
78                        (void)SkOffsetSimplePolygon(poly.begin(), poly.count(), bounds, 10,
79                                                    &result);
80                        (void)SkOffsetSimplePolygon(poly.begin(), poly.count(), bounds, -10,
81                                                    &result);
82                    }
83                }
84                break;
85            case Type::kTessellateSimple:
86                if (SkIsSimplePolygon(poly.begin(), poly.count())) {
87                    SkAutoSTMalloc<64, uint16_t> indexMap(poly.count());
88                    for (int i = 0; i < poly.count(); ++i) {
89                        indexMap[i] = i;
90                    }
91                    SkTDArray<uint16_t> triangleIndices;
92                    for (int i = 0; i < loops; i++) {
93                        SkTriangulateSimplePolygon(poly.begin(), indexMap, poly.count(),
94                                                   &triangleIndices);
95                    }
96                }
97                break;
98        }
99    }
100
101private:
102    SkString           fName;
103    Type               fType;
104
105    using INHERITED = Benchmark;
106};
107
108class StarPolyUtilsBench : public PolyUtilsBench {
109public:
110    StarPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
111
112    void appendName(SkString* name) override {
113        name->append("star");
114    }
115    void makePoly(SkTDArray<SkPoint>* poly) override {
116        // create non-intersecting star
117        const SkScalar c = SkIntToScalar(45);
118        const SkScalar r1 = SkIntToScalar(20);
119        const SkScalar r2 = SkIntToScalar(3);
120        const int n = 500;
121        SkScalar rad = 0;
122        const SkScalar drad = SK_ScalarPI / n;
123        for (int i = 0; i < n; i++) {
124            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r1, c + SkScalarSin(rad) * r1);
125            rad += drad;
126            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r2, c + SkScalarSin(rad) * r2);
127            rad += drad;
128        }
129    }
130private:
131    using INHERITED = PolyUtilsBench;
132};
133
134class CirclePolyUtilsBench : public PolyUtilsBench {
135public:
136    CirclePolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
137
138    void appendName(SkString* name) override {
139        name->append("circle");
140    }
141    void makePoly(SkTDArray<SkPoint>* poly) override {
142        // create circle with many vertices
143        const SkScalar c = SkIntToScalar(45);
144        const SkScalar r = SkIntToScalar(20);
145        const int n = 1000;
146        SkScalar rad = 0;
147        const SkScalar drad = 2 * SK_ScalarPI / n;
148        for (int i = 0; i < n; i++) {
149            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r, c + SkScalarSin(rad) * r);
150            rad += drad;
151        }
152    }
153private:
154    using INHERITED = PolyUtilsBench;
155};
156
157class IntersectingPolyUtilsBench : public PolyUtilsBench {
158public:
159    IntersectingPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
160
161    void appendName(SkString* name) override {
162        name->append("intersecting");
163    }
164    void makePoly(SkTDArray<SkPoint>* poly) override {
165        // create self-intersecting star
166        const SkScalar c = SkIntToScalar(45);
167        const SkScalar r = SkIntToScalar(20);
168        const int n = 1000;
169
170        SkScalar rad = -SK_ScalarPI / 2;
171        const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
172        *poly->push() = SkPoint::Make(c, c - r);
173        for (int i = 1; i < n; i++) {
174            rad += drad;
175            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r, c + SkScalarSin(rad) * r);
176        }
177    }
178private:
179    using INHERITED = PolyUtilsBench;
180};
181
182// familiar videogame character
183class NotchPolyUtilsBench : public PolyUtilsBench {
184public:
185    NotchPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
186
187    void appendName(SkString* name) override {
188        name->append("notch");
189    }
190    void makePoly(SkTDArray<SkPoint>* poly) override {
191        // create 3/4 circle with many vertices
192        const SkScalar c = SkIntToScalar(45);
193        const SkScalar r = SkIntToScalar(20);
194        const int n = 1000;
195        SkScalar rad = 0;
196        const SkScalar drad = 3 * SK_ScalarPI / (2*n);
197        for (int i = 0; i < n; i++) {
198            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r, c + SkScalarSin(rad) * r);
199            rad += drad;
200        }
201        // and the mouth
202        *poly->push() = SkPoint::Make(45, 45);
203    }
204private:
205    using INHERITED = PolyUtilsBench;
206};
207
208class IceCreamPolyUtilsBench : public PolyUtilsBench {
209public:
210    IceCreamPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
211
212    void appendName(SkString* name) override {
213        name->append("icecream");
214    }
215    void makePoly(SkTDArray<SkPoint>* poly) override {
216        // create 3/4 circle with many vertices
217        const SkScalar c = SkIntToScalar(45);
218        const SkScalar r = SkIntToScalar(20);
219        const int n = 1000;
220        SkScalar rad = 0;
221        const SkScalar drad = 3 * SK_ScalarPI / (2*n);
222        for (int i = 0; i < n; i++) {
223            *poly->push() = SkPoint::Make(c + SkScalarCos(rad) * r, c + SkScalarSin(rad) * r);
224            rad += drad;
225        }
226        // and the tip of the cone
227        *poly->push() = SkPoint::Make(90, 0);
228    }
229private:
230    using INHERITED = PolyUtilsBench;
231};
232
233DEF_BENCH(return new StarPolyUtilsBench(PolyUtilsBench::Type::kConvexCheck);)
234DEF_BENCH(return new StarPolyUtilsBench(PolyUtilsBench::Type::kSimpleCheck);)
235DEF_BENCH(return new StarPolyUtilsBench(PolyUtilsBench::Type::kInsetConvex);)
236DEF_BENCH(return new StarPolyUtilsBench(PolyUtilsBench::Type::kOffsetSimple);)
237DEF_BENCH(return new StarPolyUtilsBench(PolyUtilsBench::Type::kTessellateSimple);)
238DEF_BENCH(return new CirclePolyUtilsBench(PolyUtilsBench::Type::kConvexCheck);)
239DEF_BENCH(return new CirclePolyUtilsBench(PolyUtilsBench::Type::kSimpleCheck);)
240DEF_BENCH(return new CirclePolyUtilsBench(PolyUtilsBench::Type::kInsetConvex);)
241DEF_BENCH(return new CirclePolyUtilsBench(PolyUtilsBench::Type::kOffsetSimple);)
242DEF_BENCH(return new CirclePolyUtilsBench(PolyUtilsBench::Type::kTessellateSimple);)
243DEF_BENCH(return new IntersectingPolyUtilsBench(PolyUtilsBench::Type::kConvexCheck);)
244DEF_BENCH(return new IntersectingPolyUtilsBench(PolyUtilsBench::Type::kSimpleCheck);)
245DEF_BENCH(return new IntersectingPolyUtilsBench(PolyUtilsBench::Type::kInsetConvex);)
246DEF_BENCH(return new IntersectingPolyUtilsBench(PolyUtilsBench::Type::kOffsetSimple);)
247DEF_BENCH(return new IntersectingPolyUtilsBench(PolyUtilsBench::Type::kTessellateSimple);)
248DEF_BENCH(return new NotchPolyUtilsBench(PolyUtilsBench::Type::kConvexCheck);)
249DEF_BENCH(return new NotchPolyUtilsBench(PolyUtilsBench::Type::kSimpleCheck);)
250DEF_BENCH(return new NotchPolyUtilsBench(PolyUtilsBench::Type::kInsetConvex);)
251DEF_BENCH(return new NotchPolyUtilsBench(PolyUtilsBench::Type::kOffsetSimple);)
252DEF_BENCH(return new NotchPolyUtilsBench(PolyUtilsBench::Type::kTessellateSimple);)
253DEF_BENCH(return new IceCreamPolyUtilsBench(PolyUtilsBench::Type::kConvexCheck);)
254DEF_BENCH(return new IceCreamPolyUtilsBench(PolyUtilsBench::Type::kSimpleCheck);)
255DEF_BENCH(return new IceCreamPolyUtilsBench(PolyUtilsBench::Type::kInsetConvex);)
256DEF_BENCH(return new IceCreamPolyUtilsBench(PolyUtilsBench::Type::kOffsetSimple);)
257DEF_BENCH(return new IceCreamPolyUtilsBench(PolyUtilsBench::Type::kTessellateSimple);)
258
259