Home | History | Annotate | Download | only in bench
      1 /*
      2  * Copyright 2012 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 #include "Benchmark.h"
      8 #include "SkCanvas.h"
      9 #include "SkColor.h"
     10 #include "SkPaint.h"
     11 #include "SkPicture.h"
     12 #include "SkPictureRecorder.h"
     13 #include "SkPoint.h"
     14 #include "SkRandom.h"
     15 #include "SkRect.h"
     16 #include "SkString.h"
     17 
     18 class PictureRecordBench : public Benchmark {
     19 public:
     20     PictureRecordBench(const char name[])  {
     21         fName.printf("picture_record_%s", name);
     22     }
     23 
     24     virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
     25         return backend == kNonRendering_Backend;
     26     }
     27 
     28     enum {
     29         PICTURE_WIDTH = 1000,
     30         PICTURE_HEIGHT = 4000,
     31     };
     32 protected:
     33     virtual const char* onGetName() SK_OVERRIDE {
     34         return fName.c_str();
     35     }
     36 private:
     37     SkString fName;
     38     typedef Benchmark INHERITED;
     39 };
     40 
     41 
     42 static const int kMaxLoopsPerCanvas = 10000;
     43 
     44 /*
     45  *  An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
     46  *  and regions.  This bench populates those dictionaries to test the speed of
     47  *  reading and writing to those particular dictionary data structures.
     48  */
     49 class DictionaryRecordBench : public PictureRecordBench {
     50 public:
     51     DictionaryRecordBench() : INHERITED("dictionaries") {}
     52 
     53 protected:
     54     virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
     55         SkPictureRecorder recorder;
     56         SkCanvas* canvas = NULL;
     57 
     58         const SkPoint translateDelta = getTranslateDelta(loops);
     59 
     60         for (int i = 0; i < loops; i++) {
     61             if (0 == i % kMaxLoopsPerCanvas) {
     62                 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
     63                 canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
     64             }
     65 
     66             SkColor color = SK_ColorYELLOW + (i % 255);
     67             SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);
     68 
     69             canvas->save();
     70 
     71             // set the clip to the given region
     72             SkRegion region;
     73             region.setRect(rect);
     74             canvas->clipRegion(region);
     75 
     76             // fill the clip with a color
     77             SkPaint paint;
     78             paint.setColor(color);
     79             canvas->drawPaint(paint);
     80 
     81             // set a matrix on the canvas
     82             SkMatrix matrix;
     83             matrix.setRotate(SkIntToScalar(i % 360));
     84             canvas->setMatrix(matrix);
     85 
     86             // create a simple bitmap
     87             SkBitmap bitmap;
     88             bitmap.allocPixels(SkImageInfo::Make(10, 10,
     89                                                  kRGB_565_SkColorType, kOpaque_SkAlphaType));
     90 
     91             // draw a single color into the bitmap
     92             SkCanvas bitmapCanvas(bitmap);
     93             bitmapCanvas.drawColor(SkColorSetA(color, i % 255));
     94 
     95             // draw the bitmap onto the canvas
     96             canvas->drawBitmapMatrix(bitmap, matrix);
     97 
     98             canvas->restore();
     99             canvas->translate(translateDelta.fX, translateDelta.fY);
    100         }
    101     }
    102 
    103     SkPoint getTranslateDelta(int M) {
    104         SkIPoint canvasSize = onGetSize();
    105         return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
    106                              SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
    107     }
    108 private:
    109     typedef PictureRecordBench INHERITED;
    110 };
    111 
    112 /*
    113  *  Populates the SkPaint dictionary with a large number of unique paint
    114  *  objects that differ only by color
    115  */
    116 class UniquePaintDictionaryRecordBench : public PictureRecordBench {
    117 public:
    118     UniquePaintDictionaryRecordBench() : INHERITED("unique_paint_dictionary") { }
    119 
    120 protected:
    121     virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
    122         SkRandom rand;
    123         SkPaint paint;
    124         SkPictureRecorder recorder;
    125         SkCanvas* canvas = NULL;
    126         for (int i = 0; i < loops; i++) {
    127             if (0 == i % kMaxLoopsPerCanvas) {
    128                 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    129                 canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
    130             }
    131             paint.setColor(rand.nextU());
    132             canvas->drawPaint(paint);
    133         }
    134     }
    135 
    136 private:
    137     typedef PictureRecordBench INHERITED;
    138 };
    139 
    140 /*
    141  *  Populates the SkPaint dictionary with a number of unique paint
    142  *  objects that get reused repeatedly.
    143  *
    144  *  Re-creating the paint objects in the inner loop slows the benchmark down 10%.
    145  *  Using setColor(i % objCount) instead of a random color creates a very high rate
    146  *  of hash conflicts, slowing us down 12%.
    147  */
    148 class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
    149 public:
    150     RecurringPaintDictionaryRecordBench() : INHERITED("recurring_paint_dictionary") {
    151         SkRandom rand;
    152         for (int i = 0; i < ObjCount; i++) {
    153             fPaint[i].setColor(rand.nextU());
    154         }
    155     }
    156 
    157     enum {
    158         ObjCount = 100,  // number of unique paint objects
    159     };
    160 protected:
    161     virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
    162         SkPictureRecorder recorder;
    163         SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
    164         for (int i = 0; i < loops; i++) {
    165             canvas->drawPaint(fPaint[i % ObjCount]);
    166         }
    167     }
    168 
    169 private:
    170     SkPaint fPaint [ObjCount];
    171     typedef PictureRecordBench INHERITED;
    172 };
    173 
    174 ///////////////////////////////////////////////////////////////////////////////
    175 
    176 DEF_BENCH( return new DictionaryRecordBench(); )
    177 DEF_BENCH( return new UniquePaintDictionaryRecordBench(); )
    178 DEF_BENCH( return new RecurringPaintDictionaryRecordBench(); )
    179