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 16 DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench."); 17 18 class RectBench : public Benchmark { 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 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 protected: 43 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 44 c->drawRect(r, p); 45 } 46 47 virtual const char* onGetName() { return computeName("rects"); } 48 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 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 Benchmark INHERITED; 82 }; 83 84 class SrcModeRectBench : public RectBench { 85 public: 86 SrcModeRectBench() : INHERITED(1, 0) { 87 fMode = SkXfermode::Create(SkXfermode::kSrc_Mode); 88 } 89 90 virtual ~SrcModeRectBench() { 91 SkSafeUnref(fMode); 92 } 93 94 protected: 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 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: 117 OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 118 protected: 119 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 120 c->drawOval(r, p); 121 } 122 virtual const char* onGetName() { return computeName("ovals"); } 123 }; 124 125 class RRectBench : public RectBench { 126 public: 127 RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 128 protected: 129 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 130 c->drawRoundRect(r, r.width() / 4, r.height() / 4, p); 131 } 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 140 PointsBench(SkCanvas::PointMode mode, const char* name) 141 : RectBench(2) 142 , fMode(mode) { 143 fName = name; 144 } 145 146 protected: 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 } 170 virtual const char* onGetName() { return fName; } 171 }; 172 173 /******************************************************************************* 174 * to bench BlitMask [Opaque, Black, color, shader] 175 *******************************************************************************/ 176 177 class BlitMaskBench : public RectBench { 178 public: 179 enum kMaskType { 180 kMaskOpaque = 0, 181 kMaskBlack, 182 kMaskColor, 183 KMaskShader 184 }; 185 SkCanvas::PointMode fMode; 186 const char* fName; 187 188 BlitMaskBench(SkCanvas::PointMode mode, 189 BlitMaskBench::kMaskType type, const char* name) : 190 RectBench(2), fMode(mode), _type(type) { 191 fName = name; 192 } 193 194 protected: 195 virtual void onDraw(const int loops, SkCanvas* canvas) { 196 SkScalar gSizes[] = { 197 SkIntToScalar(13), SkIntToScalar(24) 198 }; 199 size_t sizes = SK_ARRAY_COUNT(gSizes); 200 201 if (FLAGS_strokeWidth >= 0) { 202 gSizes[0] = (SkScalar)FLAGS_strokeWidth; 203 sizes = 1; 204 } 205 SkRandom rand; 206 SkColor color = 0xFF000000; 207 U8CPU alpha = 0xFF; 208 SkPaint paint; 209 paint.setStrokeCap(SkPaint::kRound_Cap); 210 if (_type == KMaskShader) { 211 SkBitmap srcBM; 212 srcBM.allocN32Pixels(10, 1); 213 srcBM.eraseColor(0xFF00FF00); 214 215 SkShader* s; 216 s = SkShader::CreateBitmapShader(srcBM, SkShader::kClamp_TileMode, 217 SkShader::kClamp_TileMode); 218 paint.setShader(s)->unref(); 219 } 220 for (int loop = 0; loop < loops; loop++) { 221 for (size_t i = 0; i < sizes; i++) { 222 switch (_type) { 223 case kMaskOpaque: 224 color = fColors[i]; 225 alpha = 0xFF; 226 break; 227 case kMaskBlack: 228 alpha = 0xFF; 229 color = 0xFF000000; 230 break; 231 case kMaskColor: 232 color = fColors[i]; 233 alpha = rand.nextU() & 255; 234 break; 235 case KMaskShader: 236 break; 237 } 238 paint.setStrokeWidth(gSizes[i]); 239 this->setupPaint(&paint); 240 paint.setColor(color); 241 paint.setAlpha(alpha); 242 canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint); 243 } 244 } 245 } 246 virtual const char* onGetName() { return fName; } 247 private: 248 typedef RectBench INHERITED; 249 kMaskType _type; 250 }; 251 252 253 DEF_BENCH( return SkNEW_ARGS(RectBench, (1)); ) 254 DEF_BENCH( return SkNEW_ARGS(RectBench, (1, 4)); ) 255 DEF_BENCH( return SkNEW_ARGS(RectBench, (3)); ) 256 DEF_BENCH( return SkNEW_ARGS(RectBench, (3, 4)); ) 257 DEF_BENCH( return SkNEW_ARGS(OvalBench, (1)); ) 258 DEF_BENCH( return SkNEW_ARGS(OvalBench, (3)); ) 259 DEF_BENCH( return SkNEW_ARGS(OvalBench, (1, 4)); ) 260 DEF_BENCH( return SkNEW_ARGS(OvalBench, (3, 4)); ) 261 DEF_BENCH( return SkNEW_ARGS(RRectBench, (1)); ) 262 DEF_BENCH( return SkNEW_ARGS(RRectBench, (1, 4)); ) 263 DEF_BENCH( return SkNEW_ARGS(RRectBench, (3)); ) 264 DEF_BENCH( return SkNEW_ARGS(RRectBench, (3, 4)); ) 265 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPoints_PointMode, "points")); ) 266 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kLines_PointMode, "lines")); ) 267 DEF_BENCH( return SkNEW_ARGS(PointsBench, (SkCanvas::kPolygon_PointMode, "polygon")); ) 268 269 DEF_BENCH( return SkNEW_ARGS(SrcModeRectBench, ()); ) 270 271 /* init the blitmask bench 272 */ 273 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 274 (SkCanvas::kPoints_PointMode, 275 BlitMaskBench::kMaskOpaque, "maskopaque") 276 ); ) 277 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 278 (SkCanvas::kPoints_PointMode, 279 BlitMaskBench::kMaskBlack, "maskblack") 280 ); ) 281 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 282 (SkCanvas::kPoints_PointMode, 283 BlitMaskBench::kMaskColor, "maskcolor") 284 ); ) 285 DEF_BENCH( return SkNEW_ARGS(BlitMaskBench, 286 (SkCanvas::kPoints_PointMode, 287 BlitMaskBench::KMaskShader, "maskshader") 288 ); ) 289