stress-test.c revision 953d7d37
1953d7d37Smrg#include "utils.h"
2953d7d37Smrg
3953d7d37Smrg#if 0
4953d7d37Smrg#define fence_malloc malloc
5953d7d37Smrg#define fence_free free
6953d7d37Smrg#define make_random_bytes malloc
7953d7d37Smrg#endif
8953d7d37Smrg
9953d7d37Smrgstatic const pixman_format_code_t image_formats[] =
10953d7d37Smrg{
11953d7d37Smrg    PIXMAN_a8r8g8b8,
12953d7d37Smrg    PIXMAN_x8r8g8b8,
13953d7d37Smrg    PIXMAN_r5g6b5,
14953d7d37Smrg    PIXMAN_r3g3b2,
15953d7d37Smrg    PIXMAN_a8,
16953d7d37Smrg    PIXMAN_a8b8g8r8,
17953d7d37Smrg    PIXMAN_x8b8g8r8,
18953d7d37Smrg    PIXMAN_b8g8r8a8,
19953d7d37Smrg    PIXMAN_b8g8r8x8,
20953d7d37Smrg    PIXMAN_x14r6g6b6,
21953d7d37Smrg    PIXMAN_r8g8b8,
22953d7d37Smrg    PIXMAN_b8g8r8,
23953d7d37Smrg    PIXMAN_r5g6b5,
24953d7d37Smrg    PIXMAN_b5g6r5,
25953d7d37Smrg    PIXMAN_x2r10g10b10,
26953d7d37Smrg    PIXMAN_a2r10g10b10,
27953d7d37Smrg    PIXMAN_x2b10g10r10,
28953d7d37Smrg    PIXMAN_a2b10g10r10,
29953d7d37Smrg    PIXMAN_a1r5g5b5,
30953d7d37Smrg    PIXMAN_x1r5g5b5,
31953d7d37Smrg    PIXMAN_a1b5g5r5,
32953d7d37Smrg    PIXMAN_x1b5g5r5,
33953d7d37Smrg    PIXMAN_a4r4g4b4,
34953d7d37Smrg    PIXMAN_x4r4g4b4,
35953d7d37Smrg    PIXMAN_a4b4g4r4,
36953d7d37Smrg    PIXMAN_x4b4g4r4,
37953d7d37Smrg    PIXMAN_a8,
38953d7d37Smrg    PIXMAN_r3g3b2,
39953d7d37Smrg    PIXMAN_b2g3r3,
40953d7d37Smrg    PIXMAN_a2r2g2b2,
41953d7d37Smrg    PIXMAN_a2b2g2r2,
42953d7d37Smrg    PIXMAN_c8,
43953d7d37Smrg    PIXMAN_g8,
44953d7d37Smrg    PIXMAN_x4c4,
45953d7d37Smrg    PIXMAN_x4g4,
46953d7d37Smrg    PIXMAN_c4,
47953d7d37Smrg    PIXMAN_g4,
48953d7d37Smrg    PIXMAN_g1,
49953d7d37Smrg    PIXMAN_x4a4,
50953d7d37Smrg    PIXMAN_a4,
51953d7d37Smrg    PIXMAN_r1g2b1,
52953d7d37Smrg    PIXMAN_b1g2r1,
53953d7d37Smrg    PIXMAN_a1r1g1b1,
54953d7d37Smrg    PIXMAN_a1b1g1r1,
55953d7d37Smrg    PIXMAN_a1
56953d7d37Smrg};
57953d7d37Smrg
58953d7d37Smrgstatic pixman_filter_t filters[] =
59953d7d37Smrg{
60953d7d37Smrg    PIXMAN_FILTER_NEAREST,
61953d7d37Smrg    PIXMAN_FILTER_BILINEAR,
62953d7d37Smrg    PIXMAN_FILTER_FAST,
63953d7d37Smrg    PIXMAN_FILTER_GOOD,
64953d7d37Smrg    PIXMAN_FILTER_BEST,
65953d7d37Smrg    PIXMAN_FILTER_CONVOLUTION
66953d7d37Smrg};
67953d7d37Smrg
68953d7d37Smrgstatic int
69953d7d37Smrgget_size (void)
70953d7d37Smrg{
71953d7d37Smrg    switch (lcg_rand_n (28))
72953d7d37Smrg    {
73953d7d37Smrg    case 0:
74953d7d37Smrg	return 1;
75953d7d37Smrg
76953d7d37Smrg    case 1:
77953d7d37Smrg	return 2;
78953d7d37Smrg
79953d7d37Smrg    default:
80953d7d37Smrg    case 2:
81953d7d37Smrg	return lcg_rand_n (200);
82953d7d37Smrg
83953d7d37Smrg    case 4:
84953d7d37Smrg	return lcg_rand_n (2000) + 1000;
85953d7d37Smrg
86953d7d37Smrg    case 5:
87953d7d37Smrg	return 65535;
88953d7d37Smrg
89953d7d37Smrg    case 6:
90953d7d37Smrg	return 65536;
91953d7d37Smrg
92953d7d37Smrg    case 7:
93953d7d37Smrg	return lcg_rand_N (64000) + 63000;
94953d7d37Smrg    }
95953d7d37Smrg}
96953d7d37Smrg
97953d7d37Smrgstatic void
98953d7d37Smrgdestroy (pixman_image_t *image, void *data)
99953d7d37Smrg{
100953d7d37Smrg    if (image->type == BITS && image->bits.free_me != image->bits.bits)
101953d7d37Smrg    {
102953d7d37Smrg	uint32_t *bits;
103953d7d37Smrg
104953d7d37Smrg	if (image->bits.bits != (void *)0x01)
105953d7d37Smrg	{
106953d7d37Smrg	    bits = image->bits.bits;
107953d7d37Smrg
108953d7d37Smrg	    if (image->bits.rowstride < 0)
109953d7d37Smrg		bits -= (- image->bits.rowstride * (image->bits.height - 1));
110953d7d37Smrg
111953d7d37Smrg	    fence_free (bits);
112953d7d37Smrg	}
113953d7d37Smrg    }
114953d7d37Smrg
115953d7d37Smrg    free (data);
116953d7d37Smrg}
117953d7d37Smrg
118953d7d37Smrgstatic uint32_t
119953d7d37Smrgreal_reader (const void *src, int size)
120953d7d37Smrg{
121953d7d37Smrg    switch (size)
122953d7d37Smrg    {
123953d7d37Smrg    case 1:
124953d7d37Smrg	return *(uint8_t *)src;
125953d7d37Smrg    case 2:
126953d7d37Smrg	return *(uint16_t *)src;
127953d7d37Smrg    case 4:
128953d7d37Smrg	return *(uint32_t *)src;
129953d7d37Smrg    default:
130953d7d37Smrg	assert (0);
131953d7d37Smrg	break;
132953d7d37Smrg    }
133953d7d37Smrg}
134953d7d37Smrg
135953d7d37Smrgstatic void
136953d7d37Smrgreal_writer (void *src, uint32_t value, int size)
137953d7d37Smrg{
138953d7d37Smrg    switch (size)
139953d7d37Smrg    {
140953d7d37Smrg    case 1:
141953d7d37Smrg	*(uint8_t *)src = value;
142953d7d37Smrg	break;
143953d7d37Smrg
144953d7d37Smrg    case 2:
145953d7d37Smrg	*(uint16_t *)src = value;
146953d7d37Smrg	break;
147953d7d37Smrg
148953d7d37Smrg    case 4:
149953d7d37Smrg	*(uint32_t *)src = value;
150953d7d37Smrg	break;
151953d7d37Smrg
152953d7d37Smrg    default:
153953d7d37Smrg	assert (0);
154953d7d37Smrg	break;
155953d7d37Smrg    }
156953d7d37Smrg}
157953d7d37Smrg
158953d7d37Smrgstatic uint32_t
159953d7d37Smrgfake_reader (const void *src, int size)
160953d7d37Smrg{
161953d7d37Smrg    uint32_t r = lcg_rand_u32 ();
162953d7d37Smrg
163953d7d37Smrg    assert (size == 1 || size == 2 || size == 4);
164953d7d37Smrg    return r & ((1 << (size * 8)) - 1);
165953d7d37Smrg}
166953d7d37Smrg
167953d7d37Smrgstatic void
168953d7d37Smrgfake_writer (void *src, uint32_t value, int size)
169953d7d37Smrg{
170953d7d37Smrg    assert (size == 1 || size == 2 || size == 4);
171953d7d37Smrg}
172953d7d37Smrg
173953d7d37Smrgstatic int32_t
174953d7d37Smrglog_rand (void)
175953d7d37Smrg{
176953d7d37Smrg    uint32_t mask;
177953d7d37Smrg
178953d7d37Smrg    mask = (1 << lcg_rand_n (31)) - 1;
179953d7d37Smrg
180953d7d37Smrg    return (lcg_rand () & mask) - (mask >> 1);
181953d7d37Smrg}
182953d7d37Smrg
183953d7d37Smrgstatic pixman_image_t *
184953d7d37Smrgcreate_random_bits_image (void)
185953d7d37Smrg{
186953d7d37Smrg    pixman_format_code_t format;
187953d7d37Smrg    pixman_indexed_t *indexed;
188953d7d37Smrg    pixman_image_t *image;
189953d7d37Smrg    int width, height, stride;
190953d7d37Smrg    uint32_t *bits;
191953d7d37Smrg    pixman_read_memory_func_t read_func = NULL;
192953d7d37Smrg    pixman_write_memory_func_t write_func = NULL;
193953d7d37Smrg    pixman_filter_t filter;
194953d7d37Smrg    pixman_fixed_t *coefficients = NULL;
195953d7d37Smrg    int n_coefficients = 0;
196953d7d37Smrg
197953d7d37Smrg    /* format */
198953d7d37Smrg    format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))];
199953d7d37Smrg
200953d7d37Smrg    indexed = NULL;
201953d7d37Smrg    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
202953d7d37Smrg    {
203953d7d37Smrg	indexed = malloc (sizeof (pixman_indexed_t));
204953d7d37Smrg
205953d7d37Smrg	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE);
206953d7d37Smrg    }
207953d7d37Smrg    else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
208953d7d37Smrg    {
209953d7d37Smrg	indexed = malloc (sizeof (pixman_indexed_t));
210953d7d37Smrg
211953d7d37Smrg	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE);
212953d7d37Smrg    }
213953d7d37Smrg    else
214953d7d37Smrg    {
215953d7d37Smrg	indexed = NULL;
216953d7d37Smrg    }
217953d7d37Smrg
218953d7d37Smrg    /* size */
219953d7d37Smrg    width = get_size ();
220953d7d37Smrg    height = get_size ();
221953d7d37Smrg
222953d7d37Smrg    if ((uint64_t)width * height > 200000)
223953d7d37Smrg    {
224953d7d37Smrg	if (lcg_rand_n(2) == 0)
225953d7d37Smrg	    height = 200000 / width;
226953d7d37Smrg	else
227953d7d37Smrg	    width = 200000 / height;
228953d7d37Smrg    }
229953d7d37Smrg
230953d7d37Smrg    if (height == 0)
231953d7d37Smrg	height = 1;
232953d7d37Smrg    if (width == 0)
233953d7d37Smrg	width = 1;
234953d7d37Smrg
235953d7d37Smrg    /* bits */
236953d7d37Smrg    switch (lcg_rand_n (7))
237953d7d37Smrg    {
238953d7d37Smrg    default:
239953d7d37Smrg    case 0:
240953d7d37Smrg	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
241953d7d37Smrg	stride = (stride + 3) & (~3);
242953d7d37Smrg	bits = (uint32_t *)make_random_bytes (height * stride);
243953d7d37Smrg	break;
244953d7d37Smrg
245953d7d37Smrg    case 1:
246953d7d37Smrg	stride = 0;
247953d7d37Smrg	bits = NULL;
248953d7d37Smrg	break;
249953d7d37Smrg
250953d7d37Smrg    case 2: /* Zero-filled */
251953d7d37Smrg	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
252953d7d37Smrg	stride = (stride + 3) & (~3);
253953d7d37Smrg	bits = fence_malloc (height * stride);
254953d7d37Smrg	if (!bits)
255953d7d37Smrg	    return NULL;
256953d7d37Smrg	memset (bits, 0, height * stride);
257953d7d37Smrg	break;
258953d7d37Smrg
259953d7d37Smrg    case 3: /* Filled with 0xFF */
260953d7d37Smrg	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
261953d7d37Smrg	stride = (stride + 3) & (~3);
262953d7d37Smrg	bits = fence_malloc (height * stride);
263953d7d37Smrg	if (!bits)
264953d7d37Smrg	    return NULL;
265953d7d37Smrg	memset (bits, 0xff, height * stride);
266953d7d37Smrg	break;
267953d7d37Smrg
268953d7d37Smrg    case 4: /* bits is a bad pointer, has read/write functions */
269953d7d37Smrg	stride = 232;
270953d7d37Smrg	bits = (void *)0x01;
271953d7d37Smrg	read_func = fake_reader;
272953d7d37Smrg	write_func = fake_writer;
273953d7d37Smrg	break;
274953d7d37Smrg
275953d7d37Smrg    case 5: /* bits is a real pointer, has read/write functions */
276953d7d37Smrg	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
277953d7d37Smrg	stride = (stride + 3) & (~3);
278953d7d37Smrg	bits = fence_malloc (height * stride);
279953d7d37Smrg	if (!bits)
280953d7d37Smrg	    return NULL;
281953d7d37Smrg	memset (bits, 0xff, height * stride);
282953d7d37Smrg	read_func = real_reader;
283953d7d37Smrg	write_func = real_writer;
284953d7d37Smrg	break;
285953d7d37Smrg
286953d7d37Smrg    case 6: /* bits is a real pointer, stride is negative */
287953d7d37Smrg	stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17));
288953d7d37Smrg	stride = (stride + 3) & (~3);
289953d7d37Smrg	bits = (uint32_t *)make_random_bytes (height * stride);
290953d7d37Smrg	if (!bits)
291953d7d37Smrg	    return NULL;
292953d7d37Smrg	bits += ((height - 1) * stride) / 4;
293953d7d37Smrg	stride = - stride;
294953d7d37Smrg	break;
295953d7d37Smrg    }
296953d7d37Smrg
297953d7d37Smrg    /* Filter */
298953d7d37Smrg    filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))];
299953d7d37Smrg    if (filter == PIXMAN_FILTER_CONVOLUTION)
300953d7d37Smrg    {
301953d7d37Smrg	int width = lcg_rand_n (17);
302953d7d37Smrg	int height = lcg_rand_n (19);
303953d7d37Smrg
304953d7d37Smrg	n_coefficients = width * height + 2;
305953d7d37Smrg	coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t));
306953d7d37Smrg
307953d7d37Smrg	if (coefficients)
308953d7d37Smrg	{
309953d7d37Smrg	    int i;
310953d7d37Smrg
311953d7d37Smrg	    for (i = 0; i < width * height; ++i)
312953d7d37Smrg		coefficients[i + 2] = lcg_rand_u32();
313953d7d37Smrg
314953d7d37Smrg	    coefficients[0] = width << 16;
315953d7d37Smrg	    coefficients[1] = height << 16;
316953d7d37Smrg	}
317953d7d37Smrg	else
318953d7d37Smrg	{
319953d7d37Smrg	    filter = PIXMAN_FILTER_BEST;
320953d7d37Smrg	}
321953d7d37Smrg    }
322953d7d37Smrg
323953d7d37Smrg    /* Finally create the image */
324953d7d37Smrg    image = pixman_image_create_bits (format, width, height, bits, stride);
325953d7d37Smrg    if (!image)
326953d7d37Smrg	return NULL;
327953d7d37Smrg
328953d7d37Smrg    pixman_image_set_indexed (image, indexed);
329953d7d37Smrg    pixman_image_set_destroy_function (image, destroy, indexed);
330953d7d37Smrg    pixman_image_set_accessors (image, read_func, write_func);
331953d7d37Smrg    pixman_image_set_filter (image, filter, coefficients, n_coefficients);
332953d7d37Smrg
333953d7d37Smrg    return image;
334953d7d37Smrg}
335953d7d37Smrg
336953d7d37Smrgstatic pixman_repeat_t repeats[] =
337953d7d37Smrg{
338953d7d37Smrg    PIXMAN_REPEAT_NONE,
339953d7d37Smrg    PIXMAN_REPEAT_NORMAL,
340953d7d37Smrg    PIXMAN_REPEAT_REFLECT,
341953d7d37Smrg    PIXMAN_REPEAT_PAD
342953d7d37Smrg};
343953d7d37Smrg
344953d7d37Smrgstatic uint32_t
345953d7d37Smrgabsolute (int32_t i)
346953d7d37Smrg{
347953d7d37Smrg    return i < 0? -i : i;
348953d7d37Smrg}
349953d7d37Smrg
350953d7d37Smrgstatic void
351953d7d37Smrgset_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
352953d7d37Smrg{
353953d7d37Smrg    pixman_repeat_t repeat;
354953d7d37Smrg
355953d7d37Smrg    /* Set properties that are generic to all images */
356953d7d37Smrg
357953d7d37Smrg    /* Repeat */
358953d7d37Smrg    repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))];
359953d7d37Smrg    pixman_image_set_repeat (image, repeat);
360953d7d37Smrg
361953d7d37Smrg    /* Alpha map */
362953d7d37Smrg    if (allow_alpha_map && lcg_rand_n (3) == 0)
363953d7d37Smrg    {
364953d7d37Smrg	pixman_image_t *alpha_map;
365953d7d37Smrg	int16_t x, y;
366953d7d37Smrg
367953d7d37Smrg	alpha_map = create_random_bits_image ();
368953d7d37Smrg
369953d7d37Smrg	if (alpha_map)
370953d7d37Smrg	{
371953d7d37Smrg	    set_general_properties (alpha_map, FALSE);
372953d7d37Smrg
373953d7d37Smrg	    x = lcg_rand_N (100000) - 65536;
374953d7d37Smrg	    y = lcg_rand_N (100000) - 65536;
375953d7d37Smrg
376953d7d37Smrg	    pixman_image_set_alpha_map (image, alpha_map, x, y);
377953d7d37Smrg
378953d7d37Smrg	    pixman_image_unref (alpha_map);
379953d7d37Smrg	}
380953d7d37Smrg    }
381953d7d37Smrg
382953d7d37Smrg    /* Component alpha */
383953d7d37Smrg    pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0);
384953d7d37Smrg
385953d7d37Smrg    /* Clip region */
386953d7d37Smrg    if (lcg_rand_n (8) != 0)
387953d7d37Smrg    {
388953d7d37Smrg	pixman_region32_t region;
389953d7d37Smrg	int i, n_rects;
390953d7d37Smrg
391953d7d37Smrg	pixman_region32_init (&region);
392953d7d37Smrg
393953d7d37Smrg	switch (lcg_rand_n (10))
394953d7d37Smrg	{
395953d7d37Smrg	case 0:
396953d7d37Smrg	    n_rects = 0;
397953d7d37Smrg	    break;
398953d7d37Smrg
399953d7d37Smrg	case 1: case 2: case 3:
400953d7d37Smrg	    n_rects = 1;
401953d7d37Smrg	    break;
402953d7d37Smrg
403953d7d37Smrg	case 4: case 5:
404953d7d37Smrg	    n_rects = 2;
405953d7d37Smrg	    break;
406953d7d37Smrg
407953d7d37Smrg	case 6: case 7:
408953d7d37Smrg	    n_rects = 3;
409953d7d37Smrg
410953d7d37Smrg	default:
411953d7d37Smrg	    n_rects = lcg_rand_n (100);
412953d7d37Smrg	    break;
413953d7d37Smrg	}
414953d7d37Smrg
415953d7d37Smrg	for (i = 0; i < n_rects; ++i)
416953d7d37Smrg	{
417953d7d37Smrg	    uint32_t width, height;
418953d7d37Smrg	    int x, y;
419953d7d37Smrg
420953d7d37Smrg	    x = log_rand();
421953d7d37Smrg	    y = log_rand();
422953d7d37Smrg	    width = absolute (log_rand ()) + 1;
423953d7d37Smrg	    height = absolute (log_rand ()) + 1;
424953d7d37Smrg
425953d7d37Smrg	    pixman_region32_union_rect (
426953d7d37Smrg		&region, &region, x, y, width, height);
427953d7d37Smrg	}
428953d7d37Smrg
429953d7d37Smrg	pixman_image_set_clip_region32 (image, &region);
430953d7d37Smrg
431953d7d37Smrg	pixman_region32_fini (&region);
432953d7d37Smrg    }
433953d7d37Smrg
434953d7d37Smrg    /* Whether source clipping is enabled */
435953d7d37Smrg    pixman_image_set_source_clipping (image, !!lcg_rand_n (2));
436953d7d37Smrg
437953d7d37Smrg    /* Client clip */
438953d7d37Smrg    pixman_image_set_has_client_clip (image, !!lcg_rand_n (2));
439953d7d37Smrg
440953d7d37Smrg    /* Transform */
441953d7d37Smrg    if (lcg_rand_n (5) < 2)
442953d7d37Smrg    {
443953d7d37Smrg	pixman_transform_t xform;
444953d7d37Smrg	int i, j, k;
445953d7d37Smrg	uint32_t tx, ty, sx, sy;
446953d7d37Smrg	uint32_t c, s;
447953d7d37Smrg
448953d7d37Smrg	memset (&xform, 0, sizeof xform);
449953d7d37Smrg	xform.matrix[0][0] = pixman_fixed_1;
450953d7d37Smrg	xform.matrix[1][1] = pixman_fixed_1;
451953d7d37Smrg	xform.matrix[2][2] = pixman_fixed_1;
452953d7d37Smrg
453953d7d37Smrg	for (k = 0; k < 3; ++k)
454953d7d37Smrg	{
455953d7d37Smrg	    switch (lcg_rand_n (4))
456953d7d37Smrg	    {
457953d7d37Smrg	    case 0:
458953d7d37Smrg		/* rotation */
459953d7d37Smrg		c = lcg_rand_N (2 * 65536) - 65536;
460953d7d37Smrg		s = lcg_rand_N (2 * 65536) - 65536;
461953d7d37Smrg		pixman_transform_rotate (&xform, NULL, c, s);
462953d7d37Smrg		break;
463953d7d37Smrg
464953d7d37Smrg	    case 1:
465953d7d37Smrg		/* translation */
466953d7d37Smrg		tx = lcg_rand_u32();
467953d7d37Smrg		ty = lcg_rand_u32();
468953d7d37Smrg		pixman_transform_translate (&xform, NULL, tx, ty);
469953d7d37Smrg		break;
470953d7d37Smrg
471953d7d37Smrg	    case 2:
472953d7d37Smrg		/* scale */
473953d7d37Smrg		sx = lcg_rand_u32();
474953d7d37Smrg		sy = lcg_rand_u32();
475953d7d37Smrg		pixman_transform_scale (&xform, NULL, sx, sy);
476953d7d37Smrg		break;
477953d7d37Smrg
478953d7d37Smrg	    case 3:
479953d7d37Smrg		if (lcg_rand_n (16) == 0)
480953d7d37Smrg		{
481953d7d37Smrg		    /* random */
482953d7d37Smrg		    for (i = 0; i < 3; ++i)
483953d7d37Smrg			for (j = 0; j < 3; ++j)
484953d7d37Smrg			    xform.matrix[i][j] = lcg_rand_u32();
485953d7d37Smrg		    break;
486953d7d37Smrg		}
487953d7d37Smrg		else if (lcg_rand_n (16) == 0)
488953d7d37Smrg		{
489953d7d37Smrg		    /* zero */
490953d7d37Smrg		    memset (&xform, 0, sizeof xform);
491953d7d37Smrg		}
492953d7d37Smrg		break;
493953d7d37Smrg	    }
494953d7d37Smrg	}
495953d7d37Smrg
496953d7d37Smrg	pixman_image_set_transform (image, &xform);
497953d7d37Smrg    }
498953d7d37Smrg}
499953d7d37Smrg
500953d7d37Smrgstatic pixman_color_t
501953d7d37Smrgrandom_color (void)
502953d7d37Smrg{
503953d7d37Smrg    pixman_color_t color =
504953d7d37Smrg    {
505953d7d37Smrg	lcg_rand() & 0xffff,
506953d7d37Smrg	lcg_rand() & 0xffff,
507953d7d37Smrg	lcg_rand() & 0xffff,
508953d7d37Smrg	lcg_rand() & 0xffff,
509953d7d37Smrg    };
510953d7d37Smrg
511953d7d37Smrg    return color;
512953d7d37Smrg}
513953d7d37Smrg
514953d7d37Smrg
515953d7d37Smrgstatic pixman_image_t *
516953d7d37Smrgcreate_random_solid_image (void)
517953d7d37Smrg{
518953d7d37Smrg    pixman_color_t color = random_color();
519953d7d37Smrg    pixman_image_t *image = pixman_image_create_solid_fill (&color);
520953d7d37Smrg
521953d7d37Smrg    return image;
522953d7d37Smrg}
523953d7d37Smrg
524953d7d37Smrgstatic pixman_gradient_stop_t *
525953d7d37Smrgcreate_random_stops (int *n_stops)
526953d7d37Smrg{
527953d7d37Smrg    pixman_fixed_t step;
528953d7d37Smrg    pixman_fixed_t s;
529953d7d37Smrg    int i;
530953d7d37Smrg    pixman_gradient_stop_t *stops;
531953d7d37Smrg
532953d7d37Smrg    *n_stops = lcg_rand_n (50) + 1;
533953d7d37Smrg
534953d7d37Smrg    step = pixman_fixed_1 / *n_stops;
535953d7d37Smrg
536953d7d37Smrg    stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t));
537953d7d37Smrg
538953d7d37Smrg    s = 0;
539953d7d37Smrg    for (i = 0; i < (*n_stops) - 1; ++i)
540953d7d37Smrg    {
541953d7d37Smrg	stops[i].x = s;
542953d7d37Smrg	stops[i].color = random_color();
543953d7d37Smrg
544953d7d37Smrg	s += step;
545953d7d37Smrg    }
546953d7d37Smrg
547953d7d37Smrg    stops[*n_stops - 1].x = pixman_fixed_1;
548953d7d37Smrg    stops[*n_stops - 1].color = random_color();
549953d7d37Smrg
550953d7d37Smrg    return stops;
551953d7d37Smrg}
552953d7d37Smrg
553953d7d37Smrgstatic pixman_point_fixed_t
554953d7d37Smrgcreate_random_point (void)
555953d7d37Smrg{
556953d7d37Smrg    pixman_point_fixed_t p;
557953d7d37Smrg
558953d7d37Smrg    p.x = log_rand ();
559953d7d37Smrg    p.y = log_rand ();
560953d7d37Smrg
561953d7d37Smrg    return p;
562953d7d37Smrg}
563953d7d37Smrg
564953d7d37Smrgstatic pixman_image_t *
565953d7d37Smrgcreate_random_linear_image (void)
566953d7d37Smrg{
567953d7d37Smrg    int n_stops;
568953d7d37Smrg    pixman_gradient_stop_t *stops;
569953d7d37Smrg    pixman_point_fixed_t p1, p2;
570953d7d37Smrg    pixman_image_t *result;
571953d7d37Smrg
572953d7d37Smrg    stops = create_random_stops (&n_stops);
573953d7d37Smrg    if (!stops)
574953d7d37Smrg	return NULL;
575953d7d37Smrg
576953d7d37Smrg    p1 = create_random_point ();
577953d7d37Smrg    p2 = create_random_point ();
578953d7d37Smrg
579953d7d37Smrg    result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops);
580953d7d37Smrg
581953d7d37Smrg    free (stops);
582953d7d37Smrg
583953d7d37Smrg    return result;
584953d7d37Smrg}
585953d7d37Smrg
586953d7d37Smrgstatic pixman_image_t *
587953d7d37Smrgcreate_random_radial_image (void)
588953d7d37Smrg{
589953d7d37Smrg    int n_stops;
590953d7d37Smrg    pixman_gradient_stop_t *stops;
591953d7d37Smrg    pixman_point_fixed_t inner_c, outer_c;
592953d7d37Smrg    pixman_fixed_t inner_r, outer_r;
593953d7d37Smrg    pixman_image_t *result;
594953d7d37Smrg
595953d7d37Smrg    inner_c = create_random_point();
596953d7d37Smrg    outer_c = create_random_point();
597953d7d37Smrg    inner_r = lcg_rand();
598953d7d37Smrg    outer_r = lcg_rand();
599953d7d37Smrg
600953d7d37Smrg    stops = create_random_stops (&n_stops);
601953d7d37Smrg
602953d7d37Smrg    if (!stops)
603953d7d37Smrg	return NULL;
604953d7d37Smrg
605953d7d37Smrg    result = pixman_image_create_radial_gradient (
606953d7d37Smrg	&inner_c, &outer_c, inner_r, outer_r, stops, n_stops);
607953d7d37Smrg
608953d7d37Smrg    free (stops);
609953d7d37Smrg
610953d7d37Smrg    return result;
611953d7d37Smrg}
612953d7d37Smrg
613953d7d37Smrgstatic pixman_image_t *
614953d7d37Smrgcreate_random_conical_image (void)
615953d7d37Smrg{
616953d7d37Smrg    pixman_gradient_stop_t *stops;
617953d7d37Smrg    int n_stops;
618953d7d37Smrg    pixman_point_fixed_t c;
619953d7d37Smrg    pixman_fixed_t angle;
620953d7d37Smrg    pixman_image_t *result;
621953d7d37Smrg
622953d7d37Smrg    c = create_random_point();
623953d7d37Smrg    angle = lcg_rand();
624953d7d37Smrg
625953d7d37Smrg    stops = create_random_stops (&n_stops);
626953d7d37Smrg
627953d7d37Smrg    if (!stops)
628953d7d37Smrg	return NULL;
629953d7d37Smrg
630953d7d37Smrg    result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops);
631953d7d37Smrg
632953d7d37Smrg    free (stops);
633953d7d37Smrg
634953d7d37Smrg    return result;
635953d7d37Smrg}
636953d7d37Smrg
637953d7d37Smrgstatic pixman_image_t *
638953d7d37Smrgcreate_random_image (void)
639953d7d37Smrg{
640953d7d37Smrg    pixman_image_t *result;
641953d7d37Smrg
642953d7d37Smrg    switch (lcg_rand_n (5))
643953d7d37Smrg    {
644953d7d37Smrg    default:
645953d7d37Smrg    case 0:
646953d7d37Smrg	result = create_random_bits_image ();
647953d7d37Smrg	break;
648953d7d37Smrg
649953d7d37Smrg    case 1:
650953d7d37Smrg	result = create_random_solid_image ();
651953d7d37Smrg	break;
652953d7d37Smrg
653953d7d37Smrg    case 2:
654953d7d37Smrg	result = create_random_linear_image ();
655953d7d37Smrg	break;
656953d7d37Smrg
657953d7d37Smrg    case 3:
658953d7d37Smrg	result = create_random_radial_image ();
659953d7d37Smrg	break;
660953d7d37Smrg
661953d7d37Smrg    case 4:
662953d7d37Smrg	result = create_random_conical_image ();
663953d7d37Smrg	break;
664953d7d37Smrg    }
665953d7d37Smrg
666953d7d37Smrg    if (result)
667953d7d37Smrg	set_general_properties (result, TRUE);
668953d7d37Smrg
669953d7d37Smrg    return result;
670953d7d37Smrg}
671953d7d37Smrg
672953d7d37Smrgstatic const pixman_op_t op_list[] =
673953d7d37Smrg{
674953d7d37Smrg    PIXMAN_OP_SRC,
675953d7d37Smrg    PIXMAN_OP_OVER,
676953d7d37Smrg    PIXMAN_OP_ADD,
677953d7d37Smrg    PIXMAN_OP_CLEAR,
678953d7d37Smrg    PIXMAN_OP_SRC,
679953d7d37Smrg    PIXMAN_OP_DST,
680953d7d37Smrg    PIXMAN_OP_OVER,
681953d7d37Smrg    PIXMAN_OP_OVER_REVERSE,
682953d7d37Smrg    PIXMAN_OP_IN,
683953d7d37Smrg    PIXMAN_OP_IN_REVERSE,
684953d7d37Smrg    PIXMAN_OP_OUT,
685953d7d37Smrg    PIXMAN_OP_OUT_REVERSE,
686953d7d37Smrg    PIXMAN_OP_ATOP,
687953d7d37Smrg    PIXMAN_OP_ATOP_REVERSE,
688953d7d37Smrg    PIXMAN_OP_XOR,
689953d7d37Smrg    PIXMAN_OP_ADD,
690953d7d37Smrg    PIXMAN_OP_SATURATE,
691953d7d37Smrg    PIXMAN_OP_DISJOINT_CLEAR,
692953d7d37Smrg    PIXMAN_OP_DISJOINT_SRC,
693953d7d37Smrg    PIXMAN_OP_DISJOINT_DST,
694953d7d37Smrg    PIXMAN_OP_DISJOINT_OVER,
695953d7d37Smrg    PIXMAN_OP_DISJOINT_OVER_REVERSE,
696953d7d37Smrg    PIXMAN_OP_DISJOINT_IN,
697953d7d37Smrg    PIXMAN_OP_DISJOINT_IN_REVERSE,
698953d7d37Smrg    PIXMAN_OP_DISJOINT_OUT,
699953d7d37Smrg    PIXMAN_OP_DISJOINT_OUT_REVERSE,
700953d7d37Smrg    PIXMAN_OP_DISJOINT_ATOP,
701953d7d37Smrg    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
702953d7d37Smrg    PIXMAN_OP_DISJOINT_XOR,
703953d7d37Smrg    PIXMAN_OP_CONJOINT_CLEAR,
704953d7d37Smrg    PIXMAN_OP_CONJOINT_SRC,
705953d7d37Smrg    PIXMAN_OP_CONJOINT_DST,
706953d7d37Smrg    PIXMAN_OP_CONJOINT_OVER,
707953d7d37Smrg    PIXMAN_OP_CONJOINT_OVER_REVERSE,
708953d7d37Smrg    PIXMAN_OP_CONJOINT_IN,
709953d7d37Smrg    PIXMAN_OP_CONJOINT_IN_REVERSE,
710953d7d37Smrg    PIXMAN_OP_CONJOINT_OUT,
711953d7d37Smrg    PIXMAN_OP_CONJOINT_OUT_REVERSE,
712953d7d37Smrg    PIXMAN_OP_CONJOINT_ATOP,
713953d7d37Smrg    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
714953d7d37Smrg    PIXMAN_OP_CONJOINT_XOR,
715953d7d37Smrg    PIXMAN_OP_MULTIPLY,
716953d7d37Smrg    PIXMAN_OP_SCREEN,
717953d7d37Smrg    PIXMAN_OP_OVERLAY,
718953d7d37Smrg    PIXMAN_OP_DARKEN,
719953d7d37Smrg    PIXMAN_OP_LIGHTEN,
720953d7d37Smrg    PIXMAN_OP_COLOR_DODGE,
721953d7d37Smrg    PIXMAN_OP_COLOR_BURN,
722953d7d37Smrg    PIXMAN_OP_HARD_LIGHT,
723953d7d37Smrg    PIXMAN_OP_DIFFERENCE,
724953d7d37Smrg    PIXMAN_OP_EXCLUSION,
725953d7d37Smrg    PIXMAN_OP_SOFT_LIGHT,
726953d7d37Smrg    PIXMAN_OP_HSL_HUE,
727953d7d37Smrg    PIXMAN_OP_HSL_SATURATION,
728953d7d37Smrg    PIXMAN_OP_HSL_COLOR,
729953d7d37Smrg    PIXMAN_OP_HSL_LUMINOSITY,
730953d7d37Smrg};
731953d7d37Smrg
732953d7d37Smrgstatic void
733953d7d37Smrgrun_test (uint32_t seed)
734953d7d37Smrg{
735953d7d37Smrg    pixman_image_t *source, *mask, *dest;
736953d7d37Smrg    pixman_op_t op;
737953d7d37Smrg
738953d7d37Smrg    lcg_srand (seed);
739953d7d37Smrg
740953d7d37Smrg    source = create_random_image ();
741953d7d37Smrg    mask   = create_random_image ();
742953d7d37Smrg    dest   = create_random_bits_image ();
743953d7d37Smrg
744953d7d37Smrg    if (source && mask && dest)
745953d7d37Smrg    {
746953d7d37Smrg	set_general_properties (dest, TRUE);
747953d7d37Smrg
748953d7d37Smrg	op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))];
749953d7d37Smrg
750953d7d37Smrg	pixman_image_composite32 (op,
751953d7d37Smrg				  source, mask, dest,
752953d7d37Smrg				  log_rand(), log_rand(),
753953d7d37Smrg				  log_rand(), log_rand(),
754953d7d37Smrg				  log_rand(), log_rand(),
755953d7d37Smrg				  absolute (log_rand()),
756953d7d37Smrg				  absolute (log_rand()));
757953d7d37Smrg    }
758953d7d37Smrg    if (source)
759953d7d37Smrg	pixman_image_unref (source);
760953d7d37Smrg    if (mask)
761953d7d37Smrg	pixman_image_unref (mask);
762953d7d37Smrg    if (dest)
763953d7d37Smrg	pixman_image_unref (dest);
764953d7d37Smrg}
765953d7d37Smrg
766953d7d37Smrgstatic pixman_bool_t
767953d7d37Smrgget_int (char *s, uint32_t *i)
768953d7d37Smrg{
769953d7d37Smrg    char *end;
770953d7d37Smrg    int p;
771953d7d37Smrg
772953d7d37Smrg    p = strtol (s, &end, 0);
773953d7d37Smrg
774953d7d37Smrg    if (end != s && *end == 0)
775953d7d37Smrg    {
776953d7d37Smrg	*i = p;
777953d7d37Smrg	return TRUE;
778953d7d37Smrg    }
779953d7d37Smrg
780953d7d37Smrg    return FALSE;
781953d7d37Smrg}
782953d7d37Smrg
783953d7d37Smrgint
784953d7d37Smrgmain (int argc, char **argv)
785953d7d37Smrg{
786953d7d37Smrg    int verbose = FALSE;
787953d7d37Smrg    uint32_t seed = 1;
788953d7d37Smrg    uint32_t n_tests = 0xffffffff;
789953d7d37Smrg    uint32_t mod = 0;
790953d7d37Smrg    uint32_t i;
791953d7d37Smrg
792953d7d37Smrg    pixman_disable_out_of_bounds_workaround ();
793953d7d37Smrg
794953d7d37Smrg    enable_fp_exceptions();
795953d7d37Smrg
796953d7d37Smrg    if (getenv ("VERBOSE") != NULL)
797953d7d37Smrg	verbose = TRUE;
798953d7d37Smrg
799953d7d37Smrg    for (i = 1; i < argc; ++i)
800953d7d37Smrg    {
801953d7d37Smrg	if (strcmp (argv[i], "-v") == 0)
802953d7d37Smrg	{
803953d7d37Smrg	    verbose = TRUE;
804953d7d37Smrg
805953d7d37Smrg	    if (i + 1 < argc)
806953d7d37Smrg	    {
807953d7d37Smrg		get_int (argv[i + 1], &mod);
808953d7d37Smrg		i++;
809953d7d37Smrg	    }
810953d7d37Smrg	}
811953d7d37Smrg	else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc)
812953d7d37Smrg	{
813953d7d37Smrg	    get_int (argv[i + 1], &seed);
814953d7d37Smrg	    i++;
815953d7d37Smrg	}
816953d7d37Smrg	else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc)
817953d7d37Smrg	{
818953d7d37Smrg	    get_int (argv[i + 1], &n_tests);
819953d7d37Smrg	    i++;
820953d7d37Smrg	}
821953d7d37Smrg	else
822953d7d37Smrg	{
823953d7d37Smrg	    if (strcmp (argv[i], "-h") != 0)
824953d7d37Smrg		printf ("Unknown option '%s'\n\n", argv[i]);
825953d7d37Smrg
826953d7d37Smrg	    printf ("Options:\n\n"
827953d7d37Smrg		    "-n <number>        Number of tests to run\n"
828953d7d37Smrg		    "-s <seed> 	        Seed of first test\n"
829953d7d37Smrg		    "-v                 Print out seeds\n"
830953d7d37Smrg		    "-v <n>             Print out every n'th seed\n\n");
831953d7d37Smrg
832953d7d37Smrg	    exit (-1);
833953d7d37Smrg	}
834953d7d37Smrg    }
835953d7d37Smrg
836953d7d37Smrg    if (n_tests == 0xffffffff)
837953d7d37Smrg	n_tests = 8000;
838953d7d37Smrg
839953d7d37Smrg    /* FIXME: seed 2005763 fails in set_lum() with divide by zero */
840953d7d37Smrg#ifdef USE_OPENMP
841953d7d37Smrg#   pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed)
842953d7d37Smrg#endif
843953d7d37Smrg    for (i = seed; i < seed + n_tests; ++i)
844953d7d37Smrg    {
845953d7d37Smrg	if (verbose)
846953d7d37Smrg	{
847953d7d37Smrg	    if (mod == 0 || (i % mod) == 0)
848953d7d37Smrg		printf ("Seed %d\n", i);
849953d7d37Smrg	}
850953d7d37Smrg
851953d7d37Smrg	run_test (i);
852953d7d37Smrg    }
853953d7d37Smrg
854953d7d37Smrg    return 0;
855953d7d37Smrg}
856