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