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