Home | History | Annotate | Download | only in bench
      1 /*
      2  * Copyright 2014 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 "SkBlendModePriv.h"
     10 #include "SkCanvas.h"
     11 #include "SkPaint.h"
     12 
     13 #include <ctype.h>
     14 
     15 /** This benchmark tests rendering rotated rectangles. It can optionally apply AA and/or change the
     16     paint color between each rect in different ways using the ColorType enum. The xfermode used can
     17     be specified as well.
     18   */
     19 
     20 enum ColorType {
     21     kConstantOpaque_ColorType,
     22     kConstantTransparent_ColorType,
     23     kChangingOpaque_ColorType,
     24     kChangingTransparent_ColorType,
     25     kAlternatingOpaqueAndTransparent_ColorType,
     26 };
     27 
     28 static inline SkColor start_color(ColorType ct) {
     29     switch (ct) {
     30         case kConstantOpaque_ColorType:
     31         case kChangingOpaque_ColorType:
     32         case kAlternatingOpaqueAndTransparent_ColorType:
     33             return 0xFFA07040;
     34         case kConstantTransparent_ColorType:
     35         case kChangingTransparent_ColorType:
     36             return 0x80A07040;
     37     }
     38     SK_ABORT("Shouldn't reach here.");
     39     return 0;
     40 }
     41 
     42 static inline SkColor advance_color(SkColor old, ColorType ct, int step) {
     43     if (kAlternatingOpaqueAndTransparent_ColorType == ct) {
     44         ct = (step & 0x1) ? kChangingOpaque_ColorType : kChangingTransparent_ColorType ;
     45     }
     46     switch (ct) {
     47         case kConstantOpaque_ColorType:
     48         case kConstantTransparent_ColorType:
     49             return old;
     50         case kChangingOpaque_ColorType:
     51             return 0xFF000000 | (old + 0x00010307);
     52         case kChangingTransparent_ColorType:
     53             return (0x00FFFFFF & (old + 0x00010307)) | 0x80000000;
     54         case kAlternatingOpaqueAndTransparent_ColorType:
     55             SK_ABORT("Can't get here");
     56     }
     57     SK_ABORT("Shouldn't reach here.");
     58     return 0;
     59 }
     60 
     61 static SkString to_lower(const char* str) {
     62     SkString lower(str);
     63     for (size_t i = 0; i < lower.size(); i++) {
     64         lower[i] = tolower(lower[i]);
     65     }
     66     return lower;
     67 }
     68 
     69 class RotRectBench: public Benchmark {
     70 public:
     71     RotRectBench(bool aa, ColorType ct, SkBlendMode mode)
     72         : fAA(aa)
     73         , fColorType(ct)
     74         , fMode(mode) {
     75         this->makeName();
     76     }
     77 
     78 protected:
     79     const char* onGetName() override { return fName.c_str(); }
     80 
     81     void onDraw(int loops, SkCanvas* canvas) override {
     82         SkPaint paint;
     83         paint.setAntiAlias(fAA);
     84         paint.setBlendMode(fMode);
     85         SkColor color = start_color(fColorType);
     86 
     87         int w = this->getSize().x();
     88         int h = this->getSize().y();
     89 
     90         static const SkScalar kRectW = 25.1f;
     91         static const SkScalar kRectH = 25.9f;
     92 
     93         SkMatrix rotate;
     94         // This value was chosen so that we frequently hit the axis-aligned case.
     95         rotate.setRotate(30.f, kRectW / 2, kRectH / 2);
     96         SkMatrix m = rotate;
     97 
     98         SkScalar tx = 0, ty = 0;
     99 
    100         for (int i = 0; i < loops; ++i) {
    101             canvas->save();
    102             canvas->translate(tx, ty);
    103             canvas->concat(m);
    104             paint.setColor(color);
    105             color = advance_color(color, fColorType, i);
    106 
    107             canvas->drawRect(SkRect::MakeWH(kRectW, kRectH), paint);
    108             canvas->restore();
    109 
    110             tx += kRectW + 2;
    111             if (tx > w) {
    112                 tx = 0;
    113                 ty += kRectH + 2;
    114                 if (ty > h) {
    115                     ty = 0;
    116                 }
    117             }
    118 
    119             m.postConcat(rotate);
    120         }
    121     }
    122 
    123 private:
    124     void makeName() {
    125         fName = "rotated_rects";
    126         if (fAA) {
    127             fName.append("_aa");
    128         } else {
    129             fName.append("_bw");
    130         }
    131         switch (fColorType) {
    132             case kConstantOpaque_ColorType:
    133                 fName.append("_same_opaque");
    134                 break;
    135             case kConstantTransparent_ColorType:
    136                 fName.append("_same_transparent");
    137                 break;
    138             case kChangingOpaque_ColorType:
    139                 fName.append("_changing_opaque");
    140                 break;
    141             case kChangingTransparent_ColorType:
    142                 fName.append("_changing_transparent");
    143                 break;
    144             case kAlternatingOpaqueAndTransparent_ColorType:
    145                 fName.append("_alternating_transparent_and_opaque");
    146                 break;
    147         }
    148         fName.appendf("_%s", to_lower(SkBlendMode_Name(fMode)).c_str());
    149     }
    150 
    151     bool        fAA;
    152     ColorType   fColorType;
    153     SkBlendMode fMode;
    154     SkString    fName;
    155 
    156     typedef Benchmark INHERITED;
    157 };
    158 
    159 // Choose kSrcOver because it always allows coverage and alpha to be conflated. kSrc only allows
    160 // conflation when opaque, and kDarken because it isn't possilbe with standard GL blending.
    161 DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kSrcOver);)
    162 DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kSrcOver);)
    163 DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kSrcOver);)
    164 DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kSrcOver);)
    165 DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrcOver);)
    166 
    167 DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kSrcOver);)
    168 DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kSrcOver);)
    169 DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kSrcOver);)
    170 DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kSrcOver);)
    171 DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrcOver);)
    172 
    173 DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kSrc);)
    174 DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kSrc);)
    175 DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kSrc);)
    176 DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kSrc);)
    177 DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrc);)
    178 
    179 DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kSrc);)
    180 DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kSrc);)
    181 DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kSrc);)
    182 DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kSrc);)
    183 DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kSrc);)
    184 
    185 DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkBlendMode::kDarken);)
    186 DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkBlendMode::kDarken);)
    187 DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkBlendMode::kDarken);)
    188 DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkBlendMode::kDarken);)
    189 DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kDarken);)
    190 
    191 DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkBlendMode::kDarken);)
    192 DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkBlendMode::kDarken);)
    193 DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkBlendMode::kDarken);)
    194 DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkBlendMode::kDarken);)
    195 DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkBlendMode::kDarken);)
    196