Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

u_format_test.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /**************************************************************************
  2. *
  3. * Copyright 2009-2010 VMware, Inc.
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial portions
  16. * of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21. * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. **************************************************************************/
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <float.h>
  30. #include "util/u_half.h"
  31. #include "util/u_format.h"
  32. #include "util/u_format_tests.h"
  33. #include "util/u_format_s3tc.h"
  34. static boolean
  35. compare_float(float x, float y)
  36. {
  37. float error = y - x;
  38. if (error < 0.0f)
  39. error = -error;
  40. if (error > FLT_EPSILON) {
  41. return FALSE;
  42. }
  43. return TRUE;
  44. }
  45. static void
  46. print_packed(const struct util_format_description *format_desc,
  47. const char *prefix,
  48. const uint8_t *packed,
  49. const char *suffix)
  50. {
  51. unsigned i;
  52. const char *sep = "";
  53. printf("%s", prefix);
  54. for (i = 0; i < format_desc->block.bits/8; ++i) {
  55. printf("%s%02x", sep, packed[i]);
  56. sep = " ";
  57. }
  58. printf("%s", suffix);
  59. }
  60. static void
  61. print_unpacked_doubl(const struct util_format_description *format_desc,
  62. const char *prefix,
  63. const double unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4],
  64. const char *suffix)
  65. {
  66. unsigned i, j;
  67. const char *sep = "";
  68. printf("%s", prefix);
  69. for (i = 0; i < format_desc->block.height; ++i) {
  70. for (j = 0; j < format_desc->block.width; ++j) {
  71. printf("%s{%f, %f, %f, %f}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]);
  72. sep = ", ";
  73. }
  74. sep = ",\n";
  75. }
  76. printf("%s", suffix);
  77. }
  78. static void
  79. print_unpacked_float(const struct util_format_description *format_desc,
  80. const char *prefix,
  81. const float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4],
  82. const char *suffix)
  83. {
  84. unsigned i, j;
  85. const char *sep = "";
  86. printf("%s", prefix);
  87. for (i = 0; i < format_desc->block.height; ++i) {
  88. for (j = 0; j < format_desc->block.width; ++j) {
  89. printf("%s{%f, %f, %f, %f}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]);
  90. sep = ", ";
  91. }
  92. sep = ",\n";
  93. }
  94. printf("%s", suffix);
  95. }
  96. static void
  97. print_unpacked_8unorm(const struct util_format_description *format_desc,
  98. const char *prefix,
  99. const uint8_t unpacked[][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4],
  100. const char *suffix)
  101. {
  102. unsigned i, j;
  103. const char *sep = "";
  104. printf("%s", prefix);
  105. for (i = 0; i < format_desc->block.height; ++i) {
  106. for (j = 0; j < format_desc->block.width; ++j) {
  107. printf("%s{0x%02x, 0x%02x, 0x%02x, 0x%02x}", sep, unpacked[i][j][0], unpacked[i][j][1], unpacked[i][j][2], unpacked[i][j][3]);
  108. sep = ", ";
  109. }
  110. }
  111. printf("%s", suffix);
  112. }
  113. static boolean
  114. test_format_fetch_float(const struct util_format_description *format_desc,
  115. const struct util_format_test_case *test)
  116. {
  117. float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  118. unsigned i, j, k;
  119. boolean success;
  120. success = TRUE;
  121. for (i = 0; i < format_desc->block.height; ++i) {
  122. for (j = 0; j < format_desc->block.width; ++j) {
  123. format_desc->fetch_float(unpacked[i][j], test->packed, j, i);
  124. for (k = 0; k < 4; ++k) {
  125. if (!compare_float(test->unpacked[i][j][k], unpacked[i][j][k])) {
  126. success = FALSE;
  127. }
  128. }
  129. }
  130. }
  131. if (!success) {
  132. print_unpacked_float(format_desc, "FAILED: ", unpacked, " obtained\n");
  133. print_unpacked_doubl(format_desc, " ", test->unpacked, " expected\n");
  134. }
  135. return success;
  136. }
  137. static boolean
  138. test_format_unpack_float(const struct util_format_description *format_desc,
  139. const struct util_format_test_case *test)
  140. {
  141. float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  142. unsigned i, j, k;
  143. boolean success;
  144. format_desc->unpack_float(&unpacked[0][0][0], sizeof unpacked[0], test->packed, 0, format_desc->block.width, format_desc->block.height);
  145. success = TRUE;
  146. for (i = 0; i < format_desc->block.height; ++i) {
  147. for (j = 0; j < format_desc->block.width; ++j) {
  148. for (k = 0; k < 4; ++k) {
  149. if (!compare_float(test->unpacked[i][j][k], unpacked[i][j][k])) {
  150. success = FALSE;
  151. }
  152. }
  153. }
  154. }
  155. if (!success) {
  156. print_unpacked_float(format_desc, "FAILED: ", unpacked, " obtained\n");
  157. print_unpacked_doubl(format_desc, " ", test->unpacked, " expected\n");
  158. }
  159. return success;
  160. }
  161. static boolean
  162. test_format_pack_float(const struct util_format_description *format_desc,
  163. const struct util_format_test_case *test)
  164. {
  165. float unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  166. uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES];
  167. unsigned i, j, k;
  168. boolean success;
  169. if (test->format == PIPE_FORMAT_DXT1_RGBA) {
  170. /*
  171. * Skip S3TC as packed representation is not canonical.
  172. *
  173. * TODO: Do a round trip conversion.
  174. */
  175. return TRUE;
  176. }
  177. memset(packed, 0, sizeof packed);
  178. for (i = 0; i < format_desc->block.height; ++i) {
  179. for (j = 0; j < format_desc->block.width; ++j) {
  180. for (k = 0; k < 4; ++k) {
  181. unpacked[i][j][k] = (float) test->unpacked[i][j][k];
  182. }
  183. }
  184. }
  185. format_desc->pack_float(packed, 0, &unpacked[0][0][0], sizeof unpacked[0], format_desc->block.width, format_desc->block.height);
  186. success = TRUE;
  187. for (i = 0; i < format_desc->block.bits/8; ++i)
  188. if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i]))
  189. success = FALSE;
  190. if (!success) {
  191. print_packed(format_desc, "FAILED: ", packed, " obtained\n");
  192. print_packed(format_desc, " ", test->packed, " expected\n");
  193. }
  194. return success;
  195. }
  196. static boolean
  197. convert_float_to_8unorm(uint8_t *dst, const double *src)
  198. {
  199. unsigned i;
  200. boolean accurate = TRUE;
  201. for (i = 0; i < UTIL_FORMAT_MAX_UNPACKED_HEIGHT*UTIL_FORMAT_MAX_UNPACKED_WIDTH*4; ++i) {
  202. if (src[i] < 0.0) {
  203. accurate = FALSE;
  204. dst[i] = 0;
  205. }
  206. else if (src[i] > 1.0) {
  207. accurate = FALSE;
  208. dst[i] = 255;
  209. }
  210. else {
  211. dst[i] = src[i] * 255.0;
  212. }
  213. }
  214. return accurate;
  215. }
  216. static boolean
  217. test_format_unpack_8unorm(const struct util_format_description *format_desc,
  218. const struct util_format_test_case *test)
  219. {
  220. uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  221. uint8_t expected[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  222. unsigned i, j, k;
  223. boolean success;
  224. format_desc->unpack_8unorm(&unpacked[0][0][0], sizeof unpacked[0], test->packed, 0, 1, 1);
  225. convert_float_to_8unorm(&expected[0][0][0], &test->unpacked[0][0][0]);
  226. success = TRUE;
  227. for (i = 0; i < format_desc->block.height; ++i) {
  228. for (j = 0; j < format_desc->block.width; ++j) {
  229. for (k = 0; k < 4; ++k) {
  230. if (expected[i][j][k] != unpacked[i][j][k]) {
  231. success = FALSE;
  232. }
  233. }
  234. }
  235. }
  236. if (!success) {
  237. print_unpacked_8unorm(format_desc, "FAILED: ", unpacked, " obtained\n");
  238. print_unpacked_8unorm(format_desc, " ", expected, " expected\n");
  239. }
  240. return success;
  241. }
  242. static boolean
  243. test_format_pack_8unorm(const struct util_format_description *format_desc,
  244. const struct util_format_test_case *test)
  245. {
  246. uint8_t unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
  247. uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES];
  248. unsigned i;
  249. boolean success;
  250. if (test->format == PIPE_FORMAT_DXT1_RGBA) {
  251. /*
  252. * Skip S3TC as packed representation is not canonical.
  253. *
  254. * TODO: Do a round trip conversion.
  255. */
  256. return TRUE;
  257. }
  258. if (!convert_float_to_8unorm(&unpacked[0][0][0], &test->unpacked[0][0][0])) {
  259. /*
  260. * Skip test cases which cannot be represented by four unorm bytes.
  261. */
  262. return TRUE;
  263. }
  264. memset(packed, 0, sizeof packed);
  265. format_desc->pack_8unorm(packed, 0, &unpacked[0][0][0], sizeof unpacked[0], 1, 1);
  266. success = TRUE;
  267. for (i = 0; i < format_desc->block.bits/8; ++i)
  268. if ((test->packed[i] & test->mask[i]) != (packed[i] & test->mask[i]))
  269. success = FALSE;
  270. if (!success) {
  271. print_packed(format_desc, "FAILED: ", packed, " obtained\n");
  272. print_packed(format_desc, " ", test->packed, " expected\n");
  273. }
  274. return success;
  275. }
  276. typedef boolean
  277. (*test_func_t)(const struct util_format_description *format_desc,
  278. const struct util_format_test_case *test);
  279. static boolean
  280. test_one(test_func_t func, const char *suffix)
  281. {
  282. enum pipe_format last_format = PIPE_FORMAT_NONE;
  283. unsigned i;
  284. bool success = TRUE;
  285. for (i = 0; i < util_format_nr_test_cases; ++i) {
  286. const struct util_format_test_case *test = &util_format_test_cases[i];
  287. const struct util_format_description *format_desc;
  288. bool skip = FALSE;
  289. format_desc = util_format_description(test->format);
  290. if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC &&
  291. !util_format_s3tc_enabled) {
  292. skip = TRUE;
  293. }
  294. if (test->format != last_format) {
  295. printf("%s util_format_%s_%s ...\n",
  296. skip ? "Skipping" : "Testing", format_desc->short_name, suffix);
  297. last_format = test->format;
  298. }
  299. if (!skip) {
  300. if (!func(format_desc, &util_format_test_cases[i])) {
  301. success = FALSE;
  302. }
  303. }
  304. }
  305. return success;
  306. }
  307. static boolean
  308. test_all(void)
  309. {
  310. bool success = TRUE;
  311. if (!test_one(&test_format_fetch_float, "fetch_float"))
  312. success = FALSE;
  313. if (!test_one(&test_format_pack_float, "pack_float"))
  314. success = FALSE;
  315. if (!test_one(&test_format_unpack_float, "unpack_float"))
  316. success = FALSE;
  317. if (!test_one(&test_format_pack_8unorm, "pack_8unorm"))
  318. success = FALSE;
  319. if (!test_one(&test_format_unpack_8unorm, "unpack_8unorm"))
  320. success = FALSE;
  321. return success;
  322. }
  323. int main(int argc, char **argv)
  324. {
  325. boolean success;
  326. util_half_init_tables();
  327. util_format_s3tc_init();
  328. success = test_all();
  329. return success ? 0 : 1;
  330. }