• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PictureRecordBench(const char name[])20     PictureRecordBench(const char name[])  {
21         fName.printf("picture_record_%s", name);
22     }
23 
isSuitableFor(Backend backend)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:
onGetName()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:
DictionaryRecordBench()51     DictionaryRecordBench() : INHERITED("dictionaries") {}
52 
53 protected:
onDraw(const int loops,SkCanvas *)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 
getTranslateDelta(int M)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:
UniquePaintDictionaryRecordBench()118     UniquePaintDictionaryRecordBench() : INHERITED("unique_paint_dictionary") { }
119 
120 protected:
onDraw(const int loops,SkCanvas *)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:
RecurringPaintDictionaryRecordBench()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:
onDraw(const int loops,SkCanvas *)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