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 static pixman_indexed_t palette;
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)];
64 width = lcg_rand_n (max_width) + 1;
65 height = lcg_rand_n (max_height) + 1;
66 stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
67 lcg_rand_n (max_extra_stride + 1);
68 stride = (stride + 3) & ~3;
70 /* do the allocation */
71 buf = aligned_malloc (64, stride * height);
73 /* initialize image with random data */
74 for (i = 0; i < stride * height; i++)
76 /* generation is biased to having more 0 or 255 bytes as
77 * they are more likely to be special-cased in code
79 *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
80 (lcg_rand_n (2) ? 0 : 255);
83 img = pixman_image_create_bits (fmt, width, height, buf, stride);
85 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR ||
86 PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY)
88 pixman_image_set_indexed (img, &palette);
91 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
93 if (used_fmt) *used_fmt = fmt;
97 /* Free random image, and optionally update crc32 based on its data */
99 free_random_image (uint32_t initcrc,
101 pixman_format_code_t fmt)
104 int stride = pixman_image_get_stride (img);
105 uint32_t *data = pixman_image_get_data (img);
106 int height = pixman_image_get_height (img);
110 /* mask unused 'x' part */
111 if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
112 PIXMAN_FORMAT_DEPTH (fmt) != 0)
115 uint32_t *data = pixman_image_get_data (img);
116 uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
118 if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
119 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
121 for (i = 0; i < 32; i++)
122 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
124 for (i = 0; i < stride * height / 4; i++)
128 /* swap endiannes in order to provide identical results on both big
129 * and litte endian systems
131 image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
132 crc32 = compute_crc32 (initcrc, data, stride * height);
135 pixman_image_unref (img);
141 static pixman_op_t op_list[] = {
149 PIXMAN_OP_OVER_REVERSE,
151 PIXMAN_OP_IN_REVERSE,
153 PIXMAN_OP_OUT_REVERSE,
155 PIXMAN_OP_ATOP_REVERSE,
159 PIXMAN_OP_DISJOINT_CLEAR,
160 PIXMAN_OP_DISJOINT_SRC,
161 PIXMAN_OP_DISJOINT_DST,
162 PIXMAN_OP_DISJOINT_OVER,
163 PIXMAN_OP_DISJOINT_OVER_REVERSE,
164 PIXMAN_OP_DISJOINT_IN,
165 PIXMAN_OP_DISJOINT_IN_REVERSE,
166 PIXMAN_OP_DISJOINT_OUT,
167 PIXMAN_OP_DISJOINT_OUT_REVERSE,
168 PIXMAN_OP_DISJOINT_ATOP,
169 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
170 PIXMAN_OP_DISJOINT_XOR,
171 PIXMAN_OP_CONJOINT_CLEAR,
172 PIXMAN_OP_CONJOINT_SRC,
173 PIXMAN_OP_CONJOINT_DST,
174 PIXMAN_OP_CONJOINT_OVER,
175 PIXMAN_OP_CONJOINT_OVER_REVERSE,
176 PIXMAN_OP_CONJOINT_IN,
177 PIXMAN_OP_CONJOINT_IN_REVERSE,
178 PIXMAN_OP_CONJOINT_OUT,
179 PIXMAN_OP_CONJOINT_OUT_REVERSE,
180 PIXMAN_OP_CONJOINT_ATOP,
181 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
182 PIXMAN_OP_CONJOINT_XOR,
188 PIXMAN_OP_COLOR_DODGE,
189 PIXMAN_OP_COLOR_BURN,
190 PIXMAN_OP_HARD_LIGHT,
191 PIXMAN_OP_DIFFERENCE,
193 #if 0 /* these use floating point math and are not always bitexact on different platforms */
194 PIXMAN_OP_SOFT_LIGHT,
196 PIXMAN_OP_HSL_SATURATION,
198 PIXMAN_OP_HSL_LUMINOSITY,
202 static pixman_format_code_t img_fmt_list[] = {
250 static pixman_format_code_t mask_fmt_list[] = {
260 * Composite operation with pseudorandom images
263 test_composite (uint32_t initcrc, int testnum, int verbose)
266 pixman_image_t *src_img = NULL;
267 pixman_image_t *dst_img = NULL;
268 pixman_image_t *mask_img = NULL;
269 int src_width, src_height;
270 int dst_width, dst_height;
271 int src_stride, dst_stride;
277 pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
278 uint32_t *dstbuf, *srcbuf, *maskbuf;
280 int max_width, max_height, max_extra_stride;
282 max_width = max_height = 24 + testnum / 10000;
283 max_extra_stride = 4 + testnum / 1000000;
291 if (max_extra_stride > 8)
292 max_extra_stride = 8;
296 op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
301 src_img = create_random_image (img_fmt_list, max_width, max_height,
302 max_extra_stride, &src_fmt);
307 src_img = create_random_image (img_fmt_list, 1, 1,
308 max_extra_stride, &src_fmt);
310 pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
313 dst_img = create_random_image (img_fmt_list, max_width, max_height,
314 max_extra_stride, &dst_fmt);
316 src_width = pixman_image_get_width (src_img);
317 src_height = pixman_image_get_height (src_img);
318 src_stride = pixman_image_get_stride (src_img);
320 dst_width = pixman_image_get_width (dst_img);
321 dst_height = pixman_image_get_height (dst_img);
322 dst_stride = pixman_image_get_stride (dst_img);
324 dstbuf = pixman_image_get_data (dst_img);
325 srcbuf = pixman_image_get_data (src_img);
327 src_x = lcg_rand_n (src_width);
328 src_y = lcg_rand_n (src_height);
329 dst_x = lcg_rand_n (dst_width);
330 dst_y = lcg_rand_n (dst_height);
338 if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
339 (lcg_rand_n (4) == 0))
342 mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
343 mask_img = pixman_image_create_bits (mask_fmt,
352 else if (lcg_rand_n (2))
356 mask_img = create_random_image (mask_fmt_list, max_width, max_height,
357 max_extra_stride, &mask_fmt);
362 mask_img = create_random_image (mask_fmt_list, 1, 1,
363 max_extra_stride, &mask_fmt);
364 pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
368 pixman_image_set_component_alpha (mask_img, 1);
370 mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
371 mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
375 w = lcg_rand_n (dst_width - dst_x + 1);
376 h = lcg_rand_n (dst_height - dst_y + 1);
380 printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
381 op, src_fmt, dst_fmt, mask_fmt);
382 printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
383 src_width, src_height, dst_width, dst_height);
384 printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
385 src_x, src_y, dst_x, dst_y);
386 printf ("src_stride=%d, dst_stride=%d\n",
387 src_stride, dst_stride);
388 printf ("w=%d, h=%d\n", w, h);
391 pixman_image_composite (op, src_img, mask_img, dst_img,
392 src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
399 for (i = 0; i < dst_height; i++)
401 for (j = 0; j < dst_stride; j++)
403 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
406 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
413 free_random_image (initcrc, src_img, -1);
414 crc32 = free_random_image (initcrc, dst_img, dst_fmt);
418 if (srcbuf == maskbuf)
419 pixman_image_unref(mask_img);
421 free_random_image (initcrc, mask_img, -1);
429 initialize_palette (void)
433 for (i = 0; i < PIXMAN_MAX_INDEXED; ++i)
434 palette.rgba[i] = lcg_rand ();
436 for (i = 0; i < 32768; ++i)
437 palette.ent[i] = lcg_rand() & 0xff;
441 main (int argc, char *argv[])
443 int i, n1 = 1, n2 = 0;
445 int verbose = getenv ("VERBOSE") != NULL;
447 initialize_palette();
466 crc = test_composite (0, abs (n2), 1);
467 printf ("crc32=%08X\n", crc);
471 for (i = n1; i <= n2; i++)
473 crc = test_composite (crc, i, 0);
476 printf ("%d: %08X\n", i, crc);
478 printf ("crc32=%08X\n", crc);
482 /* Predefined value for running with all the fastpath functions
483 disabled. It needs to be updated every time when changes are
484 introduced to this program or behavior of pixman changes! */
485 if (crc == 0x8F9F7DC1)
487 printf ("blitters test passed\n");
491 printf ("blitters test failed!\n");