PolyUtilsBench.cpp 9.8 KB

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