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