glyph-test.c revision 1176bdada62cabc6ec4b0308a930e83b679d5d36
1#include <stdlib.h>
2#include "utils.h"
3
4static const pixman_format_code_t glyph_formats[] =
5{
6    PIXMAN_a8r8g8b8,
7    PIXMAN_a8,
8    PIXMAN_a4,
9    PIXMAN_a1,
10    PIXMAN_x8r8g8b8,
11    PIXMAN_r3g3b2,
12    PIXMAN_null,
13};
14
15static const pixman_format_code_t formats[] =
16{
17    PIXMAN_a8r8g8b8,
18    PIXMAN_a8b8g8r8,
19    PIXMAN_x8r8g8b8,
20    PIXMAN_x8b8g8r8,
21    PIXMAN_r5g6b5,
22    PIXMAN_b5g6r5,
23    PIXMAN_a8,
24    PIXMAN_a1,
25    PIXMAN_r3g3b2,
26    PIXMAN_b8g8r8a8,
27    PIXMAN_b8g8r8x8,
28    PIXMAN_r8g8b8a8,
29    PIXMAN_r8g8b8x8,
30    PIXMAN_x14r6g6b6,
31    PIXMAN_r8g8b8,
32    PIXMAN_b8g8r8,
33#if 0
34    /* These use floating point */
35    PIXMAN_x2r10g10b10,
36    PIXMAN_a2r10g10b10,
37    PIXMAN_x2b10g10r10,
38    PIXMAN_a2b10g10r10,
39#endif
40    PIXMAN_a1r5g5b5,
41    PIXMAN_x1r5g5b5,
42    PIXMAN_a1b5g5r5,
43    PIXMAN_x1b5g5r5,
44    PIXMAN_a4r4g4b4,
45    PIXMAN_x4r4g4b4,
46    PIXMAN_a4b4g4r4,
47    PIXMAN_x4b4g4r4,
48    PIXMAN_r3g3b2,
49    PIXMAN_b2g3r3,
50    PIXMAN_a2r2g2b2,
51    PIXMAN_a2b2g2r2,
52    PIXMAN_x4a4,
53    PIXMAN_a4,
54    PIXMAN_r1g2b1,
55    PIXMAN_b1g2r1,
56    PIXMAN_a1r1g1b1,
57    PIXMAN_a1b1g1r1,
58    PIXMAN_null,
59};
60
61static const pixman_op_t operators[] =
62{
63    PIXMAN_OP_SRC,
64    PIXMAN_OP_OVER,
65    PIXMAN_OP_ADD,
66    PIXMAN_OP_CLEAR,
67    PIXMAN_OP_SRC,
68    PIXMAN_OP_DST,
69    PIXMAN_OP_OVER,
70    PIXMAN_OP_OVER_REVERSE,
71    PIXMAN_OP_IN,
72    PIXMAN_OP_IN_REVERSE,
73    PIXMAN_OP_OUT,
74    PIXMAN_OP_OUT_REVERSE,
75    PIXMAN_OP_ATOP,
76    PIXMAN_OP_ATOP_REVERSE,
77    PIXMAN_OP_XOR,
78    PIXMAN_OP_ADD
79};
80
81enum
82{
83    ALLOW_CLIPPED		= (1 << 0),
84    ALLOW_ALPHA_MAP		= (1 << 1),
85    ALLOW_SOURCE_CLIPPING	= (1 << 2),
86    ALLOW_REPEAT		= (1 << 3),
87    ALLOW_SOLID			= (1 << 4),
88    ALLOW_FENCED_MEMORY		= (1 << 5),
89};
90
91static void
92destroy_fenced (pixman_image_t *image, void *data)
93{
94    fence_free (data);
95}
96
97static void
98destroy_malloced (pixman_image_t *image, void *data)
99{
100    free (data);
101}
102
103static pixman_format_code_t
104random_format (const pixman_format_code_t *formats)
105{
106    int i;
107    i = 0;
108    while (formats[i] != PIXMAN_null)
109	++i;
110    return formats[prng_rand_n (i)];
111}
112
113static pixman_image_t *
114create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
115{
116    int width, height;
117    pixman_image_t *image;
118    pixman_format_code_t format;
119    uint32_t *data;
120    int bpp;
121    int stride;
122    int i;
123    pixman_image_destroy_func_t destroy;
124
125    if ((flags & ALLOW_SOLID) && prng_rand_n (4) == 0)
126    {
127	pixman_color_t color;
128
129	color.alpha = prng_rand();
130	color.red = prng_rand();
131	color.green = prng_rand();
132	color.blue = prng_rand();
133
134	return pixman_image_create_solid_fill (&color);
135    }
136
137    width = prng_rand_n (max_size) + 1;
138    height = prng_rand_n (max_size) + 1;
139    format = random_format (formats);
140
141    bpp = PIXMAN_FORMAT_BPP (format);
142    stride = (width * bpp + 7) / 8 + prng_rand_n (17);
143    stride = (stride + 3) & ~3;
144
145    if (prng_rand_n (64) == 0)
146    {
147	if (!(data = (uint32_t *)make_random_bytes (stride * height)))
148	{
149	    fprintf (stderr, "Out of memory\n");
150	    abort ();
151	}
152	destroy = destroy_fenced;
153    }
154    else
155    {
156	data = malloc (stride * height);
157	prng_randmemset (data, height * stride, 0);
158	destroy = destroy_malloced;
159    }
160
161    image = pixman_image_create_bits (format, width, height, data, stride);
162    pixman_image_set_destroy_function (image, destroy, data);
163
164    if ((flags & ALLOW_CLIPPED) && prng_rand_n (8) == 0)
165    {
166	pixman_box16_t clip_boxes[8];
167	pixman_region16_t clip;
168	int n = prng_rand_n (8) + 1;
169
170	for (i = 0; i < n; i++)
171	{
172	    clip_boxes[i].x1 = prng_rand_n (width);
173	    clip_boxes[i].y1 = prng_rand_n (height);
174	    clip_boxes[i].x2 =
175		clip_boxes[i].x1 + prng_rand_n (width - clip_boxes[i].x1);
176	    clip_boxes[i].y2 =
177		clip_boxes[i].y1 + prng_rand_n (height - clip_boxes[i].y1);
178	}
179
180	pixman_region_init_rects (&clip, clip_boxes, n);
181	pixman_image_set_clip_region (image, &clip);
182	pixman_region_fini (&clip);
183    }
184
185    if ((flags & ALLOW_SOURCE_CLIPPING) && prng_rand_n (4) == 0)
186    {
187	pixman_image_set_source_clipping (image, TRUE);
188	pixman_image_set_has_client_clip (image, TRUE);
189    }
190
191    if ((flags & ALLOW_ALPHA_MAP) && prng_rand_n (16) == 0)
192    {
193	pixman_image_t *alpha_map;
194	int alpha_x, alpha_y;
195
196	alpha_x = prng_rand_n (width);
197	alpha_y = prng_rand_n (height);
198	alpha_map =
199	    create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID)));
200	pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y);
201	pixman_image_unref (alpha_map);
202    }
203
204    if ((flags & ALLOW_REPEAT) && prng_rand_n (2) == 0)
205	pixman_image_set_repeat (image, prng_rand_n (4));
206
207    image_endian_swap (image);
208
209    return image;
210}
211
212#define KEY1(p) ((void *)(((uintptr_t)p) ^ (0xa7e23dfaUL)))
213#define KEY2(p) ((void *)(((uintptr_t)p) ^ (0xabcd9876UL)))
214
215#define MAX_GLYPHS 32
216
217uint32_t
218test_glyphs (int testnum, int verbose)
219{
220    pixman_image_t *glyph_images[MAX_GLYPHS];
221    pixman_glyph_t glyphs[4 * MAX_GLYPHS];
222    uint32_t crc32 = 0;
223    pixman_image_t *source, *dest;
224    int n_glyphs, i;
225    pixman_glyph_cache_t *cache;
226
227    prng_srand (testnum);
228
229    cache = pixman_glyph_cache_create ();
230
231    source = create_image (300, formats,
232			   ALLOW_CLIPPED | ALLOW_ALPHA_MAP |
233			   ALLOW_SOURCE_CLIPPING |
234			   ALLOW_REPEAT | ALLOW_SOLID);
235
236    dest = create_image (128, formats,
237			 ALLOW_CLIPPED | ALLOW_ALPHA_MAP |
238			 ALLOW_SOURCE_CLIPPING);
239
240    pixman_glyph_cache_freeze (cache);
241
242    n_glyphs = prng_rand_n (MAX_GLYPHS);
243    for (i = 0; i < n_glyphs; ++i)
244	glyph_images[i] = create_image (32, glyph_formats, 0);
245
246    for (i = 0; i < 4 * n_glyphs; ++i)
247    {
248	int g = prng_rand_n (n_glyphs);
249	pixman_image_t *glyph_img = glyph_images[g];
250	void *key1 = KEY1 (glyph_img);
251	void *key2 = KEY2 (glyph_img);
252	const void *glyph;
253
254	if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2)))
255	{
256	    glyph =
257		pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img);
258	}
259
260	glyphs[i].glyph = glyph;
261	glyphs[i].x = prng_rand_n (128);
262	glyphs[i].y = prng_rand_n (128);
263    }
264
265    if (prng_rand_n (2) == 0)
266    {
267	int src_x = prng_rand_n (300) - 150;
268	int src_y = prng_rand_n (300) - 150;
269	int mask_x = prng_rand_n (64) - 32;
270	int mask_y = prng_rand_n (64) - 32;
271	int dest_x = prng_rand_n (64) - 32;
272	int dest_y = prng_rand_n (64) - 32;
273	int width = prng_rand_n (64);
274	int height = prng_rand_n (64);
275	pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
276	pixman_format_code_t format = random_format (glyph_formats);
277
278	pixman_composite_glyphs (
279	    op,
280	    source, dest, format,
281	    src_x, src_y,
282	    mask_x, mask_y,
283	    dest_x, dest_y,
284	    width, height,
285	    cache, 4 * n_glyphs, glyphs);
286    }
287    else
288    {
289	pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
290	int src_x = prng_rand_n (300) - 150;
291	int src_y = prng_rand_n (300) - 150;
292	int dest_x = prng_rand_n (64) - 32;
293	int dest_y = prng_rand_n (64) - 32;
294
295	pixman_composite_glyphs_no_mask (
296	    op, source, dest,
297	    src_x, src_y,
298	    dest_x, dest_y,
299	    cache, 4 * n_glyphs, glyphs);
300    }
301
302    pixman_glyph_cache_thaw (cache);
303
304    for (i = 0; i < n_glyphs; ++i)
305    {
306	pixman_image_t *img = glyph_images[i];
307	void *key1, *key2;
308
309	key1 = KEY1 (img);
310	key2 = KEY2 (img);
311
312	pixman_glyph_cache_remove (cache, key1, key2);
313	pixman_image_unref (glyph_images[i]);
314    }
315
316    crc32 = compute_crc32_for_image (0, dest);
317
318    pixman_image_unref (source);
319    pixman_image_unref (dest);
320
321    pixman_glyph_cache_destroy (cache);
322
323    return crc32;
324}
325
326int
327main (int argc, const char *argv[])
328{
329    return fuzzer_test_main ("glyph", 30000,
330			     0xFA478A79,
331			     test_glyphs, argc, argv);
332}
333