Home | History | Annotate | Download | only in test
      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
     92 destroy_fenced (pixman_image_t *image, void *data)
     93 {
     94     fence_free (data);
     95 }
     96 
     97 static void
     98 destroy_malloced (pixman_image_t *image, void *data)
     99 {
    100     free (data);
    101 }
    102 
    103 static pixman_format_code_t
    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 *
    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
    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
    327 main (int argc, const char *argv[])
    328 {
    329     return fuzzer_test_main ("glyph", 30000,
    330 			     0xFA478A79,
    331 			     test_glyphs, argc, argv);
    332 }
    333