general: Ensure that iter buffers are aligned to 16 bytes
authorSøren Sandmann Pedersen <ssp@redhat.com>
Wed, 28 Aug 2013 19:36:13 +0000 (15:36 -0400)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Mon, 16 Sep 2013 20:50:35 +0000 (16:50 -0400)
At the moment iter buffers are only guaranteed to be aligned to a 4
byte boundary. SIMD implementations benefit from the buffers being
aligned to 16 bytes, so ensure this is the case.

V2:
- Use uintptr_t instead of unsigned long
- allocate 3 * SCANLINE_BUFFER_LENGTH byte on stack rather than just
  SCANLINE_BUFFER_LENGTH
- use sizeof (stack_scanline_buffer) instead of SCANLINE_BUFFER_LENGTH
  to determine overflow

pixman/pixman-general.c
pixman/pixman-private.h
pixman/pixman-utils.c

index 6310bff9dbe7b8fd7e2989e72217f14dcc3790e9..a653fa71ae37c0393ac8e608ad780372d475a203 100644 (file)
@@ -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[3 * SCANLINE_BUFFER_LENGTH];
     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 *)((((uintptr_t)(addr)) + 15) & (~15)))
+
+    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 + sizeof (stack_scanline_buffer))
     {
-       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)
     {
index 120196ddf8f7e1c608318e0bdc1e679274cdd9e6..535117d4a4eea19d5e61f2b9c33ecb322ea55f77 100644 (file)
@@ -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);
 
index 98723a800fe465bf86532454e087215dc783ee9c..4a3a835c4239ad3166d58dec238b3870698bbd35 100644 (file)
@@ -48,6 +48,15 @@ _pixman_addition_overflows_int (unsigned int a, unsigned int b)
     return a > INT32_MAX - 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)