[Pixman] [PATCH 4/7] test: Add new check-formats utility

Søren Sandmann sandmann at cs.au.dk
Thu Jan 24 07:52:56 PST 2013


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

Given an operator and two formats, this program will composite and
check all pixels where the red and blue channels are 0. That is, if
the two formats are a8r8g8b8 and a4r4g4b4, all source pixels matching
the mask

    0xff00ff00

are composited with the given operator against all destination pixels
matching the mask

    0xf0f0

and the result is then verified against the do_composite() function
that was moved to utils.c earlier.

This program reveals that a number of operators and format
combinations are not computed to within the precision currently
accepted by pixel_checker_t. For example:

    check-formats over a8r8g8b8 r5g6b5 | grep failed | wc -l
    30

reveals that there are 30 pixel combinations where OVER produces
insufficiently precise results for the a8r8g8b8 and r5g6b5 formats.
---
 test/Makefile.am      |    2 +-
 test/Makefile.sources |    3 +-
 test/check-formats.c  |  352 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 355 insertions(+), 2 deletions(-)
 create mode 100644 test/check-formats.c

diff --git a/test/Makefile.am b/test/Makefile.am
index ca87f4e..5d901d5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,6 +8,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman $(PNG_CFLAGS)
 libutils_la_SOURCES = $(libutils_sources) $(libutils_headers)
 
 noinst_LTLIBRARIES = libutils.la
-noinst_PROGRAMS = $(TESTPROGRAMS) $(BENCHMARKS)
+noinst_PROGRAMS = $(TESTPROGRAMS) $(OTHERPROGRAMS)
 
 TESTS = $(TESTPROGRAMS)
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 8c0b505..77e2931 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -27,8 +27,9 @@ TESTPROGRAMS =			\
 	$(NULL)
 
 # Benchmarks
-BENCHMARKS =			\
+OTHERPROGRAMS =                 \
 	lowlevel-blt-bench	\
+        check-formats           \
 	$(NULL)
 
 # Utility functions
