diff options
Diffstat (limited to 'qemu/pixman/test/glyph-test.c')
-rw-r--r-- | qemu/pixman/test/glyph-test.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/qemu/pixman/test/glyph-test.c b/qemu/pixman/test/glyph-test.c new file mode 100644 index 000000000..1811add73 --- /dev/null +++ b/qemu/pixman/test/glyph-test.c @@ -0,0 +1,332 @@ +#include <stdlib.h> +#include "utils.h" + +static const pixman_format_code_t glyph_formats[] = +{ + PIXMAN_a8r8g8b8, + PIXMAN_a8, + PIXMAN_a4, + PIXMAN_a1, + PIXMAN_x8r8g8b8, + PIXMAN_r3g3b2, + PIXMAN_null, +}; + +static const pixman_format_code_t formats[] = +{ + PIXMAN_a8r8g8b8, + PIXMAN_a8b8g8r8, + PIXMAN_x8r8g8b8, + PIXMAN_x8b8g8r8, + PIXMAN_r5g6b5, + PIXMAN_b5g6r5, + PIXMAN_a8, + PIXMAN_a1, + PIXMAN_r3g3b2, + PIXMAN_b8g8r8a8, + PIXMAN_b8g8r8x8, + PIXMAN_r8g8b8a8, + PIXMAN_r8g8b8x8, + PIXMAN_x14r6g6b6, + PIXMAN_r8g8b8, + PIXMAN_b8g8r8, +#if 0 + /* These use floating point */ + PIXMAN_x2r10g10b10, + PIXMAN_a2r10g10b10, + PIXMAN_x2b10g10r10, + PIXMAN_a2b10g10r10, +#endif + PIXMAN_a1r5g5b5, + PIXMAN_x1r5g5b5, + PIXMAN_a1b5g5r5, + PIXMAN_x1b5g5r5, + PIXMAN_a4r4g4b4, + PIXMAN_x4r4g4b4, + PIXMAN_a4b4g4r4, + PIXMAN_x4b4g4r4, + PIXMAN_r3g3b2, + PIXMAN_b2g3r3, + PIXMAN_a2r2g2b2, + PIXMAN_a2b2g2r2, + PIXMAN_x4a4, + PIXMAN_a4, + PIXMAN_r1g2b1, + PIXMAN_b1g2r1, + PIXMAN_a1r1g1b1, + PIXMAN_a1b1g1r1, + PIXMAN_null, +}; + +static const pixman_op_t operators[] = +{ + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD +}; + +enum +{ + ALLOW_CLIPPED = (1 << 0), + ALLOW_ALPHA_MAP = (1 << 1), + ALLOW_SOURCE_CLIPPING = (1 << 2), + ALLOW_REPEAT = (1 << 3), + ALLOW_SOLID = (1 << 4), + ALLOW_FENCED_MEMORY = (1 << 5), +}; + +static void +destroy_fenced (pixman_image_t *image, void *data) +{ + fence_free (data); +} + +static void +destroy_malloced (pixman_image_t *image, void *data) +{ + free (data); +} + +static pixman_format_code_t +random_format (const pixman_format_code_t *formats) +{ + int i; + i = 0; + while (formats[i] != PIXMAN_null) + ++i; + return formats[prng_rand_n (i)]; +} + +static pixman_image_t * +create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags) +{ + int width, height; + pixman_image_t *image; + pixman_format_code_t format; + uint32_t *data; + int bpp; + int stride; + int i; + pixman_image_destroy_func_t destroy; + + if ((flags & ALLOW_SOLID) && prng_rand_n (4) == 0) + { + pixman_color_t color; + + color.alpha = prng_rand(); + color.red = prng_rand(); + color.green = prng_rand(); + color.blue = prng_rand(); + + return pixman_image_create_solid_fill (&color); + } + + width = prng_rand_n (max_size) + 1; + height = prng_rand_n (max_size) + 1; + format = random_format (formats); + + bpp = PIXMAN_FORMAT_BPP (format); + stride = (width * bpp + 7) / 8 + prng_rand_n (17); + stride = (stride + 3) & ~3; + + if (prng_rand_n (64) == 0) + { + if (!(data = (uint32_t *)make_random_bytes (stride * height))) + { + fprintf (stderr, "Out of memory\n"); + abort (); + } + destroy = destroy_fenced; + } + else + { + data = malloc (stride * height); + prng_randmemset (data, height * stride, 0); + destroy = destroy_malloced; + } + + image = pixman_image_create_bits (format, width, height, data, stride); + pixman_image_set_destroy_function (image, destroy, data); + + if ((flags & ALLOW_CLIPPED) && prng_rand_n (8) == 0) + { + pixman_box16_t clip_boxes[8]; + pixman_region16_t clip; + int n = prng_rand_n (8) + 1; + + for (i = 0; i < n; i++) + { + clip_boxes[i].x1 = prng_rand_n (width); + clip_boxes[i].y1 = prng_rand_n (height); + clip_boxes[i].x2 = + clip_boxes[i].x1 + prng_rand_n (width - clip_boxes[i].x1); + clip_boxes[i].y2 = + clip_boxes[i].y1 + prng_rand_n (height - clip_boxes[i].y1); + } + + pixman_region_init_rects (&clip, clip_boxes, n); + pixman_image_set_clip_region (image, &clip); + pixman_region_fini (&clip); + } + + if ((flags & ALLOW_SOURCE_CLIPPING) && prng_rand_n (4) == 0) + { + pixman_image_set_source_clipping (image, TRUE); + pixman_image_set_has_client_clip (image, TRUE); + } + + if ((flags & ALLOW_ALPHA_MAP) && prng_rand_n (16) == 0) + { + pixman_image_t *alpha_map; + int alpha_x, alpha_y; + + alpha_x = prng_rand_n (width); + alpha_y = prng_rand_n (height); + alpha_map = + create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID))); + pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y); + pixman_image_unref (alpha_map); + } + + if ((flags & ALLOW_REPEAT) && prng_rand_n (2) == 0) + pixman_image_set_repeat (image, prng_rand_n (4)); + + image_endian_swap (image); + + return image; +} + +#define KEY1(p) ((void *)(((uintptr_t)p) ^ (0xa7e23dfaUL))) +#define KEY2(p) ((void *)(((uintptr_t)p) ^ (0xabcd9876UL))) + +#define MAX_GLYPHS 32 + +uint32_t +test_glyphs (int testnum, int verbose) +{ + pixman_image_t *glyph_images[MAX_GLYPHS]; + pixman_glyph_t glyphs[4 * MAX_GLYPHS]; + uint32_t crc32 = 0; + pixman_image_t *source, *dest; + int n_glyphs, i; + pixman_glyph_cache_t *cache; + + prng_srand (testnum); + + cache = pixman_glyph_cache_create (); + + source = create_image (300, formats, + ALLOW_CLIPPED | ALLOW_ALPHA_MAP | + ALLOW_SOURCE_CLIPPING | + ALLOW_REPEAT | ALLOW_SOLID); + + dest = create_image (128, formats, + ALLOW_CLIPPED | ALLOW_ALPHA_MAP | + ALLOW_SOURCE_CLIPPING); + + pixman_glyph_cache_freeze (cache); + + n_glyphs = prng_rand_n (MAX_GLYPHS); + for (i = 0; i < n_glyphs; ++i) + glyph_images[i] = create_image (32, glyph_formats, 0); + + for (i = 0; i < 4 * n_glyphs; ++i) + { + int g = prng_rand_n (n_glyphs); + pixman_image_t *glyph_img = glyph_images[g]; + void *key1 = KEY1 (glyph_img); + void *key2 = KEY2 (glyph_img); + const void *glyph; + + if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2))) + { + glyph = + pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img); + } + + glyphs[i].glyph = glyph; + glyphs[i].x = prng_rand_n (128); + glyphs[i].y = prng_rand_n (128); + } + + if (prng_rand_n (2) == 0) + { + int src_x = prng_rand_n (300) - 150; + int src_y = prng_rand_n (300) - 150; + int mask_x = prng_rand_n (64) - 32; + int mask_y = prng_rand_n (64) - 32; + int dest_x = prng_rand_n (64) - 32; + int dest_y = prng_rand_n (64) - 32; + int width = prng_rand_n (64); + int height = prng_rand_n (64); + pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))]; + pixman_format_code_t format = random_format (glyph_formats); + + pixman_composite_glyphs ( + op, + source, dest, format, + src_x, src_y, + mask_x, mask_y, + dest_x, dest_y, + width, height, + cache, 4 * n_glyphs, glyphs); + } + else + { + pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))]; + int src_x = prng_rand_n (300) - 150; + int src_y = prng_rand_n (300) - 150; + int dest_x = prng_rand_n (64) - 32; + int dest_y = prng_rand_n (64) - 32; + + pixman_composite_glyphs_no_mask ( + op, source, dest, + src_x, src_y, + dest_x, dest_y, + cache, 4 * n_glyphs, glyphs); + } + + pixman_glyph_cache_thaw (cache); + + for (i = 0; i < n_glyphs; ++i) + { + pixman_image_t *img = glyph_images[i]; + void *key1, *key2; + + key1 = KEY1 (img); + key2 = KEY2 (img); + + pixman_glyph_cache_remove (cache, key1, key2); + pixman_image_unref (glyph_images[i]); + } + + crc32 = compute_crc32_for_image (0, dest); + + pixman_image_unref (source); + pixman_image_unref (dest); + + pixman_glyph_cache_destroy (cache); + + return crc32; +} + +int +main (int argc, const char *argv[]) +{ + return fuzzer_test_main ("glyph", 30000, + 0xFA478A79, + test_glyphs, argc, argv); +} |