16ba797d6Smrg#include <stdio.h>
29ad247e8Sjmcneill#include <stdlib.h>
3953d7d37Smrg#include "utils.h"
46ba797d6Smrg#include <sys/types.h>
5953d7d37Smrg
6953d7d37Smrg#if 0
7953d7d37Smrg#define fence_malloc malloc
8953d7d37Smrg#define fence_free free
9953d7d37Smrg#define make_random_bytes malloc
10953d7d37Smrg#endif
11953d7d37Smrg
12953d7d37Smrgstatic const pixman_format_code_t image_formats[] =
13953d7d37Smrg{
144f2886e8Smrg    PIXMAN_rgba_float,
154f2886e8Smrg    PIXMAN_rgb_float,
1614b11b2bSmrg    PIXMAN_a16b16g16r16,
17953d7d37Smrg    PIXMAN_a8r8g8b8,
18953d7d37Smrg    PIXMAN_x8r8g8b8,
19953d7d37Smrg    PIXMAN_r5g6b5,
20953d7d37Smrg    PIXMAN_r3g3b2,
21953d7d37Smrg    PIXMAN_a8,
22953d7d37Smrg    PIXMAN_a8b8g8r8,
23953d7d37Smrg    PIXMAN_x8b8g8r8,
24953d7d37Smrg    PIXMAN_b8g8r8a8,
25953d7d37Smrg    PIXMAN_b8g8r8x8,
266ba797d6Smrg    PIXMAN_r8g8b8a8,
276ba797d6Smrg    PIXMAN_r8g8b8x8,
28953d7d37Smrg    PIXMAN_x14r6g6b6,
29953d7d37Smrg    PIXMAN_r8g8b8,
30953d7d37Smrg    PIXMAN_b8g8r8,
319ad247e8Sjmcneill    PIXMAN_a8r8g8b8_sRGB,
3214b11b2bSmrg    PIXMAN_r8g8b8_sRGB,
33953d7d37Smrg    PIXMAN_r5g6b5,
34953d7d37Smrg    PIXMAN_b5g6r5,
35953d7d37Smrg    PIXMAN_x2r10g10b10,
36953d7d37Smrg    PIXMAN_a2r10g10b10,
37953d7d37Smrg    PIXMAN_x2b10g10r10,
38953d7d37Smrg    PIXMAN_a2b10g10r10,
39953d7d37Smrg    PIXMAN_a1r5g5b5,
40953d7d37Smrg    PIXMAN_x1r5g5b5,
41953d7d37Smrg    PIXMAN_a1b5g5r5,
42953d7d37Smrg    PIXMAN_x1b5g5r5,
43953d7d37Smrg    PIXMAN_a4r4g4b4,
44953d7d37Smrg    PIXMAN_x4r4g4b4,
45953d7d37Smrg    PIXMAN_a4b4g4r4,
46953d7d37Smrg    PIXMAN_x4b4g4r4,
47953d7d37Smrg    PIXMAN_a8,
48953d7d37Smrg    PIXMAN_r3g3b2,
49953d7d37Smrg    PIXMAN_b2g3r3,
50953d7d37Smrg    PIXMAN_a2r2g2b2,
51953d7d37Smrg    PIXMAN_a2b2g2r2,
52953d7d37Smrg    PIXMAN_c8,
53953d7d37Smrg    PIXMAN_g8,
54953d7d37Smrg    PIXMAN_x4c4,
55953d7d37Smrg    PIXMAN_x4g4,
56953d7d37Smrg    PIXMAN_c4,
57953d7d37Smrg    PIXMAN_g4,
58953d7d37Smrg    PIXMAN_g1,
59953d7d37Smrg    PIXMAN_x4a4,
60953d7d37Smrg    PIXMAN_a4,
61953d7d37Smrg    PIXMAN_r1g2b1,
62953d7d37Smrg    PIXMAN_b1g2r1,
63953d7d37Smrg    PIXMAN_a1r1g1b1,
64953d7d37Smrg    PIXMAN_a1b1g1r1,
65953d7d37Smrg    PIXMAN_a1
66953d7d37Smrg};
67953d7d37Smrg
68953d7d37Smrgstatic pixman_filter_t filters[] =
69953d7d37Smrg{
70953d7d37Smrg    PIXMAN_FILTER_NEAREST,
71953d7d37Smrg    PIXMAN_FILTER_BILINEAR,
72953d7d37Smrg    PIXMAN_FILTER_FAST,
73953d7d37Smrg    PIXMAN_FILTER_GOOD,
74953d7d37Smrg    PIXMAN_FILTER_BEST,
75953d7d37Smrg    PIXMAN_FILTER_CONVOLUTION
76953d7d37Smrg};
77953d7d37Smrg
78953d7d37Smrgstatic int
79953d7d37Smrgget_size (void)
80953d7d37Smrg{
81f4f78bb6Smrg    switch (prng_rand_n (28))
82953d7d37Smrg    {
83953d7d37Smrg    case 0:
84953d7d37Smrg	return 1;
85953d7d37Smrg
86953d7d37Smrg    case 1:
87953d7d37Smrg	return 2;
88953d7d37Smrg
89953d7d37Smrg    default:
90953d7d37Smrg    case 2:
91f4f78bb6Smrg	return prng_rand_n (100);
92953d7d37Smrg
93953d7d37Smrg    case 4:
94f4f78bb6Smrg	return prng_rand_n (2000) + 1000;
95953d7d37Smrg
96953d7d37Smrg    case 5:
97953d7d37Smrg	return 65535;
98953d7d37Smrg
99953d7d37Smrg    case 6:
100953d7d37Smrg	return 65536;
101953d7d37Smrg
102953d7d37Smrg    case 7:
103f4f78bb6Smrg	return prng_rand_n (64000) + 63000;
104953d7d37Smrg    }
105953d7d37Smrg}
106953d7d37Smrg
1074f2886e8Smrgstatic uint32_t
1084f2886e8Smrgreal_reader (const void *src, int size);
1094f2886e8Smrg
1104f2886e8Smrgstatic void *xor_ptr(const void *ptr)
1114f2886e8Smrg{
1124f2886e8Smrg	return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000);
1134f2886e8Smrg}
1144f2886e8Smrg
115953d7d37Smrgstatic void
116953d7d37Smrgdestroy (pixman_image_t *image, void *data)
117953d7d37Smrg{
118953d7d37Smrg    if (image->type == BITS && image->bits.free_me != image->bits.bits)
119953d7d37Smrg    {
120953d7d37Smrg	uint32_t *bits;
121953d7d37Smrg
122953d7d37Smrg	if (image->bits.bits != (void *)0x01)
123953d7d37Smrg	{
124953d7d37Smrg	    bits = image->bits.bits;
125953d7d37Smrg
126953d7d37Smrg	    if (image->bits.rowstride < 0)
127953d7d37Smrg		bits -= (- image->bits.rowstride * (image->bits.height - 1));
128953d7d37Smrg
1294f2886e8Smrg	    if (image->bits.read_func == real_reader)
1304f2886e8Smrg		bits = xor_ptr(bits);
1314f2886e8Smrg
132953d7d37Smrg	    fence_free (bits);
133953d7d37Smrg	}
134953d7d37Smrg    }
135953d7d37Smrg
136953d7d37Smrg    free (data);
137953d7d37Smrg}
138953d7d37Smrg
139953d7d37Smrgstatic uint32_t
140953d7d37Smrgreal_reader (const void *src, int size)
141953d7d37Smrg{
1424f2886e8Smrg    src = xor_ptr(src);
143953d7d37Smrg    switch (size)
144953d7d37Smrg    {
145953d7d37Smrg    case 1:
146953d7d37Smrg	return *(uint8_t *)src;
147953d7d37Smrg    case 2:
148953d7d37Smrg	return *(uint16_t *)src;
149953d7d37Smrg    case 4:
150953d7d37Smrg	return *(uint32_t *)src;
151953d7d37Smrg    default:
152953d7d37Smrg	assert (0);
1536ba797d6Smrg	return 0; /* silence MSVC */
154953d7d37Smrg    }
155953d7d37Smrg}
156953d7d37Smrg
157953d7d37Smrgstatic void
158953d7d37Smrgreal_writer (void *src, uint32_t value, int size)
159953d7d37Smrg{
1604f2886e8Smrg    src = xor_ptr(src);
161953d7d37Smrg    switch (size)
162953d7d37Smrg    {
163953d7d37Smrg    case 1:
164953d7d37Smrg	*(uint8_t *)src = value;
165953d7d37Smrg	break;
166953d7d37Smrg
167953d7d37Smrg    case 2:
168953d7d37Smrg	*(uint16_t *)src = value;
169953d7d37Smrg	break;
170953d7d37Smrg
171953d7d37Smrg    case 4:
172953d7d37Smrg	*(uint32_t *)src = value;
173953d7d37Smrg	break;
174953d7d37Smrg
175953d7d37Smrg    default:
176953d7d37Smrg	assert (0);
177953d7d37Smrg	break;
178953d7d37Smrg    }
179953d7d37Smrg}
180953d7d37Smrg
181953d7d37Smrgstatic uint32_t
182953d7d37Smrgfake_reader (const void *src, int size)
183953d7d37Smrg{
184f4f78bb6Smrg    uint32_t r = prng_rand ();
185953d7d37Smrg
186953d7d37Smrg    assert (size == 1 || size == 2 || size == 4);
1879ad247e8Sjmcneill
1889ad247e8Sjmcneill    return r >> (32 - (size * 8));
189953d7d37Smrg}
190953d7d37Smrg
191953d7d37Smrgstatic void
192953d7d37Smrgfake_writer (void *src, uint32_t value, int size)
193953d7d37Smrg{
194953d7d37Smrg    assert (size == 1 || size == 2 || size == 4);
195953d7d37Smrg}
196953d7d37Smrg
197953d7d37Smrgstatic int32_t
198953d7d37Smrglog_rand (void)
199953d7d37Smrg{
200953d7d37Smrg    uint32_t mask;
201953d7d37Smrg
202f4f78bb6Smrg    mask = (1 << prng_rand_n (10)) - 1;
2039ad247e8Sjmcneill
204f4f78bb6Smrg    return (prng_rand () & mask) - (mask >> 1);
2059ad247e8Sjmcneill}
206953d7d37Smrg
2079ad247e8Sjmcneillstatic int32_t
2089ad247e8Sjmcneillrand_x (pixman_image_t *image)
2099ad247e8Sjmcneill{
2109ad247e8Sjmcneill    if (image->type == BITS)
211f4f78bb6Smrg	return prng_rand_n (image->bits.width);
2129ad247e8Sjmcneill    else
2139ad247e8Sjmcneill	return log_rand ();
2149ad247e8Sjmcneill}
2159ad247e8Sjmcneill
2169ad247e8Sjmcneillstatic int32_t
2179ad247e8Sjmcneillrand_y (pixman_image_t *image)
2189ad247e8Sjmcneill{
2199ad247e8Sjmcneill    if (image->type == BITS)
220f4f78bb6Smrg	return prng_rand_n (image->bits.height);
2219ad247e8Sjmcneill    else
2229ad247e8Sjmcneill	return log_rand ();
223953d7d37Smrg}
224953d7d37Smrg
225f4f78bb6Smrgtypedef enum
226f4f78bb6Smrg{
227f4f78bb6Smrg    DONT_CARE,
228f4f78bb6Smrg    PREFER_ALPHA,
229f4f78bb6Smrg    REQUIRE_ALPHA
230f4f78bb6Smrg} alpha_preference_t;
231f4f78bb6Smrg
232f4f78bb6Smrgstatic pixman_format_code_t
233f4f78bb6Smrgrandom_format (alpha_preference_t alpha)
234f4f78bb6Smrg{
235f4f78bb6Smrg    pixman_format_code_t format;
236f4f78bb6Smrg    int n = prng_rand_n (ARRAY_LENGTH (image_formats));
237f4f78bb6Smrg
238f4f78bb6Smrg    if (alpha >= PREFER_ALPHA &&
239f4f78bb6Smrg	(alpha == REQUIRE_ALPHA || prng_rand_n (4) != 0))
240f4f78bb6Smrg    {
241f4f78bb6Smrg        do
242f4f78bb6Smrg        {
243f4f78bb6Smrg            format = image_formats[n++ % ARRAY_LENGTH (image_formats)];
244f4f78bb6Smrg        } while (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_A);
245f4f78bb6Smrg    }
246f4f78bb6Smrg    else
247f4f78bb6Smrg    {
248f4f78bb6Smrg        format = image_formats[n];
249f4f78bb6Smrg    }
250f4f78bb6Smrg
251f4f78bb6Smrg    return format;
252f4f78bb6Smrg}
253f4f78bb6Smrg
254953d7d37Smrgstatic pixman_image_t *
255f4f78bb6Smrgcreate_random_bits_image (alpha_preference_t alpha_preference)
256953d7d37Smrg{
257953d7d37Smrg    pixman_format_code_t format;
258953d7d37Smrg    pixman_indexed_t *indexed;
259953d7d37Smrg    pixman_image_t *image;
260953d7d37Smrg    int width, height, stride;
261953d7d37Smrg    uint32_t *bits;
262953d7d37Smrg    pixman_read_memory_func_t read_func = NULL;
263953d7d37Smrg    pixman_write_memory_func_t write_func = NULL;
264953d7d37Smrg    pixman_filter_t filter;
265953d7d37Smrg    pixman_fixed_t *coefficients = NULL;
266953d7d37Smrg    int n_coefficients = 0;
2674f2886e8Smrg    int align_add, align_mask;
268953d7d37Smrg
269953d7d37Smrg    /* format */
270f4f78bb6Smrg    format = random_format (alpha_preference);
2714f2886e8Smrg    switch (PIXMAN_FORMAT_BPP (format)) {
2724f2886e8Smrg    case 128:
2734f2886e8Smrg	align_mask = 15;
2744f2886e8Smrg	align_add = align_mask + prng_rand_n (65);
2754f2886e8Smrg	break;
2764f2886e8Smrg    default:
2774f2886e8Smrg	align_mask = 3;
2784f2886e8Smrg	align_add = align_mask + prng_rand_n (17);
2794f2886e8Smrg	break;
2804f2886e8Smrg    }
281953d7d37Smrg
282953d7d37Smrg    indexed = NULL;
283953d7d37Smrg    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
284953d7d37Smrg    {
285953d7d37Smrg	indexed = malloc (sizeof (pixman_indexed_t));
286953d7d37Smrg
287953d7d37Smrg	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE);
288953d7d37Smrg    }
289953d7d37Smrg    else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
290953d7d37Smrg    {
291953d7d37Smrg	indexed = malloc (sizeof (pixman_indexed_t));
292953d7d37Smrg
293953d7d37Smrg	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE);
294953d7d37Smrg    }
295953d7d37Smrg    else
296953d7d37Smrg    {
297953d7d37Smrg	indexed = NULL;
298953d7d37Smrg    }
299953d7d37Smrg
300953d7d37Smrg    /* size */
301953d7d37Smrg    width = get_size ();
302953d7d37Smrg    height = get_size ();
303953d7d37Smrg
3049ad247e8Sjmcneill    while ((uint64_t)width * height > 200000)
305953d7d37Smrg    {
306f4f78bb6Smrg	if (prng_rand_n(2) == 0)
307953d7d37Smrg	    height = 200000 / width;
308953d7d37Smrg	else
309953d7d37Smrg	    width = 200000 / height;
310953d7d37Smrg    }
311953d7d37Smrg
312953d7d37Smrg    if (height == 0)
313953d7d37Smrg	height = 1;
314953d7d37Smrg    if (width == 0)
315953d7d37Smrg	width = 1;
316953d7d37Smrg
317953d7d37Smrg    /* bits */
318f4f78bb6Smrg    switch (prng_rand_n (7))
319953d7d37Smrg    {
320953d7d37Smrg    default:
321953d7d37Smrg    case 0:
3224f2886e8Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
3234f2886e8Smrg	stride = (stride + align_add) & (~align_mask);
3244f2886e8Smrg	if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
3254f2886e8Smrg	    bits = (uint32_t *)make_random_floats (height * stride);
3264f2886e8Smrg	else
3274f2886e8Smrg	    bits = (uint32_t *)make_random_bytes (height * stride);
328953d7d37Smrg	break;
329953d7d37Smrg
330953d7d37Smrg    case 1:
331953d7d37Smrg	stride = 0;
332953d7d37Smrg	bits = NULL;
333953d7d37Smrg	break;
334953d7d37Smrg
335953d7d37Smrg    case 2: /* Zero-filled */
3364f2886e8Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
3374f2886e8Smrg	stride = (stride + align_add) & (~align_mask);
338953d7d37Smrg	bits = fence_malloc (height * stride);
339953d7d37Smrg	if (!bits)
340953d7d37Smrg	    return NULL;
341953d7d37Smrg	memset (bits, 0, height * stride);
342953d7d37Smrg	break;
343953d7d37Smrg
344953d7d37Smrg    case 3: /* Filled with 0xFF */
3454f2886e8Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
3464f2886e8Smrg	stride = (stride + align_add) & (~align_mask);
347953d7d37Smrg	bits = fence_malloc (height * stride);
348953d7d37Smrg	if (!bits)
349953d7d37Smrg	    return NULL;
350953d7d37Smrg	memset (bits, 0xff, height * stride);
351953d7d37Smrg	break;
352953d7d37Smrg
353953d7d37Smrg    case 4: /* bits is a bad pointer, has read/write functions */
3544f2886e8Smrg	if (PIXMAN_FORMAT_BPP (format) <= 32) {
3554f2886e8Smrg	    stride = 232;
3564f2886e8Smrg	    bits = (void *)0x01;
3574f2886e8Smrg	    read_func = fake_reader;
3584f2886e8Smrg	    write_func = fake_writer;
3594f2886e8Smrg	    break;
3604f2886e8Smrg	}
361953d7d37Smrg
362953d7d37Smrg    case 5: /* bits is a real pointer, has read/write functions */
3634f2886e8Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
3644f2886e8Smrg	stride = (stride + align_add) & (~align_mask);
365953d7d37Smrg	bits = fence_malloc (height * stride);
366953d7d37Smrg	if (!bits)
367953d7d37Smrg	    return NULL;
368953d7d37Smrg	memset (bits, 0xff, height * stride);
3694f2886e8Smrg	if (PIXMAN_FORMAT_BPP (format) <= 32) {
3704f2886e8Smrg	    bits = xor_ptr(bits);
3714f2886e8Smrg	    read_func = real_reader;
3724f2886e8Smrg	    write_func = real_writer;
3734f2886e8Smrg	}
374953d7d37Smrg	break;
375953d7d37Smrg
376953d7d37Smrg    case 6: /* bits is a real pointer, stride is negative */
3774f2886e8Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
3784f2886e8Smrg	stride = (stride + align_add) & (~align_mask);
3794f2886e8Smrg	if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
3804f2886e8Smrg	    bits = (uint32_t *)make_random_floats (height * stride);
3814f2886e8Smrg	else
3824f2886e8Smrg	    bits = (uint32_t *)make_random_bytes (height * stride);
383953d7d37Smrg	if (!bits)
384953d7d37Smrg	    return NULL;
385953d7d37Smrg	bits += ((height - 1) * stride) / 4;
386953d7d37Smrg	stride = - stride;
387953d7d37Smrg	break;
388953d7d37Smrg    }
389953d7d37Smrg
390953d7d37Smrg    /* Filter */
391f4f78bb6Smrg    filter = filters[prng_rand_n (ARRAY_LENGTH (filters))];
392953d7d37Smrg    if (filter == PIXMAN_FILTER_CONVOLUTION)
393953d7d37Smrg    {
394f4f78bb6Smrg	int width = prng_rand_n (3);
395f4f78bb6Smrg	int height = prng_rand_n (4);
396953d7d37Smrg
397953d7d37Smrg	n_coefficients = width * height + 2;
398953d7d37Smrg	coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t));
399953d7d37Smrg
400953d7d37Smrg	if (coefficients)
401953d7d37Smrg	{
402953d7d37Smrg	    int i;
403953d7d37Smrg
404953d7d37Smrg	    for (i = 0; i < width * height; ++i)
405f4f78bb6Smrg		coefficients[i + 2] = prng_rand();
406953d7d37Smrg
407953d7d37Smrg	    coefficients[0] = width << 16;
408953d7d37Smrg	    coefficients[1] = height << 16;
409953d7d37Smrg	}
410953d7d37Smrg	else
411953d7d37Smrg	{
412953d7d37Smrg	    filter = PIXMAN_FILTER_BEST;
413953d7d37Smrg	}
414953d7d37Smrg    }
415953d7d37Smrg
416953d7d37Smrg    /* Finally create the image */
417953d7d37Smrg    image = pixman_image_create_bits (format, width, height, bits, stride);
418953d7d37Smrg    if (!image)
419953d7d37Smrg	return NULL;
420953d7d37Smrg
421953d7d37Smrg    pixman_image_set_indexed (image, indexed);
422953d7d37Smrg    pixman_image_set_destroy_function (image, destroy, indexed);
423953d7d37Smrg    pixman_image_set_accessors (image, read_func, write_func);
424953d7d37Smrg    pixman_image_set_filter (image, filter, coefficients, n_coefficients);
425953d7d37Smrg
42614b11b2bSmrg    free (coefficients);
42714b11b2bSmrg
428953d7d37Smrg    return image;
429953d7d37Smrg}
430953d7d37Smrg
431953d7d37Smrgstatic pixman_repeat_t repeats[] =
432953d7d37Smrg{
433953d7d37Smrg    PIXMAN_REPEAT_NONE,
434953d7d37Smrg    PIXMAN_REPEAT_NORMAL,
435953d7d37Smrg    PIXMAN_REPEAT_REFLECT,
436953d7d37Smrg    PIXMAN_REPEAT_PAD
437953d7d37Smrg};
438953d7d37Smrg
439953d7d37Smrgstatic uint32_t
440953d7d37Smrgabsolute (int32_t i)
441953d7d37Smrg{
442953d7d37Smrg    return i < 0? -i : i;
443953d7d37Smrg}
444953d7d37Smrg
445953d7d37Smrgstatic void
446953d7d37Smrgset_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
447953d7d37Smrg{
448953d7d37Smrg    pixman_repeat_t repeat;
449953d7d37Smrg
450953d7d37Smrg    /* Set properties that are generic to all images */
451953d7d37Smrg
452953d7d37Smrg    /* Repeat */
453f4f78bb6Smrg    repeat = repeats[prng_rand_n (ARRAY_LENGTH (repeats))];
454953d7d37Smrg    pixman_image_set_repeat (image, repeat);
455953d7d37Smrg
456953d7d37Smrg    /* Alpha map */
457f4f78bb6Smrg    if (allow_alpha_map && prng_rand_n (4) == 0)
458953d7d37Smrg    {
459953d7d37Smrg	pixman_image_t *alpha_map;
460953d7d37Smrg	int16_t x, y;
461953d7d37Smrg
462f4f78bb6Smrg	alpha_map = create_random_bits_image (DONT_CARE);
463953d7d37Smrg
464953d7d37Smrg	if (alpha_map)
465953d7d37Smrg	{
466953d7d37Smrg	    set_general_properties (alpha_map, FALSE);
467953d7d37Smrg
4689ad247e8Sjmcneill	    x = rand_x (image) - image->bits.width / 2;
4699ad247e8Sjmcneill	    y = rand_y (image) - image->bits.height / 2;
470953d7d37Smrg
471953d7d37Smrg	    pixman_image_set_alpha_map (image, alpha_map, x, y);
472953d7d37Smrg
473953d7d37Smrg	    pixman_image_unref (alpha_map);
474953d7d37Smrg	}
475953d7d37Smrg    }
476953d7d37Smrg
477953d7d37Smrg    /* Component alpha */
478f4f78bb6Smrg    pixman_image_set_component_alpha (image, prng_rand_n (3) == 0);
479953d7d37Smrg
480953d7d37Smrg    /* Clip region */
481f4f78bb6Smrg    if (prng_rand_n (8) < 2)
482953d7d37Smrg    {
483953d7d37Smrg	pixman_region32_t region;
484953d7d37Smrg	int i, n_rects;
485953d7d37Smrg
486953d7d37Smrg	pixman_region32_init (&region);
487953d7d37Smrg
488f4f78bb6Smrg	switch (prng_rand_n (12))
489953d7d37Smrg	{
490953d7d37Smrg	case 0:
491953d7d37Smrg	    n_rects = 0;
492953d7d37Smrg	    break;
493953d7d37Smrg
494953d7d37Smrg	case 1: case 2: case 3:
495953d7d37Smrg	    n_rects = 1;
496953d7d37Smrg	    break;
497953d7d37Smrg
498953d7d37Smrg	case 4: case 5:
499953d7d37Smrg	    n_rects = 2;
500953d7d37Smrg	    break;
501953d7d37Smrg
502953d7d37Smrg	case 6: case 7:
503953d7d37Smrg	    n_rects = 3;
5049ad247e8Sjmcneill	    break;
505953d7d37Smrg
506953d7d37Smrg	default:
507f4f78bb6Smrg	    n_rects = prng_rand_n (100);
508953d7d37Smrg	    break;
509953d7d37Smrg	}
510953d7d37Smrg
511953d7d37Smrg	for (i = 0; i < n_rects; ++i)
512953d7d37Smrg	{
513953d7d37Smrg	    uint32_t width, height;
514953d7d37Smrg	    int x, y;
515953d7d37Smrg
516953d7d37Smrg	    x = log_rand();
517953d7d37Smrg	    y = log_rand();
518953d7d37Smrg	    width = absolute (log_rand ()) + 1;
519953d7d37Smrg	    height = absolute (log_rand ()) + 1;
520953d7d37Smrg
521953d7d37Smrg	    pixman_region32_union_rect (
522953d7d37Smrg		&region, &region, x, y, width, height);
523953d7d37Smrg	}
524953d7d37Smrg
525f4f78bb6Smrg	if (image->type == BITS && prng_rand_n (8) != 0)
5269ad247e8Sjmcneill	{
5279ad247e8Sjmcneill	    uint32_t width, height;
52814b11b2bSmrg	    uint32_t x, y;
5299ad247e8Sjmcneill	    int i;
5309ad247e8Sjmcneill
5319ad247e8Sjmcneill	    /* Also add a couple of clip rectangles inside the image
5329ad247e8Sjmcneill	     * so that compositing will actually take place.
5339ad247e8Sjmcneill	     */
5349ad247e8Sjmcneill	    for (i = 0; i < 5; ++i)
5359ad247e8Sjmcneill	    {
536f4f78bb6Smrg		x = prng_rand_n (2 * image->bits.width) - image->bits.width;
537f4f78bb6Smrg		y = prng_rand_n (2 * image->bits.height) - image->bits.height;
538f4f78bb6Smrg		width = prng_rand_n (image->bits.width) - x + 10;
539f4f78bb6Smrg		height = prng_rand_n (image->bits.height) - y + 10;
5409ad247e8Sjmcneill
5419ad247e8Sjmcneill		if (width + x < x)
5429ad247e8Sjmcneill		    width = INT32_MAX - x;
5439ad247e8Sjmcneill		if (height + y < y)
5449ad247e8Sjmcneill		    height = INT32_MAX - y;
545f4f78bb6Smrg
5469ad247e8Sjmcneill		pixman_region32_union_rect (
5479ad247e8Sjmcneill		    &region, &region, x, y, width, height);
5489ad247e8Sjmcneill	    }
5499ad247e8Sjmcneill	}
5509ad247e8Sjmcneill
551953d7d37Smrg	pixman_image_set_clip_region32 (image, &region);
552953d7d37Smrg
553953d7d37Smrg	pixman_region32_fini (&region);
554953d7d37Smrg    }
555953d7d37Smrg
556953d7d37Smrg    /* Whether source clipping is enabled */
557f4f78bb6Smrg    pixman_image_set_source_clipping (image, !!prng_rand_n (2));
558953d7d37Smrg
559953d7d37Smrg    /* Client clip */
560f4f78bb6Smrg    pixman_image_set_has_client_clip (image, !!prng_rand_n (2));
561953d7d37Smrg
562953d7d37Smrg    /* Transform */
563f4f78bb6Smrg    if (prng_rand_n (5) < 2)
564953d7d37Smrg    {
565953d7d37Smrg	pixman_transform_t xform;
566953d7d37Smrg	int i, j, k;
567953d7d37Smrg	uint32_t tx, ty, sx, sy;
568953d7d37Smrg	uint32_t c, s;
569953d7d37Smrg
570953d7d37Smrg	memset (&xform, 0, sizeof xform);
571953d7d37Smrg	xform.matrix[0][0] = pixman_fixed_1;
572953d7d37Smrg	xform.matrix[1][1] = pixman_fixed_1;
573953d7d37Smrg	xform.matrix[2][2] = pixman_fixed_1;
574953d7d37Smrg
575953d7d37Smrg	for (k = 0; k < 3; ++k)
576953d7d37Smrg	{
577f4f78bb6Smrg	    switch (prng_rand_n (4))
578953d7d37Smrg	    {
579953d7d37Smrg	    case 0:
580953d7d37Smrg		/* rotation */
581f4f78bb6Smrg		c = prng_rand_n (2 * 65536) - 65536;
582f4f78bb6Smrg		s = prng_rand_n (2 * 65536) - 65536;
583953d7d37Smrg		pixman_transform_rotate (&xform, NULL, c, s);
584953d7d37Smrg		break;
585953d7d37Smrg
586953d7d37Smrg	    case 1:
587953d7d37Smrg		/* translation */
588f4f78bb6Smrg		tx = prng_rand();
589f4f78bb6Smrg		ty = prng_rand();
590953d7d37Smrg		pixman_transform_translate (&xform, NULL, tx, ty);
591953d7d37Smrg		break;
592953d7d37Smrg
593953d7d37Smrg	    case 2:
594953d7d37Smrg		/* scale */
595f4f78bb6Smrg		sx = prng_rand();
596f4f78bb6Smrg		sy = prng_rand();
597953d7d37Smrg		pixman_transform_scale (&xform, NULL, sx, sy);
598953d7d37Smrg		break;
599953d7d37Smrg
600953d7d37Smrg	    case 3:
601f4f78bb6Smrg		if (prng_rand_n (16) == 0)
602953d7d37Smrg		{
603953d7d37Smrg		    /* random */
604953d7d37Smrg		    for (i = 0; i < 3; ++i)
605953d7d37Smrg			for (j = 0; j < 3; ++j)
606f4f78bb6Smrg			    xform.matrix[i][j] = prng_rand();
607953d7d37Smrg		    break;
608953d7d37Smrg		}
609f4f78bb6Smrg		else if (prng_rand_n (16) == 0)
610953d7d37Smrg		{
611953d7d37Smrg		    /* zero */
612953d7d37Smrg		    memset (&xform, 0, sizeof xform);
613953d7d37Smrg		}
614953d7d37Smrg		break;
615953d7d37Smrg	    }
616953d7d37Smrg	}
617953d7d37Smrg
618953d7d37Smrg	pixman_image_set_transform (image, &xform);
619953d7d37Smrg    }
620953d7d37Smrg}
621953d7d37Smrg
622953d7d37Smrgstatic pixman_color_t
623953d7d37Smrgrandom_color (void)
624953d7d37Smrg{
625953d7d37Smrg    pixman_color_t color =
626953d7d37Smrg    {
627f4f78bb6Smrg	prng_rand() & 0xffff,
628f4f78bb6Smrg	prng_rand() & 0xffff,
629f4f78bb6Smrg	prng_rand() & 0xffff,
630f4f78bb6Smrg	prng_rand() & 0xffff,
631953d7d37Smrg    };
632953d7d37Smrg
633953d7d37Smrg    return color;
634953d7d37Smrg}
635953d7d37Smrg
636953d7d37Smrg
637953d7d37Smrgstatic pixman_image_t *
638953d7d37Smrgcreate_random_solid_image (void)
639953d7d37Smrg{
640953d7d37Smrg    pixman_color_t color = random_color();
641953d7d37Smrg    pixman_image_t *image = pixman_image_create_solid_fill (&color);
642953d7d37Smrg
643953d7d37Smrg    return image;
644953d7d37Smrg}
645953d7d37Smrg
646953d7d37Smrgstatic pixman_gradient_stop_t *
647953d7d37Smrgcreate_random_stops (int *n_stops)
648953d7d37Smrg{
649953d7d37Smrg    pixman_fixed_t step;
650953d7d37Smrg    pixman_fixed_t s;
651953d7d37Smrg    int i;
652953d7d37Smrg    pixman_gradient_stop_t *stops;
653953d7d37Smrg
654f4f78bb6Smrg    *n_stops = prng_rand_n (50) + 1;
655953d7d37Smrg
656953d7d37Smrg    step = pixman_fixed_1 / *n_stops;
657953d7d37Smrg
658953d7d37Smrg    stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t));
659953d7d37Smrg
660953d7d37Smrg    s = 0;
661953d7d37Smrg    for (i = 0; i < (*n_stops) - 1; ++i)
662953d7d37Smrg    {
663953d7d37Smrg	stops[i].x = s;
664953d7d37Smrg	stops[i].color = random_color();
665953d7d37Smrg
666953d7d37Smrg	s += step;
667953d7d37Smrg    }
668953d7d37Smrg
669953d7d37Smrg    stops[*n_stops - 1].x = pixman_fixed_1;
670953d7d37Smrg    stops[*n_stops - 1].color = random_color();
671953d7d37Smrg
672953d7d37Smrg    return stops;
673953d7d37Smrg}
674953d7d37Smrg
675953d7d37Smrgstatic pixman_point_fixed_t
676953d7d37Smrgcreate_random_point (void)
677953d7d37Smrg{
678953d7d37Smrg    pixman_point_fixed_t p;
679953d7d37Smrg
680953d7d37Smrg    p.x = log_rand ();
681953d7d37Smrg    p.y = log_rand ();
682953d7d37Smrg
683953d7d37Smrg    return p;
684953d7d37Smrg}
685953d7d37Smrg
686953d7d37Smrgstatic pixman_image_t *
687953d7d37Smrgcreate_random_linear_image (void)
688953d7d37Smrg{
689953d7d37Smrg    int n_stops;
690953d7d37Smrg    pixman_gradient_stop_t *stops;
691953d7d37Smrg    pixman_point_fixed_t p1, p2;
692953d7d37Smrg    pixman_image_t *result;
693953d7d37Smrg
694953d7d37Smrg    stops = create_random_stops (&n_stops);
695953d7d37Smrg    if (!stops)
696953d7d37Smrg	return NULL;
697953d7d37Smrg
698953d7d37Smrg    p1 = create_random_point ();
699953d7d37Smrg    p2 = create_random_point ();
700953d7d37Smrg
701953d7d37Smrg    result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops);
702953d7d37Smrg
703953d7d37Smrg    free (stops);
704953d7d37Smrg
705953d7d37Smrg    return result;
706953d7d37Smrg}
707953d7d37Smrg
708953d7d37Smrgstatic pixman_image_t *
709953d7d37Smrgcreate_random_radial_image (void)
710953d7d37Smrg{
711953d7d37Smrg    int n_stops;
712953d7d37Smrg    pixman_gradient_stop_t *stops;
713953d7d37Smrg    pixman_point_fixed_t inner_c, outer_c;
714953d7d37Smrg    pixman_fixed_t inner_r, outer_r;
715953d7d37Smrg    pixman_image_t *result;
716953d7d37Smrg
717953d7d37Smrg    inner_c = create_random_point();
718953d7d37Smrg    outer_c = create_random_point();
719f4f78bb6Smrg    inner_r = prng_rand();
720f4f78bb6Smrg    outer_r = prng_rand();
721953d7d37Smrg
722953d7d37Smrg    stops = create_random_stops (&n_stops);
723953d7d37Smrg
724953d7d37Smrg    if (!stops)
725953d7d37Smrg	return NULL;
726953d7d37Smrg
727953d7d37Smrg    result = pixman_image_create_radial_gradient (
728953d7d37Smrg	&inner_c, &outer_c, inner_r, outer_r, stops, n_stops);
729953d7d37Smrg
730953d7d37Smrg    free (stops);
731953d7d37Smrg
732953d7d37Smrg    return result;
733953d7d37Smrg}
734953d7d37Smrg
735953d7d37Smrgstatic pixman_image_t *
736953d7d37Smrgcreate_random_conical_image (void)
737953d7d37Smrg{
738953d7d37Smrg    pixman_gradient_stop_t *stops;
739953d7d37Smrg    int n_stops;
740953d7d37Smrg    pixman_point_fixed_t c;
741953d7d37Smrg    pixman_fixed_t angle;
742953d7d37Smrg    pixman_image_t *result;
743953d7d37Smrg
744953d7d37Smrg    c = create_random_point();
745f4f78bb6Smrg    angle = prng_rand();
746953d7d37Smrg
747953d7d37Smrg    stops = create_random_stops (&n_stops);
748953d7d37Smrg
749953d7d37Smrg    if (!stops)
750953d7d37Smrg	return NULL;
751953d7d37Smrg
752953d7d37Smrg    result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops);
753953d7d37Smrg
754953d7d37Smrg    free (stops);
755953d7d37Smrg
756953d7d37Smrg    return result;
757953d7d37Smrg}
758953d7d37Smrg
759953d7d37Smrgstatic pixman_image_t *
760953d7d37Smrgcreate_random_image (void)
761953d7d37Smrg{
762953d7d37Smrg    pixman_image_t *result;
763953d7d37Smrg
764f4f78bb6Smrg    switch (prng_rand_n (5))
765953d7d37Smrg    {
766953d7d37Smrg    default:
767953d7d37Smrg    case 0:
768f4f78bb6Smrg	result = create_random_bits_image (DONT_CARE);
769953d7d37Smrg	break;
770953d7d37Smrg
771953d7d37Smrg    case 1:
772953d7d37Smrg	result = create_random_solid_image ();
773953d7d37Smrg	break;
774953d7d37Smrg
775953d7d37Smrg    case 2:
776953d7d37Smrg	result = create_random_linear_image ();
777953d7d37Smrg	break;
778953d7d37Smrg
779953d7d37Smrg    case 3:
780953d7d37Smrg	result = create_random_radial_image ();
781953d7d37Smrg	break;
782953d7d37Smrg
783953d7d37Smrg    case 4:
784953d7d37Smrg	result = create_random_conical_image ();
785953d7d37Smrg	break;
786953d7d37Smrg    }
787953d7d37Smrg
788953d7d37Smrg    if (result)
789953d7d37Smrg	set_general_properties (result, TRUE);
790953d7d37Smrg
791953d7d37Smrg    return result;
792953d7d37Smrg}
793953d7d37Smrg
794f4f78bb6Smrgstatic void
795f4f78bb6Smrgrandom_line (pixman_line_fixed_t *line, int width, int height)
796f4f78bb6Smrg{
797f4f78bb6Smrg    line->p1.x = prng_rand_n (width) << 16;
798f4f78bb6Smrg    line->p1.y = prng_rand_n (height) << 16;
799f4f78bb6Smrg    line->p2.x = prng_rand_n (width) << 16;
800f4f78bb6Smrg    line->p2.y = prng_rand_n (height) << 16;
801f4f78bb6Smrg}
802f4f78bb6Smrg
803f4f78bb6Smrgstatic pixman_trapezoid_t *
804f4f78bb6Smrgcreate_random_trapezoids (int *n_traps, int height, int width)
805f4f78bb6Smrg{
806f4f78bb6Smrg    pixman_trapezoid_t *trapezoids;
807f4f78bb6Smrg    int i;
808f4f78bb6Smrg
809f4f78bb6Smrg    *n_traps = prng_rand_n (16) + 1;
810f4f78bb6Smrg
811f4f78bb6Smrg    trapezoids = malloc (sizeof (pixman_trapezoid_t) * *n_traps);
812f4f78bb6Smrg
813f4f78bb6Smrg    for (i = 0; i < *n_traps; ++i)
814f4f78bb6Smrg    {
815f4f78bb6Smrg        pixman_trapezoid_t *t = &(trapezoids[i]);
816f4f78bb6Smrg
817f4f78bb6Smrg        t->top = prng_rand_n (height) << 16;
818f4f78bb6Smrg        t->bottom = prng_rand_n (height) << 16;
819f4f78bb6Smrg
820f4f78bb6Smrg        random_line (&t->left, height, width);
821f4f78bb6Smrg        random_line (&t->right, height, width);
822f4f78bb6Smrg    }
823f4f78bb6Smrg
824f4f78bb6Smrg    return trapezoids;
825f4f78bb6Smrg}
826f4f78bb6Smrg
827953d7d37Smrgstatic const pixman_op_t op_list[] =
828953d7d37Smrg{
829953d7d37Smrg    PIXMAN_OP_SRC,
830953d7d37Smrg    PIXMAN_OP_OVER,
831953d7d37Smrg    PIXMAN_OP_ADD,
832953d7d37Smrg    PIXMAN_OP_CLEAR,
833953d7d37Smrg    PIXMAN_OP_SRC,
834953d7d37Smrg    PIXMAN_OP_DST,
835953d7d37Smrg    PIXMAN_OP_OVER,
836953d7d37Smrg    PIXMAN_OP_OVER_REVERSE,
837953d7d37Smrg    PIXMAN_OP_IN,
838953d7d37Smrg    PIXMAN_OP_IN_REVERSE,
839953d7d37Smrg    PIXMAN_OP_OUT,
840953d7d37Smrg    PIXMAN_OP_OUT_REVERSE,
841953d7d37Smrg    PIXMAN_OP_ATOP,
842953d7d37Smrg    PIXMAN_OP_ATOP_REVERSE,
843953d7d37Smrg    PIXMAN_OP_XOR,
844953d7d37Smrg    PIXMAN_OP_ADD,
845953d7d37Smrg    PIXMAN_OP_SATURATE,
846953d7d37Smrg    PIXMAN_OP_DISJOINT_CLEAR,
847953d7d37Smrg    PIXMAN_OP_DISJOINT_SRC,
848953d7d37Smrg    PIXMAN_OP_DISJOINT_DST,
849953d7d37Smrg    PIXMAN_OP_DISJOINT_OVER,
850953d7d37Smrg    PIXMAN_OP_DISJOINT_OVER_REVERSE,
851953d7d37Smrg    PIXMAN_OP_DISJOINT_IN,
852953d7d37Smrg    PIXMAN_OP_DISJOINT_IN_REVERSE,
853953d7d37Smrg    PIXMAN_OP_DISJOINT_OUT,
854953d7d37Smrg    PIXMAN_OP_DISJOINT_OUT_REVERSE,
855953d7d37Smrg    PIXMAN_OP_DISJOINT_ATOP,
856953d7d37Smrg    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
857953d7d37Smrg    PIXMAN_OP_DISJOINT_XOR,
858953d7d37Smrg    PIXMAN_OP_CONJOINT_CLEAR,
859953d7d37Smrg    PIXMAN_OP_CONJOINT_SRC,
860953d7d37Smrg    PIXMAN_OP_CONJOINT_DST,
861953d7d37Smrg    PIXMAN_OP_CONJOINT_OVER,
862953d7d37Smrg    PIXMAN_OP_CONJOINT_OVER_REVERSE,
863953d7d37Smrg    PIXMAN_OP_CONJOINT_IN,
864953d7d37Smrg    PIXMAN_OP_CONJOINT_IN_REVERSE,
865953d7d37Smrg    PIXMAN_OP_CONJOINT_OUT,
866953d7d37Smrg    PIXMAN_OP_CONJOINT_OUT_REVERSE,
867953d7d37Smrg    PIXMAN_OP_CONJOINT_ATOP,
868953d7d37Smrg    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
869953d7d37Smrg    PIXMAN_OP_CONJOINT_XOR,
870953d7d37Smrg    PIXMAN_OP_MULTIPLY,
871953d7d37Smrg    PIXMAN_OP_SCREEN,
872953d7d37Smrg    PIXMAN_OP_OVERLAY,
873953d7d37Smrg    PIXMAN_OP_DARKEN,
874953d7d37Smrg    PIXMAN_OP_LIGHTEN,
875953d7d37Smrg    PIXMAN_OP_COLOR_DODGE,
876953d7d37Smrg    PIXMAN_OP_COLOR_BURN,
877953d7d37Smrg    PIXMAN_OP_HARD_LIGHT,
878953d7d37Smrg    PIXMAN_OP_DIFFERENCE,
879953d7d37Smrg    PIXMAN_OP_EXCLUSION,
880953d7d37Smrg    PIXMAN_OP_SOFT_LIGHT,
881953d7d37Smrg    PIXMAN_OP_HSL_HUE,
882953d7d37Smrg    PIXMAN_OP_HSL_SATURATION,
883953d7d37Smrg    PIXMAN_OP_HSL_COLOR,
884953d7d37Smrg    PIXMAN_OP_HSL_LUMINOSITY,
885953d7d37Smrg};
886953d7d37Smrg
887953d7d37Smrgstatic void
8886ba797d6Smrgrun_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
889953d7d37Smrg{
890953d7d37Smrg    pixman_image_t *source, *mask, *dest;
891953d7d37Smrg    pixman_op_t op;
892953d7d37Smrg
8936ba797d6Smrg    if (verbose)
8946ba797d6Smrg    {
8956ba797d6Smrg	if (mod == 0 || (seed % mod) == 0)
8966ba797d6Smrg	    printf ("Seed 0x%08x\n", seed);
8976ba797d6Smrg    }
898953d7d37Smrg
899f4f78bb6Smrg    source = mask = dest = NULL;
900953d7d37Smrg
901f4f78bb6Smrg    prng_srand (seed);
902f4f78bb6Smrg
903f4f78bb6Smrg    if (prng_rand_n (8) == 0)
904953d7d37Smrg    {
905f4f78bb6Smrg        int n_traps;
906f4f78bb6Smrg        pixman_trapezoid_t *trapezoids;
907f4f78bb6Smrg	int p = prng_rand_n (3);
908f4f78bb6Smrg
909f4f78bb6Smrg	if (p == 0)
910f4f78bb6Smrg	    dest = create_random_bits_image (DONT_CARE);
911f4f78bb6Smrg	else
912f4f78bb6Smrg	    dest = create_random_bits_image (REQUIRE_ALPHA);
913f4f78bb6Smrg
914f4f78bb6Smrg	if (!dest)
915f4f78bb6Smrg	    goto out;
916f4f78bb6Smrg
917953d7d37Smrg	set_general_properties (dest, TRUE);
918953d7d37Smrg
919f4f78bb6Smrg	if (!(trapezoids = create_random_trapezoids (
920f4f78bb6Smrg		  &n_traps, dest->bits.width, dest->bits.height)))
921f4f78bb6Smrg	{
922f4f78bb6Smrg	    goto out;
923f4f78bb6Smrg	}
924f4f78bb6Smrg
925f4f78bb6Smrg	switch (p)
926f4f78bb6Smrg	{
927f4f78bb6Smrg	case 0:
928f4f78bb6Smrg	    source = create_random_image ();
929f4f78bb6Smrg
930f4f78bb6Smrg	    if (source)
931f4f78bb6Smrg	    {
932f4f78bb6Smrg		op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))];
933f4f78bb6Smrg
934f4f78bb6Smrg		pixman_composite_trapezoids (
935f4f78bb6Smrg		    op, source, dest,
936f4f78bb6Smrg		    random_format (REQUIRE_ALPHA),
937f4f78bb6Smrg		    rand_x (source), rand_y (source),
938f4f78bb6Smrg		    rand_x (dest), rand_y (dest),
939f4f78bb6Smrg		    n_traps, trapezoids);
940f4f78bb6Smrg	    }
941f4f78bb6Smrg	    break;
942f4f78bb6Smrg
943f4f78bb6Smrg	case 1:
944f4f78bb6Smrg	    pixman_rasterize_trapezoid (
945f4f78bb6Smrg		dest, &trapezoids[prng_rand_n (n_traps)],
946f4f78bb6Smrg		rand_x (dest), rand_y (dest));
947f4f78bb6Smrg	    break;
948953d7d37Smrg
949f4f78bb6Smrg	case 2:
950f4f78bb6Smrg	    pixman_add_trapezoids (
951f4f78bb6Smrg		dest, rand_x (dest), rand_y (dest), n_traps, trapezoids);
952f4f78bb6Smrg	    break;
953f4f78bb6Smrg        }
954f4f78bb6Smrg
955f4f78bb6Smrg	free (trapezoids);
956f4f78bb6Smrg    }
957f4f78bb6Smrg    else
958f4f78bb6Smrg    {
959f4f78bb6Smrg        dest = create_random_bits_image (DONT_CARE);
960f4f78bb6Smrg        source = create_random_image ();
961f4f78bb6Smrg        mask = create_random_image ();
962f4f78bb6Smrg
963f4f78bb6Smrg        if (source && mask && dest)
964f4f78bb6Smrg        {
965f4f78bb6Smrg            set_general_properties (dest, TRUE);
966f4f78bb6Smrg
967f4f78bb6Smrg            op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))];
968f4f78bb6Smrg
969f4f78bb6Smrg            pixman_image_composite32 (op,
970f4f78bb6Smrg                                      source, mask, dest,
971f4f78bb6Smrg                                      rand_x (source), rand_y (source),
972f4f78bb6Smrg                                      rand_x (mask), rand_y (mask),
973f4f78bb6Smrg                                      0, 0,
974f4f78bb6Smrg                                      dest->bits.width,
975f4f78bb6Smrg                                      dest->bits.height);
976f4f78bb6Smrg        }
977953d7d37Smrg    }
978f4f78bb6Smrg
979f4f78bb6Smrgout:
980953d7d37Smrg    if (source)
981953d7d37Smrg	pixman_image_unref (source);
982953d7d37Smrg    if (mask)
983953d7d37Smrg	pixman_image_unref (mask);
984953d7d37Smrg    if (dest)
985953d7d37Smrg	pixman_image_unref (dest);
986953d7d37Smrg}
987953d7d37Smrg
988953d7d37Smrgstatic pixman_bool_t
989953d7d37Smrgget_int (char *s, uint32_t *i)
990953d7d37Smrg{
991953d7d37Smrg    char *end;
992953d7d37Smrg    int p;
993953d7d37Smrg
994953d7d37Smrg    p = strtol (s, &end, 0);
995953d7d37Smrg
996953d7d37Smrg    if (end != s && *end == 0)
997953d7d37Smrg    {
998953d7d37Smrg	*i = p;
999953d7d37Smrg	return TRUE;
1000953d7d37Smrg    }
1001953d7d37Smrg
1002953d7d37Smrg    return FALSE;
1003953d7d37Smrg}
1004953d7d37Smrg
1005953d7d37Smrgint
1006953d7d37Smrgmain (int argc, char **argv)
1007953d7d37Smrg{
1008953d7d37Smrg    int verbose = FALSE;
1009953d7d37Smrg    uint32_t seed = 1;
10109ad247e8Sjmcneill    uint32_t n_tests = 8000;
1011953d7d37Smrg    uint32_t mod = 0;
10126ba797d6Smrg    pixman_bool_t use_threads = TRUE;
10139ad247e8Sjmcneill    int32_t i;
1014953d7d37Smrg
1015953d7d37Smrg    pixman_disable_out_of_bounds_workaround ();
1016953d7d37Smrg
10179ad247e8Sjmcneill    enable_divbyzero_exceptions();
1018953d7d37Smrg
1019953d7d37Smrg    if (getenv ("VERBOSE") != NULL)
1020953d7d37Smrg	verbose = TRUE;
1021953d7d37Smrg
1022953d7d37Smrg    for (i = 1; i < argc; ++i)
1023953d7d37Smrg    {
1024953d7d37Smrg	if (strcmp (argv[i], "-v") == 0)
1025953d7d37Smrg	{
1026953d7d37Smrg	    verbose = TRUE;
1027953d7d37Smrg
1028953d7d37Smrg	    if (i + 1 < argc)
1029953d7d37Smrg	    {
1030953d7d37Smrg		get_int (argv[i + 1], &mod);
1031953d7d37Smrg		i++;
1032953d7d37Smrg	    }
1033953d7d37Smrg	}
1034953d7d37Smrg	else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc)
1035953d7d37Smrg	{
1036953d7d37Smrg	    get_int (argv[i + 1], &seed);
10376ba797d6Smrg	    use_threads = FALSE;
1038953d7d37Smrg	    i++;
1039953d7d37Smrg	}
1040953d7d37Smrg	else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc)
1041953d7d37Smrg	{
1042953d7d37Smrg	    get_int (argv[i + 1], &n_tests);
1043953d7d37Smrg	    i++;
1044953d7d37Smrg	}
1045953d7d37Smrg	else
1046953d7d37Smrg	{
1047953d7d37Smrg	    if (strcmp (argv[i], "-h") != 0)
1048953d7d37Smrg		printf ("Unknown option '%s'\n\n", argv[i]);
1049953d7d37Smrg
1050953d7d37Smrg	    printf ("Options:\n\n"
1051953d7d37Smrg		    "-n <number>        Number of tests to run\n"
10526ba797d6Smrg		    "-s <seed> 	        Seed of first test (ignored if PIXMAN_RANDOMIZE_TESTS is set)\n"
1053953d7d37Smrg		    "-v                 Print out seeds\n"
1054953d7d37Smrg		    "-v <n>             Print out every n'th seed\n\n");
1055953d7d37Smrg
1056953d7d37Smrg	    exit (-1);
1057953d7d37Smrg	}
1058953d7d37Smrg    }
1059953d7d37Smrg
10606ba797d6Smrg    if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
10616ba797d6Smrg    {
10626ba797d6Smrg	seed = get_random_seed();
10636ba797d6Smrg	printf ("First seed: 0x%08x\n", seed);
10646ba797d6Smrg    }
10656ba797d6Smrg
10666ba797d6Smrg    if (use_threads)
10676ba797d6Smrg    {
1068953d7d37Smrg#ifdef USE_OPENMP
1069953d7d37Smrg#   pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed)
1070953d7d37Smrg#endif
10719ad247e8Sjmcneill	for (i = 0; i < (int32_t)n_tests; ++i)
10729ad247e8Sjmcneill	    run_test (seed + i, verbose, mod);
10736ba797d6Smrg    }
10746ba797d6Smrg    else
1075953d7d37Smrg    {
10769ad247e8Sjmcneill	for (i = 0; i < (int32_t)n_tests; ++i)
10779ad247e8Sjmcneill	    run_test (seed + i, verbose, mod);
1078953d7d37Smrg    }
1079953d7d37Smrg
1080953d7d37Smrg    return 0;
1081953d7d37Smrg}
1082