BitmapBench.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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/SkColorPriv.h"
  11. #include "include/core/SkPaint.h"
  12. #include "include/core/SkString.h"
  13. #include "include/utils/SkRandom.h"
  14. #include "tools/ToolUtils.h"
  15. /* Variants for bitmaps
  16. - src depth (32 w+w/o alpha), 565, 4444, index, a8
  17. - paint options: filtering, dither, alpha
  18. - matrix options: translate, scale, rotate, persp
  19. - tiling: none, repeat, mirror, clamp
  20. */
  21. class BitmapBench : public Benchmark {
  22. const SkColorType fColorType;
  23. const SkAlphaType fAlphaType;
  24. const bool fForceUpdate; //bitmap marked as dirty before each draw. forces bitmap to be updated on device cache
  25. const bool fIsVolatile;
  26. const bool fDoScale;
  27. SkBitmap fBitmap;
  28. SkPaint fPaint;
  29. SkString fName;
  30. enum { W = 128 };
  31. enum { H = 128 };
  32. public:
  33. BitmapBench(SkColorType ct, SkAlphaType at, bool forceUpdate, bool isVolatile, bool doScale)
  34. : fColorType(ct)
  35. , fAlphaType(at)
  36. , fForceUpdate(forceUpdate)
  37. , fIsVolatile(isVolatile)
  38. , fDoScale(doScale)
  39. {}
  40. protected:
  41. const char* onGetName() override {
  42. fName.set("bitmap");
  43. fName.appendf("_%s%s",
  44. ToolUtils::colortype_name(fColorType),
  45. kOpaque_SkAlphaType == fAlphaType ? "" : "_A");
  46. if (fDoScale) {
  47. fName.append("_scale");
  48. }
  49. if (fForceUpdate) {
  50. fName.append("_update");
  51. }
  52. if (fIsVolatile) {
  53. fName.append("_volatile");
  54. }
  55. return fName.c_str();
  56. }
  57. void onDelayedSetup() override {
  58. SkBitmap bm;
  59. bm.allocPixels(SkImageInfo::Make(W, H, fColorType, fAlphaType));
  60. bm.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorBLACK : 0);
  61. this->onDrawIntoBitmap(bm);
  62. fBitmap = bm;
  63. fBitmap.setIsVolatile(fIsVolatile);
  64. }
  65. void onDraw(int loops, SkCanvas* canvas) override {
  66. if (fDoScale) {
  67. canvas->scale(.99f, .99f);
  68. }
  69. SkIPoint dim = this->getSize();
  70. SkRandom rand;
  71. SkPaint paint(fPaint);
  72. this->setupPaint(&paint);
  73. const SkBitmap& bitmap = fBitmap;
  74. const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
  75. const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
  76. for (int i = 0; i < loops; i++) {
  77. SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
  78. SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
  79. if (fForceUpdate)
  80. bitmap.notifyPixelsChanged();
  81. canvas->drawBitmap(bitmap, x, y, &paint);
  82. }
  83. }
  84. virtual void onDrawIntoBitmap(const SkBitmap& bm) {
  85. const int w = bm.width();
  86. const int h = bm.height();
  87. SkCanvas canvas(bm);
  88. SkPaint p;
  89. p.setAntiAlias(true);
  90. p.setColor(SK_ColorRED);
  91. canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
  92. SkIntToScalar(SkMin32(w, h))*3/8, p);
  93. SkRect r;
  94. r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
  95. p.setStyle(SkPaint::kStroke_Style);
  96. p.setStrokeWidth(SkIntToScalar(4));
  97. p.setColor(SK_ColorBLUE);
  98. canvas.drawRect(r, p);
  99. }
  100. private:
  101. typedef Benchmark INHERITED;
  102. };
  103. /** Explicitly invoke some filter types to improve coverage of acceleration
  104. procs. */
  105. enum Flags {
  106. kScale_Flag = 1 << 0,
  107. kRotate_Flag = 1 << 1,
  108. kBilerp_Flag = 1 << 2,
  109. kBicubic_Flag = 1 << 3,
  110. };
  111. static bool isBilerp(uint32_t flags) {
  112. return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag);
  113. }
  114. static bool isBicubic(uint32_t flags) {
  115. return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag);
  116. }
  117. class FilterBitmapBench : public BitmapBench {
  118. uint32_t fFlags;
  119. SkString fFullName;
  120. public:
  121. FilterBitmapBench(SkColorType ct, SkAlphaType at,
  122. bool forceUpdate, bool isVolitile, uint32_t flags)
  123. : INHERITED(ct, at, forceUpdate, isVolitile, false)
  124. , fFlags(flags) {
  125. }
  126. protected:
  127. const char* onGetName() override {
  128. fFullName.set(INHERITED::onGetName());
  129. if (fFlags & kScale_Flag) {
  130. fFullName.append("_scale");
  131. }
  132. if (fFlags & kRotate_Flag) {
  133. fFullName.append("_rotate");
  134. }
  135. if (isBilerp(fFlags)) {
  136. fFullName.append("_bilerp");
  137. } else if (isBicubic(fFlags)) {
  138. fFullName.append("_bicubic");
  139. }
  140. return fFullName.c_str();
  141. }
  142. void onDraw(int loops, SkCanvas* canvas) override {
  143. SkISize dim = canvas->getBaseLayerSize();
  144. if (fFlags & kScale_Flag) {
  145. const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
  146. const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
  147. canvas->translate(x, y);
  148. // just enough so we can't take the sprite case
  149. canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
  150. canvas->translate(-x, -y);
  151. }
  152. if (fFlags & kRotate_Flag) {
  153. const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
  154. const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
  155. canvas->rotate(SkIntToScalar(35), x, y);
  156. }
  157. INHERITED::onDraw(loops, canvas);
  158. }
  159. void setupPaint(SkPaint* paint) override {
  160. this->INHERITED::setupPaint(paint);
  161. int index = 0;
  162. if (fFlags & kBilerp_Flag) {
  163. index |= 1;
  164. }
  165. if (fFlags & kBicubic_Flag) {
  166. index |= 2;
  167. }
  168. static const SkFilterQuality gQualitys[] = {
  169. kNone_SkFilterQuality,
  170. kLow_SkFilterQuality,
  171. kMedium_SkFilterQuality,
  172. kHigh_SkFilterQuality
  173. };
  174. paint->setFilterQuality(gQualitys[index]);
  175. }
  176. private:
  177. typedef BitmapBench INHERITED;
  178. };
  179. /** Verify optimizations that test source alpha values. */
  180. class SourceAlphaBitmapBench : public BitmapBench {
  181. public:
  182. enum SourceAlpha { kOpaque_SourceAlpha, kTransparent_SourceAlpha,
  183. kTwoStripes_SourceAlpha, kThreeStripes_SourceAlpha};
  184. private:
  185. SkString fFullName;
  186. SourceAlpha fSourceAlpha;
  187. public:
  188. SourceAlphaBitmapBench(SourceAlpha alpha, SkColorType ct,
  189. bool forceUpdate = false, bool bitmapVolatile = false)
  190. : INHERITED(ct, kPremul_SkAlphaType, forceUpdate, bitmapVolatile, false)
  191. , fSourceAlpha(alpha) {
  192. }
  193. protected:
  194. const char* onGetName() override {
  195. fFullName.set(INHERITED::onGetName());
  196. if (fSourceAlpha == kOpaque_SourceAlpha) {
  197. fFullName.append("_source_opaque");
  198. } else if (fSourceAlpha == kTransparent_SourceAlpha) {
  199. fFullName.append("_source_transparent");
  200. } else if (fSourceAlpha == kTwoStripes_SourceAlpha) {
  201. fFullName.append("_source_stripes_two");
  202. } else if (fSourceAlpha == kThreeStripes_SourceAlpha) {
  203. fFullName.append("_source_stripes_three");
  204. }
  205. return fFullName.c_str();
  206. }
  207. void onDrawIntoBitmap(const SkBitmap& bm) override {
  208. const int w = bm.width();
  209. const int h = bm.height();
  210. if (kOpaque_SourceAlpha == fSourceAlpha) {
  211. bm.eraseColor(SK_ColorBLACK);
  212. } else if (kTransparent_SourceAlpha == fSourceAlpha) {
  213. bm.eraseColor(0);
  214. } else if (kTwoStripes_SourceAlpha == fSourceAlpha) {
  215. bm.eraseColor(0);
  216. SkCanvas canvas(bm);
  217. SkPaint p;
  218. p.setAntiAlias(false);
  219. p.setStyle(SkPaint::kFill_Style);
  220. p.setColor(SK_ColorRED);
  221. // Draw red vertical stripes on transparent background
  222. SkRect r;
  223. for (int x = 0; x < w; x+=2)
  224. {
  225. r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
  226. canvas.drawRect(r, p);
  227. }
  228. } else if (kThreeStripes_SourceAlpha == fSourceAlpha) {
  229. bm.eraseColor(0);
  230. SkCanvas canvas(bm);
  231. SkPaint p;
  232. p.setAntiAlias(false);
  233. p.setStyle(SkPaint::kFill_Style);
  234. // Draw vertical stripes on transparent background with a pattern
  235. // where the first pixel is fully transparent, the next is semi-transparent
  236. // and the third is fully opaque.
  237. SkRect r;
  238. for (int x = 0; x < w; x++)
  239. {
  240. if (x % 3 == 0) {
  241. continue; // Keep transparent
  242. } else if (x % 3 == 1) {
  243. p.setColor(SkColorSetARGB(127, 127, 127, 127)); // Semi-transparent
  244. } else if (x % 3 == 2) {
  245. p.setColor(SK_ColorRED); // Opaque
  246. }
  247. r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
  248. canvas.drawRect(r, p);
  249. }
  250. }
  251. }
  252. private:
  253. typedef BitmapBench INHERITED;
  254. };
  255. DEF_BENCH( return new BitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, false); )
  256. DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, false); )
  257. DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, true); )
  258. DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, false); )
  259. DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, false); )
  260. DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, false); )
  261. // scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2
  262. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
  263. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
  264. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kBilerp_Flag); )
  265. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kBilerp_Flag); )
  266. // The following two cases test the performance regression of b/70172912 .
  267. DEF_BENCH( return new FilterBitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
  268. DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, true); )
  269. // scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3}
  270. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
  271. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
  272. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
  273. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
  274. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); )
  275. DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); )
  276. // source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon}
  277. DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kOpaque_SourceAlpha, kN32_SkColorType); )
  278. DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTransparent_SourceAlpha, kN32_SkColorType); )
  279. DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTwoStripes_SourceAlpha, kN32_SkColorType); )
  280. DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kThreeStripes_SourceAlpha, kN32_SkColorType); )