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 /// Ignores scale
     87 static SkShader* MakeConical(const SkPoint pts[2], const GradData& data,
     88                              SkShader::TileMode tm, SkUnitMapper* mapper,
     89                              float scale) {
     90     SkPoint center0, center1;
     91     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
     92                 SkScalarAve(pts[0].fY, pts[1].fY));
     93     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
     94                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
     95     return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
     96                                                    center0, (pts[1].fX - pts[0].fX) / 2,
     97                                                    data.fColors, data.fPos, data.fCount, tm, mapper);
     98 }
     99 
    100 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
    101                                SkShader::TileMode tm, SkUnitMapper* mapper,
    102                                float scale);
    103 
    104 static const struct {
    105     GradMaker   fMaker;
    106     const char* fName;
    107     int         fRepeat;
    108 } gGrads[] = {
    109     { MakeLinear,   "linear",  15 },
    110     { MakeRadial,   "radial1", 10 },
    111     { MakeSweep,    "sweep",    1 },
    112     { Make2Radial,  "radial2",  5 },
    113     { MakeConical,  "conical",  5 },
    114 };
    115 
    116 enum GradType { // these must match the order in gGrads
    117     kLinear_GradType,
    118     kRadial_GradType,
    119     kSweep_GradType,
    120     kRadial2_GradType,
    121     kConical_GradType
    122 };
    123 
    124 enum GeomType {
    125     kRect_GeomType,
    126     kOval_GeomType
    127 };
    128 
    129 static const char* tilemodename(SkShader::TileMode tm) {
    130     switch (tm) {
    131         case SkShader::kClamp_TileMode:
    132             return "clamp";
    133         case SkShader::kRepeat_TileMode:
    134             return "repeat";
    135         case SkShader::kMirror_TileMode:
    136             return "mirror";
    137         default:
    138             SkASSERT(!"unknown tilemode");
    139             return "error";
    140     }
    141 }
    142 
    143 static const char* geomtypename(GeomType gt) {
    144     switch (gt) {
    145         case kRect_GeomType:
    146             return "rectangle";
    147         case kOval_GeomType:
    148             return "oval";
    149         default:
    150             SkASSERT(!"unknown geometry type");
    151             return "error";
    152     }
    153 }
    154 
    155 ///////////////////////////////////////////////////////////////////////////////
    156 
    157 class GradientBench : public SkBenchmark {
    158     SkString fName;
    159     SkShader* fShader;
    160     int      fCount;
    161     enum {
    162         W   = 400,
    163         H   = 400,
    164         N   = 1
    165     };
    166 public:
    167     GradientBench(void* param, GradType gradType,
    168                   SkShader::TileMode tm = SkShader::kClamp_TileMode,
    169                   GeomType geomType = kRect_GeomType,
    170                   float scale = 1.0f)
    171         : INHERITED(param) {
    172         fName.printf("gradient_%s_%s", gGrads[gradType].fName,
    173                      tilemodename(tm));
    174         if (geomType != kRect_GeomType) {
    175             fName.append("_");
    176             fName.append(geomtypename(geomType));
    177         }
    178 
    179         const SkPoint pts[2] = {
    180             { 0, 0 },
    181             { SkIntToScalar(W), SkIntToScalar(H) }
    182         };
    183 
    184         fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
    185         fShader = gGrads[gradType].fMaker(pts, gGradData[0], tm, NULL, scale);
    186         fGeomType = geomType;
    187     }
    188 
    189     virtual ~GradientBench() {
    190         fShader->unref();
    191     }
    192 
    193 protected:
    194     virtual const char* onGetName() {
    195         return fName.c_str();
    196     }
    197 
    198     virtual void onDraw(SkCanvas* canvas) {
    199         SkPaint paint;
    200         this->setupPaint(&paint);
    201 
    202         paint.setShader(fShader);
    203 
    204         SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
    205         for (int i = 0; i < fCount; i++) {
    206             switch (fGeomType) {
    207                case kRect_GeomType:
    208                    canvas->drawRect(r, paint);
    209                    break;
    210                case kOval_GeomType:
    211                    canvas->drawOval(r, paint);
    212                    break;
    213             }
    214         }
    215     }
    216 
    217 private:
    218     typedef SkBenchmark INHERITED;
    219 
    220     GeomType fGeomType;
    221 };
    222 
    223 class Gradient2Bench : public SkBenchmark {
    224 public:
    225     Gradient2Bench(void* param) : INHERITED(param) {}
    226 
    227 protected:
    228     virtual const char* onGetName() {
    229         return "gradient_create";
    230     }
    231 
    232     virtual void onDraw(SkCanvas* canvas) {
    233         SkPaint paint;
    234         this->setupPaint(&paint);
    235 
    236         const SkRect r = { 0, 0, SkIntToScalar(4), SkIntToScalar(4) };
    237         const SkPoint pts[] = {
    238             { 0, 0 },
    239             { SkIntToScalar(100), SkIntToScalar(100) },
    240         };
    241 
    242         for (int i = 0; i < SkBENCHLOOP(1000); i++) {
    243             const int a = i % 256;
    244             SkColor colors[] = {
    245                 SK_ColorBLACK,
    246                 SkColorSetARGB(a, a, a, a),
    247                 SK_ColorWHITE };
    248             SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
    249                                                          SK_ARRAY_COUNT(colors),
    250                                                          SkShader::kClamp_TileMode);
    251             paint.setShader(s)->unref();
    252             canvas->drawRect(r, paint);
    253         }
    254     }
    255 
    256 private:
    257     typedef SkBenchmark INHERITED;
    258 };
    259 
    260 static SkBenchmark* Fact0(void* p) { return new GradientBench(p, kLinear_GradType); }
    261 static SkBenchmark* Fact01(void* p) { return new GradientBench(p, kLinear_GradType, SkShader::kMirror_TileMode); }
    262 
    263 // Draw a radial gradient of radius 1/2 on a rectangle; half the lines should
    264 // be completely pinned, the other half should pe partially pinned
    265 static SkBenchmark* Fact1(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kRect_GeomType, 0.5f); }
    266 
    267 // Draw a radial gradient on a circle of equal size; all the lines should
    268 // hit the unpinned fast path (so long as GradientBench.W == H)
    269 static SkBenchmark* Fact1o(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kClamp_TileMode, kOval_GeomType); }
    270 
    271 static SkBenchmark* Fact11(void* p) { return new GradientBench(p, kRadial_GradType, SkShader::kMirror_TileMode); }
    272 static SkBenchmark* Fact2(void* p) { return new GradientBench(p, kSweep_GradType); }
    273 static SkBenchmark* Fact3(void* p) { return new GradientBench(p, kRadial2_GradType); }
    274 static SkBenchmark* Fact31(void* p) { return new GradientBench(p, kRadial2_GradType, SkShader::kMirror_TileMode); }
    275 static SkBenchmark* Fact5(void* p) { return new GradientBench(p, kConical_GradType); }
    276 
    277 static SkBenchmark* Fact4(void* p) { return new Gradient2Bench(p); }
    278 
    279 static BenchRegistry gReg0(Fact0);
    280 static BenchRegistry gReg01(Fact01);
    281 static BenchRegistry gReg1(Fact1);
    282 static BenchRegistry gReg1o(Fact1o);
    283 static BenchRegistry gReg11(Fact11);
    284 static BenchRegistry gReg2(Fact2);
    285 static BenchRegistry gReg3(Fact3);
    286 static BenchRegistry gReg31(Fact31);
    287 static BenchRegistry gReg5(Fact5);
    288 
    289 static BenchRegistry gReg4(Fact4);
    290