1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8#include "Benchmark.h" 9#include "SkCanvas.h" 10#include "SkCommandLineFlags.h" 11#include "SkPaint.h" 12#include "SkRandom.h" 13#include "SkShader.h" 14#include "SkString.h" 15 16DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench."); 17 18class RectBench : public Benchmark { 19public: 20 int fShift, fStroke; 21 enum { 22 W = 640, 23 H = 480, 24 N = 300, 25 }; 26 SkRect fRects[N]; 27 SkColor fColors[N]; 28 29 RectBench(int shift, int stroke = 0) 30 : fShift(shift) 31 , fStroke(stroke) {} 32 33 SkString fName; 34 const char* computeName(const char root[]) { 35 fName.printf("%s_%d", root, fShift); 36 if (fStroke > 0) { 37 fName.appendf("_stroke_%d", fStroke); 38 } 39 return fName.c_str(); 40 } 41 42 bool isVisual() override { return true; } 43 44protected: 45 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 46 c->drawRect(r, p); 47 } 48 49 const char* onGetName() override { return computeName("rects"); } 50 51 void onDelayedSetup() override { 52 SkRandom rand; 53 const SkScalar offset = SK_Scalar1/3; 54 for (int i = 0; i < N; i++) { 55 int x = rand.nextU() % W; 56 int y = rand.nextU() % H; 57 int w = rand.nextU() % W; 58 int h = rand.nextU() % H; 59 w >>= fShift; 60 h >>= fShift; 61 x -= w/2; 62 y -= h/2; 63 fRects[i].set(SkIntToScalar(x), SkIntToScalar(y), 64 SkIntToScalar(x+w), SkIntToScalar(y+h)); 65 fRects[i].offset(offset, offset); 66 fColors[i] = rand.nextU() | 0xFF808080; 67 } 68 } 69 70 void onDraw(int loops, SkCanvas* canvas) override { 71 SkPaint paint; 72 if (fStroke > 0) { 73 paint.setStyle(SkPaint::kStroke_Style); 74 paint.setStrokeWidth(SkIntToScalar(fStroke)); 75 } 76 for (int i = 0; i < loops; i++) { 77 paint.setColor(fColors[i % N]); 78 this->setupPaint(&paint); 79 this->drawThisRect(canvas, fRects[i % N], paint); 80 } 81 } 82private: 83 typedef Benchmark INHERITED; 84}; 85 86class SrcModeRectBench : public RectBench { 87public: 88 SrcModeRectBench() : INHERITED(1, 0) { 89 fMode = SkXfermode::Create(SkXfermode::kSrc_Mode); 90 } 91 92 virtual ~SrcModeRectBench() { 93 SkSafeUnref(fMode); 94 } 95 96protected: 97 void setupPaint(SkPaint* paint) override { 98 this->INHERITED::setupPaint(paint); 99 // srcmode is most interesting when we're not opaque 100 paint->setAlpha(0x80); 101 paint->setXfermode(fMode); 102 } 103 104 const char* onGetName() override { 105 fName.set(this->INHERITED::onGetName()); 106 fName.prepend("srcmode_"); 107 return fName.c_str(); 108 } 109 110private: 111 SkString fName; 112 SkXfermode* fMode; 113 114 typedef RectBench INHERITED; 115}; 116 117class TransparentRectBench : public RectBench { 118public: 119 TransparentRectBench() : INHERITED(1, 0) {} 120 121protected: 122 void setupPaint(SkPaint* paint) override { 123 this->INHERITED::setupPaint(paint); 124 // draw non opaque rect 125 paint->setAlpha(0x80); 126 } 127 128 const char* onGetName() override { 129 fName.set(this->INHERITED::onGetName()); 130 fName.prepend("transparent_"); 131 return fName.c_str(); 132 } 133 134private: 135 SkString fName; 136 137 typedef RectBench INHERITED; 138}; 139 140 141class OvalBench : public RectBench { 142public: 143 OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 144protected: 145 void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override { 146 c->drawOval(r, p); 147 } 148 const char* onGetName() override { return computeName("ovals"); } 149}; 150 151class RRectBench : public RectBench { 152public: 153 RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 154protected: 155 void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override { 156 c->drawRoundRect(r, r.width() / 4, r.height() / 4, p); 157 } 158 const char* onGetName() override { return computeName("rrects"); } 159}; 160 161class PointsBench : public RectBench { 162public: 163 SkCanvas::PointMode fMode; 164 const char* fName; 165 166 PointsBench(SkCanvas::PointMode mode, const char* name) 167 : RectBench(2) 168 , fMode(mode) { 169 fName = name; 170 } 171 172protected: 173 void onDraw(int loops, SkCanvas* canvas) override { 174 SkScalar gSizes[] = { 175 SkIntToScalar(7), 0 176 }; 177 size_t sizes = SK_ARRAY_COUNT(gSizes); 178 179 if (FLAGS_strokeWidth >= 0) { 180 gSizes[0] = (SkScalar)FLAGS_strokeWidth; 181 sizes = 1; 182 } 183 184 SkPaint paint; 185 paint.setStrokeCap(SkPaint::kRound_Cap); 186 187 for (int loop = 0; loop < loops; loop++) { 188 for (size_t i = 0; i < sizes; i++) { 189 paint.setStrokeWidth(gSizes[i]); 190 this->setupPaint(&paint); 191 canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); 192 paint.setColor(fColors[i % N]); 193 } 194 } 195 } 196 const char* onGetName() override { return fName; } 197}; 198 199/******************************************************************************* 200 * to bench BlitMask [Opaque, Black, color, shader] 201 *******************************************************************************/ 202 203class BlitMaskBench : public RectBench { 204public: 205 enum kMaskType { 206 kMaskOpaque = 0, 207 kMaskBlack, 208 kMaskColor, 209 KMaskShader 210 }; 211 SkCanvas::PointMode fMode; 212 const char* fName; 213 214 BlitMaskBench(SkCanvas::PointMode mode, 215 BlitMaskBench::kMaskType type, const char* name) : 216 RectBench(2), fMode(mode), _type(type) { 217 fName = name; 218 } 219 220protected: 221 void onDraw(int loops, SkCanvas* canvas) override { 222 SkScalar gSizes[] = { 223 SkIntToScalar(13), SkIntToScalar(24) 224 }; 225 size_t sizes = SK_ARRAY_COUNT(gSizes); 226 227 if (FLAGS_strokeWidth >= 0) { 228 gSizes[0] = (SkScalar)FLAGS_strokeWidth; 229 sizes = 1; 230 } 231 SkRandom rand; 232 SkColor color = 0xFF000000; 233 U8CPU alpha = 0xFF; 234 SkPaint paint; 235 paint.setStrokeCap(SkPaint::kRound_Cap); 236 if (_type == KMaskShader) { 237 SkBitmap srcBM; 238 srcBM.allocN32Pixels(10, 1); 239 srcBM.eraseColor(0xFF00FF00); 240 241 SkShader* s; 242 s = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode, 243 SkShader::kClamp_TileMode); 244 paint.setShader(s)->unref(); 245 } 246 for (int loop = 0; loop < loops; loop++) { 247 for (size_t i = 0; i < sizes; i++) { 248 switch (_type) { 249 case kMaskOpaque: 250 color = fColors[i]; 251 alpha = 0xFF; 252 break; 253 case kMaskBlack: 254 alpha = 0xFF; 255 color = 0xFF000000; 256 break; 257 case kMaskColor: 258 color = fColors[i]; 259 alpha = rand.nextU() & 255; 260 break; 261 case KMaskShader: 262 break; 263 } 264 paint.setStrokeWidth(gSizes[i]); 265 this->setupPaint(&paint); 266 paint.setColor(color); 267 paint.setAlpha(alpha); 268 canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); 269 } 270 } 271 } 272 const char* onGetName() override { return fName; } 273private: 274 typedef RectBench INHERITED; 275 kMaskType _type; 276}; 277 278DEF_BENCH(return new RectBench(1);) 279DEF_BENCH(return new RectBench(1, 4);) 280DEF_BENCH(return new RectBench(3);) 281DEF_BENCH(return new RectBench(3, 4);) 282DEF_BENCH(return new OvalBench(1);) 283DEF_BENCH(return new OvalBench(3);) 284DEF_BENCH(return new OvalBench(1, 4);) 285DEF_BENCH(return new OvalBench(3, 4);) 286DEF_BENCH(return new RRectBench(1);) 287DEF_BENCH(return new RRectBench(1, 4);) 288DEF_BENCH(return new RRectBench(3);) 289DEF_BENCH(return new RRectBench(3, 4);) 290DEF_BENCH(return new PointsBench(SkCanvas::kPoints_PointMode, "points");) 291DEF_BENCH(return new PointsBench(SkCanvas::kLines_PointMode, "lines");) 292DEF_BENCH(return new PointsBench(SkCanvas::kPolygon_PointMode, "polygon");) 293 294DEF_BENCH(return new SrcModeRectBench();) 295 296DEF_BENCH(return new TransparentRectBench();) 297 298/* init the blitmask bench 299 */ 300DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 301 BlitMaskBench::kMaskOpaque, 302 "maskopaque");) 303DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 304 BlitMaskBench::kMaskBlack, 305 "maskblack");) 306DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 307 BlitMaskBench::kMaskColor, 308 "maskcolor");) 309DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 310 BlitMaskBench::KMaskShader, 311 "maskshader");) 312