Home | History | Annotate | Download | only in bench
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkBenchmark.h"
      9 #include "SkBitmap.h"
     10 #include "SkCanvas.h"
     11 #include "SkColorPriv.h"
     12 #include "SkGradientShader.h"
     13 #include "SkPaint.h"
     14 #include "SkShader.h"
     15 #include "SkString.h"
     16 #include "SkUnitMapper.h"
     17 
     18 struct GradData {
     19     int             fCount;
     20     const SkColor*  fColors;
     21     const SkScalar* fPos;
     22 };
     23 
     24 static const SkColor gColors[] = {
     25     SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
     26 };
     27 static const SkScalar gPos0[] = { 0, SK_Scalar1 };
     28 static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
     29 static const SkScalar gPos2[] = {
     30     0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
     31 };
     32 
     33 static const GradData gGradData[] = {
     34     { 2, gColors, NULL },
     35     { 2, gColors, gPos0 },
     36     { 2, gColors, gPos1 },
     37     { 5, gColors, NULL },
     38     { 5, gColors, gPos2 }
     39 };
     40 
     41 /// Ignores scale
     42 static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
     43                             SkShader::TileMode tm, SkUnitMapper* mapper,
     44                             float scale) {
     45     return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
     46                                           data.fCount, tm, mapper);
     47 }
     48 
     49 static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
     50                             SkShader::TileMode tm, SkUnitMapper* mapper,
     51                             float scale) {
     52     SkPoint center;
     53     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
     54                SkScalarAve(pts[0].fY, pts[1].fY));
     55     return SkGradientShader::CreateRadial(center, center.fX * scale,
     56                                           data.fColors,
     57                                           data.fPos, data.fCount, tm, mapper);
     58 }
     59 
     60 /// Ignores scale
     61 static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
     62                            SkShader::TileMode tm, SkUnitMapper* mapper,
     63                            float scale) {
     64     SkPoint center;
     65     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
     66                SkScalarAve(pts[0].fY, pts[1].fY));
     67     return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
     68                                          data.fPos, data.fCount, mapper);
     69 }
     70 
     71 /// Ignores scale
     72 static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
     73                              SkShader::TileMode tm, SkUnitMapper* mapper,
     74                              float scale) {
     75     SkPoint center0, center1;
     76     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
     77                 SkScalarAve(pts[0].fY, pts[1].fY));
     78     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
     79                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
     80     return SkGradientShader::CreateTwoPointRadial(
     81             center1, (pts[1].fX - pts[0].fX) / 7,
     82             center0, (pts[1].fX - pts[0].fX) / 2,
     83             data.fColors, data.fPos, data.fCount, tm, mapper);
     84 }
     85 
     86 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
     87                                SkShader::TileMode tm, SkUnitMapper* mapper,
     88                                float scale);
     89 
     90 static const struct {
     91     GradMaker   fMaker;
     92     const char* fName;
     93     int         fRepeat;
     94 } gGrads[] = {
     95     { MakeLinear,   "linear",  15 },
     96     { MakeRadial,   "radial1", 10 },
     97     { MakeSweep,    "sweep",    1 },
     98     { Make2Radial,  "radial2",  5 },
     99 };
    100 
    101 enum GradType { // these must match the order in gGrads
    102     kLinear_GradType,
    103     kRadial_GradType,
    104     kSweep_GradType,
    105     kRadial2_GradType
    106 };
    107 
    108 enum GeomType {
    109     kRect_GeomType,
    110     kOval_GeomType
    111 };
    112 
    113 static const char* tilemodename(SkShader::TileMode tm) {
    114     switch (tm) {
    115         case SkShader::kClamp_TileMode:
    116             return "clamp";
    117         case SkShader::kRepeat_TileMode:
    118             return "repeat";
    119         case SkShader::kMirror_TileMode:
    120             return "mirror";
    121         default:
    122             SkASSERT(!"unknown tilemode");
    123             return "error";
    124     }
    125 }
    126 
    127 static const char* geomtypename(GeomType gt) {
    128     switch (gt) {
    129         case kRect_GeomType:
    130             return "rectangle";
    131         case kOval_GeomType:
    132             return "oval";
    133         default:
    134             SkASSERT(!"unknown geometry type");
    135             return "error";
    136     }
    137 }
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 
    141 class GradientBench : public SkBenchmark {
    142     SkString fName;
    143     SkShader* fShader;
    144     int      fCount;
    145     enum {
    146         W   = 400,
    147         H   = 400,
    148         N   = 1
    149     };
    150 public:
    151     GradientBench(void* param, GradType gradType,
    152                   SkShader::TileMode tm = SkShader::kClamp_TileMode,
    153                   GeomType geomType = kRect_GeomType,
    154                   float scale = 1.0f)
    155         : INHERITED(param) {
    156         fName.printf("gradient_%s_%s", gGrads[gradType].fName,
    157                      tilemodename(tm));
    158         if (geomType != kRect_GeomType) {
    159             fName.append("_");
    160             fName.append(geomtypename(geomType));
    161         }
    162 
    163         const SkPoint pts[2] = {
    164             { 0, 0 },
    165             { SkIntToScalar(W), SkIntToScalar(H) }
    166         };
    167 
    168         fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
    169         fShader = gGrads[gradType].fMaker(pts, gGradData[0], tm, NULL, scale);
    170         fGeomType = geomType;
    171     }
    172 
    173     virtual ~GradientBench() {
    174         fShader->unref();
    175     }
    176 
    177 protected:
    178     virtual const char* onGetName() {
    179         return fName.c_str();
    180     }
    181 
    182     virtual void onDraw(SkCanvas* canvas) {
    183         SkPaint paint;
    184         this->setupPaint(&paint);
    185 
    186         paint.setShader(fShader);
    187 
    188         SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
    189         for (int i = 0; i < fCount; i++) {
    190             switch (fGeomType) {
    191                case kRect_GeomType:
    192                    canvas->drawRect(r, paint);
    193                    break;
    194                case kOval_GeomType:
    195                    canvas->drawOval(r, paint);
    196                    break;
    197             }
    198         }
    199     }
    200 
    201 private:
    202     typedef SkBenchmark INHERITED;
    203 
    204     GeomType fGeomType;
    205 };
    206 
    207 class Gradient2Bench : public SkBenchmark {
    208 public:
    209     Gradient2Bench(void* param) : INHERITED(param) {}
    210 
    211 protected:
    212     virtual const char* onGetName() {
    213         return "gradient_create";
    214     }
    215 
    216     virtual void onDraw(SkCanvas* canvas) {
    217         SkPaint paint;
    218         this->setupPaint(&paint);
    219 
    220         const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
    221         const SkPoint pts[] = {
    222             { 0, 0 },
    223             { SkIntToScalar(100), SkIntToScalar(100) },
    224         };
    225 
    226         for (int i = 0; i < SkBENCHLOOP(1000); i++) {
    227             const int a = i % 256;
    228             SkColor colors[] = {
    229                 SK_ColorBLACK,
    230                 SkColorSetARGB(a, a, a, a),
    231                 SK_ColorWHITE };
    232             SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
    233                                                          SK_ARRAY_COUNT(colors),
    234                                                          SkShader::kClamp_TileMode);
    235             paint.setShader(s)->unref();
    236             canvas->drawRect(r, paint);
    237         }
    238     }
    239 
    240 private:
    241     typedef SkBenchmark INHERITED;
    242 };
    243 
    244 static SkBenchmark* Fact0(void* p) { return new GradientBench(p, kLinear_GradType); }
    245 static SkBenchmark* Fact01(void* p) { return new GradientBench(p, kLinear_GradType, SkShader::kMirror_TileMode); }
    246 
    247 // Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
    248 // be completely pinned, the other half should pe partially pinned
    249 static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); }
    250 
    251 // Draw a radial gradient on a circle of equal size; all the lines should
    252 // hit the unpinned fast path (so long as GradientBench.W == H)
    253 static SkBenchmark* Fact1o(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kOval_GeomType); }
    254 
    255 static SkBenchmark* Fact11(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kMirror_TileMode); }
    256 static SkBenchmark* Fact2(void* p) { return new GradientBench(p, kSweep_GradType); }
    257 static SkBenchmark* Fact3(void* p) { return new GradientBench(p, kRadial2_GradType); }
    258 static SkBenchmark* Fact31(void* p) { return new GradientBench(p, kRadial2_GradType, SkShader::kMirror_TileMode); }
    259 
    260 static SkBenchmark* Fact4(void* p) { return new Gradient2Bench(p); }
    261 
    262 static BenchRegistry gReg0(Fact0);
    263 static BenchRegistry gReg01(Fact01);
    264 static BenchRegistry gReg1(Fact1);
    265 static BenchRegistry gReg1o(Fact1o);
    266 static BenchRegistry gReg11(Fact11);
    267 static BenchRegistry gReg2(Fact2);
    268 static BenchRegistry gReg3(Fact3);
    269 static BenchRegistry gReg31(Fact31);
    270 
    271 static BenchRegistry gReg4(Fact4);
    272 
    273