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 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 isVisual()42 bool isVisual() override { return true; } 43 44 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)45 virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) { 46 c->drawRect(r, p); 47 } 48 onGetName()49 const char* onGetName() override { return computeName("rects"); } 50 onDelayedSetup()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 onDraw(int loops,SkCanvas * canvas)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 } 82 private: 83 typedef Benchmark INHERITED; 84 }; 85 86 class SrcModeRectBench : public RectBench { 87 public: SrcModeRectBench()88 SrcModeRectBench() : INHERITED(1, 0) { 89 fMode = SkXfermode::Create(SkXfermode::kSrc_Mode); 90 } 91 ~SrcModeRectBench()92 virtual ~SrcModeRectBench() { 93 SkSafeUnref(fMode); 94 } 95 96 protected: setupPaint(SkPaint * paint)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 onGetName()104 const char* onGetName() override { 105 fName.set(this->INHERITED::onGetName()); 106 fName.prepend("srcmode_"); 107 return fName.c_str(); 108 } 109 110 private: 111 SkString fName; 112 SkXfermode* fMode; 113 114 typedef RectBench INHERITED; 115 }; 116 117 class TransparentRectBench : public RectBench { 118 public: TransparentRectBench()119 TransparentRectBench() : INHERITED(1, 0) {} 120 121 protected: setupPaint(SkPaint * paint)122 void setupPaint(SkPaint* paint) override { 123 this->INHERITED::setupPaint(paint); 124 // draw non opaque rect 125 paint->setAlpha(0x80); 126 } 127 onGetName()128 const char* onGetName() override { 129 fName.set(this->INHERITED::onGetName()); 130 fName.prepend("transparent_"); 131 return fName.c_str(); 132 } 133 134 private: 135 SkString fName; 136 137 typedef RectBench INHERITED; 138 }; 139 140 141 class OvalBench : public RectBench { 142 public: OvalBench(int shift,int stroke=0)143 OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 144 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)145 void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override { 146 c->drawOval(r, p); 147 } onGetName()148 const char* onGetName() override { return computeName("ovals"); } 149 }; 150 151 class RRectBench : public RectBench { 152 public: RRectBench(int shift,int stroke=0)153 RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {} 154 protected: drawThisRect(SkCanvas * c,const SkRect & r,const SkPaint & p)155 void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override { 156 c->drawRoundRect(r, r.width() / 4, r.height() / 4, p); 157 } onGetName()158 const char* onGetName() override { return computeName("rrects"); } 159 }; 160 161 class PointsBench : public RectBench { 162 public: 163 SkCanvas::PointMode fMode; 164 const char* fName; 165 PointsBench(SkCanvas::PointMode mode,const char * name)166 PointsBench(SkCanvas::PointMode mode, const char* name) 167 : RectBench(2) 168 , fMode(mode) { 169 fName = name; 170 } 171 172 protected: onDraw(int loops,SkCanvas * canvas)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 } onGetName()196 const char* onGetName() override { return fName; } 197 }; 198 199 /******************************************************************************* 200 * to bench BlitMask [Opaque, Black, color, shader] 201 *******************************************************************************/ 202 203 class BlitMaskBench : public RectBench { 204 public: 205 enum kMaskType { 206 kMaskOpaque = 0, 207 kMaskBlack, 208 kMaskColor, 209 KMaskShader 210 }; 211 SkCanvas::PointMode fMode; 212 const char* fName; 213 BlitMaskBench(SkCanvas::PointMode mode,BlitMaskBench::kMaskType type,const char * name)214 BlitMaskBench(SkCanvas::PointMode mode, 215 BlitMaskBench::kMaskType type, const char* name) : 216 RectBench(2), fMode(mode), _type(type) { 217 fName = name; 218 } 219 220 protected: onDraw(int loops,SkCanvas * canvas)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 } onGetName()272 const char* onGetName() override { return fName; } 273 private: 274 typedef RectBench INHERITED; 275 kMaskType _type; 276 }; 277 278 DEF_BENCH(return new RectBench(1);) 279 DEF_BENCH(return new RectBench(1, 4);) 280 DEF_BENCH(return new RectBench(3);) 281 DEF_BENCH(return new RectBench(3, 4);) 282 DEF_BENCH(return new OvalBench(1);) 283 DEF_BENCH(return new OvalBench(3);) 284 DEF_BENCH(return new OvalBench(1, 4);) 285 DEF_BENCH(return new OvalBench(3, 4);) 286 DEF_BENCH(return new RRectBench(1);) 287 DEF_BENCH(return new RRectBench(1, 4);) 288 DEF_BENCH(return new RRectBench(3);) 289 DEF_BENCH(return new RRectBench(3, 4);) 290 DEF_BENCH(return new PointsBench(SkCanvas::kPoints_PointMode, "points");) 291 DEF_BENCH(return new PointsBench(SkCanvas::kLines_PointMode, "lines");) 292 DEF_BENCH(return new PointsBench(SkCanvas::kPolygon_PointMode, "polygon");) 293 294 DEF_BENCH(return new SrcModeRectBench();) 295 296 DEF_BENCH(return new TransparentRectBench();) 297 298 /* init the blitmask bench 299 */ 300 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 301 BlitMaskBench::kMaskOpaque, 302 "maskopaque");) 303 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 304 BlitMaskBench::kMaskBlack, 305 "maskblack");) 306 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 307 BlitMaskBench::kMaskColor, 308 "maskcolor");) 309 DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode, 310 BlitMaskBench::KMaskShader, 311 "maskshader");) 312