1 #include <stdlib.h>
2 #include "utils.h"
3 
4 static 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 
15 static 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 
61 static 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 
81 enum
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 
91 static void
destroy_fenced(pixman_image_t * image,void * data)92 destroy_fenced (pixman_image_t *image, void *data)
93 {
94     fence_free (data);
95 }
96 
97 static void
destroy_malloced(pixman_image_t * image,void * data)98 destroy_malloced (pixman_image_t *image, void *data)
99 {
100     free (data);
101 }
102 
103 static pixman_format_code_t
random_format(const pixman_format_code_t * formats)104 random_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 
113 static pixman_image_t *
create_image(int max_size,const pixman_format_code_t * formats,uint32_t flags)114 create_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 
217 uint32_t
test_glyphs(int testnum,int verbose)218 test_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 
326 int
main(int argc,const char * argv[])327 main (int argc, const char *argv[])
328 {
329     return fuzzer_test_main ("glyph", 30000,
330 			     0xFA478A79,
331 			     test_glyphs, argc, argv);
332 }
333