1/* Based loosely on scaling-test */
2
3#include <stdlib.h>
4#include <stdio.h>
5#include "utils.h"
6
7#define MAX_SRC_WIDTH  48
8#define MAX_SRC_HEIGHT 48
9#define MAX_DST_WIDTH  48
10#define MAX_DST_HEIGHT 48
11#define MAX_STRIDE     4
12
13static pixman_format_code_t formats[] =
14{
15    PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_r5g6b5, PIXMAN_a1, PIXMAN_a4
16};
17
18static pixman_format_code_t mask_formats[] =
19{
20    PIXMAN_a1, PIXMAN_a4, PIXMAN_a8,
21};
22
23static pixman_op_t operators[] =
24{
25    PIXMAN_OP_OVER, PIXMAN_OP_ADD, PIXMAN_OP_SRC, PIXMAN_OP_IN
26};
27
28#define RANDOM_ELT(array)						\
29    ((array)[prng_rand_n(ARRAY_LENGTH((array)))])
30
31static void
32destroy_bits (pixman_image_t *image, void *data)
33{
34    fence_free (data);
35}
36
37static pixman_fixed_t
38random_fixed (int n)
39{
40    return prng_rand_n (n << 16);
41}
42
43/*
44 * Composite operation with pseudorandom images
45 */
46uint32_t
47test_composite (int      testnum,
48		int      verbose)
49{
50    int                i;
51    pixman_image_t *   src_img;
52    pixman_image_t *   dst_img;
53    pixman_region16_t  clip;
54    int                dst_width, dst_height;
55    int                dst_stride;
56    int                dst_x, dst_y;
57    int                dst_bpp;
58    pixman_op_t        op;
59    uint32_t *         dst_bits;
60    uint32_t           crc32;
61    pixman_format_code_t mask_format, dst_format;
62    pixman_trapezoid_t *traps;
63    int src_x, src_y;
64    int n_traps;
65
66    static pixman_color_t colors[] =
67    {
68	{ 0xffff, 0xffff, 0xffff, 0xffff },
69	{ 0x0000, 0x0000, 0x0000, 0x0000 },
70	{ 0xabcd, 0xabcd, 0x0000, 0xabcd },
71	{ 0x0000, 0x0000, 0x0000, 0xffff },
72	{ 0x0101, 0x0101, 0x0101, 0x0101 },
73	{ 0x7777, 0x6666, 0x5555, 0x9999 },
74    };
75
76    FLOAT_REGS_CORRUPTION_DETECTOR_START ();
77
78    prng_srand (testnum);
79
80    op = RANDOM_ELT (operators);
81    mask_format = RANDOM_ELT (mask_formats);
82
83    /* Create source image */
84
85    if (prng_rand_n (4) == 0)
86    {
87	src_img = pixman_image_create_solid_fill (
88	    &(colors[prng_rand_n (ARRAY_LENGTH (colors))]));
89
90	src_x = 10;
91	src_y = 234;
92    }
93    else
94    {
95	pixman_format_code_t src_format = RANDOM_ELT(formats);
96	int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8;
97	int src_width = prng_rand_n (MAX_SRC_WIDTH) + 1;
98	int src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1;
99	int src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp;
100	uint32_t *bits;
101
102	src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2);
103	src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2);
104
105	src_stride = (src_stride + 3) & ~3;
106
107	bits = (uint32_t *)make_random_bytes (src_stride * src_height);
108
109	src_img = pixman_image_create_bits (
110	    src_format, src_width, src_height, bits, src_stride);
111
112	pixman_image_set_destroy_function (src_img, destroy_bits, bits);
113
114	if (prng_rand_n (8) == 0)
115	{
116	    pixman_box16_t clip_boxes[2];
117	    int            n = prng_rand_n (2) + 1;
118
119	    for (i = 0; i < n; i++)
120	    {
121		clip_boxes[i].x1 = prng_rand_n (src_width);
122		clip_boxes[i].y1 = prng_rand_n (src_height);
123		clip_boxes[i].x2 =
124		    clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1);
125		clip_boxes[i].y2 =
126		    clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1);
127
128		if (verbose)
129		{
130		    printf ("source clip box: [%d,%d-%d,%d]\n",
131			    clip_boxes[i].x1, clip_boxes[i].y1,
132			    clip_boxes[i].x2, clip_boxes[i].y2);
133		}
134	    }
135
136	    pixman_region_init_rects (&clip, clip_boxes, n);
137	    pixman_image_set_clip_region (src_img, &clip);
138	    pixman_image_set_source_clipping (src_img, 1);
139	    pixman_region_fini (&clip);
140	}
141
142	image_endian_swap (src_img);
143    }
144
145    /* Create destination image */
146    {
147	dst_format = RANDOM_ELT(formats);
148	dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8;
149	dst_width = prng_rand_n (MAX_DST_WIDTH) + 1;
150	dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1;
151	dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp;
152	dst_stride = (dst_stride + 3) & ~3;
153
154	dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height);
155
156	dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2);
157	dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2);
158
159	dst_img = pixman_image_create_bits (
160	    dst_format, dst_width, dst_height, dst_bits, dst_stride);
161
162	image_endian_swap (dst_img);
163    }
164
165    /* Create traps */
166    {
167	int i;
168
169	n_traps = prng_rand_n (25);
170	traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t));
171
172	for (i = 0; i < n_traps; ++i)
173	{
174	    pixman_trapezoid_t *t = &(traps[i]);
175
176	    t->top = random_fixed (MAX_DST_HEIGHT) - MAX_DST_HEIGHT / 2;
177	    t->bottom = t->top + random_fixed (MAX_DST_HEIGHT);
178	    t->left.p1.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
179	    t->left.p1.y = t->top - random_fixed (50);
180	    t->left.p2.x = random_fixed (MAX_DST_WIDTH) - MAX_DST_WIDTH / 2;
181	    t->left.p2.y = t->bottom + random_fixed (50);
182	    t->right.p1.x = t->left.p1.x + random_fixed (MAX_DST_WIDTH);
183	    t->right.p1.y = t->top - random_fixed (50);
184	    t->right.p2.x = t->left.p2.x + random_fixed (MAX_DST_WIDTH);
185	    t->right.p2.y = t->bottom - random_fixed (50);
186	}
187    }
188
189    if (prng_rand_n (8) == 0)
190    {
191	pixman_box16_t clip_boxes[2];
192	int            n = prng_rand_n (2) + 1;
193	for (i = 0; i < n; i++)
194	{
195	    clip_boxes[i].x1 = prng_rand_n (dst_width);
196	    clip_boxes[i].y1 = prng_rand_n (dst_height);
197	    clip_boxes[i].x2 =
198		clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1);
199	    clip_boxes[i].y2 =
200		clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1);
201
202	    if (verbose)
203	    {
204		printf ("destination clip box: [%d,%d-%d,%d]\n",
205		        clip_boxes[i].x1, clip_boxes[i].y1,
206		        clip_boxes[i].x2, clip_boxes[i].y2);
207	    }
208	}
209	pixman_region_init_rects (&clip, clip_boxes, n);
210	pixman_image_set_clip_region (dst_img, &clip);
211	pixman_region_fini (&clip);
212    }
213
214    pixman_composite_trapezoids (op, src_img, dst_img, mask_format,
215				 src_x, src_y, dst_x, dst_y, n_traps, traps);
216
217    if (dst_format == PIXMAN_x8r8g8b8)
218    {
219	/* ignore unused part */
220	for (i = 0; i < dst_stride * dst_height / 4; i++)
221	    dst_bits[i] &= 0xFFFFFF;
222    }
223
224    image_endian_swap (dst_img);
225
226    if (verbose)
227    {
228	int j;
229
230	for (i = 0; i < dst_height; i++)
231	{
232	    for (j = 0; j < dst_stride; j++)
233		printf ("%02X ", *((uint8_t *)dst_bits + i * dst_stride + j));
234
235	    printf ("\n");
236	}
237    }
238
239    crc32 = compute_crc32 (0, dst_bits, dst_stride * dst_height);
240
241    fence_free (dst_bits);
242
243    pixman_image_unref (src_img);
244    pixman_image_unref (dst_img);
245    fence_free (traps);
246
247    FLOAT_REGS_CORRUPTION_DETECTOR_FINISH ();
248    return crc32;
249}
250
251int
252main (int argc, const char *argv[])
253{
254    return fuzzer_test_main("composite traps", 40000, 0x749BCC57,
255			    test_composite, argc, argv);
256}
257