2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "SkPicture.h"
12 #include "SkPictureRecorder.h"
18 // This is designed to emulate about 4 screens of textual content
21 class PicturePlaybackBench : public Benchmark {
23 PicturePlaybackBench(const char name[]) {
24 fName.printf("picture_playback_%s", name);
25 fPictureWidth = SkIntToScalar(PICTURE_WIDTH);
26 fPictureHeight = SkIntToScalar(PICTURE_HEIGHT);
27 fTextSize = SkIntToScalar(TEXT_SIZE);
32 PICTURE_HEIGHT = 4000,
36 virtual const char* onGetName() {
40 virtual void onDraw(const int loops, SkCanvas* canvas) {
42 SkPictureRecorder recorder;
43 SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
44 this->recordCanvas(pCanvas);
45 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
47 const SkPoint translateDelta = getTranslateDelta(loops);
49 for (int i = 0; i < loops; i++) {
50 picture->playback(canvas);
51 canvas->translate(translateDelta.fX, translateDelta.fY);
55 virtual void recordCanvas(SkCanvas* canvas) = 0;
56 virtual SkPoint getTranslateDelta(int N) {
57 SkIPoint canvasSize = onGetSize();
58 return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/N),
59 SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/N));
63 SkScalar fPictureWidth;
64 SkScalar fPictureHeight;
67 typedef Benchmark INHERITED;
71 class TextPlaybackBench : public PicturePlaybackBench {
73 TextPlaybackBench() : INHERITED("drawText") { }
75 void recordCanvas(SkCanvas* canvas) override {
77 paint.setTextSize(fTextSize);
78 paint.setColor(SK_ColorBLACK);
80 const char* text = "Hamburgefons";
81 size_t len = strlen(text);
82 const SkScalar textWidth = paint.measureText(text, len);
84 for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
85 for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
86 canvas->drawText(text, len, x, y, paint);
91 typedef PicturePlaybackBench INHERITED;
94 class PosTextPlaybackBench : public PicturePlaybackBench {
96 PosTextPlaybackBench(bool drawPosH)
97 : INHERITED(drawPosH ? "drawPosTextH" : "drawPosText")
98 , fDrawPosH(drawPosH) { }
100 void recordCanvas(SkCanvas* canvas) override {
102 paint.setTextSize(fTextSize);
103 paint.setColor(SK_ColorBLACK);
105 const char* text = "Hamburgefons";
106 size_t len = strlen(text);
107 const SkScalar textWidth = paint.measureText(text, len);
109 SkScalar* adv = new SkScalar[len];
110 paint.getTextWidths(text, len, adv);
112 for (SkScalar x = 0; x < fPictureWidth; x += textWidth) {
113 for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) {
115 SkPoint* pos = new SkPoint[len];
118 for (size_t i = 0; i < len; i++) {
120 pos[i].set(x + advX, y);
122 pos[i].set(x + advX, y + i);
126 canvas->drawPosText(text, len, pos, paint);
134 typedef PicturePlaybackBench INHERITED;
138 ///////////////////////////////////////////////////////////////////////////////
140 DEF_BENCH( return new TextPlaybackBench(); )
141 DEF_BENCH( return new PosTextPlaybackBench(true); )
142 DEF_BENCH( return new PosTextPlaybackBench(false); )
144 // Chrome draws into small tiles with impl-side painting.
145 // This benchmark measures the relative performance of our bounding-box hierarchies,
146 // both when querying tiles perfectly and when not.
147 enum BBH { kNone, kRTree };
148 enum Mode { kTiled, kRandom };
149 class TiledPlaybackBench : public Benchmark {
151 TiledPlaybackBench(BBH bbh, Mode mode) : fBBH(bbh), fMode(mode), fName("tiled_playback") {
153 case kNone: fName.append("_none" ); break;
154 case kRTree: fName.append("_rtree" ); break;
157 case kTiled: fName.append("_tiled" ); break;
158 case kRandom: fName.append("_random"); break;
162 const char* onGetName() override { return fName.c_str(); }
163 SkIPoint onGetSize() override { return SkIPoint::Make(1024,1024); }
165 void onPreDraw() override {
166 SkAutoTDelete<SkBBHFactory> factory;
169 case kRTree: factory.reset(new SkRTreeFactory); break;
172 SkPictureRecorder recorder;
173 SkCanvas* canvas = recorder.beginRecording(1024, 1024, factory);
175 for (int i = 0; i < 10000; i++) {
176 SkScalar x = rand.nextRangeScalar(0, 1024),
177 y = rand.nextRangeScalar(0, 1024),
178 w = rand.nextRangeScalar(0, 128),
179 h = rand.nextRangeScalar(0, 128);
181 paint.setColor(rand.nextU());
182 paint.setAlpha(0xFF);
183 canvas->drawRect(SkRect::MakeXYWH(x,y,w,h), paint);
185 fPic.reset(recorder.endRecording());
188 void onDraw(const int loops, SkCanvas* canvas) override {
189 for (int i = 0; i < loops; i++) {
190 // This inner loop guarantees we make the same choices for all bench variants.
192 for (int j = 0; j < 10; j++) {
193 SkScalar x = 0, y = 0;
195 case kTiled: x = SkScalar(256 * rand.nextULessThan(4));
196 y = SkScalar(256 * rand.nextULessThan(4));
198 case kRandom: x = rand.nextRangeScalar(0, 768);
199 y = rand.nextRangeScalar(0, 768);
202 SkAutoCanvasRestore ar(canvas, true/*save now*/);
203 canvas->clipRect(SkRect::MakeXYWH(x,y,256,256));
204 fPic->playback(canvas);
213 SkAutoTUnref<SkPicture> fPic;
216 DEF_BENCH( return new TiledPlaybackBench(kNone, kRandom); )
217 DEF_BENCH( return new TiledPlaybackBench(kNone, kTiled ); )
218 DEF_BENCH( return new TiledPlaybackBench(kRTree, kRandom); )
219 DEF_BENCH( return new TiledPlaybackBench(kRTree, kTiled ); )