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