19ad247e8Sjmcneill#include <stdlib.h>
29ad247e8Sjmcneill#include "utils.h"
39ad247e8Sjmcneill
49ad247e8Sjmcneillstatic const pixman_format_code_t glyph_formats[] =
59ad247e8Sjmcneill{
69ad247e8Sjmcneill    PIXMAN_a8r8g8b8,
79ad247e8Sjmcneill    PIXMAN_a8,
89ad247e8Sjmcneill    PIXMAN_a4,
99ad247e8Sjmcneill    PIXMAN_a1,
109ad247e8Sjmcneill    PIXMAN_x8r8g8b8,
119ad247e8Sjmcneill    PIXMAN_r3g3b2,
129ad247e8Sjmcneill    PIXMAN_null,
139ad247e8Sjmcneill};
149ad247e8Sjmcneill
159ad247e8Sjmcneillstatic const pixman_format_code_t formats[] =
169ad247e8Sjmcneill{
179ad247e8Sjmcneill    PIXMAN_a8r8g8b8,
189ad247e8Sjmcneill    PIXMAN_a8b8g8r8,
199ad247e8Sjmcneill    PIXMAN_x8r8g8b8,
209ad247e8Sjmcneill    PIXMAN_x8b8g8r8,
219ad247e8Sjmcneill    PIXMAN_r5g6b5,
229ad247e8Sjmcneill    PIXMAN_b5g6r5,
239ad247e8Sjmcneill    PIXMAN_a8,
249ad247e8Sjmcneill    PIXMAN_a1,
259ad247e8Sjmcneill    PIXMAN_r3g3b2,
269ad247e8Sjmcneill    PIXMAN_b8g8r8a8,
279ad247e8Sjmcneill    PIXMAN_b8g8r8x8,
289ad247e8Sjmcneill    PIXMAN_r8g8b8a8,
299ad247e8Sjmcneill    PIXMAN_r8g8b8x8,
309ad247e8Sjmcneill    PIXMAN_x14r6g6b6,
319ad247e8Sjmcneill    PIXMAN_r8g8b8,
329ad247e8Sjmcneill    PIXMAN_b8g8r8,
339ad247e8Sjmcneill#if 0
349ad247e8Sjmcneill    /* These use floating point */
359ad247e8Sjmcneill    PIXMAN_x2r10g10b10,
369ad247e8Sjmcneill    PIXMAN_a2r10g10b10,
379ad247e8Sjmcneill    PIXMAN_x2b10g10r10,
389ad247e8Sjmcneill    PIXMAN_a2b10g10r10,
399ad247e8Sjmcneill#endif
409ad247e8Sjmcneill    PIXMAN_a1r5g5b5,
419ad247e8Sjmcneill    PIXMAN_x1r5g5b5,
429ad247e8Sjmcneill    PIXMAN_a1b5g5r5,
439ad247e8Sjmcneill    PIXMAN_x1b5g5r5,
449ad247e8Sjmcneill    PIXMAN_a4r4g4b4,
459ad247e8Sjmcneill    PIXMAN_x4r4g4b4,
469ad247e8Sjmcneill    PIXMAN_a4b4g4r4,
479ad247e8Sjmcneill    PIXMAN_x4b4g4r4,
489ad247e8Sjmcneill    PIXMAN_r3g3b2,
499ad247e8Sjmcneill    PIXMAN_b2g3r3,
509ad247e8Sjmcneill    PIXMAN_a2r2g2b2,
519ad247e8Sjmcneill    PIXMAN_a2b2g2r2,
529ad247e8Sjmcneill    PIXMAN_x4a4,
539ad247e8Sjmcneill    PIXMAN_a4,
549ad247e8Sjmcneill    PIXMAN_r1g2b1,
559ad247e8Sjmcneill    PIXMAN_b1g2r1,
569ad247e8Sjmcneill    PIXMAN_a1r1g1b1,
579ad247e8Sjmcneill    PIXMAN_a1b1g1r1,
589ad247e8Sjmcneill    PIXMAN_null,
599ad247e8Sjmcneill};
609ad247e8Sjmcneill
619ad247e8Sjmcneillstatic const pixman_op_t operators[] =
629ad247e8Sjmcneill{
639ad247e8Sjmcneill    PIXMAN_OP_SRC,
649ad247e8Sjmcneill    PIXMAN_OP_OVER,
659ad247e8Sjmcneill    PIXMAN_OP_ADD,
669ad247e8Sjmcneill    PIXMAN_OP_CLEAR,
679ad247e8Sjmcneill    PIXMAN_OP_SRC,
689ad247e8Sjmcneill    PIXMAN_OP_DST,
699ad247e8Sjmcneill    PIXMAN_OP_OVER,
709ad247e8Sjmcneill    PIXMAN_OP_OVER_REVERSE,
719ad247e8Sjmcneill    PIXMAN_OP_IN,
729ad247e8Sjmcneill    PIXMAN_OP_IN_REVERSE,
739ad247e8Sjmcneill    PIXMAN_OP_OUT,
749ad247e8Sjmcneill    PIXMAN_OP_OUT_REVERSE,
759ad247e8Sjmcneill    PIXMAN_OP_ATOP,
769ad247e8Sjmcneill    PIXMAN_OP_ATOP_REVERSE,
779ad247e8Sjmcneill    PIXMAN_OP_XOR,
789ad247e8Sjmcneill    PIXMAN_OP_ADD
799ad247e8Sjmcneill};
809ad247e8Sjmcneill
819ad247e8Sjmcneillenum
829ad247e8Sjmcneill{
839ad247e8Sjmcneill    ALLOW_CLIPPED		= (1 << 0),
849ad247e8Sjmcneill    ALLOW_ALPHA_MAP		= (1 << 1),
859ad247e8Sjmcneill    ALLOW_SOURCE_CLIPPING	= (1 << 2),
869ad247e8Sjmcneill    ALLOW_REPEAT		= (1 << 3),
879ad247e8Sjmcneill    ALLOW_SOLID			= (1 << 4),
889ad247e8Sjmcneill    ALLOW_FENCED_MEMORY		= (1 << 5),
899ad247e8Sjmcneill};
909ad247e8Sjmcneill
919ad247e8Sjmcneillstatic void
929ad247e8Sjmcneilldestroy_fenced (pixman_image_t *image, void *data)
939ad247e8Sjmcneill{
949ad247e8Sjmcneill    fence_free (data);
959ad247e8Sjmcneill}
969ad247e8Sjmcneill
979ad247e8Sjmcneillstatic void
989ad247e8Sjmcneilldestroy_malloced (pixman_image_t *image, void *data)
999ad247e8Sjmcneill{
1009ad247e8Sjmcneill    free (data);
1019ad247e8Sjmcneill}
1029ad247e8Sjmcneill
1039ad247e8Sjmcneillstatic pixman_format_code_t
1049ad247e8Sjmcneillrandom_format (const pixman_format_code_t *formats)
1059ad247e8Sjmcneill{
1069ad247e8Sjmcneill    int i;
1079ad247e8Sjmcneill    i = 0;
1089ad247e8Sjmcneill    while (formats[i] != PIXMAN_null)
1099ad247e8Sjmcneill	++i;
110f4f78bb6Smrg    return formats[prng_rand_n (i)];
1119ad247e8Sjmcneill}
1129ad247e8Sjmcneill
1139ad247e8Sjmcneillstatic pixman_image_t *
1149ad247e8Sjmcneillcreate_image (int max_size, const pixman_format_code_t *formats, uint32_t flags)
1159ad247e8Sjmcneill{
1169ad247e8Sjmcneill    int width, height;
1179ad247e8Sjmcneill    pixman_image_t *image;
1189ad247e8Sjmcneill    pixman_format_code_t format;
1199ad247e8Sjmcneill    uint32_t *data;
1209ad247e8Sjmcneill    int bpp;
1219ad247e8Sjmcneill    int stride;
1229ad247e8Sjmcneill    int i;
1239ad247e8Sjmcneill    pixman_image_destroy_func_t destroy;
1249ad247e8Sjmcneill
125f4f78bb6Smrg    if ((flags & ALLOW_SOLID) && prng_rand_n (4) == 0)
1269ad247e8Sjmcneill    {
1279ad247e8Sjmcneill	pixman_color_t color;
1289ad247e8Sjmcneill
129f4f78bb6Smrg	color.alpha = prng_rand();
130f4f78bb6Smrg	color.red = prng_rand();
131f4f78bb6Smrg	color.green = prng_rand();
132f4f78bb6Smrg	color.blue = prng_rand();
1339ad247e8Sjmcneill
1349ad247e8Sjmcneill	return pixman_image_create_solid_fill (&color);
1359ad247e8Sjmcneill    }
1369ad247e8Sjmcneill
137f4f78bb6Smrg    width = prng_rand_n (max_size) + 1;
138f4f78bb6Smrg    height = prng_rand_n (max_size) + 1;
1399ad247e8Sjmcneill    format = random_format (formats);
1409ad247e8Sjmcneill
1419ad247e8Sjmcneill    bpp = PIXMAN_FORMAT_BPP (format);
142f4f78bb6Smrg    stride = (width * bpp + 7) / 8 + prng_rand_n (17);
1439ad247e8Sjmcneill    stride = (stride + 3) & ~3;
1449ad247e8Sjmcneill
145f4f78bb6Smrg    if (prng_rand_n (64) == 0)
1469ad247e8Sjmcneill    {
1479ad247e8Sjmcneill	if (!(data = (uint32_t *)make_random_bytes (stride * height)))
1489ad247e8Sjmcneill	{
1499ad247e8Sjmcneill	    fprintf (stderr, "Out of memory\n");
1509ad247e8Sjmcneill	    abort ();
1519ad247e8Sjmcneill	}
1529ad247e8Sjmcneill	destroy = destroy_fenced;
1539ad247e8Sjmcneill    }
1549ad247e8Sjmcneill    else
1559ad247e8Sjmcneill    {
1569ad247e8Sjmcneill	data = malloc (stride * height);
157f4f78bb6Smrg	prng_randmemset (data, height * stride, 0);
1589ad247e8Sjmcneill	destroy = destroy_malloced;
1599ad247e8Sjmcneill    }
1609ad247e8Sjmcneill
1619ad247e8Sjmcneill    image = pixman_image_create_bits (format, width, height, data, stride);
1629ad247e8Sjmcneill    pixman_image_set_destroy_function (image, destroy, data);
1639ad247e8Sjmcneill
164f4f78bb6Smrg    if ((flags & ALLOW_CLIPPED) && prng_rand_n (8) == 0)
1659ad247e8Sjmcneill    {
1669ad247e8Sjmcneill	pixman_box16_t clip_boxes[8];
1679ad247e8Sjmcneill	pixman_region16_t clip;
168f4f78bb6Smrg	int n = prng_rand_n (8) + 1;
1699ad247e8Sjmcneill
1709ad247e8Sjmcneill	for (i = 0; i < n; i++)
1719ad247e8Sjmcneill	{
172f4f78bb6Smrg	    clip_boxes[i].x1 = prng_rand_n (width);
173f4f78bb6Smrg	    clip_boxes[i].y1 = prng_rand_n (height);
1749ad247e8Sjmcneill	    clip_boxes[i].x2 =
175f4f78bb6Smrg		clip_boxes[i].x1 + prng_rand_n (width - clip_boxes[i].x1);
1769ad247e8Sjmcneill	    clip_boxes[i].y2 =
177f4f78bb6Smrg		clip_boxes[i].y1 + prng_rand_n (height - clip_boxes[i].y1);
1789ad247e8Sjmcneill	}
1799ad247e8Sjmcneill
1809ad247e8Sjmcneill	pixman_region_init_rects (&clip, clip_boxes, n);
1819ad247e8Sjmcneill	pixman_image_set_clip_region (image, &clip);
1829ad247e8Sjmcneill	pixman_region_fini (&clip);
1839ad247e8Sjmcneill    }
1849ad247e8Sjmcneill
185f4f78bb6Smrg    if ((flags & ALLOW_SOURCE_CLIPPING) && prng_rand_n (4) == 0)
1869ad247e8Sjmcneill    {
1879ad247e8Sjmcneill	pixman_image_set_source_clipping (image, TRUE);
1889ad247e8Sjmcneill	pixman_image_set_has_client_clip (image, TRUE);
1899ad247e8Sjmcneill    }
1909ad247e8Sjmcneill
191f4f78bb6Smrg    if ((flags & ALLOW_ALPHA_MAP) && prng_rand_n (16) == 0)
1929ad247e8Sjmcneill    {
1939ad247e8Sjmcneill	pixman_image_t *alpha_map;
1949ad247e8Sjmcneill	int alpha_x, alpha_y;
1959ad247e8Sjmcneill
196f4f78bb6Smrg	alpha_x = prng_rand_n (width);
197f4f78bb6Smrg	alpha_y = prng_rand_n (height);
1989ad247e8Sjmcneill	alpha_map =
1999ad247e8Sjmcneill	    create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID)));
2009ad247e8Sjmcneill	pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y);
2019ad247e8Sjmcneill	pixman_image_unref (alpha_map);
2029ad247e8Sjmcneill    }
2039ad247e8Sjmcneill
204f4f78bb6Smrg    if ((flags & ALLOW_REPEAT) && prng_rand_n (2) == 0)
205f4f78bb6Smrg	pixman_image_set_repeat (image, prng_rand_n (4));
2069ad247e8Sjmcneill
2079ad247e8Sjmcneill    image_endian_swap (image);
2089ad247e8Sjmcneill
2099ad247e8Sjmcneill    return image;
2109ad247e8Sjmcneill}
2119ad247e8Sjmcneill
212f4f78bb6Smrg#define KEY1(p) ((void *)(((uintptr_t)p) ^ (0xa7e23dfaUL)))
213f4f78bb6Smrg#define KEY2(p) ((void *)(((uintptr_t)p) ^ (0xabcd9876UL)))
2149ad247e8Sjmcneill
2159ad247e8Sjmcneill#define MAX_GLYPHS 32
2169ad247e8Sjmcneill
2179ad247e8Sjmcneilluint32_t
2189ad247e8Sjmcneilltest_glyphs (int testnum, int verbose)
2199ad247e8Sjmcneill{
2209ad247e8Sjmcneill    pixman_image_t *glyph_images[MAX_GLYPHS];
2219ad247e8Sjmcneill    pixman_glyph_t glyphs[4 * MAX_GLYPHS];
2229ad247e8Sjmcneill    uint32_t crc32 = 0;
2239ad247e8Sjmcneill    pixman_image_t *source, *dest;
2249ad247e8Sjmcneill    int n_glyphs, i;
2259ad247e8Sjmcneill    pixman_glyph_cache_t *cache;
2269ad247e8Sjmcneill
227f4f78bb6Smrg    prng_srand (testnum);
2289ad247e8Sjmcneill
2299ad247e8Sjmcneill    cache = pixman_glyph_cache_create ();
2309ad247e8Sjmcneill
2319ad247e8Sjmcneill    source = create_image (300, formats,
2329ad247e8Sjmcneill			   ALLOW_CLIPPED | ALLOW_ALPHA_MAP |
2339ad247e8Sjmcneill			   ALLOW_SOURCE_CLIPPING |
2349ad247e8Sjmcneill			   ALLOW_REPEAT | ALLOW_SOLID);
2359ad247e8Sjmcneill
2369ad247e8Sjmcneill    dest = create_image (128, formats,
2379ad247e8Sjmcneill			 ALLOW_CLIPPED | ALLOW_ALPHA_MAP |
2389ad247e8Sjmcneill			 ALLOW_SOURCE_CLIPPING);
2399ad247e8Sjmcneill
2409ad247e8Sjmcneill    pixman_glyph_cache_freeze (cache);
2419ad247e8Sjmcneill
242f4f78bb6Smrg    n_glyphs = prng_rand_n (MAX_GLYPHS);
2439ad247e8Sjmcneill    for (i = 0; i < n_glyphs; ++i)
2449ad247e8Sjmcneill	glyph_images[i] = create_image (32, glyph_formats, 0);
2459ad247e8Sjmcneill
2469ad247e8Sjmcneill    for (i = 0; i < 4 * n_glyphs; ++i)
2479ad247e8Sjmcneill    {
248f4f78bb6Smrg	int g = prng_rand_n (n_glyphs);
2499ad247e8Sjmcneill	pixman_image_t *glyph_img = glyph_images[g];
2509ad247e8Sjmcneill	void *key1 = KEY1 (glyph_img);
2519ad247e8Sjmcneill	void *key2 = KEY2 (glyph_img);
2529ad247e8Sjmcneill	const void *glyph;
2539ad247e8Sjmcneill
2549ad247e8Sjmcneill	if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2)))
2559ad247e8Sjmcneill	{
2569ad247e8Sjmcneill	    glyph =
2579ad247e8Sjmcneill		pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img);
2589ad247e8Sjmcneill	}
2599ad247e8Sjmcneill
2609ad247e8Sjmcneill	glyphs[i].glyph = glyph;
261f4f78bb6Smrg	glyphs[i].x = prng_rand_n (128);
262f4f78bb6Smrg	glyphs[i].y = prng_rand_n (128);
2639ad247e8Sjmcneill    }
2649ad247e8Sjmcneill
265f4f78bb6Smrg    if (prng_rand_n (2) == 0)
2669ad247e8Sjmcneill    {
267f4f78bb6Smrg	int src_x = prng_rand_n (300) - 150;
268f4f78bb6Smrg	int src_y = prng_rand_n (300) - 150;
269f4f78bb6Smrg	int mask_x = prng_rand_n (64) - 32;
270f4f78bb6Smrg	int mask_y = prng_rand_n (64) - 32;
271f4f78bb6Smrg	int dest_x = prng_rand_n (64) - 32;
272f4f78bb6Smrg	int dest_y = prng_rand_n (64) - 32;
273f4f78bb6Smrg	int width = prng_rand_n (64);
274f4f78bb6Smrg	int height = prng_rand_n (64);
275f4f78bb6Smrg	pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
2769ad247e8Sjmcneill	pixman_format_code_t format = random_format (glyph_formats);
2779ad247e8Sjmcneill
2789ad247e8Sjmcneill	pixman_composite_glyphs (
2799ad247e8Sjmcneill	    op,
2809ad247e8Sjmcneill	    source, dest, format,
2819ad247e8Sjmcneill	    src_x, src_y,
2829ad247e8Sjmcneill	    mask_x, mask_y,
2839ad247e8Sjmcneill	    dest_x, dest_y,
2849ad247e8Sjmcneill	    width, height,
2859ad247e8Sjmcneill	    cache, 4 * n_glyphs, glyphs);
2869ad247e8Sjmcneill    }
2879ad247e8Sjmcneill    else
2889ad247e8Sjmcneill    {
289f4f78bb6Smrg	pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))];
290f4f78bb6Smrg	int src_x = prng_rand_n (300) - 150;
291f4f78bb6Smrg	int src_y = prng_rand_n (300) - 150;
292f4f78bb6Smrg	int dest_x = prng_rand_n (64) - 32;
293f4f78bb6Smrg	int dest_y = prng_rand_n (64) - 32;
2949ad247e8Sjmcneill
2959ad247e8Sjmcneill	pixman_composite_glyphs_no_mask (
2969ad247e8Sjmcneill	    op, source, dest,
2979ad247e8Sjmcneill	    src_x, src_y,
2989ad247e8Sjmcneill	    dest_x, dest_y,
2999ad247e8Sjmcneill	    cache, 4 * n_glyphs, glyphs);
3009ad247e8Sjmcneill    }
3019ad247e8Sjmcneill
3029ad247e8Sjmcneill    pixman_glyph_cache_thaw (cache);
3039ad247e8Sjmcneill
3049ad247e8Sjmcneill    for (i = 0; i < n_glyphs; ++i)
3059ad247e8Sjmcneill    {
3069ad247e8Sjmcneill	pixman_image_t *img = glyph_images[i];
3079ad247e8Sjmcneill	void *key1, *key2;
3089ad247e8Sjmcneill
3099ad247e8Sjmcneill	key1 = KEY1 (img);
3109ad247e8Sjmcneill	key2 = KEY2 (img);
3119ad247e8Sjmcneill
3129ad247e8Sjmcneill	pixman_glyph_cache_remove (cache, key1, key2);
3139ad247e8Sjmcneill	pixman_image_unref (glyph_images[i]);
3149ad247e8Sjmcneill    }
3159ad247e8Sjmcneill
3169ad247e8Sjmcneill    crc32 = compute_crc32_for_image (0, dest);
3179ad247e8Sjmcneill
3189ad247e8Sjmcneill    pixman_image_unref (source);
3199ad247e8Sjmcneill    pixman_image_unref (dest);
3209ad247e8Sjmcneill
3219ad247e8Sjmcneill    pixman_glyph_cache_destroy (cache);
3229ad247e8Sjmcneill
3239ad247e8Sjmcneill    return crc32;
3249ad247e8Sjmcneill}
3259ad247e8Sjmcneill
3269ad247e8Sjmcneillint
3279ad247e8Sjmcneillmain (int argc, const char *argv[])
3289ad247e8Sjmcneill{
3299ad247e8Sjmcneill    return fuzzer_test_main ("glyph", 30000,
330f4f78bb6Smrg			     0xFA478A79,
3319ad247e8Sjmcneill			     test_glyphs, argc, argv);
3329ad247e8Sjmcneill}
333