[Pixman] [PATCH v2 5/8] test: Add glyph-test

Søren Sandmann sandmann at cs.au.dk
Sat Jun 2 06:23:54 PDT 2012


From: Søren Sandmann Pedersen <ssp at redhat.com>

This test tests the new glyph cache and compositing API. Much of this
test is intending to making sure that clipping and alpha map handling
survive any optimizations that may be added to the glyph compositing.

V2: Evaluating lcg_rand_n() multiple times in an argument list lead
    to undefined behavior.
---
 test/Makefile.sources |    1 +
 test/glyph-test.c     |  331 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 332 insertions(+)
 create mode 100644 test/glyph-test.c

diff --git a/test/Makefile.sources b/test/Makefile.sources
index 99eb705..fad8c6f 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -16,6 +16,7 @@ TESTPROGRAMS =			\
 	stress-test		\
 	composite-traps-test	\
 	blitters-test		\
+	glyph-test		\
 	scaling-test		\
 	affine-test		\
 	composite		\
diff --git a/test/glyph-test.c b/test/glyph-test.c
new file mode 100644
index 0000000..9ff2a2b
--- /dev/null
+++ b/test/glyph-test.c
@@ -0,0 +1,331 @@
+#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,
+    PIXMAN_x2r10g10b10,
+    PIXMAN_a2r10g10b10,
+    PIXMAN_x2b10g10r10,
+    PIXMAN_a2b10g10r10,
+    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[lcg_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) && lcg_rand_n (4) == 0)
+    {
+	pixman_color_t color;
+
+	color.alpha = lcg_rand_u32();
+	color.red = lcg_rand_u32();
+	color.green = lcg_rand_u32();
+	color.blue = lcg_rand_u32();
+
+	return pixman_image_create_solid_fill (&color);
+    }
+
+    width = lcg_rand_n (max_size) + 1;
+    height = lcg_rand_n (max_size) + 1;
+    format = random_format (formats);
+
+    bpp = PIXMAN_FORMAT_BPP (format);
+    stride = (width * bpp + 7) / 8 + lcg_rand_n (17);
+    stride = (stride + 3) & ~3;
+
+    if (lcg_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);
+	for (i = 0; i < height * stride / 4; ++i)
+	    data[i] = lcg_rand_u32();
+
+	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) && lcg_rand_n (8) == 0)
+    {
+	pixman_box16_t clip_boxes[8];
+	pixman_region16_t clip;
+	int n = lcg_rand_n (8) + 1;
+
+	for (i = 0; i < n; i++)
+	{
+	    clip_boxes[i].x1 = lcg_rand_n (width);
+	    clip_boxes[i].y1 = lcg_rand_n (height);
+	    clip_boxes[i].x2 =
+		clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1);
+	    clip_boxes[i].y2 =
+		clip_boxes[i].y1 + lcg_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) && lcg_rand_n (4) == 0)
+    {
+	pixman_image_set_source_clipping (image, TRUE);
+	pixman_image_set_has_client_clip (image, TRUE);
+    }
+
+    if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0)
+    {
+	pixman_image_t *alpha_map;
+	int alpha_x, alpha_y;
+
+	alpha_x = lcg_rand_n (width);
+	alpha_y = lcg_rand_n (height);
+	alpha_map =
+	    create_image (max_size, formats, (flags & ~ALLOW_ALPHA_MAP));
+	pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y);
+	pixman_image_unref (alpha_map);
+    }
+
+    if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0)
+	pixman_image_set_repeat (image, lcg_rand_n (4));
+
+    image_endian_swap (image);
+
+    return image;
+}
+
+#define KEY1(p) ((void *)(((unsigned long)p) ^ (0xa7e23dfaUL)))
+#define KEY2(p) ((void *)(((unsigned long)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;
+
+    lcg_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 = lcg_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 = lcg_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 = lcg_rand_n (128);
+	glyphs[i].y = lcg_rand_n (128);
+    }
+
+    if (lcg_rand_n (2) == 0)
+    {
+	int src_x = lcg_rand_n (300) - 150;
+	int src_y = lcg_rand_n (300) - 150;
+	int mask_x = lcg_rand_n (64) - 32;
+	int mask_y = lcg_rand_n (64) - 32;
+	int dest_x = lcg_rand_n (64) - 32;
+	int dest_y = lcg_rand_n (64) - 32;
+	int width = lcg_rand_n (64);
+	int height = lcg_rand_n (64);
+	pixman_op_t op = operators[lcg_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[lcg_rand_n (ARRAY_LENGTH (operators))];
+	int src_x = lcg_rand_n (300) - 150;
+	int src_y = lcg_rand_n (300) - 150;
+	int dest_x = lcg_rand_n (64) - 32;
+	int dest_y = lcg_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,
+			     0xA2B67F99,
+			     test_glyphs, argc, argv);
+}
-- 
1.7.10.2



More information about the Pixman mailing list