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 "SkBenchmark.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 16 DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench."); 17 18 class RectBench : public SkBenchmark { 19 public: 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 RectBench(int shift,int stroke=0)29 RectBench(int shift, int stroke = 0) 30 : fShift(shift) 31 , fStroke(stroke) {} 32 33 SkString fName; computeName(const char root[])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 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)43 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 44 c->drawRect(r, p); 45 } 46 onGetName()47 virtual const char* onGetName() { return computeName("rects"); } 48 onPreDraw()49 virtual void onPreDraw() { 50 SkRandom rand; 51 const SkScalar offset = SK_Scalar1/3; 52 for (int i = 0; i < N; i++) { 53 int x = rand.nextU() % W; 54 int y = rand.nextU() % H; 55 int w = rand.nextU() % W; 56 int h = rand.nextU() % H; 57 w >>= fShift; 58 h >>= fShift; 59 x -= w/2; 60 y -= h/2; 61 fRects[i].set(SkIntToScalar(x), SkIntToScalar(y), 62 SkIntToScalar(x+w), SkIntToScalar(y+h)); 63 fRects[i].offset(offset, offset); 64 fColors[i] = rand.nextU() | 0xFF808080; 65 } 66 } 67 onDraw(const int loops,SkCanvas * canvas)68 virtual void onDraw(const int loops, SkCanvas* canvas) { 69 SkPaint paint; 70 if (fStroke > 0) { 71 paint.setStyle(SkPaint::kStroke_Style); 72 paint.setStrokeWidth(SkIntToScalar(fStroke)); 73 } 74 for (int i = 0; i < loops; i++) { 75 paint.setColor(fColors[i % N]); 76 this->setupPaint(&paint); 77 this->drawThisRect(canvas, fRects[i % N], paint); 78 } 79 } 80 private: 81 typedef SkBenchmark INHERITED; 82 }; 83 84 class SrcModeRectBench : public RectBench { 85 public: SrcModeRectBench()86 SrcModeRectBench() : INHERITED(1, 0) { 87 fMode = SkXfermode::Create(SkXfermode::kSrc_Mode); 88 } 89 ~SrcModeRectBench()90 virtual ~SrcModeRectBench() { 91 SkSafeUnref(fMode); 92 } 93 94 protected: setupPaint(SkPaint * paint)95 virtual void setupPaint(SkPaint* paint) SK_OVERRIDE { 96 this->INHERITED::setupPaint(paint); 97 // srcmode is most interesting when we're not opaque 98 paint->setAlpha(0x80); 99 paint->setXfermode(fMode); 100 } 101 onGetName()102 virtual const char* onGetName() SK_OVERRIDE { 103 fName.set(this->INHERITED::onGetName()); 104 fName.prepend("srcmode_"); 105 return fName.c_str(); 106 } 107 108 private: 109 SkString fName; 110 SkXfermode* fMode; 111 112 typedef RectBench INHERITED; 113 }; 114 115 class OvalBench : public RectBench { 116 public: OvalBench(int shift,int stroke=0)117 OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 118 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)119 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 120 c->drawOval(r, p); 121 } onGetName()122 virtual const char* onGetName() { return computeName("ovals"); } 123 }; 124 125 class RRectBench : public RectBench { 126 public: RRectBench(int shift,int stroke=0)127 RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 128 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)129 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 130 c->drawRoundRect(r, r.width() / 4, r.height() / 4, p); 131 } onGetName()132 virtual const char* onGetName() { return computeName("rrects"); } 133 }; 134 135 class PointsBench : public RectBench { 136 public: 137 SkCanvas::PointMode fMode; 138 const char* fName; 139 PointsBench(SkCanvas::PointMode mode,const char * name)140 PointsBench(SkCanvas::PointMode mode, const char* name) 141 : RectBench(2) 142 , fMode(mode) { 143 fName = name; 144 } 145 146 protected: onDraw(const int loops,SkCanvas * canvas)147 virtual void onDraw(const int loops, SkCanvas* canvas) { 148 SkScalar gSizes[] = { 149 SkIntToScalar(7), 0 150 }; 151 size_t sizes = SK_ARRAY_COUNT(gSizes); 152 153 if (FLAGS_strokeWidth >= 0) { 154 gSizes[0] = (SkScalar)FLAGS_strokeWidth; 155 sizes = 1; 156 } 157 158 SkPaint paint; 159 paint.setStrokeCap(SkPaint::kRound_Cap); 160 161 for (int loop = 0; loop < loops; loop++) { 162 for (size_t i = 0; i < sizes; i++) { 163 paint.setStrokeWidth(gSizes[i]); 164 this->setupPaint(&paint); 165 canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); 166 paint.setColor(fColors[i % N]); 167 } 168 } 169 } onGetName()170 virtual const char* onGetName() { return fName; } 171 }; 172 173 class AARectBench : public SkBenchmark { 174 public: 175 enum { 176 W = 640, 177 H = 480, 178 }; 179 AARectBench(bool rotate)180 AARectBench(bool rotate) : fRotate(rotate) {} 181 182 protected: 183 onGetName()184 virtual const char* onGetName() { 185 if (fRotate) { 186 return "aarects_rotated"; 187 } 188 return "aarects"; 189 } 190 onDraw(const int loops,SkCanvas * canvas)191 virtual void onDraw(const int loops, SkCanvas* canvas) { 192 static const SkScalar kHalfRectSize = 0.75f; 193 194 SkPaint paint; 195 this->setupPaint(&paint); 196 paint.setAntiAlias(true); 197 paint.setColor(SK_ColorBLACK); 198 SkRect r = { -kHalfRectSize, -kHalfRectSize, kHalfRectSize, kHalfRectSize }; 199 int rot = 0; 200 201 for (int i = 0; i < loops; i++) { 202 // Draw small aa rects in a grid across the screen 203 for (SkScalar y = kHalfRectSize+SK_Scalar1; y < H; y += 2*kHalfRectSize+2) { 204 for (SkScalar x = kHalfRectSize+SK_Scalar1; x < W; x += 2*kHalfRectSize+2) { 205 canvas->save(); 206 canvas->translate(x, y); 207 208 if (fRotate) { 209 SkMatrix rotate; 210 rotate.setRotate(SkIntToScalar(rot)); 211 canvas->concat(rotate); 212 rot += 10; 213 } 214 215 canvas->drawRect(r, paint); 216 canvas->restore(); 217 } 218 } 219 } 220 221 } 222 private: 223 bool fRotate; 224 typedef SkBenchmark INHERITED; 225 }; 226 227 /******************************************************************************* 228 * to bench BlitMask [Opaque, Black, color, shader] 229 *******************************************************************************/ 230 231 class BlitMaskBench : public RectBench { 232 public: 233 enum kMaskType { 234 kMaskOpaque = 0, 235 kMaskBlack, 236 kMaskColor, 237 KMaskShader 238 }; 239 SkCanvas::PointMode fMode; 240 const char* fName; 241 BlitMaskBench(SkCanvas::PointMode mode,BlitMaskBench::kMaskType type,const char * name)242 BlitMaskBench(SkCanvas::PointMode mode, 243 BlitMaskBench::kMaskType type, const char* name) : 244 RectBench(2), fMode(mode), _type(type) { 245 fName = name; 246 } 247 248 protected: onDraw(const int loops,SkCanvas * canvas)249 virtual void onDraw(const int loops, SkCanvas* canvas) { 250 SkScalar gSizes[] = { 251 SkIntToScalar(13), SkIntToScalar(24) 252 }; 253 size_t sizes = SK_ARRAY_COUNT(gSizes); 254 255 if (FLAGS_strokeWidth >= 0) { 256 gSizes[0] = (SkScalar)FLAGS_strokeWidth; 257 sizes = 1; 258 } 259 SkRandom rand; 260 SkColor color = 0xFF000000; 261 U8CPU alpha = 0xFF; 262 SkPaint paint; 263 paint.setStrokeCap(SkPaint::kRound_Cap); 264 if (_type == KMaskShader) { 265 SkBitmap srcBM; 266 srcBM.setConfig(SkBitmap::kARGB_8888_Config, 10, 1); 267 srcBM.allocPixels(); 268 srcBM.eraseColor(0xFF00FF00); 269 270 SkShader* s; 271 s = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode, 272 SkShader::kClamp_TileMode); 273 paint.setShader(s)->unref(); 274 } 275 for (int loop = 0; loop < loops; loop++) { 276 for (size_t i = 0; i < sizes; i++) { 277 switch (_type) { 278 case kMaskOpaque: 279 color = fColors[i]; 280 alpha = 0xFF; 281 break; 282 case kMaskBlack: 283 alpha = 0xFF; 284 color = 0xFF000000; 285 break; 286 case kMaskColor: 287 color = fColors[i]; 288 alpha = rand.nextU() & 255; 289 break; 290 case KMaskShader: 291 break; 292 } 293 paint.setStrokeWidth(gSizes[i]); 294 this->setupPaint(&paint); 295 paint.setColor(color); 296 paint.setAlpha(alpha); 297 canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); 298 } 299 } 300 } onGetName()301 virtual const char* onGetName() { return fName; } 302 private: 303 typedef RectBench INHERITED; 304 kMaskType _type; 305 }; 306 307 308 DEF_BENCH( return SkNEW_ARGS(RectBench, (1)); ) 309 DEF_BENCH( return SkNEW_ARGS(RectBench, (1, 4)); ) 310 DEF_BENCH( return SkNEW_ARGS(RectBench, (3)); ) 311 DEF_BENCH( return SkNEW_ARGS(RectBench, (3, 4)); ) 312 DEF_BENCH( return SkNEW_ARGS(OvalBench, (1)); ) 313 DEF_BENCH( return SkNEW_ARGS(OvalBench, (3)); ) 314 DEF_BENCH( return SkNEW_ARGS(OvalBench, (1, 4)); ) 315 DEF_BENCH( return SkNEW_ARGS(OvalBench, (3, 4)); ) 316 DEF_BENCH( return SkNEW_ARGS(RRectBench, (1)); ) 317 DEF_BENCH( return SkNEW_ARGS(RRectBench, (1, 4)); ) 318 DEF_BENCH( return SkNEW_ARGS(RRectBench, (3)); ) 319 DEF_BENCH( return SkNEW_ARGS(RRectBench, (3, 4)); ) 320 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPoints_PointMode, "points")); ) 321 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kLines_PointMode, "lines")); ) 322 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPolygon_PointMode, "polygon")); ) 323 324 DEF_BENCH( return SkNEW_ARGS(SrcModeRectBench, ()); ) 325 326 DEF_BENCH( return SkNEW_ARGS(AARectBench, (false)); ) 327 DEF_BENCH( return SkNEW_ARGS(AARectBench, (true)); ) 328 329 /* init the blitmask bench 330 */ 331 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 332 (SkCanvas::kPoints_PointMode, 333 BlitMaskBench::kMaskOpaque, "maskopaque") 334 ); ) 335 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 336 (SkCanvas::kPoints_PointMode, 337 BlitMaskBench::kMaskBlack, "maskblack") 338 ); ) 339 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 340 (SkCanvas::kPoints_PointMode, 341 BlitMaskBench::kMaskColor, "maskcolor") 342 ); ) 343 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 344 (SkCanvas::kPoints_PointMode, 345 BlitMaskBench::KMaskShader, "maskshader") 346 ); ) 347