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 /* Create random image for testing purposes */
48 static pixman_image_t *
49 create_random_image (pixman_format_code_t *allowed_formats,
53 pixman_format_code_t *used_fmt)
55 int n = 0, i, width, height, stride;
56 pixman_format_code_t fmt;
60 while (allowed_formats[n] != -1)
62 fmt = allowed_formats[lcg_rand_n (n)];
63 width = lcg_rand_n (max_width) + 1;
64 height = lcg_rand_n (max_height) + 1;
65 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
66 lcg_rand_n (max_extra_stride + 1);
67 stride = (stride + 3) & ~3;
69 /* do the allocation */
70 buf = aligned_malloc (64, stride * height);
72 /* initialize image with random data */
73 for (i = 0; i < stride * height; i++)
75 /* generation is biased to having more 0 or 255 bytes as
76 * they are more likely to be special-cased in code
78 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
79 (lcg_rand_n (2) ? 0 : 255);
82 img = pixman_image_create_bits (fmt, width, height, buf, stride);
84 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
86 if (used_fmt) *used_fmt = fmt;
90 /* Free random image, and optionally update crc32 based on its data */
92 free_random_image (uint32_t initcrc,
94 pixman_format_code_t fmt)
97 int stride = pixman_image_get_stride (img);
98 uint32_t *data = pixman_image_get_data (img);
99 int height = pixman_image_get_height (img);
103 /* mask unused 'x' part */
104 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
105 PIXMAN_FORMAT_DEPTH (fmt) != 0)
108 uint32_t *data = pixman_image_get_data (img);
109 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
111 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
112 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
114 for (i = 0; i < 32; i++)
115 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
117 for (i = 0; i < stride * height / 4; i++)
121 /* swap endiannes in order to provide identical results on both big
122 * and litte endian systems
124 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
125 crc32 = compute_crc32 (initcrc, data, stride * height);
128 pixman_image_unref (img);
134 static pixman_op_t op_list[] = {
142 PIXMAN_OP_OVER_REVERSE,
144 PIXMAN_OP_IN_REVERSE,
146 PIXMAN_OP_OUT_REVERSE,
148 PIXMAN_OP_ATOP_REVERSE,
152 PIXMAN_OP_DISJOINT_CLEAR,
153 PIXMAN_OP_DISJOINT_SRC,
154 PIXMAN_OP_DISJOINT_DST,
155 PIXMAN_OP_DISJOINT_OVER,
156 PIXMAN_OP_DISJOINT_OVER_REVERSE,
157 PIXMAN_OP_DISJOINT_IN,
158 PIXMAN_OP_DISJOINT_IN_REVERSE,
159 PIXMAN_OP_DISJOINT_OUT,
160 PIXMAN_OP_DISJOINT_OUT_REVERSE,
161 PIXMAN_OP_DISJOINT_ATOP,
162 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
163 PIXMAN_OP_DISJOINT_XOR,
164 PIXMAN_OP_CONJOINT_CLEAR,
165 PIXMAN_OP_CONJOINT_SRC,
166 PIXMAN_OP_CONJOINT_DST,
167 PIXMAN_OP_CONJOINT_OVER,
168 PIXMAN_OP_CONJOINT_OVER_REVERSE,
169 PIXMAN_OP_CONJOINT_IN,
170 PIXMAN_OP_CONJOINT_IN_REVERSE,
171 PIXMAN_OP_CONJOINT_OUT,
172 PIXMAN_OP_CONJOINT_OUT_REVERSE,
173 PIXMAN_OP_CONJOINT_ATOP,
174 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
175 PIXMAN_OP_CONJOINT_XOR,
181 PIXMAN_OP_COLOR_DODGE,
182 PIXMAN_OP_COLOR_BURN,
183 PIXMAN_OP_HARD_LIGHT,
184 PIXMAN_OP_DIFFERENCE,
186 #if 0 /* these use floating point math and are not always bitexact on different platforms */
187 PIXMAN_OP_SOFT_LIGHT,
189 PIXMAN_OP_HSL_SATURATION,
191 PIXMAN_OP_HSL_LUMINOSITY,
195 static pixman_format_code_t img_fmt_list[] = {
226 #if 0 /* using these crashes the test */
245 static pixman_format_code_t mask_fmt_list[] = {
255 * Composite operation with pseudorandom images
258 test_composite (uint32_t initcrc, int testnum, int verbose)
261 pixman_image_t *src_img = NULL;
262 pixman_image_t *dst_img = NULL;
263 pixman_image_t *mask_img = NULL;
264 int src_width, src_height;
265 int dst_width, dst_height;
266 int src_stride, dst_stride;
272 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
273 uint32_t *dstbuf, *srcbuf, *maskbuf;
275 int max_width, max_height, max_extra_stride;
277 max_width = max_height = 24 + testnum / 10000;
278 max_extra_stride = 4 + testnum / 1000000;
286 if (max_extra_stride > 8)
287 max_extra_stride = 8;
291 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
296 src_img = create_random_image (img_fmt_list, max_width, max_height,
297 max_extra_stride, &src_fmt);
302 src_img = create_random_image (img_fmt_list, 1, 1,
303 max_extra_stride, &src_fmt);
305 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
308 dst_img = create_random_image (img_fmt_list, max_width, max_height,
309 max_extra_stride, &dst_fmt);
311 src_width = pixman_image_get_width (src_img);
312 src_height = pixman_image_get_height (src_img);
313 src_stride = pixman_image_get_stride (src_img);
315 dst_width = pixman_image_get_width (dst_img);
316 dst_height = pixman_image_get_height (dst_img);
317 dst_stride = pixman_image_get_stride (dst_img);
319 dstbuf = pixman_image_get_data (dst_img);
320 srcbuf = pixman_image_get_data (src_img);
322 src_x = lcg_rand_n (src_width);
323 src_y = lcg_rand_n (src_height);
324 dst_x = lcg_rand_n (dst_width);
325 dst_y = lcg_rand_n (dst_height);
333 if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
334 (lcg_rand_n (4) == 0))
337 mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
338 mask_img = pixman_image_create_bits (mask_fmt,
347 else if (lcg_rand_n (2))
351 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
352 max_extra_stride, &mask_fmt);
357 mask_img = create_random_image (mask_fmt_list, 1, 1,
358 max_extra_stride, &mask_fmt);
359 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
363 pixman_image_set_component_alpha (mask_img, 1);
365 mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
366 mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
370 w = lcg_rand_n (dst_width - dst_x + 1);
371 h = lcg_rand_n (dst_height - dst_y + 1);
375 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
376 op, src_fmt, dst_fmt, mask_fmt);
377 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
378 src_width, src_height, dst_width, dst_height);
379 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
380 src_x, src_y, dst_x, dst_y);
381 printf ("src_stride=%d, dst_stride=%d\n",
382 src_stride, dst_stride);
383 printf ("w=%d, h=%d\n", w, h);
386 pixman_image_composite (op, src_img, mask_img, dst_img,
387 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
394 for (i = 0; i < dst_height; i++)
396 for (j = 0; j < dst_stride; j++)
398 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
401 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
408 free_random_image (initcrc, src_img, -1);
409 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
413 if (srcbuf == maskbuf)
414 pixman_image_unref(mask_img);
416 free_random_image (initcrc, mask_img, -1);
424 main (int argc, char *argv[])
426 int i, n1 = 1, n2 = 0;
428 int verbose = getenv ("VERBOSE") != NULL;
447 crc = test_composite (0, abs (n2), 1);
448 printf ("crc32=%08X\n", crc);
452 for (i = n1; i <= n2; i++)
454 crc = test_composite (crc, i, 0);
457 printf ("%d: %08X\n", i, crc);
459 printf ("crc32=%08X\n", crc);
463 /* Predefined value for running with all the fastpath functions
464 disabled. It needs to be updated every time when changes are
465 introduced to this program or behavior of pixman changes! */
466 if (crc == 0x20CBE02C)
468 printf ("blitters test passed\n");
472 printf ("blitters test failed!\n");