diff --git a/test/check-formats.c b/test/check-formats.c
new file mode 100644
index 0000000..7edc198
--- /dev/null
+++ b/test/check-formats.c
@@ -0,0 +1,352 @@
+#include <ctype.h>
+#include "utils.h"
+
+static int
+check_op (pixman_op_t          op,
+          pixman_format_code_t src_format,
+          pixman_format_code_t dest_format)
+{
+    uint32_t src_alpha_mask, src_green_mask;
+    uint32_t dest_alpha_mask, dest_green_mask;
+    pixel_checker_t src_checker, dest_checker;
+    pixman_image_t *si, *di;
+    uint32_t sa, sg, da, dg;
+    uint32_t s, d;
+    int retval = 0;
+
+    pixel_checker_init (&src_checker, src_format);
+    pixel_checker_init (&dest_checker, dest_format);
+
+    pixel_checker_get_masks (
+        &src_checker, &src_alpha_mask, NULL, &src_green_mask, NULL);
+    pixel_checker_get_masks (
+        &dest_checker, &dest_alpha_mask, NULL, &dest_green_mask, NULL);
+
+    /* printf ("masks: %x %x %x %x\n", */
+    /* 	    src_alpha_mask, src_green_mask, */
+    /* 	    dest_alpha_mask, dest_green_mask); */
+
+    si = pixman_image_create_bits (src_format, 1, 1, &s, 4);
+    di = pixman_image_create_bits (dest_format, 1, 1, &d, 4);
+
+    sa = 0;
+    do
+    {
+        sg = 0;
+        do
+        {
+            da = 0;
+            do
+            {
+                dg = 0;
+                do
+                {
+                    color_t src_color, dest_color, result_color;
+                    uint32_t orig_d;
+
+                    s = sa | sg;
+                    d = da | dg;
+
+                    orig_d = d;
+
+		    pixel_checker_convert_pixel_to_color (&src_checker, s, &src_color);
+		    pixel_checker_convert_pixel_to_color (&dest_checker, d, &dest_color);
+
+		    do_composite (op, &src_color, NULL, &dest_color, &result_color, FALSE);
+
+
+		    if (!is_little_endian())
+                    {
+			s <<= 32 - PIXMAN_FORMAT_BPP (src_format);
+			d <<= 32 - PIXMAN_FORMAT_BPP (dest_format);
+                    }
+
+		    pixman_image_composite32 (op, si, NULL, di,
+					      0, 0, 0, 0, 0, 0, 1, 1);
+
+		    if (!is_little_endian())
+                        d >>= (32 - PIXMAN_FORMAT_BPP (dest_format));
+
+                    if (!pixel_checker_check (&dest_checker, d, &result_color))
+                    {
+                        printf ("---- test failed ----\n");
+                        printf ("operator: %-32s\n", operator_name (op));
+                        printf ("source:   %-12s pixel: %08x\n", format_name (src_format), s);
+                        printf ("dest:     %-12s pixel: %08x\n", format_name (dest_format), orig_d);
+                        printf ("got:      %-12s pixel: %08x\n", format_name (dest_format), d);
+
+                        retval = 1;
+                    }
+
+                    dg -= dest_green_mask;
+                    dg &= dest_green_mask;
+                }
+                while (dg != 0);
+
+                da -= dest_alpha_mask;
+                da &= dest_alpha_mask;
+            }
+            while (da != 0);
+
+            sg -= src_green_mask;
+            sg &= src_green_mask;
+        }
+        while (sg != 0);
+
+        sa -= src_alpha_mask;
+        sa &= src_alpha_mask;
+    }
+    while (sa != 0);
+
+    pixman_image_unref (si);
+    pixman_image_unref (di);
+
+    return retval;
+}
+
+static const pixman_op_t op_list[] =
+{
+    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,
+    PIXMAN_OP_SATURATE,
+
+    PIXMAN_OP_DISJOINT_CLEAR,
+    PIXMAN_OP_DISJOINT_SRC,
+    PIXMAN_OP_DISJOINT_DST,
+    PIXMAN_OP_DISJOINT_OVER,
+    PIXMAN_OP_DISJOINT_OVER_REVERSE,
+    PIXMAN_OP_DISJOINT_IN,
+    PIXMAN_OP_DISJOINT_IN_REVERSE,
+    PIXMAN_OP_DISJOINT_OUT,
+    PIXMAN_OP_DISJOINT_OUT_REVERSE,
+    PIXMAN_OP_DISJOINT_ATOP,
+    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+    PIXMAN_OP_DISJOINT_XOR,
+
+    PIXMAN_OP_CONJOINT_CLEAR,
+    PIXMAN_OP_CONJOINT_SRC,
+    PIXMAN_OP_CONJOINT_DST,
+    PIXMAN_OP_CONJOINT_OVER,
+    PIXMAN_OP_CONJOINT_OVER_REVERSE,
+    PIXMAN_OP_CONJOINT_IN,
+    PIXMAN_OP_CONJOINT_IN_REVERSE,
+    PIXMAN_OP_CONJOINT_OUT,
+    PIXMAN_OP_CONJOINT_OUT_REVERSE,
+    PIXMAN_OP_CONJOINT_ATOP,
+    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+    PIXMAN_OP_CONJOINT_XOR,
+};
+
+static const pixman_format_code_t format_list[] =
+{
+    PIXMAN_a8r8g8b8,
+    PIXMAN_x8r8g8b8,
+    PIXMAN_a8b8g8r8,
+    PIXMAN_x8b8g8r8,
+    PIXMAN_b8g8r8a8,
+    PIXMAN_b8g8r8x8,
+    PIXMAN_r8g8b8a8,
+    PIXMAN_r8g8b8x8,
+    PIXMAN_x14r6g6b6,
+    PIXMAN_x2r10g10b10,
+    PIXMAN_a2r10g10b10,
+    PIXMAN_x2b10g10r10,
+    PIXMAN_a2b10g10r10,
+    PIXMAN_a8r8g8b8_sRGB,
+    PIXMAN_r8g8b8,
+    PIXMAN_b8g8r8,
+    PIXMAN_r5g6b5,
+    PIXMAN_b5g6r5,
+    PIXMAN_a1r5g5b5,
+    PIXMAN_x1r5g5b5,
+    PIXMAN_a1b5g5r5,
+    PIXMAN_x1b5g5r5,
+    PIXMAN_a4r4g4b4,
+    PIXMAN_x4r4g4b4,
+    PIXMAN_a4b4g4r4,
+    PIXMAN_x4b4g4r4,
+    PIXMAN_a8,
+    PIXMAN_r3g3b2,
+    PIXMAN_b2g3r3,
+    PIXMAN_a2r2g2b2,
+    PIXMAN_a2b2g2r2,
+    PIXMAN_x4a4,
+    PIXMAN_a4,
+    PIXMAN_r1g2b1,
+    PIXMAN_b1g2r1,
+    PIXMAN_a1r1g1b1,
+    PIXMAN_a1b1g1r1,
+    PIXMAN_a1,
+};
+
+static pixman_format_code_t
+format_from_string (const char *s)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
+    {
+        if (strcasecmp (format_name (format_list[i]), s) == 0)
+            return format_list[i];
+    }
+
+    return PIXMAN_null;
+}
+
+static void
+emit (const char *s, int *n_chars)
+{
+    *n_chars += printf ("%s,", s);
+    if (*n_chars > 60)
+    {
+        printf ("\n    ");
+        *n_chars = 0;
+    }
+    else
+    {
+        printf (" ");
+        (*n_chars)++;
+    }
+}
+
+static void
+list_formats (void)
+{
+    int n_chars;
+    int i;
+
+    printf ("Formats:\n    ");
+
+    n_chars = 0;
+    for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
+        emit (format_name (format_list[i]), &n_chars);
+
+    printf ("\n\n");
+}
+
+static void
+list_operators (void)
+{
+    char short_name [128] = { 0 };
+    int i, n_chars;
+
+    printf ("Operators:\n    ");
+
+    n_chars = 0;
+    for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
+    {
+        pixman_op_t op = op_list[i];
+        int j;
+
+        snprintf (short_name, sizeof (short_name) - 1, "%s",
+                  operator_name (op) + strlen ("PIXMAN_OP_"));
+
+        for (j = 0; short_name[j] != '\0'; ++j)
+            short_name[j] = tolower (short_name[j]);
+
+        emit (short_name, &n_chars);
+    }
+
+    printf ("\n\n");
+}
+
+static pixman_op_t
+operator_from_string (const char *s)
+{
+    char full_name[128] = { 0 };
+    int i;
+
+    snprintf (full_name, (sizeof full_name) - 1, "PIXMAN_OP_%s", s);
+
+    for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
+    {
+        pixman_op_t op = op_list[i];
+
+        if (strcasecmp (operator_name (op), full_name) == 0)
+            return op;
+    }
+
+    return PIXMAN_OP_NONE;
+}
+
+int
+main (int argc, char **argv)
+{
+    enum { OPTION_OP, OPTION_SRC, OPTION_DEST, LAST_OPTION } option;
+    pixman_format_code_t src_fmt, dest_fmt;
+    pixman_op_t op;
+
+    op = PIXMAN_OP_NONE;
+    src_fmt = PIXMAN_null;
+    dest_fmt = PIXMAN_null;
+
+    argc--;
+    argv++;
+
+    for (option = OPTION_OP; option < LAST_OPTION; ++option)
+    {
+        char *arg = NULL;
+
+        if (argc)
+        {
+            argc--;
+            arg = *argv++;
+        }
+
+        switch (option)
+        {
+        case OPTION_OP:
+            if (!arg)
+                printf ("  - missing operator\n");
+            else if ((op = operator_from_string (arg)) == PIXMAN_OP_NONE)
+                printf ("  - unknown operator %s\n", arg);
+            break;
+
+        case OPTION_SRC:
+            if (!arg)
+                printf ("  - missing source format\n");
+            else if ((src_fmt = format_from_string (arg)) == PIXMAN_null)
+                printf ("  - unknown source format %s\n", arg);
+            break;
+
+        case OPTION_DEST:
+            if (!arg)
+                printf ("  - missing destination format\n");
+            else if ((dest_fmt = format_from_string (arg)) == PIXMAN_null)
+                printf ("  - unknown destination format %s\n", arg);
+            break;
+
+        default:
+            assert (0);
+            break;
+        }
+    }
+
+    while (argc--)
+    {
+        op = PIXMAN_OP_NONE;
+        printf ("  - unexpected argument: %s\n", *argv++);
+    }
+
+    if (op == PIXMAN_OP_NONE || src_fmt == PIXMAN_null || dest_fmt == PIXMAN_null)
+    {
+        printf ("\nUsage:\n    check-formats <operator> <src-format> <dest-format>\n\n");
+        list_operators();
+        list_formats();
+
+        return -1;
+    }
+
+    return check_op (op, src_fmt, dest_fmt);
+}
-- 
1.7.4



More information about the Pixman mailing list