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 if (posix_memalign (&result, align, size) != 0)
62 result = malloc (size);
68 /*----------------------------------------------------------------------------*\
69 * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
71 * This program generates the CRC-32 values for the files named in the
72 * command-line arguments. These are the same CRC-32 values used by GZIP,
73 * PKZIP, and ZMODEM. The Crc32_ComputeBuf () can also be detached and
76 * THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
78 * Based on the byte-oriented implementation "File Verification Using CRC"
79 * by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
81 * v1.0.0: original release.
82 * v1.0.1: fixed printf formats.
83 * v1.0.2: fixed something else.
84 * v1.0.3: replaced CRC constant table by generator function.
85 * v1.0.4: reformatted code, made ANSI C. 1994-12-05.
86 * v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
87 \*----------------------------------------------------------------------------*/
89 /*----------------------------------------------------------------------------*\
91 * Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
93 * Computes or accumulates the CRC-32 value for a memory buffer.
94 * The 'inCrc32' gives a previously accumulated CRC-32 value to allow
95 * a CRC to be generated for multiple sequential buffer-fuls of data.
96 * The 'inCrc32' for the first buffer must be zero.
98 * inCrc32 - accumulated CRC-32 value, must be 0 on first call
99 * buf - buffer to compute CRC-32 value for
100 * bufLen - number of bytes in buffer
102 * crc32 - computed CRC-32 value
104 * (no errors are possible)
105 \*----------------------------------------------------------------------------*/
108 compute_crc32 (uint32_t in_crc32,
112 static const uint32_t crc_table[256] = {
113 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
114 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
115 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
116 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
117 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
118 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
119 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
120 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
121 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
122 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
123 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
124 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
125 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
126 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
127 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
128 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
129 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
130 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
131 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
132 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
133 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
134 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
135 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
136 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
137 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
138 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
139 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
140 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
141 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
142 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
143 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
144 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
145 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
146 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
147 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
148 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
149 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
150 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
151 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
152 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
153 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
154 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
155 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
159 unsigned char * byte_buf;
162 /* accumulate crc32 for buffer */
163 crc32 = in_crc32 ^ 0xFFFFFFFF;
164 byte_buf = (unsigned char*) buf;
166 for (i = 0; i < buf_len; i++)
167 crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
169 return (crc32 ^ 0xFFFFFFFF);
172 /* perform endian conversion of pixel data */
174 image_endian_swap (pixman_image_t *img, int bpp)
176 int stride = pixman_image_get_stride (img);
177 uint32_t *data = pixman_image_get_data (img);
178 int height = pixman_image_get_height (img);
181 /* swap bytes only on big endian systems */
182 volatile uint16_t endian_check_var = 0x1234;
183 if (*(volatile uint8_t *)&endian_check_var != 0x12)
186 for (i = 0; i < height; i++)
188 uint8_t *line_data = (uint8_t *)data + stride * i;
189 /* swap bytes only for 16, 24 and 32 bpp for now */
193 for (j = 0; j < stride; j++)
196 ((line_data[j] & 0x80) >> 7) |
197 ((line_data[j] & 0x40) >> 5) |
198 ((line_data[j] & 0x20) >> 3) |
199 ((line_data[j] & 0x10) >> 1) |
200 ((line_data[j] & 0x08) << 1) |
201 ((line_data[j] & 0x04) << 3) |
202 ((line_data[j] & 0x02) << 5) |
203 ((line_data[j] & 0x01) << 7);
207 for (j = 0; j < stride; j++)
209 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
213 for (j = 0; j + 2 <= stride; j += 2)
215 char t1 = line_data[j + 0];
216 char t2 = line_data[j + 1];
218 line_data[j + 1] = t1;
219 line_data[j + 0] = t2;
223 for (j = 0; j + 3 <= stride; j += 3)
225 char t1 = line_data[j + 0];
226 char t2 = line_data[j + 1];
227 char t3 = line_data[j + 2];
229 line_data[j + 2] = t1;
230 line_data[j + 1] = t2;
231 line_data[j + 0] = t3;
235 for (j = 0; j + 4 <= stride; j += 4)
237 char t1 = line_data[j + 0];
238 char t2 = line_data[j + 1];
239 char t3 = line_data[j + 2];
240 char t4 = line_data[j + 3];
242 line_data[j + 3] = t1;
243 line_data[j + 2] = t2;
244 line_data[j + 1] = t3;
245 line_data[j + 0] = t4;
254 /* Create random image for testing purposes */
255 static pixman_image_t *
256 create_random_image (pixman_format_code_t *allowed_formats,
259 int max_extra_stride,
260 pixman_format_code_t *used_fmt)
262 int n = 0, i, width, height, stride;
263 pixman_format_code_t fmt;
267 while (allowed_formats[n] != -1)
269 fmt = allowed_formats[lcg_rand_n (n)];
270 width = lcg_rand_n (max_width) + 1;
271 height = lcg_rand_n (max_height) + 1;
272 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
273 lcg_rand_n (max_extra_stride + 1);
274 stride = (stride + 3) & ~3;
276 /* do the allocation */
277 buf = aligned_malloc (64, stride * height);
279 /* initialize image with random data */
280 for (i = 0; i < stride * height; i++)
282 /* generation is biased to having more 0 or 255 bytes as
283 * they are more likely to be special-cased in code
285 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
286 (lcg_rand_n (2) ? 0 : 255);
289 img = pixman_image_create_bits (fmt, width, height, buf, stride);
291 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
293 if (used_fmt) *used_fmt = fmt;
297 /* Free random image, and optionally update crc32 based on its data */
299 free_random_image (uint32_t initcrc,
301 pixman_format_code_t fmt)
304 int stride = pixman_image_get_stride (img);
305 uint32_t *data = pixman_image_get_data (img);
306 int height = pixman_image_get_height (img);;
310 /* mask unused 'x' part */
311 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
312 PIXMAN_FORMAT_DEPTH (fmt) != 0)
315 uint32_t *data = pixman_image_get_data (img);
316 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
318 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
319 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
321 for (i = 0; i < 32; i++)
322 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
324 for (i = 0; i < stride * height / 4; i++)
328 /* swap endiannes in order to provide identical results on both big
329 * and litte endian systems
331 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
332 crc32 = compute_crc32 (initcrc, data, stride * height);
335 pixman_image_unref (img);
341 static pixman_op_t op_list[] = {
349 PIXMAN_OP_OVER_REVERSE,
351 PIXMAN_OP_IN_REVERSE,
353 PIXMAN_OP_OUT_REVERSE,
355 PIXMAN_OP_ATOP_REVERSE,
359 PIXMAN_OP_DISJOINT_CLEAR,
360 PIXMAN_OP_DISJOINT_SRC,
361 PIXMAN_OP_DISJOINT_DST,
362 PIXMAN_OP_DISJOINT_OVER,
363 PIXMAN_OP_DISJOINT_OVER_REVERSE,
364 PIXMAN_OP_DISJOINT_IN,
365 PIXMAN_OP_DISJOINT_IN_REVERSE,
366 PIXMAN_OP_DISJOINT_OUT,
367 PIXMAN_OP_DISJOINT_OUT_REVERSE,
368 PIXMAN_OP_DISJOINT_ATOP,
369 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
370 PIXMAN_OP_DISJOINT_XOR,
371 PIXMAN_OP_CONJOINT_CLEAR,
372 PIXMAN_OP_CONJOINT_SRC,
373 PIXMAN_OP_CONJOINT_DST,
374 PIXMAN_OP_CONJOINT_OVER,
375 PIXMAN_OP_CONJOINT_OVER_REVERSE,
376 PIXMAN_OP_CONJOINT_IN,
377 PIXMAN_OP_CONJOINT_IN_REVERSE,
378 PIXMAN_OP_CONJOINT_OUT,
379 PIXMAN_OP_CONJOINT_OUT_REVERSE,
380 PIXMAN_OP_CONJOINT_ATOP,
381 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
382 PIXMAN_OP_CONJOINT_XOR,
388 PIXMAN_OP_COLOR_DODGE,
389 PIXMAN_OP_COLOR_BURN,
390 PIXMAN_OP_HARD_LIGHT,
391 PIXMAN_OP_DIFFERENCE,
393 #if 0 /* these use floating point math and are not always bitexact on different platforms */
394 PIXMAN_OP_SOFT_LIGHT,
396 PIXMAN_OP_HSL_SATURATION,
398 PIXMAN_OP_HSL_LUMINOSITY,
402 static pixman_format_code_t img_fmt_list[] = {
433 #if 0 /* using these crashes the test */
452 static pixman_format_code_t mask_fmt_list[] = {
462 * Composite operation with pseudorandom images
465 test_composite (uint32_t initcrc, int testnum, int verbose)
468 pixman_image_t *src_img = NULL;
469 pixman_image_t *dst_img = NULL;
470 pixman_image_t *mask_img = NULL;
471 int src_width, src_height;
472 int dst_width, dst_height;
473 int src_stride, dst_stride;
478 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
481 int max_width, max_height, max_extra_stride;
483 max_width = max_height = 24 + testnum / 10000;
484 max_extra_stride = 4 + testnum / 1000000;
492 if (max_extra_stride > 8)
493 max_extra_stride = 8;
497 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
502 src_img = create_random_image (img_fmt_list, max_width, max_height,
503 max_extra_stride, &src_fmt);
508 src_img = create_random_image (img_fmt_list, 1, 1,
509 max_extra_stride, &src_fmt);
511 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
514 dst_img = create_random_image (img_fmt_list, max_width, max_height,
515 max_extra_stride, &dst_fmt);
524 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
525 max_extra_stride, &mask_fmt);
530 mask_img = create_random_image (mask_fmt_list, 1, 1,
531 max_extra_stride, &mask_fmt);
532 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
536 pixman_image_set_component_alpha (mask_img, 1);
539 src_width = pixman_image_get_width (src_img);
540 src_height = pixman_image_get_height (src_img);
541 src_stride = pixman_image_get_stride (src_img);
543 dst_width = pixman_image_get_width (dst_img);
544 dst_height = pixman_image_get_height (dst_img);
545 dst_stride = pixman_image_get_stride (dst_img);
547 dstbuf = pixman_image_get_data (dst_img);
549 src_x = lcg_rand_n (src_width);
550 src_y = lcg_rand_n (src_height);
551 dst_x = lcg_rand_n (dst_width);
552 dst_y = lcg_rand_n (dst_height);
554 w = lcg_rand_n (dst_width - dst_x + 1);
555 h = lcg_rand_n (dst_height - dst_y + 1);
559 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
560 op, src_fmt, dst_fmt, mask_fmt);
561 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
562 src_width, src_height, dst_width, dst_height);
563 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
564 src_x, src_y, dst_x, dst_y);
565 printf ("src_stride=%d, dst_stride=%d\n",
566 src_stride, dst_stride);
567 printf ("w=%d, h=%d\n", w, h);
570 pixman_image_composite (op, src_img, mask_img, dst_img,
571 src_x, src_y, src_x, src_y, dst_x, dst_y, w, h);
578 for (i = 0; i < dst_height; i++)
580 for (j = 0; j < dst_stride; j++)
582 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
585 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
592 free_random_image (initcrc, src_img, -1);
593 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
596 free_random_image (initcrc, mask_img, -1);
602 main (int argc, char *argv[])
604 int i, n1 = 1, n2 = 0;
606 int verbose = getenv ("VERBOSE") != NULL;
625 crc = test_composite (0, abs (n2), 1);
626 printf ("crc32=%08X\n", crc);
630 for (i = n1; i <= n2; i++)
632 crc = test_composite (crc, i, 0);
635 printf ("%d: %08X\n", i, crc);
637 printf ("crc32=%08X\n", crc);
641 /* Predefined value for running with all the fastpath functions
642 disabled. It needs to be updated every time when changes are
643 introduced to this program or behavior of pixman changes! */
644 if (crc == 0x481369DE)
646 printf ("blitters test passed\n");
650 printf ("blitters test failed!\n");