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