Merge branch 'more-flags'
[profile/ivi/pixman.git] / test / blitters-test.c
1 /*
2  * Test program, which stresses the use of different color formats and
3  * compositing operations.
4  *
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
8  *
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
23  */
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <config.h>
28 #include "utils.h"
29
30 static void *
31 aligned_malloc (size_t align, size_t size)
32 {
33     void *result;
34
35 #ifdef HAVE_POSIX_MEMALIGN
36     if (posix_memalign (&result, align, size) != 0)
37       result = NULL;
38 #else
39     result = malloc (size);
40 #endif
41
42     return result;
43 }
44
45 /* Create random image for testing purposes */
46 static pixman_image_t *
47 create_random_image (pixman_format_code_t *allowed_formats,
48                      int                   max_width,
49                      int                   max_height,
50                      int                   max_extra_stride,
51                      pixman_format_code_t *used_fmt)
52 {
53     int n = 0, i, width, height, stride;
54     pixman_format_code_t fmt;
55     uint32_t *buf;
56     pixman_image_t *img;
57
58     while (allowed_formats[n] != -1)
59         n++;
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;
66
67     /* do the allocation */
68     buf = aligned_malloc (64, stride * height);
69
70     /* initialize image with random data */
71     for (i = 0; i < stride * height; i++)
72     {
73         /* generation is biased to having more 0 or 255 bytes as
74          * they are more likely to be special-cased in code
75          */
76         *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
77             (lcg_rand_n (2) ? 0 : 255);
78     }
79
80     img = pixman_image_create_bits (fmt, width, height, buf, stride);
81
82     image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
83
84     if (used_fmt) *used_fmt = fmt;
85     return img;
86 }
87
88 /* Free random image, and optionally update crc32 based on its data */
89 static uint32_t
90 free_random_image (uint32_t initcrc,
91                    pixman_image_t *img,
92                    pixman_format_code_t fmt)
93 {
94     uint32_t crc32 = 0;
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);
98
99     if (fmt != -1)
100     {
101         /* mask unused 'x' part */
102         if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
103             PIXMAN_FORMAT_DEPTH (fmt) != 0)
104         {
105             int i;
106             uint32_t *data = pixman_image_get_data (img);
107             uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
108
109             if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA)
110                 mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
111
112             for (i = 0; i < 32; i++)
113                 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
114
115             for (i = 0; i < stride * height / 4; i++)
116                 data[i] &= mask;
117         }
118
119         /* swap endiannes in order to provide identical results on both big
120          * and litte endian systems
121          */
122         image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
123         crc32 = compute_crc32 (initcrc, data, stride * height);
124     }
125
126     pixman_image_unref (img);
127     free (data);
128
129     return crc32;
130 }
131
132 static pixman_op_t op_list[] = {
133     PIXMAN_OP_SRC,
134     PIXMAN_OP_OVER,
135     PIXMAN_OP_ADD,
136     PIXMAN_OP_CLEAR,
137     PIXMAN_OP_SRC,
138     PIXMAN_OP_DST,
139     PIXMAN_OP_OVER,
140     PIXMAN_OP_OVER_REVERSE,
141     PIXMAN_OP_IN,
142     PIXMAN_OP_IN_REVERSE,
143     PIXMAN_OP_OUT,
144     PIXMAN_OP_OUT_REVERSE,
145     PIXMAN_OP_ATOP,
146     PIXMAN_OP_ATOP_REVERSE,
147     PIXMAN_OP_XOR,
148     PIXMAN_OP_ADD,
149     PIXMAN_OP_SATURATE,
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,
174     PIXMAN_OP_MULTIPLY,
175     PIXMAN_OP_SCREEN,
176     PIXMAN_OP_OVERLAY,
177     PIXMAN_OP_DARKEN,
178     PIXMAN_OP_LIGHTEN,
179     PIXMAN_OP_COLOR_DODGE,
180     PIXMAN_OP_COLOR_BURN,
181     PIXMAN_OP_HARD_LIGHT,
182     PIXMAN_OP_DIFFERENCE,
183     PIXMAN_OP_EXCLUSION,
184 #if 0 /* these use floating point math and are not always bitexact on different platforms */
185     PIXMAN_OP_SOFT_LIGHT,
186     PIXMAN_OP_HSL_HUE,
187     PIXMAN_OP_HSL_SATURATION,
188     PIXMAN_OP_HSL_COLOR,
189     PIXMAN_OP_HSL_LUMINOSITY,
190 #endif
191 };
192
193 static pixman_format_code_t img_fmt_list[] = {
194     PIXMAN_a8r8g8b8,
195     PIXMAN_x8r8g8b8,
196     PIXMAN_r5g6b5,
197     PIXMAN_r3g3b2,
198     PIXMAN_a8,
199     PIXMAN_a8b8g8r8,
200     PIXMAN_x8b8g8r8,
201     PIXMAN_b8g8r8a8,
202     PIXMAN_b8g8r8x8,
203     PIXMAN_r8g8b8,
204     PIXMAN_b8g8r8,
205     PIXMAN_r5g6b5,
206     PIXMAN_b5g6r5,
207     PIXMAN_x2r10g10b10,
208     PIXMAN_a2r10g10b10,
209     PIXMAN_x2b10g10r10,
210     PIXMAN_a2b10g10r10,
211     PIXMAN_a1r5g5b5,
212     PIXMAN_x1r5g5b5,
213     PIXMAN_a1b5g5r5,
214     PIXMAN_x1b5g5r5,
215     PIXMAN_a4r4g4b4,
216     PIXMAN_x4r4g4b4,
217     PIXMAN_a4b4g4r4,
218     PIXMAN_x4b4g4r4,
219     PIXMAN_a8,
220     PIXMAN_r3g3b2,
221     PIXMAN_b2g3r3,
222     PIXMAN_a2r2g2b2,
223     PIXMAN_a2b2g2r2,
224 #if 0 /* using these crashes the test */
225     PIXMAN_c8,
226     PIXMAN_g8,
227     PIXMAN_x4c4,
228     PIXMAN_x4g4,
229     PIXMAN_c4,
230     PIXMAN_g4,
231     PIXMAN_g1,
232 #endif
233     PIXMAN_x4a4,
234     PIXMAN_a4,
235     PIXMAN_r1g2b1,
236     PIXMAN_b1g2r1,
237     PIXMAN_a1r1g1b1,
238     PIXMAN_a1b1g1r1,
239     PIXMAN_a1,
240     -1
241 };
242
243 static pixman_format_code_t mask_fmt_list[] = {
244     PIXMAN_a8r8g8b8,
245     PIXMAN_a8,
246     PIXMAN_a4,
247     PIXMAN_a1,
248     -1
249 };
250
251
252 /*
253  * Composite operation with pseudorandom images
254  */
255 uint32_t
256 test_composite (uint32_t initcrc, int testnum, int verbose)
257 {
258     int i;
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;
265     int src_x, src_y;
266     int dst_x, dst_y;
267     int mask_x, mask_y;
268     int w, h;
269     int op;
270     pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
271     uint32_t *dstbuf, *srcbuf, *maskbuf;
272     uint32_t crc32;
273     int max_width, max_height, max_extra_stride;
274
275     max_width = max_height = 24 + testnum / 10000;
276     max_extra_stride = 4 + testnum / 1000000;
277
278     if (max_width > 256)
279         max_width = 256;
280
281     if (max_height > 16)
282         max_height = 16;
283
284     if (max_extra_stride > 8)
285         max_extra_stride = 8;
286
287     lcg_srand (testnum);
288
289     op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
290
291     if (lcg_rand_n (8))
292     {
293         /* normal image */
294         src_img = create_random_image (img_fmt_list, max_width, max_height,
295                                        max_extra_stride, &src_fmt);
296     }
297     else
298     {
299         /* solid case */
300         src_img = create_random_image (img_fmt_list, 1, 1,
301                                        max_extra_stride, &src_fmt);
302
303         pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
304     }
305
306     dst_img = create_random_image (img_fmt_list, max_width, max_height,
307                                    max_extra_stride, &dst_fmt);
308
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);
312
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);
316
317     dstbuf = pixman_image_get_data (dst_img);
318     srcbuf = pixman_image_get_data (src_img);
319
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);
324
325     mask_img = NULL;
326     mask_fmt = -1;
327     mask_x = 0;
328     mask_y = 0;
329     maskbuf = NULL;
330
331     if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
332         (lcg_rand_n (4) == 0))
333     {
334         /* PIXBUF */
335         mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
336         mask_img = pixman_image_create_bits (mask_fmt,
337                                              src_width,
338                                              src_height,
339                                              srcbuf,
340                                              src_stride);
341         mask_x = src_x;
342         mask_y = src_y;
343         maskbuf = srcbuf;
344     }
345     else if (lcg_rand_n (2))
346     {
347         if (lcg_rand_n (2))
348         {
349             mask_img = create_random_image (mask_fmt_list, max_width, max_height,
350                                            max_extra_stride, &mask_fmt);
351         }
352         else
353         {
354             /* solid case */
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);
358         }
359
360         if (lcg_rand_n (2))
361             pixman_image_set_component_alpha (mask_img, 1);
362
363         mask_x = lcg_rand_n (pixman_image_get_width (mask_img));
364         mask_y = lcg_rand_n (pixman_image_get_height (mask_img));
365     }
366
367
368     w = lcg_rand_n (dst_width - dst_x + 1);
369     h = lcg_rand_n (dst_height - dst_y + 1);
370
371     if (verbose)
372     {
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);
382     }
383
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);
386
387     if (verbose)
388     {
389         int j;
390
391         printf ("---\n");
392         for (i = 0; i < dst_height; i++)
393         {
394             for (j = 0; j < dst_stride; j++)
395             {
396                 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
397                     printf ("| ");
398
399                 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
400             }
401             printf ("\n");
402         }
403         printf ("---\n");
404     }
405
406     free_random_image (initcrc, src_img, -1);
407     crc32 = free_random_image (initcrc, dst_img, dst_fmt);
408
409     if (mask_img)
410     {
411         if (srcbuf == maskbuf)
412             pixman_image_unref(mask_img);
413         else
414             free_random_image (initcrc, mask_img, -1);
415     }
416
417
418     return crc32;
419 }
420
421 int
422 main (int argc, char *argv[])
423 {
424     int i, n1 = 1, n2 = 0;
425     uint32_t crc = 0;
426     int verbose = getenv ("VERBOSE") != NULL;
427
428     if (argc >= 3)
429     {
430         n1 = atoi (argv[1]);
431         n2 = atoi (argv[2]);
432     }
433     else if (argc >= 2)
434     {
435         n2 = atoi (argv[1]);
436     }
437     else
438     {
439         n1 = 1;
440         n2 = 2000000;
441     }
442
443     if (n2 < 0)
444     {
445         crc = test_composite (0, abs (n2), 1);
446         printf ("crc32=%08X\n", crc);
447     }
448     else
449     {
450         for (i = n1; i <= n2; i++)
451         {
452             crc = test_composite (crc, i, 0);
453
454             if (verbose)
455                 printf ("%d: %08X\n", i, crc);
456         }
457         printf ("crc32=%08X\n", crc);
458
459         if (n2 == 2000000)
460         {
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)
465             {
466                 printf ("blitters test passed\n");
467             }
468             else
469             {
470                 printf ("blitters test failed!\n");
471                 return 1;
472             }
473         }
474     }
475     return 0;
476 }