blob: f23f0cb961187dabd406e7f83abf036a124d874d [file] [log] [blame]
djsollen@google.comdde718c2012-05-30 16:50:11 +00001/*
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"
reed@google.com7fe64092012-07-10 13:17:45 +000013#include "SkRandom.h"
djsollen@google.comdde718c2012-05-30 16:50:11 +000014#include "SkRect.h"
15#include "SkString.h"
16
17class PictureRecordBench : public SkBenchmark {
18public:
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);
bsalomon@google.com9e679352013-05-30 19:52:38 +000023 fIsRendering = false;
djsollen@google.comdde718c2012-05-30 16:50:11 +000024 }
25
26 enum {
27 N = SkBENCHLOOP(25), // number of times to create the picture
28 PICTURE_WIDTH = 1000,
29 PICTURE_HEIGHT = 4000,
30 };
31protected:
32 virtual const char* onGetName() {
33 return fName.c_str();
34 }
35
sugoi@google.com77472f02013-03-05 18:50:01 +000036 virtual void onDraw(SkCanvas*) {
reed@google.comf1d46952012-07-03 13:53:41 +000037 int n = (int)(N * this->innerLoopScale());
38 n = SkMax32(1, n);
djsollen@google.comdde718c2012-05-30 16:50:11 +000039
reed@google.comf1d46952012-07-03 13:53:41 +000040 for (int i = 0; i < n; i++) {
djsollen@google.comdde718c2012-05-30 16:50:11 +000041
42 SkPicture picture;
43
44 SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
45 recordCanvas(pCanvas);
46
47 // we don't need to draw the picture as the endRecording step will
48 // do the work of transferring the recorded content into a playback
49 // object.
50 picture.endRecording();
51 }
52 }
53
54 virtual void recordCanvas(SkCanvas* canvas) = 0;
reed@google.comf1d46952012-07-03 13:53:41 +000055 virtual float innerLoopScale() const { return 1; }
djsollen@google.comdde718c2012-05-30 16:50:11 +000056
57 SkString fName;
58 SkScalar fPictureWidth;
59 SkScalar fPictureHeight;
60 SkScalar fTextSize;
61private:
62 typedef SkBenchmark INHERITED;
63};
64
65/*
66 * An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
67 * and regions. This bench populates those dictionaries to test the speed of
68 * reading and writing to those particular dictionary data structures.
69 */
70class DictionaryRecordBench : public PictureRecordBench {
71public:
72 DictionaryRecordBench(void* param)
73 : INHERITED(param, "dictionaries") { }
74
75 enum {
76 M = SkBENCHLOOP(100), // number of elements in each dictionary
77 };
78protected:
79 virtual void recordCanvas(SkCanvas* canvas) {
80
81 const SkPoint translateDelta = getTranslateDelta();
82
83 for (int i = 0; i < M; i++) {
84
85 SkColor color = SK_ColorYELLOW + (i % 255);
86 SkIRect rect = SkIRect::MakeWH(i,i);
87
88 canvas->save();
89
90 // set the clip to the given region
91 SkRegion region;
92 region.setRect(rect);
93 canvas->clipRegion(region);
94
95 // fill the clip with a color
96 SkPaint paint;
97 paint.setColor(color);
98 canvas->drawPaint(paint);
99
100 // set a matrix on the canvas
101 SkMatrix matrix;
102 matrix.setRotate(SkIntToScalar(i % 360));
103 canvas->setMatrix(matrix);
104
105 // create a simple bitmap
106 SkBitmap bitmap;
107 bitmap.setConfig(SkBitmap::kRGB_565_Config, 10, 10);
108 bitmap.allocPixels();
109
110 // draw a single color into the bitmap
111 SkCanvas bitmapCanvas(bitmap);
112 bitmapCanvas.drawColor(SkColorSetA(color, i % 255));
113
114 // draw the bitmap onto the canvas
115 canvas->drawBitmapMatrix(bitmap, matrix);
116
117 canvas->restore();
118 canvas->translate(translateDelta.fX, translateDelta.fY);
119 }
120 }
121
122 SkPoint getTranslateDelta() {
123 SkIPoint canvasSize = onGetSize();
124 return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
125 SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
126 }
127private:
128 typedef PictureRecordBench INHERITED;
129};
130
junov@chromium.orgef760602012-06-27 20:03:16 +0000131/*
132 * Populates the SkPaint dictionary with a large number of unique paint
133 * objects that differ only by color
134 */
135class UniquePaintDictionaryRecordBench : public PictureRecordBench {
136public:
137 UniquePaintDictionaryRecordBench(void* param)
138 : INHERITED(param, "unique_paint_dictionary") { }
139
140 enum {
141 M = SkBENCHLOOP(15000), // number of unique paint objects
142 };
143protected:
reed@google.comf1d46952012-07-03 13:53:41 +0000144 virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
junov@chromium.orgef760602012-06-27 20:03:16 +0000145 virtual void recordCanvas(SkCanvas* canvas) {
reed@google.com7fe64092012-07-10 13:17:45 +0000146 SkRandom rand;
junov@chromium.orgef760602012-06-27 20:03:16 +0000147 for (int i = 0; i < M; i++) {
148 SkPaint paint;
reed@google.com7fe64092012-07-10 13:17:45 +0000149 paint.setColor(rand.nextU());
junov@chromium.orgef760602012-06-27 20:03:16 +0000150 canvas->drawPaint(paint);
151 }
152 }
153
154private:
155 typedef PictureRecordBench INHERITED;
156};
157
158/*
159 * Populates the SkPaint dictionary with a number of unique paint
commit-bot@chromium.org0c4e21d2013-07-11 14:26:09 +0000160 * objects that get reused repeatedly.
161 *
162 * Re-creating the paint objects in the inner loop slows the benchmark down 10%.
163 * Using setColor(i % objCount) instead of a random color creates a very high rate
164 * of hash conflicts, slowing us down 12%.
junov@chromium.orgef760602012-06-27 20:03:16 +0000165 */
166class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
167public:
168 RecurringPaintDictionaryRecordBench(void* param)
commit-bot@chromium.org0c4e21d2013-07-11 14:26:09 +0000169 : INHERITED(param, "recurring_paint_dictionary") {
170 SkRandom rand;
171 for (int i = 0; i < ObjCount; i++) {
172 fPaint[i].setColor(rand.nextU());
173 }
174 }
junov@chromium.orgef760602012-06-27 20:03:16 +0000175
176 enum {
177 ObjCount = 100, // number of unique paint objects
178 M = SkBENCHLOOP(50000), // number of draw iterations
179 };
180protected:
reed@google.comf1d46952012-07-03 13:53:41 +0000181 virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
junov@chromium.orgef760602012-06-27 20:03:16 +0000182 virtual void recordCanvas(SkCanvas* canvas) {
183
184 for (int i = 0; i < M; i++) {
commit-bot@chromium.org0c4e21d2013-07-11 14:26:09 +0000185 canvas->drawPaint(fPaint[i % ObjCount]);
junov@chromium.orgef760602012-06-27 20:03:16 +0000186 }
187 }
188
189private:
commit-bot@chromium.org0c4e21d2013-07-11 14:26:09 +0000190 SkPaint fPaint [ObjCount];
junov@chromium.orgef760602012-06-27 20:03:16 +0000191 typedef PictureRecordBench INHERITED;
192};
193
djsollen@google.comdde718c2012-05-30 16:50:11 +0000194///////////////////////////////////////////////////////////////////////////////
195
196static SkBenchmark* Fact0(void* p) { return new DictionaryRecordBench(p); }
junov@chromium.orgef760602012-06-27 20:03:16 +0000197static SkBenchmark* Fact1(void* p) { return new UniquePaintDictionaryRecordBench(p); }
198static SkBenchmark* Fact2(void* p) { return new RecurringPaintDictionaryRecordBench(p); }
djsollen@google.comdde718c2012-05-30 16:50:11 +0000199
200static BenchRegistry gReg0(Fact0);
junov@chromium.orgef760602012-06-27 20:03:16 +0000201static BenchRegistry gReg1(Fact1);
202static BenchRegistry gReg2(Fact2);