2 * Test program, which stresses the use of different color formats and
3 * compositing operations.
5 * Just run it without any command line arguments, and it will report either
6 * "blitters test passed" - everything is ok
7 * "blitters test failed!" - there is some problem
9 * In the case of failure, finding the problem involves the following steps:
10 * 1. Get the reference 'blitters-test' binary. It makes sense to disable all
11 * the cpu specific optimizations in pixman and also configure it with
12 * '--disable-shared' option. Those who are paranoid can also tweak the
13 * sources to disable all fastpath functions. The resulting binary
14 * can be renamed to something like 'blitters-test.ref'.
15 * 2. Compile the buggy binary (also with the '--disable-shared' option).
16 * 3. Run 'ruby blitters-test-bisect.rb ./blitters-test.ref ./blitters-test'
17 * 4. Look at the information about failed case (destination buffer content
18 * will be shown) and try to figure out what is wrong. Loading
19 * test program in gdb, specifying failed test number in the command
20 * line with '-' character prepended and setting breakpoint on
21 * 'pixman_image_composite' function can provide detailed information
22 * about function arguments
30 /* A primitive pseudorandom number generator, taken from POSIX.1-2001 example */
32 static uint32_t lcg_seed;
34 static inline uint32_t
37 lcg_seed = lcg_seed * 1103515245 + 12345;
38 return ((uint32_t)(lcg_seed / 65536) % 32768);
42 lcg_srand (uint32_t seed)
47 static inline uint32_t
50 return lcg_rand () % max;
53 /*----------------------------------------------------------------------------*\
54 * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
56 * This program generates the CRC-32 values for the files named in the
57 * command-line arguments. These are the same CRC-32 values used by GZIP,
58 * PKZIP, and ZMODEM. The Crc32_ComputeBuf () can also be detached and
61 * THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
63 * Based on the byte-oriented implementation "File Verification Using CRC"
64 * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
66 * v1.0.0: original release.
67 * v1.0.1: fixed printf formats.
68 * v1.0.2: fixed something else.
69 * v1.0.3: replaced CRC constant table by generator function.
70 * v1.0.4: reformatted code, made ANSI C. 1994-12-05.
71 * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
72 \*----------------------------------------------------------------------------*/
74 /*----------------------------------------------------------------------------*\
76 * Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
78 * Computes or accumulates the CRC-32 value for a memory buffer.
79 * The 'inCrc32' gives a previously accumulated CRC-32 value to allow
80 * a CRC to be generated for multiple sequential buffer-fuls of data.
81 * The 'inCrc32' for the first buffer must be zero.
83 * inCrc32 - accumulated CRC-32 value, must be 0 on first call
84 * buf - buffer to compute CRC-32 value for
85 * bufLen - number of bytes in buffer
87 * crc32 - computed CRC-32 value
89 * (no errors are possible)
90 \*----------------------------------------------------------------------------*/
93 compute_crc32 (uint32_t in_crc32,
97 static const uint32_t crc_table[256] = {
98 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
99 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
100 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
101 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
102 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
103 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
104 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
105 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
106 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
107 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
108 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
109 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
110 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
111 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
112 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
113 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
114 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
115 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
116 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
117 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
118 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
119 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
120 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
121 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
122 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
123 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
124 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
125 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
126 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
127 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
128 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
129 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
130 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
131 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
132 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
133 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
134 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
135 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
136 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
137 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
138 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
139 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
140 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
144 unsigned char * byte_buf;
147 /** accumulate crc32 for buffer **/
148 crc32 = in_crc32 ^ 0xFFFFFFFF;
149 byte_buf = (unsigned char*) buf;
151 for (i = 0; i < buf_len; i++)
152 crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
154 return (crc32 ^ 0xFFFFFFFF);
157 /* perform endian conversion of pixel data */
159 image_endian_swap (pixman_image_t *img, int bpp)
161 int stride = pixman_image_get_stride (img);
162 uint32_t *data = pixman_image_get_data (img);
163 int height = pixman_image_get_height (img);;
166 /* swap bytes only on big endian systems */
167 volatile uint16_t endian_check_var = 0x1234;
168 if (*(volatile uint8_t *)&endian_check_var != 0x12) return;
170 for (i = 0; i < height; i++)
172 uint8_t *line_data = (uint8_t *)data + stride * i;
173 /* swap bytes only for 16, 24 and 32 bpp for now */
177 for (j = 0; j < stride; j++)
180 ((line_data[j] & 0x80) >> 7) |
181 ((line_data[j] & 0x40) >> 5) |
182 ((line_data[j] & 0x20) >> 3) |
183 ((line_data[j] & 0x10) >> 1) |
184 ((line_data[j] & 0x08) << 1) |
185 ((line_data[j] & 0x04) << 3) |
186 ((line_data[j] & 0x02) << 5) |
187 ((line_data[j] & 0x01) << 7);
191 for (j = 0; j < stride; j++)
193 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
197 for (j = 0; j + 2 <= stride; j += 2)
199 char t1 = line_data[j + 0];
200 char t2 = line_data[j + 1];
201 line_data[j + 1] = t1;
202 line_data[j + 0] = t2;
206 for (j = 0; j + 3 <= stride; j += 3)
208 char t1 = line_data[j + 0];
209 char t2 = line_data[j + 1];
210 char t3 = line_data[j + 2];
211 line_data[j + 2] = t1;
212 line_data[j + 1] = t2;
213 line_data[j + 0] = t3;
217 for (j = 0; j + 4 <= stride; j += 4)
219 char t1 = line_data[j + 0];
220 char t2 = line_data[j + 1];
221 char t3 = line_data[j + 2];
222 char t4 = line_data[j + 3];
223 line_data[j + 3] = t1;
224 line_data[j + 2] = t2;
225 line_data[j + 1] = t3;
226 line_data[j + 0] = t4;
235 /* Create random image for testing purposes */
236 static pixman_image_t *
237 create_random_image (
238 pixman_format_code_t *allowed_formats,
241 int max_extra_stride,
242 pixman_format_code_t *used_fmt)
244 int n = 0, i, width, height, stride;
245 pixman_format_code_t fmt;
248 while (allowed_formats[n] != -1) n++;
249 fmt = allowed_formats[lcg_rand_n (n)];
250 width = lcg_rand_n (max_width) + 1;
251 height = lcg_rand_n (max_height) + 1;
252 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + lcg_rand_n (max_extra_stride + 1);
253 stride = (stride + 3) & ~3;
255 /* do the allocation */
256 buf = (uint32_t *)memalign (64, stride * height);
258 /* initialize image with random data */
259 for (i = 0; i < stride * height; i++)
261 /* generation is biased to having more 0 or 255 bytes as
262 they are more likely to be special-cased in code */
263 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
264 (lcg_rand_n (2) ? 0 : 255);
267 img = pixman_image_create_bits (
268 fmt, width, height, buf, stride);
270 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
272 if (used_fmt) *used_fmt = fmt;
276 /* Free random image, and optionally update crc32 based on its data */
281 pixman_format_code_t fmt)
284 int stride = pixman_image_get_stride (img);
285 uint32_t *data = pixman_image_get_data (img);
286 int height = pixman_image_get_height (img);;
290 /* mask unused 'x' part */
291 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
292 PIXMAN_FORMAT_DEPTH (fmt) != 0)
295 uint32_t *data = pixman_image_get_data (img);
296 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
297 for (i = 0; i < 32; i++)
298 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
300 for (i = 0; i < stride * height / 4; i++)
303 /* swap endiannes in order to provide identical results on both big
304 and litte endian systems */
305 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
306 crc32 = compute_crc32 (initcrc, data, stride * height);
308 pixman_image_unref (img);
313 static pixman_op_t op_list[] = {
322 PIXMAN_OP_OVER_REVERSE,
324 PIXMAN_OP_IN_REVERSE,
326 PIXMAN_OP_OUT_REVERSE,
328 PIXMAN_OP_ATOP_REVERSE,
332 PIXMAN_OP_DISJOINT_CLEAR,
333 PIXMAN_OP_DISJOINT_SRC,
334 #if 0 /* using this crashes the test */
335 PIXMAN_OP_DISJOINT_DST,
337 PIXMAN_OP_DISJOINT_OVER,
338 PIXMAN_OP_DISJOINT_OVER_REVERSE,
339 PIXMAN_OP_DISJOINT_IN,
340 PIXMAN_OP_DISJOINT_IN_REVERSE,
341 PIXMAN_OP_DISJOINT_OUT,
342 PIXMAN_OP_DISJOINT_OUT_REVERSE,
343 PIXMAN_OP_DISJOINT_ATOP,
344 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
345 PIXMAN_OP_DISJOINT_XOR,
346 PIXMAN_OP_CONJOINT_CLEAR,
347 PIXMAN_OP_CONJOINT_SRC,
348 #if 0 /* using this crashes the test */
349 PIXMAN_OP_CONJOINT_DST,
351 PIXMAN_OP_CONJOINT_OVER,
352 PIXMAN_OP_CONJOINT_OVER_REVERSE,
353 PIXMAN_OP_CONJOINT_IN,
354 PIXMAN_OP_CONJOINT_IN_REVERSE,
355 PIXMAN_OP_CONJOINT_OUT,
356 PIXMAN_OP_CONJOINT_OUT_REVERSE,
357 PIXMAN_OP_CONJOINT_ATOP,
358 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
359 PIXMAN_OP_CONJOINT_XOR,
365 PIXMAN_OP_COLOR_DODGE,
366 PIXMAN_OP_COLOR_BURN,
367 PIXMAN_OP_HARD_LIGHT,
368 PIXMAN_OP_DIFFERENCE,
370 #if 0 /* these use floating point math and are not always bitexact on different platforms */
371 PIXMAN_OP_SOFT_LIGHT,
373 PIXMAN_OP_HSL_SATURATION,
375 PIXMAN_OP_HSL_LUMINOSITY,
379 static pixman_format_code_t img_fmt_list[] = {
394 #if 0 /* using these makes valgrind complain */
413 #if 0 /* using these crashes the test */
432 static pixman_format_code_t mask_fmt_list[] = {
444 * Composite operation with pseudorandom images
447 test_composite (uint32_t initcrc, int testnum, int verbose)
450 pixman_image_t *src_img = NULL;
451 pixman_image_t *dst_img = NULL;
452 pixman_image_t *mask_img = NULL;
453 int src_width, src_height;
454 int dst_width, dst_height;
455 int src_stride, dst_stride;
460 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
463 int max_width, max_height, max_extra_stride;
465 max_width = max_height = 24 + testnum / 10000;
466 max_extra_stride = 4 + testnum / 1000000;
467 if (max_width > 256) max_width = 256;
468 if (max_height > 16) max_height = 16;
469 if (max_extra_stride > 8) max_extra_stride = 8;
473 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
478 src_img = create_random_image (img_fmt_list, max_width, max_height,
479 max_extra_stride, &src_fmt);
484 src_img = create_random_image (img_fmt_list, 1, 1,
485 max_extra_stride, &src_fmt);
486 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
489 dst_img = create_random_image (img_fmt_list, max_width, max_height,
490 max_extra_stride, &dst_fmt);
498 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
499 max_extra_stride, &mask_fmt);
504 mask_img = create_random_image (mask_fmt_list, 1, 1,
505 max_extra_stride, &mask_fmt);
506 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
508 #if 0 /* using this crashes the test */
510 pixman_image_set_component_alpha (mask_img, 1);
514 src_width = pixman_image_get_width (src_img);
515 src_height = pixman_image_get_height (src_img);
516 src_stride = pixman_image_get_stride (src_img);
517 dst_width = pixman_image_get_width (dst_img);
518 dst_height = pixman_image_get_height (dst_img);
519 dst_stride = pixman_image_get_stride (dst_img);
520 dstbuf = pixman_image_get_data (dst_img);
522 src_x = lcg_rand_n (src_width);
523 src_y = lcg_rand_n (src_height);
524 dst_x = lcg_rand_n (dst_width);
525 dst_y = lcg_rand_n (dst_height);
526 w = lcg_rand_n (dst_width - dst_x + 1);
527 h = lcg_rand_n (dst_height - dst_y + 1);
531 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
532 op, src_fmt, dst_fmt, mask_fmt);
533 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
534 src_width, src_height, dst_width, dst_height);
535 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
536 src_x, src_y, dst_x, dst_y);
537 printf ("src_stride=%d, dst_stride=%d\n",
538 src_stride, dst_stride);
539 printf ("w=%d, h=%d\n", w, h);
542 pixman_image_composite (op, src_img, mask_img, dst_img,
543 src_x, src_y, src_x, src_y, dst_x, dst_y, w, h);
549 for (i = 0; i < dst_height; i++)
551 for (j = 0; j < dst_stride; j++)
553 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
555 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
562 free_random_image (initcrc, src_img, -1);
563 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
564 if (mask_img) free_random_image (initcrc, mask_img, -1);
569 main (int argc, char *argv[])
571 int i, n1 = 1, n2 = 0;
591 crc = test_composite (0, abs (n2), 1);
592 printf ("crc32=%08X\n", crc);
596 for (i = n1; i <= n2; i++)
598 crc = test_composite (crc, i, 0);
600 printf ("crc32=%08X\n", crc);
604 /* Predefined value for running with all the fastpath functions
605 disabled. It needs to be updated every time when changes are
606 introduced to this program or behavior of pixman changes! */
607 if (crc == 0x4895C7B0)
609 printf ("blitters test passed\n");
613 printf ("blitters test failed!\n");