showmiplevels.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright 2016 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 "gm/gm.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkColorPriv.h"
  12. #include "include/core/SkImageInfo.h"
  13. #include "include/core/SkPaint.h"
  14. #include "include/core/SkPixmap.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/core/SkRefCnt.h"
  17. #include "include/core/SkScalar.h"
  18. #include "include/core/SkSize.h"
  19. #include "include/core/SkString.h"
  20. #include "include/private/SkNx.h"
  21. #include "src/core/SkMipMap.h"
  22. #include "tools/ToolUtils.h"
  23. #include <math.h>
  24. #define SHOW_MIP_COLOR 0xFF000000
  25. static SkBitmap make_bitmap(int w, int h) {
  26. SkBitmap bm;
  27. bm.allocN32Pixels(w, h);
  28. SkCanvas canvas(bm);
  29. canvas.clear(0xFFFFFFFF);
  30. SkPaint paint;
  31. paint.setStyle(SkPaint::kStroke_Style);
  32. paint.setStrokeWidth(w / 16.0f);
  33. paint.setColor(SHOW_MIP_COLOR);
  34. canvas.drawCircle(w/2.0f, h/2.0f, w/3.0f, paint);
  35. return bm;
  36. }
  37. static SkBitmap make_bitmap2(int w, int h) {
  38. SkBitmap bm;
  39. bm.allocN32Pixels(w, h);
  40. SkCanvas canvas(bm);
  41. canvas.clear(0xFFFFFFFF);
  42. SkPaint paint;
  43. paint.setColor(SHOW_MIP_COLOR);
  44. paint.setStyle(SkPaint::kStroke_Style);
  45. SkScalar inset = 2;
  46. SkRect r = SkRect::MakeIWH(w, h).makeInset(0.5f, 0.5f);
  47. while (r.width() > 4) {
  48. canvas.drawRect(r, paint);
  49. r.inset(inset, inset);
  50. inset += 1;
  51. }
  52. return bm;
  53. }
  54. static SkBitmap make_bitmap3(int w, int h) {
  55. SkBitmap bm;
  56. bm.allocN32Pixels(w, h);
  57. SkCanvas canvas(bm);
  58. canvas.clear(0xFFFFFFFF);
  59. SkPaint paint;
  60. paint.setStyle(SkPaint::kStroke_Style);
  61. paint.setStrokeWidth(2.1f);
  62. paint.setColor(SHOW_MIP_COLOR);
  63. SkScalar s = SkIntToScalar(w);
  64. Sk4f p(s, -s, -s, s);
  65. Sk4f d(5);
  66. while (p[1] < s) {
  67. canvas.drawLine(p[0],p[1], p[2], p[3], paint);
  68. p = p + d;
  69. }
  70. return bm;
  71. }
  72. class ShowMipLevels : public skiagm::GM {
  73. const int fN;
  74. SkBitmap fBM[4];
  75. public:
  76. static unsigned gamma(unsigned n) {
  77. float x = n / 255.0f;
  78. #if 0
  79. x = sqrtf(x);
  80. #else
  81. if (x > 0.0031308f) {
  82. x = 1.055f * (powf(x, (1.0f / 2.4f))) - 0.055f;
  83. } else {
  84. x = 12.92f * x;
  85. }
  86. #endif
  87. return (int)(x * 255);
  88. }
  89. static void apply_gamma(const SkBitmap& bm) {
  90. return; // below is our experiment for sRGB correction
  91. for (int y = 0; y < bm.height(); ++y) {
  92. for (int x = 0; x < bm.width(); ++x) {
  93. SkPMColor c = *bm.getAddr32(x, y);
  94. unsigned r = gamma(SkGetPackedR32(c));
  95. unsigned g = gamma(SkGetPackedG32(c));
  96. unsigned b = gamma(SkGetPackedB32(c));
  97. *bm.getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
  98. }
  99. }
  100. }
  101. ShowMipLevels(int N) : fN(N) { }
  102. protected:
  103. SkString onShortName() override {
  104. SkString str;
  105. str.printf("showmiplevels_%d", fN);
  106. return str;
  107. }
  108. SkISize onISize() override { return { 150, 862 }; }
  109. static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& orig, SkScalar x, SkScalar y) {
  110. SkBitmap bm;
  111. ToolUtils::copy_to(&bm, orig.colorType(), orig);
  112. apply_gamma(bm);
  113. canvas->drawBitmap(bm, x, y, nullptr);
  114. SkPaint paint;
  115. paint.setStyle(SkPaint::kStroke_Style);
  116. paint.setColor(0xFFFFCCCC);
  117. canvas->drawRect(SkRect::MakeIWH(bm.width(), bm.height()).makeOffset(x, y).makeOutset(0.5f, 0.5f), paint);
  118. }
  119. template <typename F> void drawLevels(SkCanvas* canvas, const SkBitmap& baseBM, F func) {
  120. SkScalar x = 4;
  121. SkScalar y = 4;
  122. SkPixmap prevPM;
  123. baseBM.peekPixels(&prevPM);
  124. sk_sp<SkMipMap> mm(SkMipMap::Build(baseBM, nullptr));
  125. int index = 0;
  126. SkMipMap::Level level;
  127. SkScalar scale = 0.5f;
  128. while (mm->extractLevel(SkSize::Make(scale, scale), &level)) {
  129. SkBitmap bm = func(prevPM, level.fPixmap);
  130. DrawAndFrame(canvas, bm, x, y);
  131. if (level.fPixmap.width() <= 2 || level.fPixmap.height() <= 2) {
  132. break;
  133. }
  134. if (index & 1) {
  135. x += level.fPixmap.width() + 4;
  136. } else {
  137. y += level.fPixmap.height() + 4;
  138. }
  139. scale /= 2;
  140. prevPM = level.fPixmap;
  141. index += 1;
  142. }
  143. }
  144. void drawSet(SkCanvas* canvas, const SkBitmap& orig) {
  145. SkAutoCanvasRestore acr(canvas, true);
  146. drawLevels(canvas, orig, [](const SkPixmap& prev, const SkPixmap& curr) {
  147. SkBitmap bm;
  148. bm.installPixels(curr);
  149. return bm;
  150. });
  151. }
  152. void onOnceBeforeDraw() override {
  153. fBM[0] = ToolUtils::create_checkerboard_bitmap(fN, fN, SK_ColorBLACK, SK_ColorWHITE, 2);
  154. fBM[1] = make_bitmap(fN, fN);
  155. fBM[2] = make_bitmap2(fN, fN);
  156. fBM[3] = make_bitmap3(fN, fN);
  157. }
  158. void onDraw(SkCanvas* canvas) override {
  159. canvas->translate(4, 4);
  160. for (const auto& bm : fBM) {
  161. this->drawSet(canvas, bm);
  162. // round so we always produce an integral translate, so the GOLD tool won't show
  163. // unimportant diffs if this is drawn on a GPU with different rounding rules
  164. // since we draw the bitmaps using nearest-neighbor
  165. canvas->translate(0, SkScalarRoundToScalar(bm.height() * 0.85f));
  166. }
  167. }
  168. private:
  169. typedef skiagm::GM INHERITED;
  170. };
  171. DEF_GM( return new ShowMipLevels(255); )
  172. DEF_GM( return new ShowMipLevels(256); )
  173. ///////////////////////////////////////////////////////////////////////////////////////////////////
  174. void copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
  175. if (kGray_8_SkColorType == dstColorType) {
  176. return ToolUtils::copy_to_g8(dst, src);
  177. }
  178. const SkBitmap* srcPtr = &src;
  179. SkBitmap tmp(src);
  180. if (kRGB_565_SkColorType == dstColorType) {
  181. tmp.setAlphaType(kOpaque_SkAlphaType);
  182. srcPtr = &tmp;
  183. }
  184. ToolUtils::copy_to(dst, dstColorType, *srcPtr);
  185. }
  186. /**
  187. * Show mip levels that were built, for all supported colortypes
  188. */
  189. class ShowMipLevels2 : public skiagm::GM {
  190. const int fW, fH;
  191. SkBitmap fBM[4];
  192. public:
  193. ShowMipLevels2(int w, int h) : fW(w), fH(h) { }
  194. protected:
  195. SkString onShortName() override {
  196. SkString str;
  197. str.printf("showmiplevels2_%dx%d", fW, fH);
  198. return str;
  199. }
  200. SkISize onISize() override {
  201. return { 824, 862 };
  202. }
  203. static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& bm, SkScalar x, SkScalar y) {
  204. canvas->drawBitmap(bm, x, y, nullptr);
  205. SkPaint paint;
  206. paint.setStyle(SkPaint::kStroke_Style);
  207. paint.setColor(0xFFFFCCCC);
  208. canvas->drawRect(SkRect::MakeIWH(bm.width(), bm.height()).makeOffset(x, y).makeOutset(0.5f, 0.5f), paint);
  209. }
  210. void drawLevels(SkCanvas* canvas, const SkBitmap& baseBM) {
  211. SkScalar x = 4;
  212. SkScalar y = 4;
  213. sk_sp<SkMipMap> mm(SkMipMap::Build(baseBM, nullptr));
  214. int index = 0;
  215. SkMipMap::Level level;
  216. SkScalar scale = 0.5f;
  217. while (mm->extractLevel(SkSize::Make(scale, scale), &level)) {
  218. SkBitmap bm;
  219. bm.installPixels(level.fPixmap);
  220. DrawAndFrame(canvas, bm, x, y);
  221. if (level.fPixmap.width() <= 2 || level.fPixmap.height() <= 2) {
  222. break;
  223. }
  224. if (index & 1) {
  225. x += level.fPixmap.width() + 4;
  226. } else {
  227. y += level.fPixmap.height() + 4;
  228. }
  229. scale /= 2;
  230. index += 1;
  231. }
  232. }
  233. void drawSet(SkCanvas* canvas, const SkBitmap& orig) {
  234. const SkColorType ctypes[] = {
  235. kN32_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, kGray_8_SkColorType
  236. };
  237. SkAutoCanvasRestore acr(canvas, true);
  238. for (auto ctype : ctypes) {
  239. SkBitmap bm;
  240. copy_to(&bm, ctype, orig);
  241. drawLevels(canvas, bm);
  242. canvas->translate(orig.width()/2 + 8.0f, 0);
  243. }
  244. }
  245. void onOnceBeforeDraw() override {
  246. fBM[0] = ToolUtils::create_checkerboard_bitmap(fW, fH, SHOW_MIP_COLOR, SK_ColorWHITE, 2);
  247. fBM[1] = make_bitmap(fW, fH);
  248. fBM[2] = make_bitmap2(fW, fH);
  249. fBM[3] = make_bitmap3(fW, fH);
  250. }
  251. void onDraw(SkCanvas* canvas) override {
  252. canvas->translate(4, 4);
  253. for (const auto& bm : fBM) {
  254. this->drawSet(canvas, bm);
  255. // round so we always produce an integral translate, so the GOLD tool won't show
  256. // unimportant diffs if this is drawn on a GPU with different rounding rules
  257. // since we draw the bitmaps using nearest-neighbor
  258. canvas->translate(0, SkScalarRoundToScalar(bm.height() * 0.85f));
  259. }
  260. }
  261. private:
  262. typedef skiagm::GM INHERITED;
  263. };
  264. DEF_GM( return new ShowMipLevels2(255, 255); )
  265. DEF_GM( return new ShowMipLevels2(256, 255); )
  266. DEF_GM( return new ShowMipLevels2(255, 256); )
  267. DEF_GM( return new ShowMipLevels2(256, 256); )