Home | History | Annotate | Download | only in bench
      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 
     17     PolyUtilsBench(Type type) : fType(type) {}
     18 
     19     virtual void appendName(SkString*) = 0;
     20     virtual void makePoly(SkTDArray<SkPoint>* poly) = 0;
     21     virtual int complexity() { return 0; }
     22 
     23 protected:
     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 
     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:
    104     StarPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
    105 
    106     void appendName(SkString* name) override {
    107         name->append("star");
    108     }
    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:
    132     CirclePolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
    133 
    134     void appendName(SkString* name) override {
    135         name->append("circle");
    136     }
    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:
    156     IntersectingPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
    157 
    158     void appendName(SkString* name) override {
    159         name->append("intersecting");
    160     }
    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:
    183     NotchPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
    184 
    185     void appendName(SkString* name) override {
    186         name->append("notch");
    187     }
    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:
    209     IceCreamPolyUtilsBench(PolyUtilsBench::Type type) : INHERITED(type) {}
    210 
    211     void appendName(SkString* name) override {
    212         name->append("icecream");
    213     }
    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