[Pixman] [PATCH 1/2] general: Ensure that iter buffers are aligned to 16 bytes
Siarhei Siamashka
siarhei.siamashka at gmail.com
Thu Aug 29 12:30:42 PDT 2013
On Wed, 28 Aug 2013 16:01:26 -0400
Søren Sandmann <sandmann at cs.au.dk> wrote:
> From: Søren Sandmann Pedersen <ssp at redhat.com>
>
> At the moment iter buffers are only guaranteed to be aligned to an 8
> byte bit boundary. It is useful for SIMD implementations to be able to
> assume that these buffers are aligned to 16 bytes, so ensure this.
> ---
> pixman/pixman-general.c | 22 +++++++++++++++-------
> pixman/pixman-private.h | 3 +++
> pixman/pixman-utils.c | 9 +++++++++
> 3 files changed, 27 insertions(+), 7 deletions(-)
>
> diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
> index 6310bff..60566c6 100644
> --- a/pixman/pixman-general.c
> +++ b/pixman/pixman-general.c
> @@ -114,7 +114,7 @@ general_composite_rect (pixman_implementation_t *imp,
> pixman_composite_info_t *info)
> {
> PIXMAN_COMPOSITE_ARGS (info);
> - uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
> + uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH];
Don't know if this was intended, but the array on stack becomes ~3 times
smaller after this change.
Currently with SCANLINE_BUFFER_LENGTH = 8192, the buffer on stack
was used for the compositing operations having width up to
(SCANLINE_BUFFER_LENGTH / 4 bytes per pixel) = 2048. Which probably
makes sense for the people mostly having 1920x1080 or 1920x1200
monitors.
Now avoiding malloc is only going to happen when the width is less
than ~683 pixels.
> uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
> uint8_t *src_buffer, *mask_buffer, *dest_buffer;
> pixman_iter_t src_iter, mask_iter, dest_iter;
> @@ -137,17 +137,25 @@ general_composite_rect (pixman_implementation_t *imp,
> Bpp = 16;
> }
>
> - if (width * Bpp > SCANLINE_BUFFER_LENGTH)
> +#define ALIGN(addr) \
> + ((uint8_t *)((((unsigned long)(addr)) + 15) & (~15)))
Windows and maybe some other weird systems may have 32-bit long type
even in 64-bit mode. Using "uintptr_t" instead of "unsigned long" would
be a safer choice.
> +
> + src_buffer = ALIGN (scanline_buffer);
> + mask_buffer = ALIGN (src_buffer + width * Bpp);
> + dest_buffer = ALIGN (mask_buffer + width * Bpp);
> +
> + if (ALIGN (dest_buffer + width * Bpp) >
> + scanline_buffer + SCANLINE_BUFFER_LENGTH)
> {
> - scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
> + scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 32 * 3);
>
> if (!scanline_buffer)
> return;
> - }
>
> - src_buffer = scanline_buffer;
> - mask_buffer = src_buffer + width * Bpp;
> - dest_buffer = mask_buffer + width * Bpp;
> + src_buffer = ALIGN (scanline_buffer);
> + mask_buffer = ALIGN (src_buffer + width * Bpp);
> + dest_buffer = ALIGN (mask_buffer + width * Bpp);
> + }
>
> if (width_flag == ITER_WIDE)
> {
> diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
> index 9646605..0afabad 100644
> --- a/pixman/pixman-private.h
> +++ b/pixman/pixman-private.h
> @@ -787,6 +787,9 @@ pixman_malloc_ab (unsigned int n, unsigned int b);
> void *
> pixman_malloc_abc (unsigned int a, unsigned int b, unsigned int c);
>
> +void *
> +pixman_malloc_ab_plus_c (unsigned int a, unsigned int b, unsigned int c);
> +
> pixman_bool_t
> _pixman_multiply_overflows_size (size_t a, size_t b);
>
> diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
> index 98723a8..4a3a835 100644
> --- a/pixman/pixman-utils.c
> +++ b/pixman/pixman-utils.c
> @@ -49,6 +49,15 @@ _pixman_addition_overflows_int (unsigned int a, unsigned int b)
> }
>
> void *
> +pixman_malloc_ab_plus_c (unsigned int a, unsigned int b, unsigned int c)
> +{
> + if (!b || a >= INT32_MAX / b || (a * b) > INT32_MAX - c)
> + return NULL;
> +
> + return malloc (a * b + c);
> +}
> +
> +void *
> pixman_malloc_ab (unsigned int a,
> unsigned int b)
> {
--
Best regards,
Siarhei Siamashka
More information about the Pixman
mailing list