Home | History | Annotate | Download | only in bench
      1 /*
      2  * Copyright 2011 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 "SkBenchmark.h"
      9 #include "SkAAClip.h"
     10 #include "SkPath.h"
     11 #include "SkRegion.h"
     12 #include "SkString.h"
     13 #include "SkCanvas.h"
     14 #include "SkRandom.h"
     15 
     16 ////////////////////////////////////////////////////////////////////////////////
     17 // This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls
     18 class AAClipBench : public SkBenchmark {
     19     SkString fName;
     20     SkPath   fClipPath;
     21     SkRect   fClipRect;
     22     SkRect   fDrawRect;
     23     bool     fDoPath;
     24     bool     fDoAA;
     25 
     26     enum {
     27         N = SkBENCHLOOP(200),
     28     };
     29 
     30 public:
     31     AAClipBench(void* param, bool doPath, bool doAA)
     32         : INHERITED(param)
     33         , fDoPath(doPath)
     34         , fDoAA(doAA) {
     35 
     36         fName.printf("aaclip_%s_%s",
     37                      doPath ? "path" : "rect",
     38                      doAA ? "AA" : "BW");
     39 
     40         fClipRect.set(SkFloatToScalar(10.5f), SkFloatToScalar(10.5f),
     41                       SkFloatToScalar(50.5f), SkFloatToScalar(50.5f));
     42         fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10));
     43         fDrawRect.set(SkIntToScalar(0), SkIntToScalar(0),
     44                       SkIntToScalar(100), SkIntToScalar(100));
     45 
     46         SkASSERT(fClipPath.isConvex());
     47     }
     48 
     49 protected:
     50     virtual const char* onGetName() { return fName.c_str(); }
     51     virtual void onDraw(SkCanvas* canvas) {
     52 
     53         SkPaint paint;
     54         this->setupPaint(&paint);
     55 
     56         for (int i = 0; i < N; ++i) {
     57             // jostle the clip regions each time to prevent caching
     58             fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0);
     59             fClipPath.reset();
     60             fClipPath.addRoundRect(fClipRect,
     61                                    SkIntToScalar(5), SkIntToScalar(5));
     62             SkASSERT(fClipPath.isConvex());
     63 
     64             canvas->save();
     65 #if 1
     66             if (fDoPath) {
     67                 canvas->clipPath(fClipPath, SkRegion::kReplace_Op, fDoAA);
     68             } else {
     69                 canvas->clipRect(fClipRect, SkRegion::kReplace_Op, fDoAA);
     70             }
     71 
     72             canvas->drawRect(fDrawRect, paint);
     73 #else
     74             // this path tests out directly draw the clip primitive
     75             // use it to comparing just drawing the clip vs. drawing using
     76             // the clip
     77             if (fDoPath) {
     78                 canvas->drawPath(fClipPath, paint);
     79             } else {
     80                 canvas->drawRect(fClipRect, paint);
     81             }
     82 #endif
     83             canvas->restore();
     84         }
     85     }
     86 private:
     87     typedef SkBenchmark INHERITED;
     88 };
     89 
     90 ////////////////////////////////////////////////////////////////////////////////
     91 // This bench tests out nested clip stacks. It is intended to simulate
     92 // how WebKit nests clips.
     93 class NestedAAClipBench : public SkBenchmark {
     94     SkString fName;
     95     bool     fDoAA;
     96     SkRect   fDrawRect;
     97     SkRandom fRandom;
     98 
     99     static const int kNumDraws = SkBENCHLOOP(2);
    100     static const int kNestingDepth = 3;
    101     static const int kImageSize = 400;
    102 
    103     SkPoint fSizes[kNestingDepth+1];
    104 
    105 public:
    106     NestedAAClipBench(void* param, bool doAA)
    107         : INHERITED(param)
    108         , fDoAA(doAA) {
    109 
    110         fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW");
    111 
    112         fDrawRect = SkRect::MakeLTRB(0, 0,
    113                                      SkIntToScalar(kImageSize),
    114                                      SkIntToScalar(kImageSize));
    115 
    116         fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize));
    117 
    118         for (int i = 1; i < kNestingDepth+1; ++i) {
    119             fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2);
    120         }
    121     }
    122 
    123 protected:
    124     virtual const char* onGetName() { return fName.c_str(); }
    125 
    126 
    127     void recurse(SkCanvas* canvas,
    128                  int depth,
    129                  const SkPoint& offset) {
    130 
    131             canvas->save();
    132 
    133             SkRect temp = SkRect::MakeLTRB(0, 0,
    134                                            fSizes[depth].fX, fSizes[depth].fY);
    135             temp.offset(offset);
    136 
    137             SkPath path;
    138             path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3));
    139             SkASSERT(path.isConvex());
    140 
    141             canvas->clipPath(path,
    142                              0 == depth ? SkRegion::kReplace_Op :
    143                                           SkRegion::kIntersect_Op,
    144                              fDoAA);
    145 
    146             if (kNestingDepth == depth) {
    147                 // we only draw the draw rect at the lowest nesting level
    148                 SkPaint paint;
    149                 paint.setColor(0xff000000 | fRandom.nextU());
    150                 canvas->drawRect(fDrawRect, paint);
    151             } else {
    152                 SkPoint childOffset = offset;
    153                 this->recurse(canvas, depth+1, childOffset);
    154 
    155                 childOffset += fSizes[depth+1];
    156                 this->recurse(canvas, depth+1, childOffset);
    157 
    158                 childOffset.fX = offset.fX + fSizes[depth+1].fX;
    159                 childOffset.fY = offset.fY;
    160                 this->recurse(canvas, depth+1, childOffset);
    161 
    162                 childOffset.fX = offset.fX;
    163                 childOffset.fY = offset.fY + fSizes[depth+1].fY;
    164                 this->recurse(canvas, depth+1, childOffset);
    165             }
    166 
    167             canvas->restore();
    168     }
    169 
    170     virtual void onDraw(SkCanvas* canvas) {
    171 
    172         for (int i = 0; i < kNumDraws; ++i) {
    173             SkPoint offset = SkPoint::Make(0, 0);
    174             this->recurse(canvas, 0, offset);
    175         }
    176     }
    177 
    178 private:
    179     typedef SkBenchmark INHERITED;
    180 };
    181 
    182 ////////////////////////////////////////////////////////////////////////////////
    183 class AAClipBuilderBench : public SkBenchmark {
    184     SkString fName;
    185     SkPath   fPath;
    186     SkRect   fRect;
    187     SkRegion fRegion;
    188     bool     fDoPath;
    189     bool     fDoAA;
    190 
    191     enum {
    192         N = SkBENCHLOOP(200),
    193     };
    194 
    195 public:
    196     AAClipBuilderBench(void* param, bool doPath, bool doAA) : INHERITED(param) {
    197         fDoPath = doPath;
    198         fDoAA = doAA;
    199 
    200         fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect",
    201                      doAA ? "AA" : "BW");
    202 
    203         fRegion.setRect(0, 0, 640, 480);
    204         fRect.set(fRegion.getBounds());
    205         fRect.inset(SK_Scalar1/4, SK_Scalar1/4);
    206         fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20));
    207     }
    208 
    209 protected:
    210     virtual const char* onGetName() { return fName.c_str(); }
    211     virtual void onDraw(SkCanvas*) {
    212         SkPaint paint;
    213         this->setupPaint(&paint);
    214 
    215         for (int i = 0; i < N; ++i) {
    216             SkAAClip clip;
    217             if (fDoPath) {
    218                 clip.setPath(fPath, &fRegion, fDoAA);
    219             } else {
    220                 clip.setRect(fRect, fDoAA);
    221             }
    222         }
    223     }
    224 private:
    225     typedef SkBenchmark INHERITED;
    226 };
    227 
    228 ////////////////////////////////////////////////////////////////////////////////
    229 class AAClipRegionBench : public SkBenchmark {
    230 public:
    231     AAClipRegionBench(void* param) : INHERITED(param) {
    232         SkPath path;
    233         // test conversion of a complex clip to a aaclip
    234         path.addCircle(0, 0, SkIntToScalar(200));
    235         path.addCircle(0, 0, SkIntToScalar(180));
    236         // evenodd means we've constructed basically a stroked circle
    237         path.setFillType(SkPath::kEvenOdd_FillType);
    238 
    239         SkIRect bounds;
    240         path.getBounds().roundOut(&bounds);
    241         fRegion.setPath(path, SkRegion(bounds));
    242     }
    243 
    244 protected:
    245     virtual const char* onGetName() { return "aaclip_setregion"; }
    246     virtual void onDraw(SkCanvas*) {
    247         for (int i = 0; i < N; ++i) {
    248             SkAAClip clip;
    249             clip.setRegion(fRegion);
    250         }
    251     }
    252 
    253 private:
    254     enum {
    255         N = SkBENCHLOOP(400),
    256     };
    257     SkRegion fRegion;
    258     typedef SkBenchmark INHERITED;
    259 };
    260 
    261 ////////////////////////////////////////////////////////////////////////////////
    262 
    263 static SkBenchmark* Fact0(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, false)); }
    264 static SkBenchmark* Fact1(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, true)); }
    265 static SkBenchmark* Fact2(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, true, false)); }
    266 static SkBenchmark* Fact3(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, true, true)); }
    267 
    268 static BenchRegistry gReg0(Fact0);
    269 static BenchRegistry gReg1(Fact1);
    270 static BenchRegistry gReg2(Fact2);
    271 static BenchRegistry gReg3(Fact3);
    272 
    273 static SkBenchmark* Fact01(void* p) { return SkNEW_ARGS(AAClipRegionBench, (p)); }
    274 static BenchRegistry gReg01(Fact01);
    275 
    276 static SkBenchmark* Fact000(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, false)); }
    277 static SkBenchmark* Fact001(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, true)); }
    278 static SkBenchmark* Fact002(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, false)); }
    279 static SkBenchmark* Fact003(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, true)); }
    280 
    281 static BenchRegistry gReg000(Fact000);
    282 static BenchRegistry gReg001(Fact001);
    283 static BenchRegistry gReg002(Fact002);
    284 static BenchRegistry gReg003(Fact003);
    285 
    286 static SkBenchmark* Fact004(void* p) { return SkNEW_ARGS(NestedAAClipBench, (p, false)); }
    287 static SkBenchmark* Fact005(void* p) { return SkNEW_ARGS(NestedAAClipBench, (p, true)); }
    288 
    289 static BenchRegistry gReg004(Fact004);
    290 static BenchRegistry gReg005(Fact005);
    291