pixman: Branch 'master' - 12 commits
Søren Sandmann Pedersen
sandmann at kemper.freedesktop.org
Tue Feb 12 23:36:02 PST 2013
pixman/pixman-compiler.h | 6
pixman/pixman-implementation.c | 9 -
pixman/pixman-private.h | 36 ----
pixman/pixman-sse2.c | 4
pixman/pixman-utils.c | 4
test/Makefile.am | 2
test/Makefile.sources | 4
test/a1-trap-test.c | 8
test/check-formats.c | 352 +++++++++++++++++++++++++++++++++++++++++
test/composite.c | 277 --------------------------------
test/lowlevel-blt-bench.c | 14 -
test/pixel-test.c | 267 +++++++++++++++++++++++++++++++
test/utils.c | 332 ++++++++++++++++++++++++++++++++++++++
test/utils.h | 19 ++
14 files changed, 1007 insertions(+), 327 deletions(-)
New commits:
commit 5e207f825bd1ed3142a623bcbceca00508907c5e
Author: Ben Avison <bavison at riscosopen.org>
Date: Wed Feb 6 00:39:12 2013 +0000
Fix to lowlevel-blt-bench
The source, mask and destination buffers are initialised to 0xCC just after
they are allocated. Between each benchmark, there are a pair of memcpys,
from the destination buffer to the source buffer and back again (there are
no explanatory comments, but presumably this is an effort to flush the
caches). However, it has an unintended consequence, which is to change the
contents of the buffers on entry to subsequent benchmarks. This means it is
not a fair test: for example, with over_n_8888 (featured in the following
patches) it reports L2 and even M tests as being faster than the L1 test,
because after the L1 test, the source buffer is filled with fully opaque
pixels, for which over_n_8888 has a shortcut.
The fix here is simply to reverse the order of the memcpys, so src and
destination are both filled with 0xCC on entry to all tests.
diff --git a/test/lowlevel-blt-bench.c b/test/lowlevel-blt-bench.c
index 8e80b42..4e16f7b 100644
--- a/test/lowlevel-blt-bench.c
+++ b/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 ();
commit d26f922dc1a605dae00fa0540198707485ba1f08
Author: Stefan Weil <sw at weilnetz.de>
Date: Sat Feb 9 12:40:16 2013 +0100
sse2: Use uintptr_t in type casts from pointer to integral value
Some recent code added new type casts from pointer to unsigned long.
These type casts result in compiler warnings for systems like
MinGW-w64 (64 bit Windows) where sizeof(unsigned long) != sizeof(void *).
Signed-off-by: Stefan Weil <sw at weilnetz.de>
Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c
index fc873cc..c7e9a4b 100644
--- a/pixman/pixman-sse2.c
+++ b/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)
commit dc80eb09e2831d5ad3bfe638462f80921357952b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Thu Jan 31 14:54:49 2013 -0500
lookup_composite: Don't update cache in case of error
If we fail to find a composite function, don't update the fast path
cache with the dummy compositing function.
Also make the error message state that the bug is likely caused by
issues with thread local storage.
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index c0a6436..cfb82bb 100644
--- a/pixman/pixman-implementation.c
+++ b/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)
commit 4dced81c917c753a4e699e3793efa15a39361cf0
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Thu Jan 31 14:36:38 2013 -0500
Turn on error logging at all times
While releasing 0.29.2 the distcheck run produced a number of error
messages that had to be fixed in 349015e1fc5d912ba4253133b90e751d0b.
These were not caught before so nobody had actually run pixman with
debugging turned on. It's not the first time this has happened, see
5b0563f39eb29e4ae431717696174da5 for example.
So this patch makes the return_if_fail() macros use unlikely() around
the expressions and then turns on error logging at all times. The
performance hit should negligible since we were already evaluating the
expressions.
The place where DEBUG actually does cause a performance hit is in the
region selfcheck code, and that will still only be enabled in
development snapshots.
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index cb78a2e..181ab5c 100644
--- a/pixman/pixman-private.h
+++ b/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-utils.c b/pixman/pixman-utils.c
index b1e9fb6..f31171f 100644
--- a/pixman/pixman-utils.c
+++ b/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
commit f4c9492c12d98f76d99b4dbdca56d517e1ffdb19
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Thu Jan 31 14:31:26 2013 -0500
pixman-compiler.h: Add unlikely() macro
When compiling with GCC this macro expands to __builtin_expect((expr), 0).
On other compilers, it just expands to (expr).
diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h
index 2e45dea..9b190b4 100644
--- a/pixman/pixman-compiler.h
+++ b/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
commit 5ebb5ac3807cdc7bb76358041a15cc5adca2ef23
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Tue Jan 22 08:29:57 2013 -0500
utils.c: Increase acceptable deviation to 0.0064 in pixel_checker_t
The check-formats programs reveals that the 8 bit pipeline cannot meet
the current 0.004 acceptable deviation specified in utils.c, so we
have to increase it. Some of the failing pixels were captured in
pixel-test, which with this commit now passes.
== a4r4g4b4 DISJOINT_XOR a8r8g8b8 ==
The DISJOINT_XOR operator applied to an a4r4g4b4 source pixel of
0xd0c0 and a destination pixel of 0x5300ea00 results in the exact
value:
fa = (1 - da) / sa = (1 - 0x53 / 255.0) / (0xd / 15.0) = 0.7782
fb = (1 - sa) / da = (1 - 0xd / 15.0) / (0x53 / 255.0) = 0.4096
r = fa * (0xc / 15.0) + fb * (0xea / 255.0) = 0.99853
But when computing in 8 bits, we get:
fa8 = ((255 - 0x53) * 255 + 0xdd / 2) / 0xdd = 0xc6
fb8 = ((255 - 0xdd) * 255 + 0x53 / 3) / 0x53 = 0x68
r8 = (fa8 * 0xcc + 127) / 255 + (fb8 * 0xea + 127) / 255 = 0xfd
and
0xfd / 255.0 = 0.9921568627450981
for a deviation of 0.00637118610187, which we then have to consider
acceptable given the current implementation.
By switching to computing the result with
r = (fa * s + fb * d + 127) / 255
rather than
r = (fa * s + 127) / 255 + (fb * d + 127) / 255
the deviation would be only 0.00244961747442, so at some point it may
be worth doing either this, or switching to floating point for
operators that involve divisions.
Note that the conversion from 4 bits to 8 bits does not cause any
error in this case because both rounding and bit replication produces
an exact result when the number of from-bits divide the number of
to-bits.
== a8r8g8b8 OVER r5g6b5 ==
When OVER compositing the a8r8g8b8 pixel 0x0f00c300 with the x14r6g6b6
pixel 0x03c0, the true floating point value of the resulting green
channel is:
0xc3 / 255.0 + (1.0 - 0x0f / 255.0) * (0x0f / 63.0) = 0.9887955
but when compositing 8 bit values, where the 6-bit green channel is
converted to 8 bit through bit replication, the 8-bit result is:
0xc3 + ((255 - 0x0f) * 0x3c + 127) / 255 = 251
which corresponds to a real value of 0.984314. The difference from the
true value is 0.004482 which is bigger than the acceptable deviation
of 0.004. So, if we were to compute all the CONJOINT/DISJOINT
operators in floating point, or otherwise make them more accurate, the
acceptable deviation could be set at 0.0045.
If we were doing the 6-bit conversion with rounding:
(x / 63.0 * 255.0 + 0.5)
instead of bit replication, the deviation in this particular case
would be only 0.0005, so we may want to consider this at some
point.
diff --git a/test/utils.c b/test/utils.c
index 9a8decf..3d1ba22 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1513,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,
commit f2ba7fe1d812a30004b734e398f45b586833d43f
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Sat Jan 19 16:32:15 2013 -0500
test: Add new pixel-test regression test
This test program contains a table of individual operator/pixel
combinations. For each pixel combination, images of various sizes are
filled with the pixels and then composited. The result is then
verified against the output of do_composite(). If the result doesn't
match, detailed error information is printed.
The initial 14 pixel combinations currently all fail.
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 9d0bd0f..5b30970 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -6,6 +6,7 @@ TESTPROGRAMS = \
region-test \
region-translate-test \
combiner-test \
+ pixel-test \
fetch-test \
rotate-test \
oob-test \
diff --git a/test/pixel-test.c b/test/pixel-test.c
new file mode 100644
index 0000000..8c525d2
--- /dev/null
+++ b/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;
+}
commit 6781636740099633b9a8f7e0cc8e7828770f2fc3
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Mon Jan 21 15:02:53 2013 -0500
a1-trap-test: Add tests for operator_name and format_name()
The check-formats.c test depends on the exact format of the strings
returned from these functions, so add a test here.
a1-trap-test isn't the ideal place, but it seems like overkill to add
a new test just for these trivial checks.
diff --git a/test/a1-trap-test.c b/test/a1-trap-test.c
index 93c6caa..c2b4883 100644
--- a/test/a1-trap-test.c
+++ b/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;
}
commit d1434d112ca5cd325e4fb85fc60afd1b9e902786
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Mon Jan 21 15:54:05 2013 -0500
test: Add new check-formats utility
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.
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 e323a8e..9d0bd0f 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -28,8 +28,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);
+}
commit 1820131fe6674d46b9876965b30b331d593124a8
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Tue Jan 22 07:36:19 2013 -0500
utils.[ch]: Add pixel_checker_get_masks()
This function returns the a, r, g, and b masks corresponding to the
pixel checker's format.
diff --git a/test/utils.c b/test/utils.c
index eed2476..9a8decf 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1422,6 +1422,23 @@ pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
}
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)
{
diff --git a/test/utils.h b/test/utils.h
index f6dc193..c278151 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -229,3 +229,10 @@ pixel_checker_check (const pixel_checker_t *checker,
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);
commit 5eb61f72ea50e02eb185c746108909945b589e65
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Tue Jan 22 11:57:53 2013 -0500
test/utils.[ch]: Add pixel_checker_convert_pixel_to_color()
This function takes a pixel in the format corresponding to the pixel
checker, and converts to a color_t.
diff --git a/test/utils.c b/test/utils.c
index 27d8fd9..eed2476 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1421,6 +1421,42 @@ pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
*b = (pixel & checker->bm) >> checker->bs;
}
+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)
{
diff --git a/test/utils.h b/test/utils.h
index 162aacb..f6dc193 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -225,3 +225,7 @@ 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);
commit 3ae717f71a31620a5cb28792b9effd0c69ffb822
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Sat Jan 19 12:14:24 2013 -0500
test: Move do_composite() function from composite.c to utils.c
So that it can be used in other tests.
diff --git a/test/composite.c b/test/composite.c
index b107b11..9e51a8f 100644
--- a/test/composite.c
+++ b/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/test/utils.c b/test/utils.c
index ba7e353..27d8fd9 100644
--- a/test/utils.c
+++ b/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;
diff --git a/test/utils.h b/test/utils.h
index 4988314..162aacb 100644
--- a/test/utils.h
+++ b/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
More information about the xorg-commit
mailing list