1/* 2 * Copyright 2011 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// This is designed to emulate about 4 screens of textual content 19 20 21class PicturePlaybackBench : public Benchmark { 22public: 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); 28 } 29 30 enum { 31 PICTURE_WIDTH = 1000, 32 PICTURE_HEIGHT = 4000, 33 TEXT_SIZE = 10 34 }; 35protected: 36 virtual const char* onGetName() { 37 return fName.c_str(); 38 } 39 40 virtual void onDraw(const int loops, SkCanvas* canvas) { 41 42 SkPictureRecorder recorder; 43 SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0); 44 this->recordCanvas(pCanvas); 45 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 46 47 const SkPoint translateDelta = getTranslateDelta(loops); 48 49 for (int i = 0; i < loops; i++) { 50 picture->playback(canvas); 51 canvas->translate(translateDelta.fX, translateDelta.fY); 52 } 53 } 54 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)); 60 } 61 62 SkString fName; 63 SkScalar fPictureWidth; 64 SkScalar fPictureHeight; 65 SkScalar fTextSize; 66private: 67 typedef Benchmark INHERITED; 68}; 69 70 71class TextPlaybackBench : public PicturePlaybackBench { 72public: 73 TextPlaybackBench() : INHERITED("drawText") { } 74protected: 75 void recordCanvas(SkCanvas* canvas) override { 76 SkPaint paint; 77 paint.setTextSize(fTextSize); 78 paint.setColor(SK_ColorBLACK); 79 80 const char* text = "Hamburgefons"; 81 size_t len = strlen(text); 82 const SkScalar textWidth = paint.measureText(text, len); 83 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); 87 } 88 } 89 } 90private: 91 typedef PicturePlaybackBench INHERITED; 92}; 93 94class PosTextPlaybackBench : public PicturePlaybackBench { 95public: 96 PosTextPlaybackBench(bool drawPosH) 97 : INHERITED(drawPosH ? "drawPosTextH" : "drawPosText") 98 , fDrawPosH(drawPosH) { } 99protected: 100 void recordCanvas(SkCanvas* canvas) override { 101 SkPaint paint; 102 paint.setTextSize(fTextSize); 103 paint.setColor(SK_ColorBLACK); 104 105 const char* text = "Hamburgefons"; 106 size_t len = strlen(text); 107 const SkScalar textWidth = paint.measureText(text, len); 108 109 SkScalar* adv = new SkScalar[len]; 110 paint.getTextWidths(text, len, adv); 111 112 for (SkScalar x = 0; x < fPictureWidth; x += textWidth) { 113 for (SkScalar y = 0; y < fPictureHeight; y += fTextSize) { 114 115 SkPoint* pos = new SkPoint[len]; 116 SkScalar advX = 0; 117 118 for (size_t i = 0; i < len; i++) { 119 if (fDrawPosH) 120 pos[i].set(x + advX, y); 121 else 122 pos[i].set(x + advX, y + i); 123 advX += adv[i]; 124 } 125 126 canvas->drawPosText(text, len, pos, paint); 127 delete[] pos; 128 } 129 } 130 delete[] adv; 131 } 132private: 133 bool fDrawPosH; 134 typedef PicturePlaybackBench INHERITED; 135}; 136 137 138/////////////////////////////////////////////////////////////////////////////// 139 140DEF_BENCH( return new TextPlaybackBench(); ) 141DEF_BENCH( return new PosTextPlaybackBench(true); ) 142DEF_BENCH( return new PosTextPlaybackBench(false); ) 143 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. 147enum BBH { kNone, kRTree }; 148enum Mode { kTiled, kRandom }; 149class TiledPlaybackBench : public Benchmark { 150public: 151 TiledPlaybackBench(BBH bbh, Mode mode) : fBBH(bbh), fMode(mode), fName("tiled_playback") { 152 switch (fBBH) { 153 case kNone: fName.append("_none" ); break; 154 case kRTree: fName.append("_rtree" ); break; 155 } 156 switch (fMode) { 157 case kTiled: fName.append("_tiled" ); break; 158 case kRandom: fName.append("_random"); break; 159 } 160 } 161 162 const char* onGetName() override { return fName.c_str(); } 163 SkIPoint onGetSize() override { return SkIPoint::Make(1024,1024); } 164 165 void onPreDraw() override { 166 SkAutoTDelete<SkBBHFactory> factory; 167 switch (fBBH) { 168 case kNone: break; 169 case kRTree: factory.reset(new SkRTreeFactory); break; 170 } 171 172 SkPictureRecorder recorder; 173 SkCanvas* canvas = recorder.beginRecording(1024, 1024, factory); 174 SkRandom rand; 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); 180 SkPaint paint; 181 paint.setColor(rand.nextU()); 182 paint.setAlpha(0xFF); 183 canvas->drawRect(SkRect::MakeXYWH(x,y,w,h), paint); 184 } 185 fPic.reset(recorder.endRecording()); 186 } 187 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. 191 SkRandom rand; 192 for (int j = 0; j < 10; j++) { 193 SkScalar x = 0, y = 0; 194 switch (fMode) { 195 case kTiled: x = SkScalar(256 * rand.nextULessThan(4)); 196 y = SkScalar(256 * rand.nextULessThan(4)); 197 break; 198 case kRandom: x = rand.nextRangeScalar(0, 768); 199 y = rand.nextRangeScalar(0, 768); 200 break; 201 } 202 SkAutoCanvasRestore ar(canvas, true/*save now*/); 203 canvas->clipRect(SkRect::MakeXYWH(x,y,256,256)); 204 fPic->playback(canvas); 205 } 206 } 207 } 208 209private: 210 BBH fBBH; 211 Mode fMode; 212 SkString fName; 213 SkAutoTUnref<SkPicture> fPic; 214}; 215 216DEF_BENCH( return new TiledPlaybackBench(kNone, kRandom); ) 217DEF_BENCH( return new TiledPlaybackBench(kNone, kTiled ); ) 218DEF_BENCH( return new TiledPlaybackBench(kRTree, kRandom); ) 219DEF_BENCH( return new TiledPlaybackBench(kRTree, kTiled ); ) 220