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;
54 aligned_malloc (size_t align, size_t size)
58 #ifdef HAVE_POSIX_MEMALIGN
59 posix_memalign (&result, align, size);
61 result = malloc (size);
67 /*----------------------------------------------------------------------------*\
68 * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
70 * This program generates the CRC-32 values for the files named in the
71 * command-line arguments. These are the same CRC-32 values used by GZIP,
72 * PKZIP, and ZMODEM. The Crc32_ComputeBuf () can also be detached and
75 * THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
77 * Based on the byte-oriented implementation "File Verification Using CRC"
78 * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
80 * v1.0.0: original release.
81 * v1.0.1: fixed printf formats.
82 * v1.0.2: fixed something else.
83 * v1.0.3: replaced CRC constant table by generator function.
84 * v1.0.4: reformatted code, made ANSI C. 1994-12-05.
85 * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
86 \*----------------------------------------------------------------------------*/
88 /*----------------------------------------------------------------------------*\
90 * Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
92 * Computes or accumulates the CRC-32 value for a memory buffer.
93 * The 'inCrc32' gives a previously accumulated CRC-32 value to allow
94 * a CRC to be generated for multiple sequential buffer-fuls of data.
95 * The 'inCrc32' for the first buffer must be zero.
97 * inCrc32 - accumulated CRC-32 value, must be 0 on first call
98 * buf - buffer to compute CRC-32 value for
99 * bufLen - number of bytes in buffer
101 * crc32 - computed CRC-32 value
103 * (no errors are possible)
104 \*----------------------------------------------------------------------------*/
107 compute_crc32 (uint32_t in_crc32,
111 static const uint32_t crc_table[256] = {
112 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
113 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
114 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
115 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
116 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
117 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
118 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
119 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
120 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
121 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
122 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
123 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
124 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
125 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
126 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
127 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
128 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
129 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
130 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
131 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
132 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
133 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
134 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
135 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
136 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
137 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
138 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
139 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
140 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
141 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
142 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
143 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
144 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
145 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
146 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
147 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
148 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
149 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
150 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
151 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
152 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
153 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
154 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
158 unsigned char * byte_buf;
161 /* accumulate crc32 for buffer */
162 crc32 = in_crc32 ^ 0xFFFFFFFF;
163 byte_buf = (unsigned char*) buf;
165 for (i = 0; i < buf_len; i++)
166 crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
168 return (crc32 ^ 0xFFFFFFFF);
171 /* perform endian conversion of pixel data */
173 image_endian_swap (pixman_image_t *img, int bpp)
175 int stride = pixman_image_get_stride (img);
176 uint32_t *data = pixman_image_get_data (img);
177 int height = pixman_image_get_height (img);;
180 /* swap bytes only on big endian systems */
181 volatile uint16_t endian_check_var = 0x1234;
182 if (*(volatile uint8_t *)&endian_check_var != 0x12)
185 for (i = 0; i < height; i++)
187 uint8_t *line_data = (uint8_t *)data + stride * i;
188 /* swap bytes only for 16, 24 and 32 bpp for now */
192 for (j = 0; j < stride; j++)
195 ((line_data[j] & 0x80) >> 7) |
196 ((line_data[j] & 0x40) >> 5) |
197 ((line_data[j] & 0x20) >> 3) |
198 ((line_data[j] & 0x10) >> 1) |
199 ((line_data[j] & 0x08) << 1) |
200 ((line_data[j] & 0x04) << 3) |
201 ((line_data[j] & 0x02) << 5) |
202 ((line_data[j] & 0x01) << 7);
206 for (j = 0; j < stride; j++)
208 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
212 for (j = 0; j + 2 <= stride; j += 2)
214 char t1 = line_data[j + 0];
215 char t2 = line_data[j + 1];
217 line_data[j + 1] = t1;
218 line_data[j + 0] = t2;
222 for (j = 0; j + 3 <= stride; j += 3)
224 char t1 = line_data[j + 0];
225 char t2 = line_data[j + 1];
226 char t3 = line_data[j + 2];
228 line_data[j + 2] = t1;
229 line_data[j + 1] = t2;
230 line_data[j + 0] = t3;
234 for (j = 0; j + 4 <= stride; j += 4)
236 char t1 = line_data[j + 0];
237 char t2 = line_data[j + 1];
238 char t3 = line_data[j + 2];
239 char t4 = line_data[j + 3];
241 line_data[j + 3] = t1;
242 line_data[j + 2] = t2;
243 line_data[j + 1] = t3;
244 line_data[j + 0] = t4;
253 /* Create random image for testing purposes */
254 static pixman_image_t *
255 create_random_image (pixman_format_code_t *allowed_formats,
258 int max_extra_stride,
259 pixman_format_code_t *used_fmt)
261 int n = 0, i, width, height, stride;
262 pixman_format_code_t fmt;
266 while (allowed_formats[n] != -1)
268 fmt = allowed_formats[lcg_rand_n (n)];
269 width = lcg_rand_n (max_width) + 1;
270 height = lcg_rand_n (max_height) + 1;
271 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
272 lcg_rand_n (max_extra_stride + 1);
273 stride = (stride + 3) & ~3;
275 /* do the allocation */
276 buf = aligned_malloc (64, stride * height);
278 /* initialize image with random data */
279 for (i = 0; i < stride * height; i++)
281 /* generation is biased to having more 0 or 255 bytes as
282 * they are more likely to be special-cased in code
284 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
285 (lcg_rand_n (2) ? 0 : 255);
288 img = pixman_image_create_bits (fmt, width, height, buf, stride);
290 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
292 if (used_fmt) *used_fmt = fmt;
296 /* Free random image, and optionally update crc32 based on its data */
298 free_random_image (uint32_t initcrc,
300 pixman_format_code_t fmt)
303 int stride = pixman_image_get_stride (img);
304 uint32_t *data = pixman_image_get_data (img);
305 int height = pixman_image_get_height (img);;
309 /* mask unused 'x' part */
310 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
311 PIXMAN_FORMAT_DEPTH (fmt) != 0)
314 uint32_t *data = pixman_image_get_data (img);
315 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
317 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
318 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
320 for (i = 0; i < 32; i++)
321 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
323 for (i = 0; i < stride * height / 4; i++)
327 /* swap endiannes in order to provide identical results on both big
328 * and litte endian systems
330 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
331 crc32 = compute_crc32 (initcrc, data, stride * height);
334 pixman_image_unref (img);
340 static pixman_op_t op_list[] = {
348 PIXMAN_OP_OVER_REVERSE,
350 PIXMAN_OP_IN_REVERSE,
352 PIXMAN_OP_OUT_REVERSE,
354 PIXMAN_OP_ATOP_REVERSE,
358 PIXMAN_OP_DISJOINT_CLEAR,
359 PIXMAN_OP_DISJOINT_SRC,
360 PIXMAN_OP_DISJOINT_DST,
361 PIXMAN_OP_DISJOINT_OVER,
362 PIXMAN_OP_DISJOINT_OVER_REVERSE,
363 PIXMAN_OP_DISJOINT_IN,
364 PIXMAN_OP_DISJOINT_IN_REVERSE,
365 PIXMAN_OP_DISJOINT_OUT,
366 PIXMAN_OP_DISJOINT_OUT_REVERSE,
367 PIXMAN_OP_DISJOINT_ATOP,
368 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
369 PIXMAN_OP_DISJOINT_XOR,
370 PIXMAN_OP_CONJOINT_CLEAR,
371 PIXMAN_OP_CONJOINT_SRC,
372 PIXMAN_OP_CONJOINT_DST,
373 PIXMAN_OP_CONJOINT_OVER,
374 PIXMAN_OP_CONJOINT_OVER_REVERSE,
375 PIXMAN_OP_CONJOINT_IN,
376 PIXMAN_OP_CONJOINT_IN_REVERSE,
377 PIXMAN_OP_CONJOINT_OUT,
378 PIXMAN_OP_CONJOINT_OUT_REVERSE,
379 PIXMAN_OP_CONJOINT_ATOP,
380 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
381 PIXMAN_OP_CONJOINT_XOR,
387 PIXMAN_OP_COLOR_DODGE,
388 PIXMAN_OP_COLOR_BURN,
389 PIXMAN_OP_HARD_LIGHT,
390 PIXMAN_OP_DIFFERENCE,
392 #if 0 /* these use floating point math and are not always bitexact on different platforms */
393 PIXMAN_OP_SOFT_LIGHT,
395 PIXMAN_OP_HSL_SATURATION,
397 PIXMAN_OP_HSL_LUMINOSITY,
401 static pixman_format_code_t img_fmt_list[] = {
432 #if 0 /* using these crashes the test */
451 static pixman_format_code_t mask_fmt_list[] = {
461 * Composite operation with pseudorandom images
464 test_composite (uint32_t initcrc, int testnum, int verbose)
467 pixman_image_t *src_img = NULL;
468 pixman_image_t *dst_img = NULL;
469 pixman_image_t *mask_img = NULL;
470 int src_width, src_height;
471 int dst_width, dst_height;
472 int src_stride, dst_stride;
477 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
480 int max_width, max_height, max_extra_stride;
482 max_width = max_height = 24 + testnum / 10000;
483 max_extra_stride = 4 + testnum / 1000000;
491 if (max_extra_stride > 8)
492 max_extra_stride = 8;
496 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
501 src_img = create_random_image (img_fmt_list, max_width, max_height,
502 max_extra_stride, &src_fmt);
507 src_img = create_random_image (img_fmt_list, 1, 1,
508 max_extra_stride, &src_fmt);
510 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
513 dst_img = create_random_image (img_fmt_list, max_width, max_height,
514 max_extra_stride, &dst_fmt);
523 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
524 max_extra_stride, &mask_fmt);
529 mask_img = create_random_image (mask_fmt_list, 1, 1,
530 max_extra_stride, &mask_fmt);
531 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
535 pixman_image_set_component_alpha (mask_img, 1);
538 src_width = pixman_image_get_width (src_img);
539 src_height = pixman_image_get_height (src_img);
540 src_stride = pixman_image_get_stride (src_img);
542 dst_width = pixman_image_get_width (dst_img);
543 dst_height = pixman_image_get_height (dst_img);
544 dst_stride = pixman_image_get_stride (dst_img);
546 dstbuf = pixman_image_get_data (dst_img);
548 src_x = lcg_rand_n (src_width);
549 src_y = lcg_rand_n (src_height);
550 dst_x = lcg_rand_n (dst_width);
551 dst_y = lcg_rand_n (dst_height);
553 w = lcg_rand_n (dst_width - dst_x + 1);
554 h = lcg_rand_n (dst_height - dst_y + 1);
558 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
559 op, src_fmt, dst_fmt, mask_fmt);
560 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
561 src_width, src_height, dst_width, dst_height);
562 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
563 src_x, src_y, dst_x, dst_y);
564 printf ("src_stride=%d, dst_stride=%d\n",
565 src_stride, dst_stride);
566 printf ("w=%d, h=%d\n", w, h);
569 pixman_image_composite (op, src_img, mask_img, dst_img,
570 src_x, src_y, src_x, src_y, dst_x, dst_y, w, h);
577 for (i = 0; i < dst_height; i++)
579 for (j = 0; j < dst_stride; j++)
581 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
584 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
591 free_random_image (initcrc, src_img, -1);
592 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
595 free_random_image (initcrc, mask_img, -1);
601 main (int argc, char *argv[])
603 int i, n1 = 1, n2 = 0;
605 int verbose = getenv ("VERBOSE") != NULL;
624 crc = test_composite (0, abs (n2), 1);
625 printf ("crc32=%08X\n", crc);
629 for (i = n1; i <= n2; i++)
631 crc = test_composite (crc, i, 0);
634 printf ("%d: %08X\n", i, crc);
636 printf ("crc32=%08X\n", crc);
640 /* Predefined value for running with all the fastpath functions
641 disabled. It needs to be updated every time when changes are
642 introduced to this program or behavior of pixman changes! */
643 if (crc == 0x481369DE)
645 printf ("blitters test passed\n");
649 printf ("blitters test failed!\n");