aboutsummaryrefslogtreecommitdiff
path: root/pixman
diff options
context:
space:
mode:
Diffstat (limited to 'pixman')
-rw-r--r--pixman/pixman/pixman-compiler.h6
-rw-r--r--pixman/pixman/pixman-implementation.c9
-rw-r--r--pixman/pixman/pixman-private.h36
-rwxr-xr-xpixman/pixman/pixman-sse2.c4
-rw-r--r--pixman/pixman/pixman-utils.c4
-rw-r--r--pixman/test/Makefile.am2
-rw-r--r--pixman/test/Makefile.sources4
-rw-r--r--pixman/test/a1-trap-test.c8
-rw-r--r--pixman/test/check-formats.c352
-rw-r--r--pixman/test/composite.c277
-rw-r--r--pixman/test/lowlevel-blt-bench.c14
-rw-r--r--pixman/test/pixel-test.c267
-rw-r--r--pixman/test/utils.c332
-rw-r--r--pixman/test/utils.h19
14 files changed, 1007 insertions, 327 deletions
diff --git a/pixman/pixman/pixman-compiler.h b/pixman/pixman/pixman-compiler.h
index d38dfbe34..949182d4f 100644
--- a/pixman/pixman/pixman-compiler.h
+++ b/pixman/pixman/pixman-compiler.h
@@ -19,6 +19,12 @@
#endif
#if defined (__GNUC__)
+# define unlikely(expr) __builtin_expect ((expr), 0)
+#else
+# define unlikely(expr) (expr)
+#endif
+
+#if defined (__GNUC__)
# define MAYBE_UNUSED __attribute__((unused))
#else
# define MAYBE_UNUSED
diff --git a/pixman/pixman/pixman-implementation.c b/pixman/pixman/pixman-implementation.c
index c0a643633..cfb82bb1f 100644
--- a/pixman/pixman/pixman-implementation.c
+++ b/pixman/pixman/pixman-implementation.c
@@ -150,9 +150,16 @@ _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
}
/* We should never reach this point */
- _pixman_log_error (FUNC, "No known composite function\n");
+ _pixman_log_error (
+ FUNC,
+ "No composite function found\n"
+ "\n"
+ "The most likely cause of this is that this system has issues with\n"
+ "thread local storage\n");
+
*out_imp = NULL;
*out_func = dummy_composite_rect;
+ return;
update_cache:
if (i)
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index cb78a2ed8..181ab5c35 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -1014,15 +1014,13 @@ float pixman_unorm_to_float (uint16_t u, int n_bits);
#endif
-#ifdef DEBUG
-
void
_pixman_log_error (const char *function, const char *message);
#define return_if_fail(expr) \
do \
{ \
- if (!(expr)) \
+ if (unlikely (!(expr))) \
{ \
_pixman_log_error (FUNC, "The expression " # expr " was false"); \
return; \
@@ -1033,7 +1031,7 @@ _pixman_log_error (const char *function, const char *message);
#define return_val_if_fail(expr, retval) \
do \
{ \
- if (!(expr)) \
+ if (unlikely (!(expr))) \
{ \
_pixman_log_error (FUNC, "The expression " # expr " was false"); \
return (retval); \
@@ -1044,39 +1042,11 @@ _pixman_log_error (const char *function, const char *message);
#define critical_if_fail(expr) \
do \
{ \
- if (!(expr)) \
+ if (unlikely (!(expr))) \
_pixman_log_error (FUNC, "The expression " # expr " was false"); \
} \
while (0)
-
-#else
-
-#define _pixman_log_error(f,m) do { } while (0)
-
-#define return_if_fail(expr) \
- do \
- { \
- if (!(expr)) \
- return; \
- } \
- while (0)
-
-#define return_val_if_fail(expr, retval) \
- do \
- { \
- if (!(expr)) \
- return (retval); \
- } \
- while (0)
-
-#define critical_if_fail(expr) \
- do \
- { \
- } \
- while (0)
-#endif
-
/*
* Matrix
*/
diff --git a/pixman/pixman/pixman-sse2.c b/pixman/pixman/pixman-sse2.c
index f04ea92d9..1d525794e 100755
--- a/pixman/pixman/pixman-sse2.c
+++ b/pixman/pixman/pixman-sse2.c
@@ -4558,7 +4558,7 @@ sse2_composite_add_n_8888 (pixman_implementation_t *imp,
dst = dst_line;
dst_line += dst_stride;
- while (w && (unsigned long)dst & 15)
+ while (w && (uintptr_t)dst & 15)
{
d = *dst;
*dst++ =
@@ -4617,7 +4617,7 @@ sse2_composite_add_n_8_8888 (pixman_implementation_t *imp,
mask_line += mask_stride;
w = width;
- while (w && ((unsigned long)dst & 15))
+ while (w && ((uintptr_t)dst & 15))
{
uint8_t m = *mask++;
if (m)
diff --git a/pixman/pixman/pixman-utils.c b/pixman/pixman/pixman-utils.c
index b1e9fb62d..f31171f6d 100644
--- a/pixman/pixman/pixman-utils.c
+++ b/pixman/pixman/pixman-utils.c
@@ -292,8 +292,6 @@ _pixman_internal_only_get_implementation (void)
return get_implementation ();
}
-#ifdef DEBUG
-
void
_pixman_log_error (const char *function, const char *message)
{
@@ -310,5 +308,3 @@ _pixman_log_error (const char *function, const char *message)
n_messages++;
}
}
-
-#endif
diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am
index ca87f4ef4..5d901d572 100644
--- a/pixman/test/Makefile.am
+++ b/pixman/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/pixman/test/Makefile.sources b/pixman/test/Makefile.sources
index e323a8e8c..5b30970b9 100644
--- a/pixman/test/Makefile.sources
+++ b/pixman/test/Makefile.sources
@@ -6,6 +6,7 @@ TESTPROGRAMS = \
region-test \
region-translate-test \
combiner-test \
+ pixel-test \
fetch-test \
rotate-test \
oob-test \
@@ -28,8 +29,9 @@ TESTPROGRAMS = \
$(NULL)
# Benchmarks
-BENCHMARKS = \
+OTHERPROGRAMS = \
lowlevel-blt-bench \
+ check-formats \
$(NULL)
# Utility functions
diff --git a/pixman/test/a1-trap-test.c b/pixman/test/a1-trap-test.c
index 93c6caa14..c2b488316 100644
--- a/pixman/test/a1-trap-test.c
+++ b/pixman/test/a1-trap-test.c
@@ -45,6 +45,14 @@ main (int argc, char **argv)
assert (bits[1] == 0xffffffff);
assert (bits[1 * WIDTH + 0] == 0xffffffff);
assert (bits[1 * WIDTH + 1] == 0xffffffff);
+
+ /* The check-formats test depends on operator_name() and format_name() returning
+ * these precise formats, so if those change, check-formats.c must be updated too.
+ */
+ assert (
+ strcmp (operator_name (PIXMAN_OP_DISJOINT_OVER), "PIXMAN_OP_DISJOINT_OVER") == 0);
+ assert (
+ strcmp (format_name (PIXMAN_r5g6b5), "r5g6b5") == 0);
return 0;
}
diff --git a/pixman/test/check-formats.c b/pixman/test/check-formats.c
new file mode 100644
index 000000000..7edc198c1
--- /dev/null
+++ b/pixman/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);
+}
diff --git a/pixman/test/composite.c b/pixman/test/composite.c
index b107b1106..9e51a8f65 100644
--- a/pixman/test/composite.c
+++ b/pixman/test/composite.c
@@ -181,283 +181,6 @@ static const pixman_op_t operators[] =
PIXMAN_OP_CONJOINT_XOR,
};
-static double
-calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
-{
-#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
-
- double Fa, Fb;
-
- switch (op)
- {
- case PIXMAN_OP_CLEAR:
- case PIXMAN_OP_DISJOINT_CLEAR:
- case PIXMAN_OP_CONJOINT_CLEAR:
- return mult_chan (src, dst, 0.0, 0.0);
-
- case PIXMAN_OP_SRC:
- case PIXMAN_OP_DISJOINT_SRC:
- case PIXMAN_OP_CONJOINT_SRC:
- return mult_chan (src, dst, 1.0, 0.0);
-
- case PIXMAN_OP_DST:
- case PIXMAN_OP_DISJOINT_DST:
- case PIXMAN_OP_CONJOINT_DST:
- return mult_chan (src, dst, 0.0, 1.0);
-
- case PIXMAN_OP_OVER:
- return mult_chan (src, dst, 1.0, 1.0 - srca);
-
- case PIXMAN_OP_OVER_REVERSE:
- return mult_chan (src, dst, 1.0 - dsta, 1.0);
-
- case PIXMAN_OP_IN:
- return mult_chan (src, dst, dsta, 0.0);
-
- case PIXMAN_OP_IN_REVERSE:
- return mult_chan (src, dst, 0.0, srca);
-
- case PIXMAN_OP_OUT:
- return mult_chan (src, dst, 1.0 - dsta, 0.0);
-
- case PIXMAN_OP_OUT_REVERSE:
- return mult_chan (src, dst, 0.0, 1.0 - srca);
-
- case PIXMAN_OP_ATOP:
- return mult_chan (src, dst, dsta, 1.0 - srca);
-
- case PIXMAN_OP_ATOP_REVERSE:
- return mult_chan (src, dst, 1.0 - dsta, srca);
-
- case PIXMAN_OP_XOR:
- return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
-
- case PIXMAN_OP_ADD:
- return mult_chan (src, dst, 1.0, 1.0);
-
- case PIXMAN_OP_SATURATE:
- case PIXMAN_OP_DISJOINT_OVER_REVERSE:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, (1.0 - dsta) / srca);
- return mult_chan (src, dst, Fa, 1.0);
-
- case PIXMAN_OP_DISJOINT_OVER:
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, (1.0 - srca) / dsta);
- return mult_chan (src, dst, 1.0, Fb);
-
- case PIXMAN_OP_DISJOINT_IN:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
- return mult_chan (src, dst, Fa, 0.0);
-
- case PIXMAN_OP_DISJOINT_IN_REVERSE:
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
- return mult_chan (src, dst, 0.0, Fb);
-
- case PIXMAN_OP_DISJOINT_OUT:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, (1.0 - dsta) / srca);
- return mult_chan (src, dst, Fa, 0.0);
-
- case PIXMAN_OP_DISJOINT_OUT_REVERSE:
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, (1.0 - srca) / dsta);
- return mult_chan (src, dst, 0.0, Fb);
-
- case PIXMAN_OP_DISJOINT_ATOP:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, (1.0 - srca) / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, (1.0 - dsta) / srca);
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_DISJOINT_XOR:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, (1.0 - dsta) / srca);
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, (1.0 - srca) / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_CONJOINT_OVER:
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - srca / dsta);
- return mult_chan (src, dst, 1.0, Fb);
-
- case PIXMAN_OP_CONJOINT_OVER_REVERSE:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - dsta / srca);
- return mult_chan (src, dst, Fa, 1.0);
-
- case PIXMAN_OP_CONJOINT_IN:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, dsta / srca);
- return mult_chan (src, dst, Fa, 0.0);
-
- case PIXMAN_OP_CONJOINT_IN_REVERSE:
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, srca / dsta);
- return mult_chan (src, dst, 0.0, Fb);
-
- case PIXMAN_OP_CONJOINT_OUT:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - dsta / srca);
- return mult_chan (src, dst, Fa, 0.0);
-
- case PIXMAN_OP_CONJOINT_OUT_REVERSE:
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - srca / dsta);
- return mult_chan (src, dst, 0.0, Fb);
-
- case PIXMAN_OP_CONJOINT_ATOP:
- if (srca == 0.0)
- Fa = 1.0;
- else
- Fa = MIN (1.0, dsta / srca);
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - srca / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - dsta / srca);
- if (dsta == 0.0)
- Fb = 1.0;
- else
- Fb = MIN (1.0, srca / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_CONJOINT_XOR:
- if (srca == 0.0)
- Fa = 0.0;
- else
- Fa = MAX (0.0, 1.0 - dsta / srca);
- if (dsta == 0.0)
- Fb = 0.0;
- else
- Fb = MAX (0.0, 1.0 - srca / dsta);
- return mult_chan (src, dst, Fa, Fb);
-
- case PIXMAN_OP_MULTIPLY:
- case PIXMAN_OP_SCREEN:
- case PIXMAN_OP_OVERLAY:
- case PIXMAN_OP_DARKEN:
- case PIXMAN_OP_LIGHTEN:
- case PIXMAN_OP_COLOR_DODGE:
- case PIXMAN_OP_COLOR_BURN:
- case PIXMAN_OP_HARD_LIGHT:
- case PIXMAN_OP_SOFT_LIGHT:
- case PIXMAN_OP_DIFFERENCE:
- case PIXMAN_OP_EXCLUSION:
- case PIXMAN_OP_HSL_HUE:
- case PIXMAN_OP_HSL_SATURATION:
- case PIXMAN_OP_HSL_COLOR:
- case PIXMAN_OP_HSL_LUMINOSITY:
- default:
- abort();
- return 0; /* silence MSVC */
- }
-#undef mult_chan
-}
-
-static void
-do_composite (pixman_op_t op,
- const color_t *src,
- const color_t *mask,
- const color_t *dst,
- color_t *result,
- pixman_bool_t component_alpha)
-{
- color_t srcval, srcalpha;
-
- if (mask == NULL)
- {
- srcval = *src;
-
- srcalpha.r = src->a;
- srcalpha.g = src->a;
- srcalpha.b = src->a;
- srcalpha.a = src->a;
- }
- else if (component_alpha)
- {
- srcval.r = src->r * mask->r;
- srcval.g = src->g * mask->g;
- srcval.b = src->b * mask->b;
- srcval.a = src->a * mask->a;
-
- srcalpha.r = src->a * mask->r;
- srcalpha.g = src->a * mask->g;
- srcalpha.b = src->a * mask->b;
- srcalpha.a = src->a * mask->a;
- }
- else
- {
- srcval.r = src->r * mask->a;
- srcval.g = src->g * mask->a;
- srcval.b = src->b * mask->a;
- srcval.a = src->a * mask->a;
-
- srcalpha.r = src->a * mask->a;
- srcalpha.g = src->a * mask->a;
- srcalpha.b = src->a * mask->a;
- srcalpha.a = src->a * mask->a;
- }
-
- result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
- result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
- result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
- result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
-}
-
static uint32_t
get_value (pixman_image_t *image)
{
diff --git a/pixman/test/lowlevel-blt-bench.c b/pixman/test/lowlevel-blt-bench.c
index 8e80b4280..4e16f7ba1 100644
--- a/pixman/test/lowlevel-blt-bench.c
+++ b/pixman/test/lowlevel-blt-bench.c
@@ -460,8 +460,8 @@ bench_composite (char * testname,
printf ("%24s %c", testname, func != pixman_image_composite_wrapper ?
'-' : '=');
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
l1test_width = L1CACHE_SIZE / 8 - 64;
if (l1test_width < 1)
@@ -480,8 +480,8 @@ bench_composite (char * testname,
((t3 - t2) - (t2 - t1)) / 1000000.);
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
nlines = (L2CACHE_SIZE / l1test_width) /
((PIXMAN_FORMAT_BPP(src_fmt) + PIXMAN_FORMAT_BPP(dst_fmt)) / 8);
@@ -499,8 +499,8 @@ bench_composite (char * testname,
((t3 - t2) - (t2 - t1)) / 1000000.);
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
n = 1 + npix / (WIDTH * HEIGHT);
t1 = gettime ();
@@ -515,8 +515,8 @@ bench_composite (char * testname,
((double)n * (WIDTH - 64) * HEIGHT / ((t3 - t2) - (t2 - t1)) * bytes_per_pix) * (100.0 / bandwidth) );
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
t1 = gettime ();
@@ -529,8 +529,8 @@ bench_composite (char * testname,
printf (" HT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
t1 = gettime ();
@@ -543,8 +543,8 @@ bench_composite (char * testname,
printf (" VT:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
n = 1 + npix / (8 * TILEWIDTH * TILEWIDTH);
t1 = gettime ();
@@ -557,8 +557,8 @@ bench_composite (char * testname,
printf (" R:%6.2f", (double)pix_cnt / ((t3 - t2) - (t2 - t1)) / 1000000.);
fflush (stdout);
- memcpy (src, dst, BUFSIZE);
memcpy (dst, src, BUFSIZE);
+ memcpy (src, dst, BUFSIZE);
n = 1 + npix / (16 * TINYWIDTH * TINYWIDTH);
t1 = gettime ();
diff --git a/pixman/test/pixel-test.c b/pixman/test/pixel-test.c
new file mode 100644
index 000000000..8c525d202
--- /dev/null
+++ b/pixman/test/pixel-test.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright © 2013 Soeren Sandmann
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h> /* abort() */
+#include <math.h>
+#include <time.h>
+#include "utils.h"
+
+typedef struct pixel_combination_t pixel_combination_t;
+struct pixel_combination_t
+{
+ pixman_op_t op;
+ pixman_format_code_t src_format;
+ uint32_t src_pixel;
+ pixman_format_code_t dest_format;
+ uint32_t dest_pixel;
+};
+
+static const pixel_combination_t regressions[] =
+{
+ { PIXMAN_OP_OVER,
+ PIXMAN_a8r8g8b8, 0x0f00c300,
+ PIXMAN_x14r6g6b6, 0x003c0,
+ },
+ { PIXMAN_OP_DISJOINT_XOR,
+ PIXMAN_a4r4g4b4, 0xd0c0,
+ PIXMAN_a8r8g8b8, 0x5300ea00,
+ },
+ { PIXMAN_OP_OVER,
+ PIXMAN_a8r8g8b8, 0x20c6bf00,
+ PIXMAN_r5g6b5, 0xb9ff
+ },
+ { PIXMAN_OP_OVER,
+ PIXMAN_a8r8g8b8, 0x204ac7ff,
+ PIXMAN_r5g6b5, 0xc1ff
+ },
+ { PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_r5g6b5, 0xffc3,
+ PIXMAN_a8r8g8b8, 0x102d00dd
+ },
+ { PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_r5g6b5, 0x1f00,
+ PIXMAN_a8r8g8b8, 0x1bdf0c89
+ },
+ { PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_r5g6b5, 0xf9d2,
+ PIXMAN_a8r8g8b8, 0x1076bcf7
+ },
+ { PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_r5g6b5, 0x00c3,
+ PIXMAN_a8r8g8b8, 0x1bfe9ae5
+ },
+ { PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_r5g6b5, 0x09ff,
+ PIXMAN_a8r8g8b8, 0x0b00c16c
+ },
+ { PIXMAN_OP_DISJOINT_ATOP,
+ PIXMAN_a2r2g2b2, 0xbc,
+ PIXMAN_a8r8g8b8, 0x9efff1ff
+ },
+ { PIXMAN_OP_DISJOINT_ATOP,
+ PIXMAN_a4r4g4b4, 0xae5f,
+ PIXMAN_a8r8g8b8, 0xf215b675
+ },
+ { PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+ PIXMAN_a8r8g8b8, 0xce007980,
+ PIXMAN_a8r8g8b8, 0x80ffe4ad
+ },
+ { PIXMAN_OP_DISJOINT_XOR,
+ PIXMAN_a8r8g8b8, 0xb8b07bea,
+ PIXMAN_a4r4g4b4, 0x939c
+ },
+ { PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+ PIXMAN_r5g6b5, 0x0063,
+ PIXMAN_a8r8g8b8, 0x10bb1ed7,
+ },
+};
+
+static void
+fill (pixman_image_t *image, uint32_t pixel)
+{
+ uint8_t *data = (uint8_t *)pixman_image_get_data (image);
+ int bytes_per_pixel = PIXMAN_FORMAT_BPP (pixman_image_get_format (image)) / 8;
+ int n_bytes = pixman_image_get_stride (image) * pixman_image_get_height (image);
+ int i;
+
+ switch (bytes_per_pixel)
+ {
+ case 4:
+ for (i = 0; i < n_bytes / 4; ++i)
+ ((uint32_t *)data)[i] = pixel;
+ break;
+
+ case 2:
+ pixel &= 0xffff;
+ for (i = 0; i < n_bytes / 2; ++i)
+ ((uint16_t *)data)[i] = pixel;
+ break;
+
+ case 1:
+ pixel &= 0xff;
+ for (i = 0; i < n_bytes; ++i)
+ ((uint8_t *)data)[i] = pixel;
+ break;
+
+ default:
+ assert (0);
+ break;
+ }
+}
+
+static uint32_t
+access (pixman_image_t *image, int x, int y)
+{
+ int bytes_per_pixel;
+ int stride;
+ uint32_t result;
+ uint8_t *location;
+
+ if (x < 0 || x >= image->bits.width || y < 0 || y >= image->bits.height)
+ return 0;
+
+ bytes_per_pixel = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
+ stride = image->bits.rowstride * 4;
+
+ location = (uint8_t *)image->bits.bits + y * stride + x * bytes_per_pixel;
+
+ if (bytes_per_pixel == 4)
+ result = *(uint32_t *)location;
+ else if (bytes_per_pixel == 2)
+ result = *(uint16_t *)location;
+ else if (bytes_per_pixel == 1)
+ result = *(uint8_t *)location;
+ else
+ assert (0);
+
+ return result;
+}
+
+static pixman_bool_t
+verify (int test_no, const pixel_combination_t *combination, int size)
+{
+ pixman_image_t *src, *dest;
+ pixel_checker_t src_checker, dest_checker;
+ color_t source_color, dest_color, reference_color;
+ pixman_bool_t result = TRUE;
+ int i, j;
+
+ /* Compute reference color */
+ pixel_checker_init (&src_checker, combination->src_format);
+ pixel_checker_init (&dest_checker, combination->dest_format);
+ pixel_checker_convert_pixel_to_color (
+ &src_checker, combination->src_pixel, &source_color);
+ pixel_checker_convert_pixel_to_color (
+ &dest_checker, combination->dest_pixel, &dest_color);
+ do_composite (combination->op,
+ &source_color, NULL, &dest_color,
+ &reference_color, FALSE);
+
+ src = pixman_image_create_bits (
+ combination->src_format, size, size, NULL, -1);
+ dest = pixman_image_create_bits (
+ combination->dest_format, size, size, NULL, -1);
+
+ fill (src, combination->src_pixel);
+ fill (dest, combination->dest_pixel);
+
+ pixman_image_composite32 (
+ combination->op, src, NULL, dest, 0, 0, 0, 0, 0, 0, size, size);
+
+ for (j = 0; j < size; ++j)
+ {
+ for (i = 0; i < size; ++i)
+ {
+ uint32_t computed = access (dest, i, j);
+ int32_t a, r, g, b;
+
+ if (!pixel_checker_check (&dest_checker, computed, &reference_color))
+ {
+ printf ("----------- Test %d failed ----------\n", test_no);
+
+ printf (" operator: %s\n", operator_name (combination->op));
+ printf (" src format: %s\n", format_name (combination->src_format));
+ printf (" dest format: %s\n", format_name (combination->dest_format));
+ printf (" - source ARGB: %f %f %f %f (pixel: %8x)\n",
+ source_color.a, source_color.r, source_color.g, source_color.b,
+ combination->src_pixel);
+ pixel_checker_split_pixel (&src_checker, combination->src_pixel,
+ &a, &r, &g, &b);
+ printf (" %8d %8d %8d %8d\n", a, r, g, b);
+
+ printf (" - dest ARGB: %f %f %f %f (pixel: %8x)\n",
+ dest_color.a, dest_color.r, dest_color.g, dest_color.b,
+ combination->dest_pixel);
+ pixel_checker_split_pixel (&dest_checker, combination->dest_pixel,
+ &a, &r, &g, &b);
+ printf (" %8d %8d %8d %8d\n", a, r, g, b);
+
+ pixel_checker_split_pixel (&dest_checker, computed, &a, &r, &g, &b);
+ printf (" - expected ARGB: %f %f %f %f\n",
+ reference_color.a, reference_color.r, reference_color.g, reference_color.b);
+
+ pixel_checker_get_min (&dest_checker, &reference_color, &a, &r, &g, &b);
+ printf (" min acceptable: %8d %8d %8d %8d\n", a, r, g, b);
+
+ pixel_checker_split_pixel (&dest_checker, computed, &a, &r, &g, &b);
+ printf (" got: %8d %8d %8d %8d (pixel: %8x)\n", a, r, g, b, computed);
+
+ pixel_checker_get_max (&dest_checker, &reference_color, &a, &r, &g, &b);
+ printf (" max acceptable: %8d %8d %8d %8d\n", a, r, g, b);
+
+ result = FALSE;
+ goto done;
+ }
+ }
+ }
+
+done:
+ pixman_image_unref (src);
+ pixman_image_unref (dest);
+
+ return result;
+}
+
+int
+main (int argc, char **argv)
+{
+ int result = 0;
+ int i, j;
+
+ for (i = 0; i < ARRAY_LENGTH (regressions); ++i)
+ {
+ const pixel_combination_t *combination = &(regressions[i]);
+
+ for (j = 1; j < 34; ++j)
+ {
+ if (!verify (i, combination, j))
+ {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/pixman/test/utils.c b/pixman/test/utils.c
index ba7e35335..3d1ba22ae 100644
--- a/pixman/test/utils.c
+++ b/pixman/test/utils.c
@@ -1033,6 +1033,283 @@ format_name (pixman_format_code_t format)
};
static double
+calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
+{
+#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
+
+ double Fa, Fb;
+
+ switch (op)
+ {
+ case PIXMAN_OP_CLEAR:
+ case PIXMAN_OP_DISJOINT_CLEAR:
+ case PIXMAN_OP_CONJOINT_CLEAR:
+ return mult_chan (src, dst, 0.0, 0.0);
+
+ case PIXMAN_OP_SRC:
+ case PIXMAN_OP_DISJOINT_SRC:
+ case PIXMAN_OP_CONJOINT_SRC:
+ return mult_chan (src, dst, 1.0, 0.0);
+
+ case PIXMAN_OP_DST:
+ case PIXMAN_OP_DISJOINT_DST:
+ case PIXMAN_OP_CONJOINT_DST:
+ return mult_chan (src, dst, 0.0, 1.0);
+
+ case PIXMAN_OP_OVER:
+ return mult_chan (src, dst, 1.0, 1.0 - srca);
+
+ case PIXMAN_OP_OVER_REVERSE:
+ return mult_chan (src, dst, 1.0 - dsta, 1.0);
+
+ case PIXMAN_OP_IN:
+ return mult_chan (src, dst, dsta, 0.0);
+
+ case PIXMAN_OP_IN_REVERSE:
+ return mult_chan (src, dst, 0.0, srca);
+
+ case PIXMAN_OP_OUT:
+ return mult_chan (src, dst, 1.0 - dsta, 0.0);
+
+ case PIXMAN_OP_OUT_REVERSE:
+ return mult_chan (src, dst, 0.0, 1.0 - srca);
+
+ case PIXMAN_OP_ATOP:
+ return mult_chan (src, dst, dsta, 1.0 - srca);
+
+ case PIXMAN_OP_ATOP_REVERSE:
+ return mult_chan (src, dst, 1.0 - dsta, srca);
+
+ case PIXMAN_OP_XOR:
+ return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
+
+ case PIXMAN_OP_ADD:
+ return mult_chan (src, dst, 1.0, 1.0);
+
+ case PIXMAN_OP_SATURATE:
+ case PIXMAN_OP_DISJOINT_OVER_REVERSE:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, (1.0 - dsta) / srca);
+ return mult_chan (src, dst, Fa, 1.0);
+
+ case PIXMAN_OP_DISJOINT_OVER:
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, (1.0 - srca) / dsta);
+ return mult_chan (src, dst, 1.0, Fb);
+
+ case PIXMAN_OP_DISJOINT_IN:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
+ return mult_chan (src, dst, Fa, 0.0);
+
+ case PIXMAN_OP_DISJOINT_IN_REVERSE:
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
+ return mult_chan (src, dst, 0.0, Fb);
+
+ case PIXMAN_OP_DISJOINT_OUT:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, (1.0 - dsta) / srca);
+ return mult_chan (src, dst, Fa, 0.0);
+
+ case PIXMAN_OP_DISJOINT_OUT_REVERSE:
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, (1.0 - srca) / dsta);
+ return mult_chan (src, dst, 0.0, Fb);
+
+ case PIXMAN_OP_DISJOINT_ATOP:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, (1.0 - srca) / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, (1.0 - dsta) / srca);
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_DISJOINT_XOR:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, (1.0 - dsta) / srca);
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, (1.0 - srca) / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_CONJOINT_OVER:
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - srca / dsta);
+ return mult_chan (src, dst, 1.0, Fb);
+
+ case PIXMAN_OP_CONJOINT_OVER_REVERSE:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - dsta / srca);
+ return mult_chan (src, dst, Fa, 1.0);
+
+ case PIXMAN_OP_CONJOINT_IN:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, dsta / srca);
+ return mult_chan (src, dst, Fa, 0.0);
+
+ case PIXMAN_OP_CONJOINT_IN_REVERSE:
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, srca / dsta);
+ return mult_chan (src, dst, 0.0, Fb);
+
+ case PIXMAN_OP_CONJOINT_OUT:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - dsta / srca);
+ return mult_chan (src, dst, Fa, 0.0);
+
+ case PIXMAN_OP_CONJOINT_OUT_REVERSE:
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - srca / dsta);
+ return mult_chan (src, dst, 0.0, Fb);
+
+ case PIXMAN_OP_CONJOINT_ATOP:
+ if (srca == 0.0)
+ Fa = 1.0;
+ else
+ Fa = MIN (1.0, dsta / srca);
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - srca / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - dsta / srca);
+ if (dsta == 0.0)
+ Fb = 1.0;
+ else
+ Fb = MIN (1.0, srca / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_CONJOINT_XOR:
+ if (srca == 0.0)
+ Fa = 0.0;
+ else
+ Fa = MAX (0.0, 1.0 - dsta / srca);
+ if (dsta == 0.0)
+ Fb = 0.0;
+ else
+ Fb = MAX (0.0, 1.0 - srca / dsta);
+ return mult_chan (src, dst, Fa, Fb);
+
+ case PIXMAN_OP_MULTIPLY:
+ case PIXMAN_OP_SCREEN:
+ case PIXMAN_OP_OVERLAY:
+ case PIXMAN_OP_DARKEN:
+ case PIXMAN_OP_LIGHTEN:
+ case PIXMAN_OP_COLOR_DODGE:
+ case PIXMAN_OP_COLOR_BURN:
+ case PIXMAN_OP_HARD_LIGHT:
+ case PIXMAN_OP_SOFT_LIGHT:
+ case PIXMAN_OP_DIFFERENCE:
+ case PIXMAN_OP_EXCLUSION:
+ case PIXMAN_OP_HSL_HUE:
+ case PIXMAN_OP_HSL_SATURATION:
+ case PIXMAN_OP_HSL_COLOR:
+ case PIXMAN_OP_HSL_LUMINOSITY:
+ default:
+ abort();
+ return 0; /* silence MSVC */
+ }
+#undef mult_chan
+}
+
+void
+do_composite (pixman_op_t op,
+ const color_t *src,
+ const color_t *mask,
+ const color_t *dst,
+ color_t *result,
+ pixman_bool_t component_alpha)
+{
+ color_t srcval, srcalpha;
+
+ if (mask == NULL)
+ {
+ srcval = *src;
+
+ srcalpha.r = src->a;
+ srcalpha.g = src->a;
+ srcalpha.b = src->a;
+ srcalpha.a = src->a;
+ }
+ else if (component_alpha)
+ {
+ srcval.r = src->r * mask->r;
+ srcval.g = src->g * mask->g;
+ srcval.b = src->b * mask->b;
+ srcval.a = src->a * mask->a;
+
+ srcalpha.r = src->a * mask->r;
+ srcalpha.g = src->a * mask->g;
+ srcalpha.b = src->a * mask->b;
+ srcalpha.a = src->a * mask->a;
+ }
+ else
+ {
+ srcval.r = src->r * mask->a;
+ srcval.g = src->g * mask->a;
+ srcval.b = src->b * mask->a;
+ srcval.a = src->a * mask->a;
+
+ srcalpha.r = src->a * mask->a;
+ srcalpha.g = src->a * mask->a;
+ srcalpha.b = src->a * mask->a;
+ srcalpha.a = src->a * mask->a;
+ }
+
+ result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
+ result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
+ result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
+ result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
+}
+
+static double
round_channel (double p, int m)
{
int t;
@@ -1144,6 +1421,59 @@ pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
*b = (pixel & checker->bm) >> checker->bs;
}
+void
+pixel_checker_get_masks (const pixel_checker_t *checker,
+ uint32_t *am,
+ uint32_t *rm,
+ uint32_t *gm,
+ uint32_t *bm)
+{
+ if (am)
+ *am = checker->am;
+ if (rm)
+ *rm = checker->rm;
+ if (gm)
+ *gm = checker->gm;
+ if (bm)
+ *bm = checker->bm;
+}
+
+void
+pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
+ uint32_t pixel, color_t *color)
+{
+ int a, r, g, b;
+
+ pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
+
+ if (checker->am == 0)
+ color->a = 1.0;
+ else
+ color->a = a / (double)(checker->am >> checker->as);
+
+ if (checker->rm == 0)
+ color->r = 0.0;
+ else
+ color->r = r / (double)(checker->rm >> checker->rs);
+
+ if (checker->gm == 0)
+ color->g = 0.0;
+ else
+ color->g = g / (double)(checker->gm >> checker->gs);
+
+ if (checker->bm == 0)
+ color->b = 0.0;
+ else
+ color->b = b / (double)(checker->bm >> checker->bs);
+
+ if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
+ {
+ color->r = convert_srgb_to_linear (color->r);
+ color->g = convert_srgb_to_linear (color->g);
+ color->b = convert_srgb_to_linear (color->b);
+ }
+}
+
static int32_t
convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
{
@@ -1183,7 +1513,7 @@ get_limits (const pixel_checker_t *checker, double limit,
/* The acceptable deviation in units of [0.0, 1.0]
*/
-#define DEVIATION (0.004)
+#define DEVIATION (0.0064)
void
pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
diff --git a/pixman/test/utils.h b/pixman/test/utils.h
index 498831433..c2781516f 100644
--- a/pixman/test/utils.h
+++ b/pixman/test/utils.h
@@ -189,6 +189,14 @@ typedef struct
} color_t;
void
+do_composite (pixman_op_t op,
+ const color_t *src,
+ const color_t *mask,
+ const color_t *dst,
+ color_t *result,
+ pixman_bool_t component_alpha);
+
+void
round_color (pixman_format_code_t format, color_t *color);
typedef struct
@@ -217,3 +225,14 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
pixman_bool_t
pixel_checker_check (const pixel_checker_t *checker,
uint32_t pixel, color_t *color);
+
+void
+pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
+ uint32_t pixel, color_t *color);
+
+void
+pixel_checker_get_masks (const pixel_checker_t *checker,
+ uint32_t *am,
+ uint32_t *rm,
+ uint32_t *gm,
+ uint32_t *bm);