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 */
33 aligned_malloc (size_t align, size_t size)
37 #ifdef HAVE_POSIX_MEMALIGN
38 if (posix_memalign (&result, align, size) != 0)
41 result = malloc (size);
47 /* perform endian conversion of pixel data */
49 image_endian_swap (pixman_image_t *img, int bpp)
51 int stride = pixman_image_get_stride (img);
52 uint32_t *data = pixman_image_get_data (img);
53 int height = pixman_image_get_height (img);
56 /* swap bytes only on big endian systems */
57 volatile uint16_t endian_check_var = 0x1234;
58 if (*(volatile uint8_t *)&endian_check_var != 0x12)
61 for (i = 0; i < height; i++)
63 uint8_t *line_data = (uint8_t *)data + stride * i;
64 /* swap bytes only for 16, 24 and 32 bpp for now */
68 for (j = 0; j < stride; j++)
71 ((line_data[j] & 0x80) >> 7) |
72 ((line_data[j] & 0x40) >> 5) |
73 ((line_data[j] & 0x20) >> 3) |
74 ((line_data[j] & 0x10) >> 1) |
75 ((line_data[j] & 0x08) << 1) |
76 ((line_data[j] & 0x04) << 3) |
77 ((line_data[j] & 0x02) << 5) |
78 ((line_data[j] & 0x01) << 7);
82 for (j = 0; j < stride; j++)
84 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
88 for (j = 0; j + 2 <= stride; j += 2)
90 char t1 = line_data[j + 0];
91 char t2 = line_data[j + 1];
93 line_data[j + 1] = t1;
94 line_data[j + 0] = t2;
98 for (j = 0; j + 3 <= stride; j += 3)
100 char t1 = line_data[j + 0];
101 char t2 = line_data[j + 1];
102 char t3 = line_data[j + 2];
104 line_data[j + 2] = t1;
105 line_data[j + 1] = t2;
106 line_data[j + 0] = t3;
110 for (j = 0; j + 4 <= stride; j += 4)
112 char t1 = line_data[j + 0];
113 char t2 = line_data[j + 1];
114 char t3 = line_data[j + 2];
115 char t4 = line_data[j + 3];
117 line_data[j + 3] = t1;
118 line_data[j + 2] = t2;
119 line_data[j + 1] = t3;
120 line_data[j + 0] = t4;
129 /* Create random image for testing purposes */
130 static pixman_image_t *
131 create_random_image (pixman_format_code_t *allowed_formats,
134 int max_extra_stride,
135 pixman_format_code_t *used_fmt)
137 int n = 0, i, width, height, stride;
138 pixman_format_code_t fmt;
142 while (allowed_formats[n] != -1)
144 fmt = allowed_formats[lcg_rand_n (n)];
145 width = lcg_rand_n (max_width) + 1;
146 height = lcg_rand_n (max_height) + 1;
147 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
148 lcg_rand_n (max_extra_stride + 1);
149 stride = (stride + 3) & ~3;
151 /* do the allocation */
152 buf = aligned_malloc (64, stride * height);
154 /* initialize image with random data */
155 for (i = 0; i < stride * height; i++)
157 /* generation is biased to having more 0 or 255 bytes as
158 * they are more likely to be special-cased in code
160 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
161 (lcg_rand_n (2) ? 0 : 255);
164 img = pixman_image_create_bits (fmt, width, height, buf, stride);
166 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
168 if (used_fmt) *used_fmt = fmt;
172 /* Free random image, and optionally update crc32 based on its data */
174 free_random_image (uint32_t initcrc,
176 pixman_format_code_t fmt)
179 int stride = pixman_image_get_stride (img);
180 uint32_t *data = pixman_image_get_data (img);
181 int height = pixman_image_get_height (img);;
185 /* mask unused 'x' part */
186 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
187 PIXMAN_FORMAT_DEPTH (fmt) != 0)
190 uint32_t *data = pixman_image_get_data (img);
191 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
193 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
194 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
196 for (i = 0; i < 32; i++)
197 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
199 for (i = 0; i < stride * height / 4; i++)
203 /* swap endiannes in order to provide identical results on both big
204 * and litte endian systems
206 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
207 crc32 = compute_crc32 (initcrc, data, stride * height);
210 pixman_image_unref (img);
216 static pixman_op_t op_list[] = {
224 PIXMAN_OP_OVER_REVERSE,
226 PIXMAN_OP_IN_REVERSE,
228 PIXMAN_OP_OUT_REVERSE,
230 PIXMAN_OP_ATOP_REVERSE,
234 PIXMAN_OP_DISJOINT_CLEAR,
235 PIXMAN_OP_DISJOINT_SRC,
236 PIXMAN_OP_DISJOINT_DST,
237 PIXMAN_OP_DISJOINT_OVER,
238 PIXMAN_OP_DISJOINT_OVER_REVERSE,
239 PIXMAN_OP_DISJOINT_IN,
240 PIXMAN_OP_DISJOINT_IN_REVERSE,
241 PIXMAN_OP_DISJOINT_OUT,
242 PIXMAN_OP_DISJOINT_OUT_REVERSE,
243 PIXMAN_OP_DISJOINT_ATOP,
244 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
245 PIXMAN_OP_DISJOINT_XOR,
246 PIXMAN_OP_CONJOINT_CLEAR,
247 PIXMAN_OP_CONJOINT_SRC,
248 PIXMAN_OP_CONJOINT_DST,
249 PIXMAN_OP_CONJOINT_OVER,
250 PIXMAN_OP_CONJOINT_OVER_REVERSE,
251 PIXMAN_OP_CONJOINT_IN,
252 PIXMAN_OP_CONJOINT_IN_REVERSE,
253 PIXMAN_OP_CONJOINT_OUT,
254 PIXMAN_OP_CONJOINT_OUT_REVERSE,
255 PIXMAN_OP_CONJOINT_ATOP,
256 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
257 PIXMAN_OP_CONJOINT_XOR,
263 PIXMAN_OP_COLOR_DODGE,
264 PIXMAN_OP_COLOR_BURN,
265 PIXMAN_OP_HARD_LIGHT,
266 PIXMAN_OP_DIFFERENCE,
268 #if 0 /* these use floating point math and are not always bitexact on different platforms */
269 PIXMAN_OP_SOFT_LIGHT,
271 PIXMAN_OP_HSL_SATURATION,
273 PIXMAN_OP_HSL_LUMINOSITY,
277 static pixman_format_code_t img_fmt_list[] = {
308 #if 0 /* using these crashes the test */
327 static pixman_format_code_t mask_fmt_list[] = {
337 * Composite operation with pseudorandom images
340 test_composite (uint32_t initcrc, int testnum, int verbose)
343 pixman_image_t *src_img = NULL;
344 pixman_image_t *dst_img = NULL;
345 pixman_image_t *mask_img = NULL;
346 int src_width, src_height;
347 int dst_width, dst_height;
348 int src_stride, dst_stride;
354 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
357 int max_width, max_height, max_extra_stride;
359 max_width = max_height = 24 + testnum / 10000;
360 max_extra_stride = 4 + testnum / 1000000;
368 if (max_extra_stride > 8)
369 max_extra_stride = 8;
373 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
378 src_img = create_random_image (img_fmt_list, max_width, max_height,
379 max_extra_stride, &src_fmt);
384 src_img = create_random_image (img_fmt_list, 1, 1,
385 max_extra_stride, &src_fmt);
387 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
390 dst_img = create_random_image (img_fmt_list, max_width, max_height,
391 max_extra_stride, &dst_fmt);
402 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
403 max_extra_stride, &mask_fmt);
408 mask_img = create_random_image (mask_fmt_list, 1, 1,
409 max_extra_stride, &mask_fmt);
410 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
414 pixman_image_set_component_alpha (mask_img, 1);
416 mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
417 mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
420 src_width = pixman_image_get_width (src_img);
421 src_height = pixman_image_get_height (src_img);
422 src_stride = pixman_image_get_stride (src_img);
424 dst_width = pixman_image_get_width (dst_img);
425 dst_height = pixman_image_get_height (dst_img);
426 dst_stride = pixman_image_get_stride (dst_img);
428 dstbuf = pixman_image_get_data (dst_img);
430 src_x = lcg_rand_n (src_width);
431 src_y = lcg_rand_n (src_height);
432 dst_x = lcg_rand_n (dst_width);
433 dst_y = lcg_rand_n (dst_height);
435 w = lcg_rand_n (dst_width - dst_x + 1);
436 h = lcg_rand_n (dst_height - dst_y + 1);
440 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
441 op, src_fmt, dst_fmt, mask_fmt);
442 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
443 src_width, src_height, dst_width, dst_height);
444 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
445 src_x, src_y, dst_x, dst_y);
446 printf ("src_stride=%d, dst_stride=%d\n",
447 src_stride, dst_stride);
448 printf ("w=%d, h=%d\n", w, h);
451 pixman_image_composite (op, src_img, mask_img, dst_img,
452 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
459 for (i = 0; i < dst_height; i++)
461 for (j = 0; j < dst_stride; j++)
463 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
466 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
473 free_random_image (initcrc, src_img, -1);
474 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
477 free_random_image (initcrc, mask_img, -1);
483 main (int argc, char *argv[])
485 int i, n1 = 1, n2 = 0;
487 int verbose = getenv ("VERBOSE") != NULL;
506 crc = test_composite (0, abs (n2), 1);
507 printf ("crc32=%08X\n", crc);
511 for (i = n1; i <= n2; i++)
513 crc = test_composite (crc, i, 0);
516 printf ("%d: %08X\n", i, crc);
518 printf ("crc32=%08X\n", crc);
522 /* Predefined value for running with all the fastpath functions
523 disabled. It needs to be updated every time when changes are
524 introduced to this program or behavior of pixman changes! */
525 if (crc == 0x1911E2C3)
527 printf ("blitters test passed\n");
531 printf ("blitters test failed!\n");