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
31 aligned_malloc (size_t align, size_t size)
35 #ifdef HAVE_POSIX_MEMALIGN
36 if (posix_memalign (&result, align, size) != 0)
39 result = malloc (size);
45 /* Create random image for testing purposes */
46 static pixman_image_t *
47 create_random_image (pixman_format_code_t *allowed_formats,
51 pixman_format_code_t *used_fmt)
53 int n = 0, i, width, height, stride;
54 pixman_format_code_t fmt;
58 while (allowed_formats[n] != -1)
60 fmt = allowed_formats[lcg_rand_n (n)];
61 width = lcg_rand_n (max_width) + 1;
62 height = lcg_rand_n (max_height) + 1;
63 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
64 lcg_rand_n (max_extra_stride + 1);
65 stride = (stride + 3) & ~3;
67 /* do the allocation */
68 buf = aligned_malloc (64, stride * height);
70 /* initialize image with random data */
71 for (i = 0; i < stride * height; i++)
73 /* generation is biased to having more 0 or 255 bytes as
74 * they are more likely to be special-cased in code
76 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
77 (lcg_rand_n (2) ? 0 : 255);
80 img = pixman_image_create_bits (fmt, width, height, buf, stride);
82 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
84 if (used_fmt) *used_fmt = fmt;
88 /* Free random image, and optionally update crc32 based on its data */
90 free_random_image (uint32_t initcrc,
92 pixman_format_code_t fmt)
95 int stride = pixman_image_get_stride (img);
96 uint32_t *data = pixman_image_get_data (img);
97 int height = pixman_image_get_height (img);
101 /* mask unused 'x' part */
102 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
103 PIXMAN_FORMAT_DEPTH (fmt) != 0)
106 uint32_t *data = pixman_image_get_data (img);
107 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
109 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
110 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
112 for (i = 0; i < 32; i++)
113 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
115 for (i = 0; i < stride * height / 4; i++)
119 /* swap endiannes in order to provide identical results on both big
120 * and litte endian systems
122 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
123 crc32 = compute_crc32 (initcrc, data, stride * height);
126 pixman_image_unref (img);
132 static pixman_op_t op_list[] = {
140 PIXMAN_OP_OVER_REVERSE,
142 PIXMAN_OP_IN_REVERSE,
144 PIXMAN_OP_OUT_REVERSE,
146 PIXMAN_OP_ATOP_REVERSE,
150 PIXMAN_OP_DISJOINT_CLEAR,
151 PIXMAN_OP_DISJOINT_SRC,
152 PIXMAN_OP_DISJOINT_DST,
153 PIXMAN_OP_DISJOINT_OVER,
154 PIXMAN_OP_DISJOINT_OVER_REVERSE,
155 PIXMAN_OP_DISJOINT_IN,
156 PIXMAN_OP_DISJOINT_IN_REVERSE,
157 PIXMAN_OP_DISJOINT_OUT,
158 PIXMAN_OP_DISJOINT_OUT_REVERSE,
159 PIXMAN_OP_DISJOINT_ATOP,
160 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
161 PIXMAN_OP_DISJOINT_XOR,
162 PIXMAN_OP_CONJOINT_CLEAR,
163 PIXMAN_OP_CONJOINT_SRC,
164 PIXMAN_OP_CONJOINT_DST,
165 PIXMAN_OP_CONJOINT_OVER,
166 PIXMAN_OP_CONJOINT_OVER_REVERSE,
167 PIXMAN_OP_CONJOINT_IN,
168 PIXMAN_OP_CONJOINT_IN_REVERSE,
169 PIXMAN_OP_CONJOINT_OUT,
170 PIXMAN_OP_CONJOINT_OUT_REVERSE,
171 PIXMAN_OP_CONJOINT_ATOP,
172 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
173 PIXMAN_OP_CONJOINT_XOR,
179 PIXMAN_OP_COLOR_DODGE,
180 PIXMAN_OP_COLOR_BURN,
181 PIXMAN_OP_HARD_LIGHT,
182 PIXMAN_OP_DIFFERENCE,
184 #if 0 /* these use floating point math and are not always bitexact on different platforms */
185 PIXMAN_OP_SOFT_LIGHT,
187 PIXMAN_OP_HSL_SATURATION,
189 PIXMAN_OP_HSL_LUMINOSITY,
193 static pixman_format_code_t img_fmt_list[] = {
224 #if 0 /* using these crashes the test */
243 static pixman_format_code_t mask_fmt_list[] = {
253 * Composite operation with pseudorandom images
256 test_composite (uint32_t initcrc, int testnum, int verbose)
259 pixman_image_t *src_img = NULL;
260 pixman_image_t *dst_img = NULL;
261 pixman_image_t *mask_img = NULL;
262 int src_width, src_height;
263 int dst_width, dst_height;
264 int src_stride, dst_stride;
270 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
271 uint32_t *dstbuf, *srcbuf, *maskbuf;
273 int max_width, max_height, max_extra_stride;
275 max_width = max_height = 24 + testnum / 10000;
276 max_extra_stride = 4 + testnum / 1000000;
284 if (max_extra_stride > 8)
285 max_extra_stride = 8;
289 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
294 src_img = create_random_image (img_fmt_list, max_width, max_height,
295 max_extra_stride, &src_fmt);
300 src_img = create_random_image (img_fmt_list, 1, 1,
301 max_extra_stride, &src_fmt);
303 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
306 dst_img = create_random_image (img_fmt_list, max_width, max_height,
307 max_extra_stride, &dst_fmt);
309 src_width = pixman_image_get_width (src_img);
310 src_height = pixman_image_get_height (src_img);
311 src_stride = pixman_image_get_stride (src_img);
313 dst_width = pixman_image_get_width (dst_img);
314 dst_height = pixman_image_get_height (dst_img);
315 dst_stride = pixman_image_get_stride (dst_img);
317 dstbuf = pixman_image_get_data (dst_img);
318 srcbuf = pixman_image_get_data (src_img);
320 src_x = lcg_rand_n (src_width);
321 src_y = lcg_rand_n (src_height);
322 dst_x = lcg_rand_n (dst_width);
323 dst_y = lcg_rand_n (dst_height);
331 if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
332 (lcg_rand_n (4) == 0))
335 mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
336 mask_img = pixman_image_create_bits (mask_fmt,
345 else if (lcg_rand_n (2))
349 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
350 max_extra_stride, &mask_fmt);
355 mask_img = create_random_image (mask_fmt_list, 1, 1,
356 max_extra_stride, &mask_fmt);
357 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
361 pixman_image_set_component_alpha (mask_img, 1);
363 mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
364 mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
368 w = lcg_rand_n (dst_width - dst_x + 1);
369 h = lcg_rand_n (dst_height - dst_y + 1);
373 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
374 op, src_fmt, dst_fmt, mask_fmt);
375 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
376 src_width, src_height, dst_width, dst_height);
377 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
378 src_x, src_y, dst_x, dst_y);
379 printf ("src_stride=%d, dst_stride=%d\n",
380 src_stride, dst_stride);
381 printf ("w=%d, h=%d\n", w, h);
384 pixman_image_composite (op, src_img, mask_img, dst_img,
385 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
392 for (i = 0; i < dst_height; i++)
394 for (j = 0; j < dst_stride; j++)
396 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
399 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
406 free_random_image (initcrc, src_img, -1);
407 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
411 if (srcbuf == maskbuf)
412 pixman_image_unref(mask_img);
414 free_random_image (initcrc, mask_img, -1);
422 main (int argc, char *argv[])
424 int i, n1 = 1, n2 = 0;
426 int verbose = getenv ("VERBOSE") != NULL;
445 crc = test_composite (0, abs (n2), 1);
446 printf ("crc32=%08X\n", crc);
450 for (i = n1; i <= n2; i++)
452 crc = test_composite (crc, i, 0);
455 printf ("%d: %08X\n", i, crc);
457 printf ("crc32=%08X\n", crc);
461 /* Predefined value for running with all the fastpath functions
462 disabled. It needs to be updated every time when changes are
463 introduced to this program or behavior of pixman changes! */
464 if (crc == 0x20CBE02C)
466 printf ("blitters test passed\n");
470 printf ("blitters test failed!\n");