[Pixman] [PATCH] test: Fix bug in color_correct() in composite.c
From: Søren Sandmann Pedersen This function was using the number of bits in a channel as if it were a mask, which lead to many spurious errors. With that fixed, we can turn on testing for all formats where all channels have 5 or more bits. Cc: ch...@chris-wilson.co.uk --- test/composite.c | 38 +++--- 1 files changed, 23 insertions(+), 15 deletions(-) diff --git a/test/composite.c b/test/composite.c index 0624cd3..cea44cb 100644 --- a/test/composite.c +++ b/test/composite.c @@ -85,7 +85,6 @@ compute_pixman_color (const color_t *color, static const format_t formats[] = { #define P(x) { PIXMAN_##x, #x } -P(a8), /* 32bpp formats */ P(a8r8g8b8), @@ -94,33 +93,40 @@ static const format_t formats[] = P(x8b8g8r8), P(b8g8r8a8), P(b8g8r8x8), - -/* XXX: and here the errors begin! */ -#if 0 P(x2r10g10b10), -P(a2r10g10b10), P(x2b10g10r10), -P(a2b10g10r10), /* 24bpp formats */ P(r8g8b8), P(b8g8r8), - -/* 16bpp formats */ P(r5g6b5), P(b5g6r5), -P(a1r5g5b5), +/* 16bpp formats */ P(x1r5g5b5), -P(a1b5g5r5), P(x1b5g5r5), -P(a4r4g4b4), -P(x4r4g4b4), + +/* 8bpp formats */ +P(a8), + +#if 0 +/* XXX: and here the errors begin! + * + * The formats below all have channels with 4 bits or less, and + * the eval_diff code doesn't deal correctly with that. + */ +P(a2r10g10b10), +P(a2b10g10r10), + +/* 16bpp formats */ +P(a1r5g5b5), +P(a1b5g5r5), P(a4b4g4r4), P(x4b4g4r4), +P(a4r4g4b4), +P(x4r4g4b4), /* 8bpp formats */ -P(a8), P(r3g3b2), P(b2g3r3), P(a2r2g2b2), @@ -482,8 +488,9 @@ static void color_correct (pixman_format_code_t format, color_t *color) { -#define round_pix(pix, mask) \ -((int)((pix) * (mask) + .5) / (double) (mask)) +#define MASK(x) ((1 << (x)) - 1) +#define round_pix(pix, m) \ +((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m))) if (PIXMAN_FORMAT_R (format) == 0) { @@ -504,6 +511,7 @@ color_correct (pixman_format_code_t format, color->a = round_pix (color->a, PIXMAN_FORMAT_A (format)); #undef round_pix +#undef MASK } static void -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] test: Fix eval_diff() so that it provides useful error values.
From: Søren Sandmann Pedersen Previously, this function would evaluate the error under the assumption that the format was 565 or wider. This patch changes it to take the actual format into account. With that fixed, we can turn on testing for the rest of the formats. Cc: ch...@chris-wilson.co.uk --- test/composite.c | 46 +++--- 1 files changed, 15 insertions(+), 31 deletions(-) diff --git a/test/composite.c b/test/composite.c index cea44cb..632e14b 100644 --- a/test/composite.c +++ b/test/composite.c @@ -86,7 +86,7 @@ static const format_t formats[] = { #define P(x) { PIXMAN_##x, #x } -/* 32bpp formats */ +/* 32 bpp formats */ P(a8r8g8b8), P(x8r8g8b8), P(a8b8g8r8), @@ -95,30 +95,18 @@ static const format_t formats[] = P(b8g8r8x8), P(x2r10g10b10), P(x2b10g10r10), +P(a2r10g10b10), +P(a2b10g10r10), -/* 24bpp formats */ +/* 24 bpp formats */ P(r8g8b8), P(b8g8r8), P(r5g6b5), P(b5g6r5), -/* 16bpp formats */ +/* 16 bpp formats */ P(x1r5g5b5), P(x1b5g5r5), - -/* 8bpp formats */ -P(a8), - -#if 0 -/* XXX: and here the errors begin! - * - * The formats below all have channels with 4 bits or less, and - * the eval_diff code doesn't deal correctly with that. - */ -P(a2r10g10b10), -P(a2b10g10r10), - -/* 16bpp formats */ P(a1r5g5b5), P(a1b5g5r5), P(a4b4g4r4), @@ -126,24 +114,23 @@ static const format_t formats[] = P(a4r4g4b4), P(x4r4g4b4), -/* 8bpp formats */ +/* 8 bpp formats */ +P(a8), P(r3g3b2), P(b2g3r3), P(a2r2g2b2), P(a2b2g2r2), - P(x4a4), -/* 4bpp formats */ +/* 4 bpp formats */ P(a4), P(r1g2b1), P(b1g2r1), P(a1r1g1b1), P(a1b1g1r1), -/* 1bpp formats */ +/* 1 bpp formats */ P(a1) -#endif #undef P }; @@ -602,18 +589,15 @@ get_pixel (pixman_image_t *image, } static double -eval_diff (color_t *expected, color_t *test) +eval_diff (color_t *expected, color_t *test, pixman_format_code_t format) { double rscale, gscale, bscale, ascale; double rdiff, gdiff, bdiff, adiff; -/* XXX: Need to be provided mask shifts so we can produce useful error - * values. - */ -rscale = 1.0 * (1 << 5); -gscale = 1.0 * (1 << 6); -bscale = 1.0 * (1 << 5); -ascale = 1.0 * 32; +rscale = 1.0 * ((1 << PIXMAN_FORMAT_R (format)) - 1); +gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)) - 1); +bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)) - 1); +ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)) - 1); rdiff = fabs (test->r - expected->r) * rscale; bdiff = fabs (test->g - expected->g) * gscale; @@ -707,7 +691,7 @@ composite_test (image_t *dst, &expected, component_alpha); color_correct (dst->format->format, &expected); -diff = eval_diff (&expected, &result); +diff = eval_diff (&expected, &result, dst->format->format); if (diff > 3.0) { char buf[40]; -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] test: Change composite so that it tests randomly generated images
From: Søren Sandmann Pedersen Previously this test would try to exhaustively test all combinations of formats and operators, which meant that it would take years to run. Instead, generate random images and test those. The random seed is based on time(), so we will get different tests every time it is run. Whenever the test fails, it will print what the value of lcg_seed was when the test began. This patch also adds a table of random seeds that have failed at some point. These seeds are run first before the random testing begins. Whenever this tests fails, you are supposed to add the seed that failed to the table, so that we can track that the bug doesn't get reintroduced. Cc: ch...@chris-wilson.co.uk --- test/Makefile.am |4 +- test/composite.c | 183 -- 2 files changed, 99 insertions(+), 88 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 841ff8d..322f3e3 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -15,7 +15,6 @@ TESTPROGRAMS =\ a1_trap_test_LDADD = $(TEST_LDADD) fetch_test_LDADD = $(TEST_LDADD) -composite_LDADD = $(TEST_LDADD) trap_crasher_LDADD = $(TEST_LDADD) oob_test_LDADD = $(TEST_LDADD) window_test_LDADD = $(TEST_LDADD) @@ -32,6 +31,9 @@ scaling_test_SOURCES = scaling-test.c utils.c utils.h alphamap_LDADD = $(TEST_LDADD) alphamap_SOURCES = alphamap.c utils.c utils.h +composite_LDADD = $(TEST_LDADD) +composite_SOURCES = composite.c utils.c utils.h + # GTK using test programs if HAVE_GTK diff --git a/test/composite.c b/test/composite.c index 632e14b..0610805 100644 --- a/test/composite.c +++ b/test/composite.c @@ -1,6 +1,7 @@ /* * Copyright © 2005 Eric Anholt * Copyright © 2009 Chris Wilson + * Copyright © 2010 Soeren Sandmann * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -20,15 +21,14 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ - +#define PIXMAN_USE_INTERNAL_API #include #include #include /* abort() */ #include #include - -#define FALSE 0 -#define TRUE !FALSE +#include +#include "utils.h" #define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0]))) #define min(a,b) ((a) <= (b) ? (a) : (b)) @@ -692,6 +692,11 @@ composite_test (image_t *dst, color_correct (dst->format->format, &expected); diff = eval_diff (&expected, &result, dst->format->format); + +/* FIXME: We should find out what deviation is acceptable. 3.0 + * is clearly absurd for 2 bit formats for example. On the other + * hand currently 1.0 does not work. + */ if (diff > 3.0) { char buf[40]; @@ -709,7 +714,7 @@ composite_test (image_t *dst, result.r, result.g, result.b, result.a, *(unsigned long *) pixman_image_get_data (dst->image), expected.r, expected.g, expected.b, expected.a); - + if (mask != NULL) { printf ("src color: %.2f %.2f %.2f %.2f\n" @@ -792,102 +797,106 @@ image_fini (image_t *info) pixman_image_unref (info->image); } -int -main (void) +static int +random_color (void) +{ +return lcg_rand_n (ARRAY_LENGTH (colors)); +} + +static int +random_format (void) +{ +return lcg_rand_n (ARRAY_LENGTH (formats)); +} + +static pixman_bool_t +run_test (void) { -pixman_bool_t ok, group_ok = TRUE, ca; -int i, d, m, s; -int tests_passed = 0, tests_total = 0; +uint32_t seed = lcg_seed; +image_t src, mask, dst; int sizes[] = { 1, 1 | REPEAT, 10 }; -int num_tests; +int n_sizes = ARRAY_LENGTH (sizes); +const operator_t *op; +int ca; +int ok; + +image_init (&dst, random_color(), random_format(), 1); +image_init (&src, random_color(), random_format(), lcg_rand_n (n_sizes)); +image_init (&mask, random_color(), random_format(), lcg_rand_n (n_sizes)); -for (i = 0; i < ARRAY_LENGTH (colors); i++) +op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]); + +ca = lcg_rand_n (3); + +switch (ca) { - colors[i].r *= colors[i].a; - colors[i].g *= colors[i].a; - colors[i].b *= colors[i].a; +case 0: + ok = composite_test (&dst, op, &src, NULL, FALSE); + break; +case 1: + ok = composite_test (&dst, op, &src, &mask, FALSE); + break; +case 2: + ok = composite_test (&dst, op, &src, &mask, +mask.size? TRUE : FALSE); + break; +default: + ok = FALSE; + break; } -num_tests = ARRAY_LENGTH (colors) * ARRAY_LENGTH (formats); +image_fini (&src); +image_fini (&mask); +image_fini (&dst); -for (d = 0; d < num_tests; d++) +if (!ok) { - image_
[Pixman] [PATCH] pixman.h: Only define stdint types when PIXMAN_DONT_DEFINE_STDINT is undefined
From: Søren Sandmann Pedersen In SPICE, with Microsoft Visual C++, pixman.h is included after another file that defines these types, which causes warnings and errors. This patch allows such code to just define PIXMAN_DONT_DEFINE_STDINT to use its own version of those types. Cc: al...@redhat.com --- pixman/pixman.h |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/pixman/pixman.h b/pixman/pixman.h index 69af0f9..ce1cca0 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -84,6 +84,9 @@ PIXMAN_BEGIN_DECLS /* * Standard integers */ + +#if !defined (PIXMAN_DONT_DEFINE_STDINT) + #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) || defined (__HP_cc) # include #elif defined (_MSC_VER) @@ -101,6 +104,8 @@ typedef unsigned __int64 uint64_t; # include #endif +#endif + /* * Boolean */ -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] When storing 4 bit pixels, make sure only the low 4 bits are stored.
From: Søren Sandmann Pedersen In some cases we end up trying to use the STORE_4 macro with an 8 bit values, which resulted in other pixels getting overwritten. Fix this by always masking away the high 4 bits. --- pixman/pixman-access.c | 22 ++ test/blitters-test.c |2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 389cf2a..fa0a267 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2445,9 +2445,12 @@ store_scanline_x4a4 (bits_image_t * image, do \ { \ int bo = 4 * (o); \ - STORE_8 (img, l, bo, (bo & 4 ? \ - (FETCH_8 (img, l, bo) & 0xf0) | (v) : \ - (FETCH_8 (img, l, bo) & 0x0f) | ((v) << 4))); \ + int v4 = (v) & 0x0f;\ + \ + STORE_8 (img, l, bo, ( \ +bo & 4 ? \ +(FETCH_8 (img, l, bo) & 0xf0) | (v4) : \ +(FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4))); \ } while (0) #else @@ -2455,9 +2458,12 @@ store_scanline_x4a4 (bits_image_t * image, do \ { \ int bo = 4 * (o); \ - STORE_8 (img, l, bo, (bo & 4 ? \ - (FETCH_8 (img, l, bo) & 0x0f) | ((v) << 4) : \ - (FETCH_8 (img, l, bo) & 0xf0) | (v)));\ + int v4 = (v) & 0x0f;\ + \ + STORE_8 (img, l, bo, ( \ +bo & 4 ? \ +(FETCH_8 (img, l, bo) & 0x0f) | (v4 << 4) :\ +(FETCH_8 (img, l, bo) & 0xf0) | (v4)));\ } while (0) #endif @@ -2484,11 +2490,11 @@ store_scanline_r1g2b1 (bits_image_t * image, { uint32_t *bits = image->bits + image->rowstride * y; int i; - + for (i = 0; i < width; ++i) { uint32_t pixel; - + SPLIT (values[i]); pixel = (((r >> 4) & 0x8) | ((g >> 5) & 0x6) | diff --git a/test/blitters-test.c b/test/blitters-test.c index c11917d..5e33031 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -482,7 +482,7 @@ main (int argc, char *argv[]) /* Predefined value for running with all the fastpath functions disabled. It needs to be updated every time when changes are introduced to this program or behavior of pixman changes! */ - if (crc == 0xEF7A1179) + if (crc == 0xA058F792) { printf ("blitters test passed\n"); } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/2] Thread local support on OS X
So apparently OS X does not support __thread which means current pixman does not compile there. See this: http://tinderbox.x.org/builds/2010-03-16-0022/logs/pixman/#build The following patches add some macros that expand to various types of thread local support. On Linux, Unix, and Windows they continue to expand to __thread and __declspec(thread), but on OS X they expand to a set of functions that use pthread_once() and pthread_get/setspecific() for thread local data. I'm not particularly happy with this, but the only alternative seems to be to just disable the fast path cache there. If anyone has better ideas, I'm interested. I have tested that the pthread_get/setspecific() code works on Linux, but I don't have any way to test it on OS X. I'd appreciate if someone can test it there. Of course, comments on the code are welcome too. Thanks, Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/2] Add checks for various types of thread local storage.
From: Søren Sandmann Pedersen OS X does not support __thread, so we have to check for it before using it. It does however support pthread_get/setspecific(), so if we don't have __thread, check if those are available. --- configure.ac | 80 pixman/Makefile.am |2 +- 2 files changed, 81 insertions(+), 1 deletions(-) diff --git a/configure.ac b/configure.ac index fed97b1..0bf5658 100644 --- a/configure.ac +++ b/configure.ac @@ -523,6 +523,86 @@ if test x$have_posix_memalign = xyes; then AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, [Whether we have posix_memalign()]) fi +dnl = +dnl Thread local storage + +support_for__thread=no + +AC_MSG_CHECKING(for __thread) +AC_COMPILE_IFELSE([ +__thread int x ; +int main () { return 0; } +], support_for__thread=yes) + +if test $support_for__thread = yes; then + AC_DEFINE([TOOLCHAIN_SUPPORTS__THREAD],[],[Whether the tool chain supports __thread]) +fi + +AC_MSG_RESULT($support_for__thread) + +dnl posix tls + +if test $support_for__thread = no; then + +support_for_pthread_setspecific=no + +AC_MSG_CHECKING(for pthread_setspecific) + +save_LDFLAGS=$LDFLAGS + +LDFLAGS="-pthread" + +AC_LINK_IFELSE([ +#include + +#include +#include + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; +static pthread_key_t key; + +static void +make_key (void) +{ +pthread_key_create (&key, NULL); +} + +int +main () +{ +void *value = NULL; + +if (pthread_once (&once_control, make_key) != 0) +{ + value = NULL; +} +else +{ + value = pthread_getspecific (key); + if (!value) + { + value = malloc (100); + pthread_setspecific (key, value); + } +} +} +], support_for_pthread_setspecific=yes); + +LDFLAGS=$save_LDFLAGS + +if test $support_for_pthread_setspecific = yes; then + PTHREAD_LDFLAGS="-pthread" + AC_DEFINE([HAVE_PTHREAD_SETSPECIFIC], [], [Whether pthread_setspecific() is supported]) +fi + +AC_MSG_RESULT($support_for_pthread_setspecific); + +fi + +AC_SUBST(TOOLCHAIN_SUPPORTS__THREAD) +AC_SUBST(HAVE_PTHREAD_SETSPECIFIC) +AC_SUBST(PTHREAD_LDFLAGS) + AC_OUTPUT([pixman-1.pc pixman-1-uninstalled.pc Makefile diff --git a/pixman/Makefile.am b/pixman/Makefile.am index 8ac6827..5a0e7a9 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES = libpixman-1.la -libpixman_1_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined +libpixman_1_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined @PTHREAD_LDFLAGS@ libpixman_1_la_LIBADD = @DEP_LIBS@ -lm libpixman_1_la_SOURCES = \ pixman.h\ -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] Add PIXMAN_DEFINE_THREAD_LOCAL() and PIXMAN_GET_THREAD_LOCAL() macros
From: Søren Sandmann Pedersen These macros hide the various types of thread local support. On Linux and Unix, they expand to just __thread. On Microsoft Visual C++, they expand to __declspec(thread). On OS X and other systems that don't have __thread, they expand to a complicated concoction that uses pthread_once() and pthread_get/set_specific() to get thread local variables. --- configure.ac |2 +- pixman/pixman-compiler.h | 63 + pixman/pixman.c | 37 --- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 0bf5658..d790bf3 100644 --- a/configure.ac +++ b/configure.ac @@ -532,7 +532,7 @@ AC_MSG_CHECKING(for __thread) AC_COMPILE_IFELSE([ __thread int x ; int main () { return 0; } -], support_for__thread=yes) +], support_for__thread=no) if test $support_for__thread = yes; then AC_DEFINE([TOOLCHAIN_SUPPORTS__THREAD],[],[Whether the tool chain supports __thread]) diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h index 5aeef86..a4e3f88 100644 --- a/pixman/pixman-compiler.h +++ b/pixman/pixman-compiler.h @@ -70,11 +70,62 @@ #endif /* TLS */ -#if (defined (__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR >= 3) || __GNUC__ > 3)) || defined(__SUNPRO_C) -#define THREAD_LOCAL __thread -#elif defined (_MSC_VER) -#define THREAD_LOCAL __declspec(thread) +#if defined(TOOLCHAIN_SUPPORTS__THREAD) + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ +static __thread type name +# define PIXMAN_GET_THREAD_LOCAL(name) \ +(&name) + +#elif defined(_MSC_VER) + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ +static __declspec(thread) type name +# define PIXMAN_GET_THREAD_LOCAL(name) \ +(&name) + +#elif defined(HAVE_PTHREAD_SETSPECIFIC) + +#include + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ +static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \ +static pthread_key_t tls_ ## name ## _key; \ + \ +static void \ +tls_ ## name ## _make_key (void) \ +{ \ + pthread_key_create (&tls_ ## name ## _key, NULL); \ +} \ + \ +static type * \ +tls_ ## name ## _alloc (key) \ +{ \ + type *value = malloc (sizeof (type)); \ + if (value) \ + pthread_setspecific (key, value); \ + return value; \ +} \ + \ +static force_inline type * \ +tls_ ## name ## _get (key) \ +{ \ + type *value = NULL; \ + if (pthread_once (&tls_ ## name ## _once_control, \ + tls_ ## name ## _make_key) == 0) \ + { \ + value = pthread_getspecific (tls_ ## name ## _key); \ + if (!value) \ + value = tls_ ## name ## _alloc (key); \ + } \ + return value; \ +} + +# define PIXMAN_GET_THREAD_LOCAL(name) \ +tls_ ## name ## _get (tls_ ## name ## _key) + #else -#warning "unknown compiler" -#define THREAD_LOCAL __thread + +#error "Unknown thread local support for this system" + #endif diff --git a/pixman/pixman.c b/pixman/pixman.c index c71617e..68483a0 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -499,6 +499,15 @@ image_covers (pixman_image_t *image, return TRUE; } +#define N_CACHED_FAST_PATHS 8 + +typedef struct +{ +pixman_fast_path_t cache [N_CACHED_FAST_PATHS]; +} cache_t; + +PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cac
[Pixman] [ANNOUNCE] pixman stable release 0.18.0 now available
A new major stable release 0.18.0 of the pixman library is now available. New features: - - Support for creating regions from images [Alexander Larsson] - Improved support for images larger than 16 bits [Benjamin Otte] Performance improvements: - Performance was a major theme of this release. Optimizations include: - Faster rescaling with nearest filter [Alexander Larsson, Siarhei Siamashka, Søren Sandmann Pedersen] - Faster rescaling with bilinear filter [André Tupinambá] - Many new fast paths for ARM NEON [Siarhei Siamashka] - Faster unantialised text rendering [Siarhei Siamashka] - Reduced overhead in fast path lookup [Søren] Results from a number of benchmarks in the cairo performance test suite on x86 and ARM. A number such as 1.84x means that on that particular benchmark pixman 0.18.0 runs 1.84 times faster than pixman 0.16.6. x86 evolution .. image ███▋ 1.06x image16 ███▍ 1.13x xlib ██▌ 1.04x firefox-planet-gnome ... image ███▌ 1.45x image16 ██▌ 1.20x xlib ██▎ 1.29x firefox-talos-gfx .. image ▊ 1.84x image16 ███▋ 2.00x xlib ▎ 1.35x firefox-talos-svg .. image ▍ 1.07x image16 ██▋ 1.04x xlib ███▊ 1.06x gnome-system-monitor ... image ███▌ 2.00x image16 ███▌ 2.00x xlib ▋ 1.01x gnome-terminal-vim . image █▎ 1.09x image16 █▊ 1.28x xlib ███▋ 1.23x poppler image 2.73x image16 2.73x xlib ▉ 2.09x gvim ... image █ 1.02x image16 ▊ 0.99x xlib ██▍ 1.04x swfdec-giant-steps . image ██▉ 1.05x image16 ██▌ 1.12x xlib ▎ 1.00x swfdec-youtube . image ▌ 1.48x image16 ██▉ 1.12x xlib ███▋ 1.45x ARM evolution .. image ██▎ 1.04x image16 ██▎ 1.04x xlib ▒▒▒▏ 0.95x firefox-planet-gnome ... image █▋ 1.27x image16 ██▎ 1.04x xlib ██▋ 1.30x firefox-talos-gfx .. image █▋ 1.39x image16 ███▌ 1.13x xlib ███ 1.12x firefox-talos-svg .. image █▋ 1.18x image16 ▌ 1.16x xlib ███▉ 1.14x gnome-system-monitor ... image ███▏ 1.75x image16 ██▋ 1.73x xlib ▊ 1.08x gnome-terminal-vim . image ██▎ 1.11x image16 ▎ 1.07x xlib ▍ 1.07x poppler image ███▌ 1.60x image16 ███▋ 1.60x xlib ███▎ 1.32x gvim ... image ▎ 1.00x image16 ▒▋ 0.97x xlib ▊ 1.01x swfdec-giant-steps . image █▌ 1.18x image16 ▋ 1.25x xlib ▋ 1.16x swfdec-youtube . image ██▌ 1.56x image16 ███▍ 1.22x xlib ██▉ 1.57x Thanks to everybody who contributed to 0.18.0, including: Alan Coopersmith, Alexander Larsson, Andrea Canciani, André Tupinambá, Benjamin Otte, Chris Wilson, Egor Starkov, Gaetan Nadon, Gerdus van Zyl, Guillem Jover, Jeremy Huddleston, Jon TURNEY, Loïc Minier, M Joonas Pihlaja, Makoto Kato, Marvin Schmidt, Pierre-Loup A. Griffais, Siarhei Siamashka, Søren Sandmann Pedersen Søren tar.gz: http://cairographics.org/releases/pixman-0.18.0.tar.gz http://xorg.freedesktop.org/archive/individual/lib/pixman-0.18.0.tar.gz tar.bz2: http://xorg.freedesktop.org/archive/individual/lib/pixman-0.18.0.tar.bz2 Hashes: MD5: a4fb870fc325be258089f1683642e976 pixman-0.18.0.tar.gz MD5: a1b5a0a145cab653f5c1e8cf2f98f945 pixman-0.18.0.tar.bz2 SHA1: 26d204499bd78d82801db50f620bba29c2686cfc pixman-0.18.0.tar.gz SHA1: 0ff0944b3335f156a94949842b429229e5ae1db4 pixman-0.18.0.tar.bz2 GPG signature: http://cairographics.org/releases/pixman-0.18.0.tar.gz.sha1.asc (signed by Søren Sandmann Pedersen ) Git: git://git.freedesktop.org/git/pixman tag: pixman-0.18.0 Log: Alan Coopersmith (3): Update Sun license notices to current X.Org standard form Make .s target asm flag selection more portable Add Sun cc to thread-local support checks in pixman-compiler.h Alexander Larsson (11): Add extern "C" guards for c++ Add pixman_image_get_destroy_data() Move SCREEN_SHIFT_LEFT/RIGHT to pixman-private.h Add pixman_region{32}_init_from_image Test pixman_region32_init_from_image in region-test Add CONVERT_0565_TO_ macro Add CONVERT__TO_ and CONVERT_0565_TO_0565 macros Add FAST_PATH_NO_NONE_REPEAT flag Add FAST_PATH_SAMPLES_COVER_CLIP and FAST_PATH_16BIT_SAFE Add specialized fast nearest scalers Use the right format for the OVER__565 fast path Andrea Canciani (1): Fix composite on big-endian systems. André Tupinambá (2): Speed up bilinear interpolation. Add fast path scaled, bilinear fetcher. Benjamin Otte (11): Fix compile warnings Add default cases for all switch statements --enable-maintainer-mode is
[Pixman] [ANNOUNCE] pixman release 0.18.0 now available [fixed formatting]
[Apologies for the previous misformatted announce email. Hopefully this one will get through correctly]. A new major stable release 0.18.0 of the pixman library is now available. New features: - - Support for creating regions from images [Alexander Larsson] - Improved support for images larger than 16 bits [Benjamin Otte] Performance improvements: - Performance was a major theme of this release. Optimizations include: - Faster rescaling with nearest filter [Alexander Larsson, Siarhei Siamashka, Søren Sandmann Pedersen] - Faster rescaling with bilinear filter [André Tupinambá] - Many new fast paths for ARM NEON [Siarhei Siamashka] - Faster unantialised text rendering [Siarhei Siamashka] - Reduced overhead in fast path lookup [Søren] Results from a number of benchmarks in the cairo performance test suite on x86 and ARM. A number such as 1.84x means that on that particular benchmark pixman 0.18.0 runs 1.84 times faster than pixman 0.16.6. x86 evolution .. image ███▋ 1.06x image16 ███▍ 1.13x xlib ██▌ 1.04x firefox-planet-gnome ... image ███▌ 1.45x image16 ██▌ 1.20x xlib ██▎ 1.29x firefox-talos-gfx .. image ▊ 1.84x image16 ███▋ 2.00x xlib ▎ 1.35x firefox-talos-svg .. image ▍ 1.07x image16 ██▋ 1.04x xlib ███▊ 1.06x gnome-system-monitor ... image ███▌ 2.00x image16 ███▌ 2.00x xlib ▋ 1.01x gnome-terminal-vim . image █▎ 1.09x image16 █▊ 1.28x xlib ███▋ 1.23x poppler image 2.73x image16 2.73x xlib ▉ 2.09x gvim ... image █ 1.02x image16 ▊ 0.99x xlib ██▍ 1.04x swfdec-giant-steps . image ██▉ 1.05x image16 ██▌ 1.12x xlib ▎ 1.00x swfdec-youtube . image ▌ 1.48x image16 ██▉ 1.12x xlib ███▋ 1.45x ARM evolution .. image ██▎ 1.04x image16 ██▎ 1.04x xlib ▒▒▒▏ 0.95x firefox-planet-gnome ... image █▋ 1.27x image16 ██▎ 1.04x xlib ██▋ 1.30x firefox-talos-gfx .. image █▋ 1.39x image16 ███▌ 1.13x xlib ███ 1.12x firefox-talos-svg .. image █▋ 1.18x image16 ▌ 1.16x xlib ███▉ 1.14x gnome-system-monitor ... image ███▏ 1.75x image16 ██▋ 1.73x xlib ▊ 1.08x gnome-terminal-vim . image ██▎ 1.11x image16 ▎ 1.07x xlib ▍ 1.07x poppler image ███▌ 1.60x image16 ███▋ 1.60x xlib ███▎ 1.32x gvim ... image ▎ 1.00x image16 ▒▋ 0.97x xlib ▊ 1.01x swfdec-giant-steps . image █▌ 1.18x image16 ▋ 1.25x xlib ▋ 1.16x swfdec-youtube . image ██▌ 1.56x image16 ███▍ 1.22x xlib ██▉ 1.57x Thanks to everybody who contributed to 0.18.0, including: Alan Coopersmith, Alexander Larsson, Andrea Canciani, André Tupinambá, Benjamin Otte, Chris Wilson, Egor Starkov, Gaetan Nadon, Gerdus van Zyl, Guillem Jover, Jeremy Huddleston, Jon TURNEY, Loïc Minier, M Joonas Pihlaja, Makoto Kato, Marvin Schmidt, Pierre-Loup A. Griffais, Siarhei Siamashka, Søren Sandmann Pedersen Søren tar.gz: http://cairographics.org/releases/pixman-0.18.0.tar.gz http://xorg.freedesktop.org/archive/individual/lib/pixman-0.18.0.tar.gz tar.bz2: http://xorg.freedesktop.org/archive/individual/lib/pixman-0.18.0.tar.bz2 Hashes: MD5: a4fb870fc325be258089f1683642e976 pixman-0.18.0.tar.gz MD5: a1b5a0a145cab653f5c1e8cf2f98f945 pixman-0.18.0.tar.bz2 SHA1
[Pixman] [PATCH 1/2] Extend blitters test to first check known failure cases
From: Søren Sandmann Pedersen This serves to make sure we don't accidentally reintroduce old bugs. --- test/blitters-test.c | 43 +++ 1 files changed, 43 insertions(+), 0 deletions(-) diff --git a/test/blitters-test.c b/test/blitters-test.c index 5e33031..25b3c7b 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -437,6 +437,46 @@ initialize_palette (void) palette.ent[i] = lcg_rand() & 0xff; } +typedef struct +{ +uint32_t nth; +uint32_t crc; +} testcase_t; + +static testcase_t known_failures[] = +{ +{ 592654, 0x06BF6ADE }, +}; + +static int +run_known_failures (void) +{ +int i; + +for (i = 0; i < sizeof (known_failures) / sizeof (known_failures[0]); ++i) +{ + testcase_t *testcase = &(known_failures[i]); + uint32_t crc; + + crc = test_composite (0, testcase->nth, 0); + + if (crc != testcase->crc) + { + crc = test_composite (0, testcase->nth, 1); + + printf ("Test case %d failed\n" + "CRC: %08x\n" + "Expected: %08x\n", + testcase->nth, + crc, + testcase->crc); + return 1; + } +} + +return 0; +} + int main (int argc, char *argv[]) { @@ -446,6 +486,9 @@ main (int argc, char *argv[]) initialize_palette(); +if (run_known_failures ()) + return 1; + if (argc >= 3) { n1 = atoi (argv[1]); -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] [mmx] Fix mask creation bugs
From: Søren Sandmann Pedersen This line: mask = mask | mask >> 8 | mask >> 16 | mask >> 24; only works when mask has 0s in the lower 24 bits, so add mask &= 0xff00; before. Reported by Todd Rinaldo on the #cairo IRC channel. --- pixman/pixman-mmx.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index e084e7f..d51b40c 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -1385,6 +1385,7 @@ mmx_composite_over__n_ (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (mask_image, dst_image->bits.format); +mask &= 0xff00; mask = mask | mask >> 8 | mask >> 16 | mask >> 24; vmask = load (mask); srca = MC (4x00ff); @@ -1470,6 +1471,7 @@ mmx_composite_over_x888_n_ (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (mask_image, dst_image->bits.format); +mask &= 0xff00; mask = mask | mask >> 8 | mask >> 16 | mask >> 24; vmask = load (mask); srca = MC (4x00ff); -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add pixman_image_get_format() accessor
From: Søren Sandmann Pedersen --- pixman/pixman-image.c |9 + pixman/pixman.h |1 + 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 9b44aa9..9604bfe 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -739,6 +739,15 @@ pixman_image_get_depth (pixman_image_t *image) return 0; } +PIXMAN_EXPORT pixman_format_code_t +pixman_image_get_format (pixman_image_t *image) +{ +if (image->type == BITS) + return image->bits.format; + +return 0; +} + uint32_t _pixman_image_get_solid (pixman_image_t * image, pixman_format_code_t format) diff --git a/pixman/pixman.h b/pixman/pixman.h index 964d04a..7b95fed 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -778,6 +778,7 @@ int pixman_image_get_width (pixman_image_t *image); int pixman_image_get_height (pixman_image_t *image); intpixman_image_get_stride (pixman_image_t *image); /* in bytes */ intpixman_image_get_depth (pixman_image_t *image); +pixman_format_code_t pixman_image_get_format(pixman_image_t *image); pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, pixman_image_t *image, pixman_color_t *color, -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] Misc patches
This is a series of asssorted patches that I've had lying around for a while. Here's what's in it: - Use memcpy() for SRC compositing in various cases. There was already a memcpy() based fast path, but it was only used for SRC__x888. There is no reason not to used for all copying between identical formats. - Add pixman_region{,32}_intersect_rect(). We already have a _union_rect(), and intersecting with a rectangle is pretty common. - SSE2 fast paths: - OVER xx. I have seen this on some benchmark, but I can't remember which one. If anyone knows, please let me know. - OVER_REVERSE n_. Poppler uses this, presumably to composite a white background behind an image. This fast path is a small speed-up on the poppler cairo trace. - Support for 8bpp in pixman_fill_sse2(). Previously this would fall back to MMX for no good reason. - A bug fix: Currently we consider indexed formats opaque which is wrong because their palettes could contain non-opaque colors. Adding the over_reverse fast path triggered this because the opaqueness caused an ATOP_REVERSE to be strength-reduced to OVER_REVERSE. - A patch from Benjamin to detect and use bswap_32() if it is available. When compiling for 486 or later, this macro expands to the bswap instruction. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/7] Rename fast_composite_src_8888_x888 to fast_composite_src_memcpy()
From: Søren Sandmann Pedersen Then generalize it and use it for SRC copying between various identical formats. --- pixman/pixman-fast-path.c | 60 1 files changed, 38 insertions(+), 22 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index bf5b298..c4dd3a6 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1315,27 +1315,31 @@ fast_composite_solid_fill (pixman_implementation_t *imp, } static void -fast_composite_src__x888 (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +fast_composite_src_memcpy (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { -uint32_t*dst; -uint32_t*src; +int bpp = PIXMAN_FORMAT_BPP (dst_image->bits.format) / 8; +uint32_t n_bytes = width * bpp; int dst_stride, src_stride; -uint32_t n_bytes = width * sizeof (uint32_t); +uint8_t*dst; +uint8_t*src; + +src_stride = src_image->bits.rowstride * 4; +dst_stride = dst_image->bits.rowstride * 4; -PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src, 1); -PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst, 1); +src = (uint8_t *)src_image->bits.bits + src_y * src_stride + src_x * bpp; +dst = (uint8_t *)dst_image->bits.bits + dest_y * dst_stride + dest_x * bpp; while (height--) { @@ -1792,10 +1796,22 @@ static const pixman_fast_path_t c_fast_paths[] = PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill), PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill), PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill), -PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src__x888), -PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src__x888), -PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src__x888), -PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src__x888), +PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8x8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, b8g8r8a8, null, b8g8r8a8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, b8g8r8x8, null, b8g8r8x8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, b8g8r8, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, fast_composite_src_memcpy), +PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, fast_composite_src_memcpy), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composit
[Pixman] [PATCH 2/7] Add pixman_region{,32}_intersect_rect()
From: Søren Sandmann Pedersen --- pixman/pixman-region.c | 18 ++ pixman/pixman.h| 13 - 2 files changed, 30 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c index a6a4005..3ea88a0 100644 --- a/pixman/pixman-region.c +++ b/pixman/pixman-region.c @@ -1329,6 +1329,24 @@ pixman_region_union_o (region_type_t *region, return TRUE; } +PIXMAN_EXPORT pixman_bool_t +PREFIX(_intersect_rect) (region_type_t *dest, +region_type_t *source, +int x, int y, +unsigned int width, +unsigned int height) +{ +region_type_t region; + +region.data = NULL; +region.extents.x1 = x; +region.extents.y1 = y; +region.extents.x2 = x + width; +region.extents.y2 = y + height; + +return PREFIX(_intersect) (dest, source, ®ion); +} + /* Convenience function for performing union of region with a * single rectangle */ diff --git a/pixman/pixman.h b/pixman/pixman.h index 7b95fed..8df5813 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -420,7 +420,6 @@ voidpixman_region_init_from_image (pixman_region16_t *reg voidpixman_region_fini (pixman_region16_t *region); - /* manipulation */ voidpixman_region_translate (pixman_region16_t *region, intx, @@ -439,6 +438,12 @@ pixman_bool_t pixman_region_union_rect (pixman_region16_t *des inty, unsigned int width, unsigned int height); +pixman_bool_t pixman_region_intersect_rect (pixman_region16_t *dest, + pixman_region16_t *source, + intx, + inty, + unsigned int width, + unsigned int height); pixman_bool_t pixman_region_subtract (pixman_region16_t *reg_d, pixman_region16_t *reg_m, pixman_region16_t *reg_s); @@ -521,6 +526,12 @@ pixman_bool_t pixman_region32_intersect (pixman_region32_t *n pixman_bool_t pixman_region32_union (pixman_region32_t *new_reg, pixman_region32_t *reg1, pixman_region32_t *reg2); +pixman_bool_t pixman_region32_intersect_rect (pixman_region32_t *dest, + pixman_region32_t *source, + int x, + int y, + unsigned int width, + unsigned int height); pixman_bool_t pixman_region32_union_rect (pixman_region32_t *dest, pixman_region32_t *source, int x, -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/7] Add an over_8888_8888_8888 sse2 fast path.
From: Søren Sandmann Pedersen --- pixman/pixman-sse2.c | 168 ++ 1 files changed, 168 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 946e7ba..09da14d 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -5765,6 +5765,173 @@ sse2_composite_over__8_ (pixman_implementation_t *imp, _mm_empty (); } +static void +sse2_composite_over___ (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint32_t*src, *src_line, s; +uint32_t*dst, *dst_line, d; +uint32_t*mask, *mask_line; +uint32_tm; +int src_stride, mask_stride, dst_stride; +int32_t w; + +__m128i xmm_src, xmm_src_lo, xmm_src_hi, xmm_srca_lo, xmm_srca_hi; +__m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; +__m128i xmm_mask, xmm_mask_lo, xmm_mask_hi; + +PIXMAN_IMAGE_GET_LINE ( + dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); +PIXMAN_IMAGE_GET_LINE ( + mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1); +PIXMAN_IMAGE_GET_LINE ( + src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + +while (height--) +{ +src = src_line; +src_line += src_stride; +dst = dst_line; +dst_line += dst_stride; +mask = mask_line; +mask_line += mask_stride; + +w = width; + +/* call prefetch hint to optimize cache load*/ +cache_prefetch ((__m128i *)src); +cache_prefetch ((__m128i *)dst); +cache_prefetch ((__m128i *)mask); + +while (w && (unsigned long)dst & 15) +{ + uint32_t sa; + +s = *src++; +m = (*mask++) >> 24; +d = *dst; + + sa = s >> 24; + + if (m) + { + if (sa == 0xff && m == 0xff) + { + *dst = s; + } + else + { + __m64 ms, md, ma, msa; + + ma = expand_alpha_rev_1x64 (load_32_1x64 (m)); + ms = unpack_32_1x64 (s); + md = unpack_32_1x64 (d); + + msa = expand_alpha_rev_1x64 (load_32_1x64 (sa)); + + *dst = pack_1x64_32 (in_over_1x64 (&ms, &msa, &ma, &md)); + } + } + + dst++; +w--; +} + +/* call prefetch hint to optimize cache load*/ +cache_prefetch ((__m128i *)src); +cache_prefetch ((__m128i *)dst); +cache_prefetch ((__m128i *)mask); + +while (w >= 4) +{ +/* fill cache line with next memory */ +cache_prefetch_next ((__m128i *)src); +cache_prefetch_next ((__m128i *)dst); +cache_prefetch_next ((__m128i *)mask); + + xmm_mask = load_128_unaligned ((__m128i*)mask); + + if (!is_transparent (xmm_mask)) + { + xmm_src = load_128_unaligned ((__m128i*)src); + + if (is_opaque (xmm_mask) && is_opaque (xmm_src)) + { + save_128_aligned ((__m128i *)dst, xmm_src); + } + else + { + xmm_dst = load_128_aligned ((__m128i *)dst); + + unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); + unpack_128_2x128 (xmm_mask, &xmm_mask_lo, &xmm_mask_hi); + unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); + + expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi); + expand_alpha_2x128 (xmm_mask_lo, xmm_mask_hi, &xmm_mask_lo, &xmm_mask_hi); + + in_over_2x128 (&xmm_src_lo, &xmm_src_hi, &xmm_srca_lo, &xmm_srca_hi, + &xmm_mask_lo, &xmm_mask_hi, &xmm_dst_lo, &xmm_dst_hi); + + save_128_aligned ((__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); + } +
[Pixman] [PATCH 4/7] Don't consider indexed formats opaque.
From: Søren Sandmann Pedersen The indexed formats have 0 bits of alpha, but can't be considered opaque because there may be non-opaque colors in the palette. --- pixman/pixman-image.c |6 -- test/blitters-test.c |2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 9604bfe..6b0dc6d 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -394,8 +394,10 @@ compute_image_info (pixman_image_t *image) } } - if (image->common.repeat != PIXMAN_REPEAT_NONE && - !PIXMAN_FORMAT_A (image->bits.format)) + if (image->common.repeat != PIXMAN_REPEAT_NONE && + !PIXMAN_FORMAT_A (image->bits.format) && + PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY && + PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR) { flags |= FAST_PATH_IS_OPAQUE; } diff --git a/test/blitters-test.c b/test/blitters-test.c index 5e33031..18f871e 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -482,7 +482,7 @@ main (int argc, char *argv[]) /* Predefined value for running with all the fastpath functions disabled. It needs to be updated every time when changes are introduced to this program or behavior of pixman changes! */ - if (crc == 0xA058F792) + if (crc == 0x8F9F7DC1) { printf ("blitters test passed\n"); } -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 5/7] sse2: Add sse2_composite_over_reverse_n_8888
From: Søren Sandmann Pedersen This is a small speed-up for the poppler benchmark: Before: [ # ] backend test min(s) median(s) stddev. count [ 0]image poppler4.4434.474 0.31%6/6 After: [ # ] backend test min(s) median(s) stddev. count [ 0]image poppler4.2244.248 0.42%6/6 --- pixman/pixman-sse2.c | 104 ++ 1 files changed, 104 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 09da14d..3f474d7 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -5766,6 +5766,106 @@ sse2_composite_over__8_ (pixman_implementation_t *imp, } static void +sse2_composite_over_reverse_n_ (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint32_t src; +uint32_t*dst_line, *dst; +__m128i xmm_src; +__m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; +__m128i xmm_dsta_hi, xmm_dsta_lo; +int dst_stride; +int32_t w; + +src = _pixman_image_get_solid (src_image, dst_image->bits.format); + +if (src == 0) + return; + +PIXMAN_IMAGE_GET_LINE ( + dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); + +xmm_src = expand_pixel_32_1x128 (src); + +while (height--) +{ + dst = dst_line; + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)dst); + + dst_line += dst_stride; + w = width; + + while (w && (unsigned long)dst & 15) + { + __m64 vd; + + vd = unpack_32_1x64 (*dst); + + *dst = pack_1x64_32 (over_1x64 (vd, expand_alpha_1x64 (vd), + _mm_movepi64_pi64 (xmm_src))); + w--; + dst++; + } + + cache_prefetch ((__m128i*)dst); + + while (w >= 4) + { + __m128i tmp_lo, tmp_hi; + + /* fill cache line with next memory */ + cache_prefetch_next ((__m128i*)(dst + 4)); + + xmm_dst = load_128_aligned ((__m128i*)dst); + + unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); + expand_alpha_2x128 (xmm_dst_lo, xmm_dst_hi, &xmm_dsta_lo, &xmm_dsta_hi); + + tmp_lo = xmm_src; + tmp_hi = xmm_src; + + over_2x128 (&xmm_dst_lo, &xmm_dst_hi, + &xmm_dsta_lo, &xmm_dsta_hi, + &tmp_lo, &tmp_hi); + + save_128_aligned ( + (__m128i*)dst, pack_2x128_128 (tmp_lo, tmp_hi)); + + w -= 4; + dst += 4; + } + + while (w) + { + __m64 vd; + + vd = unpack_32_1x64 (*dst); + + *dst = pack_1x64_32 (over_1x64 (vd, expand_alpha_1x64 (vd), + _mm_movepi64_pi64 (xmm_src))); + w--; + dst++; + } + +} + +_mm_empty (); +} + +static void sse2_composite_over___ (pixman_implementation_t *imp, pixman_op_t op, pixman_image_t * src_image, @@ -5982,6 +6082,10 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), +/* PIXMAN_OP_OVER_REVERSE */ +PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, sse2_composite_over_reverse_n_), +PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, sse2_composite_over_reverse_n_), + /* PIXMAN_OP_ADD */ PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, sse2_composite_add_n___ca), PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, sse2_composite_add_8000_8000), -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 6/7] Add support for 8bpp to pixman_fill_sse2()
From: Søren Sandmann Pedersen --- pixman/pixman-sse2.c | 39 ++- 1 files changed, 34 insertions(+), 5 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 3f474d7..d5349d7 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -3981,24 +3981,40 @@ pixman_fill_sse2 (uint32_t *bits, __m128i xmm_def; -if (bpp != 16 && bpp != 32) - return FALSE; +if (bpp == 8) +{ + uint8_t b; + uint16_t w; + + stride = stride * (int) sizeof (uint32_t) / 1; + byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x); + byte_width = width; + stride *= 1; -if (bpp == 16) + b = data & 0xff; + w = (b << 8) | b; + data = (w << 16) | w; +} +else if (bpp == 16) { stride = stride * (int) sizeof (uint32_t) / 2; byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); byte_width = 2 * width; stride *= 2; + data = (data & 0x) * 0x00010001; } -else +else if (bpp == 32) { stride = stride * (int) sizeof (uint32_t) / 4; byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x); byte_width = 4 * width; stride *= 4; } +else +{ + return FALSE; +} cache_prefetch ((__m128i*)byte_line); xmm_def = create_mask_2x32_128 (data, data); @@ -4010,9 +4026,15 @@ pixman_fill_sse2 (uint32_t *bits, byte_line += stride; w = byte_width; - cache_prefetch_next ((__m128i*)d); + while (w >= 1 && ((unsigned long)d & 1)) + { + *(uint8_t *)d = data; + w -= 1; + d += 1; + } + while (w >= 2 && ((unsigned long)d & 3)) { *(uint16_t *)d = data; @@ -4095,6 +4117,13 @@ pixman_fill_sse2 (uint32_t *bits, w -= 2; d += 2; } + + if (w >= 1) + { + *(uint8_t *)d = data; + w -= 1; + d += 1; + } } _mm_empty (); -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 7/7] Add bswap() macros and use them
From: Benjamin Otte Code taken from Cairo. --- configure.ac|1 + pixman/pixman-access.c | 35 +-- pixman/pixman-private.h | 18 ++ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/configure.ac b/configure.ac index aabe721..7aed963 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,7 @@ AC_PROG_CC AM_PROG_AS AC_PROG_LIBTOOL AC_CHECK_FUNCS([getisax]) +AC_CHECK_HEADERS(byteswap.h) AC_C_BIGENDIAN AC_C_INLINE diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index fa0a267..5e203f6 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -184,11 +184,8 @@ fetch_scanline_b8g8r8a8 (pixman_image_t *image, while (pixel < end) { uint32_t p = READ (image, pixel++); - - *buffer++ = (((p & 0xff00) >> 24) | -((p & 0x00ff) >> 8)| -((p & 0xff00) << 8)| -((p & 0x00ff) << 24)); + + *buffer++ = bswap_32 (p); } } @@ -209,10 +206,7 @@ fetch_scanline_b8g8r8x8 (pixman_image_t *image, { uint32_t p = READ (image, pixel++); - *buffer++ = (0xff00 | -((p & 0xff00) >> 24) | -((p & 0x00ff) >> 8)| -((p & 0xff00) << 8)); + *buffer++ = 0xff00 | bswap_32 (p); } } @@ -1285,10 +1279,7 @@ fetch_pixel_b8g8r8a8 (bits_image_t *image, uint32_t *bits = image->bits + line * image->rowstride; uint32_t pixel = READ (image, (uint32_t *)bits + offset); -return ((pixel & 0xff00) >> 24 | - (pixel & 0x00ff) >> 8 | - (pixel & 0xff00) << 8 | - (pixel & 0x00ff) << 24); +return bswap_32 (pixel); } static uint32_t @@ -1299,10 +1290,7 @@ fetch_pixel_b8g8r8x8 (bits_image_t *image, uint32_t *bits = image->bits + line * image->rowstride; uint32_t pixel = READ (image, (uint32_t *)bits + offset); -return ((0xff00) | - (pixel & 0xff00) >> 24 | - (pixel & 0x00ff) >> 8 | - (pixel & 0xff00) << 8); +return 0xff00 | bswap_32 (pixel); } static uint32_t @@ -1997,11 +1985,8 @@ store_scanline_b8g8r8a8 (bits_image_t * image, for (i = 0; i < width; ++i) { - WRITE (image, pixel++, - ((values[i] >> 24) & 0x00ff) | - ((values[i] >> 8) & 0xff00) | - ((values[i] << 8) & 0x00ff) | - ((values[i] << 24) & 0xff00)); +uint32_t p = bswap_32 (values[i]); + WRITE (image, pixel++, p); } } @@ -2018,10 +2003,8 @@ store_scanline_b8g8r8x8 (bits_image_t * image, for (i = 0; i < width; ++i) { - WRITE (image, pixel++, - ((values[i] >> 8) & 0xff00) | - ((values[i] << 8) & 0x00ff) | - ((values[i] << 24) & 0xff00)); +uint32_t p = bswap_32 (values[i]); + WRITE (image, pixel++, p); } } diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d5767af..c4f5064 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -686,6 +686,24 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, # define MAX(a, b) ((a > b) ? a : b) #endif +/* Byte swapping */ +#if HAVE_BYTESWAP_H +# include +#endif +#ifndef bswap_16 +# define bswap_16(p) \ + (uint16_t)(p)) & 0x00ff) << 8) | \ + (((uint16_t)(p)) >> 8)); +#endif +#ifndef bswap_32 +# define bswap_32(p) \ + (uint32_t)(p)) & 0x00ff) << 24) | \ + uint32_t)(p)) & 0xff00) << 8) | \ + uint32_t)(p)) & 0x00ff) >> 8) | \ + uint32_t)(p))) >> 24)); +#endif + + /* Integer division that rounds towards -infinity */ #define DIV(a, b) \ a) < 0) == ((b) < 0)) ? (a) / (b) :\ -- 1.7.0.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] MinGW thread local storage
Hi, The patches below are supposed to fix the thread local storage issue on MinGW 32. Apparently, __thread is "supported" in the latest GCC, but doesn't actually work. The first patch here simply disables __thread if MinGW32 is detected. The second patch is based on Tor's code from here: http://lists.freedesktop.org/archives/pixman/2010-April/000160.html Sven Goericke tested a tarball with these patches applied, so it apparently works, but more testing from people using MinGW32 would be appreciated. Also, I would still like to know if which pixman identifiers the file is clashing with; maybe we can just rename those. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Don't use __thread on MinGW.
From: Søren Sandmann Pedersen It is apparently broken. See this: http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-thread-specifier-not-working-td3440749.html We'll need to support thread local storage on MinGW32 some other way. Cc: t...@iki.fi --- configure.ac |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index aabe721..c9d0c66 100644 --- a/configure.ac +++ b/configure.ac @@ -524,6 +524,9 @@ support_for__thread=no AC_MSG_CHECKING(for __thread) AC_COMPILE_IFELSE([ +#ifdef __MINGW32__ +#error MinGW has broken __thread support +#endif __thread int x ; int main () { return 0; } ], support_for__thread=yes) -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add macros for thread local storage on MinGW 32
From: Søren Sandmann Pedersen These macros are identical to the ones that Tor Lillqvist posted here: http://lists.freedesktop.org/archives/pixman/2010-April/000160.html with one exception: the variable is allocated with calloc() and not malloc(). Cc: t...@iki.fi --- pixman/pixman-compiler.h | 65 ++ 1 files changed, 65 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h index 531c8c9..1a1350d 100644 --- a/pixman/pixman-compiler.h +++ b/pixman/pixman-compiler.h @@ -77,6 +77,71 @@ # define PIXMAN_GET_THREAD_LOCAL(name) \ (&name) +#elif defined(__MINGW32__) && !defined(__WIN64) + +/* We can't include as it causes carious clashes with + * identifiers in pixman, sigh. So just declare the functions we need + * here. + */ +extern __stdcall long InterlockedCompareExchange(long volatile *, long, long); +#define InterlockedCompareExchangePointer(d,e,c) \ +(void *)InterlockedCompareExchange((long volatile *)(d),(long)(e),(long)(c)) +extern __stdcall int TlsAlloc (void); +extern __stdcall void *TlsGetValue (unsigned); +extern __stdcall int TlsSetValue (unsigned, void *); +extern __stdcall void *CreateMutexA(void *, int, char *); +extern __stdcall int CloseHandle(void *); +extern __stdcall unsigned WaitForSingleObject (void *, unsigned); +extern __stdcall int ReleaseMutex (void *); + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ +static volatile int tls_ ## name ## _initialized = 0; \ +static void *tls_ ## name ## _mutex = NULL; \ +static unsigned tls_ ## name ## _index;\ + \ +static type * \ +tls_ ## name ## _alloc (void) \ +{ \ +type *value = calloc (1, sizeof (type)); \ +if (value) \ +TlsSetValue (tls_ ## name ## _index, value); \ +return value; \ +} \ + \ +static force_inline type * \ +tls_ ## name ## _get (void) \ +{ \ + type *value;\ + if (!tls_ ## name ## _initialized) \ + { \ + if (!tls_ ## name ## _mutex)\ + { \ + void *mutex = CreateMutexA (NULL, 0, NULL); \ + if (InterlockedCompareExchangePointer ( \ + &tls_ ## name ## _mutex, mutex, NULL) != NULL) \ + { \ + CloseHandle (mutex);\ + } \ + } \ + WaitForSingleObject (tls_ ## name ## _mutex, 0x); \ + if (!tls_ ## name ## _initialized) \ + { \ + tls_ ## name ## _index = TlsAlloc (); \ + tls_ ## name ## _initialized = 1; \ + } \ + ReleaseMutex (tls_ ## name ## _mutex); \ + } \ + if (tls_ ## name ## _index == 0x) \ + return NULL;\ + value = TlsGetValue (tls_ ## name ## _index); \ + if (!value) \ + value = tls_ ## name ## _alloc (); \ + return value; \ +} + +# define PIXMAN_GET_THREAD_LOCAL(name) \ +tls_ ## name ## _get () + #elif defined(_MSC_VER) # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ -- 1.6.0.6 ___ Pixman mailing list Pixman@lists
[Pixman] [PATCH] Eliminate mask_bits from all the scanline fetchers.
From: Søren Sandmann Pedersen Back in the day, the mask_bits argument was used to distinguish between masks used for component alpha (where it was 0x) and masks for unified alpha (where it was 0xff00). In this way, the fetchers could check if just the alpha channel was 0 and in that case avoid fetching the source. However, we haven't actually used it like that for a long time; it is currently always either 0x or 0 (if the mask is NULL). It also doesn't seem worthwhile resurrecting it because for premultiplied buffers, if alpha is 0, then so are the color channels normally. This patch eliminates the mask_bits and changes the fetchers to just assume it is 0x if mask is non-NULL. --- pixman/pixman-access.c | 122 +- pixman/pixman-bits-image.c | 33 -- pixman/pixman-conical-gradient.c |7 +- pixman/pixman-general.c | 11 ++-- pixman/pixman-image.c| 18 ++ pixman/pixman-linear-gradient.c | 13 ++-- pixman/pixman-private.h | 12 +--- pixman/pixman-radial-gradient.c |7 +- pixman/pixman-solid-fill.c |6 +- 9 files changed, 85 insertions(+), 144 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index fa0a267..809cc38 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -94,8 +94,7 @@ fetch_scanline_a8r8g8b8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; @@ -110,8 +109,7 @@ fetch_scanline_x8r8g8b8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (const uint32_t *)bits + x; @@ -127,8 +125,7 @@ fetch_scanline_a8b8g8r8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; @@ -150,8 +147,7 @@ fetch_scanline_x8b8g8r8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; @@ -174,8 +170,7 @@ fetch_scanline_b8g8r8a8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; @@ -198,8 +193,7 @@ fetch_scanline_b8g8r8x8 (pixman_image_t *image, int y, int width, uint32_t * buffer, - const uint32_t *mask, - uint32_tmask_bits) + const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = (uint32_t *)bits + x; @@ -223,8 +217,7 @@ fetch_scanline_a2r10g10b10 (pixman_image_t *image, int y, int width, uint32_t * b, -const uint32_t *mask, -uint32_tmask_bits) +const uint32_t *mask) { const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; const uint32_t *pixel = bits + x; @@ -259,8 +252,7 @@ fetch_scanline_x2r10g10b10 (pixman_image_t *image, int y, int w
[Pixman] [PATCH] Make the combiner macros less likely to cause name collisions.
From: Søren Sandmann Pedersen Protect the arguments to the combiner macros with parentheses, and prefix their temporary variables with underscores to avoid name space collisions with the surrounding code. --- pixman/pixman-combine.h.template | 152 +++--- 1 files changed, 76 insertions(+), 76 deletions(-) diff --git a/pixman/pixman-combine.h.template b/pixman/pixman-combine.h.template index 2f6392f..012ada7 100644 --- a/pixman/pixman-combine.h.template +++ b/pixman/pixman-combine.h.template @@ -31,7 +31,7 @@ (((comp2_t) (a) * MASK) / (b)) #define ADD_UNc(x, y, t)\ -((t) = x + y, \ +((t) = (x) + (y), \ (comp4_t) (comp1_t) ((t) | (0 - ((t) >> G_SHIFT #define DIV_ONE_UNc(x) \ @@ -84,15 +84,15 @@ #define UNcx4_MUL_UNc(x, a)\ do \ { \ - comp4_t r1, r2, t; \ + comp4_t __r1, __r2, __t;\ \ - r1 = (x); \ - UNc_rb_MUL_UNc (r1, a, t); \ + __r1 = (x); \ + UNc_rb_MUL_UNc (__r1, (a), __t);\ \ - r2 = (x) >> G_SHIFT;\ - UNc_rb_MUL_UNc (r2, a, t); \ + __r2 = (x) >> G_SHIFT; \ + UNc_rb_MUL_UNc (__r2, (a), __t);\ \ - x = r1 | (r2 << G_SHIFT); \ + (x) = __r1 | (__r2 << G_SHIFT); \ } while (0) /* @@ -101,19 +101,19 @@ #define UNcx4_MUL_UNc_ADD_UNcx4(x, a, y) \ do \ { \ - comp4_t r1, r2, r3, t; \ + comp4_t __r1, __r2, __r3, __t; \ \ - r1 = (x); \ - r2 = (y) & RB_MASK; \ - UNc_rb_MUL_UNc (r1, a, t); \ - UNc_rb_ADD_UNc_rb (r1, r2, t); \ + __r1 = (x); \ + __r2 = (y) & RB_MASK; \ + UNc_rb_MUL_UNc (__r1, (a), __t);\ + UNc_rb_ADD_UNc_rb (__r1, __r2, __t);\ \ - r2 = (x) >> G_SHIFT;\ - r3 = ((y) >> G_SHIFT) & RB_MASK;\ - UNc_rb_MUL_UNc (r2, a, t); \ - UNc_rb_ADD_UNc_rb (r2, r3, t); \ + __r2 = (x) >> G_SHIFT; \ + __r3 = ((y) >> G_SHIFT) & RB_MASK; \ + UNc_rb_MUL_UNc (__r2, (a), __t);\ + UNc_rb_ADD_UNc_rb (__r2, __r3, __t);\ \ - x = r1 | (r2 << G_SHIFT); \ + (x) = __r1 | (__r2 << G_SHIFT); \ } while (0) /* @@ -122,21 +122,21 @@ #define UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc(x, a, y, b)\ do \ { \ - comp4_t r1, r2, r3, t; \ + comp4_t __r1, __r2, __r3, __t; \ \ - r1 = x; \ - r2 = y; \ - UNc_rb_MUL_UNc (
[Pixman] [PATCH] test: Make sure the palettes for indexed format roundtrip properly
From: Søren Sandmann Pedersen The palettes for indexed formats must satisfy the condition that if some index maps to a color C, then the 15 bit version of that color must map back to the index. This ensures that the destination operator is always a no-op, which seems like a reasonable assumption to make. --- test/blitters-test.c | 74 ++--- 1 files changed, 63 insertions(+), 11 deletions(-) diff --git a/test/blitters-test.c b/test/blitters-test.c index 2673968..5becada 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -11,7 +11,8 @@ #include #include "utils.h" -static pixman_indexed_t palette; +static pixman_indexed_t rgb_palette[9]; +static pixman_indexed_t y_palette[9]; static void * aligned_malloc (size_t align, size_t size) @@ -66,10 +67,13 @@ create_random_image (pixman_format_code_t *allowed_formats, img = pixman_image_create_bits (fmt, width, height, buf, stride); -if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR || - PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) +if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_COLOR) { - pixman_image_set_indexed (img, &palette); + pixman_image_set_indexed (img, &(rgb_palette[PIXMAN_FORMAT_BPP (fmt)])); +} +else if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_GRAY) +{ + pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); } image_endian_swap (img, PIXMAN_FORMAT_BPP (fmt)); @@ -409,23 +413,71 @@ test_composite (int testnum, int verbose) return crc32; } +#define CONVERT_15(c, is_rgb) \ +(is_rgb? \ + c) >> 3) & 0x001f) | \ + (((c) >> 6) & 0x03e0) | \ + (((c) >> 9) & 0x7c00)) : \ + (c) >> 16) & 0xff) * 153 +\ + (((c) >> 8) & 0xff) * 301 +\ + (((c) ) & 0xff) * 58) >> 2)) + static void -initialize_palette (void) +initialize_palette (pixman_indexed_t *palette, uint32_t mask, int is_rgb) { int i; -for (i = 0; i < PIXMAN_MAX_INDEXED; ++i) - palette.rgba[i] = lcg_rand (); - for (i = 0; i < 32768; ++i) - palette.ent[i] = lcg_rand() & 0xff; + palette->ent[i] = lcg_rand() & mask; + +for (i = 0; i < mask + 1; ++i) +{ + uint32_t rgba24; + pixman_bool_t retry; + uint32_t i15; + + /* We filled the rgb->index map with random numbers, but we +* do need the ability to round trip, that is if some indexed +* color expands to an argb24, then the 15 bit version of that +* color must map back to the index. Anything else, we don't +* care about too much. +*/ + do + { + uint32_t old_idx; + + rgba24 = lcg_rand(); + i15 = CONVERT_15 (rgba24, is_rgb); + + old_idx = palette->ent[i15]; + if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15) + retry = 1; + else + retry = 0; + } while (retry); + + palette->rgba[i] = rgba24; + palette->ent[i15] = i; +} + +for (i = 0; i < mask + 1; ++i) +{ + assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i); +} } int main (int argc, const char *argv[]) { -initialize_palette(); +int i; + +for (i = 1; i <= 8; i++) +{ + initialize_palette (&(rgb_palette[i]), (1 << i) - 1, TRUE); + initialize_palette (&(y_palette[i]), (1 << i) - 1, FALSE); +} -return fuzzer_test_main("blitters", 200, 0xD09B1C03, +return fuzzer_test_main("blitters", 200, + 0xD0B050B1, test_composite, argc, argv); } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] When converting indexed formats to 64 bits, don't correct for channel widths
From: Søren Sandmann Pedersen Indexed formats are mapped to a8r8g8b8 with full precision, so when expanding we shouldn't correct for the width of the channels --- pixman/pixman-access.c | 31 +-- test/blitters-test.c |2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 9708b10..80fa9e8 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2683,12 +2683,26 @@ fetch_scanline_generic_64 (pixman_image_t *image, uint32_t * buffer, const uint32_t *mask) { +pixman_format_code_t format; + /* Fetch the pixels into the first half of buffer and then expand them in * place. */ image->bits.fetch_scanline_raw_32 (image, x, y, width, buffer, NULL); + +format = image->bits.format; +if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || + PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) +{ + /* Indexed formats are mapped to a8r8g8b8 with full +* precision, so when expanding we shouldn't correct +* for the width of the channels +*/ + + format = PIXMAN_a8r8g8b8; +} -pixman_expand ((uint64_t *)buffer, buffer, image->bits.format, width); +pixman_expand ((uint64_t *)buffer, buffer, format, width); } /* Despite the type, this function expects a uint64_t *buffer */ @@ -2699,8 +2713,21 @@ fetch_pixel_generic_64 (bits_image_t *image, { uint32_t pixel32 = image->fetch_pixel_raw_32 (image, offset, line); uint64_t result; +pixman_format_code_t format; + +format = image->format; +if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || + PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY) +{ + /* Indexed formats are mapped to a8r8g8b8 with full +* precision, so when expanding we shouldn't correct +* for the width of the channels +*/ + + format = PIXMAN_a8r8g8b8; +} -pixman_expand ((uint64_t *)&result, &pixel32, image->format, 1); +pixman_expand ((uint64_t *)&result, &pixel32, format, 1); return result; } diff --git a/test/blitters-test.c b/test/blitters-test.c index 5becada..2c6334a 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -478,6 +478,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 200, - 0xD0B050B1, + 0xD5833506, test_composite, argc, argv); } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Make the repeat mode explicit in the FAST_NEAREST macro.
From: Søren Sandmann Pedersen Before, it was 0 or 1 meaning 'no repeat' and 'normal repeat' respectively. Now we explicitly pass in either NONE or NORMAL. --- pixman/pixman-fast-path.c | 43 ++- 1 files changed, 26 insertions(+), 17 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index c4dd3a6..7b8c9bc 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1399,7 +1399,7 @@ repeat (pixman_repeat_t repeat, int *c, int size) #define GET_0565_ALPHA(s) 0xff #define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \ -src_type_t, dst_type_t, OP, do_repeat) \ +src_type_t, dst_type_t, OP, repeat_mode) \ static void \ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementation_t *imp,\ pixman_op_t op, \ @@ -1435,6 +1435,12 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat if (PIXMAN_OP_ ## OP != PIXMAN_OP_SRC && PIXMAN_OP_ ## OP != PIXMAN_OP_OVER) \ abort(); \ \ +if (PIXMAN_REPEAT_ ## repeat_mode != PIXMAN_REPEAT_NORMAL && \ + PIXMAN_REPEAT_ ## repeat_mode != PIXMAN_REPEAT_NONE) \ +{ \ + abort(); \ +} \ + \ PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \ /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ * transformed from destination space to source space */ \ @@ -1458,7 +1464,7 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat vx = v.vector[0]; \ vy = v.vector[1]; \ \ -if (do_repeat) \ +if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ { \ /* Clamp repeating positions inside the actual samples */ \ max_vx = src_image->bits.width << 16; \ @@ -1477,7 +1483,7 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat \ y = vy >> 16; \ vy += unit_y; \ - if (do_repeat) \ + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ \ src = src_first_line + src_stride * y; \ @@ -1488,7 +1494,7 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat { \ x1 = vx >> 16; \ vx += unit_x; \ - if (do_repeat) \ + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ { \
[Pixman] [PATCH] In the FAST_NEAREST macro call the function 8888_8888 and not x888_x888
From: Søren Sandmann Pedersen The x888 suggests that they have something to do with the x8r8g8b8 formats, but that's not the case; they are assuming a8r8g8b8 formats. (Although in some cases they also work for x8r8g8b8 type formats). --- pixman/pixman-fast-path.c | 36 ++-- 1 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 7b8c9bc..2e9d39a 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1590,12 +1590,12 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat } \ } -FAST_NEAREST(x888_x888_none, , , uint32_t, uint32_t, SRC, NONE); -FAST_NEAREST(x888_x888_normal, , , uint32_t, uint32_t, SRC, NORMAL); -FAST_NEAREST(x888_x888_none, , , uint32_t, uint32_t, OVER, NONE); -FAST_NEAREST(x888_x888_normal, , , uint32_t, uint32_t, OVER, NORMAL); -FAST_NEAREST(x888_565_none, , 0565, uint32_t, uint16_t, SRC, NONE); -FAST_NEAREST(x888_565_normal, , 0565, uint32_t, uint16_t, SRC, NORMAL); +FAST_NEAREST(__none, , , uint32_t, uint32_t, SRC, NONE); +FAST_NEAREST(__normal, , , uint32_t, uint32_t, SRC, NORMAL); +FAST_NEAREST(__none, , , uint32_t, uint32_t, OVER, NONE); +FAST_NEAREST(__normal, , , uint32_t, uint32_t, OVER, NORMAL); +FAST_NEAREST(_565_none, , 0565, uint32_t, uint16_t, SRC, NONE); +FAST_NEAREST(_565_normal, , 0565, uint32_t, uint16_t, SRC, NORMAL); FAST_NEAREST(565_565_none, 0565, 0565, uint16_t, uint16_t, SRC, NONE); FAST_NEAREST(565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL); FAST_NEAREST(_565_none, , 0565, uint32_t, uint16_t, OVER, NONE); @@ -1855,23 +1855,23 @@ static const pixman_fast_path_t c_fast_paths[] = PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ } -SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, x888_x888), +SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, _), +SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, _), +SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, _), +SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, _), -SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, x888_x888), +SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, _), +SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, _), -SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, x888_565), -SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, x888_565), +SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, _565), +SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, _565), SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, 565_565), -SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, x888_x888), -SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, x888_x888), +SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, _), +SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, _), +SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, _), +SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, _), SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, _565), -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] fast-path: Some formatting fixes
From: Søren Sandmann Pedersen Add spaces before parentheses; fix indentation in the macro. --- pixman/pixman-fast-path.c | 26 +- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 2e9d39a..c65dfb1 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1547,8 +1547,8 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat } \ else /* PIXMAN_OP_SRC */ \ { \ - *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ - *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ } \ } \ \ @@ -1584,22 +1584,22 @@ fast_composite_scaled_nearest_ ## scale_func_name ## _ ## OP (pixman_implementat } \ else /* PIXMAN_OP_SRC */ \ { \ - *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ } \ } \ } \ } -FAST_NEAREST(__none, , , uint32_t, uint32_t, SRC, NONE); -FAST_NEAREST(__normal, , , uint32_t, uint32_t, SRC, NORMAL); -FAST_NEAREST(__none, , , uint32_t, uint32_t, OVER, NONE); -FAST_NEAREST(__normal, , , uint32_t, uint32_t, OVER, NORMAL); -FAST_NEAREST(_565_none, , 0565, uint32_t, uint16_t, SRC, NONE); -FAST_NEAREST(_565_normal, , 0565, uint32_t, uint16_t, SRC, NORMAL); -FAST_NEAREST(565_565_none, 0565, 0565, uint16_t, uint16_t, SRC, NONE); -FAST_NEAREST(565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL); -FAST_NEAREST(_565_none, , 0565, uint32_t, uint16_t, OVER, NONE); -FAST_NEAREST(_565_normal, , 0565, uint32_t, uint16_t, OVER, NORMAL); +FAST_NEAREST (__none, , , uint32_t, uint32_t, SRC, NONE); +FAST_NEAREST (__normal, , , uint32_t, uint32_t, SRC, NORMAL); +FAST_NEAREST (__none, , , uint32_t, uint32_t, OVER, NONE); +FAST_NEAREST (__normal, , , uint32_t, uint32_t, OVER, NORMAL); +FAST_NEAREST (_565_none, , 0565, uint32_t, uint16_t, SRC, NONE); +FAST_NEAREST (_565_normal, , 0565, uint32_t, uint16_t, SRC, NORMAL); +FAST_NEAREST (565_565_none, 0565, 0565, uint16_t, uint16_t, SRC, NONE); +FAST_NEAREST (565_565_normal, 0565, 0565, uint16_t, uint16_t, SRC, NORMAL); +FAST_NEAREST (_565_none, , 0565, uint32_t, uint16_t, OVER, NONE); +FAST_NEAREST (_565_normal, , 0565, uint32_t, uint16_t, OVER, NORMAL); static force_inline uint32_t fetch_nearest (pixman_repeat_t src_repeat, -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Check for read accessors before taking the bilinear fast path
From: Søren Sandmann Pedersen The bilinear fast path accesses pixels directly, so if the image has a read accessor, then it can't be used. --- pixman/pixman-bits-image.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index ff59a8f..95710b4 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -909,6 +909,7 @@ bits_image_property_changed (pixman_image_t *image) bits->common.transform->matrix[2][2] == pixman_fixed_1 && bits->common.transform->matrix[0][0] > 0 && bits->common.transform->matrix[1][0] == 0 && +!bits->read_func && (bits->common.filter == PIXMAN_FILTER_BILINEAR || bits->common.filter == PIXMAN_FILTER_GOOD || bits->common.filter == PIXMAN_FILTER_BEST)&& -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] [fast] Add fast_composite_src_x888_8888()
From: Søren Sandmann Pedersen This shows up on when Firefox displays http://dougx.net/plunder/plunder.html --- pixman/pixman-fast-path.c | 38 ++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index c65dfb1..6ed1580 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -724,6 +724,42 @@ fast_composite_over__ (pixman_implementation_t *imp, } } +static void +fast_composite_src_x888_ (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint32_t*dst_line, *dst; +uint32_t*src_line, *src; +int dst_stride, src_stride; +int32_t w; + +PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); +PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + +while (height--) +{ + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w--) + *dst++ = (*src++) | 0xff00; +} +} + #if 0 static void fast_composite_over__0888 (pixman_implementation_t *imp, @@ -1805,6 +1841,8 @@ static const pixman_fast_path_t c_fast_paths[] = PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill), PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill), PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill), +PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, fast_composite_src_x888_), +PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, fast_composite_src_x888_), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, fast_composite_src_memcpy), PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_memcpy), -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] [sse2] Add sse2_composite_src_x888_8888()
From: Søren Sandmann Pedersen This operation shows up when Firefox displays http://dougx.net/plunder/plunder.html --- pixman/pixman-sse2.c | 84 ++ 1 files changed, 84 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index d5349d7..2c9f5eb 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -3517,6 +3517,88 @@ sse2_composite_over__n_ (pixman_implementation_t *imp, _mm_empty (); } +/*- + * composite_over__n_ + */ + +static void +sse2_composite_src_x888_ (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint32_t*dst_line, *dst; +uint32_t*src_line, *src; +int32_t w; +int dst_stride, src_stride; + + +PIXMAN_IMAGE_GET_LINE ( + dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); +PIXMAN_IMAGE_GET_LINE ( + src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + +while (height--) +{ + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)src); + + while (w && (unsigned long)dst & 15) + { + *dst++ = *src++ | 0xff00; + w--; + } + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)src); + + while (w >= 16) + { + __m128i xmm_src1, xmm_src2, xmm_src3, xmm_src4; + + /* fill cache line with next memory */ + cache_prefetch_next ((__m128i*)src); + + xmm_src1 = load_128_unaligned ((__m128i*)src + 0); + xmm_src2 = load_128_unaligned ((__m128i*)src + 1); + xmm_src3 = load_128_unaligned ((__m128i*)src + 2); + xmm_src4 = load_128_unaligned ((__m128i*)src + 3); + + save_128_aligned ((__m128i*)dst + 0, _mm_or_si128 (xmm_src1, mask_ff00)); + save_128_aligned ((__m128i*)dst + 1, _mm_or_si128 (xmm_src2, mask_ff00)); + save_128_aligned ((__m128i*)dst + 2, _mm_or_si128 (xmm_src3, mask_ff00)); + save_128_aligned ((__m128i*)dst + 3, _mm_or_si128 (xmm_src4, mask_ff00)); + + dst += 16; + src += 16; + w -= 16; + } + + while (w) + { + *dst++ = *src++ | 0xff00; + w--; + } +} + +_mm_empty (); +} + /* - * composite_over_x888_n_ */ @@ -6127,6 +6209,8 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, sse2_composite_src_n_8_), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, sse2_composite_src_n_8_), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, sse2_composite_src_n_8_), +PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, sse2_composite_src_x888_), +PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, sse2_composite_src_x888_), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, sse2_composite_copy_area), PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, sse2_composite_copy_area), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] [sse2] Add sse2_composite_add_n_8()
From: Søren Sandmann Pedersen This shows up when epiphany displays the "ImageTest" on glimr.rubyforge.org/cake/canvas.html --- pixman/pixman-sse2.c | 98 ++ 1 files changed, 98 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 822fffe..3dd7967 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -5386,6 +5386,103 @@ sse2_composite_add_n_8_8 (pixman_implementation_t *imp, _mm_empty (); } +/* - + * composite_add_n_8_8 + */ + +static void +sse2_composite_add_n_8 (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint8_t *dst_line, *dst; +int dst_stride; +int32_t w; +uint32_t src; + +__m128i xmm_src; + +PIXMAN_IMAGE_GET_LINE ( + dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); + +src = _pixman_image_get_solid (src_image, dst_image->bits.format); + +src >>= 24; + +if (src == 0x00) + return; + +if (src == 0xff) +{ + pixman_fill (dst_image->bits.bits, dst_image->bits.rowstride, +8, dest_x, dest_y, width, height, 0xff); + + return; +} + +src = (src << 24) | (src << 16) | (src << 8) | src; +xmm_src = _mm_set_epi32 (src, src, src, src); + +while (height--) +{ + dst = dst_line; + dst_line += dst_stride; + w = width; + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)dst); + + while (w && ((unsigned long)dst & 15)) + { + *dst = (uint8_t)_mm_cvtsi64_si32 ( + _mm_adds_pu8 ( + _mm_movepi64_pi64 (xmm_src), + _mm_cvtsi32_si64 (*dst))); + + w--; + dst++; + } + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)dst); + + while (w >= 16) + { + /* fill cache line with next memory */ + cache_prefetch_next ((__m128i*)dst); + + save_128_aligned ( + (__m128i*)dst, _mm_adds_epu8 (xmm_src, load_128_aligned ((__m128i*)dst))); + + dst += 16; + w -= 16; + } + + while (w) + { + *dst = (uint8_t)_mm_cvtsi64_si32 ( + _mm_adds_pu8 ( + _mm_movepi64_pi64 (xmm_src), + _mm_cvtsi32_si64 (*dst))); + + w--; + dst++; + } +} + +_mm_empty (); +} + /* -- * composite_add_8000_8000 */ @@ -6309,6 +6406,7 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, sse2_composite_add__), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, sse2_composite_add__), PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, sse2_composite_add_n_8_8), +PIXMAN_STD_FAST_PATH (ADD, solid, null, a8, sse2_composite_add_n_8), /* PIXMAN_OP_SRC */ PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, sse2_composite_src_n_8_), -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] [sse2] Add sse2_composite_in_n_8()
From: Søren Sandmann Pedersen This shows up when epiphany displays the "ImageTest" on glimr.rubyforge.org/cake/canvas.html --- pixman/pixman-sse2.c | 109 +- 1 files changed, 108 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 2c9f5eb..822fffe 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -5066,6 +5066,112 @@ sse2_composite_in_n_8_8 (pixman_implementation_t *imp, _mm_empty (); } +/* --- + * composite_in_n_8 + */ + +static void +sse2_composite_in_n_8 (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ +uint8_t *dst_line, *dst; +int dst_stride; +uint32_t d; +uint32_t src; +int32_t w; + +__m128i xmm_alpha; +__m128i xmm_dst, xmm_dst_lo, xmm_dst_hi; + +PIXMAN_IMAGE_GET_LINE ( + dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1); + +src = _pixman_image_get_solid (src_image, dst_image->bits.format); + +xmm_alpha = expand_alpha_1x128 (expand_pixel_32_1x128 (src)); + +src = src >> 24; + +if (src == 0xff) + return; + +if (src == 0x00) +{ + pixman_fill (dst_image->bits.bits, dst_image->bits.rowstride, +8, dest_x, dest_y, width, height, src); + + return; +} + +while (height--) +{ + dst = dst_line; + dst_line += dst_stride; + w = width; + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)dst); + + while (w && ((unsigned long)dst & 15)) + { + d = (uint32_t) *dst; + + *dst++ = (uint8_t) pack_1x64_32 ( + pix_multiply_1x64 ( + _mm_movepi64_pi64 (xmm_alpha), + unpack_32_1x64 (d))); + w--; + } + + /* call prefetch hint to optimize cache load*/ + cache_prefetch ((__m128i*)dst); + + while (w >= 16) + { + /* fill cache line with next memory */ + cache_prefetch_next ((__m128i*)dst); + + xmm_dst = load_128_aligned ((__m128i*)dst); + + unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); + + pix_multiply_2x128 (&xmm_alpha, &xmm_alpha, + &xmm_dst_lo, &xmm_dst_hi, + &xmm_dst_lo, &xmm_dst_hi); + + save_128_aligned ( + (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); + + dst += 16; + w -= 16; + } + + while (w) + { + d = (uint32_t) *dst; + + *dst++ = (uint8_t) pack_1x64_32 ( + pix_multiply_1x64 ( + _mm_movepi64_pi64 (xmm_alpha), + unpack_32_1x64 (d))); + w--; + } +} + +_mm_empty (); +} + /* --- * composite_in_8_8 */ @@ -6192,7 +6298,7 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, rpixbuf, rpixbuf, b5g6r5, sse2_composite_over_pixbuf_0565), PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, x8r8g8b8, sse2_composite_copy_area), PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, x8b8g8r8, sse2_composite_copy_area), - + /* PIXMAN_OP_OVER_REVERSE */ PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, sse2_composite_over_reverse_n_), PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, sse2_composite_over_reverse_n_), @@ -6223,6 +6329,7 @@ static const pixman_fast_path_t sse2_fast_paths[] = /* PIXMAN_OP_IN */ PIXMAN_STD_FAST_PATH (IN, a8, null, a8, sse2_composite_in_8_8), PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, sse2_composite_in_n_8_8), +PIXMAN_STD_FAST_PATH (IN, solid, null, a8, sse2_composite_in_n_8), { PIXMAN_OP_NONE }, }; -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] bits: Fix potential divide-by-zero in projective code
From: Søren Sandmann Pedersen If the homogeneous coordinate is 0, just set the coordinates to 0. --- pixman/pixman-bits-image.c | 16 1 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 95710b4..36ea0af 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -695,12 +695,20 @@ bits_image_fetch_transformed (pixman_image_t * image, { for (i = 0; i < width; ++i) { - pixman_fixed_t x0, y0; - if (!mask || mask[i]) { - x0 = ((pixman_fixed_48_16_t)x << 16) / w; - y0 = ((pixman_fixed_48_16_t)y << 16) / w; + pixman_fixed_t x0, y0; + + if (w != 0) + { + x0 = ((pixman_fixed_48_16_t)x << 16) / w; + y0 = ((pixman_fixed_48_16_t)y << 16) / w; + } + else + { + x0 = 0; + y0 = 0; + } buffer[i] = bits_image_fetch_pixel_filtered (&image->bits, x0, y0); -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] If we bail out of do_composite, make sure to undo any workarounds.
From: Søren Sandmann Pedersen The workaround for an old X bug has to be undone if we bail from do_composite, so we can't just return. --- pixman/pixman.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 80a766a..2d06ce2 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -742,7 +742,7 @@ do_composite (pixman_op_t op, ®ion, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) { - return; + goto out; } extents = pixman_region32_extents (®ion); @@ -759,7 +759,7 @@ do_composite (pixman_op_t op, */ op = optimize_operator (op, src_flags, mask_flags, dest_flags); if (op == PIXMAN_OP_DST) - return; + goto out; lookup_composite_function (op, src_format, src_flags, @@ -776,6 +776,7 @@ do_composite (pixman_op_t op, (mask_flags & FAST_PATH_SIMPLE_REPEAT), ®ion, func); +out: if (need_workaround) { unapply_workaround (src, src_bits, src_dx, src_dy); -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [bits] Some cleanups of fetchers, plus flags for bits-image
The following patches contain some cleanups of the way the scanline fetching works for bits images. By removing the support for alpha map recursion, there is no longer any need to distinguish between 'raw' and non-raw scanline fetchers. Instead there is only one type of scanline fetcher, and only two function pointers in the image struct: one for 32 bit fetching and one for 64 bits. This then allows the various types of fetchers to be stored in an array indexed by flags, similar to how the fast paths are stored. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/7] Eliminate recursion from alpha map code
From: Søren Sandmann Pedersen Alpha maps with alpha maps are no longer supported. It's not a useful feature and it could could lead to infinite recursion. --- pixman/pixman-bits-image.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 36ea0af..81722c2 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -51,7 +51,7 @@ bits_image_store_scanline_32 (bits_image_t * image, x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - bits_image_store_scanline_32 (image->common.alpha_map, x, y, width, buffer); + image->common.alpha_map->store_scanline_raw_32 (image->common.alpha_map, x, y, width, buffer); } } @@ -69,7 +69,7 @@ bits_image_store_scanline_64 (bits_image_t * image, x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - bits_image_store_scanline_64 (image->common.alpha_map, x, y, width, buffer); + image->common.alpha_map->store_scanline_raw_64 (image->common.alpha_map, x, y, width, buffer); } } -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/7] Eliminate get_pixel_32() and get_pixel_64() from bits_image.
From: Søren Sandmann Pedersen These functions can simply be passed as arguments to the various pixel fetchers. We don't need to store them. Since they are known at compile time and the pixel fetchers are force_inline, this is not a performance issue. Also temporarily make all pixel access go through the alpha path. --- pixman/pixman-bits-image.c | 78 +-- pixman/pixman-private.h|4 -- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 81722c2..0372217 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -96,38 +96,47 @@ _pixman_image_store_scanline_64 (bits_image_t * image, /* Fetch functions */ static uint32_t -bits_image_fetch_pixel_alpha (bits_image_t *image, int x, int y) +fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) { uint32_t pixel; -uint32_t pixel_a; + +if (check_bounds && + (x < 0 || x >= image->width || y < 0 || y >= image->height)) +{ + return 0; +} pixel = image->fetch_pixel_raw_32 (image, x, y); -assert (image->common.alpha_map); +if (image->common.alpha_map) +{ + uint32_t pixel_a; -x -= image->common.alpha_origin_x; -y -= image->common.alpha_origin_y; + x -= image->common.alpha_origin_x; + y -= image->common.alpha_origin_y; -if (x < 0 || x >= image->common.alpha_map->width || - y < 0 || y >= image->common.alpha_map->height) -{ - pixel_a = 0; -} -else -{ - pixel_a = image->common.alpha_map->fetch_pixel_raw_32 ( - image->common.alpha_map, x, y); - pixel_a = ALPHA_8 (pixel_a); -} + if (x < 0 || x >= image->common.alpha_map->width || + y < 0 || y >= image->common.alpha_map->height) + { + pixel_a = 0; + } + else + { + pixel_a = image->common.alpha_map->fetch_pixel_raw_32 ( + image->common.alpha_map, x, y); -pixel &= 0x00ff; -pixel |= (pixel_a << 24); + pixel_a = ALPHA_8 (pixel_a); + } + + pixel &= 0x00ff; + pixel |= (pixel_a << 24); +} return pixel; } static force_inline uint32_t -get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) +fetch_pixel_no_alpha (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) { if (check_bounds && (x < 0 || x >= image->width || y < 0 || y >= image->height)) @@ -135,9 +144,12 @@ get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) return 0; } -return image->fetch_pixel_32 (image, x, y); +return image->fetch_pixel_raw_32 (image, x, y); } +typedef uint32_t (* get_pixel_t) (bits_image_t *image, + int x, int y, pixman_bool_t check_bounds); + static force_inline void repeat (pixman_repeat_t repeat, int size, int *coord) { @@ -169,7 +181,8 @@ repeat (pixman_repeat_t repeat, int size, int *coord) static force_inline uint32_t bits_image_fetch_pixel_nearest (bits_image_t *image, pixman_fixed_t x, - pixman_fixed_t y) + pixman_fixed_t y, + get_pixel_t get_pixel) { int x0 = pixman_fixed_to_int (x - pixman_fixed_e); int y0 = pixman_fixed_to_int (y - pixman_fixed_e); @@ -281,7 +294,8 @@ bilinear_interpolation (uint32_t tl, uint32_t tr, static force_inline uint32_t bits_image_fetch_pixel_bilinear (bits_image_t *image, pixman_fixed_t x, -pixman_fixed_t y) +pixman_fixed_t y, +get_pixel_t get_pixel) { pixman_repeat_t repeat_mode = image->common.repeat; int width = image->width; @@ -538,7 +552,8 @@ bits_image_fetch_bilinear_no_repeat_ (pixman_image_t * ima, static force_inline uint32_t bits_image_fetch_pixel_convolution (bits_image_t *image, pixman_fixed_t x, - pixman_fixed_t y) + pixman_fixed_t y, + get_pixel_t get_pixel) { pixman_fixed_t *params = image->common.filter_params; int x_off = (params[0] - pixman_fixed_1) >> 1; @@ -611,23 +626,24 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, static force_inline uint32_t bits_image_fetch_pixel_filtered (bits_image_t *image, pixman_fixed_t x, -pixman_fixed_t y) +pixman_fixed_t
[Pixman] [PATCH 3/7] Split bits_image_fetch_transformed() into two functions.
From: Søren Sandmann Pedersen One function deals with the common affine, no-alpha-map case. The other deals with perspective transformations and alpha maps. --- pixman/pixman-bits-image.c | 222 +--- 1 files changed, 128 insertions(+), 94 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 0372217..09b69df 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -95,48 +95,9 @@ _pixman_image_store_scanline_64 (bits_image_t * image, /* Fetch functions */ -static uint32_t -fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) -{ -uint32_t pixel; - -if (check_bounds && - (x < 0 || x >= image->width || y < 0 || y >= image->height)) -{ - return 0; -} - -pixel = image->fetch_pixel_raw_32 (image, x, y); - -if (image->common.alpha_map) -{ - uint32_t pixel_a; - - x -= image->common.alpha_origin_x; - y -= image->common.alpha_origin_y; - - if (x < 0 || x >= image->common.alpha_map->width || - y < 0 || y >= image->common.alpha_map->height) - { - pixel_a = 0; - } - else - { - pixel_a = image->common.alpha_map->fetch_pixel_raw_32 ( - image->common.alpha_map, x, y); - - pixel_a = ALPHA_8 (pixel_a); - } - - pixel &= 0x00ff; - pixel |= (pixel_a << 24); -} - -return pixel; -} - static force_inline uint32_t -fetch_pixel_no_alpha (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) +fetch_pixel_no_alpha (bits_image_t *image, + int x, int y, pixman_bool_t check_bounds) { if (check_bounds && (x < 0 || x >= image->width || y < 0 || y >= image->height)) @@ -654,12 +615,101 @@ bits_image_fetch_pixel_filtered (bits_image_t *image, } static void -bits_image_fetch_transformed (pixman_image_t * image, - int offset, - int line, - int width, - uint32_t * buffer, - const uint32_t * mask) +bits_image_fetch_affine_no_alpha (pixman_image_t * image, + int offset, + int line, + int width, + uint32_t * buffer, + const uint32_t * mask) +{ +pixman_fixed_t x, y; +pixman_fixed_t ux, uy; +pixman_vector_t v; +int i; + +/* reference point is the center of the pixel */ +v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; +v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; +v.vector[2] = pixman_fixed_1; + +if (image->common.transform) +{ + if (!pixman_transform_point_3d (image->common.transform, &v)) + return; + + ux = image->common.transform->matrix[0][0]; + uy = image->common.transform->matrix[1][0]; +} +else +{ + ux = pixman_fixed_1; + uy = 0; +} + +x = v.vector[0]; +y = v.vector[1]; + +for (i = 0; i < width; ++i) +{ + if (!mask || mask[i]) + { + buffer[i] = bits_image_fetch_pixel_filtered ( + &image->bits, x, y, fetch_pixel_no_alpha); + } + + x += ux; + y += uy; +} +} + +/* General fetcher */ +static force_inline uint32_t +fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds) +{ +uint32_t pixel; + +if (check_bounds && + (x < 0 || x >= image->width || y < 0 || y >= image->height)) +{ + return 0; +} + +pixel = image->fetch_pixel_raw_32 (image, x, y); + +if (image->common.alpha_map) +{ + uint32_t pixel_a; + + x -= image->common.alpha_origin_x; + y -= image->common.alpha_origin_y; + + if (x < 0 || x >= image->common.alpha_map->width || + y < 0 || y >= image->common.alpha_map->height) + { + pixel_a = 0; + } + else + { + pixel_a = image->common.alpha_map->fetch_pixel_raw_32 ( + image->common.alpha_map, x, y); + + pixel_a = ALPHA_8 (pixel_a); + } + + pixel &= 0x00ff; + pixel |= (pixel_a << 24); +} + +return pixel; +} + +static void +bits_image_fetch_general (pixman_image_t * image, + int offset, + int line, + int width, + uint32_t * buffer, +
[Pixman] [PATCH 4/7] Eliminate the store_scanline_{32, 64} function pointers.
From: Søren Sandmann Pedersen Now that we can't recurse on alpha maps, they are not needed anymore. --- pixman/pixman-bits-image.c | 54 +--- pixman/pixman-private.h|4 --- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 09b69df..f8ddcbc 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -36,13 +36,12 @@ #include "pixman-combine32.h" /* Store functions */ - -static void -bits_image_store_scanline_32 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *buffer) +void +_pixman_image_store_scanline_32 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *buffer) { image->store_scanline_raw_32 (image, x, y, width, buffer); @@ -51,16 +50,17 @@ bits_image_store_scanline_32 (bits_image_t * image, x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - image->common.alpha_map->store_scanline_raw_32 (image->common.alpha_map, x, y, width, buffer); + image->common.alpha_map->store_scanline_raw_32 ( + image->common.alpha_map, x, y, width, buffer); } } -static void -bits_image_store_scanline_64 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *buffer) +void +_pixman_image_store_scanline_64 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *buffer) { image->store_scanline_raw_64 (image, x, y, width, buffer); @@ -69,30 +69,11 @@ bits_image_store_scanline_64 (bits_image_t * image, x -= image->common.alpha_origin_x; y -= image->common.alpha_origin_y; - image->common.alpha_map->store_scanline_raw_64 (image->common.alpha_map, x, y, width, buffer); + image->common.alpha_map->store_scanline_raw_64 ( + image->common.alpha_map, x, y, width, buffer); } } -void -_pixman_image_store_scanline_32 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *buffer) -{ -image->store_scanline_32 (image, x, y, width, buffer); -} - -void -_pixman_image_store_scanline_64 (bits_image_t * image, - int x, - int y, - int width, - const uint32_t *buffer) -{ -image->store_scanline_64 (image, x, y, width, buffer); -} - /* Fetch functions */ static force_inline uint32_t @@ -983,9 +964,6 @@ bits_image_property_changed (pixman_image_t *image) image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; image->common.get_scanline_32 = bits_image_fetch_general; } - -bits->store_scanline_64 = bits_image_store_scanline_64; -bits->store_scanline_32 = bits_image_store_scanline_32; } static uint32_t * diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 06f6d11..15a5bc2 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -187,10 +187,6 @@ struct bits_image store_scanline_t store_scanline_raw_32; store_scanline_t store_scanline_raw_64; -/* Store a scanline, taking alpha maps into account */ -store_scanline_t store_scanline_32; -store_scanline_t store_scanline_64; - /* Used for indirect access to the bits */ pixman_read_memory_func_t read_func; pixman_write_memory_func_t write_func; -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 5/7] Remove "_raw_" from all the accessors.
From: Søren Sandmann Pedersen There are no non-raw accessors anymore. --- pixman/pixman-access.c | 40 pixman/pixman-bits-image.c | 28 ++-- pixman/pixman-private.h| 19 +++ 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 80fa9e8..a786947 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2667,7 +2667,7 @@ store_scanline_generic_64 (bits_image_t * image, */ pixman_contract (argb8_pixels, (uint64_t *)values, width); -image->store_scanline_raw_32 (image, x, y, width, argb8_pixels); +image->store_scanline_32 (image, x, y, width, argb8_pixels); free (argb8_pixels); } @@ -2688,7 +2688,7 @@ fetch_scanline_generic_64 (pixman_image_t *image, /* Fetch the pixels into the first half of buffer and then expand them in * place. */ -image->bits.fetch_scanline_raw_32 (image, x, y, width, buffer, NULL); +image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL); format = image->bits.format; if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR || @@ -2711,7 +2711,7 @@ fetch_pixel_generic_64 (bits_image_t *image, int offset, int line) { -uint32_t pixel32 = image->fetch_pixel_raw_32 (image, offset, line); +uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); uint64_t result; pixman_format_code_t format; @@ -2743,7 +2743,7 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image, int offset, int line) { -uint64_t pixel64 = image->fetch_pixel_raw_64 (image, offset, line); +uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line); uint32_t result; pixman_contract (&result, &pixel64, 1); @@ -2754,12 +2754,12 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image, typedef struct { pixman_format_code_t format; -fetch_scanline_t fetch_scanline_raw_32; -fetch_scanline_t fetch_scanline_raw_64; -fetch_pixel_32_t fetch_pixel_raw_32; -fetch_pixel_64_t fetch_pixel_raw_64; -store_scanline_t store_scanline_raw_32; -store_scanline_t store_scanline_raw_64; +fetch_scanline_t fetch_scanline_32; +fetch_scanline_t fetch_scanline_64; +fetch_pixel_32_t fetch_pixel_32; +fetch_pixel_64_t fetch_pixel_64; +store_scanline_t store_scanline_32; +store_scanline_t store_scanline_64; } format_info_t; #define FORMAT_INFO(format)\ @@ -2885,12 +2885,12 @@ setup_accessors (bits_image_t *image) { if (info->format == image->format) { - image->fetch_scanline_raw_32 = info->fetch_scanline_raw_32; - image->fetch_scanline_raw_64 = info->fetch_scanline_raw_64; - image->fetch_pixel_raw_32 = info->fetch_pixel_raw_32; - image->fetch_pixel_raw_64 = info->fetch_pixel_raw_64; - image->store_scanline_raw_32 = info->store_scanline_raw_32; - image->store_scanline_raw_64 = info->store_scanline_raw_64; + image->fetch_scanline_32 = info->fetch_scanline_32; + image->fetch_scanline_64 = info->fetch_scanline_64; + image->fetch_pixel_32 = info->fetch_pixel_32; + image->fetch_pixel_64 = info->fetch_pixel_64; + image->store_scanline_32 = info->store_scanline_32; + image->store_scanline_64 = info->store_scanline_64; return; } @@ -2901,13 +2901,13 @@ setup_accessors (bits_image_t *image) #ifndef PIXMAN_FB_ACCESSORS void -_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image); +_pixman_bits_image_setup_accessors_accessors (bits_image_t *image); void -_pixman_bits_image_setup_raw_accessors (bits_image_t *image) +_pixman_bits_image_setup_accessors (bits_image_t *image) { if (image->read_func || image->write_func) - _pixman_bits_image_setup_raw_accessors_accessors (image); + _pixman_bits_image_setup_accessors_accessors (image); else setup_accessors (image); } @@ -2915,7 +2915,7 @@ _pixman_bits_image_setup_raw_accessors (bits_image_t *image) #else void -_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image) +_pixman_bits_image_setup_accessors_accessors (bits_image_t *image) { setup_accessors (image); } diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index f8ddcbc..d27256d 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -43,14 +43,14 @@ _pixman_image_store_scanline_32 (bits_imag
[Pixman] [PATCH 6/7] Add some new FAST_PATH flags
From: Søren Sandmann Pedersen The flags are: * AFFINE_TRANSFORM, for affine transforms * Y_UNIT_ZERO, for when the 10 entry in the transformation is zero * FILTER_BILINEAR, for when the image has a bilinear filter * NO_NORMAL_REPEAT, for when the repeat mode is not NORMAL * HAS_TRANSFORM, for when the transform is not NULL Also add some new FAST_PATH_REPEAT_* macros. These are just shorthands for the image not having any of the other repeat modes. For example REPEAT_NORMAL is (NO_NONE | NO_PAD | NO_REFLECT). --- pixman/pixman-bits-image.c |1 - pixman/pixman-fast-path.c |9 +++-- pixman/pixman-image.c | 36 +++- pixman/pixman-private.h| 25 + 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index d27256d..7129e86 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -954,7 +954,6 @@ bits_image_property_changed (pixman_image_t *image) bits->common.transform->matrix[2][0] == 0 && bits->common.transform->matrix[2][1] == 0 && bits->common.transform->matrix[2][2] == pixman_fixed_1) - { image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; image->common.get_scanline_32 = bits_image_fetch_affine_no_alpha; diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 9cc8529..f03752f 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1866,15 +1866,12 @@ static const pixman_fast_path_t c_fast_paths[] = FAST_PATH_NO_ACCESSORS| \ FAST_PATH_NO_WIDE_FORMAT) -#define HAS_NORMAL_REPEAT_FLAGS \ -(FAST_PATH_NO_REFLECT_REPEAT | \ - FAST_PATH_NO_PAD_REPEAT | \ - FAST_PATH_NO_NONE_REPEAT) - #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \ { PIXMAN_OP_ ## op, \ PIXMAN_ ## s, \ - SCALED_NEAREST_FLAGS | HAS_NORMAL_REPEAT_FLAGS | FAST_PATH_X_UNIT_POSITIVE, \ + (SCALED_NEAREST_FLAGS | \ +FAST_PATH_NORMAL_REPEAT| \ +FAST_PATH_X_UNIT_POSITIVE),\ PIXMAN_null, 0, \ PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 5c6d415..269c3c1 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -297,21 +297,33 @@ compute_image_info (pixman_image_t *image) /* Transform */ if (!image->common.transform) { - flags |= (FAST_PATH_ID_TRANSFORM | FAST_PATH_X_UNIT_POSITIVE); + flags |= (FAST_PATH_ID_TRANSFORM| + FAST_PATH_X_UNIT_POSITIVE | + FAST_PATH_Y_UNIT_ZERO | + FAST_PATH_AFFINE_TRANSFORM); } else { - if (image->common.transform->matrix[0][1] == 0 && - image->common.transform->matrix[1][0] == 0 && - image->common.transform->matrix[2][0] == 0 && - image->common.transform->matrix[2][1] == 0 && + flags |= FAST_PATH_HAS_TRANSFORM; + + if (image->common.transform->matrix[2][0] == 0 && + image->common.transform->matrix[2][1] == 0 && image->common.transform->matrix[2][2] == pixman_fixed_1) { - flags |= FAST_PATH_SCALE_TRANSFORM; + flags |= FAST_PATH_AFFINE_TRANSFORM; + + if (image->common.transform->matrix[0][1] == 0 && + image->common.transform->matrix[1][0] == 0) + { + flags |= FAST_PATH_SCALE_TRANSFORM; + } } if (image->common.transform->matrix[0][0] > 0) flags |= FAST_PATH_X_UNIT_POSITIVE; + + if (image->common.transform->matrix[1][0] == 0) + flags |= FAST_PATH_Y_UNIT_ZERO; } /* Alpha map */ @@ -326,6 +338,12 @@ compute_image_info (pixman_image_t *image) flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); break; +case PIXMAN_FILTER_BILINEAR: +case PIXMAN_FILTER_GOOD: +case PIXMAN_FILTER_BEST: + flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); + break; + case PIXMAN_FILTER_CONVOLUTION: break; @@ -338,15 +3
[Pixman] [PATCH 7/7] Store the various bits image fetchers in a table with formats and flags.
From: Søren Sandmann Pedersen Similarly to how the fast paths are done, put the various bits_image fetchers in a table, so that we can quickly find the best one based on the image's flags and format. --- pixman/pixman-bits-image.c | 126 ++- 1 files changed, 76 insertions(+), 50 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 7129e86..a32ebcc 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -906,62 +906,88 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image, } } +typedef struct +{ +pixman_format_code_t format; +uint32_t flags; +fetch_scanline_t fetch_32; +fetch_scanline_t fetch_64; +} fetcher_info_t; + +static const fetcher_info_t fetcher_info[] = +{ +{ PIXMAN_solid, + FAST_PATH_NO_ALPHA_MAP, + bits_image_fetch_solid_32, + bits_image_fetch_solid_64 +}, + +{ PIXMAN_any, + (FAST_PATH_NO_ALPHA_MAP | + FAST_PATH_ID_TRANSFORM | + FAST_PATH_NO_CONVOLUTION_FILTER | + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_REFLECT_REPEAT), + bits_image_fetch_untransformed_32, + bits_image_fetch_untransformed_64 +}, + +#define FAST_BILINEAR_FLAGS\ +(FAST_PATH_NO_ALPHA_MAP| \ + FAST_PATH_NO_ACCESSORS| \ + FAST_PATH_HAS_TRANSFORM | \ + FAST_PATH_AFFINE_TRANSFORM| \ + FAST_PATH_X_UNIT_POSITIVE | \ + FAST_PATH_Y_UNIT_ZERO | \ + FAST_PATH_NONE_REPEAT | \ + FAST_PATH_BILINEAR_FILTER) + +{ PIXMAN_a8r8g8b8, + FAST_BILINEAR_FLAGS, + bits_image_fetch_bilinear_no_repeat_, + _pixman_image_get_scanline_generic_64 +}, + +{ PIXMAN_x8r8g8b8, + FAST_BILINEAR_FLAGS, + bits_image_fetch_bilinear_no_repeat_, + _pixman_image_get_scanline_generic_64 +}, + +{ PIXMAN_any, + (FAST_PATH_NO_ALPHA_MAP | + FAST_PATH_HAS_TRANSFORM | + FAST_PATH_AFFINE_TRANSFORM), + bits_image_fetch_affine_no_alpha, + _pixman_image_get_scanline_generic_64 +}, + +{ PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 }, + +{ PIXMAN_null }, +}; + static void bits_image_property_changed (pixman_image_t *image) { -bits_image_t *bits = (bits_image_t *)image; +uint32_t flags = image->common.flags; +pixman_format_code_t format = image->common.extended_format_code; +const fetcher_info_t *info; -_pixman_bits_image_setup_accessors (bits); +_pixman_bits_image_setup_accessors (&image->bits); -if (bits->common.alpha_map) -{ - image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64; - image->common.get_scanline_32 = bits_image_fetch_general; -} -else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) && - bits->width == 1 && - bits->height == 1) -{ - image->common.get_scanline_64 = bits_image_fetch_solid_64; - image->common.get_scanline_32 = bits_image_fetch_solid_32; -} -else if (!bits->common.transform && - bits->common.filter != PIXMAN_FILTER_CONVOLUTION && - (bits->common.repeat == PIXMAN_REPEAT_NONE || - bits->common.repeat == PIXMAN_REPEAT_NORMAL)) -{ - image->common.get_scanline_64 = bits_image_fetch_untransformed_64; - image->common.get_scanline_32 = bits_image_fetch_untransformed_32; -} -else if (bits->common.transform&& -bits->common.transform->matrix[2][0] == 0 && -bits->common.transform->matrix[2][1] == 0 && -bits->common.transform->matrix[2][2] == pixman_fixed_1 && -bits->common.transform->matrix[0][0] > 0 && -bits->common.transform->matrix[1][0] == 0 && -!bits->read_func && -(bits->common.filter == PIXMAN_FILTER_BILINEAR || - bits->common.filter == PIXMAN_FILTER_GOOD || - bits->common.filter == PIXMAN_FILTER_BEST)&& -bits->common.repeat == PIXMAN_REPEAT_NONE && -(bits->format == PIXMAN_a8r8g8b8 || - bits->format == PIXMAN_x8
[Pixman] [PATCH] Add support for AltiVec detection for OpenBSD/PowerPC.
From: Brad Smith Bug 29331. --- pixman/pixman-cpu.c | 25 - 1 files changed, 24 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c index e96b140..1b31885 100644 --- a/pixman/pixman-cpu.c +++ b/pixman/pixman-cpu.c @@ -61,6 +61,29 @@ pixman_have_vmx (void) return have_vmx; } +#elif defined (__OpenBSD__) +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ +if (!initialized) +{ + int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; + size_t length = sizeof(have_vmx); + int error = + sysctl (&mib, 2, &have_vmx, &length, NULL, 0); + + if (error) + have_vmx = FALSE; + + initialized = TRUE; +} +return have_vmx; +} + #elif defined (__linux__) #include #include @@ -123,7 +146,7 @@ pixman_have_vmx (void) return have_vmx; } -#else /* !__APPLE__ && !__linux__ */ +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ #include #include -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Use stdint.h on OpenBSD
From: Brad Smith OpenBSD has had stdint.h for a long time now. Bug 29330. --- pixman/pixman.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pixman/pixman.h b/pixman/pixman.h index 9981f0d..c1ecedc 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -87,7 +87,7 @@ PIXMAN_BEGIN_DECLS #if !defined (PIXMAN_DONT_DEFINE_STDINT) -#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) || defined (__HP_cc) +#if defined (_SVR4) || defined (SVR4) || defined (_sgi) || defined (__sun) || defined (sun) || defined (__digital__) || defined (__HP_cc) # include /* VS 2010 (_MSC_VER 1600) has stdint.h */ #elif defined (_MSC_VER) && _MSC_VER < 1600 -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add alpha-loop test program
From: Søren Sandmann Pedersen This tests what happens if you attempt to make an image with an alpha map that has the image as its alpha map. This results in an infinite loop in _pixman_image_validate(), so the test sets up a SIGALRM to exit if it runs for more than five seconds. --- configure.ac | 12 +++- test/Makefile.am |4 test/alpha-loop.c | 29 + test/utils.c | 33 + test/utils.h |3 +++ 5 files changed, 80 insertions(+), 1 deletions(-) create mode 100644 test/alpha-loop.c diff --git a/configure.ac b/configure.ac index 98c2783..acec8a1 100644 --- a/configure.ac +++ b/configure.ac @@ -600,13 +600,23 @@ AC_SUBST(DEP_CFLAGS) AC_SUBST(DEP_LIBS) dnl = -dnl posix_memalign +dnl posix_memalign, sigaction, alarm AC_CHECK_FUNC(posix_memalign, have_posix_memalign=yes, have_posix_memalign=no) if test x$have_posix_memalign = xyes; then AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, [Whether we have posix_memalign()]) fi +AC_CHECK_FUNC(sigaction, have_sigaction=yes, have_sigaction=no) +if test x$have_sigaction = xyes; then + AC_DEFINE(HAVE_SIGACTION, 1, [Whether we have sigaction()]) +fi + +AC_CHECK_FUNC(alarm, have_alarm=yes, have_alarm=no) +if test x$have_alarm = xyes; then + AC_DEFINE(HAVE_ALARM, 1, [Whether we have alarm()]) +fi + dnl = dnl Thread local storage diff --git a/test/Makefile.am b/test/Makefile.am index 2a7aea2..5273bec 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ TESTPROGRAMS =\ gradient-crash-test \ trap-crasher\ alphamap\ + alpha-loop \ scaling-crash-test \ blitters-test \ scaling-test\ @@ -39,6 +40,9 @@ scaling_test_SOURCES = scaling-test.c utils.c utils.h alphamap_LDADD = $(TEST_LDADD) alphamap_SOURCES = alphamap.c utils.c utils.h +alpha_loop_LDADD = $(TEST_LDADD) +alpha_loop_SOURCES = alpha-loop.c utils.c utils.h + # GTK using test programs if HAVE_GTK diff --git a/test/alpha-loop.c b/test/alpha-loop.c new file mode 100644 index 000..e4d90a9 --- /dev/null +++ b/test/alpha-loop.c @@ -0,0 +1,29 @@ +#include +#include +#include "utils.h" + +#define WIDTH 400 +#define HEIGHT 200 + +int +main (int argc, char **argv) +{ +uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); +uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); +uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); + +pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); +pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); +pixman_image_t *s = pixman_image_create_bits (PIXMAN_a2r10g10b10, WIDTH, HEIGHT, src, WIDTH * 4); + +fail_after (5, "Infinite loop detected: 5 seconds without progress\n"); + +pixman_image_set_alpha_map (s, a, 0, 0); +pixman_image_set_alpha_map (a, s, 0, 0); + +pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + +pixman_image_unref (s); + +return 0; +} diff --git a/test/utils.c b/test/utils.c index 1ee5c9c..d95cbc2 100644 --- a/test/utils.c +++ b/test/utils.c @@ -1,4 +1,9 @@ #include "utils.h" +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /* Random number seed */ @@ -319,3 +324,31 @@ fuzzer_test_main (const char *test_name, return 0; } + +static const char *global_msg; + +static void +on_alarm (int signo) +{ +printf ("%s\n", global_msg); +exit (1); +} + +void +fail_after (int seconds, const char *msg) +{ +#ifdef HAVE_SIGACTION +#ifdef HAVE_ALARM +struct sigaction action; + +global_msg = msg; + +memset (&action, 0, sizeof (action)); +action.sa_handler = on_alarm; + +alarm (seconds); + +sigaction (SIGALRM, &action, NULL); +#endif +#endif +} diff --git a/test/utils.h b/test/utils.h index 95d809a..bfb76a5 100644 --- a/test/utils.h +++ b/test/utils.h @@ -62,3 +62,6 @@ fuzzer_test_main (const char *test_name, uint32_t(*test_function)(int testnum, int verbose), int argc, const char *argv[]); + +void +fail_after (int seconds, const char *msg); -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] pixman_image_set_alpha_map(): Disallow alpha map cycles
From: Søren Sandmann Pedersen If someone tries to set an alpha map that itself has an alpha map, simply return. Also, if someone tries to add an alpha map to an image that is being _used_ as an alpha map, simply return. This ensures that an alpha map can never have an alpha map. --- pixman/pixman-image.c | 30 +++--- pixman/pixman-private.h |1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 269c3c1..0b8bb3c 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -101,6 +101,7 @@ _pixman_image_allocate (void) pixman_region32_init (&common->clip_region); + common->alpha_count = 0; common->have_clip_region = FALSE; common->clip_sources = FALSE; common->transform = NULL; @@ -195,9 +196,6 @@ pixman_image_unref (pixman_image_t *image) if (common->filter_params) free (common->filter_params); - if (common->alpha_map) - pixman_image_unref ((pixman_image_t *)common->alpha_map); - if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL) @@ -668,15 +666,41 @@ pixman_image_set_alpha_map (pixman_image_t *image, return_if_fail (!alpha_map || alpha_map->type == BITS); +if (alpha_map && common->alpha_count > 0) +{ + /* If this image is being used as an alpha map itself, +* then you can't give it an alpha map of its own. +*/ + return; +} + +if (alpha_map && alpha_map->common.alpha_map) +{ + /* If the image has an alpha map of its own, +* then it can't be used as an alpha map itself +*/ + return; +} + if (common->alpha_map != (bits_image_t *)alpha_map) { if (common->alpha_map) + { + common->alpha_map->common.alpha_count--; + pixman_image_unref ((pixman_image_t *)common->alpha_map); + } if (alpha_map) + { common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map); + + common->alpha_map->common.alpha_count++; + } else + { common->alpha_map = NULL; + } } common->alpha_origin_x = x; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 0629c42..c4e6bb8 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -80,6 +80,7 @@ struct image_common image_type_ttype; int32_t ref_count; pixman_region32_t clip_region; +int32_talpha_count;/* How many times this image is being used as an alpha map */ pixman_bool_t have_clip_region; /* FALSE if there is no clip */ pixman_bool_t client_clip;/* Whether the source clip was set by a client */ -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Merge pixman_image_composite32() and do_composite().
From: Søren Sandmann Pedersen There is not much point having a separate function that just validates the images. Also add a boolean return to lookup_composite_function() so that we can return if no composite function is found. --- pixman/pixman.c | 131 +++--- 1 files changed, 56 insertions(+), 75 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index ddd4935..402c72c 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -501,7 +501,7 @@ typedef struct PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); -static force_inline void +static force_inline pixman_bool_t lookup_composite_function (pixman_op_t op, pixman_format_code_t src_format, uint32_t src_flags, @@ -577,7 +577,7 @@ lookup_composite_function (pixman_op_t op, ++info; } } -return; +return FALSE; update_cache: if (i) @@ -595,6 +595,8 @@ update_cache: cache->cache[0].fast_path.dest_flags = dest_flags; cache->cache[0].fast_path.func = *out_func; } + +return TRUE; } static pixman_bool_t @@ -803,19 +805,38 @@ analyze_extent (pixman_image_t *image, int x, int y, return TRUE; } -static void -do_composite (pixman_op_t op, - pixman_image_t *src, - pixman_image_t *mask, - pixman_image_t *dest, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dest_x, - int dest_y, - int width, - int height) +/* + * Work around GCC bug causing crashes in Mozilla with SSE2 + * + * When using -msse, gcc generates movdqa instructions assuming that + * the stack is 16 byte aligned. Unfortunately some applications, such + * as Mozilla and Mono, end up aligning the stack to 4 bytes, which + * causes the movdqa instructions to fail. + * + * The __force_align_arg_pointer__ makes gcc generate a prologue that + * realigns the stack pointer to 16 bytes. + * + * On x86-64 this is not necessary because the standard ABI already + * calls for a 16 byte aligned stack. + * + * See https://bugs.freedesktop.org/show_bug.cgi?id=15693 + */ +#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) +__attribute__((__force_align_arg_pointer__)) +#endif +PIXMAN_EXPORT void +pixman_image_composite32 (pixman_op_t op, + pixman_image_t * src, + pixman_image_t * mask, + pixman_image_t * dest, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { pixman_format_code_t src_format, mask_format, dest_format; uint32_t src_flags, mask_flags, dest_flags; @@ -831,6 +852,11 @@ do_composite (pixman_op_t op, pixman_implementation_t *imp; pixman_composite_func_t func; +_pixman_image_validate (src); +if (mask) + _pixman_image_validate (mask); +_pixman_image_validate (dest); + src_format = src->common.extended_format_code; src_flags = src->common.flags; @@ -907,20 +933,21 @@ do_composite (pixman_op_top, if (op == PIXMAN_OP_DST) goto out; -lookup_composite_function (op, - src_format, src_flags, - mask_format, mask_flags, - dest_format, dest_flags, - &imp, &func); - -walk_region_internal (imp, op, - src, mask, dest, - src_x, src_y, mask_x, mask_y, - dest_x, dest_y, - width, height, - (src_flags & FAST_PATH_SIMPLE_REPEAT), - (mask_flags & FAST_PATH_SIMPLE_REPEAT), - ®ion, func); +if (lookup_composite_function (op, + src_format, src_flags, + mask_format, mask_flags, + dest_format, dest_flags, + &imp, &func)) +{ + walk_region_internal (imp, op, + src, mask, dest, + src_x, src_y, mask_x, mask_y, +
[Pixman] [PATCH] Be more paranoid about checking for GTK+
From: Søren Sandmann Pedersen From time to time peole run into issues where the configure script detects GTK+ when it is either not installed, or not functional due to a missing pixman. Most recently, https://bugs.freedesktop.org/show_bug.cgi?id=29736 This patch makes the configure script more paranoid by - always using PKG_CHECK_MODULES and not PKG_CHECK_EXISTS, since it seems PKG_CHECK_EXISTS will sometimes return true even if a dependency of GTK+, such as pixman-1, is missing. - explicitly checking that pixman-1 is installed before enabling GTK+. Cc: my.somewhat.lengthy.loginn...@gmail.com --- configure.ac | 14 ++ 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index d8a8999..dbff2a6 100644 --- a/configure.ac +++ b/configure.ac @@ -178,7 +178,6 @@ AC_SUBST(PIXMAN_VERSION_MICRO) AC_SUBST(LT_VERSION_INFO) # Check for dependencies -#PKG_CHECK_MODULES(DEP, x11) PIXMAN_CHECK_CFLAG([-Wall]) PIXMAN_CHECK_CFLAG([-fno-strict-aliasing]) @@ -585,11 +584,18 @@ AC_ARG_ENABLE(gtk, [enable_gtk=$enableval], [enable_gtk=auto]) PKG_PROG_PKG_CONFIG + +if test $enable_gtk = yes ; then + AC_CHECK_LIB([pixman-1], [pixman_version_string]) + PKG_CHECK_MODULES(GTK, [gtk+-2.0 pixman-1]) +fi + if test $enable_gtk = auto ; then - PKG_CHECK_EXISTS([gtk+-2.0], [enable_gtk=yes], [enable_gtk=no]) + AC_CHECK_LIB([pixman-1], [pixman_version_string], [enable_gtk=auto], [enable_gtk=no]) fi -if test $enable_gtk = yes ; then - PKG_CHECK_MODULES(GTK, [gtk+-2.0]) + +if test $enable_gtk = auto ; then + PKG_CHECK_MODULES(GTK, [gtk+-2.0 pixman-1], [enable_gtk=yes], [enable_gtk=no]) fi AM_CONDITIONAL(HAVE_GTK, [test "x$enable_gtk" = xyes]) -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Store a2b2g2r2 pixel through the WRITE macro
From: Søren Sandmann Pedersen Otherwise, accessor functions won't work. --- pixman/pixman-access.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 56de711..f1ce0ba 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2425,11 +2425,11 @@ store_scanline_a2b2g2r2 (bits_image_t * image, { SPLIT_A (values[i]); - *(pixel++) = - ((a ) & 0xc0) | - ((b >> 2) & 0x30) | - ((g >> 4) & 0x0c) | - ((r >> 6) ); + WRITE (image, pixel++, + ((a ) & 0xc0) | + ((b >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((r >> 6) )); } } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] When pixman_compute_composite_region32() return FALSE, don't fini the region.
From: Søren Sandmann Pedersen The rule is that the region passed in must be initialized and that the region returned will still be valid. Ie., the lifecycle is the responsibility of the caller, regardless of what the function returns. Previously, composite_region32() would finalize the region and then return FALSE, and then the caller would finalize the region again, leading to memory corruption in some cases. --- pixman/pixman.c | 14 +- 1 files changed, 1 insertions(+), 13 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 402c72c..62b58b8 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -302,17 +302,13 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (region->extents.x1 >= region->extents.x2 || region->extents.y1 >= region->extents.y2) { - pixman_region32_init (region); return FALSE; } if (dst_image->common.have_clip_region) { if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) - { - pixman_region32_fini (region); return FALSE; - } } if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) @@ -321,7 +317,6 @@ pixman_compute_composite_region32 (pixman_region32_t * region, -dst_image->common.alpha_origin_x, -dst_image->common.alpha_origin_y)) { - pixman_region32_fini (region); return FALSE; } } @@ -330,10 +325,7 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (src_image->common.have_clip_region) { if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) - { - pixman_region32_fini (region); return FALSE; - } } if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) { @@ -341,7 +333,6 @@ pixman_compute_composite_region32 (pixman_region32_t * region, dest_x - (src_x - src_image->common.alpha_origin_x), dest_y - (src_y - src_image->common.alpha_origin_y))) { - pixman_region32_fini (region); return FALSE; } } @@ -349,17 +340,14 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (mask_image && mask_image->common.have_clip_region) { if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) - { - pixman_region32_fini (region); return FALSE; - } + if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) { if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, dest_x - (mask_x - mask_image->common.alpha_origin_x), dest_y - (mask_y - mask_image->common.alpha_origin_y))) { - pixman_region32_fini (region); return FALSE; } } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Silence some warnings about uninitialized variables
From: Søren Sandmann Pedersen Neither were real problems, but GCC were complaining about them. --- pixman/pixman.c |3 +++ test/composite.c |1 + 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 62b58b8..47ffdd6 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -613,6 +613,9 @@ compute_sample_extents (pixman_transform_t *transform, { int i; + /* Silence GCC */ + tx1 = ty1 = tx2 = ty2 = 0; + for (i = 0; i < 4; ++i) { pixman_fixed_48_16_t tx, ty; diff --git a/test/composite.c b/test/composite.c index 0624cd3..b530a20 100644 --- a/test/composite.c +++ b/test/composite.c @@ -882,6 +882,7 @@ main (void) mask.size? TRUE : FALSE); break; default: + ok = FALSE; /* Silence GCC */ break; } group_ok = group_ok && ok; -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add FAST_PATH_NO_ALPHA_MAP to the standard destination flags.
From: Søren Sandmann Pedersen We can't in general take a fast path if the destination has an alpha map. --- pixman/pixman-private.h |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index dedea0b..3557fb2 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -613,6 +613,7 @@ _pixman_choose_implementation (void); FAST_PATH_COMPONENT_ALPHA) #define FAST_PATH_STD_DEST_FLAGS \ (FAST_PATH_NO_ACCESSORS| \ + FAST_PATH_NO_ALPHA_MAP| \ FAST_PATH_NO_WIDE_FORMAT) #define FAST_PATH(op, src, src_flags, mask, mask_flags, dest, dest_flags, func) \ -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Do opacity computation with shifts instead of comparing with 0
From: Søren Sandmann Pedersen Also add a COMPILE_TIME_ASSERT() macro and use it to assert that the shift is correct. --- pixman/pixman-private.h |3 +++ pixman/pixman.c | 14 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 3557fb2..36b9d91 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -744,6 +744,9 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, #undef DEBUG +#define COMPILE_TIME_ASSERT(x) \ +do { typedef int compile_time_assertion [(x)?1:-1]; } while (0) + /* Turn on debugging depending on what type of release this is */ #if (((PIXMAN_VERSION_MICRO % 2) == 0) && ((PIXMAN_VERSION_MINOR % 2) == 1)) diff --git a/pixman/pixman.c b/pixman/pixman.c index 47ffdd6..cdf4b75 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -139,14 +139,18 @@ optimize_operator (pixman_op_t op, uint32_tdst_flags) { pixman_bool_t is_source_opaque, is_dest_opaque; -int opaqueness; -is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0; -is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0; +#define OPAQUE_SHIFT 13 + +COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT)); + +is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE); +is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE); -opaqueness = ((is_dest_opaque << 1) | is_source_opaque); +is_dest_opaque >>= OPAQUE_SHIFT - 1; +is_source_opaque >>= OPAQUE_SHIFT; -return operator_table[op].opaque_info[opaqueness]; +return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque]; } static void -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/5] Add fence_malloc() and fence_free().
From: Søren Sandmann Pedersen These variants of malloc() and free() try to surround the allocated memory with protected pages so that out-of-bounds accessess will cause a segmentation fault. If mprotect() and getpagesize() are not available, these functions are simply equivalent to malloc() and free(). --- configure.ac | 10 + test/utils.c | 105 +- test/utils.h | 11 +- 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index dbff2a6..652fec9 100644 --- a/configure.ac +++ b/configure.ac @@ -623,6 +623,16 @@ if test x$have_alarm = xyes; then AC_DEFINE(HAVE_ALARM, 1, [Whether we have alarm()]) fi +AC_CHECK_FUNC(mprotect, have_mprotect=yes, have_mprotect=no) +if test x$have_mprotect = xyes; then + AC_DEFINE(HAVE_MPROTECT, 1, [Whether we have mprotect()]) +fi + +AC_CHECK_FUNC(getpagesize, have_getpagesize=yes, have_=no) +if test x$have_getpagesize = xyes; then + AC_DEFINE(HAVE_GETPAGESIZE, 1, [Whether we have getpagesize()]) +fi + dnl = dnl Thread local storage diff --git a/test/utils.c b/test/utils.c index d95cbc2..0134e04 100644 --- a/test/utils.c +++ b/test/utils.c @@ -5,6 +5,8 @@ #include #endif +#include + /* Random number seed */ @@ -197,10 +199,111 @@ image_endian_swap (pixman_image_t *img, int bpp) } } +#define N_LEADING_PROTECTED10 +#define N_TRAILING_PROTECTED 10 +#define INITIAL_PAGE + +typedef struct +{ +void *addr; +uint32_t len; +uint8_t *trailing; +} info_t; + +#if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) + +void * +fence_malloc (uint32_t len) +{ +unsigned long page_size = getpagesize(); +unsigned long page_mask = page_size - 1; +uint32_t n_payload_bytes = (len + page_mask) & ~page_mask; +uint32_t n_bytes = + (len + +page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) + +n_payload_bytes) & ~page_mask; +uint8_t *initial_page; +uint8_t *leading_protected; +uint8_t *trailing_protected; +uint8_t *payload; +uint8_t *addr; + +addr = malloc (n_bytes); + +if (!addr) +{ + printf ("malloc failed on %u %u\n", len, n_bytes); + return NULL; +} + +initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask); +leading_protected = initial_page + page_size; +payload = leading_protected + N_LEADING_PROTECTED * page_size; +trailing_protected = payload + n_payload_bytes; + +((info_t *)initial_page)->addr = addr; +((info_t *)initial_page)->len = len; +((info_t *)initial_page)->trailing = trailing_protected; + +if (mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_NONE) == -1) +{ + free (addr); + return NULL; +} + +if (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size, + PROT_NONE) == -1) +{ + mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + + free (addr); + return NULL; +} + +return payload; +} + +void +fence_free (void *data) +{ +uint32_t page_size = getpagesize(); +uint8_t *payload = data; +uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size; +uint8_t *initial_page = leading_protected - page_size; +info_t *info = (info_t *)initial_page; +uint8_t *trailing_protected = info->trailing; + +mprotect (leading_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + +mprotect (trailing_protected, N_LEADING_PROTECTED * page_size, + PROT_READ | PROT_WRITE); + +free (info->addr); +} + +#else + +void * +fence_malloc (uint32_t len) +{ +return malloc (len); +} + +void +fence_free (void *data) +{ +free (data); +} + +#endif + uint8_t * make_random_bytes (int n_bytes) { -uint8_t *bytes = malloc (n_bytes); +uint8_t *bytes = fence_malloc (n_bytes); int i; if (!bytes) diff --git a/test/utils.h b/test/utils.h index a39af02..14e3c8b 100644 --- a/test/utils.h +++ b/test/utils.h @@ -51,7 +51,16 @@ compute_crc32 (uint32_tin_crc32, void image_endian_swap (pixman_image_t *img, int bpp); -/* Generate n_bytes random bytes in malloced memory */ +/* Allocate memory that is bounded by protected pages, + * so that out-of-bounds access will cause segfaults + */ +void * +fence_malloc (uint32_t len); + +void +fence_free (void *data); + +/* Generate n_bytes random bytes in fence_malloced memory */ uint8_t * make_random_bytes (int n_bytes); -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/5] Update and extend the alphamap test
From: Søren Sandmann Pedersen - Test many more combinations of formats - Test destination alpha maps - Test various different alpha origins Also add a transformation to the destination, but comment it out because it is actually broken at the moment (and pretty difficult to fix). --- test/Makefile.am |2 +- test/alphamap.c | 243 -- 2 files changed, 218 insertions(+), 27 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 3d98e17..f3b2b58 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,9 +13,9 @@ TESTPROGRAMS =\ window-test \ gradient-crash-test \ trap-crasher\ - alphamap\ alpha-loop \ scaling-crash-test \ + alphamap\ blitters-test \ scaling-test\ composite diff --git a/test/alphamap.c b/test/alphamap.c index e6a25ef..09de387 100644 --- a/test/alphamap.c +++ b/test/alphamap.c @@ -2,47 +2,238 @@ #include #include "utils.h" -#define WIDTH 400 -#define HEIGHT 200 +#define WIDTH 100 +#define HEIGHT 100 -int -main (int argc, char **argv) +static const pixman_format_code_t formats[] = +{ +PIXMAN_a8r8g8b8, +PIXMAN_a2r10g10b10, +PIXMAN_a4r4g4b4, +PIXMAN_a8 +}; + +static const pixman_format_code_t alpha_formats[] = +{ +PIXMAN_null, +PIXMAN_a8, +PIXMAN_a2r10g10b10, +PIXMAN_a4r4g4b4 +}; + +static const int origins[] = { -uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); -uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); -uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); -int i; +0, 10, -100 +}; -pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); -pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); +static const char * +format_name (pixman_format_code_t format) +{ +if (format == PIXMAN_a8) + return "a8"; +else if (format == PIXMAN_a2r10g10b10) + return "a2r10g10b10"; +else if (format == PIXMAN_a8r8g8b8) + return "a8r8g8b8"; +else if (format == PIXMAN_a4r4g4b4) + return "a4r4g4b4"; +else if (format == PIXMAN_null) + return "none"; +else + assert (0); -for (i = 0; i < 2; ++i) +return ""; +} + +static pixman_image_t * +make_image (pixman_format_code_t format) +{ +uint32_t *bits; +uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8; + +bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp); + +return pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp); +} + +static pixman_image_t * +create_image (pixman_format_code_t format, pixman_format_code_t alpha_format, + int alpha_origin_x, int alpha_origin_y) +{ +pixman_image_t *image = make_image (format); + +if (alpha_format != PIXMAN_null) { - pixman_format_code_t sformat = (i == 0)? PIXMAN_a8r8g8b8 : PIXMAN_a2r10g10b10; - pixman_image_t *s = pixman_image_create_bits (sformat, WIDTH, HEIGHT, src, WIDTH * 4); - int j, k; + pixman_image_t *alpha = make_image (alpha_format); - pixman_image_set_alpha_map (s, a, 0, 0); + pixman_image_set_alpha_map (image, alpha, + alpha_origin_x, alpha_origin_y); +} - pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); +return image; +} - for (j = 0; j < HEIGHT; ++j) +static uint8_t +get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y) +{ +uint8_t *bits; +uint8_t r; + +if (image->common.alpha_map) +{ + if (x - orig_x >= 0 && x - orig_x < WIDTH && + y - orig_y >= 0 && y - orig_y < HEIGHT) + { + image = (pixman_image_t *)image->common.alpha_map; + + x -= orig_x; + y -= orig_y; + } + else { - for (k = 0; k < WIDTH; ++k) + return 0; + } +} + +bits = (uint8_t *)image->bits.bits; + +if (image->bits.format == PIXMAN_a8) +{ + r = bits[y * WIDTH + x]; +} +else if (image->bits.format == PIXMAN_a2r10g10b10) +{ + r = ((uint32_t *)bits)[y * WIDTH + x] >> 30; + r |= r << 2; + r |= r << 4; +} +else if (image->bits.format == PIXMAN_a8r8g8b8) +{ + r = ((uint32_t *)bits)[y * WIDTH + x] >> 24; +} +else if (image->bits.format == PIXMAN_a4r4g4b4) +{ + r = ((uint16_t *)bits)[y * WIDTH + x] >> 12; + r |= r << 4; +} +else +{ + assert (0); +} + +return r; +} + +#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof (
[Pixman] [PATCH 3/5] Rename FAST_PATH_NO_WIDE_FORMAT to FAST_PATH_NARROW_FORMAT
From: Søren Sandmann Pedersen This avoids a negative in the name. Also, by renaming the "wide" variable in pixman-general.c to "narrow" and fixing up the logic correspondingly, the code there reads a lot more straightforwardly. --- pixman/pixman-fast-path.c |2 +- pixman/pixman-general.c | 46 ++-- pixman/pixman-image.c |4 +- pixman/pixman-private.h |6 ++-- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index f03752f..6dee472 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1864,7 +1864,7 @@ static const pixman_fast_path_t c_fast_paths[] = FAST_PATH_NO_ALPHA_MAP| \ FAST_PATH_NEAREST_FILTER | \ FAST_PATH_NO_ACCESSORS| \ - FAST_PATH_NO_WIDE_FORMAT) + FAST_PATH_NARROW_FORMAT) #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \ { PIXMAN_OP_ ## op, \ diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index fc742c0..fc276bd 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -63,11 +63,11 @@ general_composite_rect (pixman_implementation_t *imp, mask && mask->type == BITS ? mask->bits.format : 0; const pixman_format_code_t dest_format = dest->type == BITS ? dest->bits.format : 0; -const int src_wide = PIXMAN_FORMAT_IS_WIDE (src_format); -const int mask_wide = mask && PIXMAN_FORMAT_IS_WIDE (mask_format); -const int dest_wide = PIXMAN_FORMAT_IS_WIDE (dest_format); -const int wide = src_wide || mask_wide || dest_wide; -const int Bpp = wide ? 8 : 4; +const int src_narrow = !PIXMAN_FORMAT_IS_WIDE (src_format); +const int mask_narrow = !mask || !PIXMAN_FORMAT_IS_WIDE (mask_format); +const int dest_narrow = !PIXMAN_FORMAT_IS_WIDE (dest_format); +const int narrow = src_narrow && mask_narrow && dest_narrow; +const int Bpp = narrow ? 4 : 8; uint8_t *scanline_buffer = stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL; @@ -106,29 +106,29 @@ general_composite_rect (pixman_implementation_t *imp, if (op == PIXMAN_OP_CLEAR) fetch_src = NULL; -else if (wide) - fetch_src = _pixman_image_get_scanline_64; -else +else if (narrow) fetch_src = _pixman_image_get_scanline_32; +else + fetch_src = _pixman_image_get_scanline_64; if (!mask || op == PIXMAN_OP_CLEAR) fetch_mask = NULL; -else if (wide) - fetch_mask = _pixman_image_get_scanline_64; -else +else if (narrow) fetch_mask = _pixman_image_get_scanline_32; +else + fetch_mask = _pixman_image_get_scanline_64; if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC) fetch_dest = NULL; -else if (wide) - fetch_dest = _pixman_image_get_scanline_64; -else +else if (narrow) fetch_dest = _pixman_image_get_scanline_32; - -if (wide) - store = _pixman_image_store_scanline_64; else + fetch_dest = _pixman_image_get_scanline_64; + +if (narrow) store = _pixman_image_store_scanline_32; +else + store = _pixman_image_store_scanline_64; /* Skip the store step and composite directly into the * destination if the output format of the compose func matches @@ -148,7 +148,7 @@ general_composite_rect (pixman_implementation_t *imp, op == PIXMAN_OP_OUT_REVERSE || op == PIXMAN_OP_DST))) { - if (!wide && + if (narrow && !dest->common.alpha_map && !dest->bits.write_func) { @@ -175,19 +175,19 @@ general_composite_rect (pixman_implementation_t *imp, mask->common.component_alpha&& PIXMAN_FORMAT_RGB (mask->bits.format); -if (wide) +if (narrow) { if (component_alpha) - compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; + compose = _pixman_implementation_combine_32_ca; else - compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; + compose = _pixman_implementation_combine_32; } else { if (component_alpha) - compose = _pixman_implementation_combine_32_ca; + compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; else - compose = _pixman_implementation_combine_32; + compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; } if (!compose) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index cfee865..102df6c 100644 --
[Pixman] [PATCH 4/5] Remove FAST_PATH_NARROW_FORMAT flag if there is a wide alpha map
From: Søren Sandmann Pedersen If an image has an alpha map that has wide components, then we need to use 64 bit processing for that image. We detect this situation in pixman-image.c and remove the FAST_PATH_NARROW_FORMAT flag. In pixman-general, the wide/narrow decision is now based on the flags instead of on the formats. --- pixman/pixman-general.c | 18 +++--- pixman/pixman-image.c | 15 +++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index fc276bd..4d234a0 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -57,17 +57,6 @@ general_composite_rect (pixman_implementation_t *imp, int32_t height) { uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3]; -const pixman_format_code_t src_format = - src->type == BITS ? src->bits.format : 0; -const pixman_format_code_t mask_format = - mask && mask->type == BITS ? mask->bits.format : 0; -const pixman_format_code_t dest_format = - dest->type == BITS ? dest->bits.format : 0; -const int src_narrow = !PIXMAN_FORMAT_IS_WIDE (src_format); -const int mask_narrow = !mask || !PIXMAN_FORMAT_IS_WIDE (mask_format); -const int dest_narrow = !PIXMAN_FORMAT_IS_WIDE (dest_format); -const int narrow = src_narrow && mask_narrow && dest_narrow; -const int Bpp = narrow ? 4 : 8; uint8_t *scanline_buffer = stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL; @@ -77,8 +66,15 @@ general_composite_rect (pixman_implementation_t *imp, pixman_bool_t component_alpha; uint32_t *bits; int32_t stride; +int narrow, Bpp; int i; +narrow = + (src->common.flags & FAST_PATH_NARROW_FORMAT) && + (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) && + (dest->common.flags & FAST_PATH_NARROW_FORMAT); +Bpp = narrow ? 4 : 8; + if (width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (width, 3, Bpp); diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 102df6c..029a1df 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -327,10 +327,6 @@ compute_image_info (pixman_image_t *image) flags |= FAST_PATH_Y_UNIT_ZERO; } -/* Alpha map */ -if (!image->common.alpha_map) - flags |= FAST_PATH_NO_ALPHA_MAP; - /* Filter */ switch (image->common.filter) { @@ -454,6 +450,17 @@ compute_image_info (pixman_image_t *image) break; } +/* Alpha map */ +if (!image->common.alpha_map) +{ + flags |= FAST_PATH_NO_ALPHA_MAP; +} +else +{ + if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format)) + flags &= ~FAST_PATH_NARROW_FORMAT; +} + /* Both alpha maps and convolution filters can introduce * non-opaqueness in otherwise opaque images. Also * an image with component alpha turned on is only opaque -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 5/5] Clip composite region against the destination alpha map extents.
From: Søren Sandmann Pedersen Otherwise we can end up writing outside the alpha map. --- pixman/pixman.c | 21 + 1 files changed, 17 insertions(+), 4 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index cdf4b75..285bbfc 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -315,14 +315,27 @@ pixman_compute_composite_region32 (pixman_region32_t * region, return FALSE; } -if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) +if (dst_image->common.alpha_map) { - if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, --dst_image->common.alpha_origin_x, --dst_image->common.alpha_origin_y)) + if (!pixman_region32_intersect_rect (region, region, +dst_image->common.alpha_origin_x, +dst_image->common.alpha_origin_y, +dst_image->common.alpha_map->width, + dst_image->common.alpha_map->height)) { return FALSE; } + if (!pixman_region32_not_empty (region)) + return FALSE; + if (dst_image->common.alpha_map->common.have_clip_region) + { + if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, +-dst_image->common.alpha_origin_x, +-dst_image->common.alpha_origin_y)) + { + return FALSE; + } + } } /* clip against src */ -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/5] Fix various alpha map related bugs
From: Søren Sandmann Pedersen Hi, The following patch series contains some fixes for various alpha-map related bugs. The bugs are: - We don't currently clip the composite region against the extents of the alpha map of the destination. This means that if the alpha map doesn't cover the entire destination, we will make invalid writes to it. - If the alpha map is one of the 10bpc formats, then it doesn't have a 32 bit fetcher installed, which causes crashes. The fix for this is to make sure wide alpha maps result in wide processing. There is also a stylistic change where the NO_WIDE_FORMAT flag is renamed to FAST_PATH_NARROW_FORMAT to avoid the negative in the name. Finally, there are some updates to the test suite: - The alpha map test is much more aggressive. It now demonstrates the two bugs above and also tests that destination alpha maps are correctly read and written. - The alpha map test now also has code to set a transformation on the destination, but this is commented out because it causes crashes even with the other changes. This problem is somewhat difficult to fix because we currently don't have any fetchers that will do alphamap processing, but ignore transformations. - There is a new fence_malloc()/fence_free() pair of utility functions. These attempt to allocate the memory surrounded by mprotect()ed pages so that invalid reads or writes will cause crashes. Soren Søren Sandmann Pedersen (5): Add fence_malloc() and fence_free(). Update and extend the alphamap test Rename FAST_PATH_NO_WIDE_FORMAT to FAST_PATH_NARROW_FORMAT Remove FAST_PATH_NARROW_FORMAT flag if there is a wide alpha map Clip composite region against the destination alpha map extents. configure.ac | 10 ++ pixman/pixman-fast-path.c |2 +- pixman/pixman-general.c | 54 +-- pixman/pixman-image.c | 19 +++- pixman/pixman-private.h |6 +- pixman/pixman.c | 21 +++- test/Makefile.am |2 +- test/alphamap.c | 243 - test/utils.c | 105 +++- test/utils.h | 11 ++- 10 files changed, 401 insertions(+), 72 deletions(-) ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/3] Add new FAST_PATH_UNCOMPOSITABLE flag
From: Søren Sandmann Pedersen This is set if the image can't be used for compositing, such as when it's bigger than 0x or has size 0. --- pixman/pixman-image.c | 10 ++ pixman/pixman-private.h |1 + pixman/pixman.c | 10 +++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 029a1df..512142d 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -398,6 +398,16 @@ compute_image_info (pixman_image_t *image) { code = image->bits.format; + /* During repeat mode calculations we might convert the +* width/height of an image to fixed 16.16, so we need +* them to be smaller than 16 bits. +*/ + if (image->bits.width == 0 || image->bits.height == 0 || + image->bits.width >= 0x || image->bits.height >= 0x) + { + flags |= FAST_PATH_UNCOMPOSITABLE; + } + if (!image->common.transform && image->common.repeat == PIXMAN_REPEAT_NORMAL) { diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d85868f..b05a68d 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -572,6 +572,7 @@ _pixman_choose_implementation (void); #define FAST_PATH_NO_NORMAL_REPEAT (1 << 21) #define FAST_PATH_HAS_TRANSFORM(1 << 22) #define FAST_PATH_SAMPLES_OPAQUE (1 << 23) +#define FAST_PATH_UNCOMPOSITABLE (1 << 24) #define FAST_PATH_PAD_REPEAT \ (FAST_PATH_NO_NONE_REPEAT | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index 285bbfc..ea048cc 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -715,13 +715,6 @@ analyze_extent (pixman_image_t *image, int x, int y, transform = image->common.transform; if (image->common.type == BITS) { - /* During repeat mode calculations we might convert the -* width/height of an image to fixed 16.16, so we need -* them to be smaller than 16 bits. -*/ - if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff) - return FALSE; - if (image->common.repeat == PIXMAN_REPEAT_NONE && (x > extents->x1 || y > extents->y1 || x + image->bits.width < extents->x2 || @@ -882,6 +875,9 @@ pixman_image_composite32 (pixman_op_t op, dest_format = dest->common.extended_format_code; dest_flags = dest->common.flags; +if ((src_flags | dest_flags | mask_flags) & FAST_PATH_UNCOMPOSITABLE) + return; + /* Check for pixbufs */ if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && (src->type == BITS && src->bits.bits == mask->bits.bits) && -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/3] Move some of the FAST_PATH_COVERS_CLIP computation to pixman-image.c
From: Søren Sandmann Pedersen When an image is solid or repeating, the FAST_PATH_COVERS_CLIP flag can be set in compute_image_info(). Also the code that turned this flag off in pixman.c was not correct; it didn't take transformations into account. With this patch, pixman.c doesn't set the flag by default, but instead relies on the call to compute_samples_extents() to set it when possible. --- pixman/pixman-image.c | 25 + pixman/pixman.c | 21 + 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 512142d..8d92dd9 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -353,19 +353,34 @@ compute_image_info (pixman_image_t *image) switch (image->common.repeat) { case PIXMAN_REPEAT_NONE: - flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NORMAL_REPEAT; + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NORMAL_REPEAT; break; case PIXMAN_REPEAT_REFLECT: - flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT; + flags |= + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NONE_REPEAT| + FAST_PATH_NO_NORMAL_REPEAT | + FAST_PATH_COVERS_CLIP; break; case PIXMAN_REPEAT_PAD: - flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT; + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_NONE_REPEAT| + FAST_PATH_NO_NORMAL_REPEAT | + FAST_PATH_COVERS_CLIP; break; default: - flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT; + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NONE_REPEAT| + FAST_PATH_COVERS_CLIP; break; } @@ -385,6 +400,8 @@ compute_image_info (pixman_image_t *image) if (image->solid.color.alpha == 0x) flags |= FAST_PATH_IS_OPAQUE; + + flags |= FAST_PATH_COVERS_CLIP; break; case BITS: diff --git a/pixman/pixman.c b/pixman/pixman.c index ea048cc..bf7de7d 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -708,22 +708,9 @@ analyze_extent (pixman_image_t *image, int x, int y, pixman_fixed_t width, height; pixman_box32_t ex; -*flags |= FAST_PATH_COVERS_CLIP; if (!image) return TRUE; -transform = image->common.transform; -if (image->common.type == BITS) -{ - if (image->common.repeat == PIXMAN_REPEAT_NONE && - (x > extents->x1 || y > extents->y1 || -x + image->bits.width < extents->x2 || -y + image->bits.height < extents->y2)) - { - (*flags) &= ~FAST_PATH_COVERS_CLIP; - } -} - /* Some compositing functions walk one step * outside the destination rectangle, so we * check here that the expanded-by-one source @@ -779,14 +766,16 @@ analyze_extent (pixman_image_t *image, int x, int y, } /* Check that the extents expanded by one don't overflow. This ensures that - * compositing functions can simply walk the source space using 16.16 variables - * without worrying about overflow. + * compositing functions can simply walk the source space using 16.16 + * variables without worrying about overflow. */ ex.x1 = extents->x1 - 1; ex.y1 = extents->y1 - 1; ex.x2 = extents->x2 + 1; ex.y2 = extents->y2 + 1; +transform = image->common.transform; + if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) return FALSE; @@ -799,7 +788,7 @@ analyze_extent (pixman_image_t *image, int x, int y, if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) { if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height) - *flags |= FAST_PATH_SAMPLES_COVER_CLIP; + *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP); } } -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/3] analyze_extents: Fast path for non-transformed BITS images
From: Søren Sandmann Pedersen Profiling various cairo traces showed that we were spending a lot of time in analyze_extents and compute_sample_extents(). This was especially bad for glyphs where all this computation was completely unnecessary. This patch adds a fast path for the case of non-transformed BITS images. The result is approximately a 6% improvement on the firefox-talos-gfx benchmark: Before: [ # ] backend test min(s) median(s) stddev. count [ 0]imagefirefox-talos-gfx 13.797 13.848 0.20%6/6 After: [ # ] backend test min(s) median(s) stddev. count [ 0]imagefirefox-talos-gfx 12.946 13.018 0.39%6/6 --- pixman/pixman.c | 39 --- 1 files changed, 24 insertions(+), 15 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index bf7de7d..26fe823 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -724,8 +724,21 @@ analyze_extent (pixman_image_t *image, int x, int y, return FALSE; } +transform = image->common.transform; if (image->common.type == BITS) { +#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER) + + if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST && + extents->x1 - x >= 0 && + extents->y1 - y >= 0 && + extents->x2 - x <= image->bits.width && + extents->y2 - y <= image->bits.height) + { + *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP); + return TRUE; + } + switch (image->common.filter) { case PIXMAN_FILTER_CONVOLUTION: @@ -756,6 +769,17 @@ analyze_extent (pixman_image_t *image, int x, int y, default: return FALSE; } + + /* Check whether the non-expanded, transformed extent is entirely within +* the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is. +*/ + ex = *extents; + if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) && + ex.x1 >= 0 && ex.y1 >= 0 && + ex.x2 <= image->bits.width && ex.y2 <= image->bits.height) + { + *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP); + } } else { @@ -774,24 +798,9 @@ analyze_extent (pixman_image_t *image, int x, int y, ex.x2 = extents->x2 + 1; ex.y2 = extents->y2 + 1; -transform = image->common.transform; - if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) return FALSE; -if (image->type == BITS) -{ - /* Check whether the non-expanded, transformed extent is entirely within -* the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is. -*/ - ex = *extents; - if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height)) - { - if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height) - *flags |= (FAST_PATH_SAMPLES_COVER_CLIP | FAST_PATH_COVERS_CLIP); - } -} - return TRUE; } -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] Fast paths for bilinear transformation
Hi, The following patches add some fast paths for bilinear transformation for the most important formats: a8, r5g6b5, x8r8g8b8, and a8r8g8b8. The code is actually commented out in the patches. It is enabled in a bunch of trivial commits here: http://cgit.freedesktop.org/~sandmann/pixman/log/?h=more-scalers that I didn't want to spam the list with. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 01/19] test: Add affine-test
From: Søren Sandmann Pedersen This test tests compositing with various affine transformations. It is almost identical to scaling-test, except that it also applies a random rotation in addition to the random scaling and translation. --- test/Makefile.am|4 + test/affine-test.c | 255 +++ test/scaling-test.c |2 +- 3 files changed, 260 insertions(+), 1 deletions(-) create mode 100644 test/affine-test.c diff --git a/test/Makefile.am b/test/Makefile.am index f3b2b58..ff851c9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,6 +18,7 @@ TESTPROGRAMS =\ alphamap\ blitters-test \ scaling-test\ + affine-test \ composite a1_trap_test_LDADD = $(TEST_LDADD) @@ -39,6 +40,9 @@ blitters_test_SOURCES = blitters-test.c utils.c utils.h scaling_test_LDADD = $(TEST_LDADD) scaling_test_SOURCES = scaling-test.c utils.c utils.h +affine_test_LDADD = $(TEST_LDADD) +affine_test_SOURCES = affine-test.c utils.c utils.h + alphamap_LDADD = $(TEST_LDADD) alphamap_SOURCES = alphamap.c utils.c utils.h diff --git a/test/affine-test.c b/test/affine-test.c new file mode 100644 index 000..5c6031c --- /dev/null +++ b/test/affine-test.c @@ -0,0 +1,255 @@ +/* + * Test program, which can detect some problems with affine transformations + * in pixman. Testing is done by running lots of random SRC and OVER + * compositing operations a8r8g8b8, x8a8r8g8b8 and r5g6b5 color formats + * with random scaled, rotated and translated transforms. + * + * Script 'fuzzer-find-diff.pl' can be used to narrow down the problem in + * the case of test failure. + */ +#include +#include +#include +#include "utils.h" + +#define MAX_SRC_WIDTH 10 +#define MAX_SRC_HEIGHT 10 +#define MAX_DST_WIDTH 10 +#define MAX_DST_HEIGHT 10 +#define MAX_STRIDE 4 + +/* + * Composite operation with pseudorandom images + */ +static uint32_t +test_composite (int testnum, + int verbose) +{ +inti; +pixman_image_t * src_img; +pixman_image_t * dst_img; +pixman_transform_t transform; +pixman_region16_t clip; +intsrc_width, src_height; +intdst_width, dst_height; +intsrc_stride, dst_stride; +intsrc_x, src_y; +intdst_x, dst_y; +intsrc_bpp; +intdst_bpp; +intw, h; +intscale_x = 32768, scale_y = 32768; +intop; +intrepeat = 0; +intsrc_fmt, dst_fmt; +uint32_t * srcbuf; +uint32_t * dstbuf; +uint32_t crc32; +FLOAT_REGS_CORRUPTION_DETECTOR_START(); + +lcg_srand (testnum); + +src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; +dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; +op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; + +src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; +src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; +dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; +dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; +src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; +dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; + +if (src_stride & 3) + src_stride += 2; + +if (dst_stride & 3) + dst_stride += 2; + +src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); +src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); +dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); +dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); +w = lcg_rand_n (dst_width * 3 / 2 - dst_x); +h = lcg_rand_n (dst_height * 3 / 2 - dst_y); + +srcbuf = (uint32_t *)malloc (src_stride * src_height); +dstbuf = (uint32_t *)malloc (dst_stride * dst_height); + +for (i = 0; i < src_stride * src_height; i++) + *((uint8_t *)srcbuf + i) = lcg_rand_n (256); + +for (i = 0; i < dst_stride * dst_height; i++) + *((uint8_t *)dstbuf + i) = lcg_rand_n (256); + +src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ? + PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; + +dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? + PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; + +src_img = pixman_image_create_bits ( +src_fmt, src_width, src_height, srcbuf, src_stride); + +dst_img = pixman_image_create_bits ( +dst_fmt, dst_width, dst_height, dstbuf, dst_stride); + +image_endian_swap (src_img, src_bpp * 8); +image_endian_swap (dst_img, dst_bpp * 8); + +pixman_transform_init_identity (&transform); + +if (lcg_rand_n (8) > 0) +{ + scale_x = 32768 + lcg_rand_n (65536); + scale_y = 32768 + lcg_rand_n (65536); +
[Pixman] [PATCH 02/19] Add nearest scaler for x888 on 8888
From: Søren Sandmann Pedersen --- pixman/pixman-fast-path.c | 10 +- pixman/pixman-private.h |5 - 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 6dee472..64e69e5 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1430,9 +1430,10 @@ repeat (pixman_repeat_t repeat, int *c, int size) */ #define GET__ALPHA(s) ((s) >> 24) +#define GET_x888_ALPHA(s) (0xff) /* This is not actually used since we don't have an OVER with 565 source, but it is needed to build. */ -#define GET_0565_ALPHA(s) 0xff +#define GET_0565_ALPHA(s) (0xff) #define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \ src_type_t, dst_type_t, OP, repeat_mode) \ @@ -1623,6 +1624,10 @@ FAST_NEAREST (__none, , , uint32_t, uint32_t, SRC, NONE); FAST_NEAREST (__normal, , , uint32_t, uint32_t, SRC, NORMAL); FAST_NEAREST (__none, , , uint32_t, uint32_t, OVER, NONE); FAST_NEAREST (__normal, , , uint32_t, uint32_t, OVER, NORMAL); + +FAST_NEAREST (x888__none, x888, , uint32_t, uint32_t, SRC, NONE); +FAST_NEAREST (x888__normal, x888, , uint32_t, uint32_t, SRC, NORMAL); + FAST_NEAREST (_565_none, , 0565, uint32_t, uint16_t, SRC, NONE); FAST_NEAREST (_565_normal, , 0565, uint32_t, uint16_t, SRC, NORMAL); FAST_NEAREST (565_565_none, 0565, 0565, uint16_t, uint16_t, SRC, NONE); @@ -1888,6 +1893,9 @@ static const pixman_fast_path_t c_fast_paths[] = SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, _), SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, _), +SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8, x888_), +SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8, x888_), + SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, _), SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, _), diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index b05a68d..ef87678 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -707,7 +707,7 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, #define CLIP(v, low, high) ((v) < (low) ? (low) : ((v) > (high) ? (high) : (v))) -/* Conversion between and 0565 */ +/* Various conversion macros */ #define CONVERT__TO_0565(s) \ s) >> 3) & 0x001f) | \ @@ -721,6 +721,9 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, #define CONVERT_0565_TO_(s) (CONVERT_0565_TO_0888(s) | 0xff00) +#define CONVERT_x888_TO_(s) \ +((s) | 0xff00) + /* Trivial versions that are useful in macros */ #define CONVERT__TO_(s) (s) #define CONVERT_0565_TO_0565(s) (s) -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 03/19] Use a macro to generate some {a, x}8r8g8b8, a8, and r5g6b5 bilinear fetchers.
From: Søren Sandmann Pedersen There are versions for all combinations of x8r8g8b8/a8r8g8b8 and pad/repeat/none/normal repeat modes. The bulk of each scaler is an inline function that takes a format and a repeat mode as parameters. The new scalers are all commented out, but the next commits will enable them one at a time to facilitate bisecting. --- pixman/pixman-bits-image.c | 257 +++- test/composite-test.c |5 +- 2 files changed, 255 insertions(+), 7 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index a32ebcc..98dc28a 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -637,7 +637,7 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image, buffer[i] = bits_image_fetch_pixel_filtered ( &image->bits, x, y, fetch_pixel_no_alpha); } - + x += ux; y += uy; } @@ -749,6 +749,222 @@ bits_image_fetch_general (pixman_image_t * image, } } +static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); + +static force_inline void +bits_image_fetch_bilinear_affine (pixman_image_t * image, + int offset, + int line, + int width, + uint32_t * buffer, + const uint32_t * mask, + + convert_pixel_t convert_pixel, + pixman_format_code_t format, + pixman_repeat_t repeat_mode) +{ +pixman_fixed_t x, y; +pixman_fixed_t ux, uy; +pixman_vector_t v; +bits_image_t *bits = &image->bits; +int i; + +/* reference point is the center of the pixel */ +v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; +v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; +v.vector[2] = pixman_fixed_1; + +if (!pixman_transform_point_3d (image->common.transform, &v)) + return; + +ux = image->common.transform->matrix[0][0]; +uy = image->common.transform->matrix[1][0]; + +x = v.vector[0]; +y = v.vector[1]; + +for (i = 0; i < width; ++i) +{ + int x1, y1, x2, y2; + uint32_t tl, tr, bl, br; + int32_t distx, disty; + int width = image->bits.width; + int height = image->bits.height; + const uint8_t *row1; + const uint8_t *row2; + + if (mask && !mask[i]) + goto next; + + x1 = x - pixman_fixed_1 / 2; + y1 = y - pixman_fixed_1 / 2; + + distx = (x1 >> 8) & 0xff; + disty = (y1 >> 8) & 0xff; + + y1 = pixman_fixed_to_int (y1); + y2 = y1 + 1; + x1 = pixman_fixed_to_int (x1); + x2 = x1 + 1; + + if (repeat_mode != PIXMAN_REPEAT_NONE) + { + uint32_t mask; + + mask = PIXMAN_FORMAT_A (format)? 0 : 0xff00; + + repeat (repeat_mode, width, &x1); + repeat (repeat_mode, height, &y1); + repeat (repeat_mode, width, &x2); + repeat (repeat_mode, height, &y2); + + row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; + row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2; + + tl = convert_pixel (row1, x1) | mask; + tr = convert_pixel (row1, x2) | mask; + bl = convert_pixel (row2, x1) | mask; + br = convert_pixel (row2, x2) | mask; + } + else + { + uint32_t mask1, mask2; + int bpp; + + /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value, +* which means if you use it in expressions, those +* expressions become unsigned themselves. Since +* the variables below can be negative in some cases, +* that will lead to crashes on 64 bit architectures. +* +* So this line makes sure bpp is signed +*/ + bpp = PIXMAN_FORMAT_BPP (format); + + if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0) + { + buffer[i] = 0; + goto next; + } + + if (y2 == 0) + { + row1 = zero; + mask1 = 0; + } + else + { + row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1; + row1 += bpp / 8 * x1; + + mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff00; + } + + if (y1 == height - 1) + { + row2 = zero; + mask2 = 0; + } + else + { + row2 = (uint8_t *)bits->bits + bits->ro
[Pixman] [PATCH] Rename all the fast paths with _8000 in their names to _8
From: Søren Sandmann Pedersen This inconsistent naming somehow survived the refactoring from a while back. --- pixman/pixman-arm-neon-asm.S | 22 +++--- pixman/pixman-arm-neon.c |4 ++-- pixman/pixman-arm-simd-asm.S |2 +- pixman/pixman-arm-simd.c | 16 pixman/pixman-fast-path.c| 28 ++-- pixman/pixman-mmx.c | 28 ++-- pixman/pixman-sse2.c | 30 +++--- test/lowlevel-blt-bench.c|6 +++--- 8 files changed, 68 insertions(+), 68 deletions(-) diff --git a/pixman/pixman-arm-neon-asm.S b/pixman/pixman-arm-neon-asm.S index 9f6568f..b854ab3 100644 --- a/pixman/pixman-arm-neon-asm.S +++ b/pixman/pixman-arm-neon-asm.S @@ -495,15 +495,15 @@ generate_composite_function \ /**/ -.macro pixman_composite_add_8000_8000_process_pixblock_head +.macro pixman_composite_add_8_8_process_pixblock_head vqadd.u8q14, q0, q2 vqadd.u8q15, q1, q3 .endm -.macro pixman_composite_add_8000_8000_process_pixblock_tail +.macro pixman_composite_add_8_8_process_pixblock_tail .endm -.macro pixman_composite_add_8000_8000_process_pixblock_tail_head +.macro pixman_composite_add_8_8_process_pixblock_tail_head vld1.8 {d0, d1, d2, d3}, [SRC]! PF add PF_X, PF_X, #32 PF tst PF_CTL, #0xF @@ -523,15 +523,15 @@ generate_composite_function \ .endm generate_composite_function \ -pixman_composite_add_8000_8000_asm_neon, 8, 0, 8, \ +pixman_composite_add_8_8_asm_neon, 8, 0, 8, \ FLAG_DST_READWRITE, \ 32, /* number of pixels, processed in a single block */ \ 10, /* prefetch distance */ \ default_init, \ default_cleanup, \ -pixman_composite_add_8000_8000_process_pixblock_head, \ -pixman_composite_add_8000_8000_process_pixblock_tail, \ -pixman_composite_add_8000_8000_process_pixblock_tail_head +pixman_composite_add_8_8_process_pixblock_head, \ +pixman_composite_add_8_8_process_pixblock_tail, \ +pixman_composite_add_8_8_process_pixblock_tail_head /**/ @@ -561,8 +561,8 @@ generate_composite_function \ 10, /* prefetch distance */ \ default_init, \ default_cleanup, \ -pixman_composite_add_8000_8000_process_pixblock_head, \ -pixman_composite_add_8000_8000_process_pixblock_tail, \ +pixman_composite_add_8_8_process_pixblock_head, \ +pixman_composite_add_8_8_process_pixblock_tail, \ pixman_composite_add___process_pixblock_tail_head generate_composite_function_single_scanline \ @@ -571,8 +571,8 @@ generate_composite_function_single_scanline \ 8, /* number of pixels, processed in a single block */ \ default_init, \ default_cleanup, \ -pixman_composite_add_8000_8000_process_pixblock_head, \ -pixman_composite_add_8000_8000_process_pixblock_tail, \ +pixman_composite_add_8_8_process_pixblock_head, \ +pixman_composite_add_8_8_process_pixblock_tail, \ pixman_composite_add___process_pixblock_tail_head /**/ diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c index ece6054..cdaa29a 100644 --- a/pixman/pixman-arm-neon.c +++ b/pixman/pixman-arm-neon.c @@ -52,7 +52,7 @@ PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0565_rev, uint8_t, 3, uint16_t, 1) PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_pixbuf_, uint32_t, 1, uint32_t, 1) -PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8000_8000, +PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8_8, uint8_t, 1, uint8_t, 1) PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add__, uint32_t, 1, uint32_t, 1) @@ -257,7 +257,7 @@ static const pixman_fast_path_t arm_neon_fast_paths[] = PIXMAN_STD_FAST_PATH (ADD, solid,a8, a8, neon_composite_add_n_8_8), PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add___), -PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8000_8000), +PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8_8), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add__), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add__), PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, neon_composite_over_reverse_n_), diff --git a/pixman/pixman-arm-simd-asm.S b/pixman/pixman-arm-simd-asm.S index 1a1a0d6..a3d2d40 100644 --- a
[Pixman] [PATCH 1/2] Fix bug in FAST_PATH_STD_FAST_PATH
From: Søren Sandmann Pedersen The standard fast paths deal with two kinds of images: solids and bits. These two image types require different flags, but PIXMAN_STD_FAST_PATH uses the same ones for both. This patch makes it so that solid images just get the standard flags, while bits images must be untransformed, and the destination clip contained within the sample grid. This means that old FAST_PATH_COVERS_CLIP flag is now not used anymore, so it can be deleted. --- pixman/pixman-image.c | 11 ++-- pixman/pixman-private.h | 55 +- pixman/pixman.c |4 +- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 8397f6a..9802d8c 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -363,24 +363,21 @@ compute_image_info (pixman_image_t *image) flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT| - FAST_PATH_NO_NORMAL_REPEAT | - FAST_PATH_COVERS_CLIP; + FAST_PATH_NO_NORMAL_REPEAT; break; case PIXMAN_REPEAT_PAD: flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT| - FAST_PATH_NO_NORMAL_REPEAT | - FAST_PATH_COVERS_CLIP; + FAST_PATH_NO_NORMAL_REPEAT; break; default: flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | - FAST_PATH_NO_NONE_REPEAT| - FAST_PATH_COVERS_CLIP; + FAST_PATH_NO_NONE_REPEAT; break; } @@ -400,8 +397,6 @@ compute_image_info (pixman_image_t *image) if (image->solid.color.alpha == 0x) flags |= FAST_PATH_IS_OPAQUE; - - flags |= FAST_PATH_COVERS_CLIP; break; case BITS: diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d85868f..59d9c5d 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -554,9 +554,9 @@ _pixman_choose_implementation (void); #define FAST_PATH_NO_PAD_REPEAT(1 << 3) #define FAST_PATH_NO_REFLECT_REPEAT(1 << 4) #define FAST_PATH_NO_ACCESSORS (1 << 5) -#define FAST_PATH_NARROW_FORMAT(1 << 6) -#define FAST_PATH_COVERS_CLIP (1 << 7) +#define FAST_PATH_NARROW_FORMAT(1 << 6) #define FAST_PATH_COMPONENT_ALPHA (1 << 8) +#define FAST_PATH_SAMPLES_OPAQUE (1 << 7) #define FAST_PATH_UNIFIED_ALPHA(1 << 9) #define FAST_PATH_SCALE_TRANSFORM (1 << 10) #define FAST_PATH_NEAREST_FILTER (1 << 11) @@ -571,7 +571,6 @@ _pixman_choose_implementation (void); #define FAST_PATH_BILINEAR_FILTER (1 << 20) #define FAST_PATH_NO_NORMAL_REPEAT (1 << 21) #define FAST_PATH_HAS_TRANSFORM(1 << 22) -#define FAST_PATH_SAMPLES_OPAQUE (1 << 23) #define FAST_PATH_PAD_REPEAT \ (FAST_PATH_NO_NONE_REPEAT | \ @@ -593,29 +592,25 @@ _pixman_choose_implementation (void); FAST_PATH_NO_NORMAL_REPEAT| \ FAST_PATH_NO_PAD_REPEAT) -#define _FAST_PATH_STANDARD_FLAGS \ -(FAST_PATH_ID_TRANSFORM| \ - FAST_PATH_NO_ALPHA_MAP| \ - FAST_PATH_NO_CONVOLUTION_FILTER | \ - FAST_PATH_NO_PAD_REPEAT | \ - FAST_PATH_NO_REFLECT_REPEAT | \ +#define FAST_PATH_STANDARD_FLAGS \ +(FAST_PATH_NO_CONVOLUTION_FILTER | \ FAST_PATH_NO_ACCESSORS| \ - FAST_PATH_NARROW_FORMAT | \ - FAST_PATH_COVERS_CLIP) - -#define FAST_PATH_STD_SRC_FLAGS \ -_FAST_PATH_STANDARD_FLAGS -#define FAST_PATH_STD_MASK_U_FLAGS \ -(_FAST_PATH_STANDARD_FLAGS | \ - FAST_PATH_UNIFIED_ALPHA) -#define FAST_PATH_STD_MASK_CA_FLAGS\ -(_FAST_PATH_STANDARD_FLAGS | \ - FAST_PATH_COMPONENT_ALPHA) + FAST_PATH_NO_ALPHA_MAP| \ + FAST_PATH_NARROW_FORMAT) + #define FAST_PATH_STD_DEST_FLAGS \ (FAS
[Pixman] [PATCH 2/2] Delete simple repeat code
From: Søren Sandmann Pedersen This was supposedly an optimization, but it has pathological cases where it definitely isn't. For example it has terrible memory access patterns when called with a 1 x n image. With small images in general, it will do lots and lots of modulus operations. Since no one has ever measure whether it actually is an improvement, and since it is doing the repeating at the wrong the stage in the pipeline, just delete it. --- pixman/pixman-image.c |6 -- pixman/pixman-private.h |3 +- pixman/pixman.c | 148 ++ 3 files changed, 21 insertions(+), 136 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 9802d8c..7a9c423 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -409,12 +409,6 @@ compute_image_info (pixman_image_t *image) else { code = image->bits.format; - - if (!image->common.transform && - image->common.repeat == PIXMAN_REPEAT_NORMAL) - { - flags |= FAST_PATH_SIMPLE_REPEAT; - } } if (!PIXMAN_FORMAT_A (image->bits.format) && diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 59d9c5d..3979f60 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -560,7 +560,7 @@ _pixman_choose_implementation (void); #define FAST_PATH_UNIFIED_ALPHA(1 << 9) #define FAST_PATH_SCALE_TRANSFORM (1 << 10) #define FAST_PATH_NEAREST_FILTER (1 << 11) -#define FAST_PATH_SIMPLE_REPEAT(1 << 12) +#define FAST_PATH_HAS_TRANSFORM(1 << 12) #define FAST_PATH_IS_OPAQUE(1 << 13) #define FAST_PATH_NEEDS_WORKAROUND (1 << 14) #define FAST_PATH_NO_NONE_REPEAT (1 << 15) @@ -570,7 +570,6 @@ _pixman_choose_implementation (void); #define FAST_PATH_Y_UNIT_ZERO (1 << 19) #define FAST_PATH_BILINEAR_FILTER (1 << 20) #define FAST_PATH_NO_NORMAL_REPEAT (1 << 21) -#define FAST_PATH_HAS_TRANSFORM(1 << 22) #define FAST_PATH_PAD_REPEAT \ (FAST_PATH_NO_NONE_REPEAT | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index 15e7fbf..3a62b2d 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -377,126 +377,6 @@ pixman_compute_composite_region32 (pixman_region32_t * region, return TRUE; } -static void -walk_region_internal (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height, - pixman_bool_tsrc_repeat, - pixman_bool_tmask_repeat, - pixman_region32_t * region, - pixman_composite_func_t composite_rect) -{ -int w, h, w_this, h_this; -int x_msk, y_msk, x_src, y_src, x_dst, y_dst; -int src_dy = src_y - dest_y; -int src_dx = src_x - dest_x; -int mask_dy = mask_y - dest_y; -int mask_dx = mask_x - dest_x; -const pixman_box32_t *pbox; -int n; - -pbox = pixman_region32_rectangles (region, &n); - -/* Fast path for non-repeating sources */ -if (!src_repeat && !mask_repeat) -{ - while (n--) - { - (*composite_rect) (imp, op, - src_image, mask_image, dst_image, - pbox->x1 + src_dx, - pbox->y1 + src_dy, - pbox->x1 + mask_dx, - pbox->y1 + mask_dy, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - - pbox++; - } - - return; -} - -while (n--) -{ - h = pbox->y2 - pbox->y1; - y_src = pbox->y1 + src_dy; - y_msk = pbox->y1 + mask_dy; - y_dst = pbox->y1; - - while (h) - { - h_this = h; - w
[Pixman] [PATCH] Remove broken optimizations in combine_disjoint_over_u()
From: Søren Sandmann Pedersen The first broken optimization is that it checks "a != 0x00" where it should check "s != 0x00". The other is that it skips the computation when alpha is 0xff. That is wrong because in the formula: min (1, (1 - Aa)/Ab) the render specification states that if Ab is 0, the quotient is defined to positive infinity. That is the case even if (1 - Aa) is 0. --- pixman/pixman-combine.c.template | 14 +- test/blitters-test.c |2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template index c129980..0d3b95d 100644 --- a/pixman/pixman-combine.c.template +++ b/pixman/pixman-combine.c.template @@ -1296,17 +1296,13 @@ combine_disjoint_over_u (pixman_implementation_t *imp, comp4_t s = combine_mask (src, mask, i); comp2_t a = s >> A_SHIFT; - if (a != 0x00) + if (s != 0x00) { - if (a != MASK) - { - comp4_t d = *(dest + i); - a = combine_disjoint_out_part (d >> A_SHIFT, a); - UNcx4_MUL_UNc_ADD_UNcx4 (d, a, s); - s = d; - } + comp4_t d = *(dest + i); + a = combine_disjoint_out_part (d >> A_SHIFT, a); + UNcx4_MUL_UNc_ADD_UNcx4 (d, a, s); - *(dest + i) = s; + *(dest + i) = d; } } } diff --git a/test/blitters-test.c b/test/blitters-test.c index 7ba80eb..77a26dd 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -465,6 +465,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 200, - 0x217CF14A, + 0x1DB8BDF8, test_composite, argc, argv); } -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add no-op combiners for DST and the CA versions of the HSL operators.
From: Søren Sandmann Pedersen We already exit early for DST, but for the HSL operators with component alpha, we crash at the moment. Fix that by adding a dummy combine_dst() function. --- pixman/pixman-combine.c.template | 31 +-- 1 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template index 0d3b95d..56dfb43 100644 --- a/pixman/pixman-combine.c.template +++ b/pixman/pixman-combine.c.template @@ -133,6 +133,17 @@ combine_clear (pixman_implementation_t *imp, } static void +combine_dst (pixman_implementation_t *imp, +pixman_op_t op, +comp4_t *dest, +const comp4_t * src, +const comp4_t * mask, +int width) +{ +return; +} + +static void combine_src_u (pixman_implementation_t *imp, pixman_op_t op, comp4_t *dest, @@ -2310,7 +2321,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) /* Unified alpha */ imp->combine_width[PIXMAN_OP_CLEAR] = combine_clear; imp->combine_width[PIXMAN_OP_SRC] = combine_src_u; -/* dest */ +imp->combine_width[PIXMAN_OP_DST] = combine_dst; imp->combine_width[PIXMAN_OP_OVER] = combine_over_u; imp->combine_width[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u; imp->combine_width[PIXMAN_OP_IN] = combine_in_u; @@ -2326,7 +2337,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) /* Disjoint, unified */ imp->combine_width[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear; imp->combine_width[PIXMAN_OP_DISJOINT_SRC] = combine_src_u; -/* dest */ +imp->combine_width[PIXMAN_OP_DISJOINT_DST] = combine_dst; imp->combine_width[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u; imp->combine_width[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u; imp->combine_width[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u; @@ -2340,7 +2351,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) /* Conjoint, unified */ imp->combine_width[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear; imp->combine_width[PIXMAN_OP_CONJOINT_SRC] = combine_src_u; -/* dest */ +imp->combine_width[PIXMAN_OP_CONJOINT_DST] = combine_dst; imp->combine_width[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u; imp->combine_width[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u; imp->combine_width[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u; @@ -2386,7 +2397,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) /* Disjoint CA */ imp->combine_width_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca; imp->combine_width_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca; -/* dest */ +imp->combine_width_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst; imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca; imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca; imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca; @@ -2400,7 +2411,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) /* Conjoint CA */ imp->combine_width_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca; imp->combine_width_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca; -/* dest */ +imp->combine_width_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst; imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca; imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca; imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca; @@ -2423,10 +2434,10 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp) imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca; imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca; -/* It is not clear that these make sense, so leave them out for now */ -imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = NULL; -imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = NULL; -imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = NULL; -imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = NULL; +/* It is not clear that these make sense, so make them noops for now */ +imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = combine_dst; +imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst; +imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = combine_dst; +imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst; } -- 1.7.1.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Plug leak in the alphamap test.
From: Søren Sandmann Pedersen The images are being created with non-NULL data, so we have to free it outselves. This is important because the Cygwin tinderbox is running out of memory and produces this: mmap failed on 2 1507328 mmap failed on 4 1507328 mmap failed on 2 1507328 mmap failed on 4 1507328 mmap failed on 4 1507328 mmap failed on 4 1507328 http://tinderbox.x.org/builds/2010-10-05-0014/logs/pixman/#check --- test/alphamap.c | 14 +- 1 files changed, 13 insertions(+), 1 deletions(-) diff --git a/test/alphamap.c b/test/alphamap.c index 09de387..498fdab 100644 --- a/test/alphamap.c +++ b/test/alphamap.c @@ -45,15 +45,27 @@ format_name (pixman_format_code_t format) return ""; } +static void +on_destroy (pixman_image_t *image, void *data) +{ +uint32_t *bits = pixman_image_get_data (image); + +fence_free (bits); +} + static pixman_image_t * make_image (pixman_format_code_t format) { uint32_t *bits; uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8; +pixman_image_t *image; bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp); -return pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp); +image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp); + +if (image && bits) + pixman_image_set_destroy_function (image, on_destroy, NULL); } static pixman_image_t * -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Remove workaround for a bug in the 1.6 X server.
From: Søren Sandmann Pedersen There used to be a bug in the X server where it would rely on out-of-bounds accesses when it was asked to composite with a window as the source. It would create a pixman image pointing to some bogus position in memory, but then set a clip region to the position where the actual bits were. Due to a bug in old versions of pixman, where it would not clip against the image bounds when a clip region was set, this would actually work. So when the pixman bug was fixed, a workaround was added to allow certain out-of-bound accesses. This function disabled those workarounds. However, the 1.6 X server is so old now that we can remove this workaround. This does mean that if you update pixman to 0.22 or later, you will need to use a 1.7 X server or later. --- pixman/pixman-image.c | 56 pixman/pixman-private.h |3 +- pixman/pixman.c | 75 pixman/pixman.h | 22 -- test/Makefile.am|2 - test/window-test.c | 173 --- 6 files changed, 28 insertions(+), 303 deletions(-) delete mode 100644 test/window-test.c diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index fabcd63..aa988a8 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -238,54 +238,27 @@ _pixman_image_reset_clip_region (pixman_image_t *image) image->common.have_clip_region = FALSE; } -static pixman_bool_t out_of_bounds_workaround = TRUE; - -/* Old X servers rely on out-of-bounds accesses when they are asked - * to composite with a window as the source. They create a pixman image - * pointing to some bogus position in memory, but then they set a clip - * region to the position where the actual bits are. +/* Executive Summary: This function is a no-op that only exists + * for historical reasons. + * + * There used to be a bug in the X server where it would rely on + * out-of-bounds accesses when it was asked to composite with a + * window as the source. It would create a pixman image pointing + * to some bogus position in memory, but then set a clip region + * to the position where the actual bits were. * * Due to a bug in old versions of pixman, where it would not clip * against the image bounds when a clip region was set, this would - * actually work. So by default we allow certain out-of-bound access - * to happen unless explicitly disabled. + * actually work. So when the pixman bug was fixed, a workaround was + * added to allow certain out-of-bound accesses. This function disabled + * those workarounds. * - * Fixed X servers should call this function to disable the workaround. + * Since 0.21.2 pixman doen't do these workaround anymore, so now this + * function is a no-op. */ PIXMAN_EXPORT void pixman_disable_out_of_bounds_workaround (void) { -out_of_bounds_workaround = FALSE; -} - -static pixman_bool_t -source_image_needs_out_of_bounds_workaround (bits_image_t *image) -{ -if (image->common.clip_sources && -image->common.repeat == PIXMAN_REPEAT_NONE && - image->common.have_clip_region && -out_of_bounds_workaround) -{ - if (!image->common.client_clip) - { - /* There is no client clip, so if the clip region extends beyond the -* drawable geometry, it must be because the X server generated the -* bogus clip region. -*/ - const pixman_box32_t *extents = - pixman_region32_extents (&image->common.clip_region); - - if (extents->x1 >= 0 && extents->x2 <= image->width && - extents->y1 >= 0 && extents->y2 <= image->height) - { - return FALSE; - } - } - - return TRUE; -} - -return FALSE; } static void @@ -420,9 +393,6 @@ compute_image_info (pixman_image_t *image) flags |= FAST_PATH_IS_OPAQUE; } - if (source_image_needs_out_of_bounds_workaround (&image->bits)) - flags |= FAST_PATH_NEEDS_WORKAROUND; - if (image->bits.read_func || image->bits.write_func) flags &= ~FAST_PATH_NO_ACCESSORS; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index c43172b..497c3fb 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -561,14 +561,13 @@ _pixman_choose_implementation (void); #define FAST_PATH_NEAREST_FILTER (1 << 11) #define FAST_PATH_HAS_TRANSFORM(1 << 12) #define FAST_PATH_IS_OPAQUE(1 << 13) -#define FAST_PATH_NEEDS_WORKAROUND (1 << 14) +#define FAST_PATH_NO_NORMAL_REPEAT (1 << 14) #define FAST_PATH_NO_NONE_REPEAT (1 << 15) #define FAST_PATH_SAMPLES_COVER_CLIP (1 << 16) #
[Pixman] [PATCH] [mmx] Mark some of the output variables as earlyclobber.
From: Søren Sandmann Pedersen GCC assumes that input variables in inline assembly are fully consumed before any output variable is written. This means it may allocate the variables in the same register unless the output variables are marked as early-clobber. From Jeremy Huddleston: I noticed a problem building pixman with clang and reported it to the clang developers. They responded back with a comment about the inline asm in pixman-mmx.c and suggested a fix: """ Incidentally, Jeremy, in the asm that reads __asm__ ( "movq %7, %0\n" "movq %7, %1\n" "movq %7, %2\n" "movq %7, %3\n" "movq %7, %4\n" "movq %7, %5\n" "movq %7, %6\n" : "=y" (v1), "=y" (v2), "=y" (v3), "=y" (v4), "=y" (v5), "=y" (v6), "=y" (v7) : "y" (vfill)); all the output operands except the last one should be marked as earlyclobber ("=&y"). This is working by accident with gcc. """ Cc: jerem...@apple.com --- pixman/pixman-mmx.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index e936c4c..34637a4 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -1921,8 +1921,8 @@ pixman_fill_mmx (uint32_t *bits, "movq %7, %4\n" "movq %7, %5\n" "movq %7, %6\n" - : "=y" (v1), "=y" (v2), "=y" (v3), - "=y" (v4), "=y" (v5), "=y" (v6), "=y" (v7) + : "=&y" (v1), "=&y" (v2), "=&y" (v3), + "=&y" (v4), "=&y" (v5), "=&y" (v6), "=y" (v7) : "y" (vfill)); #endif -- 1.7.3.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Delete the source_image_t struct.
From: Søren Sandmann Pedersen It serves no purpose anymore now that the source_class_t field is gone. --- pixman/pixman-conical-gradient.c | 17 - pixman/pixman-linear-gradient.c | 30 ++ pixman/pixman-private.h | 11 ++- pixman/pixman-radial-gradient.c | 19 +-- 4 files changed, 33 insertions(+), 44 deletions(-) diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c index 897948b..a3685d1 100644 --- a/pixman/pixman-conical-gradient.c +++ b/pixman/pixman-conical-gradient.c @@ -58,8 +58,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, uint32_t * buffer, const uint32_t *mask) { -source_image_t *source = (source_image_t *)image; -gradient_t *gradient = (gradient_t *)source; +gradient_t *gradient = (gradient_t *)image; conical_gradient_t *conical = (conical_gradient_t *)image; uint32_t *end = buffer + width; pixman_gradient_walker_t walker; @@ -71,9 +70,9 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, double ry = y + 0.5; double rz = 1.; -_pixman_gradient_walker_init (&walker, gradient, source->common.repeat); +_pixman_gradient_walker_init (&walker, gradient, image->common.repeat); -if (source->common.transform) +if (image->common.transform) { pixman_vector_t v; @@ -82,19 +81,19 @@ conical_gradient_get_scanline_32 (pixman_image_t *image, v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; v.vector[2] = pixman_fixed_1; - if (!pixman_transform_point_3d (source->common.transform, &v)) + if (!pixman_transform_point_3d (image->common.transform, &v)) return; - cx = source->common.transform->matrix[0][0] / 65536.; - cy = source->common.transform->matrix[1][0] / 65536.; - cz = source->common.transform->matrix[2][0] / 65536.; + cx = image->common.transform->matrix[0][0] / 65536.; + cy = image->common.transform->matrix[1][0] / 65536.; + cz = image->common.transform->matrix[2][0] / 65536.; rx = v.vector[0] / 65536.; ry = v.vector[1] / 65536.; rz = v.vector[2] / 65536.; affine = - source->common.transform->matrix[2][0] == 0 && + image->common.transform->matrix[2][0] == 0 && v.vector[2] == pixman_fixed_1; } diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c index b048e7b..1547882 100644 --- a/pixman/pixman-linear-gradient.c +++ b/pixman/pixman-linear-gradient.c @@ -38,7 +38,6 @@ linear_gradient_classify (pixman_image_t *image, int width, int height) { -source_image_t *source = (source_image_t *)image; linear_gradient_t *linear = (linear_gradient_t *)image; pixman_vector_t v; pixman_fixed_32_32_t l; @@ -48,19 +47,19 @@ linear_gradient_classify (pixman_image_t *image, class = SOURCE_IMAGE_CLASS_UNKNOWN; -if (source->common.transform) +if (image->common.transform) { /* projective transformation */ - if (source->common.transform->matrix[2][0] != 0 || - source->common.transform->matrix[2][1] != 0 || - source->common.transform->matrix[2][2] == 0) + if (image->common.transform->matrix[2][0] != 0 || + image->common.transform->matrix[2][1] != 0 || + image->common.transform->matrix[2][2] == 0) { return class; } - v.vector[0] = source->common.transform->matrix[0][1]; - v.vector[1] = source->common.transform->matrix[1][1]; - v.vector[2] = source->common.transform->matrix[2][2]; + v.vector[0] = image->common.transform->matrix[0][1]; + v.vector[1] = image->common.transform->matrix[1][1]; + v.vector[2] = image->common.transform->matrix[2][2]; } else { @@ -104,26 +103,25 @@ linear_gradient_get_scanline_32 (pixman_image_t *image, pixman_fixed_32_32_t l; pixman_fixed_48_16_t dx, dy; gradient_t *gradient = (gradient_t *)image; -source_image_t *source = (source_image_t *)image; linear_gradient_t *linear = (linear_gradient_t *)image; uint32_t *end = buffer + width; pixman_gradient_walker_t walker; -_pixman_gradient_walker_init (&walker, gradient, source->common.repeat); +_pixman_gradient_walker_init (&walker, gradient, image->common.repeat); /* reference point is the center of the pixel */ v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; v.vector[2] = pixman_fixed_1; -
[Pixman] [PATCH] Generate {a, x}8r8g8b8, a8, 565 fetchers for nearest/affine images
From: Søren Sandmann Pedersen There are versions for all combinations of x8r8g8b8/a8r8g8b8 and pad/repeat/none/normal repeat modes. The bulk of each function is an inline function that takes a format and a repeat mode as parameters. --- pixman/pixman-bits-image.c | 177 +++ 1 files changed, 144 insertions(+), 33 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 2e83c82..ff2dde3 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -907,6 +907,77 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image, } } +static force_inline void +bits_image_fetch_nearest_affine (pixman_image_t * image, +int offset, +int line, +int width, +uint32_t * buffer, +const uint32_t * mask, + +convert_pixel_tconvert_pixel, +pixman_format_code_t format, +pixman_repeat_trepeat_mode) +{ +pixman_fixed_t x, y; +pixman_fixed_t ux, uy; +pixman_vector_t v; +bits_image_t *bits = &image->bits; +int i; + +/* reference point is the center of the pixel */ +v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; +v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; +v.vector[2] = pixman_fixed_1; + +if (!pixman_transform_point_3d (image->common.transform, &v)) + return; + +ux = image->common.transform->matrix[0][0]; +uy = image->common.transform->matrix[1][0]; + +x = v.vector[0]; +y = v.vector[1]; + +for (i = 0; i < width; ++i) +{ + int width, height, x0, y0; + const uint8_t *row; + + if (mask && !mask[i]) + goto next; + + width = image->bits.width; + height = image->bits.height; + x0 = pixman_fixed_to_int (x - pixman_fixed_e); + y0 = pixman_fixed_to_int (y - pixman_fixed_e); + + if (repeat_mode == PIXMAN_REPEAT_NONE && + (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width)) + { + buffer[i] = 0; + } + else + { + uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff00; + + if (repeat_mode != PIXMAN_REPEAT_NONE) + { + repeat (repeat_mode, width, &x0); + repeat (repeat_mode, height, &y0); + } + + row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0; + + buffer[i] = convert_pixel (row, x0) | mask; + } + +next: + x += ux; + y += uy; +} +} + static force_inline uint32_t convert_a8r8g8b8 (const uint8_t *row, int x) { @@ -940,29 +1011,51 @@ convert_r5g6b5 (const uint8_t *row, int x) uint32_t * buffer, \ const uint32_t * mask) \ { \ - bits_image_fetch_bilinear_affine (image, offset, line, width, buffer, mask, \ + bits_image_fetch_bilinear_affine (image, offset, line, \ + width, buffer, mask, \ convert_ ## format, \ PIXMAN_ ## format,\ repeat_mode); \ } \ extern int no_such_variable -MAKE_BILINEAR_FETCHER (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD); -MAKE_BILINEAR_FETCHER (none_a8r8g8b8,a8r8g8b8, PIXMAN_REPEAT_NONE); -MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT); -MAKE_BILINEAR_FETCHER (normal_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NORMAL); -MAKE_BILINEAR_FETCHER (pad_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_PAD); -MAKE_BILINEAR_FETCHER (none_x8r8g8b8,x8r8g8b8, PIXMAN_REPEAT_NONE); -MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT); -MAKE_BILINEAR_FETCHER (normal_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_NORMAL); -MAKE_BILINEAR_FETCHER (pad_a8, a8, PIXMAN_REPEAT_PAD); -MAKE_BILINEAR_FETCHER (none_a8, a8, PIXMAN_REPEAT_NONE); -MAKE_BILINEAR_FETCHER (reflect_a8, a8, PIXMAN_REPEAT_REFLECT); -MAKE_BILINEAR_FETCHER (normal_a8, a8, PIXMAN_REPEAT_NORMAL); -MAKE_BILINEAR_FETCHER (pad_r5g6b5, r5g6b5, PIXMAN_REPEAT_PAD); -MAKE_BILINEAR_FETCHER (none_r5g6b5, r5g6b5, PIXMAN_REPEAT_NONE); -MAKE_BILINEAR_FETCHER (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT); -MAKE_BILINEAR_FETCHER (normal_r5g6b5,r5g6b5, P
[Pixman] [PATCH] Add support for AltiVec detection for OpenBSD/PowerPC.
From: Brad Smith Bug 29331. --- pixman/pixman-cpu.c | 25 - 1 files changed, 24 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c index e96b140..1b31885 100644 --- a/pixman/pixman-cpu.c +++ b/pixman/pixman-cpu.c @@ -61,6 +61,29 @@ pixman_have_vmx (void) return have_vmx; } +#elif defined (__OpenBSD__) +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ +if (!initialized) +{ + int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; + size_t length = sizeof(have_vmx); + int error = + sysctl (&mib, 2, &have_vmx, &length, NULL, 0); + + if (error) + have_vmx = FALSE; + + initialized = TRUE; +} +return have_vmx; +} + #elif defined (__linux__) #include #include @@ -123,7 +146,7 @@ pixman_have_vmx (void) return have_vmx; } -#else /* !__APPLE__ && !__linux__ */ +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ #include #include -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] pixman_image_set_alpha_map(): Disallow alpha map cycles
From: Søren Sandmann Pedersen If someone tries to set an alpha map that itself has an alpha map, simply return. Also, if someone tries to add an alpha map to an image that is being _used_ as an alpha map, simply return. This ensures that an alpha map can never have an alpha map. --- pixman/pixman-image.c | 30 +++--- pixman/pixman-private.h |1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 269c3c1..0b8bb3c 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -101,6 +101,7 @@ _pixman_image_allocate (void) pixman_region32_init (&common->clip_region); + common->alpha_count = 0; common->have_clip_region = FALSE; common->clip_sources = FALSE; common->transform = NULL; @@ -195,9 +196,6 @@ pixman_image_unref (pixman_image_t *image) if (common->filter_params) free (common->filter_params); - if (common->alpha_map) - pixman_image_unref ((pixman_image_t *)common->alpha_map); - if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL) @@ -668,15 +666,41 @@ pixman_image_set_alpha_map (pixman_image_t *image, return_if_fail (!alpha_map || alpha_map->type == BITS); +if (alpha_map && common->alpha_count > 0) +{ + /* If this image is being used as an alpha map itself, +* then you can't give it an alpha map of its own. +*/ + return; +} + +if (alpha_map && alpha_map->common.alpha_map) +{ + /* If the image has an alpha map of its own, +* then it can't be used as an alpha map itself +*/ + return; +} + if (common->alpha_map != (bits_image_t *)alpha_map) { if (common->alpha_map) + { + common->alpha_map->common.alpha_count--; + pixman_image_unref ((pixman_image_t *)common->alpha_map); + } if (alpha_map) + { common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map); + + common->alpha_map->common.alpha_count++; + } else + { common->alpha_map = NULL; + } } common->alpha_origin_x = x; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 0629c42..c4e6bb8 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -80,6 +80,7 @@ struct image_common image_type_ttype; int32_t ref_count; pixman_region32_t clip_region; +int32_talpha_count;/* How many times this image is being used as an alpha map */ pixman_bool_t have_clip_region; /* FALSE if there is no clip */ pixman_bool_t client_clip;/* Whether the source clip was set by a client */ -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] Some test suite improvements
Here is a set of patches that contain some updates to the test suite. Specifically, - gradient-crash-test is extended to test more scenarios - floating point exceptions are enabled in some cases - The argument to fence_malloc() becomes a signed integer, and it will abort() if someone tries to malloc a negative size. - A new stress-test program that tries to use various combinations of unusual features. The hope is that this will provoke crashes or irregular behavior. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add alpha-loop test program
From: Søren Sandmann Pedersen This tests what happens if you attempt to make an image with an alpha map that has the image as its alpha map. This results in an infinite loop in _pixman_image_validate(), so the test sets up a SIGALRM to exit if it runs for more than five seconds. --- configure.ac | 12 +++- test/Makefile.am |4 test/alpha-loop.c | 29 + test/utils.c | 33 + test/utils.h |3 +++ 5 files changed, 80 insertions(+), 1 deletions(-) create mode 100644 test/alpha-loop.c diff --git a/configure.ac b/configure.ac index 98c2783..acec8a1 100644 --- a/configure.ac +++ b/configure.ac @@ -600,13 +600,23 @@ AC_SUBST(DEP_CFLAGS) AC_SUBST(DEP_LIBS) dnl = -dnl posix_memalign +dnl posix_memalign, sigaction, alarm AC_CHECK_FUNC(posix_memalign, have_posix_memalign=yes, have_posix_memalign=no) if test x$have_posix_memalign = xyes; then AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, [Whether we have posix_memalign()]) fi +AC_CHECK_FUNC(sigaction, have_sigaction=yes, have_sigaction=no) +if test x$have_sigaction = xyes; then + AC_DEFINE(HAVE_SIGACTION, 1, [Whether we have sigaction()]) +fi + +AC_CHECK_FUNC(alarm, have_alarm=yes, have_alarm=no) +if test x$have_alarm = xyes; then + AC_DEFINE(HAVE_ALARM, 1, [Whether we have alarm()]) +fi + dnl = dnl Thread local storage diff --git a/test/Makefile.am b/test/Makefile.am index 2a7aea2..5273bec 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ TESTPROGRAMS =\ gradient-crash-test \ trap-crasher\ alphamap\ + alpha-loop \ scaling-crash-test \ blitters-test \ scaling-test\ @@ -39,6 +40,9 @@ scaling_test_SOURCES = scaling-test.c utils.c utils.h alphamap_LDADD = $(TEST_LDADD) alphamap_SOURCES = alphamap.c utils.c utils.h +alpha_loop_LDADD = $(TEST_LDADD) +alpha_loop_SOURCES = alpha-loop.c utils.c utils.h + # GTK using test programs if HAVE_GTK diff --git a/test/alpha-loop.c b/test/alpha-loop.c new file mode 100644 index 000..e4d90a9 --- /dev/null +++ b/test/alpha-loop.c @@ -0,0 +1,29 @@ +#include +#include +#include "utils.h" + +#define WIDTH 400 +#define HEIGHT 200 + +int +main (int argc, char **argv) +{ +uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); +uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); +uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); + +pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); +pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); +pixman_image_t *s = pixman_image_create_bits (PIXMAN_a2r10g10b10, WIDTH, HEIGHT, src, WIDTH * 4); + +fail_after (5, "Infinite loop detected: 5 seconds without progress\n"); + +pixman_image_set_alpha_map (s, a, 0, 0); +pixman_image_set_alpha_map (a, s, 0, 0); + +pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + +pixman_image_unref (s); + +return 0; +} diff --git a/test/utils.c b/test/utils.c index 1ee5c9c..d95cbc2 100644 --- a/test/utils.c +++ b/test/utils.c @@ -1,4 +1,9 @@ #include "utils.h" +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /* Random number seed */ @@ -319,3 +324,31 @@ fuzzer_test_main (const char *test_name, return 0; } + +static const char *global_msg; + +static void +on_alarm (int signo) +{ +printf ("%s\n", global_msg); +exit (1); +} + +void +fail_after (int seconds, const char *msg) +{ +#ifdef HAVE_SIGACTION +#ifdef HAVE_ALARM +struct sigaction action; + +global_msg = msg; + +memset (&action, 0, sizeof (action)); +action.sa_handler = on_alarm; + +alarm (seconds); + +sigaction (SIGALRM, &action, NULL); +#endif +#endif +} diff --git a/test/utils.h b/test/utils.h index 95d809a..bfb76a5 100644 --- a/test/utils.h +++ b/test/utils.h @@ -62,3 +62,6 @@ fuzzer_test_main (const char *test_name, uint32_t(*test_function)(int testnum, int verbose), int argc, const char *argv[]); + +void +fail_after (int seconds, const char *msg); -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Store a2b2g2r2 pixel through the WRITE macro
From: Søren Sandmann Pedersen Otherwise, accessor functions won't work. --- pixman/pixman-access.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 56de711..f1ce0ba 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2425,11 +2425,11 @@ store_scanline_a2b2g2r2 (bits_image_t * image, { SPLIT_A (values[i]); - *(pixel++) = - ((a ) & 0xc0) | - ((b >> 2) & 0x30) | - ((g >> 4) & 0x0c) | - ((r >> 6) ); + WRITE (image, pixel++, + ((a ) & 0xc0) | + ((b >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((r >> 6) )); } } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] test: Make composite test use some existing macros instead of defining its own
From: Søren Sandmann Pedersen Also move the ARRAY_LENGTH macro into utils.h so it can be used elsewhere. --- test/composite.c | 56 + test/utils.h |2 + 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/test/composite.c b/test/composite.c index 5cdc521..e14f954 100644 --- a/test/composite.c +++ b/test/composite.c @@ -31,10 +31,6 @@ #include #include "utils.h" -#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0]))) -#define min(a,b) ((a) <= (b) ? (a) : (b)) -#define max(a,b) ((a) >= (b) ? (a) : (b)) - typedef struct color_t color_t; typedef struct format_t format_t; typedef struct image_t image_t; @@ -211,7 +207,7 @@ static const operator_t operators[] = 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) +#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) double Fa, Fb; @@ -267,150 +263,150 @@ calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) if (srca == 0.0) Fa = 1.0; else - Fa = min (1.0, (1.0 - dsta) / srca); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + Fa = MIN (1.0, (1.0 - dsta) / srca); if (dsta == 0.0) Fb = 1.0; else - Fb = min (1.0, (1.0 - srca) / dsta); + 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); + 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); + 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); + 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); + 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); + Fa = MAX (0.0, 1.0 - dsta / srca); return mult_chan (src, dst, Fa, 0
[Pixman] [PATCH] Add enable_fp_exceptions() function in utils.[ch]
From: Søren Sandmann Pedersen This function enables floating point traps if possible. --- configure.ac |8 test/utils.c | 26 ++ test/utils.h |3 +++ 3 files changed, 37 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 147e1bf..2570c84 100644 --- a/configure.ac +++ b/configure.ac @@ -639,6 +639,14 @@ if test x$have_getpagesize = xyes; then AC_DEFINE(HAVE_GETPAGESIZE, 1, [Whether we have getpagesize()]) fi +AC_CHECK_HEADER([fenv.h], + [AC_DEFINE(HAVE_FENV_H, [1], [Define to 1 if we have ])]) + +AC_CHECK_LIB(m, feenableexcept, have_feenableexcept=yes, have_feenableexcept=no) +if test x$have_feenableexcept = xyes; then + AC_DEFINE(HAVE_FEENABLEEXCEPT, 1, [Whether we have feenableexcept()]) +fi + AC_CHECK_FUNC(gettimeofday, have_gettimeofday=yes, have_gettimeofday=no) AC_CHECK_HEADER(sys/time.h, have_sys_time_h=yes, have_sys_time_h=no) if test x$have_gettimeofday = xyes && test x$have_sys_time_h = xyes; then diff --git a/test/utils.c b/test/utils.c index f6278fe..a7c55f6 100644 --- a/test/utils.c +++ b/test/utils.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE + #include "utils.h" #include @@ -15,6 +17,10 @@ #include #endif +#ifdef HAVE_FENV_H +#include +#endif + /* Random number seed */ @@ -469,6 +475,26 @@ fail_after (int seconds, const char *msg) #endif } +void +enable_fp_exceptions (void) +{ +#ifdef HAVE_FENV_H +#ifdef HAVE_FEENABLEEXCEPT +/* Note: we don't enable the FE_INEXACT trap because + * that happens quite commonly. It is possible that + * over- and underflow should similarly be considered + * okay, but for now the test suite passes with them + * enabled, and it's useful to know if they start + * occuring. + */ +feenableexcept (FE_DIVBYZERO | + FE_INVALID | + FE_OVERFLOW | + FE_UNDERFLOW); +#endif +#endif +} + void * aligned_malloc (size_t align, size_t size) { diff --git a/test/utils.h b/test/utils.h index 2ea4170..bac2916 100644 --- a/test/utils.h +++ b/test/utils.h @@ -82,6 +82,9 @@ fuzzer_test_main (const char *test_name, void fail_after (int seconds, const char *msg); +/* If possible, enable traps for floating point exceptions */ +void enable_fp_exceptions(void); + /* A pair of macros which can help to detect corruption of * floating point registers after a function call. This may * happen if _mm_empty() call is forgotten in MMX/SSE2 fast -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] When pixman_compute_composite_region32() return FALSE, don't fini the region.
From: Søren Sandmann Pedersen The rule is that the region passed in must be initialized and that the region returned will still be valid. Ie., the lifecycle is the responsibility of the caller, regardless of what the function returns. Previously, composite_region32() would finalize the region and then return FALSE, and then the caller would finalize the region again, leading to memory corruption in some cases. --- pixman/pixman.c | 14 +- 1 files changed, 1 insertions(+), 13 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 402c72c..62b58b8 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -302,17 +302,13 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (region->extents.x1 >= region->extents.x2 || region->extents.y1 >= region->extents.y2) { - pixman_region32_init (region); return FALSE; } if (dst_image->common.have_clip_region) { if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) - { - pixman_region32_fini (region); return FALSE; - } } if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) @@ -321,7 +317,6 @@ pixman_compute_composite_region32 (pixman_region32_t * region, -dst_image->common.alpha_origin_x, -dst_image->common.alpha_origin_y)) { - pixman_region32_fini (region); return FALSE; } } @@ -330,10 +325,7 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (src_image->common.have_clip_region) { if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) - { - pixman_region32_fini (region); return FALSE; - } } if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) { @@ -341,7 +333,6 @@ pixman_compute_composite_region32 (pixman_region32_t * region, dest_x - (src_x - src_image->common.alpha_origin_x), dest_y - (src_y - src_image->common.alpha_origin_y))) { - pixman_region32_fini (region); return FALSE; } } @@ -349,17 +340,14 @@ pixman_compute_composite_region32 (pixman_region32_t * region, if (mask_image && mask_image->common.have_clip_region) { if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) - { - pixman_region32_fini (region); return FALSE; - } + if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) { if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, dest_x - (mask_x - mask_image->common.alpha_origin_x), dest_y - (mask_y - mask_image->common.alpha_origin_y))) { - pixman_region32_fini (region); return FALSE; } } -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] bits: Fix potential divide-by-zero in projective code
From: Søren Sandmann Pedersen If the homogeneous coordinate is 0, just set the coordinates to 0. --- pixman/pixman-bits-image.c | 16 1 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 95710b4..36ea0af 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -695,12 +695,20 @@ bits_image_fetch_transformed (pixman_image_t * image, { for (i = 0; i < width; ++i) { - pixman_fixed_t x0, y0; - if (!mask || mask[i]) { - x0 = ((pixman_fixed_48_16_t)x << 16) / w; - y0 = ((pixman_fixed_48_16_t)y << 16) / w; + pixman_fixed_t x0, y0; + + if (w != 0) + { + x0 = ((pixman_fixed_48_16_t)x << 16) / w; + y0 = ((pixman_fixed_48_16_t)y << 16) / w; + } + else + { + x0 = 0; + y0 = 0; + } buffer[i] = bits_image_fetch_pixel_filtered (&image->bits, x0, y0); -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/7] Some test suite improvements (second attempt)
Sorry about the spam I just sent with a jumble of old and new patches. Hopefully this time it will work better. Here is a set of patches that contain some updates to the test suite. Specifically, - gradient-crash-test is extended to test more scenarios - floating point exceptions are enabled in some cases - The argument to fence_malloc() becomes a signed integer, and it will abort() if someone tries to malloc a negative size. - A new stress-test program that tries to use various combinations of unusual features. The hope is that this will provoke crashes or irregular behavior. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/7] Add enable_fp_exceptions() function in utils.[ch]
From: Søren Sandmann Pedersen This function enables floating point traps if possible. --- configure.ac |8 test/utils.c | 26 ++ test/utils.h |3 +++ 3 files changed, 37 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 147e1bf..2570c84 100644 --- a/configure.ac +++ b/configure.ac @@ -639,6 +639,14 @@ if test x$have_getpagesize = xyes; then AC_DEFINE(HAVE_GETPAGESIZE, 1, [Whether we have getpagesize()]) fi +AC_CHECK_HEADER([fenv.h], + [AC_DEFINE(HAVE_FENV_H, [1], [Define to 1 if we have ])]) + +AC_CHECK_LIB(m, feenableexcept, have_feenableexcept=yes, have_feenableexcept=no) +if test x$have_feenableexcept = xyes; then + AC_DEFINE(HAVE_FEENABLEEXCEPT, 1, [Whether we have feenableexcept()]) +fi + AC_CHECK_FUNC(gettimeofday, have_gettimeofday=yes, have_gettimeofday=no) AC_CHECK_HEADER(sys/time.h, have_sys_time_h=yes, have_sys_time_h=no) if test x$have_gettimeofday = xyes && test x$have_sys_time_h = xyes; then diff --git a/test/utils.c b/test/utils.c index f6278fe..a7c55f6 100644 --- a/test/utils.c +++ b/test/utils.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE + #include "utils.h" #include @@ -15,6 +17,10 @@ #include #endif +#ifdef HAVE_FENV_H +#include +#endif + /* Random number seed */ @@ -469,6 +475,26 @@ fail_after (int seconds, const char *msg) #endif } +void +enable_fp_exceptions (void) +{ +#ifdef HAVE_FENV_H +#ifdef HAVE_FEENABLEEXCEPT +/* Note: we don't enable the FE_INEXACT trap because + * that happens quite commonly. It is possible that + * over- and underflow should similarly be considered + * okay, but for now the test suite passes with them + * enabled, and it's useful to know if they start + * occuring. + */ +feenableexcept (FE_DIVBYZERO | + FE_INVALID | + FE_OVERFLOW | + FE_UNDERFLOW); +#endif +#endif +} + void * aligned_malloc (size_t align, size_t size) { diff --git a/test/utils.h b/test/utils.h index 2ea4170..bac2916 100644 --- a/test/utils.h +++ b/test/utils.h @@ -82,6 +82,9 @@ fuzzer_test_main (const char *test_name, void fail_after (int seconds, const char *msg); +/* If possible, enable traps for floating point exceptions */ +void enable_fp_exceptions(void); + /* A pair of macros which can help to detect corruption of * floating point registers after a function call. This may * happen if _mm_empty() call is forgotten in MMX/SSE2 fast -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/7] test: Make composite test use some existing macros instead of defining its own
From: Søren Sandmann Pedersen Also move the ARRAY_LENGTH macro into utils.h so it can be used elsewhere. --- test/composite.c | 56 + test/utils.h |2 + 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/test/composite.c b/test/composite.c index 5cdc521..e14f954 100644 --- a/test/composite.c +++ b/test/composite.c @@ -31,10 +31,6 @@ #include #include "utils.h" -#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0]))) -#define min(a,b) ((a) <= (b) ? (a) : (b)) -#define max(a,b) ((a) >= (b) ? (a) : (b)) - typedef struct color_t color_t; typedef struct format_t format_t; typedef struct image_t image_t; @@ -211,7 +207,7 @@ static const operator_t operators[] = 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) +#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) double Fa, Fb; @@ -267,150 +263,150 @@ calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) if (srca == 0.0) Fa = 1.0; else - Fa = min (1.0, (1.0 - dsta) / srca); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + Fa = MIN (1.0, (1.0 - dsta) / srca); if (dsta == 0.0) Fb = 1.0; else - Fb = min (1.0, (1.0 - srca) / dsta); + 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); + 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); + 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); + 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); + 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); + Fa = MAX (0.0, 1.0 - dsta / srca); return mult_chan (src, dst, Fa, 0
[Pixman] [PATCH 3/7] Extend gradient-crash-test
From: Søren Sandmann Pedersen Test the gradients with various transformations, and test cases where the gradients are specified with two identical points. --- test/Makefile.am |5 ++- test/gradient-crash-test.c | 124 +-- 2 files changed, 87 insertions(+), 42 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 79a1223..4f950d9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -14,6 +14,7 @@ TESTPROGRAMS =\ trap-crasher\ alpha-loop \ scaling-crash-test \ + gradient-crash-test \ alphamap\ blitters-test \ scaling-test\ @@ -22,7 +23,6 @@ TESTPROGRAMS =\ a1_trap_test_LDADD = $(TEST_LDADD) fetch_test_LDADD = $(TEST_LDADD) -gradient_crash_test_LDADD = $(TEST_LDADD) trap_crasher_LDADD = $(TEST_LDADD) oob_test_LDADD = $(TEST_LDADD) scaling_crash_test_LDADD = $(TEST_LDADD) @@ -49,6 +49,9 @@ alpha_loop_SOURCES = alpha-loop.c utils.c utils.h composite_LDADD = $(TEST_LDADD) composite_SOURCES = composite.c utils.c utils.h +gradient_crash_test_LDADD = $(TEST_LDADD) +gradient_crash_test_SOURCES = gradient-crash-test.c utils.c utils.h + # GTK using test programs if HAVE_GTK diff --git a/test/gradient-crash-test.c b/test/gradient-crash-test.c index 804f83b..395c469 100644 --- a/test/gradient-crash-test.c +++ b/test/gradient-crash-test.c @@ -1,6 +1,7 @@ #include #include -#include "pixman.h" +#include +#include "utils.h" int main (int argc, char **argv) @@ -11,8 +12,14 @@ main (int argc, char **argv) uint32_t *dest = malloc (WIDTH * HEIGHT * 4); pixman_image_t *src_img; pixman_image_t *dest_img; -int i, j; +int i, j, k, p; +typedef struct +{ + pixman_point_fixed_t p0; + pixman_point_fixed_t p1; +} point_pair_t; + pixman_gradient_stop_t onestop[1] = { { pixman_int_to_fixed (1), { 0x, 0x, 0x, 0x } }, @@ -30,29 +37,56 @@ main (int argc, char **argv) { pixman_int_to_fixed (1), { 0x, 0x, 0x, 0x } } }; -pixman_point_fixed_t p1 = { pixman_double_to_fixed (0), 0 }; -pixman_point_fixed_t p2 = { pixman_double_to_fixed (WIDTH / 8.), - pixman_int_to_fixed (0) }; - -#if 0 -pixman_transform_t trans = { - { { pixman_double_to_fixed (2), pixman_double_to_fixed (0.5), pixman_double_to_fixed (-100), }, - { pixman_double_to_fixed (0), pixman_double_to_fixed (3), pixman_double_to_fixed (0), }, - { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } - } -}; -#else -pixman_transform_t trans = { - { { pixman_fixed_1, 0, 0 }, - { 0, pixman_fixed_1, 0 }, - { 0, 0, pixman_fixed_1 } } +point_pair_t point_pairs [] = + { { { pixman_double_to_fixed (0), 0 }, + { pixman_double_to_fixed (WIDTH / 8.), pixman_int_to_fixed (0) } }, + { { pixman_double_to_fixed (WIDTH / 2.0), pixman_double_to_fixed (HEIGHT / 2.0) }, + { pixman_double_to_fixed (WIDTH / 2.0), pixman_double_to_fixed (HEIGHT / 2.0) } } + }; + +pixman_transform_t transformations[] = { + { + { { pixman_double_to_fixed (2), pixman_double_to_fixed (0.5), pixman_double_to_fixed (-100), }, + { pixman_double_to_fixed (0), pixman_double_to_fixed (3), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } + } + }, + { + { { pixman_double_to_fixed (1), pixman_double_to_fixed (0), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (0), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } + } + }, + { + { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (2), pixman_double_to_fixed (1.000), pixman_double_to_fixed (1.0) } + } + }, + { + { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (0), pixman_double_to_fixed (0), pixman_double_to_fixed (0) } + } + }, + { + { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), }, + { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixma
[Pixman] [PATCH 4/7] test: Move palette initialization to utils.[ch]
From: Søren Sandmann Pedersen --- test/blitters-test.c | 57 + test/utils.c | 54 +++ test/utils.h |3 ++ 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/test/blitters-test.c b/test/blitters-test.c index 77a26dd..21685b1 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -400,59 +400,6 @@ test_composite (int testnum, int verbose) return crc32; } -#define CONVERT_15(c, is_rgb) \ -(is_rgb? \ - c) >> 3) & 0x001f) | \ - (((c) >> 6) & 0x03e0) | \ - (((c) >> 9) & 0x7c00)) : \ - (c) >> 16) & 0xff) * 153 +\ - (((c) >> 8) & 0xff) * 301 +\ - (((c) ) & 0xff) * 58) >> 2)) - -static void -initialize_palette (pixman_indexed_t *palette, uint32_t mask, int is_rgb) -{ -int i; - -for (i = 0; i < 32768; ++i) - palette->ent[i] = lcg_rand() & mask; - -for (i = 0; i < mask + 1; ++i) -{ - uint32_t rgba24; - pixman_bool_t retry; - uint32_t i15; - - /* We filled the rgb->index map with random numbers, but we -* do need the ability to round trip, that is if some indexed -* color expands to an argb24, then the 15 bit version of that -* color must map back to the index. Anything else, we don't -* care about too much. -*/ - do - { - uint32_t old_idx; - - rgba24 = lcg_rand(); - i15 = CONVERT_15 (rgba24, is_rgb); - - old_idx = palette->ent[i15]; - if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15) - retry = 1; - else - retry = 0; - } while (retry); - - palette->rgba[i] = rgba24; - palette->ent[i15] = i; -} - -for (i = 0; i < mask + 1; ++i) -{ - assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i); -} -} - int main (int argc, const char *argv[]) { @@ -460,8 +407,8 @@ main (int argc, const char *argv[]) for (i = 1; i <= 8; i++) { - initialize_palette (&(rgb_palette[i]), (1 << i) - 1, TRUE); - initialize_palette (&(y_palette[i]), (1 << i) - 1, FALSE); + initialize_palette (&(rgb_palette[i]), i, TRUE); + initialize_palette (&(y_palette[i]), i, FALSE); } return fuzzer_test_main("blitters", 200, diff --git a/test/utils.c b/test/utils.c index a7c55f6..4701bf6 100644 --- a/test/utils.c +++ b/test/utils.c @@ -509,3 +509,57 @@ aligned_malloc (size_t align, size_t size) return result; } + +#define CONVERT_15(c, is_rgb) \ +(is_rgb? \ + c) >> 3) & 0x001f) | \ + (((c) >> 6) & 0x03e0) | \ + (((c) >> 9) & 0x7c00)) : \ + (c) >> 16) & 0xff) * 153 +\ + (((c) >> 8) & 0xff) * 301 +\ + (((c) ) & 0xff) * 58) >> 2)) + +void +initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb) +{ +int i; +uint32_t mask = (1 << depth) - 1; + +for (i = 0; i < 32768; ++i) + palette->ent[i] = lcg_rand() & mask; + +for (i = 0; i < mask + 1; ++i) +{ + uint32_t rgba24; + pixman_bool_t retry; + uint32_t i15; + + /* We filled the rgb->index map with random numbers, but we +* do need the ability to round trip, that is if some indexed +* color expands to an argb24, then the 15 bit version of that +* color must map back to the index. Anything else, we don't +* care about too much. +*/ + do + { + uint32_t old_idx; + + rgba24 = lcg_rand(); + i15 = CONVERT_15 (rgba24, is_rgb); + + old_idx = palette->ent[i15]; + if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15) + retry = 1; + else + retry = 0; + } while (retry); + + palette->rgba[i] = rgba24; + palette->ent[i15] = i; +} + +for (i = 0; i < mask + 1; ++i) +{ + assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i); +} +} diff --git a/test/utils.h b/test/utils.h index bac2916..7b33461 100644
[Pixman] [PATCH 6/7] Make the argument to fence_malloc() an int64_t
From: Søren Sandmann Pedersen That way we can detect if someone attempts to allocate a negative size and abort instead of just returning NULL and segfaulting later. --- test/utils.c |7 +-- test/utils.h |2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/utils.c b/test/utils.c index cde9c62..6bcc935 100644 --- a/test/utils.c +++ b/test/utils.c @@ -232,7 +232,7 @@ typedef struct #endif void * -fence_malloc (uint32_t len) +fence_malloc (int64_t len) { unsigned long page_size = getpagesize(); unsigned long page_mask = page_size - 1; @@ -246,12 +246,15 @@ fence_malloc (uint32_t len) uint8_t *payload; uint8_t *addr; +if (len < 0) + abort(); + addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { - printf ("mmap failed on %u %u\n", len, n_bytes); + printf ("mmap failed on %lld %u\n", len, n_bytes); return NULL; } diff --git a/test/utils.h b/test/utils.h index 7b33461..abd11ec 100644 --- a/test/utils.h +++ b/test/utils.h @@ -57,7 +57,7 @@ image_endian_swap (pixman_image_t *img, int bpp); * so that out-of-bounds access will cause segfaults */ void * -fence_malloc (uint32_t len); +fence_malloc (int64_t len); void fence_free (void *data); -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 5/7] test/utils.c: Initialize palette->rgba to 0.
From: Søren Sandmann Pedersen That way it can be used with palettes that are not statically allocated, without causing valgrind issues. --- test/utils.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/test/utils.c b/test/utils.c index 4701bf6..cde9c62 100644 --- a/test/utils.c +++ b/test/utils.c @@ -528,6 +528,8 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb) for (i = 0; i < 32768; ++i) palette->ent[i] = lcg_rand() & mask; +memset (palette->rgba, 0, sizeof (palette->rgba)); + for (i = 0; i < mask + 1; ++i) { uint32_t rgba24; -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 7/7] Add a stress-test program.
From: Søren Sandmann Pedersen This test program tries to use as many rarely-used features as possible, including alpha maps, accessor functions, oddly-sized images, strange transformations, conical gradients, etc. The hope is to provoke crashes or irregular behavior in pixman. --- test/Makefile.am |4 + test/stress-test.c | 858 test/utils.h |9 + 3 files changed, 871 insertions(+), 0 deletions(-) create mode 100644 test/stress-test.c diff --git a/test/Makefile.am b/test/Makefile.am index 4f950d9..e557d7a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -16,6 +16,7 @@ TESTPROGRAMS =\ scaling-crash-test \ gradient-crash-test \ alphamap\ + stress-test \ blitters-test \ scaling-test\ affine-test \ @@ -52,6 +53,9 @@ composite_SOURCES = composite.c utils.c utils.h gradient_crash_test_LDADD = $(TEST_LDADD) gradient_crash_test_SOURCES = gradient-crash-test.c utils.c utils.h +stress_test_LDADD = $(TEST_LDADD) +stress_test_SOURCES = stress-test.c utils.c utils.h + # GTK using test programs if HAVE_GTK diff --git a/test/stress-test.c b/test/stress-test.c new file mode 100644 index 000..d8dd79c --- /dev/null +++ b/test/stress-test.c @@ -0,0 +1,858 @@ +#include "utils.h" + +#if 0 +#define fence_malloc malloc +#define fence_free free +#define make_random_bytes malloc +#endif + +static const pixman_format_code_t image_formats[] = +{ +PIXMAN_a8r8g8b8, +PIXMAN_x8r8g8b8, +PIXMAN_r5g6b5, +PIXMAN_r3g3b2, +PIXMAN_a8, +PIXMAN_a8b8g8r8, +PIXMAN_x8b8g8r8, +PIXMAN_b8g8r8a8, +PIXMAN_b8g8r8x8, +PIXMAN_x14r6g6b6, +PIXMAN_r8g8b8, +PIXMAN_b8g8r8, +PIXMAN_r5g6b5, +PIXMAN_b5g6r5, +PIXMAN_x2r10g10b10, +PIXMAN_a2r10g10b10, +PIXMAN_x2b10g10r10, +PIXMAN_a2b10g10r10, +PIXMAN_a1r5g5b5, +PIXMAN_x1r5g5b5, +PIXMAN_a1b5g5r5, +PIXMAN_x1b5g5r5, +PIXMAN_a4r4g4b4, +PIXMAN_x4r4g4b4, +PIXMAN_a4b4g4r4, +PIXMAN_x4b4g4r4, +PIXMAN_a8, +PIXMAN_r3g3b2, +PIXMAN_b2g3r3, +PIXMAN_a2r2g2b2, +PIXMAN_a2b2g2r2, +PIXMAN_c8, +PIXMAN_g8, +PIXMAN_x4c4, +PIXMAN_x4g4, +PIXMAN_c4, +PIXMAN_g4, +PIXMAN_g1, +PIXMAN_x4a4, +PIXMAN_a4, +PIXMAN_r1g2b1, +PIXMAN_b1g2r1, +PIXMAN_a1r1g1b1, +PIXMAN_a1b1g1r1, +PIXMAN_a1 +}; + +static pixman_filter_t filters[] = +{ +PIXMAN_FILTER_NEAREST, +PIXMAN_FILTER_BILINEAR, +PIXMAN_FILTER_FAST, +PIXMAN_FILTER_GOOD, +PIXMAN_FILTER_BEST, +PIXMAN_FILTER_CONVOLUTION +}; + +static int +get_size (void) +{ +switch (lcg_rand_n (28)) +{ +case 0: + return 1; + +case 1: + return 2; + +default: +case 2: + return lcg_rand_n (200); + +case 4: + return lcg_rand_n (2000) + 1000; + +case 5: + return 65535; + +case 6: + return 65536; + +case 7: + return lcg_rand_N (64000) + 63000; +} +} + +static void +destroy (pixman_image_t *image, void *data) +{ +if (image->type == BITS && image->bits.free_me != image->bits.bits) +{ + uint32_t *bits; + + if (image->bits.bits != (void *)0x01) + { + bits = image->bits.bits; + + if (image->bits.rowstride < 0) + { + bits -= (- image->bits.rowstride * (image->bits.height - 1)); + + } + + fence_free (bits); + } +} + +free (data); +} + +static uint32_t +real_reader (const void *src, int size) +{ +switch (size) +{ +case 1: + return *(uint8_t *)src; +case 2: + return *(uint16_t *)src; +case 4: + return *(uint32_t *)src; +default: + assert (0); + break; +} +} + +static void +real_writer (void *src, uint32_t value, int size) +{ +switch (size) +{ +case 1: + *(uint8_t *)src = value; + break; + +case 2: + *(uint16_t *)src = value; + break; + +case 4: + *(uint32_t *)src = value; + break; + +default: + assert (0); + break; +} +} + +static uint32_t +fake_reader (const void *src, int size) +{ +uint32_t r = lcg_rand_u32 (); + +assert (size == 1 || size == 2 || size == 4); +return r & ((1 << (size * 8)) - 1); +} + +static void +fake_writer (void *src, uint32_t value, int size) +{ +assert (size == 1 || size == 2 || size == 4); +} + +static int32_t +log_rand (void) +{ +uint32_t mask; + +mask = (1 << lcg_rand_n (31)) - 1; + +return (lcg_rand () & mask) - (mask >> 1); +} + +static pixman_image_t * +create_random_bits_image (void) +{ +pixman_format_code_t format; +pixman_indexed_t *indexed; +pixman_image_t *image; +int width, height, stride; +uint32_t *bits; +pixman_read_mem
[Pixman] [PATCH 1/2] Add a test compositing with the various PDF operators.
From: Søren Sandmann Pedersen The test has floating point exceptions enabled, and currently fails with a divide-by-zero. --- test/Makefile.am |4 ++ test/pdf-op-test.c | 84 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 test/pdf-op-test.c diff --git a/test/Makefile.am b/test/Makefile.am index 52e4183..3d40157 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,6 +6,7 @@ INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman TESTPROGRAMS = \ a1-trap-test\ + pdf-op-test \ region-test \ region-translate-test \ fetch-test \ @@ -28,6 +29,9 @@ oob_test_LDADD = $(TEST_LDADD) scaling_crash_test_LDADD = $(TEST_LDADD) region_translate_test_LDADD = $(TEST_LDADD) +pdf_op_test_LDADD = $(TEST_LDADD) +pdf_op_test_SOURCES = pdf-op-test.c utils.c utils.h + region_test_LDADD = $(TEST_LDADD) region_test_SOURCES = region-test.c utils.c utils.h diff --git a/test/pdf-op-test.c b/test/pdf-op-test.c new file mode 100644 index 000..dc7a4fd --- /dev/null +++ b/test/pdf-op-test.c @@ -0,0 +1,84 @@ +#include +#include +#include "utils.h" + +static const pixman_op_t pdf_ops[] = +{ +PIXMAN_OP_MULTIPLY, +PIXMAN_OP_SCREEN, +PIXMAN_OP_OVERLAY, +PIXMAN_OP_DARKEN, +PIXMAN_OP_LIGHTEN, +PIXMAN_OP_COLOR_DODGE, +PIXMAN_OP_COLOR_BURN, +PIXMAN_OP_HARD_LIGHT, +PIXMAN_OP_SOFT_LIGHT, +PIXMAN_OP_DIFFERENCE, +PIXMAN_OP_EXCLUSION, +PIXMAN_OP_HSL_HUE, +PIXMAN_OP_HSL_SATURATION, +PIXMAN_OP_HSL_COLOR, +PIXMAN_OP_HSL_LUMINOSITY +}; + +static const uint32_t pixels[] = +{ +0x00808080, +0x80123456, +0x, +0x, +0x00ff, +0x80808080, +0x00123456, +}; + +int +main () +{ +int o, s, m, d; + +enable_fp_exceptions(); + +for (o = 0; o < ARRAY_LENGTH (pdf_ops); ++o) +{ + pixman_op_t op = pdf_ops[o]; + + for (s = 0; s < ARRAY_LENGTH (pixels); ++s) + { + pixman_image_t *src; + + src = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, 1, 1, (uint32_t *)&(pixels[s]), 4); + + for (m = -1; m < ARRAY_LENGTH (pixels); ++m) + { + pixman_image_t *msk = NULL; + if (m >= 0) + { + msk = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, 1, 1, (uint32_t *)&(pixels[m]), 4); + } + + for (d = 0; d < ARRAY_LENGTH (pixels); ++d) + { + pixman_image_t *dst; + uint32_t dp = pixels[d]; + + dst = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, 1, 1, &dp, 4); + + pixman_image_composite (op, src, msk, dst, + 0, 0, 0, 0, 0, 0, 1, 1); + + pixman_image_unref (dst); + } + if (msk) + pixman_image_unref (msk); + } + + pixman_image_unref (src); + } +} + +return 0; +} -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] Fix divide-by-zero in set_lum().
From: Søren Sandmann Pedersen When (l - min) or (max - l) are zero, simply set all the channels to the limit, 0 in the case of (l - min), and a in the case of (max - l). --- pixman/pixman-combine.c.template | 30 -- 1 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template index 56dfb43..f5dd8e1 100644 --- a/pixman/pixman-combine.c.template +++ b/pixman/pixman-combine.c.template @@ -959,15 +959,33 @@ set_lum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum) if (min < 0) { - tmp[0] = l + (tmp[0] - l) * l / (l - min); - tmp[1] = l + (tmp[1] - l) * l / (l - min); - tmp[2] = l + (tmp[2] - l) * l / (l - min); + if (l - min == 0.0) + { + tmp[0] = 0; + tmp[1] = 0; + tmp[2] = 0; + } + else + { + tmp[0] = l + (tmp[0] - l) * l / (l - min); + tmp[1] = l + (tmp[1] - l) * l / (l - min); + tmp[2] = l + (tmp[2] - l) * l / (l - min); + } } if (max > a) { - tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l); - tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l); - tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l); + if (max - l == 0.0) + { + tmp[0] = a; + tmp[1] = a; + tmp[2] = a; + } + else + { + tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l); + tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l); + tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l); + } } dest[0] = tmp[0] * MASK + 0.5; -- 1.6.0.6 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] sse2: Skip src pixels that are zero in sse2_composite_over_8888_n_8888()
From: Søren Sandmann Pedersen This is a big speed-up in the SVG helicopter game: http://ie.microsoft.com/testdrive/Performance/Helicopter/Default.xhtml when rendered by Firefox 4 since it is compositing big images consisting almost entirely of zeros. --- pixman/pixman-sse2.c | 75 + 1 files changed, 44 insertions(+), 31 deletions(-) diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c index 5907de0..032f13b 100644 --- a/pixman/pixman-sse2.c +++ b/pixman/pixman-sse2.c @@ -3051,37 +3051,45 @@ sse2_composite_over__n_ (pixman_implementation_t *imp, while (w && (unsigned long)dst & 15) { uint32_t s = *src++; - uint32_t d = *dst; - - __m64 ms = unpack_32_1x64 (s); - __m64 alpha= expand_alpha_1x64 (ms); - __m64 dest = _mm_movepi64_pi64 (xmm_mask); - __m64 alpha_dst = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 ( - in_over_1x64 (&ms, &alpha, &dest, &alpha_dst)); + if (s) + { + uint32_t d = *dst; + + __m64 ms = unpack_32_1x64 (s); + __m64 alpha= expand_alpha_1x64 (ms); + __m64 dest = _mm_movepi64_pi64 (xmm_mask); + __m64 alpha_dst = unpack_32_1x64 (d); + + *dst = pack_1x64_32 ( + in_over_1x64 (&ms, &alpha, &dest, &alpha_dst)); + } + dst++; w--; } while (w >= 4) { xmm_src = load_128_unaligned ((__m128i*)src); - xmm_dst = load_128_aligned ((__m128i*)dst); - - unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); - unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); - expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, - &xmm_alpha_lo, &xmm_alpha_hi); - - in_over_2x128 (&xmm_src_lo, &xmm_src_hi, - &xmm_alpha_lo, &xmm_alpha_hi, - &xmm_mask, &xmm_mask, - &xmm_dst_lo, &xmm_dst_hi); - - save_128_aligned ( - (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); + if (!is_zero (xmm_src)) + { + xmm_dst = load_128_aligned ((__m128i*)dst); + + unpack_128_2x128 (xmm_src, &xmm_src_lo, &xmm_src_hi); + unpack_128_2x128 (xmm_dst, &xmm_dst_lo, &xmm_dst_hi); + expand_alpha_2x128 (xmm_src_lo, xmm_src_hi, + &xmm_alpha_lo, &xmm_alpha_hi); + + in_over_2x128 (&xmm_src_lo, &xmm_src_hi, + &xmm_alpha_lo, &xmm_alpha_hi, + &xmm_mask, &xmm_mask, + &xmm_dst_lo, &xmm_dst_hi); + + save_128_aligned ( + (__m128i*)dst, pack_2x128_128 (xmm_dst_lo, xmm_dst_hi)); + } + dst += 4; src += 4; w -= 4; @@ -3090,16 +3098,21 @@ sse2_composite_over__n_ (pixman_implementation_t *imp, while (w) { uint32_t s = *src++; - uint32_t d = *dst; - __m64 ms = unpack_32_1x64 (s); - __m64 alpha = expand_alpha_1x64 (ms); - __m64 mask = _mm_movepi64_pi64 (xmm_mask); - __m64 dest = unpack_32_1x64 (d); - - *dst++ = pack_1x64_32 ( - in_over_1x64 (&ms, &alpha, &mask, &dest)); + if (s) + { + uint32_t d = *dst; + + __m64 ms = unpack_32_1x64 (s); + __m64 alpha = expand_alpha_1x64 (ms); + __m64 mask = _mm_movepi64_pi64 (xmm_mask); + __m64 dest = unpack_32_1x64 (d); + + *dst = pack_1x64_32 ( + in_over_1x64 (&ms, &alpha, &mask, &dest)); + } + dst++; w--; } } -- 1.7.3.1 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman