Reenable commented-out tests in blitter-test.
[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 <malloc.h>
28 #include "pixman.h"
29
30 /* A primitive pseudorandom number generator, taken from POSIX.1-2001 example */
31
32 static uint32_t lcg_seed;
33
34 static inline uint32_t
35 lcg_rand (void)
36 {
37     lcg_seed = lcg_seed * 1103515245 + 12345;
38     return ((uint32_t)(lcg_seed / 65536) % 32768);
39 }
40
41 static inline void
42 lcg_srand (uint32_t seed)
43 {
44     lcg_seed = seed;
45 }
46
47 static inline uint32_t
48 lcg_rand_n (int max)
49 {
50     return lcg_rand () % max;
51 }
52
53 /*----------------------------------------------------------------------------*\
54  *  CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
55  *
56  *  This program generates the CRC-32 values for the files named in the
57  *  command-line arguments.  These are the same CRC-32 values used by GZIP,
58  *  PKZIP, and ZMODEM.  The Crc32_ComputeBuf () can also be detached and
59  *  used independently.
60  *
61  *  THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
62  *
63  *  Based on the byte-oriented implementation "File Verification Using CRC"
64  *  by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
65  *
66  *  v1.0.0: original release.
67  *  v1.0.1: fixed printf formats.
68  *  v1.0.2: fixed something else.
69  *  v1.0.3: replaced CRC constant table by generator function.
70  *  v1.0.4: reformatted code, made ANSI C.  1994-12-05.
71  *  v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
72 \*----------------------------------------------------------------------------*/
73
74 /*----------------------------------------------------------------------------*\
75  *  NAME:
76  *     Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
77  *  DESCRIPTION:
78  *     Computes or accumulates the CRC-32 value for a memory buffer.
79  *     The 'inCrc32' gives a previously accumulated CRC-32 value to allow
80  *     a CRC to be generated for multiple sequential buffer-fuls of data.
81  *     The 'inCrc32' for the first buffer must be zero.
82  *  ARGUMENTS:
83  *     inCrc32 - accumulated CRC-32 value, must be 0 on first call
84  *     buf     - buffer to compute CRC-32 value for
85  *     bufLen  - number of bytes in buffer
86  *  RETURNS:
87  *     crc32 - computed CRC-32 value
88  *  ERRORS:
89  *     (no errors are possible)
90 \*----------------------------------------------------------------------------*/
91
92 static uint32_t
93 compute_crc32 (uint32_t    in_crc32,
94                   const void *buf,
95                   size_t      buf_len)
96 {
97     static const uint32_t crc_table[256] = {
98         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
99         0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
100         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
101         0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
102         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
103         0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
104         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
105         0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
106         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
107         0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
108         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
109         0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
110         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
111         0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
112         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
113         0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
114         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
115         0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
116         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
117         0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
118         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
119         0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
120         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
121         0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
122         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
123         0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
124         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
125         0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
126         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
127         0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
128         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
129         0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
130         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
131         0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
132         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
133         0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
134         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
135         0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
136         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
137         0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
138         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
139         0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
140         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
141     };
142
143     uint32_t              crc32;
144     unsigned char *       byte_buf;
145     size_t                i;
146
147     /** accumulate crc32 for buffer **/
148     crc32 = in_crc32 ^ 0xFFFFFFFF;
149     byte_buf = (unsigned char*) buf;
150
151     for (i = 0; i < buf_len; i++)
152         crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
153
154     return (crc32 ^ 0xFFFFFFFF);
155 }
156
157 /* perform endian conversion of pixel data */
158 static void
159 image_endian_swap (pixman_image_t *img, int bpp)
160 {
161     int stride = pixman_image_get_stride (img);
162     uint32_t *data = pixman_image_get_data (img);
163     int height = pixman_image_get_height (img);;
164     int i, j;
165
166     /* swap bytes only on big endian systems */
167     volatile uint16_t endian_check_var = 0x1234;
168     if (*(volatile uint8_t *)&endian_check_var != 0x12) return;
169
170     for (i = 0; i < height; i++)
171     {
172         uint8_t *line_data = (uint8_t *)data + stride * i;
173         /* swap bytes only for 16, 24 and 32 bpp for now */
174         switch (bpp)
175         {
176         case 1:
177             for (j = 0; j < stride; j++)
178             {
179                 line_data[j] =
180                     ((line_data[j] & 0x80) >> 7) |
181                     ((line_data[j] & 0x40) >> 5) |
182                     ((line_data[j] & 0x20) >> 3) |
183                     ((line_data[j] & 0x10) >> 1) |
184                     ((line_data[j] & 0x08) << 1) |
185                     ((line_data[j] & 0x04) << 3) |
186                     ((line_data[j] & 0x02) << 5) |
187                     ((line_data[j] & 0x01) << 7);
188             }
189             break;
190         case 4:
191             for (j = 0; j < stride; j++)
192             {
193                 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
194             }
195             break;
196         case 16:
197             for (j = 0; j + 2 <= stride; j += 2)
198             {
199                 char t1 = line_data[j + 0];
200                 char t2 = line_data[j + 1];
201                 line_data[j + 1] = t1;
202                 line_data[j + 0] = t2;
203             }
204             break;
205         case 24:
206             for (j = 0; j + 3 <= stride; j += 3)
207             {
208                 char t1 = line_data[j + 0];
209                 char t2 = line_data[j + 1];
210                 char t3 = line_data[j + 2];
211                 line_data[j + 2] = t1;
212                 line_data[j + 1] = t2;
213                 line_data[j + 0] = t3;
214             }
215             break;
216         case 32:
217             for (j = 0; j + 4 <= stride; j += 4)
218             {
219                 char t1 = line_data[j + 0];
220                 char t2 = line_data[j + 1];
221                 char t3 = line_data[j + 2];
222                 char t4 = line_data[j + 3];
223                 line_data[j + 3] = t1;
224                 line_data[j + 2] = t2;
225                 line_data[j + 1] = t3;
226                 line_data[j + 0] = t4;
227             }
228             break;
229         default:
230             break;
231         }
232     }
233 }
234
235 /* Create random image for testing purposes */
236 static pixman_image_t *
237 create_random_image (
238         pixman_format_code_t *allowed_formats,
239         int max_width,
240         int max_height,
241         int max_extra_stride,
242         pixman_format_code_t *used_fmt)
243 {
244     int n = 0, i, width, height, stride;
245     pixman_format_code_t fmt;
246     uint32_t *buf;
247     pixman_image_t *img;
248     while (allowed_formats[n] != -1) n++;
249     fmt = allowed_formats[lcg_rand_n (n)];
250     width = lcg_rand_n (max_width) + 1;
251     height = lcg_rand_n (max_height) + 1;
252     stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + lcg_rand_n (max_extra_stride + 1);
253     stride = (stride + 3) & ~3;
254
255     /* do the allocation */
256     buf = (uint32_t *)memalign (64, stride * height);
257
258     /* initialize image with random data */
259     for (i = 0; i < stride * height; i++)
260     {
261         /* generation is biased to having more 0 or 255 bytes as
262            they are more likely to be special-cased in code */
263         *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) :
264             (lcg_rand_n (2) ? 0 : 255);
265     }
266
267     img = pixman_image_create_bits (
268         fmt, width, height, buf, stride);
269
270     image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
271
272     if (used_fmt) *used_fmt = fmt;
273     return img;
274 }
275
276 /* Free random image, and optionally update crc32 based on its data */
277 static uint32_t
278 free_random_image (
279     uint32_t initcrc,
280     pixman_image_t *img,
281     pixman_format_code_t fmt)
282 {
283     uint32_t crc32 = 0;
284     int stride = pixman_image_get_stride (img);
285     uint32_t *data = pixman_image_get_data (img);
286     int height = pixman_image_get_height (img);;
287
288     if (fmt != -1)
289     {
290         /* mask unused 'x' part */
291         if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
292             PIXMAN_FORMAT_DEPTH (fmt) != 0)
293         {
294             int i;
295             uint32_t *data = pixman_image_get_data (img);
296             uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
297             for (i = 0; i < 32; i++)
298                 mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
299
300             for (i = 0; i < stride * height / 4; i++)
301                 data[i] &= mask;
302         }
303         /* swap endiannes in order to provide identical results on both big
304            and litte endian systems */
305         image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt));
306         crc32 = compute_crc32 (initcrc, data, stride * height);
307     }
308     pixman_image_unref (img);
309     free (data);
310     return crc32;
311 }
312
313 static pixman_op_t op_list[] = {
314     PIXMAN_OP_SRC,
315     PIXMAN_OP_OVER,
316     PIXMAN_OP_ADD,
317     PIXMAN_OP_CLEAR,
318     PIXMAN_OP_SRC,
319     PIXMAN_OP_DST,
320     PIXMAN_OP_OVER,
321     PIXMAN_OP_OVER_REVERSE,
322     PIXMAN_OP_IN,
323     PIXMAN_OP_IN_REVERSE,
324     PIXMAN_OP_OUT,
325     PIXMAN_OP_OUT_REVERSE,
326     PIXMAN_OP_ATOP,
327     PIXMAN_OP_ATOP_REVERSE,
328     PIXMAN_OP_XOR,
329     PIXMAN_OP_ADD,
330     PIXMAN_OP_SATURATE,
331     PIXMAN_OP_DISJOINT_CLEAR,
332     PIXMAN_OP_DISJOINT_SRC,
333     PIXMAN_OP_DISJOINT_DST,
334     PIXMAN_OP_DISJOINT_OVER,
335     PIXMAN_OP_DISJOINT_OVER_REVERSE,
336     PIXMAN_OP_DISJOINT_IN,
337     PIXMAN_OP_DISJOINT_IN_REVERSE,
338     PIXMAN_OP_DISJOINT_OUT,
339     PIXMAN_OP_DISJOINT_OUT_REVERSE,
340     PIXMAN_OP_DISJOINT_ATOP,
341     PIXMAN_OP_DISJOINT_ATOP_REVERSE,
342     PIXMAN_OP_DISJOINT_XOR,
343     PIXMAN_OP_CONJOINT_CLEAR,
344     PIXMAN_OP_CONJOINT_SRC,
345     PIXMAN_OP_CONJOINT_DST,
346     PIXMAN_OP_CONJOINT_OVER,
347     PIXMAN_OP_CONJOINT_OVER_REVERSE,
348     PIXMAN_OP_CONJOINT_IN,
349     PIXMAN_OP_CONJOINT_IN_REVERSE,
350     PIXMAN_OP_CONJOINT_OUT,
351     PIXMAN_OP_CONJOINT_OUT_REVERSE,
352     PIXMAN_OP_CONJOINT_ATOP,
353     PIXMAN_OP_CONJOINT_ATOP_REVERSE,
354     PIXMAN_OP_CONJOINT_XOR,
355     PIXMAN_OP_MULTIPLY,
356     PIXMAN_OP_SCREEN,
357     PIXMAN_OP_OVERLAY,
358     PIXMAN_OP_DARKEN,
359     PIXMAN_OP_LIGHTEN,
360     PIXMAN_OP_COLOR_DODGE,
361     PIXMAN_OP_COLOR_BURN,
362     PIXMAN_OP_HARD_LIGHT,
363     PIXMAN_OP_DIFFERENCE,
364     PIXMAN_OP_EXCLUSION,
365 #if 0 /* these use floating point math and are not always bitexact on different platforms */
366     PIXMAN_OP_SOFT_LIGHT,
367     PIXMAN_OP_HSL_HUE,
368     PIXMAN_OP_HSL_SATURATION,
369     PIXMAN_OP_HSL_COLOR,
370     PIXMAN_OP_HSL_LUMINOSITY,
371 #endif
372 };
373 static pixman_format_code_t img_fmt_list[] = {
374     PIXMAN_a8r8g8b8,
375     PIXMAN_x8r8g8b8,
376     PIXMAN_r5g6b5,
377     PIXMAN_r3g3b2,
378     PIXMAN_a8,
379     PIXMAN_a8b8g8r8,
380     PIXMAN_x8b8g8r8,
381     PIXMAN_b8g8r8a8,
382     PIXMAN_b8g8r8x8,
383     PIXMAN_r8g8b8,
384     PIXMAN_b8g8r8,
385     PIXMAN_r5g6b5,
386     PIXMAN_b5g6r5,
387     PIXMAN_x2r10g10b10,
388     PIXMAN_a2r10g10b10,
389     PIXMAN_x2b10g10r10,
390     PIXMAN_a2b10g10r10,
391     PIXMAN_a1r5g5b5,
392     PIXMAN_x1r5g5b5,
393     PIXMAN_a1b5g5r5,
394     PIXMAN_x1b5g5r5,
395     PIXMAN_a4r4g4b4,
396     PIXMAN_x4r4g4b4,
397     PIXMAN_a4b4g4r4,
398     PIXMAN_x4b4g4r4,
399     PIXMAN_a8,
400     PIXMAN_r3g3b2,
401     PIXMAN_b2g3r3,
402     PIXMAN_a2r2g2b2,
403     PIXMAN_a2b2g2r2,
404 #if 0 /* using these crashes the test */
405     PIXMAN_c8,
406     PIXMAN_g8,
407     PIXMAN_x4c4,
408     PIXMAN_x4g4,
409     PIXMAN_c4,
410     PIXMAN_g4,
411     PIXMAN_g1,
412 #endif
413     PIXMAN_x4a4,
414     PIXMAN_a4,
415     PIXMAN_r1g2b1,
416     PIXMAN_b1g2r1,
417     PIXMAN_a1r1g1b1,
418     PIXMAN_a1b1g1r1,
419     PIXMAN_a1,
420     -1
421 };
422 static pixman_format_code_t mask_fmt_list[] = {
423     PIXMAN_a8r8g8b8,
424     PIXMAN_a8,
425     PIXMAN_a4,
426     PIXMAN_a1,
427     -1
428 };
429
430
431 /*
432  * Composite operation with pseudorandom images
433  */
434 uint32_t
435 test_composite (uint32_t initcrc, int testnum, int verbose)
436 {
437     int i;
438     pixman_image_t *src_img = NULL;
439     pixman_image_t *dst_img = NULL;
440     pixman_image_t *mask_img = NULL;
441     int src_width, src_height;
442     int dst_width, dst_height;
443     int src_stride, dst_stride;
444     int src_x, src_y;
445     int dst_x, dst_y;
446     int w, h;
447     int op;
448     pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
449     uint32_t *dstbuf;
450     uint32_t crc32;
451     int max_width, max_height, max_extra_stride;
452
453     max_width = max_height = 24 + testnum / 10000;
454     max_extra_stride = 4 + testnum / 1000000;
455     if (max_width > 256) max_width = 256;
456     if (max_height > 16) max_height = 16;
457     if (max_extra_stride > 8) max_extra_stride = 8;
458
459     lcg_srand (testnum);
460
461     op = op_list[lcg_rand_n (sizeof (op_list) / sizeof (op_list[0]))];
462
463     if (lcg_rand_n (8))
464     {
465         /* normal image */
466         src_img = create_random_image (img_fmt_list, max_width, max_height,
467                                       max_extra_stride, &src_fmt);
468     }
469     else
470     {
471         /* solid case */
472         src_img = create_random_image (img_fmt_list, 1, 1,
473                                       max_extra_stride, &src_fmt);
474         pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
475     }
476
477     dst_img = create_random_image (img_fmt_list, max_width, max_height,
478                                   max_extra_stride, &dst_fmt);
479
480     mask_img = NULL;
481     mask_fmt = -1;
482     if (lcg_rand_n (2))
483     {
484         if (lcg_rand_n (2))
485         {
486             mask_img = create_random_image (mask_fmt_list, max_width, max_height,
487                                            max_extra_stride, &mask_fmt);
488         }
489         else
490         {
491             /* solid case */
492             mask_img = create_random_image (mask_fmt_list, 1, 1,
493                                            max_extra_stride, &mask_fmt);
494             pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
495         }
496         if (lcg_rand_n (2))
497             pixman_image_set_component_alpha (mask_img, 1);
498     }
499
500     src_width = pixman_image_get_width (src_img);
501     src_height = pixman_image_get_height (src_img);
502     src_stride = pixman_image_get_stride (src_img);
503     dst_width = pixman_image_get_width (dst_img);
504     dst_height = pixman_image_get_height (dst_img);
505     dst_stride = pixman_image_get_stride (dst_img);
506     dstbuf = pixman_image_get_data (dst_img);
507
508     src_x = lcg_rand_n (src_width);
509     src_y = lcg_rand_n (src_height);
510     dst_x = lcg_rand_n (dst_width);
511     dst_y = lcg_rand_n (dst_height);
512     w = lcg_rand_n (dst_width - dst_x + 1);
513     h = lcg_rand_n (dst_height - dst_y + 1);
514
515     if (verbose)
516     {
517         printf ("op=%d, src_fmt=%08X, dst_fmt=%08X, mask_fmt=%08X\n",
518             op, src_fmt, dst_fmt, mask_fmt);
519         printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
520             src_width, src_height, dst_width, dst_height);
521         printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
522             src_x, src_y, dst_x, dst_y);
523         printf ("src_stride=%d, dst_stride=%d\n",
524             src_stride, dst_stride);
525         printf ("w=%d, h=%d\n", w, h);
526     }
527
528     pixman_image_composite (op, src_img, mask_img, dst_img,
529                             src_x, src_y, src_x, src_y, dst_x, dst_y, w, h);
530
531     if (verbose)
532     {
533         int j;
534         printf ("---\n");
535         for (i = 0; i < dst_height; i++)
536         {
537             for (j = 0; j < dst_stride; j++)
538             {
539                 if (j == (dst_width * PIXMAN_FORMAT_BPP (dst_fmt) + 7) / 8)
540                     printf ("| ");
541                 printf ("%02X ", *((uint8_t *)dstbuf + i * dst_stride + j));
542             }
543             printf ("\n");
544         }
545         printf ("---\n");
546     }
547
548     free_random_image (initcrc, src_img, -1);
549     crc32 = free_random_image (initcrc, dst_img, dst_fmt);
550     if (mask_img) free_random_image (initcrc, mask_img, -1);
551     return crc32;
552 }
553
554 int
555 main (int argc, char *argv[])
556 {
557     int i, n1 = 1, n2 = 0;
558     uint32_t crc = 0;
559
560     if (argc >= 3)
561     {
562         n1 = atoi (argv[1]);
563         n2 = atoi (argv[2]);
564     }
565     else if (argc >= 2)
566     {
567         n2 = atoi (argv[1]);
568     }
569     else
570     {
571         n1 = 1;
572         n2 = 2000000;
573     }
574
575     if (n2 < 0)
576     {
577         crc = test_composite (0, abs (n2), 1);
578         printf ("crc32=%08X\n", crc);
579     }
580     else
581     {
582         for (i = n1; i <= n2; i++)
583         {
584             crc = test_composite (crc, i, 0);
585         }
586         printf ("crc32=%08X\n", crc);
587
588         if (n2 == 2000000)
589         {
590             /* Predefined value for running with all the fastpath functions
591                disabled. It needs to be updated every time when changes are
592                introduced to this program or behavior of pixman changes! */
593             if (crc == 0x4895C7B0)
594             {
595                 printf ("blitters test passed\n");
596             }
597             else
598             {
599                 printf ("blitters test failed!\n");
600                 return 1;
601             }
602         }
603     }
604     return 0;
605 }