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