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 "SkBenchmark.h"
      8 #include "SkCanvas.h"
      9 #include "SkColor.h"
     10 #include "SkPaint.h"
     11 #include "SkPicture.h"
     12 #include "SkPoint.h"
     13 #include "SkRandom.h"
     14 #include "SkRect.h"
     15 #include "SkString.h"
     16 
     17 class PictureRecordBench : public SkBenchmark {
     18 public:
     19     PictureRecordBench(void* param, const char name[]) : INHERITED(param) {
     20         fName.printf("picture_record_%s", name);
     21         fPictureWidth = SkIntToScalar(PICTURE_WIDTH);
     22         fPictureHeight = SkIntToScalar(PICTURE_HEIGHT);
     23     }
     24 
     25     enum {
     26         N = SkBENCHLOOP(25), // number of times to create the picture
     27         PICTURE_WIDTH = 1000,
     28         PICTURE_HEIGHT = 4000,
     29     };
     30 protected:
     31     virtual const char* onGetName() {
     32         return fName.c_str();
     33     }
     34 
     35     virtual void onDraw(SkCanvas* canvas) {
     36         int n = (int)(N * this->innerLoopScale());
     37         n = SkMax32(1, n);
     38 
     39         for (int i = 0; i < n; i++) {
     40 
     41             SkPicture picture;
     42 
     43             SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
     44             recordCanvas(pCanvas);
     45 
     46             // we don't need to draw the picture as the endRecording step will
     47             // do the work of transferring the recorded content into a playback
     48             // object.
     49             picture.endRecording();
     50         }
     51     }
     52 
     53     virtual void recordCanvas(SkCanvas* canvas) = 0;
     54     virtual float innerLoopScale() const { return 1; }
     55 
     56     SkString fName;
     57     SkScalar fPictureWidth;
     58     SkScalar fPictureHeight;
     59     SkScalar fTextSize;
     60 private:
     61     typedef SkBenchmark INHERITED;
     62 };
     63 
     64 /*
     65  *  An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
     66  *  and regions.  This bench populates those dictionaries to test the speed of
     67  *  reading and writing to those particular dictionary data structures.
     68  */
     69 class DictionaryRecordBench : public PictureRecordBench {
     70 public:
     71     DictionaryRecordBench(void* param)
     72         : INHERITED(param, "dictionaries") { }
     73 
     74     enum {
     75         M = SkBENCHLOOP(100),   // number of elements in each dictionary
     76     };
     77 protected:
     78     virtual void recordCanvas(SkCanvas* canvas) {
     79 
     80         const SkPoint translateDelta = getTranslateDelta();
     81 
     82         for (int i = 0; i < M; i++) {
     83 
     84             SkColor color = SK_ColorYELLOW + (i % 255);
     85             SkIRect rect = SkIRect::MakeWH(i,i);
     86 
     87             canvas->save();
     88 
     89             // set the clip to the given region
     90             SkRegion region;
     91             region.setRect(rect);
     92             canvas->clipRegion(region);
     93 
     94             // fill the clip with a color
     95             SkPaint paint;
     96             paint.setColor(color);
     97             canvas->drawPaint(paint);
     98 
     99             // set a matrix on the canvas
    100             SkMatrix matrix;
    101             matrix.setRotate(SkIntToScalar(i % 360));
    102             canvas->setMatrix(matrix);
    103 
    104             // create a simple bitmap
    105             SkBitmap bitmap;
    106             bitmap.setConfig(SkBitmap::kRGB_565_Config, 10, 10);
    107             bitmap.allocPixels();
    108 
    109             // draw a single color into the bitmap
    110             SkCanvas bitmapCanvas(bitmap);
    111             bitmapCanvas.drawColor(SkColorSetA(color, i % 255));
    112 
    113             // draw the bitmap onto the canvas
    114             canvas->drawBitmapMatrix(bitmap, matrix);
    115 
    116             canvas->restore();
    117             canvas->translate(translateDelta.fX, translateDelta.fY);
    118         }
    119     }
    120 
    121     SkPoint getTranslateDelta() {
    122         SkIPoint canvasSize = onGetSize();
    123         return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
    124                              SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
    125     }
    126 private:
    127     typedef PictureRecordBench INHERITED;
    128 };
    129 
    130 /*
    131  *  Populates the SkPaint dictionary with a large number of unique paint
    132  *  objects that differ only by color
    133  */
    134 class UniquePaintDictionaryRecordBench : public PictureRecordBench {
    135 public:
    136     UniquePaintDictionaryRecordBench(void* param)
    137         : INHERITED(param, "unique_paint_dictionary") { }
    138 
    139     enum {
    140         M = SkBENCHLOOP(15000),   // number of unique paint objects
    141     };
    142 protected:
    143     virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
    144     virtual void recordCanvas(SkCanvas* canvas) {
    145         SkRandom rand;
    146         for (int i = 0; i < M; i++) {
    147             SkPaint paint;
    148             paint.setColor(rand.nextU());
    149             canvas->drawPaint(paint);
    150         }
    151     }
    152 
    153 private:
    154     typedef PictureRecordBench INHERITED;
    155 };
    156 
    157 /*
    158  *  Populates the SkPaint dictionary with a number of unique paint
    159  *  objects that get reused repeatedly
    160  */
    161 class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
    162 public:
    163     RecurringPaintDictionaryRecordBench(void* param)
    164         : INHERITED(param, "recurring_paint_dictionary") { }
    165 
    166     enum {
    167         ObjCount = 100,           // number of unique paint objects
    168         M = SkBENCHLOOP(50000),   // number of draw iterations
    169     };
    170 protected:
    171     virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
    172     virtual void recordCanvas(SkCanvas* canvas) {
    173 
    174         for (int i = 0; i < M; i++) {
    175             SkPaint paint;
    176             paint.setColor(i % ObjCount);
    177             canvas->drawPaint(paint);
    178         }
    179     }
    180 
    181 private:
    182     typedef PictureRecordBench INHERITED;
    183 };
    184 
    185 ///////////////////////////////////////////////////////////////////////////////
    186 
    187 static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); }
    188 static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); }
    189 static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); }
    190 
    191 static BenchRegistry gReg0(Fact0);
    192 static BenchRegistry gReg1(Fact1);
    193 static BenchRegistry gReg2(Fact2);
    194