[Pixman] [PATCH] Remove pointless declaration of _pixman_image_get_scanline_generic_64()
From: Søren Sandmann Pedersen This declaration used to be necessary when _pixman_image_get_scanline_generic_64() referred to a structure that itself referred back to _pixman_image_get_scanline_generic_64(). --- pixman/pixman-bits-image.c |4 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index b6c8630..c69e151 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -1123,10 +1123,6 @@ bits_image_fetch_untransformed_64 (pixman_iter_t * iter, return buffer; } -static uint32_t * -_pixman_image_get_scanline_generic_64 (pixman_iter_t *iter, - const uint32_t * mask); - typedef struct { pixman_format_code_t format; -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Remove TODO file
From: Søren Sandmann Pedersen It's obsolete and irrelevant. --- TODO | 271 -- 1 files changed, 0 insertions(+), 271 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 4434ec7..000 --- a/TODO +++ /dev/null @@ -1,271 +0,0 @@ - - Testing -- Test implementations against each other -- Test both with and without the operator strength reduction. - They shold be identical. - - - SSE 2 issues: - - - Use MM_HINT_NTA instead of MM_HINT_T0 - - - Use of fbCompositeOver_x888x8xsse2() - - - Update the RLEASING file - - - Things to keep in mind if breaking ABI: - - - There should be a guard #ifndef I_AM_EITHER_CAIRO_OR_THE_X_SERVER - - - X server will require 16.16 essentially forever. Can we get -the required precision by simply adding offset_x/y to the -relevant rendering API? - - - Get rid of workaround for X server bug. - - - pixman_image_set_indexed() should copy its argument, and X -should be ported over to use a pixman_image as the -representation of a Picture, rather than creating one on each -operation. - - - We should get rid of pixman_set_static_pointers() - - - We should get rid of the various trapezoid helper functions(). -(They only exist because they are theoretically available to -drivers). - - - 16 bit regions should be deleted - - - There should only be one trap rasterization API. - - - The PIXMAN_g8/c8/etc formats should use the A channel -to indicate the actual depth. That way PIXMAN_x4c4 and PIXMAN_c8 - won't collide. - - - Maybe bite the bullet and make configure.ac generate a pixman-types.h -file that can be included from pixman.h to avoid the #ifdef magic -in pixman.h - - - Make pixman_region_point_in() survive a NULL box, then fix up -pixman-compose.c - - - Possibly look into inlining the fetch functions - - - There is a bug with source clipping demonstrated by clip-test in the -test directory. If we interprete source clipping as given in -destination coordinates, which is probably the only sane choice, -then the result should have two red bars down the sides. - - - Test suite - - - Add a general way of dealing with architecture specific -fast-paths. The current idea is to have each operation that can -be optimized is called through a function pointer that is -initially set to an initialization function that is responsible for -setting the function pointer to the appropriate fast-path. - - - Go through things marked FIXME - - - Add calls to prepare and finish access where necessary. grep for -ACCESS_MEM, and make sure they are correctly wrapped in prepare -and finish. - - - restore READ/WRITE in the fbcompose combiners since they sometimes -store directly to destination drawables. - - - It probably makes sense to move the more strange X region API -into pixman as well, but guarded with PIXMAN_XORG_COMPATIBILITY - - - Reinstate the FbBits typedef? At the moment we don't -even have the FbBits type; we just use uint32_t everywhere. - -Keith says in bug 2335: - -The 64-bit code in fb (pixman) is probably broken; it hasn't been -used in quite some time as PCI (and AGP) is 32-bits wide, so -doing things 64-bits at a time is a net loss. To quickly fix -this, I suggest just using 32-bit datatypes by setting -IC_SHIFT to 5 for all machines. - - - Consider optimizing the 8/16 bit solid fills in pixman-util.c by -storing more than one value at a time. - - - Add an image cache to prevent excessive malloc/free. Note that pixman -needs to be thread safe when used from cairo. - - - Moving to 24.8 coordinates. This is tricky because X is still -defined as 16.16 and will be basically forever. It's possible we -could do this by adding extra offset_x/y parameters to the -trapezoid calls. The X server could then just call the API with -(0, 0). Cairo would have to make sure that the delta *within* a -batch of trapezoids does not exceed 16 bit. - - - Consider adding actual backends. Brain dump: - -A backend is something that knows how to - - - Create images - - Composite three images - - Rasterize trapezoids - - Do solid fills and blits - -These operations are provided by a vtable that the backend will -create when it is initialized. Initial backends: - - - VMX - - SSE2 - - MMX - - Plain Old C - -When the SIMD backends are initialized, they will be passed a -pointer to the Plain Old C backend that they can use for fallback -purposes. - -Images would gain a vtable as well that would contain things like - - - Read scanline - - Write scanline - -(Or even read_patch/write_patch as suggested b
[Pixman] [PATCH] pixel_checker: Move sRGB conversion into get_limits()
From: Søren Sandmann Pedersen The sRGB conversion has to be done every time the limits are being computed. Without this fix, pixel_checker_get_min/max() will produce the wrong results when called from somewhere other than pixel_checker_check(). --- test/utils.c | 28 +--- 1 files changed, 13 insertions(+), 15 deletions(-) diff --git a/test/utils.c b/test/utils.c index 85b58d0..df16ef5 100644 --- a/test/utils.c +++ b/test/utils.c @@ -962,6 +962,18 @@ get_limits (const pixel_checker_t *checker, double limit, color_t *color, int *ao, int *ro, int *go, int *bo) { +color_t tmp; + +if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB) +{ + tmp.a = color->a; + tmp.r = convert_linear_to_srgb (color->r); + tmp.g = convert_linear_to_srgb (color->g); + tmp.b = convert_linear_to_srgb (color->b); + + color = &tmp; +} + *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0); *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0); *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0); @@ -988,25 +1000,11 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color, pixman_bool_t pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel, -color_t *color_in) +color_t *color) { int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi; int32_t ai, ri, gi, bi; pixman_bool_t result; -color_t tmp, *color; - -if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB) -{ - tmp.a = color_in->a; - tmp.r = convert_linear_to_srgb (color_in->r); - tmp.g = convert_linear_to_srgb (color_in->g); - tmp.b = convert_linear_to_srgb (color_in->b); - color = &tmp; -} -else -{ - color = color_in; -} pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo); pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi); -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] test/utils.c: Use pow(), not powf() in sRGB conversion routines
From: Søren Sandmann Pedersen These functions are operating on double precision, so use pow() instead of powf(). --- test/utils.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils.c b/test/utils.c index df16ef5..c922ae5 100644 --- a/test/utils.c +++ b/test/utils.c @@ -772,7 +772,7 @@ convert_srgb_to_linear (double c) if (c <= 0.04045) return c / 12.92; else -return powf ((c + 0.055) / 1.055, 2.4); +return pow ((c + 0.055) / 1.055, 2.4); } double @@ -781,7 +781,7 @@ convert_linear_to_srgb (double c) if (c <= 0.0031308) return c * 12.92; else -return 1.055 * powf (c, 1.0/2.4) - 0.055; +return 1.055 * pow (c, 1.0/2.4) - 0.055; } void -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [cairo] help building cairo on windows
Andrea Canciani writes: > This reminds me that I have some patches to improve building pixman on win32: > http://cgit.freedesktop.org/~ranma42/pixman/commit/?h=wip/simpleops-to-master > > Soren, is it ok if I push the attached patches? No objections from me if the test suite still passes with PIXMAN_DISABLE=sse2 set. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] pixman hangs in affine-test
Siarhei Siamashka writes: > Hello, > > $ test/affine-test 212944861 > src_fmt=2002, dst_fmt=2002 > op=3, scale_x=-6077, scale_y=-148221, repeat=1 > translate_x=105371, translate_y=105371 > src_width=16, src_height=12, dst_width=7, dst_height=2 > src_x=-3, src_y=-3, dst_x=0, dst_y=0 > w=6, h=2 > > This still needs a separate testcase for the test suite and a bugfix. Good catch. This branch: http://cgit.freedesktop.org/~sandmann/pixman/log/?h=infinite-loop adds a test case. I haven't tried tracking down the bug at all. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] pixman hangs in affine-test
Søren Sandmann writes: > Good catch. This branch: > > http://cgit.freedesktop.org/~sandmann/pixman/log/?h=infinite-loop > > adds a test case. I haven't tried tracking down the bug at all. The infinite loop is caused by an overflow in this expression from FAST_BILINEAR_MAINLOOP_INT in pixman-inlines.h: pixman_int_to_fixed (vx + (width - 1) * unit_x) + 1; where unit_x is 0x200017bd and width - 1 is 5 so the multiplication result doesn't fit in a signed 32 bit integer. A simple fix is to just cast unit_x to int64_t, which is what the following patch does. However, I don't know this code very well and I'm not convinced that just casting is the right fix, so review and better suggestions are welcome. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/3] affine-test: Print out the transformation matrix when verbose
From: Søren Sandmann Pedersen Printing out the translation and scale is a bit misleading because the actual transformation matrix can be modified in various other ways. Instead simply print the whole transformation matrix that is actually used. --- test/affine-test.c | 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/affine-test.c b/test/affine-test.c index 6827cc3..7bc28b4 100644 --- a/test/affine-test.c +++ b/test/affine-test.c @@ -200,11 +200,19 @@ test_composite (int testnum, if (verbose) { +#define M(r,c) \ + transform.matrix[r][c] + printf ("src_fmt=%08X, dst_fmt=%08X\n", src_fmt, dst_fmt); - printf ("op=%d, scale_x=%d, scale_y=%d, repeat=%d\n", - op, scale_x, scale_y, repeat); - printf ("translate_x=%d, translate_y=%d\n", - translate_x, translate_y); + printf ("op=%d, repeat=%d, transform=\n", + op, repeat); + printf (" { { { 0x%08x, 0x%08x, 0x%08x },\n" + " { 0x%08x, 0x%08x, 0x%08x },\n" + " { 0x%08x, 0x%08x, 0x%08x },\n" + " } };\n", + M(0,0), M(0,1), M(0,2), + M(1,0), M(1,1), M(1,2), + M(2,0), M(2,1), M(2,2)); printf ("src_width=%d, src_height=%d, dst_width=%d, dst_height=%d\n", src_width, src_height, dst_width, dst_height); printf ("src_x=%d, src_y=%d, dst_x=%d, dst_y=%d\n", -- 1.7.11.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/3] test: Add inifinite-loop test
From: Søren Sandmann Pedersen This test demonstrates a bug where a certain transformation matrix can result in an infinite loop. It was extracted as a standalone version of "affine-test 212944861". If given the option -nf, the test program will not call fail_after() and therefore potentially run forever. --- test/Makefile.sources | 1 + test/infinite-loop.c | 39 +++ 2 files changed, 40 insertions(+) create mode 100644 test/infinite-loop.c diff --git a/test/Makefile.sources b/test/Makefile.sources index fad8c6f..1ecface 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -6,6 +6,7 @@ TESTPROGRAMS = \ region-translate-test \ fetch-test \ oob-test\ + infinite-loop \ trap-crasher\ alpha-loop \ scaling-crash-test \ diff --git a/test/infinite-loop.c b/test/infinite-loop.c new file mode 100644 index 000..8a7a2ab --- /dev/null +++ b/test/infinite-loop.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "utils.h" + +int +main (int argc, char **argv) +{ +#define SRC_WIDTH 16 +#define SRC_HEIGHT 12 +#define DST_WIDTH 7 +#define DST_HEIGHT 2 + +static const pixman_transform_t transform = { + { { 0x200017bd, 0x, 0x000e6465 }, + { 0x, 0x000a42fd, 0x000e6465 }, + { 0x, 0x, 0x0001 }, + } +}; +pixman_image_t *src, *dest; + +src = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, SRC_WIDTH, SRC_HEIGHT, NULL, -1); +dest = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, DST_WIDTH, DST_HEIGHT, NULL, -1); + +pixman_image_set_transform (src, &transform); +pixman_image_set_repeat (src, PIXMAN_REPEAT_NORMAL); +pixman_image_set_filter (src, PIXMAN_FILTER_BILINEAR, NULL, 0); + +if (argc == 1 || strcmp (argv[1], "-nf") != 0) + fail_after (1, "infinite loop detected"); + +pixman_image_composite ( + PIXMAN_OP_OVER, src, NULL, dest, -3, -3, 0, 0, 0, 0, 6, 2); + +return 0; +} -- 1.7.11.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/3] Possible fix for infinite loop
From: Søren Sandmann Pedersen The infinite loop detected by "affine-test 212944861" is caused by an overflow in this expression: max_x = pixman_fixed_to_int (vx + (width - 1) * unit_x) + 1; where (width - 1) * unit_x doesn't fit in a signed int. By casting unit_x to int64_t, the expression no longer overflows and affine-test 212944861 no longer loops forever. --- pixman/pixman-inlines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pixman/pixman-inlines.h b/pixman/pixman-inlines.h index 5517de5..3a3c658 100644 --- a/pixman/pixman-inlines.h +++ b/pixman/pixman-inlines.h @@ -859,7 +859,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, { \ vx = v.vector[0]; \ repeat (PIXMAN_REPEAT_NORMAL, &vx, pixman_int_to_fixed(src_image->bits.width)); \ - max_x = pixman_fixed_to_int (vx + (width - 1) * unit_x) + 1; \ + max_x = pixman_fixed_to_int (vx + (width - 1) * (int64_t)unit_x) + 1; \ \ if (src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH) \ { \ -- 1.7.11.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/7] implementation: Write lookup_combiner() in a less convoluted way.
From: Søren Sandmann Pedersen Instead of initializing an array on the stack, just use a simple switch to select which set of combiners to look up in. --- pixman/pixman-implementation.c | 37 - 1 files changed, 24 insertions(+), 13 deletions(-) diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 77d0906..d2573ab 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -121,25 +121,36 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, pixman_bool_t component_alpha, pixman_bool_tnarrow) { -pixman_combine_32_func_t f; - -do +while (imp) { - pixman_combine_32_func_t (*combiners[]) = + pixman_combine_32_func_t f = NULL; + + switch ((narrow << 1) | component_alpha) { - (pixman_combine_32_func_t *)imp->combine_64, - (pixman_combine_32_func_t *)imp->combine_64_ca, - imp->combine_32, - imp->combine_32_ca, - }; + case 0: /* not narrow, not component alpha */ + f = (pixman_combine_32_func_t)imp->combine_64[op]; + break; + + case 1: /* not narrow, component_alpha */ + f = (pixman_combine_32_func_t)imp->combine_64_ca[op]; + break; + + case 2: /* narrow, not component alpha */ + f = imp->combine_32[op]; + break; + + case 3: /* narrow, component_alpha */ + f = imp->combine_32_ca[op]; + break; + } - f = combiners[component_alpha | (narrow << 1)][op]; + if (f) + return f; imp = imp->delegate; } -while (!f); -return f; +return NULL; } pixman_bool_t -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/7] Clean up delegation logic
Hi, The following patches move all the delegation logic into pixman-implementation.c and then, since the chain of implementations no longer has anything to do with the delegation design pattern, rename "delegate" to "fallback". It's a net win of 227 lines of code, and makes pixman-implementation.c look a lot nicer because all the trivial "delegate_blah()" functions go away. There are some changes to the NEON and DSPr2 backends that I haven't tried to compile. If there are any problems there, please let me know. Thanks, Soren pixman-arm-neon.c | 89 +++ pixman-fast-path.c |6 - pixman-general.c| 46 +--- pixman-glyph.c |4 pixman-implementation.c | 276 pixman-mips-dspr2.c | 89 +++ pixman-mmx.c| 119 ++-- pixman-noop.c | 14 +- pixman-private.h| 36 +++--- pixman-sse2.c | 146 - pixman-utils.c | 112 --- pixman.c|2 12 files changed, 356 insertions(+), 583 deletions(-) ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/7] Move blt delegation into pixman-implementation.c
From: Søren Sandmann Pedersen Rather than require each individual implementation to do the delegation for blt, just do it in pixman-implementation.c whenever the implementation blt returns FALSE. With this change, there is no longer any reason for the implementations to have one blt function that delegates and one that actually blits, so consolidate those in the NEON, DSPr2, SSE2, and MMX implementations. --- pixman/pixman-arm-neon.c | 54 +++--- pixman/pixman-general.c| 21 pixman/pixman-implementation.c | 40 +-- pixman/pixman-mips-dspr2.c | 54 +++--- pixman/pixman-mmx.c| 68 +++--- pixman/pixman-sse2.c | 69 +++ 6 files changed, 81 insertions(+), 225 deletions(-) diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c index ca139de..f4cc0ba 100644 --- a/pixman/pixman-arm-neon.c +++ b/pixman/pixman-arm-neon.c @@ -227,18 +227,19 @@ pixman_fill_neon (uint32_t *bits, } static pixman_bool_t -pixman_blt_neon (uint32_t *src_bits, - uint32_t *dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height) +arm_neon_blt (pixman_implementation_t *imp, + uint32_t * src_bits, + uint32_t * dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dest_x, + int dest_y, + int width, + int height) { if (src_bpp != dst_bpp) return FALSE; @@ -423,35 +424,6 @@ static const pixman_fast_path_t arm_neon_fast_paths[] = }; static pixman_bool_t -arm_neon_blt (pixman_implementation_t *imp, - uint32_t * src_bits, - uint32_t * dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height) -{ -if (!pixman_blt_neon ( -src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, -src_x, src_y, dest_x, dest_y, width, height)) - -{ - return _pixman_implementation_blt ( - imp->delegate, - src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, - src_x, src_y, dest_x, dest_y, width, height); -} - -return TRUE; -} - -static pixman_bool_t arm_neon_fill (pixman_implementation_t *imp, uint32_t * bits, int stride, diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index d4b2daa..dcf9bfc 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -201,26 +201,6 @@ static const pixman_fast_path_t general_fast_path[] = }; static pixman_bool_t -general_blt (pixman_implementation_t *imp, - uint32_t * src_bits, - uint32_t * dst_bits, - int src_stride, - int dst_stride, - int src_bpp, - int dst_bpp, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height) -{ -/* We can't blit unless we have sse2 or mmx */ - -return FALSE; -} - -static pixman_bool_t general_fill (pixman_implementation_t *imp, uint32_t * bits, int stride, @@ -242,7 +222,6 @@ _pixman_implementation_create_general (void) _pixman_setup_combiner_functions_32 (imp); _pixman_setup_combiner_functions_64 (imp); -imp->blt = general_blt; imp->fill = general_fill; imp->src_iter_init = general_src_iter_init; im
[Pixman] [PATCH 3/7] Move fill delegation into pixman-implementation.c
From: Søren Sandmann Pedersen As in the blt commit, do the delegation in pixman-implementation.c whenever the implementation fill returns FALSE instead of relying on each implementation to do it by itself. With this change there is no longer any reason for the implementations to have one fill function that delegates and one that actually blits, so consolidate those in the NEON, DSPr2, SSE2, and MMX implementations. --- pixman/pixman-arm-neon.c | 35 +-- pixman/pixman-fast-path.c |4 +-- pixman/pixman-general.c| 15 pixman/pixman-implementation.c | 30 +++- pixman/pixman-mips-dspr2.c | 35 +-- pixman/pixman-mmx.c| 45 +++-- pixman/pixman-sse2.c | 71 ++- 7 files changed, 71 insertions(+), 164 deletions(-) diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c index f4cc0ba..60e9c78 100644 --- a/pixman/pixman-arm-neon.c +++ b/pixman/pixman-arm-neon.c @@ -183,14 +183,15 @@ pixman_composite_src_n__asm_neon (int32_t w, uint32_t src); static pixman_bool_t -pixman_fill_neon (uint32_t *bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t _xor) +arm_neon_fill (pixman_implementation_t *imp, + uint32_t * bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t _xor) { /* stride is always multiple of 32bit units in pixman */ uint32_t byte_stride = stride * sizeof(uint32_t); @@ -423,24 +424,6 @@ static const pixman_fast_path_t arm_neon_fast_paths[] = { PIXMAN_OP_NONE }, }; -static pixman_bool_t -arm_neon_fill (pixman_implementation_t *imp, - uint32_t * bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t xor) -{ -if (pixman_fill_neon (bits, stride, bpp, x, y, width, height, xor)) - return TRUE; - -return _pixman_implementation_fill ( - imp->delegate, bits, stride, bpp, x, y, width, height, xor); -} - #define BIND_COMBINE_U(name) \ void \ pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \ diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 9778b0c..d26f6e7 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -2192,9 +2192,7 @@ fast_path_fill (pixman_implementation_t *imp, break; default: - return _pixman_implementation_fill ( - imp->delegate, bits, stride, bpp, x, y, width, height, xor); - break; + return FALSE; } return TRUE; diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index dcf9bfc..6c6bda0 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -200,20 +200,6 @@ static const pixman_fast_path_t general_fast_path[] = { PIXMAN_OP_NONE } }; -static pixman_bool_t -general_fill (pixman_implementation_t *imp, - uint32_t * bits, - int stride, - int bpp, - int x, - int y, - int width, - int height, - uint32_t xor) -{ -return FALSE; -} - pixman_implementation_t * _pixman_implementation_create_general (void) { @@ -222,7 +208,6 @@ _pixman_implementation_create_general (void) _pixman_setup_combiner_functions_32 (imp); _pixman_setup_combiner_functions_64 (imp); -imp->fill = general_fill; imp->src_iter_init = general_src_iter_init; imp->dest_iter_init = general_dest_iter_init; diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 8b07848..5607f9d 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -27,21 +27,6 @@ #include #include "pixman-private.h" -static pixman_bool_t -delegate_fill (pixman_implementation_t *imp, - uint32_t * bits, - int stride, - int
[Pixman] [PATCH 4/7] Move delegation of src/dest iter init into pixman-implementation.c
From: Søren Sandmann Pedersen Instead of relying on each implementation to delegate when an iterator can't be initialized, change the type of iterator initializers to boolean and make pixman-implementation.c do the delegation whenever an iterator initializer returns FALSE. --- pixman/pixman-general.c| 10 +++- pixman/pixman-implementation.c | 42 --- pixman/pixman-mmx.c|6 ++-- pixman/pixman-noop.c | 14 pixman/pixman-private.h|8 +++--- pixman/pixman-sse2.c |6 ++-- 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index 6c6bda0..42a84a0 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -37,7 +37,7 @@ #include #include "pixman-private.h" -static void +static pixman_bool_t general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; @@ -54,18 +54,24 @@ general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) _pixman_bits_image_src_iter_init (image, iter); else _pixman_log_error (FUNC, "Pixman bug: unknown image type\n"); + +return TRUE; } -static void +static pixman_bool_t general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { if (iter->image->type == BITS) { _pixman_bits_image_dest_iter_init (iter->image, iter); + + return TRUE; } else { _pixman_log_error (FUNC, "Trying to write to a non-writable image"); + + return FALSE; } } diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 5607f9d..18da162 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -27,20 +27,6 @@ #include #include "pixman-private.h" -static void -delegate_src_iter_init (pixman_implementation_t *imp, - pixman_iter_t * iter) -{ -imp->delegate->src_iter_init (imp->delegate, iter); -} - -static void -delegate_dest_iter_init (pixman_implementation_t *imp, -pixman_iter_t * iter) -{ -imp->delegate->dest_iter_init (imp->delegate, iter); -} - pixman_implementation_t * _pixman_implementation_create (pixman_implementation_t *delegate, const pixman_fast_path_t *fast_paths) @@ -63,8 +49,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate, */ imp->blt = NULL; imp->fill = NULL; -imp->src_iter_init = delegate_src_iter_init; -imp->dest_iter_init = delegate_dest_iter_init; +imp->src_iter_init = NULL; +imp->dest_iter_init = NULL; imp->fast_paths = fast_paths; @@ -173,7 +159,7 @@ _pixman_implementation_fill (pixman_implementation_t *imp, return FALSE; } -void +pixman_bool_t _pixman_implementation_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter, pixman_image_t*image, @@ -194,10 +180,18 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, iter->iter_flags = iter_flags; iter->image_flags = image_flags; -(*imp->src_iter_init) (imp, iter); +while (imp) +{ + if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter)) + return TRUE; + + imp = imp->delegate; +} + +return FALSE; } -void +pixman_bool_t _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t*iter, pixman_image_t *image, @@ -218,7 +212,15 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, iter->iter_flags = iter_flags; iter->image_flags = image_flags; -(*imp->dest_iter_init) (imp, iter); +while (imp) +{ + if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter)) + return TRUE; + + imp = imp->delegate; +} + +return FALSE; } pixman_bool_t diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index 5deb9a4..c02595d 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -3914,7 +3914,7 @@ static const fetcher_info_t fetchers[] = { PIXMAN_null } }; -static void +static pixman_bool_t mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; @@ -3939,12 +3939,12 @@ mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) iter->stride = s; iter->get_scanline = f->get_scanline; - return; + return TRUE; } } } -imp->delegate->src_iter_
[Pixman] [PATCH 5/7] Rename _pixman_lookup_composite_function() to _pixman_implementation_lookup_composite()
From: Søren Sandmann Pedersen And move it into pixman-implementation.c which is where it belongs logically. --- pixman/pixman-fast-path.c |2 +- pixman/pixman-glyph.c |4 +- pixman/pixman-implementation.c | 112 pixman/pixman-private.h| 24 pixman/pixman-utils.c | 112 pixman/pixman.c|2 +- 6 files changed, 128 insertions(+), 128 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index d26f6e7..83c317f 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1258,7 +1258,7 @@ fast_composite_tiled_repeat (pixman_implementation_t *imp, mask_flags = FAST_PATH_IS_OPAQUE; } -if (_pixman_lookup_composite_function ( +if (_pixman_implementation_lookup_composite ( imp->toplevel, info->op, src_image->common.extended_format_code, src_flags, mask_format, mask_flags, diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c index cbc3637..30a4099 100644 --- a/pixman/pixman-glyph.c +++ b/pixman/pixman-glyph.c @@ -464,7 +464,7 @@ pixman_composite_glyphs_no_mask (pixman_op_top, glyph_format = glyph_img->common.extended_format_code; glyph_flags = glyph_img->common.flags; - _pixman_lookup_composite_function ( + _pixman_implementation_lookup_composite ( get_implementation(), op, src->common.extended_format_code, src->common.flags, glyph_format, glyph_flags | extra, @@ -576,7 +576,7 @@ add_glyphs (pixman_glyph_cache_t *cache, white_src = TRUE; } - _pixman_lookup_composite_function ( + _pixman_implementation_lookup_composite ( get_implementation(), PIXMAN_OP_ADD, src_format, info.src_flags, mask_format, info.mask_flags, diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 18da162..1da9d82 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -65,6 +65,118 @@ _pixman_implementation_create (pixman_implementation_t *delegate, return imp; } +#define N_CACHED_FAST_PATHS 8 + +typedef struct +{ +struct +{ + pixman_implementation_t * imp; + pixman_fast_path_t fast_path; +} cache [N_CACHED_FAST_PATHS]; +} cache_t; + +PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); + +pixman_bool_t +_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel, +pixman_op_t op, +pixman_format_code_t src_format, +uint32_t src_flags, +pixman_format_code_t mask_format, +uint32_t mask_flags, +pixman_format_code_t dest_format, +uint32_t dest_flags, +pixman_implementation_t **out_imp, +pixman_composite_func_t *out_func) +{ +pixman_implementation_t *imp; +cache_t *cache; +int i; + +/* Check cache for fast paths */ +cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); + +for (i = 0; i < N_CACHED_FAST_PATHS; ++i) +{ + const pixman_fast_path_t *info = &(cache->cache[i].fast_path); + + /* Note that we check for equality here, not whether +* the cached fast path matches. This is to prevent +* us from selecting an overly general fast path +* when a more specific one would work. +*/ + if (info->op == op && + info->src_format == src_format && + info->mask_format == mask_format&& + info->dest_format == dest_format&& + info->src_flags == src_flags&& + info->mask_flags == mask_flags && + info->dest_flags == dest_flags && + info->func) + { + *out_imp = cache->cache[i].imp; + *out_func = cache->cache[i].fast_path.func; + + goto update_cache; + } +} + +for (imp = toplevel; imp != NULL; imp = imp->delegate) +{ + const pixman_fast_path_t *info = imp->fast_paths; + + while (info->op != PIXMAN_OP_NONE) + { + if ((info->op == op || info->op == PIXMAN_OP_any) && + /* Formats */ + ((info->src_format == src_format) || +
[Pixman] [PATCH 6/7] _pixman_implementation_create(): Initialize implementation with memset()
From: Søren Sandmann Pedersen All the function pointers are NULL by default now, so we can just zero the struct. Also write the function a little more compactly. --- pixman/pixman-implementation.c | 35 +++ 1 files changed, 11 insertions(+), 24 deletions(-) diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index 1da9d82..f371172 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -31,35 +31,22 @@ pixman_implementation_t * _pixman_implementation_create (pixman_implementation_t *delegate, const pixman_fast_path_t *fast_paths) { -pixman_implementation_t *imp = malloc (sizeof (pixman_implementation_t)); -pixman_implementation_t *d; -int i; - -if (!imp) - return NULL; +pixman_implementation_t *imp; assert (fast_paths); -/* Make sure the whole delegate chain has the right toplevel */ -imp->delegate = delegate; -for (d = imp; d != NULL; d = d->delegate) - d->toplevel = imp; - -/* Fill out function pointers with ones that just delegate - */ -imp->blt = NULL; -imp->fill = NULL; -imp->src_iter_init = NULL; -imp->dest_iter_init = NULL; +if ((imp = malloc (sizeof (pixman_implementation_t +{ + pixman_implementation_t *d; -imp->fast_paths = fast_paths; + memset (imp, 0, sizeof *imp); -for (i = 0; i < PIXMAN_N_OPERATORS; ++i) -{ - imp->combine_32[i] = NULL; - imp->combine_64[i] = NULL; - imp->combine_32_ca[i] = NULL; - imp->combine_64_ca[i] = NULL; + imp->delegate = delegate; + imp->fast_paths = fast_paths; + + /* Make sure the whole delegate chain has the right toplevel */ + for (d = imp; d != NULL; d = d->delegate) + d->toplevel = imp; } return imp; -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 7/7] implementation: Rename delegate to fallback
From: Søren Sandmann Pedersen At this point the chain of implementations has nothing to do with the delegation design pattern anymore, so rename the delegate pointer to 'fallback'. --- pixman/pixman-implementation.c | 20 ++-- pixman/pixman-private.h|4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index f371172..5dd0501 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -28,7 +28,7 @@ #include "pixman-private.h" pixman_implementation_t * -_pixman_implementation_create (pixman_implementation_t *delegate, +_pixman_implementation_create (pixman_implementation_t *fallback, const pixman_fast_path_t *fast_paths) { pixman_implementation_t *imp; @@ -41,11 +41,11 @@ _pixman_implementation_create (pixman_implementation_t *delegate, memset (imp, 0, sizeof *imp); - imp->delegate = delegate; + imp->fallback = fallback; imp->fast_paths = fast_paths; - /* Make sure the whole delegate chain has the right toplevel */ - for (d = imp; d != NULL; d = d->delegate) + /* Make sure the whole fallback chain has the right toplevel */ + for (d = imp; d != NULL; d = d->fallback) d->toplevel = imp; } @@ -109,7 +109,7 @@ _pixman_implementation_lookup_composite (pixman_implementation_t *toplevel, } } -for (imp = toplevel; imp != NULL; imp = imp->delegate) +for (imp = toplevel; imp != NULL; imp = imp->fallback) { const pixman_fast_path_t *info = imp->fast_paths; @@ -196,7 +196,7 @@ _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, if (f) return f; - imp = imp->delegate; + imp = imp->fallback; } return NULL; @@ -227,7 +227,7 @@ _pixman_implementation_blt (pixman_implementation_t * imp, return TRUE; } - imp = imp->delegate; + imp = imp->fallback; } return FALSE; @@ -252,7 +252,7 @@ _pixman_implementation_fill (pixman_implementation_t *imp, return TRUE; } - imp = imp->delegate; + imp = imp->fallback; } return FALSE; @@ -284,7 +284,7 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter)) return TRUE; - imp = imp->delegate; + imp = imp->fallback; } return FALSE; @@ -316,7 +316,7 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter)) return TRUE; - imp = imp->delegate; + imp = imp->fallback; } return FALSE; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index e671508..b9c8319 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -466,7 +466,7 @@ typedef struct struct pixman_implementation_t { pixman_implementation_t * toplevel; -pixman_implementation_t * delegate; +pixman_implementation_t * fallback; const pixman_fast_path_t * fast_paths; pixman_blt_func_t blt; @@ -486,7 +486,7 @@ _pixman_image_get_solid (pixman_implementation_t *imp, pixman_format_code_t format); pixman_implementation_t * -_pixman_implementation_create (pixman_implementation_t *delegate, +_pixman_implementation_create (pixman_implementation_t *fallback, const pixman_fast_path_t *fast_paths); pixman_bool_t -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] build: Support building Loongson code for 2e, 2f, 3a
Matt Turner writes: > pixman/Makefile.am contains a hack that allows pixman-mmx.c to > be compiled with different overriding CFLAGS, since automake > seriously doesn't have a way to do this. Seriously stupid. > > It works by defining a new rule and recursively calling make > with modified CFLAGS set. > > Note the difference between the USE_LOONGSON* and HAVE_LOONGSON* > preprocessor macros. > > Cc: Cyril Brulebois > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51451 > --- > This patch applies on top of the previous. The DEP patch looks good to me. Apparently the "DEP" stuff was present in the first check-in but never used. > Although the build system works, linking unfortunately doesn't. gcc > refuses to link object files that have been compiled with different > -march=loongson* options together. This sucks. > > I'm not sure what to do. I guess I could make them separate shared > objects or even dlopen them, but that really sucks, especially when > I don't see a reason why gcc shouldn't be able to link this code > together. > > Anyone have any other ideas? If the shared library thing works, I'm fine with it. Another idea is to use some objcopy or elfedit hack where the binary files are edited to have the same architecture. That's not exactly beautiful either, though. > It's really obnoxious that there's not just a simple -mloongson-mmi > flag irrespective of -march=... This probably just have to be fixed in GCC or the linker. We have a similar obnoxiousness in x86 where the -mmmx/-msse flags mean two separate things at the same time: "the compiler may generate mmx/sse instructions" and "the files may use mmx/sse intrinsics". But at least the linker doesn't refuse to link files compiled with different such flags. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Fix bugs in component alpha combiners for separable PDF operators
From: Søren Sandmann Pedersen In general, the component alpha version of an operator is supposed to do this: - multiply source with mask in all channels - multiply mask with source alpha in all channels - compute the regular operator in all channels using the mask value whenever source alpha is called for The first two steps are usually accomplished with the function combine_mask_ca(), but for operators where source alpha is not used, such as SRC, ADD and OUT, the simpler function combine_mask_value_ca(), which doesn't compute the new mask values, can be used. However, the PDF blend modes generally *do* make use of source alpha, so they can't use combine_mask_value_ca() as they do now. They have to use combine_mask_ca(). This patch fixes this in combine_multiply_ca() and the CA combiners generated by PDF_SEPARABLE_BLEND_MODE. --- pixman/pixman-combine.c.template |4 ++-- test/blitters-test.c |2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template index cd008d9..50d2b0a 100644 --- a/pixman/pixman-combine.c.template +++ b/pixman/pixman-combine.c.template @@ -489,7 +489,7 @@ combine_multiply_ca (pixman_implementation_t *imp, comp4_t r = d; comp4_t dest_ia = ALPHA_c (~d); - combine_mask_value_ca (&s, &m); + combine_mask_ca (&s, &m); UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (r, ~m, s, dest_ia); UNcx4_MUL_UNcx4 (d, s); @@ -546,7 +546,7 @@ combine_multiply_ca (pixman_implementation_t *imp, comp1_t ida = ~da; \ comp4_t result; \ \ - combine_mask_value_ca (&s, &m); \ + combine_mask_ca (&s, &m); \ \ result = d; \ UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \ diff --git a/test/blitters-test.c b/test/blitters-test.c index 6a3cc86..8c46cef 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -395,6 +395,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 200, - 0xA364B5BF, + 0x3E1DD2E8, test_composite, argc, argv); } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] Fix bug in fast_composite_scaled_nearest()
From: Søren Sandmann Pedersen The fast_composite_scaled_nearest() function can be called when the format is x8b8g8r8. In that case pixels fetched in fetch_nearest() need to have their alpha channel set to 0xff. Fixes test suite failure in scaling-test. --- pixman/pixman-fast-path.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 9778b0c..53fc784 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1458,7 +1458,7 @@ fetch_nearest (pixman_repeat_t src_repeat, { if (repeat (src_repeat, &x, src_width)) { - if (format == PIXMAN_x8r8g8b8) + if (format == PIXMAN_x8r8g8b8 || format == PIXMAN_x8b8g8r8) return *(src + x) | 0xff00; else return *(src + x); -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/2] Add PIXMAN_x8b8g8r8 and PIXMAN_a8b8g8r8 formats to scaling-test
From: Søren Sandmann Pedersen Update the CRC values based on what the general implementation reports. This reveals a bug in the fast implementation: % env PIXMAN_DISABLE="mmx sse2" ./test/scaling-test pixman: Disabled mmx implementation pixman: Disabled sse2 implementation scaling test failed! (checksum=AA722B06, expected 03A23E0C) vs. % env PIXMAN_DISABLE="mmx sse2 fast" ./test/scaling-test pixman: Disabled fast implementation pixman: Disabled mmx implementation pixman: Disabled sse2 implementation scaling test passed (checksum=03A23E0C) --- test/scaling-test.c | 40 +++- 1 files changed, 31 insertions(+), 9 deletions(-) diff --git a/test/scaling-test.c b/test/scaling-test.c index 44c4f3d..2736123 100644 --- a/test/scaling-test.c +++ b/test/scaling-test.c @@ -20,6 +20,31 @@ /* * Composite operation with pseudorandom images */ + +static pixman_format_code_t +get_format (int bpp) +{ +if (bpp == 4) +{ + switch (lcg_rand_n (4)) + { + default: + case 0: + return PIXMAN_a8r8g8b8; + case 1: + return PIXMAN_x8r8g8b8; + case 2: + return PIXMAN_a8b8g8r8; + case 3: + return PIXMAN_x8b8g8r8; + } +} +else +{ + return PIXMAN_r5g6b5; +} +} + uint32_t test_composite (int testnum, int verbose) @@ -124,11 +149,8 @@ test_composite (int testnum, 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_fmt = get_format (src_bpp); +dst_fmt = get_format (dst_bpp); src_img = pixman_image_create_bits ( src_fmt, src_width, src_height, srcbuf, src_stride); @@ -322,7 +344,7 @@ test_composite (int testnum, pixman_image_composite (op, src_img, mask_img, dst_img, src_x, src_y, mask_x, mask_y, dst_x, dst_y, w, h); -if (dst_fmt == PIXMAN_x8r8g8b8) +if (dst_fmt == PIXMAN_x8r8g8b8 || dst_fmt == PIXMAN_x8b8g8r8) { /* ignore unused part */ for (i = 0; i < dst_stride * dst_height / 4; i++) @@ -358,11 +380,11 @@ test_composite (int testnum, } #if BILINEAR_INTERPOLATION_BITS == 8 -#define CHECKSUM 0x80DF1CB2 +#define CHECKSUM 0x8D3A7539 #elif BILINEAR_INTERPOLATION_BITS == 7 -#define CHECKSUM 0x2818D5FB +#define CHECKSUM 0x03A23E0C #elif BILINEAR_INTERPOLATION_BITS == 4 -#define CHECKSUM 0x387540A5 +#define CHECKSUM 0xE96D1A5E #else #define CHECKSUM 0x #endif -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/2] Add rotate-test.c test program
From: Søren Sandmann Pedersen This program exercises a bug in pixman-image.c where "-1" and "1" were used instead of the correct "- pixman_fixed_1" and "pixman_fixed_1". With the fast implementation enabled: % ./rotate-test rotate test failed! (checksum=672ED720, expected 721947E4) Without it: % env PIXMAN_DISABLE=fast ./rotate-test pixman: Disabled fast implementation rotate test passed (checksum=721947E4) --- test/Makefile.sources |1 + test/rotate-test.c| 112 + 2 files changed, 113 insertions(+), 0 deletions(-) create mode 100644 test/rotate-test.c diff --git a/test/Makefile.sources b/test/Makefile.sources index fad8c6f..3e37e32 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -5,6 +5,7 @@ TESTPROGRAMS = \ region-test \ region-translate-test \ fetch-test \ + rotate-test \ oob-test\ trap-crasher\ alpha-loop \ diff --git a/test/rotate-test.c b/test/rotate-test.c new file mode 100644 index 000..dabdf8e --- /dev/null +++ b/test/rotate-test.c @@ -0,0 +1,112 @@ +#include +#include "utils.h" + +#define WIDTH 32 +#define HEIGHT 32 + +static const pixman_format_code_t formats[] = +{ +PIXMAN_a8r8g8b8, +PIXMAN_a8b8g8r8, +PIXMAN_x8r8g8b8, +PIXMAN_x8b8g8r8, +PIXMAN_r5g6b5, +PIXMAN_b5g6r5, +PIXMAN_a8, +PIXMAN_a1, +}; + +static const pixman_op_t ops[] = +{ +PIXMAN_OP_OVER, +PIXMAN_OP_SRC, +PIXMAN_OP_ADD, +}; + +#define TRANSFORM(v00, v01, v10, v11) \ +{ { { v00, v01, WIDTH * pixman_fixed_1 / 2 }, \ + { v10, v11, HEIGHT * pixman_fixed_1 / 2 }, \ + { 0, 0, pixman_fixed_1 } } } + +#define F1 pixman_fixed_1 + +static const pixman_transform_t transforms[] = +{ +TRANSFORM (0, -1, 1, 0), /* wrong 90 degree rotation */ +TRANSFORM (0, 1, -1, 0), /* wrong 270 degree rotation */ +TRANSFORM (1, 0, 0, 1),/* wrong identity */ +TRANSFORM (-1, 0, 0, -1), /* wrong 180 degree rotation */ +TRANSFORM (0, -F1, F1, 0), /* correct 90 degree rotation */ +TRANSFORM (0, F1, -F1, 0), /* correct 270 degree rotation */ +TRANSFORM (F1, 0, 0, F1), /* correct identity */ +TRANSFORM (-F1, 0, 0, -F1),/* correct 180 degree rotation */ +}; + +#define RANDOM_FORMAT() \ +(formats[lcg_rand_n (ARRAY_LENGTH (formats))]) + +#define RANDOM_OP()\ +(ops[lcg_rand_n (ARRAY_LENGTH (ops))]) + +#define RANDOM_TRANSFORM() \ +(&(transforms[lcg_rand_n (ARRAY_LENGTH (transforms))])) + +static void +on_destroy (pixman_image_t *image, void *data) +{ +free (data); +} + +static pixman_image_t * +make_image (void) +{ +pixman_format_code_t format = RANDOM_FORMAT(); +uint32_t *bytes = malloc (WIDTH * HEIGHT * 4); +pixman_image_t *image; +int i; + +for (i = 0; i < WIDTH * HEIGHT * 4; ++i) + ((uint8_t *)bytes)[i] = lcg_rand_n (256); + +image = pixman_image_create_bits ( + format, WIDTH, HEIGHT, bytes, WIDTH * 4); + +pixman_image_set_transform (image, RANDOM_TRANSFORM()); +pixman_image_set_destroy_function (image, on_destroy, bytes); +pixman_image_set_repeat (image, PIXMAN_REPEAT_NORMAL); + +return image; +} + +static uint32_t +test_transform (int testnum, int verbose) +{ +pixman_image_t *src, *dest, *mask; +uint32_t crc; + +src = make_image (); +mask = NULL; // lcg_rand_n (2) ? NULL : make_image(); +dest = make_image (); + +pixman_image_composite (RANDOM_OP(), + src, mask, dest, + 0, 0, 0, 0, WIDTH / 2, HEIGHT / 2, + WIDTH, HEIGHT); + +crc = compute_crc32_for_image (0, dest); + +pixman_image_unref (src); +if (mask) + pixman_image_unref (mask); +pixman_image_unref (dest); + +return crc; +} + +int +main (int argc, const char *argv[]) +{ +return fuzzer_test_main ("rotate", 15000, +0x721947E4, +test_transform, argc, argv); +} -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] Fix bugs in pixman-image.c
From: Søren Sandmann Pedersen In the checks for whether the transforms are rotation matrices "-1" and "1" were used instead of the correct -pixman_fixed_1 and pixman_fixed_1. Fixes test suite failure for rotate-test. --- pixman/pixman-image.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 15597bd..d9c3034 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -301,9 +301,9 @@ compute_image_info (pixman_image_t *image) pixman_fixed_t m01 = image->common.transform->matrix[0][1]; pixman_fixed_t m10 = image->common.transform->matrix[1][0]; - if (m01 == -1 && m10 == 1) + if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1) flags |= FAST_PATH_ROTATE_90_TRANSFORM; - else if (m01 == 1 && m10 == -1) + else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1) flags |= FAST_PATH_ROTATE_270_TRANSFORM; } } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] pixman-combine.c.template: Formatting clean-ups
From: Søren Sandmann Pedersen Various formatting fixes, and removal of some obsolete comments about strength reduction of operators. --- pixman/pixman-combine.c.template | 38 +++--- 1 files changed, 7 insertions(+), 31 deletions(-) diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template index 50d2b0a..f405312 100644 --- a/pixman/pixman-combine.c.template +++ b/pixman/pixman-combine.c.template @@ -6,10 +6,9 @@ #include #include "pixman-private.h" - #include "pixman-combine.h" -/*** per channel helper functions ***/ +/* component alpha helper functions */ static void combine_mask_ca (comp4_t *src, comp4_t *mask) @@ -91,15 +90,11 @@ combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask) /* * There are two ways of handling alpha -- either as a single unified value or * a separate value for each component, hence each macro must have two - * versions. The unified alpha version has a 'U' at the end of the name, - * the component version has a 'C'. Similarly, functions which deal with + * versions. The unified alpha version has a 'u' at the end of the name, + * the component version has a 'ca'. Similarly, functions which deal with * this difference will have two versions using the same convention. */ -/* - * All of the composing functions - */ - static force_inline comp4_t combine_mask (const comp4_t *src, const comp4_t *mask, int i) { @@ -154,7 +149,9 @@ combine_src_u (pixman_implementation_t *imp, int i; if (!mask) +{ memcpy (dest, src, width * sizeof (comp4_t)); +} else { for (i = 0; i < width; ++i) @@ -166,7 +163,6 @@ combine_src_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_src_u */ static void combine_over_u (pixman_implementation_t *imp, pixman_op_t op, @@ -188,7 +184,6 @@ combine_over_u (pixman_implementation_t *imp, } } -/* if the Dst is opaque, this is a noop */ static void combine_over_reverse_u (pixman_implementation_t *imp, pixman_op_t op, @@ -209,7 +204,6 @@ combine_over_reverse_u (pixman_implementation_t *imp, } } -/* if the Dst is opaque, call combine_src_u */ static void combine_in_u (pixman_implementation_t *imp, pixman_op_t op, @@ -229,7 +223,6 @@ combine_in_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, this is a noop */ static void combine_in_reverse_u (pixman_implementation_t *imp, pixman_op_t op, @@ -250,7 +243,6 @@ combine_in_reverse_u (pixman_implementation_t *imp, } } -/* if the Dst is opaque, call combine_clear */ static void combine_out_u (pixman_implementation_t *imp, pixman_op_t op, @@ -270,7 +262,6 @@ combine_out_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_clear */ static void combine_out_reverse_u (pixman_implementation_t *imp, pixman_op_t op, @@ -291,9 +282,6 @@ combine_out_reverse_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_in_u */ -/* if the Dst is opaque, call combine_over_u */ -/* if both the Src and Dst are opaque, call combine_src_u */ static void combine_atop_u (pixman_implementation_t *imp, pixman_op_t op, @@ -316,9 +304,6 @@ combine_atop_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_over_reverse_u */ -/* if the Dst is opaque, call combine_in_reverse_u */ -/* if both the Src and Dst are opaque, call combine_dst_u */ static void combine_atop_reverse_u (pixman_implementation_t *imp, pixman_op_t op, @@ -341,9 +326,6 @@ combine_atop_reverse_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_over_u */ -/* if the Dst is opaque, call combine_over_reverse_u */ -/* if both the Src and Dst are opaque, call combine_clear */ static void combine_xor_u (pixman_implementation_t *imp, pixman_op_t op, @@ -385,9 +367,6 @@ combine_add_u (pixman_implementation_t *imp, } } -/* if the Src is opaque, call combine_add_u */ -/* if the Dst is opaque, call combine_add_u */ -/* if both the Src and Dst are opaque, call combine_add_u */ static void combine_saturate_u (pixman_implementation_t *imp, pixman_op_t op, @@ -444,7 +423,6 @@ combine_saturate_u (pixman_implementation_t *imp, * Multiply * B(Dca, ad, Sca, as) = Dca.Sca */ - static void combine_multiply_u (pixman_implementation_t *imp, pixman_op_t op, @@ -1579,9 +1557,8 @@ combine_conjoint_xor_u (pixman_implementation_t *imp,
Re: [Pixman] More MIPS OVER fast paths (over_8888_n_8888, over_8888_n_0565, over_0565_n_0565, over_8888_8_8888, over_8888_8_0565, over_0565_8_0565, over_8888_8888 and over_8888_8888_8888) including OV
Nemanja Lukic writes: > Added optimizations for several OVER fast paths: > - over__n_ > - over__n_0565 > - over_0565_n_0565 > - over__8_ > - over__8_0565 > - over_0565_8_0565 > - over__ > - over___ > Including OVER combiner. > Per previous code review: > - Previously pushed single big commit is now divided into 4 smaller pieces. Thanks for the patches. I have pushed them to master with a few formatting fixes. However, you should get a freedesktop account so that you can push patches yourself, or at least, if you want me to merge them, provide a public git repository that can be pulled from. > - Added OVER combiner. Did you do any measurements of this one? As Siarhei said: As for the performance numbers. I wonder how much faster would these new specialized MIPS fast paths be if we had a DSPr2 optimized OVER combiner? You can check "sse2_combine_over_u" and "neon_combine_over_u" functions as examples of existing combiners. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/10] Floating point pipeline again
Hi, Here is a new version of the floating point patches. The main changes since last time are: (a) It is now explicit that the only guarantee wrt. floating point exceptions is that divide-by-zero is not generated. So if an application enables for example FP_INVALID, it may crash. It can safely enablE FP_DIVBYZERO though. (b) pixman_expand_to_float() is faster. The first version was written in a way that caused gcc to generate divisions in the inner loop. The new version avoids that. Below are the results of some benchmark runs. From top to bottom: - Regular, unmodified pixman - With all compositing going through the current 16 bpc wide path - With all compositign going through the new floating point wide path There is a performance hit for the wide path, but it's not that big, especially not compared to the performance vs. unmodified pixman. Soren == [ 0]imageevolution3.8613.905 0.57%2/2 [ 0]imageevolution 12.292 12.322 0.12%2/2 [ 0]imageevolution 12.758 12.790 0.13%2/2 == [ 1]imagefirefox-asteroids 15.279 15.387 0.35%2/2 [ 1]imagefirefox-asteroids 132.169 132.583 0.16%2/2 [ 1]imagefirefox-asteroids 153.967 154.097 0.04%2/2 == [ 2]image firefox-canvas-alpha 117.215 117.576 0.15%2/2 [ 2]image firefox-canvas-alpha 520.440 520.931 0.05%2/2 [ 2]image firefox-canvas-alpha 612.296 613.220 0.08%2/2 == [ 3]image firefox-canvas 70.088 70.348 0.18%2/2 [ 3]image firefox-canvas 195.548 195.887 0.09%2/2 [ 3]image firefox-canvas 214.703 214.998 0.07%2/2 == [ 4]image firefox-fishbowl 328.958 329.090 0.02%2/2 [ 4]image firefox-fishbowl 1000.298 1000.555 0.01%2/2 [ 4]image firefox-fishbowl 1133.374 1134.628 0.06%2/2 == [ 5]image firefox-fishtank 177.031 177.075 0.01%2/2 [ 5]image firefox-fishtank 1285.495 1286.696 0.05%2/2 [ 5]image firefox-fishtank 1416.589 1421.419 0.17%2/2 == [ 6]imagefirefox-paintball 244.934 245.251 0.06%2/2 [ 6]imagefirefox-paintball 1906.528 1907.546 0.03%2/2 [ 6]imagefirefox-paintball 2186.297 2187.079 0.02%2/2 == [ 7]imagefirefox-particles 147.026 147.423 0.13%2/2 [ 0]imagefirefox-particles 560.488 560.974 0.04%2/2 [ 7]imagefirefox-particles 634.497 635.891 0.11%2/2 == [ 8]image firefox-planet-gnome 21.534 21.562 0.06%2/2 [ 1]image firefox-planet-gnome 91.861 92.053 0.10%2/2 [ 8]image firefox-planet-gnome 112.708 112.852 0.06%2/2 == [ 9]imagefirefox-talos-gfx 18.107 18.171 0.18%2/2 [ 2]imagefirefox-talos-gfx 104.107 104.116 0.00%2/2 [ 9]imagefirefox-talos-gfx 113.000 113.301 0.13%2/2 == [ 10]imagefirefox-talos-svg 90.002 90.067 0.04%2/2 [ 3]imagefirefox-talos-svg 164.665 164.715 0.02%2/2 [ 10]imagefirefox-talos-svg 190.393 191.722 0.35%2/2 == [ 11]image gnome-system-monitor6.9906.994 0.03%2/2 [ 4]image gnome-system-monitor 38.850 38.880 0.04%2/2 [ 11]image gnome-system-monitor 63.256 63.275 0.02%2/2 == [ 12]image gnome-terminal-vim9.3599.512 0.81%2/2 [ 5]image gnome-terminal-vim 23.560 23.575 0.03%2/2 [ 12]image gnome-terminal-vim 23.928 24.062 0.28%2/2 == [ 13]image grads-heat-map0.4490.456 0.80%2/2 [ 6]image grads-heat-map0.4550.463 0.88%2/2 [ 13]image grads-heat-map0.4670.491 2.56%2/2 == [ 14]image gvim5.49
[Pixman] [PATCH 01/10] glyph-test: Prepare for floating point
From: Søren Sandmann Pedersen In preparation for an upcoming change of the wide pipe to use floating point, comment out some formats in glyph-test that are going to be using floating point, and update the CRC32 value to match. --- test/glyph-test.c |7 +-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/glyph-test.c b/test/glyph-test.c index 84de5aa..9dd5b41 100644 --- a/test/glyph-test.c +++ b/test/glyph-test.c @@ -30,10 +30,13 @@ static const pixman_format_code_t formats[] = PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, +#if 0 +/* These use floating point */ PIXMAN_x2r10g10b10, PIXMAN_a2r10g10b10, PIXMAN_x2b10g10r10, PIXMAN_a2b10g10r10, +#endif PIXMAN_a1r5g5b5, PIXMAN_x1r5g5b5, PIXMAN_a1b5g5r5, @@ -329,7 +332,7 @@ test_glyphs (int testnum, int verbose) int main (int argc, const char *argv[]) { -return fuzzer_test_main ("glyph", 3, -0x741CB2DB, +return fuzzer_test_main ("glyph", 3, +0x79E74996, test_glyphs, argc, argv); } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 02/10] blitters-test: Prepare for floating point
From: Søren Sandmann Pedersen Comment out some formats in blitters-test that are going to rely on floating point in the upcoming patches. --- test/blitters-test.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/test/blitters-test.c b/test/blitters-test.c index 8c46cef..30d6912 100644 --- a/test/blitters-test.c +++ b/test/blitters-test.c @@ -172,10 +172,12 @@ static pixman_format_code_t img_fmt_list[] = { PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, +#if 0 /* These are going to use floating point in the near future */ PIXMAN_x2r10g10b10, PIXMAN_a2r10g10b10, PIXMAN_x2b10g10r10, PIXMAN_a2b10g10r10, +#endif PIXMAN_a1r5g5b5, PIXMAN_x1r5g5b5, PIXMAN_a1b5g5r5, @@ -395,6 +397,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 200, - 0x3E1DD2E8, + 0x46136E0A, test_composite, argc, argv); } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 03/10] Add pixman-combine-float.c
From: Søren Sandmann Pedersen This file contains floating point implementations of combiners for all pixman operators. These combiners operate on buffers containing single precision floating point pixels stored in (a, r, g, b) order in memory. The combiners are added to the pixman_implementation_t struct, but nothing uses them yet. This commit incorporates a number of bug fixes contributed by Andrea Canciani. Some notes: - The combiners are making sure to never divide by zero regardless of input, so an application could enable divide-by-zero exceptions and pixman wouldn't generate any. - The operators are implemented according to the Render spec. Ie., - If the input pixels are between 0 and 1, then so is the output. - The source and destination coefficients for the conjoint and disjoint operators are clamped to [0, 1]. - The PDF operators are not described in the render spec, and the implementation here doesn't do any clamping except in the final conversion from floating point to destination format. All of the above will need to be rethought if we add support for pixel formats that can support negative and greater-than-one pixels. It is in fact already the case in principle that convolution filters can produce pixels with negative values, but since these go through the broken "wide" path that narrows everything to 32 bits, these negative values don't currently survive to the combiners. --- pixman/Makefile.sources |1 + pixman/pixman-combine-float.c | 1003 + pixman/pixman-general.c |1 + pixman/pixman-private.h | 10 + 4 files changed, 1015 insertions(+), 0 deletions(-) create mode 100644 pixman/pixman-combine-float.c diff --git a/pixman/Makefile.sources b/pixman/Makefile.sources index cf7040f..96540ec 100644 --- a/pixman/Makefile.sources +++ b/pixman/Makefile.sources @@ -5,6 +5,7 @@ libpixman_sources = \ pixman-bits-image.c \ pixman-combine32.c \ pixman-combine64.c \ + pixman-combine-float.c \ pixman-conical-gradient.c \ pixman-x86.c\ pixman-mips.c \ diff --git a/pixman/pixman-combine-float.c b/pixman/pixman-combine-float.c new file mode 100644 index 000..7bf5b5a --- /dev/null +++ b/pixman/pixman-combine-float.c @@ -0,0 +1,1003 @@ +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ +/* + * Copyright © 2010, 2012 Soren Sandmann Pedersen + * Copyright © 2010, 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann Pedersen (sandm...@cs.au.dk) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "pixman-private.h" + +typedef float (* combine_channel_t) (float sa, float s, float da, float d); + +static force_inline void +combine_inner (pixman_bool_t component, + float *dest, const float *src, const float *mask, int n_pixels, + combine_channel_t combine_a, combine_channel_t combine_c) +{ +int i; + +if (!mask) +{ + for (i = 0; i < 4 * n_pixels; i += 4) + { + float sa = src[i + 0]; + float sr = src[i + 1]; + float sg = src[i + 2]; + float sb = src[i + 3]; + + float da = dest[i + 0]; + float dr = dest[i + 1]; + float dg = dest[i + 2]; + float db = dest[i + 3]; + + dest[i + 0] = combine_a (sa, sa, da, da); + dest[i + 1] = combine_c (sa, sr, da, dr); + dest[i + 2] = combine_c (sa, sg, da, dg); + dest[i + 3] = combine_c (sa, sb, da, db); + } +} +else +{ + for (i = 0; i <
[Pixman] [PATCH 04/10] Add combiner test
From: Søren Sandmann Pedersen This test runs the new floating point combiners on random input with divide-by-zero exceptions turned on. With the floating point combiners the only thing we guarantee is that divide-by-zero exceptions are not generated, so change enable_fp_exceptions() to only enable those, and rename accordingly. --- demos/radial-test.c|2 +- pixman/pixman-private.h|6 ++ pixman/pixman-utils.c |9 +++ test/Makefile.sources |1 + test/combiner-test.c | 151 test/gradient-crash-test.c |2 +- test/pdf-op-test.c |2 +- test/stress-test.c |2 +- test/utils.c | 14 + test/utils.h |2 +- 10 files changed, 174 insertions(+), 17 deletions(-) create mode 100644 test/combiner-test.c diff --git a/demos/radial-test.c b/demos/radial-test.c index 35e90d7..e64f357 100644 --- a/demos/radial-test.c +++ b/demos/radial-test.c @@ -133,7 +133,7 @@ main (int argc, char **argv) pixman_image_t *src_img, *dest_img; int i, j; -enable_fp_exceptions (); +enable_divbyzero_exceptions (); dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 949d384..c82316f 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -764,6 +764,12 @@ get_implementation (void) return global_implementation; } +/* This function is exported for the sake of the test suite and not part + * of the ABI. + */ +PIXMAN_EXPORT pixman_implementation_t * +_pixman_internal_only_get_implementation (void); + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index 5633f8f..e4a9730 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -262,6 +262,15 @@ pixman_region32_copy_from_region16 (pixman_region32_t *dst, return retval; } +/* This function is exported for the sake of the test suite and not part + * of the ABI. + */ +PIXMAN_EXPORT pixman_implementation_t * +_pixman_internal_only_get_implementation (void) +{ +return get_implementation (); +} + #ifdef DEBUG void diff --git a/test/Makefile.sources b/test/Makefile.sources index 0f34411..0778971 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -4,6 +4,7 @@ TESTPROGRAMS = \ pdf-op-test \ region-test \ region-translate-test \ + combiner-test \ fetch-test \ rotate-test \ oob-test\ diff --git a/test/combiner-test.c b/test/combiner-test.c new file mode 100644 index 000..c438ae6 --- /dev/null +++ b/test/combiner-test.c @@ -0,0 +1,151 @@ +#include +#include +#include "utils.h" +#include +#include "pixman-private.h" + +static const pixman_op_t op_list[] = +{ +PIXMAN_OP_SRC, +PIXMAN_OP_OVER, +PIXMAN_OP_ADD, +PIXMAN_OP_CLEAR, +PIXMAN_OP_SRC, +PIXMAN_OP_DST, +PIXMAN_OP_OVER, +PIXMAN_OP_OVER_REVERSE, +PIXMAN_OP_IN, +PIXMAN_OP_IN_REVERSE, +PIXMAN_OP_OUT, +PIXMAN_OP_OUT_REVERSE, +PIXMAN_OP_ATOP, +PIXMAN_OP_ATOP_REVERSE, +PIXMAN_OP_XOR, +PIXMAN_OP_ADD, +PIXMAN_OP_SATURATE, +PIXMAN_OP_DISJOINT_CLEAR, +PIXMAN_OP_DISJOINT_SRC, +PIXMAN_OP_DISJOINT_DST, +PIXMAN_OP_DISJOINT_OVER, +PIXMAN_OP_DISJOINT_OVER_REVERSE, +PIXMAN_OP_DISJOINT_IN, +PIXMAN_OP_DISJOINT_IN_REVERSE, +PIXMAN_OP_DISJOINT_OUT, +PIXMAN_OP_DISJOINT_OUT_REVERSE, +PIXMAN_OP_DISJOINT_ATOP, +PIXMAN_OP_DISJOINT_ATOP_REVERSE, +PIXMAN_OP_DISJOINT_XOR, +PIXMAN_OP_CONJOINT_CLEAR, +PIXMAN_OP_CONJOINT_SRC, +PIXMAN_OP_CONJOINT_DST, +PIXMAN_OP_CONJOINT_OVER, +PIXMAN_OP_CONJOINT_OVER_REVERSE, +PIXMAN_OP_CONJOINT_IN, +PIXMAN_OP_CONJOINT_IN_REVERSE, +PIXMAN_OP_CONJOINT_OUT, +PIXMAN_OP_CONJOINT_OUT_REVERSE, +PIXMAN_OP_CONJOINT_ATOP, +PIXMAN_OP_CONJOINT_ATOP_REVERSE, +PIXMAN_OP_CONJOINT_XOR, +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_DIFFERENCE, +PIXMAN_OP_EXCLUSION, +PIXMAN_OP_SOFT_LIGHT, +PIXMAN_OP_HSL_HUE, +PIXMAN_OP_HSL_SATURATION, +PIXMAN_OP_HSL_COLOR, +PIXMAN_OP_HSL_LUMINOSITY, +}; + +static float +rand_float (void) +{ +uint32_t u = lcg_rand_u32(); + +return *(float *)&u; +} + +static void +random_floats (argb_t *argb, int width) +{ +int i; + +for (i = 0; i < width; ++i) +{ + argb_t *p = argb + i; + + p->a = rand_float(); + p->r = rand_float(); + p->g = rand_float(); + p->b = rand_float(); +
[Pixman] [PATCH 05/10] pixman-utils.c, pixman-private.h: Add floating point conversion routines
From: Søren Sandmann Pedersen A new struct argb_t containing a floating point pixel is added to pixman-private.h, and conversion routines are added to pixman-utils.c to convert normalized integers to and from that struct. New functions: - pixman_expand_to_float() Expands a buffer of integer pixels to a buffer of argb_t pixels - pixman_contract_from_float() Converts a buffer of argb_t pixels to a buffer integer pixels - pixman_float_to_unorm() Converts a floating point number to an unsigned normalized integer - pixman_unorm_to_float() Converts an unsigned normalized integer to a floating point number --- pixman/pixman-private.h | 35 +++ pixman/pixman-utils.c | 107 +++ 2 files changed, 142 insertions(+), 0 deletions(-) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index c82316f..91f35ed 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -45,6 +45,16 @@ typedef struct radial_gradient radial_gradient_t; typedef struct bits_image bits_image_t; typedef struct circle circle_t; +typedef struct argb_t argb_t; + +struct argb_t +{ +float a; +float r; +float g; +float b; +}; + typedef void (*fetch_scanline_t) (pixman_image_t *image, int x, int y, @@ -792,12 +802,34 @@ pixman_expand (uint64_t * dst, const uint32_t * src, pixman_format_code_t format, int width); +void +pixman_expand_to_float (argb_t *dst, + const uint32_t *src, + pixman_format_code_t format, + int width); void pixman_contract (uint32_t * dst, const uint64_t *src, int width); +void +pixman_contract_from_float (uint32_t *dst, + const argb_t *src, + int width); + +pixman_bool_t +_pixman_lookup_composite_function (pixman_implementation_t *toplevel, + pixman_op_t op, + pixman_format_code_t src_format, + uint32_t src_flags, + pixman_format_code_t mask_format, + uint32_t mask_flags, + pixman_format_code_t dest_format, + uint32_t dest_flags, + pixman_implementation_t**out_imp, + pixman_composite_func_t *out_func); + /* Region Helpers */ pixman_bool_t pixman_region32_copy_from_region16 (pixman_region32_t *dst, @@ -957,6 +989,9 @@ unorm_to_unorm (uint32_t val, int from_bits, int to_bits) return result; } +uint16_t pixman_float_to_unorm (float f, int n_bits); +float pixman_unorm_to_float (uint16_t u, int n_bits); + /* * Various debugging code */ diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index e4a9730..4f9db29 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -162,6 +162,113 @@ pixman_expand (uint64_t * dst, } } +static force_inline uint16_t +float_to_unorm (float f, int n_bits) +{ +uint32_t u; + +if (f > 1.0) + f = 1.0; +if (f < 0.0) + f = 0.0; + +u = f * (1 << n_bits); +u -= (u >> n_bits); + +return u; +} + +static force_inline float +unorm_to_float (uint16_t u, int n_bits) +{ +uint32_t m = ((1 << n_bits) - 1); + +return (u & m) * (1.f / (float)m); +} + +/* + * This function expands images from a8r8g8b8 to argb_t. To preserve + * precision, it needs to know from which source format the a8r8g8b8 pixels + * originally came. + * + * For example, if the source was PIXMAN_x1r5g5b5 and the red component + * contained bits 12345, then the 8-bit value is 12345123. To correctly + * expand this to floating point, it should be 12345 / 31.0 and not + * 12345123 / 255.0. + */ +void +pixman_expand_to_float (argb_t *dst, + const uint32_t *src, + pixman_format_code_t format, + int width) +{ +int a_size, r_size, g_size, b_size; +int a_shift, r_shift, g_shift, b_shift; +int i; + +if (!PIXMAN_FORMAT_VIS (format)) + format = PIXMAN_a8r8g8b8; + +/* + * Determine the sizes of each component and the masks and shifts + * required to extract them from the source pixel. + */ +a_size = PIXMAN_FORMAT_A (format); +r_size = PIXMAN_FORMAT_R (format); +g_size = PIXMAN_FORMAT_G (format); +b_size = PIXMAN_FORMAT_B (format); + +a_shift = 32 - a_size
[Pixman] [PATCH 06/10] pixman-access.c: Add floating point accessor functions
From: Søren Sandmann Pedersen Three new function pointer fields are added to bits_image_t: fetch_scanline_float fetch_pixel_float store_scanline_float similar to the existing 32 and 64 bit accessors. The fetcher_info_t struct in pixman_access similarly gets a new get_scanline_float field. For most formats, the new get_scanline_float field is set to a new function fetch_scanline_generic_float() that first calls the 32 bit fetcher uses the 32 bit scanline fetcher and then expands these pixels to floating point. For the 10 bpc formats, new floating point accessors are added that use pixman_unorm_to_float() and pixman_float_to_unorm() to convert back and forth. The PIXMAN_a8r8g8b8_sRGB format is handled with a 256-entry table that maps 8 bit sRGB channels to linear single precision floating point numbers. The sRGB->linear direction can then be done with a simple table lookup. The other direction is currently done with a 4096-entry table which works fine for 16 bit integers, but not so great for floating point. So instead this patch uses a binary search in the sRGB->linear table. The existing 32 bit accessors for the sRGB format are also converted to use this method. --- pixman/pixman-access.c | 619 +--- pixman/pixman-bits-image.c | 40 +++- pixman/pixman-private.h|8 + 3 files changed, 624 insertions(+), 43 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 9feafc4..1eef621 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "pixman-accessor.h" #include "pixman-private.h" @@ -635,6 +636,231 @@ fetch_scanline_x2b10g10r10 (pixman_image_t *image, } } +/* Table mapping sRGB-encoded 8 bit numbers to linearly encoded + * floating point numbers. We assume that single precision + * floating point follows the IEEE 754 format. + */ +static const uint32_t to_linear_u[256] = +{ +0x, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61, +0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a, +0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d, +0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152, +0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43, +0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e, +0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601, +0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9, +0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae, +0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380, +0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466, +0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65, +0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48, +0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728, +0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4, +0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16, +0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f, +0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50, +0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a, +0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702, +0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027, +0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf, +0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0, +0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281, +0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0, +0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a, +0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15, +0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14, +0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508, +0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64, +0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594, +0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8, +0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65, +0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237, +0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c, +0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680, +0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24, +0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e, +0x3f469c49, 0x3f4895ee, 0x3f4a92
[Pixman] [PATCH 07/10] Switch the wide pipeline over to using floating point
From: Søren Sandmann Pedersen In pixman-bits-image.c, remove bits_image_fetch_untransformed_64() and add bits_image_fetch_untransformed_float(); change dest_get_scanline_wide() to produce a floating point buffer, In the gradients, change *_get_scanline_wide() to call pixman_expand_to_float() instead of pixman_expand(). In pixman-general.c change the wide Bpp to 16 instead of 8, and initialize the buffers to 0 to prevent NaNs from causing trouble. In pixman-noop.c make the wide solid iterator generate floating point pixels. In pixman-solid-fill.c, cache a floating point pixel, and make the wide iterator generate floating point pixels. --- pixman/pixman-bits-image.c | 64 ++ pixman/pixman-conical-gradient.c |3 +- pixman/pixman-general.c | 10 +- pixman/pixman-implementation.c |4 +- pixman/pixman-linear-gradient.c |3 +- pixman/pixman-noop.c |6 ++-- pixman/pixman-private.h |3 +- pixman/pixman-radial-gradient.c |3 +- pixman/pixman-solid-fill.c | 10 -- 9 files changed, 59 insertions(+), 47 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 07353dc..81a5a6f 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -979,17 +979,17 @@ replicate_pixel_32 (bits_image_t * bits, } static void -replicate_pixel_64 (bits_image_t * bits, - int x, - int y, - int width, - uint32_t * b) +replicate_pixel_float (bits_image_t * bits, + int x, + int y, + int width, + uint32_t * b) { -uint64_t color; -uint64_t *buffer = (uint64_t *)b; -uint64_t *end; +argb_t color; +argb_t *buffer = (argb_t *)b; +argb_t *end; -color = bits->fetch_pixel_64 (bits, x, y); +color = bits->fetch_pixel_float (bits, x, y); end = buffer + width; while (buffer < end) @@ -1008,7 +1008,7 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, if (y < 0 || y >= image->height) { - memset (buffer, 0, width * (wide? 8 : 4)); + memset (buffer, 0, width * (wide? sizeof (argb_t) : 4)); return; } @@ -1016,10 +1016,10 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, { w = MIN (width, -x); - memset (buffer, 0, w * (wide ? 8 : 4)); + memset (buffer, 0, w * (wide ? sizeof (argb_t) : 4)); width -= w; - buffer += w * (wide? 2 : 1); + buffer += w * (wide? 4 : 1); x += w; } @@ -1028,16 +1028,16 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image, w = MIN (width, image->width - x); if (wide) - image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL); + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); else image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); width -= w; - buffer += w * (wide? 2 : 1); + buffer += w * (wide? 4 : 1); x += w; } -memset (buffer, 0, width * (wide ? 8 : 4)); +memset (buffer, 0, width * (wide ? sizeof (argb_t) : 4)); } static void @@ -1059,7 +1059,7 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, if (image->width == 1) { if (wide) - replicate_pixel_64 (image, 0, y, width, buffer); + replicate_pixel_float (image, 0, y, width, buffer); else replicate_pixel_32 (image, 0, y, width, buffer); @@ -1076,7 +1076,7 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, w = MIN (width, image->width - x); if (wide) - image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL); + image->fetch_scanline_float ((pixman_image_t *)image, x, y, w, buffer, NULL); else image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL); @@ -1112,9 +1112,8 @@ bits_image_fetch_untransformed_32 (pixman_iter_t * iter, } static uint32_t * -bits_image_fetch_untransformed_64 (pixman_iter_t * iter, - const uint32_t *mask) - +bits_image_fetch_untransformed_float (pixman_iter_t * iter, + const uint32_t *mask) { pixman_image_t *image = iter->image; int x = iter->x; @@ -1155,8 +1154,8 @@ static const fetcher_info_t fetcher_info[] = FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_REFLECT_REPEAT), bits_image_fetch_untransformed_32, - bits_image_fetch_untransformed_64, - _
[Pixman] [PATCH 08/10] Remove 64 bit pipeline
From: Søren Sandmann Pedersen The 64 bit pipeline is not used anymore, so it can now be removed. Don't generate pixman-combine64.[ch] anymore. Don't generate the pixman-srgb.c anymore. Delete all the 64 bit fetchers in pixman-access.c, all the 64 bit iterator functions in pixman-bits-image.c and all the functions that expand from 8 to 16 bits. --- .gitignore |2 - pixman/Makefile.am |1 - pixman/Makefile.sources| 14 -- pixman/pixman-access.c | 517 +++- pixman/pixman-bits-image.c | 49 + pixman/pixman-general.c|1 - pixman/pixman-private.h| 41 pixman/pixman-solid-fill.c | 23 +- pixman/pixman-utils.c | 116 -- 9 files changed, 39 insertions(+), 725 deletions(-) diff --git a/.gitignore b/.gitignore index a4d9f99..a67da1d 100644 --- a/.gitignore +++ b/.gitignore @@ -41,8 +41,6 @@ demos/trap-test demos/tri-test pixman/pixman-combine32.c pixman/pixman-combine32.h -pixman/pixman-combine64.c -pixman/pixman-combine64.h pixman/pixman-srgb.c pixman/pixman-version.h test/a1-trap-test diff --git a/pixman/Makefile.am b/pixman/Makefile.am index 270d65e..3060569 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -13,7 +13,6 @@ noinst_LTLIBRARIES = EXTRA_DIST = \ Makefile.win32 \ make-combine.pl \ - make-srgb.pl\ pixman-combine.c.template \ pixman-combine.h.template \ pixman-region.c \ diff --git a/pixman/Makefile.sources b/pixman/Makefile.sources index 96540ec..5be288d 100644 --- a/pixman/Makefile.sources +++ b/pixman/Makefile.sources @@ -4,7 +4,6 @@ libpixman_sources = \ pixman-access-accessors.c \ pixman-bits-image.c \ pixman-combine32.c \ - pixman-combine64.c \ pixman-combine-float.c \ pixman-conical-gradient.c \ pixman-x86.c\ @@ -26,7 +25,6 @@ libpixman_sources = \ pixman-region16.c \ pixman-region32.c \ pixman-solid-fill.c \ - pixman-srgb.c \ pixman-timer.c \ pixman-trap.c \ pixman-utils.c \ @@ -36,7 +34,6 @@ libpixman_headers = \ pixman.h\ pixman-accessor.h \ pixman-combine32.h \ - pixman-combine64.h \ pixman-compiler.h \ pixman-edge-imp.h \ pixman-inlines.h\ @@ -46,20 +43,9 @@ libpixman_headers = \ BUILT_SOURCES =\ pixman-combine32.c \ pixman-combine32.h \ - pixman-combine64.c \ - pixman-combine64.h \ - pixman-srgb.c \ $(NULL) -pixman-srgb.c: make-srgb.pl - $(PERL) $< > $@ || ($(RM) $@; exit 1) - pixman-combine32.c: pixman-combine.c.template make-combine.pl $(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1) pixman-combine32.h: pixman-combine.h.template make-combine.pl $(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1) - -pixman-combine64.c: pixman-combine.c.template make-combine.pl - $(PERL) $(lastword $+) 16 < $< > $@ || ($(RM) $@; exit 1) -pixman-combine64.h: pixman-combine.h.template make-combine.pl - $(PERL) $(lastword $+) 16 < $< > $@ || ($(RM) $@; exit 1) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 1eef621..b5c8e40 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -507,135 +507,6 @@ MAKE_ACCESSORS(a1); MAKE_ACCESSORS(g1); /** Fetch / - -/* Expects a uint64_t buffer */ -static void -fetch_scanline_a2r10g10b10 (pixman_image_t *image, -int x, -int y, -int width, -uint32_t * b, -const uint32_t *mask) -{ -const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; -const uint32_t *pixel = bits + x; -const uint32_t *end = pixel + width; -uint64_t *buffer = (uint64_t *)b; - -while (pixel < end) -{ - uint32_t p = READ (image, pixel++); - uint64_t a = p >> 30; - uint64_t r = (p >> 20) & 0x3ff; - uint64_t g = (p >> 10) & 0x3ff; - uint64_t b = p & 0x3ff; - - r = r << 6 | r >> 4; - g = g << 6 | g >> 4; - b = b << 6 | b &
[Pixman] [PATCH 10/10] Speed up pixman_expand_to_float()
From: Søren Sandmann Pedersen GCC doesn't move the divisions out of the loop, so do it manually by looking up the four (1.0f / mask) values in a table. Table lookups are used under the theory that one L2 hit plus three L1 hits is preferable to four floating point divisions. --- pixman/pixman-utils.c | 38 ++ 1 files changed, 34 insertions(+), 4 deletions(-) diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index 551f3f9..b1e9fb6 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -111,8 +111,28 @@ pixman_expand_to_float (argb_t *dst, pixman_format_code_t format, int width) { +static const float multipliers[16] = { + 0.0f, + 1.0f / ((1 << 1) - 1), + 1.0f / ((1 << 2) - 1), + 1.0f / ((1 << 3) - 1), + 1.0f / ((1 << 4) - 1), + 1.0f / ((1 << 5) - 1), + 1.0f / ((1 << 6) - 1), + 1.0f / ((1 << 7) - 1), + 1.0f / ((1 << 8) - 1), + 1.0f / ((1 << 9) - 1), + 1.0f / ((1 << 10) - 1), + 1.0f / ((1 << 11) - 1), + 1.0f / ((1 << 12) - 1), + 1.0f / ((1 << 13) - 1), + 1.0f / ((1 << 14) - 1), + 1.0f / ((1 << 15) - 1), +}; int a_size, r_size, g_size, b_size; int a_shift, r_shift, g_shift, b_shift; +float a_mul, r_mul, g_mul, b_mul; +uint32_t a_mask, r_mask, g_mask, b_mask; int i; if (!PIXMAN_FORMAT_VIS (format)) @@ -132,6 +152,16 @@ pixman_expand_to_float (argb_t *dst, g_shift = 16 - g_size; b_shift = 8 - b_size; +a_mask = ((1 << a_size) - 1); +r_mask = ((1 << r_size) - 1); +g_mask = ((1 << g_size) - 1); +b_mask = ((1 << b_size) - 1); + +a_mul = multipliers[a_size]; +r_mul = multipliers[r_size]; +g_mul = multipliers[g_size]; +b_mul = multipliers[b_size]; + /* Start at the end so that we can do the expansion in place * when src == dst */ @@ -139,10 +169,10 @@ pixman_expand_to_float (argb_t *dst, { const uint32_t pixel = src[i]; - dst[i].a = a_size? unorm_to_float (pixel >> a_shift, a_size) : 1.0; - dst[i].r = r_size? unorm_to_float (pixel >> r_shift, r_size) : 0.0; - dst[i].g = g_size? unorm_to_float (pixel >> g_shift, g_size) : 0.0; - dst[i].b = b_size? unorm_to_float (pixel >> b_shift, b_size) : 0.0; + dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f; + dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul; + dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul; + dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul; } } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH 0/10] Floating point pipeline again
Behdad Esfahbod writes: > On 09/26/2012 04:43 PM, Søren Sandmann wrote: >> Hi, >> >> Here is a new version of the floating point patches. The main changes >> since last time are: >> >> (a) It is now explicit that the only guarantee wrt. floating point >> exceptions is that divide-by-zero is not generated. So if an >> application enables for example FP_INVALID, it may crash. It can >> safely enablE FP_DIVBYZERO though. >> >> (b) pixman_expand_to_float() is faster. The first version was written >> in a way that caused gcc to generate divisions in the inner >> loop. The new version avoids that. >> >> Below are the results of some benchmark runs. From top to bottom: >> >> - Regular, unmodified pixman >> - With all compositing going through the current 16 bpc wide path >> - With all compositign going through the new floating point wide path > > What are the columns? [test number], [cairo backend], [test name], [min time], [median time], [std variance] The 2/2 column I believe indicates that the test was run twice and two of those runs were used in the data gathering (ie., not considered outliers). Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH 05/10] pixman-utils.c, pixman-private.h: Add floating point conversion routines
Matt Turner writes: >> +pixman_bool_t >> +_pixman_lookup_composite_function (pixman_implementation_t *toplevel, >> + pixman_op_t op, >> + pixman_format_code_t src_format, >> + uint32_t src_flags, >> + pixman_format_code_t mask_format, >> + uint32_t mask_flags, >> + pixman_format_code_t dest_format, >> + uint32_t dest_flags, >> + pixman_implementation_t**out_imp, >> + pixman_composite_func_t *out_func); >> + This declaration is the result of a mismerge. I'll remove it before comitting. >> +void >> +pixman_expand_to_float (argb_t *dst, >> + const uint32_t *src, >> + pixman_format_code_t format, >> + int width) >> +{ >> +void >> +pixman_contract_from_float (uint32_t *dst, >> + const argb_t *src, >> + int width) >> +{ > > As I'm sure you know, these functions can be done with SSE 2 or 4.1 if > we could convert 4 pixels at once. How can we override their > implementations with optimized ones? A way to do that might be to make it a new entry point in the implementation struct, and then make sure that the implementation pointer is passed down to the accessors. But a simpler approach would probably be to write SIMD iterators for the most common formats that would convert to and from floating point without using these expand/contract functions. An idea here might be to change the "untransformed" iterators such that they could take an accessor function as a parameter. Then the SIMD implementations could simply write accessor functions and pass them to that iterator. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Make pixman.h more const-correct
From: Søren Sandmann Pedersen Add const to pointer arguments when the function doesn't change the pointed-to data. --- pixman/pixman-conical-gradient.c |2 +- pixman/pixman-glyph.c|8 pixman/pixman-linear-gradient.c |4 ++-- pixman/pixman-radial-gradient.c |4 ++-- pixman/pixman-solid-fill.c |2 +- pixman/pixman-trap.c | 10 +- pixman/pixman.c | 10 +- pixman/pixman.h | 24 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c index 8b52176..05d3595 100644 --- a/pixman/pixman-conical-gradient.c +++ b/pixman/pixman-conical-gradient.c @@ -180,7 +180,7 @@ _pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) } PIXMAN_EXPORT pixman_image_t * -pixman_image_create_conical_gradient (pixman_point_fixed_t *center, +pixman_image_create_conical_gradient (const pixman_point_fixed_t * center, pixman_fixed_tangle, const pixman_gradient_stop_t *stops, int n_stops) diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c index 30a4099..657b62d 100644 --- a/pixman/pixman-glyph.c +++ b/pixman/pixman-glyph.c @@ -354,7 +354,7 @@ pixman_glyph_get_extents (pixman_glyph_cache_t *cache, PIXMAN_EXPORT pixman_format_code_t pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, int n_glyphs, - pixman_glyph_t * glyphs) + const pixman_glyph_t *glyphs) { pixman_format_code_t format = PIXMAN_a1; int i; @@ -401,7 +401,7 @@ pixman_composite_glyphs_no_mask (pixman_op_top, int32_tdest_y, pixman_glyph_cache_t *cache, intn_glyphs, -pixman_glyph_t*glyphs) +const pixman_glyph_t *glyphs) { pixman_region32_t region; pixman_format_code_t glyph_format = PIXMAN_null; @@ -502,7 +502,7 @@ static void add_glyphs (pixman_glyph_cache_t *cache, pixman_image_t *dest, int off_x, int off_y, - int n_glyphs, pixman_glyph_t *glyphs) + int n_glyphs, const pixman_glyph_t *glyphs) { pixman_format_code_t glyph_format = PIXMAN_null; uint32_t glyph_flags = 0; @@ -651,7 +651,7 @@ pixman_composite_glyphs (pixman_op_top, int32_theight, pixman_glyph_cache_t *cache, intn_glyphs, -pixman_glyph_t*glyphs) +const pixman_glyph_t *glyphs) { pixman_image_t *mask; diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c index 32b8ba7..e511368 100644 --- a/pixman/pixman-linear-gradient.c +++ b/pixman/pixman-linear-gradient.c @@ -255,8 +255,8 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) } PIXMAN_EXPORT pixman_image_t * -pixman_image_create_linear_gradient (pixman_point_fixed_t *p1, - pixman_point_fixed_t *p2, +pixman_image_create_linear_gradient (const pixman_point_fixed_t * p1, + const pixman_point_fixed_t * p2, const pixman_gradient_stop_t *stops, int n_stops) { diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c index 715711f..41bb79d 100644 --- a/pixman/pixman-radial-gradient.c +++ b/pixman/pixman-radial-gradient.c @@ -420,8 +420,8 @@ _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) } PIXMAN_EXPORT pixman_image_t * -pixman_image_create_radial_gradient (pixman_point_fixed_t *inner, - pixman_point_fixed_t *outer, +pixman_image_create_radial_gradient (const pixman_point_fixed_t * inner, + const pixman_point_fixed_t * outer, pixman_fixed_t inner_radius, pixman_fixed_t outer_radius, const pixman_gradient_stop_t *stops, diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c index 8b25d5d..26f85ce 100644 --- a/pixman/pixman-solid-fill.c +++ b/pixman/pixman-solid-fill.c @@ -72,7 +72,7 @@ color_to_uint64 (const pixman_color_t *color) } PIXMAN_EXPORT pixman_image_t * -pixman_image_create_solid_fill (pixman_co
[Pixman] [PATCH] Make 'white' in add_glyphs() static and const
From: Søren Sandmann Pedersen --- pixman/pixman-glyph.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-glyph.c b/pixman/pixman-glyph.c index 657b62d..15b3f1f 100644 --- a/pixman/pixman-glyph.c +++ b/pixman/pixman-glyph.c @@ -560,7 +560,7 @@ add_glyphs (pixman_glyph_cache_t *cache, { if (!white_img) { - pixman_color_t white = { 0x, 0x, 0x, 0x }; + static const pixman_color_t white = { 0x, 0x, 0x, 0x }; if (!(white_img = pixman_image_create_solid_fill (&white))) goto out; -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] ARMv5 optimisations
Siarhei Siamashka writes: >> As the code comes from the Android code base, it is Apache licensed - >> is this a problem with Pixman? > > I am not a lawyer, but Apache license does not seem to be > compatible with GPL2 according to: >http://www.apache.org/licenses/GPL-compatibility.html > This is an extra restriction, which does not exist in the current > pixman MIT/X11 license. I personally would not touch Apache licensed > code without a really good reason. Yeah, unfortunately we can't ship Apache licensed code in pixman. > BTW, the nearest scaling code from pixman-arm-simd-asm.S can be > moved to the arm-v5 file if pixman gets ARMv5 support. There is also an old bug here: https://bugs.freedesktop.org/show_bug.cgi?id=13445 with some ARM assembly fill routines that probably could be resurrected fairly easily. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] ARMv5 optimisations
Andre Renaud writes: As the code comes from the Android code base, it is Apache licensed - is this a problem with Pixman? >>> >>> I am not a lawyer, but Apache license does not seem to be >>> compatible with GPL2 according to: >>>http://www.apache.org/licenses/GPL-compatibility.html >>> This is an extra restriction, which does not exist in the current >>> pixman MIT/X11 license. I personally would not touch Apache licensed >>> code without a really good reason. >> >> Yeah, unfortunately we can't ship Apache licensed code in pixman. > > Thanks for all the feedback, I'll probably take a look at the bugs & > check them. However given that the license is incompatible, it doesn't > seem like there is much point in continuing with this, as it's not > possible for it to be merged. Unfortunately I don't think my ARM ASM > skills are up to recreating these from scratch. > > Is the Pixman project GPL2? I thought it was all MIT - is that an > upcoming change? It's all MIT, but if we added Apache licensed code, it would effectively become Apache licensed and therefore among other things become incompatible with GPL2. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] debuging wxruby
Svend Haugaard Sørensen writes: > The top of the stack dump look like this. > > #0 0xb47a6d9d in _pixman_lookup_composite_function (toplevel=0x80be750, > op=PIXMAN_OP_SRC, > src_format=262144, src_flags=1043063, mask_format=0, mask_flags=8192, > dest_format=PIXMAN_a8r8g8b8, dest_flags=34032255, out_imp=0xbfffb82c, > out_func=0xbfffb828) > at > /var/tmp/portage/x11-libs/pixman-0.26.0/work/pixman-0.26.0/pixman/pixman-utils.c:74 A crash at this point suggests that something is broken with thread local storage on your setup. When you compiled pixman, which type of thread local storage was detected by the configure script? Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] debuging wxruby
Svend Haugaard Sørensen writes: > On Sun, 07 Oct 2012 05:10:18 +0200 > sandm...@cs.au.dk (Søren Sandmann) wrote: > >> Svend Haugaard Sørensen writes: >> >> > The top of the stack dump look like this. >> > >> > #0 0xb47a6d9d in _pixman_lookup_composite_function >> > (toplevel=0x80be750, op=PIXMAN_OP_SRC, src_format&2144, >> > src_flags43063, mask_format=0, mask_flags92, >> > dest_format=PIXMAN_a8r8g8b8, dest_flags4032255, >> > out_imp=0xbfffb82c, out_func=0xbfffb828) >> > at >> > /var/tmp/portage/x11-libs/pixman-0.26.0/work/pixman-0.26.0/pixman/pixman-utils.c:74 >> >> A crash at this point suggests that something is broken with thread >> local storage on your setup. When you compiled pixman, which type of >> thread local storage was detected by the configure script? >> >> >> Søren > > The configure script write this to the output. > checking for thread local storage (TLS) support... __thread > > I have posted the complete output on the gentoo forum. > http://forums.gentoo.org/viewtopic-p-7157526.html#7157526 > Most likely the issue is the same as in this bug: https://bugs.freedesktop.org/show_bug.cgi?id=34335 where some other library is using the TLS model "initial-exec", which then conflicts with pixman using the "dynamic" model. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] debuging wxruby
Svend Haugaard Sørensen writes: >> Most likely the issue is the same as in this bug: >> >>https://bugs.freedesktop.org/show_bug.cgi?id4335 >> >> where some other library is using the TLS model "initial-exec", which >> then conflicts with pixman using the "dynamic" model. > > And how do we find, test and fix that?? > > Is the TLS supported by a certain dynamic library? Because the I > can search for it. > > PS. I don't use mesa, but the nvidia driver. It's possible that the root cause is this bug in glibc: http://sourceware.org/bugzilla/show_bug.cgi?id=12453 If your C library is older than that, I'd try updating it first. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Only regard images as pixbufs if they have identity transformations
From: Søren Sandmann Pedersen In order for a src/mask pair to be considered a pixbuf, they have to have identical transformations, but we don't check for that. Since the only fast paths we have for pixbufs require identity transformations, it sufficies to check that both source and mask are untransformed. This is also the reason that this bug can't be triggered by any test code - if the source and mask had different transformations, we would consider them a pixbuf, but then wouldn't take the fast path because at least one of the transformations would be different from the identity. --- pixman/pixman.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pixman/pixman.c b/pixman/pixman.c index bbe8b08..e3b6516 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -605,6 +605,7 @@ pixman_image_composite32 (pixman_op_t op, if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) && (src->type == BITS && src->bits.bits == mask->bits.bits) && (src->common.repeat == mask->common.repeat)&& + (src_flags & mask_flags & FAST_PATH_ID_TRANSFORM) && (src_x == mask_x && src_y == mask_y)) { if (src_format == PIXMAN_x8b8g8r8) -- 1.7.11.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] region: Remove overlap argument from pixman_op()
From: Søren Sandmann Pedersen This is used to compute whether the regions in question overlap, but nothing makes use of this information, so it can be removed. --- pixman/pixman-region.c | 53 +- 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c index 7dbcf9a..c30d49b 100644 --- a/pixman/pixman-region.c +++ b/pixman/pixman-region.c @@ -742,8 +742,7 @@ typedef pixman_bool_t (*overlap_proc_ptr) (region_type_t *region, box_type_t * r2, box_type_t * r2_end, inty1, - inty2, - int * overlap); + inty2); static pixman_bool_t pixman_op (region_type_t * new_reg, /* Place to store result */ @@ -754,10 +753,10 @@ pixman_op (region_type_t * new_reg, /* Place to store result int append_non1, /* Append non-overlapping bands * in region 1 ? */ - int append_non2, /* Append non-overlapping bands + int append_non2/* Append non-overlapping bands * in region 2 ? */ - int *overlap) +) { box_type_t *r1; /* Pointer into first region */ box_type_t *r2; /* Pointer into 2d region */ @@ -935,8 +934,7 @@ pixman_op (region_type_t * new_reg, /* Place to store result if (!(*overlap_func)(new_reg, r1, r1_band_end, r2, r2_band_end, - ytop, ybot, - overlap)) + ytop, ybot)) { goto bail; } @@ -1113,8 +,7 @@ pixman_region_intersect_o (region_type_t *region, box_type_t * r2, box_type_t * r2_end, inty1, - inty2, - int * overlap) + inty2) { int x1; int x2; @@ -1210,13 +1207,9 @@ PREFIX (_intersect) (region_type_t * new_reg, else { /* General purpose intersection */ -int overlap; /* result ignored */ -if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE, -&overlap)) - { +if (!pixman_op (new_reg, reg1, reg2, pixman_region_intersect_o, FALSE, FALSE)) return FALSE; - } pixman_set_extents (new_reg); } @@ -1230,10 +1223,6 @@ PREFIX (_intersect) (region_type_t * new_reg, { \ if (r->x1 <= x2) \ { \ -/* Merge with current rectangle */ \ -if (r->x1 < x2)\ - *overlap = TRUE;\ - \ if (x2 < r->x2)\ x2 = r->x2; \ } \ @@ -1273,8 +1262,7 @@ pixman_region_union_o (region_type_t *region, box_type_t * r2, box_type_t * r2_end, inty1, - inty2, - int * overlap) + inty2) { box_type_t *next_rect; int x1;/* left and right side of current union */ @@ -1383,8 +1371,6 @@ PREFIX (_union) (region_type_t *new_reg, region_type_t *reg1, region_type_t *reg2) { -int overlap; /* result ignored */ - /* Return TRUE if some overlap * between reg1, reg2 */ @@ -1450,7 +1436,7 @@ PREFIX (_union) (region_type_t *new_reg, return TRUE; } -if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE, &overlap)) +if (!pixman_op (new_reg, reg1, reg2, pixman_region_union_o, TRUE, TRUE)) return FALSE; new_reg->extents.x1 = MIN (re
[Pixman] [PATCH 1/2] region: Formatting fix
From: Søren Sandmann Pedersen The while part of a do/while loop was formatted as if it were a while loop with an empty body. Probably some indent tool misinterpreted the code at some point. --- pixman/pixman-region.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c index 4626f9c..7dbcf9a 100644 --- a/pixman/pixman-region.c +++ b/pixman/pixman-region.c @@ -1517,9 +1517,7 @@ quick_sort_rects ( r++; i++; } - -while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))) - ; + while (i != numRects && (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); r = &(rects[j]); do -- 1.7.11.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] image byte order?
Jonathan Morton writes: >> > The 24-bit formats are not. >> >> So PIXMAN_r8g8b8 has the red byte first no matter what the endian is, >> correct? > > Yes. This is potentially useful for subpixel antialiasing masks, BTW. The 24 bit formats are native endian as well, so PIXMAN_r8g8b8 is a sequence of [r, g, b] bytes on big endian, and a sequence of [b, g, r] bytes on little endian. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add new pixman_image_create_bits_no_clear() API
From: Søren Sandmann Pedersen When pixman_image_create_bits() function is given NULL for bits, it will allocate a new buffer and initialize it to zero. However, in some cases, only a small region of the image is actually used; in that case it is wasteful to touch all of the memory. The new pixman_image_create_bits_no_clear() works exactly like _create_bits() except that it doesn't initialize any newly allocated memory. --- pixman/pixman-bits-image.c | 54 +++- pixman/pixman-fast-path.c |3 +- pixman/pixman-private.h|3 +- pixman/pixman.h|5 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 029093d..085dd16 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -1388,7 +1388,8 @@ static uint32_t * create_bits (pixman_format_code_t format, int width, int height, - int * rowstride_bytes) + int * rowstride_bytes, +pixman_bool_tclear) { int stride; size_t buf_size; @@ -1420,7 +1421,10 @@ create_bits (pixman_format_code_t format, if (rowstride_bytes) *rowstride_bytes = stride; -return calloc (buf_size, 1); +if (clear) + return calloc (buf_size, 1); +else + return malloc (buf_size); } pixman_bool_t @@ -1429,7 +1433,8 @@ _pixman_bits_image_init (pixman_image_t * image, int width, int height, uint32_t * bits, - int rowstride) + int rowstride, +pixman_bool_tclear) { uint32_t *free_me = NULL; @@ -1437,7 +1442,7 @@ _pixman_bits_image_init (pixman_image_t * image, { int rowstride_bytes; - free_me = bits = create_bits (format, width, height, &rowstride_bytes); + free_me = bits = create_bits (format, width, height, &rowstride_bytes, clear); if (!bits) return FALSE; @@ -1465,12 +1470,13 @@ _pixman_bits_image_init (pixman_image_t * image, return TRUE; } -PIXMAN_EXPORT pixman_image_t * -pixman_image_create_bits (pixman_format_code_t format, - int width, - int height, - uint32_t * bits, - int rowstride_bytes) +static pixman_image_t * +create_bits_image_internal (pixman_format_code_t format, + int width, + int height, + uint32_t * bits, + int rowstride_bytes, + pixman_bool_tclear) { pixman_image_t *image; @@ -1487,7 +1493,8 @@ pixman_image_create_bits (pixman_format_code_t format, return NULL; if (!_pixman_bits_image_init (image, format, width, height, bits, - rowstride_bytes / (int) sizeof (uint32_t))) + rowstride_bytes / (int) sizeof (uint32_t), + clear)) { free (image); return NULL; @@ -1495,3 +1502,28 @@ pixman_image_create_bits (pixman_format_code_t format, return image; } + +/* If bits is NULL, a buffer will be allocated and initialized to 0 */ +PIXMAN_EXPORT pixman_image_t * +pixman_image_create_bits (pixman_format_code_t format, + int width, + int height, + uint32_t * bits, + int rowstride_bytes) +{ +return create_bits_image_internal ( + format, width, height, bits, rowstride_bytes, TRUE); +} + + +/* If bits is NULL, a buffer will be allocated and _not_ initialized */ +PIXMAN_EXPORT pixman_image_t * +pixman_image_create_bits_no_clear (pixman_format_code_t format, + int width, + int height, + uint32_t * bits, + int rowstride_bytes) +{ +return create_bits_image_internal ( + format, width, height, bits, rowstride_bytes, FALSE); +} diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 22bfd30..a0eed59 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1296,7 +1296,8 @@ fast_composite_tiled_repeat (pixman_implementation_t *imp, /* Initialize/validate stack-allocated temporary image */ _pixman_bi
[Pixman] [PATCH 2/2] pixman_composite_trapezoids(): don't clip to extents for some operators
From: Søren Sandmann Pedersen pixman_composite_trapezoids() is supposed to composite across the entire destination, but it actually only composites across the extent of the trapezoids. For operators such as ADD or OVER this doesn't matter since a zero source has no effect on the destination. But for operators such as SRC or IN, it does matter. So for such operators where a zero source has an effect, don't clip to the trap extents. --- pixman/pixman-trap.c| 43 +++ test/composite-traps-test.c |2 +- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c index f633738..ab5c8c8 100644 --- a/pixman/pixman-trap.c +++ b/pixman/pixman-trap.c @@ -387,12 +387,43 @@ pixman_rasterize_trapezoid (pixman_image_t * image, } } +static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] = +{ +FALSE, /* Clear0 0*/ +FALSE, /* Src 1 0*/ +TRUE, /* Dst 0 1*/ +TRUE, /* Over 1 1-Aa */ +TRUE, /* OverReverse 1-Ab1*/ +FALSE, /* In Ab 0*/ +FALSE, /* InReverse0 Aa */ +FALSE, /* Out 1-Ab0*/ +TRUE, /* OutReverse 0 1-Aa */ +TRUE, /* Atop Ab 1-Aa */ +FALSE, /* AtopReverse 1-AbAa */ +TRUE, /* Xor 1-Ab1-Aa */ +TRUE, /* Add 1 1*/ +}; + static pixman_bool_t -get_trap_extents (pixman_op_t op, const pixman_trapezoid_t *traps, int n_traps, +get_trap_extents (pixman_op_t op, pixman_image_t *dest, + const pixman_trapezoid_t *traps, int n_traps, pixman_box32_t *box) { int i; +/* When the operator is such that a zero source has an + * effect on the underlying image, we have to + * composite across the entire destination + */ +if (!zero_src_has_no_effect [op]) +{ + box->x1 = 0; + box->y1 = 0; + box->x2 = dest->bits.width; + box->y2 = dest->bits.height; + return TRUE; +} + box->x1 = INT32_MAX; box->y1 = INT32_MAX; box->x2 = INT32_MIN; @@ -443,12 +474,8 @@ get_trap_extents (pixman_op_t op, const pixman_trapezoid_t *traps, int n_traps, * All the trapezoids are conceptually rendered to an infinitely big image. * The (0, 0) coordinates of this image are then aligned with the (x, y) * coordinates of the source image, and then both images are aligned with - * the (x, y) coordinates of the destination. Then, in principle, compositing - * of these three images takes place across the entire destination. - * - * FIXME: However, there is currently a bug, where we restrict this compositing - * to the bounding box of the trapezoids. This is incorrect for operators such - * as SRC and IN where blank source pixels do have an effect on the destination. + * the (x, y) coordinates of the destination. Then these three images are + * composited across the entire destination. */ PIXMAN_EXPORT void pixman_composite_trapezoids (pixman_op_t op, @@ -491,7 +518,7 @@ pixman_composite_trapezoids (pixman_op_top, pixman_box32_t box; int i; - if (!get_trap_extents (op, traps, n_traps, &box)) + if (!get_trap_extents (op, dst, traps, n_traps, &box)) return; tmp = pixman_image_create_bits ( diff --git a/test/composite-traps-test.c b/test/composite-traps-test.c index ff03b50..9fc94a4 100644 --- a/test/composite-traps-test.c +++ b/test/composite-traps-test.c @@ -251,6 +251,6 @@ test_composite (int testnum, int main (int argc, const char *argv[]) { -return fuzzer_test_main("composite traps", 4, 0xE3112106, +return fuzzer_test_main("composite traps", 4, 0x33BFAA55, test_composite, argc, argv); } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/2] pixman_composite_trapezoids(): Factor out extents computation
From: Søren Sandmann Pedersen The computation of the extents rectangle is moved to its own function. --- pixman/pixman-trap.c | 93 - 1 files changed, 53 insertions(+), 40 deletions(-) diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c index 35128ee..f633738 100644 --- a/pixman/pixman-trap.c +++ b/pixman/pixman-trap.c @@ -387,6 +387,56 @@ pixman_rasterize_trapezoid (pixman_image_t * image, } } +static pixman_bool_t +get_trap_extents (pixman_op_t op, const pixman_trapezoid_t *traps, int n_traps, + pixman_box32_t *box) +{ +int i; + +box->x1 = INT32_MAX; +box->y1 = INT32_MAX; +box->x2 = INT32_MIN; +box->y2 = INT32_MIN; + +for (i = 0; i < n_traps; ++i) +{ + const pixman_trapezoid_t *trap = &(traps[i]); + int y1, y2; + + if (!pixman_trapezoid_valid (trap)) + continue; + + y1 = pixman_fixed_to_int (trap->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom)); + if (y2 > box->y2) + box->y2 = y2; + +#define EXTEND_MIN(x) \ + if (pixman_fixed_to_int ((x)) < box->x1)\ + box->x1 = pixman_fixed_to_int ((x)); +#define EXTEND_MAX(x) \ + if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)\ + box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x))); + +#define EXTEND(x) \ + EXTEND_MIN(x); \ + EXTEND_MAX(x); + + EXTEND(trap->left.p1.x); + EXTEND(trap->left.p2.x); + EXTEND(trap->right.p1.x); + EXTEND(trap->right.p2.x); +} + +if (box->x1 >= box->x2 || box->y1 >= box->y2) + return FALSE; + +return TRUE; +} + /* * pixman_composite_trapezoids() * @@ -439,46 +489,9 @@ pixman_composite_trapezoids (pixman_op_t op, { pixman_image_t *tmp; pixman_box32_t box; - - box.x1 = INT32_MAX; - box.y1 = INT32_MAX; - box.x2 = INT32_MIN; - box.y2 = INT32_MIN; - - for (i = 0; i < n_traps; ++i) - { - const pixman_trapezoid_t *trap = &(traps[i]); - int y1, y2; - - if (!pixman_trapezoid_valid (trap)) - continue; - - y1 = pixman_fixed_to_int (trap->top); - if (y1 < box.y1) - box.y1 = y1; - - y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom)); - if (y2 > box.y2) - box.y2 = y2; - -#define EXTEND_MIN(x) \ - if (pixman_fixed_to_int ((x)) < box.x1) \ - box.x1 = pixman_fixed_to_int ((x)); -#define EXTEND_MAX(x) \ - if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box.x2) \ - box.x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x))); - -#define EXTEND(x) \ - EXTEND_MIN(x); \ - EXTEND_MAX(x); - - EXTEND(trap->left.p1.x); - EXTEND(trap->left.p2.x); - EXTEND(trap->right.p1.x); - EXTEND(trap->right.p2.x); - } - - if (box.x1 >= box.x2 || box.y1 >= box.y2) + int i; + + if (!get_trap_extents (op, traps, n_traps, &box)) return; tmp = pixman_image_create_bits ( -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] configure.ac: PIXMAN_LINK_WITH_ENV fix
Makes sense to me. Pushed to master. Thanks, Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [ANNOUNCE] pixman release 0.27.4 now available
A new pixman release 0.27.4 is now available. This is a release candidate for a stable 0.28.0 release. News: * Improvements to the MIPS DSPr2 backend * Compositing wide formats is done with floating point * A large number of bug fixes Please test and send bug reports to pixman@lists.freedesktop.org or file them at https://bugs.freedesktop.org/enter_bug.cgi?product=pixman Thanks, Soren tar.gz: http://cairographics.org/snapshots/pixman-0.27.4.tar.gz http://xorg.freedesktop.org/archive/individual/lib/pixman-0.27.4.tar.gz tar.bz2: http://xorg.freedesktop.org/archive/individual/lib/pixman-0.27.4.tar.bz2 Hashes: MD5: d55534b5a691bea305e7bcd5ba654427 pixman-0.27.4.tar.gz MD5: e0312169da99576023df25d673132d2f pixman-0.27.4.tar.bz2 SHA1: 6bd2834e18f77b815047ec27ea8965fa26a36c2b pixman-0.27.4.tar.gz SHA1: 42103f7cadaf0a68114d46cf2d3532086313847f pixman-0.27.4.tar.bz2 GPG signature: http://cairographics.org/snapshots/pixman-0.27.4.tar.gz.sha1.asc (signed by Søren Sandmann Pedersen =gcc-4.8 Nemanja Lukic (7): MIPS: DSPr2: Added fast-paths for OVER operation: - over__n_ - ov MIPS: DSPr2: Added fast-paths for OVER operation: - over__n_0565 - ov MIPS: DSPr2: Added fast-paths for OVER operation: - over_0565_n_0565 - ov MIPS: DSPr2: Added OVER combiner and two new fast paths: - over__ MIPS: DSPr2: Added fast-paths for ADD operation: - add_n_8_8 - add_n_8_88 MIPS: DSPr2: Added more fast-paths for ADD operation: - add_0565_8_0565 - MIPS: DSPr2: Added more fast-paths for ADD operation: - add___888 Siarhei Siamashka (4): Add scaled nearest repeat fast paths MIPS: skip runtime detection for DSPr2 if -mdspr2 option is in CFLAGS Add missing force_inline to in() function used for C fast paths Workaround for FTBFS with gcc 4.6 (http://gcc.gnu.org/PR54965) Søren Sandmann Pedersen (44): Post-release version bump to 0.27.3 Define TIMER_BEGIN and TIMER_END even when timers are not enabled Make show_image() cope with more formats demos: Add srgb_trap_test.c Remove pointless declaration of _pixman_image_get_scanline_generic_64() Remove obsolete TODO file pixel_checker: Move sRGB conversion into get_limits() test/utils.c: Use pow(), not powf() in sRGB conversion routines implementation: Write lookup_combiner() in a less convoluted way. Move blt delegation into pixman-implementation.c Move fill delegation into pixman-implementation.c Move delegation of src/dest iter init into pixman-implementation.c Rename _pixman_lookup_composite_function() to _pixman_implementation_look _pixman_implementation_create(): Initialize implementation with memset() implementation: Rename delegate to fallback Add PIXMAN_x8b8g8r8 and PIXMAN_a8b8g8r8 formats to scaling-test Fix bug in fast_composite_scaled_nearest() Fix bugs in component alpha combiners for separable PDF operators Add rotate-test.c test program Fix bugs in pixman-image.c pixman-combine.c.template: Formatting clean-ups affine-test: Print out the transformation matrix when verbose test: Add inifinite-loop test Fix for infinite-loop test rotate-test: Call image_endian_swap() in make_image() Make pixman.h more const-correct glyph-test: Prepare for floating point blitters-test: Prepare for floating point Add pixman-combine-float.c Add combiner test pixman-utils.c, pixman-private.h: Add floating point conversion routines pixman-access.c: Add floating point accessor functions Switch the wide pipeline over to using floating point Remove 64 bit pipeline Don't auto-generate pixman-combine32.[ch] anymore Speed up pixman_expand_to_float() Remove BUILT_SOURCES Only regard images as pixbufs if they have identity transformations region: Formatting fix region: Remove overlap argument from pixman_op() Add new pixman_image_create_bits_no_clear() API pixman_composite_trapezoids(): Factor out extents computation pixman_composite_trapezoids(): don't clip to extents for some operators Pre-release version bump to 0.27.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] pixman on iOS
Siarhei Siamashka writes: >> > I would suggest to just change the order of checks for >> > __declspec(thread) and __thread in configure.ac >> >> We should maybe try using -Werror=ignored-attributes in the test, or >> just prefer the first one. > > Using -Werror=ignored-attributes will not help because clang-3.1 (and > maybe older versions too) just silently ignores __declspec(thread). > This non-working TLS problem could have been detected by the pixman test > suite if clang had OpenMP support. In any case, I was just lucky to > notice the fresh warning when doing preemptive testing for the current > clang svn (just to be sure that pixman would not need any ugly compiler > bug workarounds for the upcoming clang-3.2). > > Regarding your original patch, how does iOS behave when somebody > tries to use __thread keyword? Does it fail compilation? If nobody knows the answer to this, let's just change the order of the checks as you suggested. We can't support iOS unless someone is willing to maintain it. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH 3/3] MIPS: DSPr2: Added more fast-paths for OVER operation:
Nemanja Lukic writes: > From: Nemanja Lukic > > Performance numbers before/after on MIPS-74kc @ 1GHz: > > lowlevel-blt-bench results > > Referent (before): > over_n_0565 = L1: 12.04 L2: 21.45 M: 18.50 ( 24.55%) HT: 6.93 > VT: 6.45 R: 6.38 RT: 2.16 ( 22Kops/s) This one: > over_n_ = L1: 93.76 L2: 85.96 M: 24.41 ( 64.78%) HT: 8.93 > VT: 8.08 R: 7.99 RT: 2.54 ( 25Kops/s) > over_n_ = L1: 55.31 L2: 49.07 M: 28.60 ( 75.93%) HT: 23.99 > VT: 22.95 R: 22.34 RT: 12.85 ( 61Kops/s) looks like a performance regression for L1 and L2? Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [ANNOUNCE] pixman major release 0.28.0 now available
A new major release 0.28.0 of the pixman rendering library is now available. Highlights of this release: * Support for sRGB coded images [Antti Lankila] * New API for fast glyph rendering [Soren Sandmann] * Faster bilinear scaling on iwMMX, Loongson and MMX [Matt Turner] * More fast paths in the MIPS DSPr2 backend [Nemanja Lukic] * Faster scaling in general and on SSE2 in particular [Siarhei Siamashka] Please send bug reports to pixman@lists.freedesktop.org or file them at https://bugs.freedesktop.org/enter_bug.cgi?product=pixman Thanks, Soren tar.gz: http://cairographics.org/releases/pixman-0.28.0.tar.gz http://xorg.freedesktop.org/archive/individual/lib/pixman-0.28.0.tar.gz tar.bz2: http://xorg.freedesktop.org/archive/individual/lib/pixman-0.28.0.tar.bz2 Hashes: MD5: 0554c354aed2d7845180f310a9a15f20 pixman-0.28.0.tar.gz MD5: 703c3f62437b161c610056e076560570 pixman-0.28.0.tar.bz2 SHA1: 79828c1a69b459c8cc7d468dd09e2b11ecdc9c19 pixman-0.28.0.tar.gz SHA1: cfc7a18a8811bf4ff0890f547c315bda8097f6ad pixman-0.28.0.tar.bz2 GPG signature: http://cairographics.org/releases/pixman-0.28.0.tar.gz.sha1.asc (signed by Søren Sandmann Pedersen Git: git://git.freedesktop.org/git/pixman tag: pixman-0.28.0 Log: Andrea Canciani (3): build: Fix compilation on win32 mmx: Fix x86 build on MSVC build: Improve win32 build system Antti S. Lankila (5): Faster unorm_to_unorm for wide processing. Remove unnecessary dst initialization Add support for sRGB surfaces Add sRGB blending demo program Add tests to validate new sRGB behavior Benny Siegert (1): configure.ac: PIXMAN_LINK_WITH_ENV fix Matt Turner (22): mmx: add and use expand_4xpacked565 function mmx: implement expand_4x565 in terms of expand_4xpacked565 fast: add add_0565_0565 function mmx: add add_0565_0565 mmx: add over_reverse_n_ mmx: add missing _mm_empty calls autotools: use custom build rule to build iwMMXt code configure.ac: add iwmmxt2 configure flag .gitignore: add test/glyph-test sse2: enable over_n_0565 for b5g6r5 sse2: add src_x888_0565 Fix distcheck due to custom iwMMXt rules mmx: Use expand_alpha instead of mask/shift mmx: add scaled bilinear src__ mmx: add scaled bilinear over__ mmx: add scaled bilinear over__8_ mmx: optimize bilinear function when using 7-bit precision loongson: optimize _mm_set_pi* functions with shuffle instructions sse2: add missing ABGR entires for bilinear src__ build: Remove useless DEP_CFLAGS/DEP_LIBS variables sse2: mark pack_565_2x128_128 as static force_inline iwmmxt: Don't define dummy _mm_empty for >=gcc-4.8 Nemanja Lukic (9): MIPS: DSPr2: Added several bilinear fast paths with a8 mask MIPS: DSPr2: Added more bilinear fast paths (without mask) MIPS: DSPr2: Added fast-paths for OVER operation: - over__n_ - ov MIPS: DSPr2: Added fast-paths for OVER operation: - over__n_0565 - ov MIPS: DSPr2: Added fast-paths for OVER operation: - over_0565_n_0565 - ov MIPS: DSPr2: Added OVER combiner and two new fast paths: - over__ MIPS: DSPr2: Added fast-paths for ADD operation: - add_n_8_8 - add_n_8_88 MIPS: DSPr2: Added more fast-paths for ADD operation: - add_0565_8_0565 - MIPS: DSPr2: Added more fast-paths for ADD operation: - add___888 Sebastian Bauer (4): Qualify the static variables in pixman_f_transform_invert() with the cons Changed the style of two function headers Added HAVE_CONFIG_H check before including config.h Use angle brackets form of including config.h Siarhei Siamashka (12): test: OpenMP 2.5 requires signed loop iteration variables test: fix bisecting issue in fuzzer-find-diff.pl test: Fix for strict aliasing issue in 'get_random_seed' test: support nearest/bilinear scaling in lowlevel-blt-bench sse2: faster bilinear scaling (use _mm_loadl_epi64) Bilinear interpolation precision is now configurable at compile time sse2: _mm_madd_epi16 for faster bilinear scaling with 7-bit precision Change default bilinear interpolation precision to 7 bits Add scaled nearest repeat fast paths
[Pixman] [PATCH] pixman_image_composite: Reduce opaque masks to NULL
From: Søren Sandmann Pedersen When the mask is known to be opaque, we might as well reduce it to NULL to take advantage of the various fast paths that operate on NULL masks. --- pixman/pixman.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index e3b6516..e0ccd87 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -587,7 +587,7 @@ pixman_image_composite32 (pixman_op_t op, src_format = src->common.extended_format_code; src_flags = src->common.flags; -if (mask) +if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE)) { mask_format = mask->common.extended_format_code; mask_flags = mask->common.flags; -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] pixman.h: Add typedefs for pixman_f_transform and pixman_f_vector
From: Søren Sandmann Pedersen --- pixman/pixman.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pixman/pixman.h b/pixman/pixman.h index c8723cf..33ebf3f 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -226,6 +226,9 @@ pixman_bool_t pixman_transform_is_inverse (const struct pixman_transform * /* * Floating point matrices */ +typedef struct pixman_f_transform pixman_f_transform_t; +typedef struct pixman_f_vector pixman_f_vector_t; + struct pixman_f_vector { double v[3]; -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Allow src and dst to be identical in pixman_f_transform_invert()
From: Søren Sandmann Pedersen It is useful to be able to invert a matrix in place, but currently pixman_f_transform_invert() will produce wrong results if you pass the same matrix as both source and destination. Fix that by inverting into a temporary matrix and then copying that to the destination. --- pixman/pixman-matrix.c | 15 +-- 1 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pixman/pixman-matrix.c b/pixman/pixman-matrix.c index a029ab7..d2ab609 100644 --- a/pixman/pixman-matrix.c +++ b/pixman/pixman-matrix.c @@ -336,14 +336,14 @@ PIXMAN_EXPORT pixman_bool_t pixman_transform_invert (struct pixman_transform * dst, const struct pixman_transform *src) { -struct pixman_f_transform m, r; +struct pixman_f_transform m; pixman_f_transform_from_pixman_transform (&m, src); -if (!pixman_f_transform_invert (&r, &m)) +if (!pixman_f_transform_invert (&m, &m)) return FALSE; -if (!pixman_transform_from_pixman_f_transform (dst, &r)) +if (!pixman_transform_from_pixman_f_transform (dst, &m)) return FALSE; return TRUE; @@ -469,10 +469,11 @@ PIXMAN_EXPORT pixman_bool_t pixman_f_transform_invert (struct pixman_f_transform * dst, const struct pixman_f_transform *src) { -double det; -int i, j; static const int a[3] = { 2, 2, 1 }; static const int b[3] = { 1, 0, 0 }; +pixman_f_transform_t d; +double det; +int i, j; det = 0; for (i = 0; i < 3; i++) @@ -507,10 +508,12 @@ pixman_f_transform_invert (struct pixman_f_transform * dst, if (((i + j) & 1) != 0) p = -p; - dst->m[j][i] = det * p; + d.m[j][i] = det * p; } } +*dst = d; + return TRUE; } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] pixman: Use uintptr_t in type casts from pointer to integral value
Stefan Weil writes: > These modifications fix lots of compiler warnings for systems where > sizeof(unsigned long) != sizeof(void *). > This is especially true for MinGW-w64 (64 bit Windows). All three patches pushed to master. I suspect there may be issues with some versions of MSVC not having uintptr_t, but that will have to be dealt with by MSVC users. Thanks, Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/3] Round fixed-point multiplication
From: Søren Sandmann Pedersen After two fixed-point numbers are multiplied, the result is shifted into place, but up until now pixman has simply discarded the low-order bits instead of rounding to the closest number. Fix that by adding 0x8000 (or 0x2 in one place) before shifting and update the test checksums to match. --- pixman/pixman-matrix.c | 10 +- test/affine-test.c |6 +++--- test/rotate-test.c |2 +- test/scaling-test.c|6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pixman/pixman-matrix.c b/pixman/pixman-matrix.c index d2ab609..cd2f1b5 100644 --- a/pixman/pixman-matrix.c +++ b/pixman/pixman-matrix.c @@ -62,7 +62,7 @@ pixman_transform_point_3d (const struct pixman_transform *transform, { partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] * (pixman_fixed_48_16_t) vector->vector[i]); - v += partial >> 16; + v += (partial + 0x8000) >> 16; } if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16) @@ -96,16 +96,16 @@ pixman_transform_point (const struct pixman_transform *transform, { partial = ((pixman_fixed_32_32_t) transform->matrix[j][i] * (pixman_fixed_32_32_t) vector->vector[i]); - v[j] += partial >> 2; + v[j] += (partial + 2) >> 2; } } -if (!(v[2] >> 16)) +if (!((v[2] + 0x8000) >> 16)) return FALSE; for (j = 0; j < 2; j++) { - quo = v[j] / (v[2] >> 16); + quo = v[j] / ((v[2] + 0x8000) >> 16); if (quo > pixman_max_fixed_48_16 || quo < pixman_min_fixed_48_16) return FALSE; vector->vector[j] = (pixman_fixed_t) quo; @@ -138,7 +138,7 @@ pixman_transform_multiply (struct pixman_transform * dst, (pixman_fixed_32_32_t) l->matrix[dy][o] * (pixman_fixed_32_32_t) r->matrix[o][dx]; - v += partial >> 16; + v += (partial + 0x8000) >> 16; } if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16) diff --git a/test/affine-test.c b/test/affine-test.c index 7bc28b4..daa86c8 100644 --- a/test/affine-test.c +++ b/test/affine-test.c @@ -310,11 +310,11 @@ test_composite (int testnum, } #if BILINEAR_INTERPOLATION_BITS == 8 -#define CHECKSUM 0x1EF2175A +#define CHECKSUM 0x344413F0 #elif BILINEAR_INTERPOLATION_BITS == 7 -#define CHECKSUM 0x74050F50 +#define CHECKSUM 0xC8181A76 #elif BILINEAR_INTERPOLATION_BITS == 4 -#define CHECKSUM 0x4362EAE8 +#define CHECKSUM 0xD672A457 #else #define CHECKSUM 0x #endif diff --git a/test/rotate-test.c b/test/rotate-test.c index d63a289..a0488ef 100644 --- a/test/rotate-test.c +++ b/test/rotate-test.c @@ -108,6 +108,6 @@ int main (int argc, const char *argv[]) { return fuzzer_test_main ("rotate", 15000, -0x03A24D51, +0x5236FD9F, test_transform, argc, argv); } diff --git a/test/scaling-test.c b/test/scaling-test.c index 2736123..0354103 100644 --- a/test/scaling-test.c +++ b/test/scaling-test.c @@ -380,11 +380,11 @@ test_composite (int testnum, } #if BILINEAR_INTERPOLATION_BITS == 8 -#define CHECKSUM 0x8D3A7539 +#define CHECKSUM 0x107B67ED #elif BILINEAR_INTERPOLATION_BITS == 7 -#define CHECKSUM 0x03A23E0C +#define CHECKSUM 0x30EC0CF0 #elif BILINEAR_INTERPOLATION_BITS == 4 -#define CHECKSUM 0xE96D1A5E +#define CHECKSUM 0x87B496BC #else #define CHECKSUM 0x #endif -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 0/3] Some rounding related patches
The following patches fixed-point arithmetic to round instead of truncate. That is, instead of this: (a * b) >> 16 the patches now do this instead: (a * b + 0x8000) >> 16 which I believe produces more accurate results. The second patch does the same thing for the color calculations in the convolution filter, where currently if the user isn't careful to normalize the convolution matrix, we can end up with opaque images becoming slightly translucent or the like. Finally, the third patch adds a file "rounding.txt" that describes in detail how the filtering code gets from a source image location to a pixel value. The fixed-point rounding does cause some changes to transformed output, so the test suite has gotten new checksums. I'd appreciate testing on architectures other than x86 to ensure the various transformed fast paths didn't break. Siarhei pointed out here: http://lists.freedesktop.org/archives/pixman/2012-June/002095.html that the current bilinear filters also have an issue where the weights are computed based on truncated rather than rounded locations. In addition to that they also have the same issue as the convolution filter in that the *color* computation should in principle also be rounded rather than truncated from 16 to 8 bits as it is now. It would be worthwhile to fix these bugs, but the patches here don't attempt to. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/3] Convolution filter: round color values instead of truncating
From: Søren Sandmann Pedersen The pixel computed by the convolution filter should be rounded off, not truncated. As a simple example consider a convolution matrix consisting of five times 0x. If all five all five input pixels are 0xff, then the result of truncating will be (5 * 0x * 255) >> 16 = 254 But the real value of the computation is (5 * 0x / 65536.0) * 254 = 254.9961, so the error is almost 1. If the user isn't very careful about normalizing the convolution kernel so that it sums to one in fixed point, such error might cause solid images to change color, or opaque images to become translucent. The fix is simply to round instead of truncate. --- pixman/pixman-bits-image.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 085dd16..7787ef1 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -413,10 +413,10 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, } } -satot >>= 16; -srtot >>= 16; -sgtot >>= 16; -sbtot >>= 16; +satot = (satot + 0x8000) >> 16; +srtot = (srtot + 0x8000) >> 16; +sgtot = (sgtot + 0x8000) >> 16; +sbtot = (sbtot + 0x8000) >> 16; satot = CLIP (satot, 0, 0xff); srtot = CLIP (srtot, 0, 0xff); -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/3] Add text file rounding.txt describing how rounding works
From: Søren Sandmann Pedersen It is not entirely obvious how pixman gets from "location in the source image" to "pixel value stored in the destination". This file describes how the filters work, and in particular how positions are rounded to samples. --- pixman/rounding.txt | 134 +++ 1 files changed, 134 insertions(+), 0 deletions(-) create mode 100644 pixman/rounding.txt diff --git a/pixman/rounding.txt b/pixman/rounding.txt new file mode 100644 index 000..1a19f45 --- /dev/null +++ b/pixman/rounding.txt @@ -0,0 +1,134 @@ +*** General notes about rounding + +Suppose a function is sampled at positions [k + o] where k is an +integer and o is a fractional offset 0 <= o < 1. + +To round a value to the nearest sample, breaking ties by rounding up, +we can do this: + + round(x) = floor(x - o + 0.5) + o + +That is, first subtract o to let us pretend that the samples are at +integer coordinates, then add 0.5 and floor to round to nearest +integer, then add the offset back in. + +To break ties by rounding down: + +round(x) = ceil(x - o - 0.5) + o + +or if we have an epsilon value: + +round(x) = floor(x - o + 0.5 - e) + o + +To always round *up* to the next sample: + +round_up(x) = ceil(x - o) + o + +To always round *down* to the previous sample: + +round_down(x) = floor(x - o) + o + +If a set of samples is stored in an array, you get from the sample +position to an index by subtracting the position of the first sample +in the array: + +index(s) = s - first_sample + + +*** Application to pixman + +In pixman, images are sampled with o = 0.5, that is, pixels are +located midways between integers. We usually break ties by rounding +down (i.e., "round towards north-west"). + + +-- NEAREST filtering: + +The NEAREST filter simply picks the closest pixel to the given +position: + +round(x) = floor(x - 0.5 + 0.5 - e) + 0.5 = floor (x - e) + 0.5 + +The first sample of a pixman image has position 0.5, so to find the +index in the pixel array, we have to subtract 0.5: + +floor (x - e) + 0.5 - 0.5 = floor (x - e). + +Therefore a 16.16 fixed-point image location is turned into a pixel +value with NEAREST filtering by doing this: + +pixels[((y - e) >> 16) * stride + ((x - e) >> 16)] + +where stride is the number of pixels allocated per scanline and e = +0x0001. + + +-- CONVOLUTION filtering: + +A convolution matrix is considered a sampling of a function f at +values surrounding 0. For example, this convolution matrix: + + [a, b, c, d] + +is interpreted as the values of a function f: + + a = f(-1.5) +b = f(-0.5) +c = f(0.5) +d = f(1.5) + +The sample offset in this case is o = 0.5 and the first sample has +position s0 = -1.5. If the matrix is: + +[a, b, c, d, e] + +the sample offset is o = 0 and the first sample has position s0 = +-2.0. In general we have + + s0 = (- width / 2.0 + 0.5). + +and + + o = frac (s0) + +To evaluate f at a position between the samples, we round to the +closest sample, and then we subtract the position of the first sample +to get the index in the matrix: + + f(t) = matrix[floor(t - o + 0.5) + o - s0] + +Note that in this case we break ties by rounding up. + +If we write s0 = m + o, where m is an integer, this is equivalent to + +f(t) = matrix[floor(t - o + 0.5) + o - (m + o)] += matrix[floor(t - o + 0.5 - m) + o - o] += matrix[floor(t - s0 + 0.5)] + +The convolution filter in pixman positions f such that 0 aligns with +the given position x. For a given pixel x0 in the image, the closest +sample of f is then computed by taking (x - x0) and rounding that to +the closest index: + + i = floor ((x0 - x) - s0 + 0.5) + +To perform the convolution, we have to find the first pixel x0 whose +corresponding sample has index 0. We can write x0 = k + 0.5, where k +is an integer: + + 0 = floor(k + 0.5 - x - s0 + 0.5) + + = k + floor(1 - x - s0) + + = k - ceil(x + s0 - 1) + + = k - floor(x + s0 - e) + + = k - floor(x - (width - 1) / 2.0 - e) + +And so the final formula for the index k of x0 in the image is: + + k = floor(x - (width - 1) / 2.0 - e) + +Computing the result is then simply a matter of convolving all the +pixels starting at k with all the samples in the matrix. -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] Image resampling [PATCH 0/6]
Hi, Reviewing the supersampling patch here: http://cgit.freedesktop.org/~ajohnson/pixman/log/?h=supersampling I wasn't happy with either the performance and image quality, and I realized that the whole supersampling approach just isn't going to fly. Since I told people to do it that way, I apologize for that. The approach advocated by Bill Spitzak in the various downsampling threads of computing a convolution kernel up front, is the much better way to go. To make up for being misleading, the following patches implement comprehensive support for high-quality image scaling filters. Pixman already has a convolution filter, but since it only allows one sample per pixel of the filter, it is limited in the quality that it can support, so the following patches (to be applied on top of the three rounding patches) add a new filter type PIXMAN_FILTER_SEPARABLE_CONVOLUTION that supports multiple different convolution matrices that are chosen between based on the subpixel source location. The matrices are specified as tensor products of x/y vectors, which makes them separable by definition. The patches also add a helper function pixman_filter_create_separable_convolution() that will create the parameters for the filter based on scaling factors, filter kernels and subsampling resolution. Currently the supported kernels are impulse, box, linear, cubic (Mitchell-Netravali), lanczos2, lanczos3, lanczos3_stretched (aka. Blinn's 'Nice' filter), and Gaussian. There also a new demo program "demos/scale" that shows how the new API can be used. For some useful math regarding image transformations, see http://people.redhat.com/otaylor/gtk/pixbuf-transform-math.ps . For some informatino about how to compute the convolution matrices, see the additions to rounding.txt in the second patch. -=- Adding support to cairo and further work Once these patches have landed in Pixman, support will have to be added to cairo to make use of them. How to do that exactly requires figuring out what new API to offer, and how the tradeoffs between performance and quality should be made. This is not something that I personally plan to work on anytime soon, except to make three notes: - While transformations that are not pure scalings will not generally result in a separable filter, OK-looking results for non-scalings can be achieved by using scaling factors based on the bounding box of a transformation - For equivalent quality to GdkPixbuf do this: In each direction compute the scaling factors and then, if the scaling factor is less than 1 (ie., a downscaling), use PIXMAN_KERNEL_BOX for both reconstruction and sampling, and if it's greater than one, use PIXMAN_KERNEL_LINEAR for reconstruction and PIXMAN_KERNEL_IMPULSE for sampling. - If PIXMAN_KERNEL_GAUSSIAN is used with large downscaling factors and the resulting filter is then used with an identity transform, the result is a Gaussian blur, which is a feature that has sometimes been requested. The code in demos/scale.c may be useful as an example. -=- Further work and examples There is some additional work that could be done: - Performance improvements. Low-hanging fruit includes adding new fast path iterators that assume the source is a8r8g8b8 or r5g6b5. Higher hanging fruit is SIMD optimziations and implementations that take advantage of separability. It may also be interesting to speed up pixman_filter_create_separable_convolution() by tabularizing some of the trigonometric functions etc. - A non-separable, but subsampled, convolution filter type could be interesting to allow correct filters for non-scaling transformations and non-separable filters in general. As a reward for reading this entire mail, here are some images: Original (2.6 MB): http://www.daimi.au.dk/~sandmann/house.jpg Scaled down 12.9 times in each dimension: - With a box filter: http://www.daimi.au.dk/~sandmann/house-box.png - With Lanczos3: http://www.daimi.au.dk/~sandmann/house-lanczos3.png - With stretched Lanczos3: http://www.daimi.au.dk/~sandmann/house-nice.png For more examples, try demos/scale. The patch series is also available in this repository: http://cgit.freedesktop.org/~sandmann/pixman/log/?h=separable Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 4/6] demos/gtk-utils.[ch]: Add pixman_image_from_file()
From: Søren Sandmann Pedersen This function uses GdkPixbuf to load various common formats such as .png and .jpg into a pixman image. --- demos/gtk-utils.c | 66 + demos/gtk-utils.h |3 ++ 2 files changed, 69 insertions(+), 0 deletions(-) diff --git a/demos/gtk-utils.c b/demos/gtk-utils.c index 8291a1e..d7e946d 100644 --- a/demos/gtk-utils.c +++ b/demos/gtk-utils.c @@ -3,6 +3,72 @@ #include "../test/utils.h" #include "gtk-utils.h" +pixman_image_t * +pixman_image_from_file (const char *filename, pixman_format_code_t format) +{ +GdkPixbuf *pixbuf; +pixman_image_t *image; +int width, height; +uint32_t *data, *d; +uint8_t *gdk_data; +int n_channels; +int j, i; +int stride; + +if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL))) + return NULL; + +image = NULL; + +width = gdk_pixbuf_get_width (pixbuf); +height = gdk_pixbuf_get_height (pixbuf); +n_channels = gdk_pixbuf_get_n_channels (pixbuf); +gdk_data = gdk_pixbuf_get_pixels (pixbuf); +stride = gdk_pixbuf_get_rowstride (pixbuf); + +if (!(data = malloc (width * height * sizeof (uint32_t + goto out; + +d = data; +for (j = 0; j < height; ++j) +{ + uint8_t *gdk_line = gdk_data; + + for (i = 0; i < width; ++i) + { + int r, g, b, a; + uint32_t pixel; + + r = gdk_line[0]; + g = gdk_line[1]; + b = gdk_line[2]; + + if (n_channels == 4) + a = gdk_line[3]; + else + a = 0xff; + + r = (r * a + 127) / 255; + g = (g * a + 127) / 255; + b = (b * a + 127) / 255; + + pixel = (a << 24) | (r << 16) | (g << 8) | b; + + *d++ = pixel; + gdk_line += n_channels; + } + + gdk_data += stride; +} + +image = pixman_image_create_bits ( + format, width, height, data, width * 4); + +out: +g_object_unref (pixbuf); +return image; +} + GdkPixbuf * pixbuf_from_argb32 (uint32_t *bits, int width, diff --git a/demos/gtk-utils.h b/demos/gtk-utils.h index 55cb701..36be4de 100644 --- a/demos/gtk-utils.h +++ b/demos/gtk-utils.h @@ -6,6 +6,9 @@ void show_image (pixman_image_t *image); +pixman_image_t * +pixman_image_from_file (const char *filename, pixman_format_code_t format); + GdkPixbuf *pixbuf_from_argb32 (uint32_t *bits, int width, int height, -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/6] Add new filter PIXMAN_FILTER_SEPARABLE_CONVOLUTION
From: Søren Sandmann Pedersen This filter is a new way to use a convolution matrix for filtering. In contrast to the existing CONVOLUTION filter, this new variant is different in two respects: - It is subsampled: Instead of just one convolution matrix, this filter chooses between a number of matrices based on the subpixel sample location, allowing the convolution kernel to be sampled at a higher resolution. - It is separable: Each matrix is specified as the tensor product of two vectors. This has the advantages that many fewer values have to be stored, and that the filtering can be done separately in the x and y dimensions (although the initial implementation doesn't actually do that). The motivation for this new filter is to improve image downsampling quality. Currently, the best pixman can do is the regular convolution filter which is limited to coarsely sampled convolution kernels. With this new feature, any separable filter can be used at any desired resolution. --- pixman/pixman-bits-image.c | 102 pixman/pixman-image.c | 19 +++- pixman/pixman.c|8 +++ pixman/pixman.h| 23 +- 4 files changed, 149 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 7787ef1..97db108 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -426,6 +426,104 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); } +static uint32_t +bits_image_fetch_pixel_convolution_separable (bits_image_t *image, + pixman_fixed_t x, + pixman_fixed_t y, + get_pixel_tget_pixel) +{ +pixman_fixed_t *params = image->common.filter_params; +pixman_repeat_t repeat_mode = image->common.repeat; +int width = image->width; +int height = image->height; +int cwidth = pixman_fixed_to_int (params[0]); +int cheight = pixman_fixed_to_int (params[1]); +int x_phase_bits = pixman_fixed_to_int (params[2]); +int y_phase_bits = pixman_fixed_to_int (params[3]); +int x_phase_shift = 16 - x_phase_bits; +int y_phase_shift = 16 - y_phase_bits; +int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; +int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; +pixman_fixed_t *y_params; +int srtot, sgtot, sbtot, satot; +int32_t x1, x2, y1, y2; +int32_t px, py; +int i, j; + +/* Round x and y to the middle of the closest phase before continuing. This + * ensures that the convolution matrix is aligned right, since it was + * positioned relative to a particular phase (and not relative to whatever + * exact fraction we happen to get here). + */ +x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); +y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); + +px = (x & 0x) >> x_phase_shift; +py = (y & 0x) >> y_phase_shift; + +y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; + +x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); +y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); +x2 = x1 + cwidth; +y2 = y1 + cheight; + +srtot = sgtot = sbtot = satot = 0; + +for (i = y1; i < y2; ++i) +{ +pixman_fixed_48_16_t fy = *y_params++; +pixman_fixed_t *x_params = params + 4 + px * cwidth; + +if (fy) +{ +for (j = x1; j < x2; ++j) +{ +pixman_fixed_t fx = *x_params++; + int rx = j; + int ry = i; + +if (fx) +{ +pixman_fixed_t f; +uint32_t pixel; + +if (repeat_mode != PIXMAN_REPEAT_NONE) +{ +repeat (repeat_mode, &rx, width); +repeat (repeat_mode, &ry, height); + +pixel = get_pixel (image, rx, ry, FALSE); +} +else +{ +pixel = get_pixel (image, rx, ry, TRUE); + } + +f = (fy * fx + 0x8000) >> 16; + +srtot += (int)RED_8 (pixel) * f; +sgtot += (int)GREEN_8 (pixel) * f; +sbtot += (int)BLUE_8 (pixel) * f; +satot += (int)ALPHA_8 (pixel) * f; +} +} + } +} + +satot = (satot + 0x8000) >> 16; +srtot = (srtot + 0x8000) >> 16; +sgtot = (sgtot + 0x8000) >> 16; +sbtot = (sbtot + 0x8000) >> 16; + +
[Pixman] [PATCH 2/6] rounding.txt: Describe how SEPARABLE_CONVOLUTION filter works
From: Søren Sandmann Pedersen Add some notes on how to compute the convolution matrices to be used with the SEPARABLE_CONVOLUTION filter. --- pixman/rounding.txt | 33 + 1 files changed, 33 insertions(+), 0 deletions(-) diff --git a/pixman/rounding.txt b/pixman/rounding.txt index 1a19f45..b52b084 100644 --- a/pixman/rounding.txt +++ b/pixman/rounding.txt @@ -132,3 +132,36 @@ And so the final formula for the index k of x0 in the image is: Computing the result is then simply a matter of convolving all the pixels starting at k with all the samples in the matrix. + + +--- SEPARABLE_CONVOLUTION + +For this filter, x is first rounded to one of n regularly spaced +subpixel positions. This subpixel position determines which of n +convolution matrices is being used. + +Then, as in a regular convolution filter, the first pixel to be used +is determined: + + k = floor (x - (width - 1) / 2.0 - e) + +and then the image pixels starting there are convolved with the chosen +matrix. If we write x = xi + frac, where xi is an integer, we get + + k = xi + floor (frac - (width - 1) / 2.0 - e) + +so the location of k relative to x is given by: + +(k + 0.5 - x) = xi + floor (frac - (width - 1) / 2.0 - e) + 0.5 - x + + = floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac + +which means the contents of the matrix corresponding to (frac) should +contain width samplings of the function, with the first sample at: + + floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac + +This filter is called separable because each of the k x k convolution +matrices is specified with two k-wide vectors, one for each dimension, +where each entry in the matrix is computed as the product of the +corresponding entries in the vectors. -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/6] Add new pixman_filter_create_separable_convolution() API
From: Søren Sandmann Pedersen This new API is a helper function to create filter parameters suitable for use with PIXMAN_FILTER_SEPARABLE_CONVOLUTION. For each dimension, given a scale factor, reconstruction and sample filter kernels, and a subsampling resolution, this function will compute a convolution of the two kernels scaled appropriately, then sample that convolution and return the resulting vectors in a form suitable for being used as parameters to PIXMAN_FILTER_SEPARABLE_CONVOLUTION. The filter kernels offered are the following: - IMPULSE:Dirac delta function, ie., point sampling - BOX:Box filter - LINEAR: Linear filter, aka. "Tent" filter - CUBIC: Cubic filter, currently Mitchell-Netravali - GAUSSIAN: Gaussian function, sigma=1, support=3*sigma - LANCZOS2: Two-lobed Lanczos filter - LANCZOS3: Three-lobed Lanczos filter - LANCZOS3_STRETCHED: Three-lobed Lanczos filter, stretched by 4/3.0. This is the "Nice" filter from Dirty Pixels by Jim Blinn. The intended way to use this function is to extract scaling factors from the transformation and then pass those to this function to get a filter suitable for compositing with that transformation. The filter kernels can be chosen according to quality and performance tradeoffs. To get equivalent quality to GdkPixbuf for downscalings, use BOX for both reconstruction and sampling. For upscalings, use LINEAR for reconstruction and IMPULSE for sampling (though note that for upscaling in both X and Y directions, simply using PIXMAN_FILTER_BILINEAR will likely be a better choice). --- pixman/Makefile.sources |1 + pixman/pixman-filter.c | 340 +++ pixman/pixman.h | 27 3 files changed, 368 insertions(+), 0 deletions(-) create mode 100644 pixman/pixman-filter.c diff --git a/pixman/Makefile.sources b/pixman/Makefile.sources index 5351fb0..c624eb9 100644 --- a/pixman/Makefile.sources +++ b/pixman/Makefile.sources @@ -6,6 +6,7 @@ libpixman_sources = \ pixman-combine32.c \ pixman-combine-float.c \ pixman-conical-gradient.c \ + pixman-filter.c \ pixman-x86.c\ pixman-mips.c \ pixman-arm.c\ diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c new file mode 100644 index 000..c9d2dc7 --- /dev/null +++ b/pixman/pixman-filter.c @@ -0,0 +1,340 @@ +/* + * Copyright 2012, Red Hat, Inc. + * Copyright 2012, Soren Sandmann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann + */ +#include +#include +#include +#include +#include +#include +#include "pixman-private.h" + +typedef double (* kernel_func_t) (double x); + +typedef struct +{ +pixman_kernel_tkernel; +kernel_func_t func; +double width; +} filter_info_t; + +static double +impulse_kernel (double x) +{ +return (x == 0.0)? 1.0 : 0.0; +} + +static double +box_kernel (double x) +{ +return 1; +} + +static double +linear_kernel (double x) +{ +return 1 - fabs (x); +} + +static double +gaussian_kernel (double x) +{ +#define SQRT2 (1.4142135623730950488016887242096980785696718753769480) +#define SIGMA (SQRT2 / 2.0) + +return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI)); +} + +static double +sinc (double x) +{ +if (x == 0.0) + return 1.0; +else + return sin (M_PI * x) / (M_PI * x); +} + +static double +lanczos (double x, int n) +{ +return sinc (x) * sinc (x * (1.0 / n)); +} + +static double +lanczos2_kernel (double x) +{ +return lanczos (x, 2); +} + +static double +lanczos3_kernel (dou
[Pixman] [PATCH 5/6] demos: Add new demo program, "scale"
From: Søren Sandmann Pedersen This program allows interactively scaling and rotating images with using various filters and repeat modes. It uses pixman_filter_create_separate_convolution() to generate the filters. --- demos/Makefile.am |6 +- demos/scale.c | 431 + demos/scale.ui| 302 + 3 files changed, 737 insertions(+), 2 deletions(-) create mode 100644 demos/scale.c create mode 100644 demos/scale.ui diff --git a/demos/Makefile.am b/demos/Makefile.am index f324f5f..ffb7a6b 100644 --- a/demos/Makefile.am +++ b/demos/Makefile.am @@ -22,9 +22,10 @@ DEMOS = \ quad2quad \ checkerboard\ srgb-trap-test \ - srgb-test + srgb-test \ + scale -EXTRA_DIST = parrot.c parrot.jpg +EXTRA_DIST = parrot.c parrot.jpg scale.ui gradient_test_SOURCES = gradient-test.c $(GTK_UTILS) alpha_test_SOURCES = alpha-test.c $(GTK_UTILS) @@ -39,6 +40,7 @@ tri_test_SOURCES = tri-test.c $(GTK_UTILS) checkerboard_SOURCES = checkerboard.c $(GTK_UTILS) srgb_test_SOURCES = srgb-test.c $(GTK_UTILS) srgb_trap_test_SOURCES = srgb-trap-test.c $(GTK_UTILS) +scale_SOURCES = scale.c $(GTK_UTILS) noinst_PROGRAMS = $(DEMOS) diff --git a/demos/scale.c b/demos/scale.c new file mode 100644 index 000..9100ff7 --- /dev/null +++ b/demos/scale.c @@ -0,0 +1,431 @@ +/* + * Copyright 2012, Red Hat, Inc. + * Copyright 2012, Soren Sandmann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include "gtk-utils.h" + +typedef struct +{ +GtkBuilder *builder; +pixman_image_t * original; +GtkAdjustment * scale_x_adjustment; +GtkAdjustment * scale_y_adjustment; +GtkAdjustment * rotate_adjustment; +int scaled_width; +int scaled_height; +} app_t; + +static GtkWidget * +get_widget (app_t *app, const char *name) +{ +GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (app->builder, name)); + +if (!widget) +g_error ("Widget %s not found\n", name); + +return widget; +} + +static double +min4 (double a, double b, double c, double d) +{ +double m1, m2; + +m1 = MIN (a, b); +m2 = MIN (c, d); +return MIN (m1, m2); +} + +static double +max4 (double a, double b, double c, double d) +{ +double m1, m2; + +m1 = MAX (a, b); +m2 = MAX (c, d); +return MAX (m1, m2); +} + +static void +compute_extents (pixman_f_transform_t *trans, double *sx, double *sy) +{ +double min_x, max_x, min_y, max_y; +pixman_f_vector_t v[4] = +{ + { { 1, 1, 1 } }, + { { -1, 1, 1 } }, + { { -1, -1, 1 } }, + { { 1, -1, 1 } }, +}; + +pixman_f_transform_point (trans, &v[0]); +pixman_f_transform_point (trans, &v[1]); +pixman_f_transform_point (trans, &v[2]); +pixman_f_transform_point (trans, &v[3]); + +min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); +max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); +min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); +max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); + +*sx = (max_x - min_x) / 2.0; +*sy = (max_y - min_y) / 2.0; +} + +typedef struct +{ +char name [20]; +pixman_kernel_tvalue; +} named_int_t; + +static const named_int_t filters[] = +{ +{ "Box", PIXMAN_KERNEL_BOX }, +{ "Impulse", PIXMAN_KERNEL_IMPULSE }, +{ "Linear",PIXMAN_KERNEL_LINEAR }, +{ "Cubic",
Re: [Pixman] [PATCH 6/6] Add demos/zone_plate.png
Siarhei Siamashka writes: > Hi, the size of this PNG file can be cut in half: > > $ optipng -o7 zone_plate.png > ** Processing: zone_plate.png > 512x512 pixels, 3x8 bits/pixel, RGB > Reducing image to 8 bits/pixel, grayscale > Input IDAT size = 522048 bytes > Input file size = 522879 bytes Good point. I'll run it through optipng before pushing. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] Image resampling [PATCH 0/6]
Søren Sandmann writes: > There is some additional work that could be done: > > - Performance improvements. Low-hanging fruit includes adding new fast > path iterators that assume the source is a8r8g8b8 or r5g6b5. I went ahead and wrote some affine fast paths. There is still room for improvement though. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add fast paths for separable convolution
From: Søren Sandmann Pedersen Similar to the fetchers for affine bilinear and nearest, add some fast paths for the separable convolution filter for all combinations of formats x8r8g8b8, a8r8g8b8, r5g6b5, a8 with the four repeat modes. On a 1.2GHz AMD Phenom the time to scale down a 3200x1200 image by 9.22 went from 0.2238s to 0.1875s, an improvement of about 16%. For comparison GdkPixbuf does the same thing in about 0.07s, so there is still a lot of room for improvement. --- pixman/pixman-bits-image.c | 183 +++- pixman/pixman-image.c |3 + pixman/pixman-private.h|1 + 3 files changed, 184 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index e76b78c..86d80c3 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -720,11 +720,155 @@ bits_image_fetch_general (pixman_iter_t *iter, return buffer; } -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_separable_convolution_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) +{ +bits_image_t *bits = &image->bits; +pixman_fixed_t *params = image->common.filter_params; +int cwidth = pixman_fixed_to_int (params[0]); +int cheight = pixman_fixed_to_int (params[1]); +int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; +int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; +int x_phase_bits = pixman_fixed_to_int (params[2]); +int y_phase_bits = pixman_fixed_to_int (params[3]); +int x_phase_shift = 16 - x_phase_bits; +int y_phase_shift = 16 - y_phase_bits; +pixman_fixed_t vx, vy; +pixman_fixed_t ux, uy; +pixman_vector_t v; +int k; + +/* 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]; + +vx = v.vector[0]; +vy = v.vector[1]; + +for (k = 0; k < width; ++k) +{ + pixman_fixed_t *y_params; + int satot, srtot, sgtot, sbtot; + pixman_fixed_t x, y; + int32_t x1, x2, y1, y2; + int32_t px, py; + int i, j; + + if (mask && !mask[k]) + goto next; + + /* Round x and y to the middle of the closest phase before continuing. This +* ensures that the convolution matrix is aligned right, since it was +* positioned relative to a particular phase (and not relative to whatever +* exact fraction we happen to get here). +*/ + x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); + y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); + + px = (x & 0x) >> x_phase_shift; + py = (y & 0x) >> y_phase_shift; + + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); + x2 = x1 + cwidth; + y2 = y1 + cheight; + + satot = srtot = sgtot = sbtot = 0; + + y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; + + for (i = y1; i < y2; ++i) + { + pixman_fixed_t fy = *y_params++; + + if (fy) + { + pixman_fixed_t *x_params = params + 4 + px * cwidth; + + for (j = x1; j < x2; ++j) + { + pixman_fixed_t fx = *x_params++; + int rx = j; + int ry = i; + + if (fx) + { + pixman_fixed_t f; + uint32_t pixel, mask; + uint8_t *row; + + mask = PIXMAN_FORMAT_A (format)? 0 : 0xff00; + + if (repeat_mode != PIXMAN_REPEAT_NONE) + { + repeat (repeat_mode, &rx, bits->width); + repeat (re
Re: [Pixman] [PATCH 0/5] PRNG upgrade for pixman tests
Siarhei Siamashka writes: > A simple linear congruential generator (LCG) has been used for pixman > test suite since the introduction of the tests based on random fuzzing. > There was no particular reason why it was selected. The compilers are > traditionally using LCG. So just implementing LCG for pixman tests, we > got it as good (and as bad) as "rand" from the C library, but > deterministic, predictable and fully under our control. > > But LCG has some practical issues, which are already showing up: This patch series looks like a very nice improvement. Excellent work as always. > As for the SIMD implementation, I decided to take a somewhat unusual > approach. Typically one uses CPU-specific intrinsics. This provides > support for just one hardware platform (let's say x86 SSE2), but > with a choice of multiple compilers (gcc, clang, icc, ...). I decided > to do this the other way around :) And implemented the code using > the GCC specific vector extensions: > http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html > This means that just a single compiler is supported (GCC 4.7 or newer), > but the code is quite conveniently optimized for multiple platforms at > once (x86 SSE2, ARM NEON, PPC Altivec, ...). It might be interesting to try using these extensions within pixman itself as a fallback for the cases where we don't have CPU specific fast paths. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Add demo program for conical gradients
From: Søren Sandmann Pedersen This new test is derived from radial-test.c and displays conical gradients at various angles. It also demonstrates how PIXMAN_REPEAT_NORMAL is supposed to work when used with a gradient specification where the first stop is not a 0.0: In this case the gradient is supposed to have a smooth transition from the last stop back to the first stop with no sharp transitions. It also shows that the repeat mode is not ignored for conical gradients as one might be tempted to think. --- demos/Makefile.am|2 + demos/conical-test.c | 134 ++ 2 files changed, 136 insertions(+), 0 deletions(-) create mode 100644 demos/conical-test.c diff --git a/demos/Makefile.am b/demos/Makefile.am index ffb7a6b..4d88cb8 100644 --- a/demos/Makefile.am +++ b/demos/Makefile.am @@ -14,6 +14,7 @@ DEMOS = \ composite-test \ gradient-test \ radial-test \ + conical-test\ alpha-test \ screen-test \ convolution-test\ @@ -36,6 +37,7 @@ trap_test_SOURCES = trap-test.c $(GTK_UTILS) screen_test_SOURCES = screen-test.c $(GTK_UTILS) convolution_test_SOURCES = convolution-test.c $(GTK_UTILS) radial_test_SOURCES = radial-test.c $(GTK_UTILS) +conical_test_SOURCES = conical-test.c $(GTK_UTILS) tri_test_SOURCES = tri-test.c $(GTK_UTILS) checkerboard_SOURCES = checkerboard.c $(GTK_UTILS) srgb_test_SOURCES = srgb-test.c $(GTK_UTILS) diff --git a/demos/conical-test.c b/demos/conical-test.c new file mode 100644 index 000..1e08e42 --- /dev/null +++ b/demos/conical-test.c @@ -0,0 +1,134 @@ +#include "../test/utils.h" +#include "gtk-utils.h" + +#define SIZE 128 +#define GRADIENTS_PER_ROW 7 +#define NUM_ROWS ((NUM_GRADIENTS + GRADIENTS_PER_ROW - 1) / GRADIENTS_PER_ROW) +#define WIDTH (SIZE * GRADIENTS_PER_ROW) +#define HEIGHT (SIZE * NUM_ROWS) +#define NUM_GRADIENTS 35 + +#define double_to_color(x) \ +(((uint32_t) ((x)*65536)) - (((uint32_t) ((x)*65536)) >> 16)) + +#define PIXMAN_STOP(offset,r,g,b,a)\ +{ pixman_double_to_fixed (offset), \ + { \ + double_to_color (r),\ + double_to_color (g),\ + double_to_color (b),\ + double_to_color (a) \ + } \ +} + + +static const pixman_gradient_stop_t stops[] = { +PIXMAN_STOP (0.25, 1, 0, 0, 0.7), +PIXMAN_STOP (0.5,1, 1, 0, 0.7), +PIXMAN_STOP (0.75, 0, 1, 0, 0.7), +PIXMAN_STOP (1.0,0, 0, 1, 0.7) +}; + +#define NUM_STOPS (sizeof (stops) / sizeof (stops[0])) + +static pixman_image_t * +create_conical (int index) +{ +pixman_point_fixed_t c; +double angle; + +c.x = pixman_double_to_fixed (0); +c.y = pixman_double_to_fixed (0); + +angle = (0.5 / NUM_GRADIENTS + index / (double)NUM_GRADIENTS) * 720 - 180; + +return pixman_image_create_conical_gradient ( + &c, pixman_double_to_fixed (angle), stops, NUM_STOPS); +} + +#define CHECK_SIZE 25 + +static void +fill_checkerboard (pixman_image_t *image, int width, int height) +{ +#define C1 0x +#define C2 0x + +pixman_color_t check1 = { C1, C1, C1, 0x }; +pixman_color_t check2 = { C2, C2, C2, 0x }; +pixman_image_t *c1, *c2; +int i, j; + +c1 = pixman_image_create_solid_fill (&check1); +c2 = pixman_image_create_solid_fill (&check2); + +for (j = 0; j < height; j += CHECK_SIZE) +{ + for (i = 0; i < width; i += CHECK_SIZE) + { + pixman_image_t *src; + + if i / CHECK_SIZE) ^ (j / CHECK_SIZE)) & 1) == 0) + src = c1; + else + src = c2; + + pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, + 0, 0, 0, 0, i, j, + CHECK_SIZE, CHECK_SIZE); + } +} +} + +int +main (int argc, char **argv) +{ +pixman_transform_t transform; +pixman_image_t *src_img, *dest_img; +int i; + +enable_divbyzero_exceptions (); + +dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, +WIDTH, HEIGHT, +NULL, 0); + +fill_checkerboard (dest_img, WIDTH, HEIGHT); + +pixman_transform_init_identity (&transform); + +pixman_transform_translate (NULL, &transform, + pixman_double_to_fixed (0.5), + pixman_double_to_fixed (0.5)); + +pixman_transform_scale (NULL, &transform, + pixman_double_to_fixed (SIZE), + pixman_double_to_fixe
Re: [Pixman] [cairo] Cairo/pixman behavior with large translations
Siarhei Siamashka writes: > The main culprits are functions pixman_transform_point_3d() and > pixman_transform_point() here: > > http://cgit.freedesktop.org/pixman/tree/pixman/pixman-matrix.c?id=pixman-0.28.0#n49 > They perform multiplication of a matrix (16.16 fixed point) with a > vector (16.16 fixed point), to get a vector with 16.16 fixed point > values. This code can be upgraded to perform multiplication of the same > 16.16 fixed point matrix, but use something like 31.16 fixed point > for input vectors and get results in the 48.16 fixed point output > vectors. The caller then should be able to deal with the 48.16 > results depending on the type of repeat set for the image. One > example is here: > > http://cgit.freedesktop.org/pixman/tree/pixman/pixman-inlines.h?id=pixman-0.28.0#n417 > In this code, the "src_x" and "src_y" arguments are originally coming > from pixman_image_composite32() function and are already supposed to be > larger than 16 bits after the following commit: > > http://cgit.freedesktop.org/pixman/commit/?id=e841c556d59ca0aa6d86eaf6dbf061ae0f4287de > If they are getting converted to fixed point, we already get something > like 32.16 fixed point values which are asking for a larger vector > argument for pixman_transform_point_3d() function (though we might > want not to allow the use of full 32-bit range for "src_x" and "src_y" > in order to keep some headroom and safeguard against overflows). In any > case, immediately after pixman_transform_point_3d() we are > tweaking v.vector[0] and v.vector[1] according to the repeat type: > > http://cgit.freedesktop.org/pixman/tree/pixman/pixman-inlines.h?id=pixman-0.28.0#n432 > Updating this code ("repeat" and "pad_repeat_get_scanline_bounds" > functions) to deal with 48.16 fixed point values from the vector can't > be too hard. There is really a lot to be said for this 31.16 format. Intermediate results from matrix and vector multiplications fit in 64 bits, and image access coordinates up to +/- 1 billion pixels can be supported. Yet it is still a fixed-point format so there won't be any weird effects where positions are rounded differently depending on where they are on the screen. If 64 bit coordinates become a performance problem, a new flag, "FAST_PATH_16_16_IS_ENOUGH" or something, could be added so that fast paths could use 32 bit coordinates. (We used to have something like this before pixman started to just return without compositing when it detects overflow). It's very tempting to switch pixman over to using this format internally. The one thing I'm not sure of is whether this bug: https://bugs.freedesktop.org/show_bug.cgi?id=15355 "Under a non-affine transform, or, in fact, any transform where the 'w' component of the (u,v,w) homogeneous source coordinate is not 1, the representation of u,v,w as 16.16 fixed point numbers will over/under flow on a regular basis even given fairly mundane transformations (like a simple keystone correction). I've fixed the intel driver to do these computations in floating point; I'm not sure we want to try to use fixed point here." is adequately taken care off by using this format. It's worth pointing out that even if there are useful non-affine transformations that still overflow, a homogeneous transformation matrix doesn't change if multiplied or divided by an arbitrary constant, so if worse comes to worst, we could drop precision by rounding the overflowing result down to 47 bits and then dividing all the other entries by a similar amount, in effect faking a floating point type. Keith, comments on this would definitely be appreciated. For the RandR use cases, would 31.16 be good enough? Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [cairo] Cairo/pixman behavior with large translations
Søren Sandmann writes: > Intermediate results from matrix and vector multiplications fit in 64 > bits, and That is, as long as the final result doesn't overflow the 31.16 type, the intermediate values fit in 64 bits. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/2] demos/radial-test: Add zero-radius circles to demonstrate rendering bugs
From: Søren Sandmann Pedersen Add two new gradients: one where the start circle is degenerate with a radius of 0, and one where the end circle is degenerate. All the new gradients except the one with degenerate start circle and REPEAT_NONE are rendered with a bright dot in the middle. In most but not all cases this is incorrect. Cc: ranm...@gmail.com --- demos/radial-test.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/demos/radial-test.c b/demos/radial-test.c index e64f357..203ad68 100644 --- a/demos/radial-test.c +++ b/demos/radial-test.c @@ -1,7 +1,7 @@ #include "../test/utils.h" #include "gtk-utils.h" -#define NUM_GRADIENTS 7 +#define NUM_GRADIENTS 9 #define NUM_STOPS 3 #define NUM_REPEAT 4 #define SIZE 128 @@ -28,6 +28,9 @@ * centers (0, 0) and (1, 0), but with different radiuses. From left * to right: * + * - Degenerate start circle completely inside the end circle + * 0.00 -> 1.75; dr = 1.75 > 0; a = 1 - 1.75^2 < 0 + * * - Small start circle completely inside the end circle * 0.25 -> 1.75; dr = 1.5 > 0; a = 1 - 1.50^2 < 0 * @@ -49,15 +52,20 @@ * - Small end circle completely inside the start circle * 1.75 -> 0.25; dr = -1.5 > 0; a = 1 - 1.50^2 < 0 * + * - Degenerate end circle completely inside the start circle + * 0.00 -> 1.75; dr = 1.75 > 0; a = 1 - 1.75^2 < 0 + * */ const static double radiuses[NUM_GRADIENTS] = { +0.00, 0.25, 0.50, 0.50, 1.00, 1.00, 1.50, +1.75, 1.75 }; -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/2] radial: When comparing the compute t to mindr, use >= rather than >
From: Søren Sandmann Pedersen It is legitimate for t * dr value to be exactly equal to the minimum dr. This happens when the sampled point is precisely on the edge of the c1 circle, or exactly on the center of c1 when its radius is 0. This fixes the dots in demos/radial-test.c except for two: When the c2 circle has radius 0 and a repeat mode of NONE, the dot remains. When the repeat mode is NORMAL, the dot is now red where it used to be white. Before these cases correspond to a t value of 1.0, which we generally treat as a value that is outside the gradient's defined interval [0.0,1) and is therefore subject to the repeat algorithm. Given this, in the repeat==NONE case, a value of 1.0 is expected to generate a value of { 0, 0, 0, 0 }. In the repeat==NORMAL, it wraps around and becomes the value at 0.0, which is red in radial-test. Cc: ranm...@gmail.com --- pixman/pixman-radial-gradient.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c index 8d56246..6a21796 100644 --- a/pixman/pixman-radial-gradient.c +++ b/pixman/pixman-radial-gradient.c @@ -109,7 +109,7 @@ radial_compute_color (doublea, } else { - if (t * dr > mindr) + if (t * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t); } @@ -145,9 +145,9 @@ radial_compute_color (doublea, } else { - if (t0 * dr > mindr) + if (t0 * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t0); - else if (t1 * dr > mindr) + else if (t1 * dr >= mindr) return _pixman_gradient_walker_pixel (walker, t1); } } -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/3] test/utils.[ch]: Add utility function to draw a checkerboard
From: Søren Sandmann Pedersen This is useful in demo programs to display the alpha channel. --- test/utils.c | 54 ++ test/utils.h | 5 + 2 files changed, 59 insertions(+) diff --git a/test/utils.c b/test/utils.c index 66c8dcb..08eaabb 100644 --- a/test/utils.c +++ b/test/utils.c @@ -548,6 +548,60 @@ write_png (pixman_image_t *image, const char *filename) #endif +static void +color8_to_color16 (uint32_t color8, pixman_color_t *color16) +{ +color16->alpha = ((color8 & 0xff00) >> 24); +color16->red = ((color8 & 0x00ff) >> 16); +color16->green = ((color8 & 0xff00) >> 8); +color16->blue = ((color8 & 0x00ff) >> 0); + +color16->alpha |= color16->alpha << 8; +color16->red |= color16->red << 8; +color16->blue |= color16->blue << 8; +color16->green |= color16->green << 8; +} + +void +draw_checkerboard (pixman_image_t *image, + int check_size, + uint32_t color1, uint32_t color2) +{ +pixman_color_t check1, check2; +pixman_image_t *c1, *c2; +int n_checks_x, n_checks_y; +int i, j; + +color8_to_color16 (color1, &check1); +color8_to_color16 (color2, &check2); + +c1 = pixman_image_create_solid_fill (&check1); +c2 = pixman_image_create_solid_fill (&check2); + +n_checks_x = ( + pixman_image_get_width (image) + check_size - 1) / check_size; +n_checks_y = ( + pixman_image_get_height (image) + check_size - 1) / check_size; + +for (j = 0; j < n_checks_y; j++) +{ + for (i = 0; i < n_checks_x; i++) + { + pixman_image_t *src; + + if (((i ^ j) & 1)) + src = c1; + else + src = c2; + + pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, + 0, 0, 0, 0, + i * check_size, j * check_size, + check_size, check_size); + } +} +} + /* * A function, which can be used as a core part of the test programs, * intended to detect various problems with the help of fuzzing input diff --git a/test/utils.h b/test/utils.h index 78cf0d1..45b457e 100644 --- a/test/utils.h +++ b/test/utils.h @@ -124,6 +124,11 @@ a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels); pixman_bool_t write_png (pixman_image_t *image, const char *filename); +void +draw_checkerboard (pixman_image_t *image, + int check_size, + uint32_t color1, uint32_t color2); + /* 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.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 2/3] demos/conical-test: Use the draw_checkerboard() utility function
From: Søren Sandmann Pedersen Instead of having its own copy. --- demos/conical-test.c | 38 ++ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/demos/conical-test.c b/demos/conical-test.c index 1e08e42..6b32430 100644 --- a/demos/conical-test.c +++ b/demos/conical-test.c @@ -46,40 +46,6 @@ create_conical (int index) &c, pixman_double_to_fixed (angle), stops, NUM_STOPS); } -#define CHECK_SIZE 25 - -static void -fill_checkerboard (pixman_image_t *image, int width, int height) -{ -#define C1 0x -#define C2 0x - -pixman_color_t check1 = { C1, C1, C1, 0x }; -pixman_color_t check2 = { C2, C2, C2, 0x }; -pixman_image_t *c1, *c2; -int i, j; - -c1 = pixman_image_create_solid_fill (&check1); -c2 = pixman_image_create_solid_fill (&check2); - -for (j = 0; j < height; j += CHECK_SIZE) -{ - for (i = 0; i < width; i += CHECK_SIZE) - { - pixman_image_t *src; - - if i / CHECK_SIZE) ^ (j / CHECK_SIZE)) & 1) == 0) - src = c1; - else - src = c2; - - pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, - 0, 0, 0, 0, i, j, - CHECK_SIZE, CHECK_SIZE); - } -} -} - int main (int argc, char **argv) { @@ -92,8 +58,8 @@ main (int argc, char **argv) dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, NULL, 0); - -fill_checkerboard (dest_img, WIDTH, HEIGHT); + +draw_checkerboard (dest_img, 25, 0xffaa, 0xff88); pixman_transform_init_identity (&transform); -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/3] demos/radial-test: Add checkerboard to display the alpha channel
From: Søren Sandmann Pedersen --- demos/radial-test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demos/radial-test.c b/demos/radial-test.c index 203ad68..08a367c 100644 --- a/demos/radial-test.c +++ b/demos/radial-test.c @@ -147,6 +147,8 @@ main (int argc, char **argv) WIDTH, HEIGHT, NULL, 0); +draw_checkerboard (dest_img, 25, 0xffaa, 0xffbb); + pixman_transform_init_identity (&transform); /* -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] Subject: [ANNOUNCE] pixman release 0.28.2 now available
A new pixman release 0.28.2 is now available. This stable release in the 0.28 series contains fixes for 64 bit Windows, clang, and PowerPC on MacOS and OpenBSD. Søren tar.gz: http://cairographics.org/releases/pixman-0.28.2.tar.gz http://xorg.freedesktop.org/archive/individual/lib/pixman-0.28.2.tar.gz tar.bz2: http://xorg.freedesktop.org/archive/individual/lib/pixman-0.28.2.tar.bz2 Hashes: MD5: f68916a612921c24e5f94f1eae71d121 pixman-0.28.2.tar.gz MD5: f6e3294c4edb7b6bca8459e604286348 pixman-0.28.2.tar.bz2 SHA1: fd81193e3d970a4a44f8c3818fc10cb449fdca8b pixman-0.28.2.tar.gz SHA1: 9e9ede6e13061030f9c827219cb87f47e32ecdb4 pixman-0.28.2.tar.bz2 GPG signature: http://cairographics.org/releases/pixman-0.28.2.tar.gz.sha1.asc (signed by Søren Sandmann Pedersen ) Git: git://git.freedesktop.org/git/pixman tag: pixman-0.28.2 Log: Benjamin Gilbert (1): Fix thread safety on mingw-w64 and clang Joshua Root (1): Fix undeclared variable use and sysctlbyname error handling on ppc Stefan Weil (1): Always use xmmintrin.h for 64 bit Windows Søren Sandmann Pedersen (2): Post-release version bump to 0.28.1 Pre-release version bump to 0.28.2 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 1/3] Add testing of trapezoids to stress-test
From: Søren Sandmann Pedersen The entry points add_trapezoids(), rasterize_trapezoid() and composite_trapezoid() are exercised with random trapezoids. This uncovers crashes with stress-test seeds 0x17ee and 0x313c. --- test/stress-test.c | 160 - 1 file changed, 135 insertions(+), 25 deletions(-) diff --git a/test/stress-test.c b/test/stress-test.c index ee55c21..9d949af 100644 --- a/test/stress-test.c +++ b/test/stress-test.c @@ -205,8 +205,29 @@ rand_y (pixman_image_t *image) return log_rand (); } +static pixman_format_code_t +random_format (pixman_bool_t prefer_alpha) +{ +pixman_format_code_t format; +int n = prng_rand_n (ARRAY_LENGTH (image_formats)); + +if (prefer_alpha && prng_rand_n (4) != 0) +{ +do +{ +format = image_formats[n++ % ARRAY_LENGTH (image_formats)]; +} while (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_A); +} +else +{ +format = image_formats[n]; +} + +return format; +} + static pixman_image_t * -create_random_bits_image (void) +create_random_bits_image (pixman_bool_t prefer_alpha) { pixman_format_code_t format; pixman_indexed_t *indexed; @@ -220,7 +241,7 @@ create_random_bits_image (void) int n_coefficients = 0; /* format */ -format = image_formats[prng_rand_n (ARRAY_LENGTH (image_formats))]; +format = random_format (prefer_alpha); indexed = NULL; if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) @@ -389,7 +410,7 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) pixman_image_t *alpha_map; int16_t x, y; - alpha_map = create_random_bits_image (); + alpha_map = create_random_bits_image (FALSE); if (alpha_map) { @@ -695,7 +716,7 @@ create_random_image (void) { default: case 0: - result = create_random_bits_image (); + result = create_random_bits_image (FALSE); break; case 1: @@ -721,6 +742,39 @@ create_random_image (void) return result; } +static void +random_line (pixman_line_fixed_t *line, int width, int height) +{ +line->p1.x = prng_rand_n (width) << 16; +line->p1.y = prng_rand_n (height) << 16; +line->p2.x = prng_rand_n (width) << 16; +line->p2.y = prng_rand_n (height) << 16; +} + +static pixman_trapezoid_t * +create_random_trapezoids (int *n_traps, int height, int width) +{ +pixman_trapezoid_t *trapezoids; +int i; + +*n_traps = prng_rand_n (16) + 1; + +trapezoids = malloc (sizeof (pixman_trapezoid_t) * *n_traps); + +for (i = 0; i < *n_traps; ++i) +{ +pixman_trapezoid_t *t = &(trapezoids[i]); + +t->top = prng_rand_n (height) << 16; +t->bottom = prng_rand_n (height) << 16; + +random_line (&t->left, height, width); +random_line (&t->right, height, width); +} + +return trapezoids; +} + static const pixman_op_t op_list[] = { PIXMAN_OP_SRC, @@ -792,31 +846,87 @@ run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod) if (mod == 0 || (seed % mod) == 0) printf ("Seed 0x%08x\n", seed); } - -prng_srand (seed); -source = create_random_image (); -mask = create_random_image (); -dest = create_random_bits_image (); +source = mask = dest = NULL; + +prng_srand (seed); -if (source && mask && dest) +if (prng_rand_n (8) == 0) { - set_general_properties (dest, TRUE); - - op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))]; - - pixman_image_composite32 (op, - source, mask, dest, - rand_x (source), rand_y (source), - rand_x (mask), rand_y (mask), - 0, 0, - dest->bits.width, - dest->bits.height); +int n_traps; +pixman_trapezoid_t *trapezoids; + +dest = create_random_bits_image (TRUE); + +if (dest) +{ +set_general_properties (dest, TRUE); + +trapezoids = create_random_trapezoids ( +&n_traps, dest->bits.width, dest->bits.height); + +if (trapezoids) +{ +switch (prng_rand_n (3)) +{ +case 0: +pixman_rasterize_trapezoid ( +dest, &trapezoids[prng_rand_n (n_traps)], +rand_x (dest), rand_y (dest)); +break; + +case 1: +source = create_random_image (); + +if (source) +{ +op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))
[Pixman] [PATCH 2/3] pixman_composite_trapezoids: Return early if mask_format is not of TYPE_ALPHA
From: Søren Sandmann Pedersen stress-test -s 0x17ee crashes because pixman_composite_trapezoids() is given a mask_format of PIXMAN_c8, which causes it to create a temporary image with that format but without a palette. This causes crashes later. The only mask_format that we actually support are those of TYPE_ALPHA, so this patch add a return_if_fail() to ensure this. Similarly, although currently it won't crash if given an invalid format, alpha-only formats have always been the only thing that made sense for the pixman_rasterize_edges() functions, so add a return_if_fail() ensuring that the destination format is of type PIXMAN_TYPE_ALPHA. --- pixman/pixman-edge.c | 1 + pixman/pixman-trap.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/pixman/pixman-edge.c b/pixman/pixman-edge.c index 8d498ab..ad6dfc4 100644 --- a/pixman/pixman-edge.c +++ b/pixman/pixman-edge.c @@ -374,6 +374,7 @@ pixman_rasterize_edges (pixman_image_t *image, pixman_fixed_t b) { return_if_fail (image->type == BITS); +return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A); if (image->bits.read_func || image->bits.write_func) pixman_rasterize_edges_accessors (image, l, r, t, b); diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c index ab5c8c8..4dad179 100644 --- a/pixman/pixman-trap.c +++ b/pixman/pixman-trap.c @@ -491,6 +491,8 @@ pixman_composite_trapezoids (pixman_op_top, { int i; +return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A); + if (n_traps <= 0) return; -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH 3/3] pixman_composite_trapezoids(): Check for NULL return from create_bits()
From: Søren Sandmann Pedersen A check is needed that the creation of the temporary image in pixman_composite_trapezoids() succeeds. Fixes crash in stress-test -s 0x313c on my system. --- pixman/pixman-trap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c index 4dad179..91766fd 100644 --- a/pixman/pixman-trap.c +++ b/pixman/pixman-trap.c @@ -523,8 +523,9 @@ pixman_composite_trapezoids (pixman_op_top, if (!get_trap_extents (op, dst, traps, n_traps, &box)) return; - tmp = pixman_image_create_bits ( - mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1); + if (!(tmp = pixman_image_create_bits ( + mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1))) + return; for (i = 0; i < n_traps; ++i) { -- 1.7.11.7 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] Fwd: make error on pixman library
Andrew Scott writes: > /bin/bash: line 5: 5532 Floating point exception${dir}$tst > FAIL: combiner-test Thanks for the bug report. Can we get a backtrace for it? That is, after running combiner-test once, run it again like this: ~/pixman/test% gdb .libs/lt-combiner-test (gdb) run ... (gdb) bt Thanks, Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] Fwd: make error on pixman library
Søren Sandmann writes: >> /bin/bash: line 5: 5532 Floating point exception${dir}$tst >> FAIL: combiner-test I managed to reproduce this using the -m32 option to gcc. The problem is a divide-by-zero in blend_color_dodge(): static force_inline float blend_color_dodge (float sa, float s, float da, float d) { if (d == 0.0f) return 0.0f; else if (d * sa >= sa * da - s * da) return sa * da; else if (sa - s == 0.0f) return sa * da; else return sa * sa * d / (sa - s); } The division is guarded by if (sa - s == 0.0f) ; else / (sa - s); which in theory should be correct, but isn't with the combination of x87 and gcc optimizations. The following patch fixes the issue by changing the comparision for equality with zero into a comparision for the interval -FLT_MIN, FLT_MIN. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] float-combiner.c: Change tests for x == 0.0 tests to - FLT_MIN < x < FLT_MIN
From: Søren Sandmann Pedersen pixman-float-combiner.c currently uses checks like these: if (x == 0.0f) ... else ... / x; to prevent division by 0. In theory this is correct: a division-by-zero exception is only supposed to happen when the floating point numerator is exactly equal to a positive or negative zero. However, in practice, the combination of x87 and gcc optimizations causes issues. The x87 registers are 80 bits wide, which means the initial test: if (x == 0.0f) may be false when x is an 80 bit floating point number, but when x is rounded to a 32 bit single precision number, it becomes equal to 0.0. In principle, gcc should compensate for this quirk of x87, and there are some options such as -ffloat-store, -fexcess-precision=standard, and -std=c99 that will make it do so, but these all have a performance cost. It is also possible to set the FPU to a mode that makes it do all computation with single or double precision, but that would require pixman to save the existing mode before doing anything with floating point and restore it afterwards. Instead, this patch side-steps the issue by replacing exact checks for equality with zero with a new macro that checkes whether the value is between -FLT_MIN and FLT_MIN. There is extensive reading material about this issue linked off the infamous gcc bug 323: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 --- pixman/pixman-combine-float.c | 28 +++- 1 files changed, 15 insertions(+), 13 deletions(-) diff --git a/pixman/pixman-combine-float.c b/pixman/pixman-combine-float.c index c3d54f0..c916df8 100644 --- a/pixman/pixman-combine-float.c +++ b/pixman/pixman-combine-float.c @@ -42,6 +42,8 @@ #define force_inline __inline__ #endif +#define IS_ZERO(f) (-FLT_MIN < (f) && (f) < FLT_MIN) + typedef float (* combine_channel_t) (float sa, float s, float da, float d); static force_inline void @@ -201,56 +203,56 @@ get_factor (combine_factor_t factor, float sa, float da) break; case SA_OVER_DA: - if (da == 0.0f) + if (IS_ZERO (da)) f = 1.0f; else f = CLAMP (sa / da); break; case DA_OVER_SA: - if (sa == 0.0f) + if (IS_ZERO (sa)) f = 1.0f; else f = CLAMP (da / sa); break; case INV_SA_OVER_DA: - if (da == 0.0f) + if (IS_ZERO (da)) f = 1.0f; else f = CLAMP ((1.0f - sa) / da); break; case INV_DA_OVER_SA: - if (sa == 0.0f) + if (IS_ZERO (sa)) f = 1.0f; else f = CLAMP ((1.0f - da) / sa); break; case ONE_MINUS_SA_OVER_DA: - if (da == 0.0f) + if (IS_ZERO (da)) f = 0.0f; else f = CLAMP (1.0f - sa / da); break; case ONE_MINUS_DA_OVER_SA: - if (sa == 0.0f) + if (IS_ZERO (sa)) f = 0.0f; else f = CLAMP (1.0f - da / sa); break; case ONE_MINUS_INV_DA_OVER_SA: - if (sa == 0.0f) + if (IS_ZERO (sa)) f = 0.0f; else f = CLAMP (1.0f - (1.0f - da) / sa); break; case ONE_MINUS_INV_SA_OVER_DA: - if (da == 0.0f) + if (IS_ZERO (da)) f = 0.0f; else f = CLAMP (1.0f - (1.0f - sa) / da); @@ -403,11 +405,11 @@ blend_lighten (float sa, float s, float da, float d) static force_inline float blend_color_dodge (float sa, float s, float da, float d) { -if (d == 0.0f) +if (IS_ZERO (d)) return 0.0f; else if (d * sa >= sa * da - s * da) return sa * da; -else if (sa - s == 0.0f) +else if (IS_ZERO (sa - s)) return sa * da; else return sa * sa * d / (sa - s); @@ -420,7 +422,7 @@ blend_color_burn (float sa, float s, float da, float d) return sa * da; else if (sa * (da - d) >= s * da) return 0.0f; -else if (s == 0.0f) +else if (IS_ZERO (s)) return 0.0f; else return sa * (da - sa * (da - d) / s); @@ -440,14 +442,14 @@ blend_soft_light (float sa, float s, float da, float d) { if (2 * s < sa) { - if (da == 0.0f) + if (IS_ZERO (da)) return d * sa; else return d * sa - d * (da - d) * (sa - 2 * s) / da; } else { - if (da == 0.0f) + if (IS_ZERO (da)) { return 0.0f; } -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH/RFC 0/4] New option to build pixman as C++ code (--enable-enforced-cplusplus)
Siarhei Siamashka writes: > This is not intended to be immediately pushed to pixman git repository. > At least not until it proves to have some real practical use. Except > maybe for the 'xor'->'filler' variable rename patch, which clearly > should not cause any regressions or inconveniences. There is a number of things in this series that look like good changes regardless of moving to C++ or not. Some I noticed: The SIZE_MAX change was requested here: http://lists.freedesktop.org/archives/pixman/2012-August/002196.html and someone recently mailed me privately and pointed out that Solaris 9 doesn't have it either. The xor->filler change should be harmless as you point out, and 'filler' probably is a better name than 'xor'. The uint32->pixman_format_t in pixman-glyph.c looks good. Regarding the malloc() changes, it might be worthwhile to add some macros that take a typename as a parameter, along the lines of #define pixman_new(type, n)\ ((type *)pixman_malloc_ab (sizeof (type), n)) so that we get warnings if we try to assign the result to an incorrect pointer type. Although for a lot of code in pixman, we do actually rely on the ability to do type aliasing of malloc()ed memory, so maybe the usefulness of such macros is limited. > Any comments or ideas? Hopefully not a C vs. C++ flamewar :) Every once in a while I let myself be convinced me that C++ can be used as a better C, but whenever I have tried it, it has somehow always ended up driving me crazy with longer compile times and casts all over the place. I guess I could see the potential for better debug builds that you mention in the first commit message, but I'd definitely like to see some concrete benefits before committing to keep all pixman code compilable as C++. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] float-combiner.c: Change tests for x == 0.0 tests to - FLT_MIN < x < FLT_MIN
Siarhei Siamashka writes: > I just wonder how big is the performance cost for adding an extra > comparison operation. Probably much less than using -ffloat-store, > -fexcess-precision=standard, and -std=c99 options, but might be > interesting to confirm. It's not going to matter all that much in any case since we are talking about floating point variants of operations that involve divisions. These are not used that much, and the divisions will tend to swamp a lot of the difference. However, I added conjoint_over__2a10 to lowlevel-blt-test and did some measurements: As a baseline, current master compiled with -m32 and == 0.0f checks: conjoint_over__2a10 = L1: 5.62 L2: 5.67 M: 5.65 ( 0.50%) HT: 5.59 VT: 5.52 R: 5.49 RT: 5.06 ( 68Kops/s) With the FLT_MIN checks: conjoint_over__2a10 = L1: 5.68 L2: 5.73 M: 5.72 ( 0.51%) HT: 5.65 VT: 5.53 R: 5.45 RT: 5.02 ( 67Kops/s) The numbers are actually slightly better with the checks, so I suspect the difference is just noise (although conceivably, the checks may filter out more divisions than before). When just pixman-combine-float.c is compiled with -ffloat-store: conjoint_over__2a10 = L1: 5.58 L2: 5.60 M: 5.60 ( 0.50%) HT: 5.53 VT: 5.44 R: 5.41 RT: 4.99 ( 67Kops/s) The numbers here are slightly worse than the baseline, but possibly still just noise. If all of pixman is compiled with -ffloat-store: conjoint_over__2a10 = L1: 4.31 L2: 4.34c M: 4.31 ( 0.38%) HT: 4.26 VT: 4.21 R: 4.14 RT: 3.92 ( 53Kops/s) the numbers are clearly worse. Finally, the numbers in x86_64 mode. Current master: conjoint_over__2a10 = L1: 19.09 L2: 19.58 M: 19.13 ( 1.75%) HT: 17.47 VT: 17.35 R: 17.32 RT: 13.72 ( 178Kops/s) With FLT_MIN checks: conjoint_over__2a10 = L1: 19.09 L2: 19.59 M: 19.51 ( 1.76%) HT: 17.52 VT: 17.02 R: 17.00 RT: 13.43 ( 175Kops/s) Ie., no real difference. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Make the noop iterator work for solid images
From: Søren Sandmann Pedersen The noop iterator is supposedly handling solid images, but currently it never triggers because a solid image cannot have both an extended format code of PIXMAN_solid while at the same time having the FAST_PATH_BITS_IMAGE flag set. If these two were to be set at the same time, the fast_composite_tiled_repeat() fast path would trigger for solid images (because it triggers for PIXMAN_any formats, which includes PIXMAN_solid), but for solid images we can usually do better than that fast path. So this patch changes the noop iterator to no longer require the FAST_PATH_BITS_IMAGE flag and handle both solid fill images and 1x1 bits images. --- pixman/pixman-noop.c | 19 +-- 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pixman/pixman-noop.c b/pixman/pixman-noop.c index 850caa1..adaa0c7 100644 --- a/pixman/pixman-noop.c +++ b/pixman/pixman-noop.c @@ -77,25 +77,32 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_solid && -((iter->image_flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == - (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP))) +(iter->image_flags & FAST_PATH_NO_ALPHA_MAP)) { - bits_image_t *bits = &image->bits; - if (iter->iter_flags & ITER_NARROW) { - uint32_t color = bits->fetch_pixel_32 (bits, 0, 0); uint32_t *buffer = iter->buffer; uint32_t *end = buffer + iter->width; + uint32_t color; + + if (image->type == SOLID) + color = image->solid.color_32; + else + color = image->bits.fetch_pixel_32 (&image->bits, 0, 0); while (buffer < end) *(buffer++) = color; } else { - argb_t color = bits->fetch_pixel_float (bits, 0, 0); argb_t *buffer = (argb_t *)iter->buffer; argb_t *end = buffer + iter->width; + argb_t color; + + if (image->type == SOLID) + color = image->solid.color_float; + else + color = image->bits.fetch_pixel_float (&image->bits, 0, 0); while (buffer < end) *(buffer++) = color; -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] Make the noop iterator work for solid images
Siarhei Siamashka writes: > Isn't this code in noop iterator mostly a duplicate of: > > http://cgit.freedesktop.org/pixman/tree/pixman/pixman-solid-fill.c?id=pixman-0.28.2#n29 > which gets called from general_src_iter_init: > > http://cgit.freedesktop.org/pixman/tree/pixman/pixman-general.c?id=pixman-0.28.2#n40 > > At least earlier _pixman_solid_fill_iter_init was used when running > cairo perf traces. But not anymore after your patch is applied. > > Sure, I can see a rationale to handle such simple cases earlier and > not pass them through the whole fallbacks chain (where they could > potentially and unexpectedly match something less efficient like > fast_composite_tiled_repeat). But maybe it's a good idea to also > get rid of _pixman_solid_fill_iter_init in this case (unless I'm > missing something and it is still in use)? I guess that makes sense. The one case that was handled by _pixman_solid_fill_iter_init() is a solid image with an alpha map, but since alpha maps are ignored for anything but bits images, there is no reason to not handle this case in noop as well. This further breaks down the concept introduced with the refactoring in 0.16 that images are self-contained objects that know how to draw themselves in favor of the concept that implementations are objects that know how to draw images. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] Handle solid images in the noop iterator
From: Søren Sandmann Pedersen The noop src iterator already has code to handle solid images, but that code never actually runs currently because it is not possible for an image to have both a format code of PIXMAN_solid and a flag of FAST_PATH_BITS_IMAGE. If these two were to be set at the same time, the fast_composite_tiled_repeat() fast path would trigger for solid images (because it triggers for PIXMAN_any formats, which includes PIXMAN_solid), but for solid images we can usually do better than that fast path. So this patch removes _pixman_solid_fill_iter_init() and instead handles such images (along with 1x1 bits images without an alpha map) in pixman-noop.c. --- pixman/pixman-general.c|8 pixman/pixman-noop.c | 20 ++-- pixman/pixman-private.h|3 --- pixman/pixman-solid-fill.c | 25 - 4 files changed, 18 insertions(+), 38 deletions(-) diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index 0bf91e4..f175d77 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -42,9 +42,7 @@ general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; -if (image->type == SOLID) - _pixman_solid_fill_iter_init (image, iter); -else if (image->type == LINEAR) +if (image->type == LINEAR) _pixman_linear_gradient_iter_init (image, iter); else if (image->type == RADIAL) _pixman_radial_gradient_iter_init (image, iter); @@ -52,7 +50,9 @@ general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) _pixman_conical_gradient_iter_init (image, iter); else if (image->type == BITS) _pixman_bits_image_src_iter_init (image, iter); -else +else if (image->type == SOLID) +_pixman_log_error (FUNC, "Solid image not handled by noop"); +else _pixman_log_error (FUNC, "Pixman bug: unknown image type\n"); return TRUE; diff --git a/pixman/pixman-noop.c b/pixman/pixman-noop.c index 850caa1..e39996d 100644 --- a/pixman/pixman-noop.c +++ b/pixman/pixman-noop.c @@ -77,25 +77,33 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_solid && -((iter->image_flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == - (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP))) +(iter->image->type == SOLID || + (iter->image_flags & FAST_PATH_NO_ALPHA_MAP))) { - bits_image_t *bits = &image->bits; - if (iter->iter_flags & ITER_NARROW) { - uint32_t color = bits->fetch_pixel_32 (bits, 0, 0); uint32_t *buffer = iter->buffer; uint32_t *end = buffer + iter->width; + uint32_t color; + + if (image->type == SOLID) + color = image->solid.color_32; + else + color = image->bits.fetch_pixel_32 (&image->bits, 0, 0); while (buffer < end) *(buffer++) = color; } else { - argb_t color = bits->fetch_pixel_float (bits, 0, 0); argb_t *buffer = (argb_t *)iter->buffer; argb_t *end = buffer + iter->width; + argb_t color; + + if (image->type == SOLID) + color = image->solid.color_float; + else + color = image->bits.fetch_pixel_float (&image->bits, 0, 0); while (buffer < end) *(buffer++) = color; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index ea447aa..dfc4fa6 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -263,9 +263,6 @@ void _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter); void -_pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t *iter); - -void _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter); void diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c index 60d56d5..5f9fef6 100644 --- a/pixman/pixman-solid-fill.c +++ b/pixman/pixman-solid-fill.c @@ -26,31 +26,6 @@ #endif #include "pixman-private.h" -void -_pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t *iter) -{ -if (iter->iter_flags & ITER_NARROW) -{ - uint32_t *b = (uint32_t *)iter->buffer; - uint32_t *e = b + iter->width; - uint32_t color = iter->image->solid.color_32; - - while (b < e) - *(b++) = color; -} -else -{ - argb_t *b = (argb_t *)iter->buffer; - argb_t *e = b + iter->width; - argb_t color = image->solid.color_float;
[Pixman] [PATCH] pixman-filter.c: Cope with NULL returns from malloc()
From: Søren Sandmann Pedersen --- pixman/pixman-filter.c | 25 +++-- 1 files changed, 15 insertions(+), 10 deletions(-) diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c index c9d2dc7..6fe7c93 100644 --- a/pixman/pixman-filter.c +++ b/pixman/pixman-filter.c @@ -231,6 +231,8 @@ create_1d_filter (int *width, *width = ceil (size); p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t)); +if (!params) +return NULL; step = 1.0 / n_phases; @@ -309,7 +311,7 @@ pixman_filter_create_separable_convolution (int *n_values, { double sx = fabs (pixman_fixed_to_double (scale_x)); double sy = fabs (pixman_fixed_to_double (scale_y)); -pixman_fixed_t *horz, *vert, *params; +pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL; int subsample_x, subsample_y; int width, height; @@ -323,15 +325,18 @@ pixman_filter_create_separable_convolution (int *n_values, params = malloc (*n_values * sizeof (pixman_fixed_t)); -params[0] = pixman_int_to_fixed (width); -params[1] = pixman_int_to_fixed (height); -params[2] = pixman_int_to_fixed (subsample_bits_x); -params[3] = pixman_int_to_fixed (subsample_bits_y); - -memcpy (params + 4, horz, - width * subsample_x * sizeof (pixman_fixed_t)); -memcpy (params + 4 + width * subsample_x, vert, - height * subsample_y * sizeof (pixman_fixed_t)); +if (horz && vert && params) +{ +params[0] = pixman_int_to_fixed (width); +params[1] = pixman_int_to_fixed (height); +params[2] = pixman_int_to_fixed (subsample_bits_x); +params[3] = pixman_int_to_fixed (subsample_bits_y); + +memcpy (params + 4, horz, +width * subsample_x * sizeof (pixman_fixed_t)); +memcpy (params + 4 + width * subsample_x, vert, +height * subsample_y * sizeof (pixman_fixed_t)); +} free (horz); free (vert); -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] pixman-filter.c: Cope with NULL returns from malloc()
Søren Sandmann writes: > From: Søren Sandmann Pedersen This patch is wrong. If the horz and vert allocations fail, but the params one doesn't, a pointer to uninitialized memory will be returned. New patch to follow shortly. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
[Pixman] [PATCH] pixman-filter.c: Cope with NULL returns from malloc()
From: Søren Sandmann Pedersen v2: Don't return a pointer to uninitialized memory when the allocation of horz and vert fails, but allocation of params doesn't. --- pixman/pixman-filter.c | 10 +- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c index c9d2dc7..26b39d5 100644 --- a/pixman/pixman-filter.c +++ b/pixman/pixman-filter.c @@ -231,6 +231,8 @@ create_1d_filter (int *width, *width = ceil (size); p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t)); +if (!params) +return NULL; step = 1.0 / n_phases; @@ -309,7 +311,7 @@ pixman_filter_create_separable_convolution (int *n_values, { double sx = fabs (pixman_fixed_to_double (scale_x)); double sy = fabs (pixman_fixed_to_double (scale_y)); -pixman_fixed_t *horz, *vert, *params; +pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL; int subsample_x, subsample_y; int width, height; @@ -319,9 +321,14 @@ pixman_filter_create_separable_convolution (int *n_values, horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x); vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y); +if (!horz || !vert) +goto out; + *n_values = 4 + width * subsample_x + height * subsample_y; params = malloc (*n_values * sizeof (pixman_fixed_t)); +if (!params) +goto out; params[0] = pixman_int_to_fixed (width); params[1] = pixman_int_to_fixed (height); @@ -333,6 +340,7 @@ pixman_filter_create_separable_convolution (int *n_values, memcpy (params + 4 + width * subsample_x, vert, height * subsample_y * sizeof (pixman_fixed_t)); +out: free (horz); free (vert); -- 1.7.4 ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] sse2: Add a fast path for add_n_8888
Chris Wilson writes: > This path is being exercised by inplace compositing of trapezoids, for > instance as used in the firefox-asteroids cairo-trace. > > core2 @ 2.66GHz, > > reference memcpy speed = 4898.2MB/s (1224.6MP/s for 32bpp fills) > > before: add_n_ = L1: 4.36 L2: 4.27 M: 1.61 ( 0.13%) HT: > 1.65 VT: 1.63 R: 1.63 RT: 1.59 ( 21Kops/s) > > after: add_n_ = L1:2969.09 L2:3926.11 M:603.30 ( 49.27%) HT:524.69 > VT:401.01 R:407.59 RT:210.34 ( 804Kops/s) Just two brief comments, and then I'll disappear again (until the 11th or so): - It looks like this function will work for abgr destinations as well as argb. - I'm surprised that the new function is _that_ much better. The current code should hit an SSE2 combiner and noop iterators for both source and destination, so while I'd expect a solid improvement from a dedicated fast path, it is hard to believe that it would be 919 times faster than the old. If these numbers are real, there has to be something wrong with either the benchmark or the current code. Soren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman
Re: [Pixman] [PATCH] bits: Special case src_iter for 1x1R images
Chris Wilson writes: > These are often used inplace of a solid-fill gradient, with the > expectation that have similar performance and hit the same fast paths. > One exception is the identification of the 1x1R <-> solid-fill > equivalence in general_composite_rect(). By adding the special case to > _pixman_bits_image_src_iter_init, we can recover the lost performance: This issue is also fixed by the patch here: http://lists.freedesktop.org/archives/pixman/2012-December/002444.html which I will push shortly (with an updated commit message that includes similar performance numbers to those you posted). Doing it in the noop implementation is better because it avoids the question of, say, a repeating SSE2 iterator potentially getting picked before the one in pixman-bits-image.c. Søren ___ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman