1a450e446Smrg/*
2a450e446Smrg * Test program, which stresses the use of different color formats and
3a450e446Smrg * compositing operations.
4a450e446Smrg *
51b18d63aSmrg * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in
61b18d63aSmrg * the case of test failure.
7a450e446Smrg */
8a450e446Smrg#include <stdlib.h>
9a450e446Smrg#include <stdio.h>
10952204abSmrg#include "utils.h"
11a450e446Smrg
121b18d63aSmrgstatic pixman_indexed_t rgb_palette[9];
131b18d63aSmrgstatic pixman_indexed_t y_palette[9];
14a450e446Smrg
156ba797d6Smrg/* The first eight format in the list are by far the most widely
166ba797d6Smrg * used formats, so we test those more than the others
176ba797d6Smrg */
186ba797d6Smrg#define N_MOST_LIKELY_FORMATS 8
196ba797d6Smrg
20a450e446Smrg/* Create random image for testing purposes */
21a450e446Smrgstatic pixman_image_t *
22a450e446Smrgcreate_random_image (pixman_format_code_t *allowed_formats,
23a450e446Smrg		     int                   max_width,
24a450e446Smrg		     int                   max_height,
25a450e446Smrg		     int                   max_extra_stride,
26a450e446Smrg		     pixman_format_code_t *used_fmt)
27a450e446Smrg{
28f4f78bb6Smrg    int n = 0, width, height, stride;
29a450e446Smrg    pixman_format_code_t fmt;
30a450e446Smrg    uint32_t *buf;
31a450e446Smrg    pixman_image_t *img;
32a450e446Smrg
336ba797d6Smrg    while (allowed_formats[n] != PIXMAN_null)
34a450e446Smrg	n++;
356ba797d6Smrg
36f4f78bb6Smrg    if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0)
376ba797d6Smrg	n = N_MOST_LIKELY_FORMATS;
38f4f78bb6Smrg    fmt = allowed_formats[prng_rand_n (n)];
39952204abSmrg
40f4f78bb6Smrg    width = prng_rand_n (max_width) + 1;
41f4f78bb6Smrg    height = prng_rand_n (max_height) + 1;
42a450e446Smrg    stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 +
43f4f78bb6Smrg	prng_rand_n (max_extra_stride + 1);
44a450e446Smrg    stride = (stride + 3) & ~3;
45a450e446Smrg
46a450e446Smrg    /* do the allocation */
47a450e446Smrg    buf = aligned_malloc (64, stride * height);
48a450e446Smrg
49f4f78bb6Smrg    if (prng_rand_n (4) == 0)
50a450e446Smrg    {
51f4f78bb6Smrg	/* uniform distribution */
52f4f78bb6Smrg	prng_randmemset (buf, stride * height, 0);
53f4f78bb6Smrg    }
54f4f78bb6Smrg    else
55f4f78bb6Smrg    {
56f4f78bb6Smrg	/* significantly increased probability for 0x00 and 0xFF */
57f4f78bb6Smrg	prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF);
58a450e446Smrg    }
59a450e446Smrg
60de17ff4aSmrg    /* test negative stride */
61de17ff4aSmrg    if (prng_rand_n (4) == 0)
62de17ff4aSmrg    {
63de17ff4aSmrg	buf += (stride / 4) * (height - 1);
64de17ff4aSmrg	stride = - stride;
65de17ff4aSmrg    }
66de17ff4aSmrg
67a450e446Smrg    img = pixman_image_create_bits (fmt, width, height, buf, stride);
68a450e446Smrg
691b18d63aSmrg    if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR)
701b18d63aSmrg    {
711b18d63aSmrg	pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)]));
721b18d63aSmrg    }
731b18d63aSmrg    else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY)
74952204abSmrg    {
751b18d63aSmrg	pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)]));
76952204abSmrg    }
77952204abSmrg
78f4f78bb6Smrg    if (prng_rand_n (16) == 0)
799ad247e8Sjmcneill	pixman_image_set_filter (img, PIXMAN_FILTER_BILINEAR, NULL, 0);
809ad247e8Sjmcneill
816ba797d6Smrg    image_endian_swap (img);
82a450e446Smrg
83a450e446Smrg    if (used_fmt) *used_fmt = fmt;
84a450e446Smrg    return img;
85a450e446Smrg}
86a450e446Smrg
87a450e446Smrg/* Free random image, and optionally update crc32 based on its data */
88a450e446Smrgstatic uint32_t
89a450e446Smrgfree_random_image (uint32_t initcrc,
90a450e446Smrg		   pixman_image_t *img,
91a450e446Smrg		   pixman_format_code_t fmt)
92a450e446Smrg{
93a450e446Smrg    uint32_t crc32 = 0;
94a450e446Smrg    uint32_t *data = pixman_image_get_data (img);
95a450e446Smrg
966ba797d6Smrg    if (fmt != PIXMAN_null)
979ad247e8Sjmcneill	crc32 = compute_crc32_for_image (initcrc, img);
98a450e446Smrg
99de17ff4aSmrg    if (img->bits.rowstride < 0)
100de17ff4aSmrg	data += img->bits.rowstride * (img->bits.height - 1);
101de17ff4aSmrg
102a450e446Smrg    pixman_image_unref (img);
103a450e446Smrg    free (data);
104a450e446Smrg
105a450e446Smrg    return crc32;
106a450e446Smrg}
107a450e446Smrg
108a450e446Smrgstatic pixman_op_t op_list[] = {
109a450e446Smrg    PIXMAN_OP_SRC,
110a450e446Smrg    PIXMAN_OP_OVER,
111a450e446Smrg    PIXMAN_OP_ADD,
112a450e446Smrg    PIXMAN_OP_CLEAR,
113a450e446Smrg    PIXMAN_OP_SRC,
114a450e446Smrg    PIXMAN_OP_DST,
115a450e446Smrg    PIXMAN_OP_OVER,
116a450e446Smrg    PIXMAN_OP_OVER_REVERSE,
117a450e446Smrg    PIXMAN_OP_IN,
118a450e446Smrg    PIXMAN_OP_IN_REVERSE,
119a450e446Smrg    PIXMAN_OP_OUT,
120a450e446Smrg    PIXMAN_OP_OUT_REVERSE,
121a450e446Smrg    PIXMAN_OP_ATOP,
122a450e446Smrg    PIXMAN_OP_ATOP_REVERSE,
123a450e446Smrg    PIXMAN_OP_XOR,
124a450e446Smrg    PIXMAN_OP_ADD,
1256ca29ff0Smrg    PIXMAN_OP_MULTIPLY,
1266ca29ff0Smrg    PIXMAN_OP_SCREEN,
1276ca29ff0Smrg    PIXMAN_OP_OVERLAY,
1286ca29ff0Smrg    PIXMAN_OP_DARKEN,
1296ca29ff0Smrg    PIXMAN_OP_LIGHTEN,
1306ca29ff0Smrg    PIXMAN_OP_HARD_LIGHT,
1316ca29ff0Smrg    PIXMAN_OP_DIFFERENCE,
1326ca29ff0Smrg    PIXMAN_OP_EXCLUSION,
1336ca29ff0Smrg#if 0 /* these use floating point math and are not always bitexact on different platforms */
134a450e446Smrg    PIXMAN_OP_SATURATE,
135a450e446Smrg    PIXMAN_OP_DISJOINT_CLEAR,
136a450e446Smrg    PIXMAN_OP_DISJOINT_SRC,
137a450e446Smrg    PIXMAN_OP_DISJOINT_DST,
138a450e446Smrg    PIXMAN_OP_DISJOINT_OVER,
139a450e446Smrg    PIXMAN_OP_DISJOINT_OVER_REVERSE,
140a450e446Smrg    PIXMAN_OP_DISJOINT_IN,
141a450e446Smrg    PIXMAN_OP_DISJOINT_IN_REVERSE,
142a450e446Smrg    PIXMAN_OP_DISJOINT_OUT,
143a450e446Smrg    PIXMAN_OP_DISJOINT_OUT_REVERSE,
144a450e446Smrg    PIXMAN_OP_DISJOINT_ATOP,
145a450e446Smrg    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
146a450e446Smrg    PIXMAN_OP_DISJOINT_XOR,
147a450e446Smrg    PIXMAN_OP_CONJOINT_CLEAR,
148a450e446Smrg    PIXMAN_OP_CONJOINT_SRC,
149a450e446Smrg    PIXMAN_OP_CONJOINT_DST,
150a450e446Smrg    PIXMAN_OP_CONJOINT_OVER,
151a450e446Smrg    PIXMAN_OP_CONJOINT_OVER_REVERSE,
152a450e446Smrg    PIXMAN_OP_CONJOINT_IN,
153a450e446Smrg    PIXMAN_OP_CONJOINT_IN_REVERSE,
154a450e446Smrg    PIXMAN_OP_CONJOINT_OUT,
155a450e446Smrg    PIXMAN_OP_CONJOINT_OUT_REVERSE,
156a450e446Smrg    PIXMAN_OP_CONJOINT_ATOP,
157a450e446Smrg    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
158a450e446Smrg    PIXMAN_OP_CONJOINT_XOR,
159a450e446Smrg    PIXMAN_OP_COLOR_DODGE,
160a450e446Smrg    PIXMAN_OP_COLOR_BURN,
161a450e446Smrg    PIXMAN_OP_SOFT_LIGHT,
162a450e446Smrg    PIXMAN_OP_HSL_HUE,
163a450e446Smrg    PIXMAN_OP_HSL_SATURATION,
164a450e446Smrg    PIXMAN_OP_HSL_COLOR,
165a450e446Smrg    PIXMAN_OP_HSL_LUMINOSITY,
166a450e446Smrg#endif
167a450e446Smrg};
168a450e446Smrg
169a450e446Smrgstatic pixman_format_code_t img_fmt_list[] = {
170a450e446Smrg    PIXMAN_a8r8g8b8,
1716ba797d6Smrg    PIXMAN_a8b8g8r8,
172a450e446Smrg    PIXMAN_x8r8g8b8,
1736ba797d6Smrg    PIXMAN_x8b8g8r8,
174a450e446Smrg    PIXMAN_r5g6b5,
1756ba797d6Smrg    PIXMAN_b5g6r5,
176a450e446Smrg    PIXMAN_a8,
1776ba797d6Smrg    PIXMAN_a1,
1786ba797d6Smrg    PIXMAN_r3g3b2,
179a450e446Smrg    PIXMAN_b8g8r8a8,
180a450e446Smrg    PIXMAN_b8g8r8x8,
1816ba797d6Smrg    PIXMAN_r8g8b8a8,
1826ba797d6Smrg    PIXMAN_r8g8b8x8,
1831b18d63aSmrg    PIXMAN_x14r6g6b6,
184a450e446Smrg    PIXMAN_r8g8b8,
185a450e446Smrg    PIXMAN_b8g8r8,
1869ad247e8Sjmcneill#if 0 /* These are going to use floating point in the near future */
187a450e446Smrg    PIXMAN_x2r10g10b10,
188a450e446Smrg    PIXMAN_a2r10g10b10,
189a450e446Smrg    PIXMAN_x2b10g10r10,
190a450e446Smrg    PIXMAN_a2b10g10r10,
1919ad247e8Sjmcneill#endif
192a450e446Smrg    PIXMAN_a1r5g5b5,
193a450e446Smrg    PIXMAN_x1r5g5b5,
194a450e446Smrg    PIXMAN_a1b5g5r5,
195a450e446Smrg    PIXMAN_x1b5g5r5,
196a450e446Smrg    PIXMAN_a4r4g4b4,
197a450e446Smrg    PIXMAN_x4r4g4b4,
198a450e446Smrg    PIXMAN_a4b4g4r4,
199a450e446Smrg    PIXMAN_x4b4g4r4,
200a450e446Smrg    PIXMAN_r3g3b2,
201a450e446Smrg    PIXMAN_b2g3r3,
202a450e446Smrg    PIXMAN_a2r2g2b2,
203a450e446Smrg    PIXMAN_a2b2g2r2,
204a450e446Smrg    PIXMAN_c8,
205a450e446Smrg    PIXMAN_g8,
206a450e446Smrg    PIXMAN_x4c4,
207a450e446Smrg    PIXMAN_x4g4,
208a450e446Smrg    PIXMAN_c4,
209a450e446Smrg    PIXMAN_g4,
210a450e446Smrg    PIXMAN_g1,
211a450e446Smrg    PIXMAN_x4a4,
212a450e446Smrg    PIXMAN_a4,
213a450e446Smrg    PIXMAN_r1g2b1,
214a450e446Smrg    PIXMAN_b1g2r1,
215a450e446Smrg    PIXMAN_a1r1g1b1,
216a450e446Smrg    PIXMAN_a1b1g1r1,
2176ba797d6Smrg    PIXMAN_null
218a450e446Smrg};
219a450e446Smrg
220a450e446Smrgstatic pixman_format_code_t mask_fmt_list[] = {
221a450e446Smrg    PIXMAN_a8r8g8b8,
222a450e446Smrg    PIXMAN_a8,
223a450e446Smrg    PIXMAN_a4,
224a450e446Smrg    PIXMAN_a1,
2256ba797d6Smrg    PIXMAN_null
226a450e446Smrg};
227a450e446Smrg
228a450e446Smrg
229a450e446Smrg/*
230a450e446Smrg * Composite operation with pseudorandom images
231a450e446Smrg */
232a450e446Smrguint32_t
2331b18d63aSmrgtest_composite (int testnum, int verbose)
234a450e446Smrg{
235a450e446Smrg    pixman_image_t *src_img = NULL;
236a450e446Smrg    pixman_image_t *dst_img = NULL;
237a450e446Smrg    pixman_image_t *mask_img = NULL;
238a450e446Smrg    int src_width, src_height;
239a450e446Smrg    int dst_width, dst_height;
240a450e446Smrg    int src_stride, dst_stride;
241a450e446Smrg    int src_x, src_y;
242a450e446Smrg    int dst_x, dst_y;
243952204abSmrg    int mask_x, mask_y;
244a450e446Smrg    int w, h;
2456ba797d6Smrg    pixman_op_t op;
246a450e446Smrg    pixman_format_code_t src_fmt, dst_fmt, mask_fmt;
247de17ff4aSmrg    uint32_t *srcbuf, *maskbuf;
248a450e446Smrg    uint32_t crc32;
249a450e446Smrg    int max_width, max_height, max_extra_stride;
2501b18d63aSmrg    FLOAT_REGS_CORRUPTION_DETECTOR_START ();
251a450e446Smrg
252a450e446Smrg    max_width = max_height = 24 + testnum / 10000;
253a450e446Smrg    max_extra_stride = 4 + testnum / 1000000;
254a450e446Smrg
255a450e446Smrg    if (max_width > 256)
256a450e446Smrg	max_width = 256;
257a450e446Smrg
258a450e446Smrg    if (max_height > 16)
259a450e446Smrg	max_height = 16;
260a450e446Smrg
261a450e446Smrg    if (max_extra_stride > 8)
262a450e446Smrg	max_extra_stride = 8;
263a450e446Smrg
264f4f78bb6Smrg    prng_srand (testnum);
265a450e446Smrg
266f4f78bb6Smrg    op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))];
267a450e446Smrg
268f4f78bb6Smrg    if (prng_rand_n (8))
269a450e446Smrg    {
270a450e446Smrg	/* normal image */
271a450e446Smrg	src_img = create_random_image (img_fmt_list, max_width, max_height,
272a450e446Smrg				       max_extra_stride, &src_fmt);
273a450e446Smrg    }
274a450e446Smrg    else
275a450e446Smrg    {
276a450e446Smrg	/* solid case */
277a450e446Smrg	src_img = create_random_image (img_fmt_list, 1, 1,
278a450e446Smrg				       max_extra_stride, &src_fmt);
279a450e446Smrg
280a450e446Smrg	pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL);
281a450e446Smrg    }
282a450e446Smrg
283a450e446Smrg    dst_img = create_random_image (img_fmt_list, max_width, max_height,
284a450e446Smrg				   max_extra_stride, &dst_fmt);
285a450e446Smrg
286952204abSmrg    src_width = pixman_image_get_width (src_img);
287952204abSmrg    src_height = pixman_image_get_height (src_img);
288952204abSmrg    src_stride = pixman_image_get_stride (src_img);
289952204abSmrg
290952204abSmrg    dst_width = pixman_image_get_width (dst_img);
291952204abSmrg    dst_height = pixman_image_get_height (dst_img);
292952204abSmrg    dst_stride = pixman_image_get_stride (dst_img);
293952204abSmrg
294952204abSmrg    srcbuf = pixman_image_get_data (src_img);
295952204abSmrg
296f4f78bb6Smrg    src_x = prng_rand_n (src_width);
297f4f78bb6Smrg    src_y = prng_rand_n (src_height);
298f4f78bb6Smrg    dst_x = prng_rand_n (dst_width);
299f4f78bb6Smrg    dst_y = prng_rand_n (dst_height);
300952204abSmrg
301a450e446Smrg    mask_img = NULL;
3026ba797d6Smrg    mask_fmt = PIXMAN_null;
303952204abSmrg    mask_x = 0;
304952204abSmrg    mask_y = 0;
305952204abSmrg    maskbuf = NULL;
306a450e446Smrg
307952204abSmrg    if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) &&
308f4f78bb6Smrg	(prng_rand_n (4) == 0))
309952204abSmrg    {
310952204abSmrg	/* PIXBUF */
311f4f78bb6Smrg	mask_fmt = prng_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8;
312952204abSmrg	mask_img = pixman_image_create_bits (mask_fmt,
313952204abSmrg	                                     src_width,
314952204abSmrg	                                     src_height,
315952204abSmrg	                                     srcbuf,
316952204abSmrg	                                     src_stride);
317952204abSmrg	mask_x = src_x;
318952204abSmrg	mask_y = src_y;
319952204abSmrg	maskbuf = srcbuf;
320952204abSmrg    }
321f4f78bb6Smrg    else if (prng_rand_n (2))
322a450e446Smrg    {
323f4f78bb6Smrg	if (prng_rand_n (2))
324a450e446Smrg	{
325a450e446Smrg	    mask_img = create_random_image (mask_fmt_list, max_width, max_height,
326a450e446Smrg					   max_extra_stride, &mask_fmt);
327a450e446Smrg	}
328a450e446Smrg	else
329a450e446Smrg	{
330a450e446Smrg	    /* solid case */
331a450e446Smrg	    mask_img = create_random_image (mask_fmt_list, 1, 1,
332a450e446Smrg					   max_extra_stride, &mask_fmt);
333a450e446Smrg	    pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL);
334a450e446Smrg	}
335a450e446Smrg
336f4f78bb6Smrg	if (prng_rand_n (2))
337a450e446Smrg	    pixman_image_set_component_alpha (mask_img, 1);
338a450e446Smrg
339f4f78bb6Smrg	mask_x = prng_rand_n (pixman_image_get_width (mask_img));
340f4f78bb6Smrg	mask_y = prng_rand_n (pixman_image_get_height (mask_img));
341952204abSmrg    }
342a450e446Smrg
343a450e446Smrg
344f4f78bb6Smrg    w = prng_rand_n (dst_width - dst_x + 1);
345f4f78bb6Smrg    h = prng_rand_n (dst_height - dst_y + 1);
346a450e446Smrg
347a450e446Smrg    if (verbose)
348a450e446Smrg    {
349f4f78bb6Smrg        printf ("op=%s\n", operator_name (op));
350f4f78bb6Smrg	printf ("src_fmt=%s, dst_fmt=%s, mask_fmt=%s\n",
351f4f78bb6Smrg	    format_name (src_fmt), format_name (dst_fmt),
352f4f78bb6Smrg	    format_name (mask_fmt));
353a450e446Smrg	printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n",
354a450e446Smrg	    src_width, src_height, dst_width, dst_height);
355a450e446Smrg	printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n",
356a450e446Smrg	    src_x, src_y, dst_x, dst_y);
357a450e446Smrg	printf ("src_stride=%d, dst_stride=%d\n",
358a450e446Smrg	    src_stride, dst_stride);
359a450e446Smrg	printf ("w=%d, h=%d\n", w, h);
360a450e446Smrg    }
361a450e446Smrg
362a450e446Smrg    pixman_image_composite (op, src_img, mask_img, dst_img,
363952204abSmrg			    src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h);
364a450e446Smrg
365a450e446Smrg    if (verbose)
366de17ff4aSmrg	print_image (dst_img);
367a450e446Smrg
3686ba797d6Smrg    free_random_image (0, src_img, PIXMAN_null);
3691b18d63aSmrg    crc32 = free_random_image (0, dst_img, dst_fmt);
370a450e446Smrg
371a450e446Smrg    if (mask_img)
372952204abSmrg    {
373952204abSmrg	if (srcbuf == maskbuf)
374952204abSmrg	    pixman_image_unref(mask_img);
375952204abSmrg	else
3766ba797d6Smrg	    free_random_image (0, mask_img, PIXMAN_null);
377952204abSmrg    }
378952204abSmrg
3791b18d63aSmrg    FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
380a450e446Smrg    return crc32;
381a450e446Smrg}
382a450e446Smrg
3831b18d63aSmrgint
3841b18d63aSmrgmain (int argc, const char *argv[])
3851b18d63aSmrg{
3861b18d63aSmrg    int i;
387a450e446Smrg
388f4f78bb6Smrg    prng_srand (0);
389f4f78bb6Smrg
3901b18d63aSmrg    for (i = 1; i <= 8; i++)
3911b18d63aSmrg    {
392953d7d37Smrg	initialize_palette (&(rgb_palette[i]), i, TRUE);
393953d7d37Smrg	initialize_palette (&(y_palette[i]), i, FALSE);
394a450e446Smrg    }
3951b18d63aSmrg
3961b18d63aSmrg    return fuzzer_test_main("blitters", 2000000,
3976ca29ff0Smrg			    0xCC21DDF0,
3981b18d63aSmrg			    test_composite, argc, argv);
399a450e446Smrg}
400