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