RectBench.cpp 11 KB

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