glyph-test.c revision 9ad247e8
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[lcg_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) && lcg_rand_n (4) == 0) 126 { 127 pixman_color_t color; 128 129 color.alpha = lcg_rand_u32(); 130 color.red = lcg_rand_u32(); 131 color.green = lcg_rand_u32(); 132 color.blue = lcg_rand_u32(); 133 134 return pixman_image_create_solid_fill (&color); 135 } 136 137 width = lcg_rand_n (max_size) + 1; 138 height = lcg_rand_n (max_size) + 1; 139 format = random_format (formats); 140 141 bpp = PIXMAN_FORMAT_BPP (format); 142 stride = (width * bpp + 7) / 8 + lcg_rand_n (17); 143 stride = (stride + 3) & ~3; 144 145 if (lcg_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 uint8_t *d8; 157 158 data = malloc (stride * height); 159 160 d8 = (uint8_t *)data; 161 for (i = 0; i < height * stride; ++i) 162 d8[i] = lcg_rand_n (256); 163 164 destroy = destroy_malloced; 165 } 166 167 image = pixman_image_create_bits (format, width, height, data, stride); 168 pixman_image_set_destroy_function (image, destroy, data); 169 170 if ((flags & ALLOW_CLIPPED) && lcg_rand_n (8) == 0) 171 { 172 pixman_box16_t clip_boxes[8]; 173 pixman_region16_t clip; 174 int n = lcg_rand_n (8) + 1; 175 176 for (i = 0; i < n; i++) 177 { 178 clip_boxes[i].x1 = lcg_rand_n (width); 179 clip_boxes[i].y1 = lcg_rand_n (height); 180 clip_boxes[i].x2 = 181 clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1); 182 clip_boxes[i].y2 = 183 clip_boxes[i].y1 + lcg_rand_n (height - clip_boxes[i].y1); 184 } 185 186 pixman_region_init_rects (&clip, clip_boxes, n); 187 pixman_image_set_clip_region (image, &clip); 188 pixman_region_fini (&clip); 189 } 190 191 if ((flags & ALLOW_SOURCE_CLIPPING) && lcg_rand_n (4) == 0) 192 { 193 pixman_image_set_source_clipping (image, TRUE); 194 pixman_image_set_has_client_clip (image, TRUE); 195 } 196 197 if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0) 198 { 199 pixman_image_t *alpha_map; 200 int alpha_x, alpha_y; 201 202 alpha_x = lcg_rand_n (width); 203 alpha_y = lcg_rand_n (height); 204 alpha_map = 205 create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID))); 206 pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y); 207 pixman_image_unref (alpha_map); 208 } 209 210 if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0) 211 pixman_image_set_repeat (image, lcg_rand_n (4)); 212 213 image_endian_swap (image); 214 215 return image; 216} 217 218#define KEY1(p) ((void *)(((unsigned long)p) ^ (0xa7e23dfaUL))) 219#define KEY2(p) ((void *)(((unsigned long)p) ^ (0xabcd9876UL))) 220 221#define MAX_GLYPHS 32 222 223uint32_t 224test_glyphs (int testnum, int verbose) 225{ 226 pixman_image_t *glyph_images[MAX_GLYPHS]; 227 pixman_glyph_t glyphs[4 * MAX_GLYPHS]; 228 uint32_t crc32 = 0; 229 pixman_image_t *source, *dest; 230 int n_glyphs, i; 231 pixman_glyph_cache_t *cache; 232 233 lcg_srand (testnum); 234 235 cache = pixman_glyph_cache_create (); 236 237 source = create_image (300, formats, 238 ALLOW_CLIPPED | ALLOW_ALPHA_MAP | 239 ALLOW_SOURCE_CLIPPING | 240 ALLOW_REPEAT | ALLOW_SOLID); 241 242 dest = create_image (128, formats, 243 ALLOW_CLIPPED | ALLOW_ALPHA_MAP | 244 ALLOW_SOURCE_CLIPPING); 245 246 pixman_glyph_cache_freeze (cache); 247 248 n_glyphs = lcg_rand_n (MAX_GLYPHS); 249 for (i = 0; i < n_glyphs; ++i) 250 glyph_images[i] = create_image (32, glyph_formats, 0); 251 252 for (i = 0; i < 4 * n_glyphs; ++i) 253 { 254 int g = lcg_rand_n (n_glyphs); 255 pixman_image_t *glyph_img = glyph_images[g]; 256 void *key1 = KEY1 (glyph_img); 257 void *key2 = KEY2 (glyph_img); 258 const void *glyph; 259 260 if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2))) 261 { 262 glyph = 263 pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img); 264 } 265 266 glyphs[i].glyph = glyph; 267 glyphs[i].x = lcg_rand_n (128); 268 glyphs[i].y = lcg_rand_n (128); 269 } 270 271 if (lcg_rand_n (2) == 0) 272 { 273 int src_x = lcg_rand_n (300) - 150; 274 int src_y = lcg_rand_n (300) - 150; 275 int mask_x = lcg_rand_n (64) - 32; 276 int mask_y = lcg_rand_n (64) - 32; 277 int dest_x = lcg_rand_n (64) - 32; 278 int dest_y = lcg_rand_n (64) - 32; 279 int width = lcg_rand_n (64); 280 int height = lcg_rand_n (64); 281 pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; 282 pixman_format_code_t format = random_format (glyph_formats); 283 284 pixman_composite_glyphs ( 285 op, 286 source, dest, format, 287 src_x, src_y, 288 mask_x, mask_y, 289 dest_x, dest_y, 290 width, height, 291 cache, 4 * n_glyphs, glyphs); 292 } 293 else 294 { 295 pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; 296 int src_x = lcg_rand_n (300) - 150; 297 int src_y = lcg_rand_n (300) - 150; 298 int dest_x = lcg_rand_n (64) - 32; 299 int dest_y = lcg_rand_n (64) - 32; 300 301 pixman_composite_glyphs_no_mask ( 302 op, source, dest, 303 src_x, src_y, 304 dest_x, dest_y, 305 cache, 4 * n_glyphs, glyphs); 306 } 307 308 pixman_glyph_cache_thaw (cache); 309 310 for (i = 0; i < n_glyphs; ++i) 311 { 312 pixman_image_t *img = glyph_images[i]; 313 void *key1, *key2; 314 315 key1 = KEY1 (img); 316 key2 = KEY2 (img); 317 318 pixman_glyph_cache_remove (cache, key1, key2); 319 pixman_image_unref (glyph_images[i]); 320 } 321 322 crc32 = compute_crc32_for_image (0, dest); 323 324 pixman_image_unref (source); 325 pixman_image_unref (dest); 326 327 pixman_glyph_cache_destroy (cache); 328 329 return crc32; 330} 331 332int 333main (int argc, const char *argv[]) 334{ 335 return fuzzer_test_main ("glyph", 30000, 336 0x79E74996, 337 test_glyphs, argc, argv); 338} 339