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