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