pixman: Branch 'master' - 17 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Sat Feb 20 10:10:21 PST 2010


 pixman/pixman-arm-neon.c       |   41 --
 pixman/pixman-arm-simd.c       |   41 --
 pixman/pixman-fast-path.c      |  208 +++++--------
 pixman/pixman-general.c        |   26 -
 pixman/pixman-implementation.c |   53 ---
 pixman/pixman-mmx.c            |   34 --
 pixman/pixman-private.h        |  124 ++------
 pixman/pixman-sse2.c           |   58 ---
 pixman/pixman-utils.c          |  531 ----------------------------------
 pixman/pixman-vmx.c            |    7 
 pixman/pixman.c                |  635 ++++++++++++++++++++++++++++++++++++++---
 11 files changed, 750 insertions(+), 1008 deletions(-)

New commits:
commit 14f201dc47ba76fcf677936f4f809249054fd6ad
Merge: 94f5859... 6b2da68...
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Feb 20 13:09:01 2010 -0500

    Merge branch 'eliminate-composite'
    
    Conflicts:
    	pixman/pixman-sse2.c

diff --cc pixman/pixman-sse2.c
index f69de0b,c8481dc..946e7ba
--- a/pixman/pixman-sse2.c
+++ b/pixman/pixman-sse2.c
@@@ -5955,12 -5900,8 +5900,12 @@@ __attribute__((__force_align_arg_pointe
  pixman_implementation_t *
  _pixman_implementation_create_sse2 (void)
  {
 -    pixman_implementation_t *mmx = _pixman_implementation_create_mmx ();
 -    pixman_implementation_t *imp = _pixman_implementation_create (mmx, sse2_fast_paths);
 +#ifdef USE_MMX
 +    pixman_implementation_t *fallback = _pixman_implementation_create_mmx ();
 +#else
 +    pixman_implementation_t *fallback = _pixman_implementation_create_fast_path ();
 +#endif
-     pixman_implementation_t *imp = _pixman_implementation_create (fallback);
++    pixman_implementation_t *imp = _pixman_implementation_create (fallback, sse2_fast_paths);
  
      /* SSE2 constants */
      mask_565_r  = create_mask_2x32_128 (0x00f80000, 0x00f80000);
commit 6b2da683debd1b3fc1862752cb26e6799b644e05
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Wed Sep 16 07:29:08 2009 -0400

    Move NULL check out of get_image_info()
    
    The NULL check is only necessary for masks, so there is no reason to
    do it for destinations and sources.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 16adad7..6a260ed 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -347,14 +347,14 @@ walk_region_internal (pixman_implementation_t *imp,
                       pixman_region32_t *      region,
                       pixman_composite_func_t  composite_rect)
 {
-    int n;
-    const pixman_box32_t *pbox;
     int w, h, w_this, h_this;
     int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
     int src_dy = src_y - dest_y;
     int src_dx = src_x - dest_x;
     int mask_dy = mask_y - dest_y;
     int mask_dx = mask_x - dest_x;
+    const pixman_box32_t *pbox;
+    int n;
 
     pbox = pixman_region32_rectangles (region, &n);
 
@@ -455,67 +455,60 @@ get_image_info (pixman_image_t       *image,
 {
     *flags = 0;
     
-    if (!image)
+    if (!image->common.transform)
     {
-	*code = PIXMAN_null;
+	*flags |= FAST_PATH_ID_TRANSFORM;
     }
     else
     {
-	if (!image->common.transform)
-	{
-	    *flags |= FAST_PATH_ID_TRANSFORM;
-	}
-	else
+	if (image->common.transform->matrix[0][1] == 0 &&
+	    image->common.transform->matrix[1][0] == 0 &&
+	    image->common.transform->matrix[2][0] == 0 &&
+	    image->common.transform->matrix[2][1] == 0 &&
+	    image->common.transform->matrix[2][2] == pixman_fixed_1)
 	{
-	    if (image->common.transform->matrix[0][1] == 0 &&
-		image->common.transform->matrix[1][0] == 0 &&
-		image->common.transform->matrix[2][0] == 0 &&
-		image->common.transform->matrix[2][1] == 0 &&
-		image->common.transform->matrix[2][2] == pixman_fixed_1)
-	    {
-		*flags |= FAST_PATH_SCALE_TRANSFORM;
-	    }
+	    *flags |= FAST_PATH_SCALE_TRANSFORM;
 	}
+    }
+    
+    if (!image->common.alpha_map)
+	*flags |= FAST_PATH_NO_ALPHA_MAP;
+    
+    if (image->common.filter != PIXMAN_FILTER_CONVOLUTION)
+    {
+	*flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
 	
-	if (!image->common.alpha_map)
-	    *flags |= FAST_PATH_NO_ALPHA_MAP;
-
-	if (image->common.filter != PIXMAN_FILTER_CONVOLUTION)
-	{
-	    *flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
-
-	    if (image->common.filter == PIXMAN_FILTER_NEAREST)
-		*flags |= FAST_PATH_NEAREST_FILTER;
-	}
-
-	if (image->common.repeat != PIXMAN_REPEAT_PAD)
-	    *flags |= FAST_PATH_NO_PAD_REPEAT;
-
-	if (image->common.repeat != PIXMAN_REPEAT_REFLECT)
-	    *flags |= FAST_PATH_NO_REFLECT_REPEAT;
-
-	*flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT);
-	if (image->type == BITS)
-	{
-	    if (image->bits.read_func || image->bits.write_func)
-		*flags &= ~FAST_PATH_NO_ACCESSORS;
-
-	    if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
-		*flags &= ~FAST_PATH_NO_WIDE_FORMAT;
-	}
-
-	if (image->common.component_alpha)
-	    *flags |= FAST_PATH_COMPONENT_ALPHA;
-	else
-	    *flags |= FAST_PATH_UNIFIED_ALPHA;
-
-	if (_pixman_image_is_solid (image))
-	    *code = PIXMAN_solid;
-	else if (image->common.type == BITS)
-	    *code = image->bits.format;
-	else
-	    *code = PIXMAN_unknown;
+	if (image->common.filter == PIXMAN_FILTER_NEAREST)
+	    *flags |= FAST_PATH_NEAREST_FILTER;
+    }
+    
+    if (image->common.repeat != PIXMAN_REPEAT_PAD)
+	*flags |= FAST_PATH_NO_PAD_REPEAT;
+    
+    if (image->common.repeat != PIXMAN_REPEAT_REFLECT)
+	*flags |= FAST_PATH_NO_REFLECT_REPEAT;
+    
+    *flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT);
+    if (image->type == BITS)
+    {
+	if (image->bits.read_func || image->bits.write_func)
+	    *flags &= ~FAST_PATH_NO_ACCESSORS;
+	
+	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
+	    *flags &= ~FAST_PATH_NO_WIDE_FORMAT;
     }
+    
+    if (image->common.component_alpha)
+	*flags |= FAST_PATH_COMPONENT_ALPHA;
+    else
+	*flags |= FAST_PATH_UNIFIED_ALPHA;
+    
+    if (_pixman_image_is_solid (image))
+	*code = PIXMAN_solid;
+    else if (image->common.type == BITS)
+	*code = image->bits.format;
+    else
+	*code = PIXMAN_unknown;
 }
 
 static force_inline pixman_bool_t
@@ -560,7 +553,15 @@ do_composite (pixman_implementation_t *imp,
     pixman_box32_t *extents;
 
     get_image_info (src,  &src_format,  &src_flags);
-    get_image_info (mask, &mask_format, &mask_flags);
+    if (mask)
+    {
+	get_image_info (mask, &mask_format, &mask_flags);
+    }
+    else
+    {
+	mask_format = PIXMAN_null;
+	mask_flags = 0;
+    }
     get_image_info (dest, &dest_format, &dest_flags);
     
     /* Check for pixbufs */
commit 1dd8744f40f4b754fb3aa26a3c7f4fbe54c27155
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Wed Sep 16 06:54:43 2009 -0400

    Add a fast path for non-repeating sources in walk_region_internal().
    
    In the common case where there is no repeating, the loop in
    walk_region_internal() reduces to just walking of the boxes involved
    and calling the composite function.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 9821d09..16adad7 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -351,21 +351,48 @@ walk_region_internal (pixman_implementation_t *imp,
     const pixman_box32_t *pbox;
     int w, h, w_this, h_this;
     int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+    int src_dy = src_y - dest_y;
+    int src_dx = src_x - dest_x;
+    int mask_dy = mask_y - dest_y;
+    int mask_dx = mask_x - dest_x;
 
     pbox = pixman_region32_rectangles (region, &n);
+
+    /* Fast path for non-repeating sources */
+    if (!src_repeat && !mask_repeat)
+    {
+       while (n--)
+       {
+           (*composite_rect) (imp, op,
+                              src_image, mask_image, dst_image,
+                              pbox->x1 + src_dx,
+                              pbox->y1 + src_dy,
+                              pbox->x1 + mask_dx,
+                              pbox->y1 + mask_dy,
+                              pbox->x1,
+                              pbox->y1,
+                              pbox->x2 - pbox->x1,
+                              pbox->y2 - pbox->y1);
+           
+           pbox++;
+       }
+
+       return;
+    }
+    
     while (n--)
     {
 	h = pbox->y2 - pbox->y1;
-	y_src = pbox->y1 - dest_y + src_y;
-	y_msk = pbox->y1 - dest_y + mask_y;
+	y_src = pbox->y1 + src_dy;
+	y_msk = pbox->y1 + mask_dy;
 	y_dst = pbox->y1;
 
 	while (h)
 	{
 	    h_this = h;
 	    w = pbox->x2 - pbox->x1;
-	    x_src = pbox->x1 - dest_x + src_x;
-	    x_msk = pbox->x1 - dest_x + mask_x;
+	    x_src = pbox->x1 + src_dx;
+	    x_msk = pbox->x1 + mask_dx;
 	    x_dst = pbox->x1;
 
 	    if (mask_repeat)
commit 362a9f564a9a58c48ab0129ca3ac997d0cb84bab
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 01:34:33 2009 -0400

    Move more things out of the inner loop in do_composite().
    
    Specifically,
    
    - the src_ and mask_repeat computations
    
    - the check for whether the involved images cover the composite
      region.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 9d0641b..9821d09 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -528,7 +528,9 @@ do_composite (pixman_implementation_t *imp,
 {
     pixman_format_code_t src_format, mask_format, dest_format;
     uint32_t src_flags, mask_flags, dest_flags;
+    pixman_bool_t src_repeat, mask_repeat;
     pixman_region32_t region;
+    pixman_box32_t *extents;
 
     get_image_info (src,  &src_format,  &src_flags);
     get_image_info (mask, &mask_format, &mask_flags);
@@ -546,6 +548,19 @@ do_composite (pixman_implementation_t *imp,
 	    src_format = mask_format = PIXMAN_rpixbuf;
     }
 	    
+    src_repeat =
+	src->type == BITS					&&
+	src_flags & FAST_PATH_ID_TRANSFORM			&&
+	src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	src_format != PIXMAN_solid;
+    
+    mask_repeat =
+	mask							&&
+	mask->type == BITS					&&
+	mask_flags & FAST_PATH_ID_TRANSFORM			&&
+	mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	mask_format != PIXMAN_solid;
+    
     pixman_region32_init (&region);
     
     if (!pixman_compute_composite_region32 (
@@ -555,63 +570,34 @@ do_composite (pixman_implementation_t *imp,
 	return;
     }
     
+    extents = pixman_region32_extents (&region);
+    
+    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
+	src_flags |= FAST_PATH_COVERS_CLIP;
+    
+    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
+	mask_flags |= FAST_PATH_COVERS_CLIP;
+	    
     while (imp)
     {
-	{
-	    pixman_composite_func_t func;
-	    const pixman_fast_path_t *info;
-	    pixman_bool_t result;
-	    pixman_box32_t *extents;
-	    
-	    result = FALSE;
-	    
-	    extents = pixman_region32_extents (&region);
-	    
-	    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
-		src_flags |= FAST_PATH_COVERS_CLIP;
-	    
-	    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
-		mask_flags |= FAST_PATH_COVERS_CLIP;
+	const pixman_fast_path_t *info;
 	    
-	    func = NULL;
-	    for (info = imp->fast_paths; info->op != PIXMAN_OP_NONE; ++info)
-	    {
-		if ((info->op == op || info->op == PIXMAN_OP_any)	&&
-		    /* src */
-		    ((info->src_format == src_format) ||
-		     (info->src_format == PIXMAN_any))			&&
-		    (info->src_flags & src_flags) == info->src_flags	&&
-		    /* mask */
-		    ((info->mask_format == mask_format) ||
-		     (info->mask_format == PIXMAN_any))			&&
-		    (info->mask_flags & mask_flags) == info->mask_flags	&&
-		    /* dest */
-		    ((info->dest_format == dest_format) ||
-		     (info->dest_format == PIXMAN_any))			&&
-		    (info->dest_flags & dest_flags) == info->dest_flags)
-		{
-		    func = info->func;
-		    break;
-		}
-	    }
-	    
-	    if (func)
+	for (info = imp->fast_paths; info->op != PIXMAN_OP_NONE; ++info)
+	{
+	    if ((info->op == op || info->op == PIXMAN_OP_any)		&&
+		/* src */
+		((info->src_format == src_format) ||
+		 (info->src_format == PIXMAN_any))			&&
+		(info->src_flags & src_flags) == info->src_flags	&&
+		/* mask */
+		((info->mask_format == mask_format) ||
+		 (info->mask_format == PIXMAN_any))			&&
+		(info->mask_flags & mask_flags) == info->mask_flags	&&
+		/* dest */
+		((info->dest_format == dest_format) ||
+		 (info->dest_format == PIXMAN_any))			&&
+		(info->dest_flags & dest_flags) == info->dest_flags)
 	    {
-		pixman_bool_t src_repeat, mask_repeat;
-		
-		src_repeat =
-		    src->type == BITS					&&
-		    src_flags & FAST_PATH_ID_TRANSFORM			&&
-		    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-		    src_format != PIXMAN_solid;
-		
-		mask_repeat =
-		    mask						&&
-		    mask->type == BITS					&&
-		    mask_flags & FAST_PATH_ID_TRANSFORM			&&
-		    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-		    mask_format != PIXMAN_solid;
-		
 		walk_region_internal (imp, op,
 				      src, mask, dest,
 				      src_x, src_y, mask_x, mask_y,
@@ -619,18 +605,16 @@ do_composite (pixman_implementation_t *imp,
 				      width, height,
 				      src_repeat, mask_repeat,
 				      &region,
-				      func);
+				      info->func);
 		
-		result = TRUE;
+		goto done;
 	    }
-	    
-	    if (result)
-		break;
 	}
 	
 	imp = imp->delegate;
     }
 
+done:
     pixman_region32_fini (&region);
 }
 
commit 129d9c187146a060863598d154e6770394547afd
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 01:16:40 2009 -0400

    Move region computation out of the loop in do_composite()
    
    We only need to compute the composite region once, not on every
    iteration.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 822d7f4..9d0641b 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -528,6 +528,7 @@ do_composite (pixman_implementation_t *imp,
 {
     pixman_format_code_t src_format, mask_format, dest_format;
     uint32_t src_flags, mask_flags, dest_flags;
+    pixman_region32_t region;
 
     get_image_info (src,  &src_format,  &src_flags);
     get_image_info (mask, &mask_format, &mask_flags);
@@ -545,24 +546,23 @@ do_composite (pixman_implementation_t *imp,
 	    src_format = mask_format = PIXMAN_rpixbuf;
     }
 	    
+    pixman_region32_init (&region);
+    
+    if (!pixman_compute_composite_region32 (
+	    &region, src, mask, dest,
+	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
+    {
+	return;
+    }
+    
     while (imp)
     {
 	{
 	    pixman_composite_func_t func;
 	    const pixman_fast_path_t *info;
 	    pixman_bool_t result;
-	    pixman_region32_t region;
 	    pixman_box32_t *extents;
 	    
-	    pixman_region32_init (&region);
-	    
-	    if (!pixman_compute_composite_region32 (
-		    &region, src, mask, dest,
-		    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
-	    {
-		return;
-	    }
-	    
 	    result = FALSE;
 	    
 	    extents = pixman_region32_extents (&region);
@@ -624,13 +624,14 @@ do_composite (pixman_implementation_t *imp,
 		result = TRUE;
 	    }
 	    
-	    pixman_region32_fini (&region);
 	    if (result)
-		return;
+		break;
 	}
 	
 	imp = imp->delegate;
     }
+
+    pixman_region32_fini (&region);
 }
 
 /*
commit 4c185503d26374915942d1f64c02134e4a2c5a99
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 01:14:41 2009 -0400

    Move get_image_info() out of the loop in do_composite
    
    The computation of image formats and flags is invariant to the loop,
    so it can all be moved out.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 25f773b..822d7f4 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -526,33 +526,34 @@ do_composite (pixman_implementation_t *imp,
 	      int		       width,
 	      int		       height)
 {
+    pixman_format_code_t src_format, mask_format, dest_format;
+    uint32_t src_flags, mask_flags, dest_flags;
+
+    get_image_info (src,  &src_format,  &src_flags);
+    get_image_info (mask, &mask_format, &mask_flags);
+    get_image_info (dest, &dest_format, &dest_flags);
+    
+    /* Check for pixbufs */
+    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_x == mask_x && src_y == mask_y))
+    {
+	if (src_format == PIXMAN_x8b8g8r8)
+	    src_format = mask_format = PIXMAN_pixbuf;
+	else if (src_format == PIXMAN_x8r8g8b8)
+	    src_format = mask_format = PIXMAN_rpixbuf;
+    }
+	    
     while (imp)
     {
 	{
-	    pixman_format_code_t src_format, mask_format, dest_format;
-	    uint32_t src_flags, mask_flags, dest_flags;
 	    pixman_composite_func_t func;
 	    const pixman_fast_path_t *info;
 	    pixman_bool_t result;
 	    pixman_region32_t region;
 	    pixman_box32_t *extents;
 	    
-	    get_image_info (src,  &src_format,  &src_flags);
-	    get_image_info (mask, &mask_format, &mask_flags);
-	    get_image_info (dest, &dest_format, &dest_flags);
-	    
-	    /* Check for pixbufs */
-	    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_x == mask_x && src_y == mask_y))
-	    {
-		if (src_format == PIXMAN_x8b8g8r8)
-		    src_format = mask_format = PIXMAN_pixbuf;
-		else if (src_format == PIXMAN_x8r8g8b8)
-		    src_format = mask_format = PIXMAN_rpixbuf;
-	    }
-	    
 	    pixman_region32_init (&region);
 	    
 	    if (!pixman_compute_composite_region32 (
commit 81b7d7b18050c770f272fd10aa7f5cf85ddc25cc
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 01:13:36 2009 -0400

    Manually inline _pixman_run_fast_path()
    
    Move all of the code into do_composite().

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 59e44bf..25f773b 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -511,120 +511,6 @@ image_covers (pixman_image_t *image,
     return TRUE;
 }
 
-static pixman_bool_t
-_pixman_run_fast_path (const pixman_fast_path_t *paths,
-                       pixman_implementation_t * imp,
-                       pixman_op_t               op,
-                       pixman_image_t *          src,
-                       pixman_image_t *          mask,
-                       pixman_image_t *          dest,
-                       int32_t                   src_x,
-                       int32_t                   src_y,
-                       int32_t                   mask_x,
-                       int32_t                   mask_y,
-                       int32_t                   dest_x,
-                       int32_t                   dest_y,
-                       int32_t                   width,
-                       int32_t                   height)
-{
-    pixman_format_code_t src_format, mask_format, dest_format;
-    uint32_t src_flags, mask_flags, dest_flags;
-    pixman_composite_func_t func;
-    const pixman_fast_path_t *info;
-    pixman_bool_t result;
-    pixman_region32_t region;
-    pixman_box32_t *extents;
-    
-    get_image_info (src,  &src_format,  &src_flags);
-    get_image_info (mask, &mask_format, &mask_flags);
-    get_image_info (dest, &dest_format, &dest_flags);
-    
-    /* Check for pixbufs */
-    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_x == mask_x && src_y == mask_y))
-    {
-	if (src_format == PIXMAN_x8b8g8r8)
-	    src_format = mask_format = PIXMAN_pixbuf;
-	else if (src_format == PIXMAN_x8r8g8b8)
-	    src_format = mask_format = PIXMAN_rpixbuf;
-    }
-
-    pixman_region32_init (&region);
-    
-    if (!pixman_compute_composite_region32 (
-	    &region, src, mask, dest,
-	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
-    {
-	return TRUE;
-    }
-
-    result = FALSE;
-    
-    extents = pixman_region32_extents (&region);
-
-    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
-	src_flags |= FAST_PATH_COVERS_CLIP;
-
-    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
-	mask_flags |= FAST_PATH_COVERS_CLIP;
-
-    func = NULL;
-    for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
-    {
-	if ((info->op == op || info->op == PIXMAN_OP_any)	&&
-	    /* src */
-	    ((info->src_format == src_format) ||
-	     (info->src_format == PIXMAN_any))			&&
-	    (info->src_flags & src_flags) == info->src_flags	&&
-	    /* mask */
-	    ((info->mask_format == mask_format) ||
-	     (info->mask_format == PIXMAN_any))			&&
-	    (info->mask_flags & mask_flags) == info->mask_flags	&&
-	    /* dest */
-	    ((info->dest_format == dest_format) ||
-	     (info->dest_format == PIXMAN_any))			&&
-	    (info->dest_flags & dest_flags) == info->dest_flags)
-	{
-	    func = info->func;
-	    break;
-	}
-    }
-
-    if (func)
-    {
-	pixman_bool_t src_repeat, mask_repeat;
-	
-	src_repeat =
-	    src->type == BITS					&&
-	    src_flags & FAST_PATH_ID_TRANSFORM			&&
-	    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-	    src_format != PIXMAN_solid;
-	
-	mask_repeat =
-	    mask						&&
-	    mask->type == BITS					&&
-	    mask_flags & FAST_PATH_ID_TRANSFORM			&&
-	    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-	    mask_format != PIXMAN_solid;
-	
-	walk_region_internal (imp, op,
-			      src, mask, dest,
-			      src_x, src_y, mask_x, mask_y,
-			      dest_x, dest_y,
-			      width, height,
-			      src_repeat, mask_repeat,
-			      &region,
-			      func);
-	
-	result = TRUE;
-    }
-
-    pixman_region32_fini (&region);
-    return result;
-}
-
 static void
 do_composite (pixman_implementation_t *imp,
 	      pixman_op_t	       op,
@@ -642,16 +528,106 @@ do_composite (pixman_implementation_t *imp,
 {
     while (imp)
     {
-	if (_pixman_run_fast_path (imp->fast_paths, imp,
-				   op, src, mask, dest,
-				   src_x, src_y,
-				   mask_x, mask_y,
-				   dest_x, dest_y,
-				   width, height))
 	{
-	    return;
+	    pixman_format_code_t src_format, mask_format, dest_format;
+	    uint32_t src_flags, mask_flags, dest_flags;
+	    pixman_composite_func_t func;
+	    const pixman_fast_path_t *info;
+	    pixman_bool_t result;
+	    pixman_region32_t region;
+	    pixman_box32_t *extents;
+	    
+	    get_image_info (src,  &src_format,  &src_flags);
+	    get_image_info (mask, &mask_format, &mask_flags);
+	    get_image_info (dest, &dest_format, &dest_flags);
+	    
+	    /* Check for pixbufs */
+	    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_x == mask_x && src_y == mask_y))
+	    {
+		if (src_format == PIXMAN_x8b8g8r8)
+		    src_format = mask_format = PIXMAN_pixbuf;
+		else if (src_format == PIXMAN_x8r8g8b8)
+		    src_format = mask_format = PIXMAN_rpixbuf;
+	    }
+	    
+	    pixman_region32_init (&region);
+	    
+	    if (!pixman_compute_composite_region32 (
+		    &region, src, mask, dest,
+		    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
+	    {
+		return;
+	    }
+	    
+	    result = FALSE;
+	    
+	    extents = pixman_region32_extents (&region);
+	    
+	    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
+		src_flags |= FAST_PATH_COVERS_CLIP;
+	    
+	    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
+		mask_flags |= FAST_PATH_COVERS_CLIP;
+	    
+	    func = NULL;
+	    for (info = imp->fast_paths; info->op != PIXMAN_OP_NONE; ++info)
+	    {
+		if ((info->op == op || info->op == PIXMAN_OP_any)	&&
+		    /* src */
+		    ((info->src_format == src_format) ||
+		     (info->src_format == PIXMAN_any))			&&
+		    (info->src_flags & src_flags) == info->src_flags	&&
+		    /* mask */
+		    ((info->mask_format == mask_format) ||
+		     (info->mask_format == PIXMAN_any))			&&
+		    (info->mask_flags & mask_flags) == info->mask_flags	&&
+		    /* dest */
+		    ((info->dest_format == dest_format) ||
+		     (info->dest_format == PIXMAN_any))			&&
+		    (info->dest_flags & dest_flags) == info->dest_flags)
+		{
+		    func = info->func;
+		    break;
+		}
+	    }
+	    
+	    if (func)
+	    {
+		pixman_bool_t src_repeat, mask_repeat;
+		
+		src_repeat =
+		    src->type == BITS					&&
+		    src_flags & FAST_PATH_ID_TRANSFORM			&&
+		    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+		    src_format != PIXMAN_solid;
+		
+		mask_repeat =
+		    mask						&&
+		    mask->type == BITS					&&
+		    mask_flags & FAST_PATH_ID_TRANSFORM			&&
+		    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+		    mask_format != PIXMAN_solid;
+		
+		walk_region_internal (imp, op,
+				      src, mask, dest,
+				      src_x, src_y, mask_x, mask_y,
+				      dest_x, dest_y,
+				      width, height,
+				      src_repeat, mask_repeat,
+				      &region,
+				      func);
+		
+		result = TRUE;
+	    }
+	    
+	    pixman_region32_fini (&region);
+	    if (result)
+		return;
 	}
-
+	
 	imp = imp->delegate;
     }
 }
commit e914cccb24c1391aa25eca8df87a08bd935cd870
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 01:11:04 2009 -0400

    Move compositing functionality from pixman-utils.c into pixman.c
    
    _pixman_run_fast_path() and pixman_compute_composite_region() are both
    moved to pixman-image, since at this point that's the only place they
    are being called from.

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 435d195..5fe2a3b 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -641,22 +641,6 @@ pixman_bool_t
 pixman_addition_overflows_int (unsigned int a, unsigned int b);
 
 /* Compositing utilities */
-pixman_bool_t
-_pixman_run_fast_path (const pixman_fast_path_t *paths,
-                       pixman_implementation_t * imp,
-                       pixman_op_t               op,
-                       pixman_image_t *          src,
-                       pixman_image_t *          mask,
-                       pixman_image_t *          dest,
-                       int32_t                   src_x,
-                       int32_t                   src_y,
-                       int32_t                   mask_x,
-                       int32_t                   mask_y,
-                       int32_t                   dest_x,
-                       int32_t                   dest_y,
-                       int32_t                   width,
-                       int32_t                   height);
-
 void
 pixman_expand (uint64_t *           dst,
                const uint32_t *     src,
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 6e2fd98..373e318 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -30,208 +30,6 @@
 
 #include "pixman-private.h"
 
-/*
- * Computing composite region
- */
-static inline pixman_bool_t
-clip_general_image (pixman_region32_t * region,
-                    pixman_region32_t * clip,
-                    int                 dx,
-                    int                 dy)
-{
-    if (pixman_region32_n_rects (region) == 1 &&
-        pixman_region32_n_rects (clip) == 1)
-    {
-	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
-	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
-	int v;
-
-	if (rbox->x1 < (v = cbox->x1 + dx))
-	    rbox->x1 = v;
-	if (rbox->x2 > (v = cbox->x2 + dx))
-	    rbox->x2 = v;
-	if (rbox->y1 < (v = cbox->y1 + dy))
-	    rbox->y1 = v;
-	if (rbox->y2 > (v = cbox->y2 + dy))
-	    rbox->y2 = v;
-	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
-	{
-	    pixman_region32_init (region);
-	    return FALSE;
-	}
-    }
-    else if (!pixman_region32_not_empty (clip))
-    {
-	return FALSE;
-    }
-    else
-    {
-	if (dx || dy)
-	    pixman_region32_translate (region, -dx, -dy);
-
-	if (!pixman_region32_intersect (region, region, clip))
-	    return FALSE;
-
-	if (dx || dy)
-	    pixman_region32_translate (region, dx, dy);
-    }
-
-    return pixman_region32_not_empty (region);
-}
-
-static inline pixman_bool_t
-clip_source_image (pixman_region32_t * region,
-                   pixman_image_t *    image,
-                   int                 dx,
-                   int                 dy)
-{
-    /* Source clips are ignored, unless they are explicitly turned on
-     * and the clip in question was set by an X client. (Because if
-     * the clip was not set by a client, then it is a hierarchy
-     * clip and those should always be ignored for sources).
-     */
-    if (!image->common.clip_sources || !image->common.client_clip)
-	return TRUE;
-
-    return clip_general_image (region,
-                               &image->common.clip_region,
-                               dx, dy);
-}
-
-/*
- * returns FALSE if the final region is empty.  Indistinguishable from
- * an allocation failure, but rendering ignores those anyways.
- */
-static pixman_bool_t
-pixman_compute_composite_region32 (pixman_region32_t * region,
-                                   pixman_image_t *    src_image,
-                                   pixman_image_t *    mask_image,
-                                   pixman_image_t *    dst_image,
-                                   int32_t             src_x,
-                                   int32_t             src_y,
-                                   int32_t             mask_x,
-                                   int32_t             mask_y,
-                                   int32_t             dest_x,
-                                   int32_t             dest_y,
-                                   int32_t             width,
-                                   int32_t             height)
-{
-    region->extents.x1 = dest_x;
-    region->extents.x2 = dest_x + width;
-    region->extents.y1 = dest_y;
-    region->extents.y2 = dest_y + height;
-
-    region->extents.x1 = MAX (region->extents.x1, 0);
-    region->extents.y1 = MAX (region->extents.y1, 0);
-    region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
-    region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
-
-    region->data = 0;
-
-    /* Check for empty operation */
-    if (region->extents.x1 >= region->extents.x2 ||
-        region->extents.y1 >= region->extents.y2)
-    {
-	pixman_region32_init (region);
-	return FALSE;
-    }
-
-    if (dst_image->common.have_clip_region)
-    {
-	if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
-	{
-	    pixman_region32_fini (region);
-	    return FALSE;
-	}
-    }
-
-    if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
-    {
-	if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
-	                         -dst_image->common.alpha_origin_x,
-	                         -dst_image->common.alpha_origin_y))
-	{
-	    pixman_region32_fini (region);
-	    return FALSE;
-	}
-    }
-
-    /* clip against src */
-    if (src_image->common.have_clip_region)
-    {
-	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
-	{
-	    pixman_region32_fini (region);
-	    return FALSE;
-	}
-    }
-    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
-    {
-	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
-	                        dest_x - (src_x - src_image->common.alpha_origin_x),
-	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
-	{
-	    pixman_region32_fini (region);
-	    return FALSE;
-	}
-    }
-    /* clip against mask */
-    if (mask_image && mask_image->common.have_clip_region)
-    {
-	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
-	{
-	    pixman_region32_fini (region);
-	    return FALSE;
-	}
-	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
-	{
-	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
-	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
-	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
-	    {
-		pixman_region32_fini (region);
-		return FALSE;
-	    }
-	}
-    }
-
-    return TRUE;
-}
-
-PIXMAN_EXPORT pixman_bool_t
-pixman_compute_composite_region (pixman_region16_t * region,
-                                 pixman_image_t *    src_image,
-                                 pixman_image_t *    mask_image,
-                                 pixman_image_t *    dst_image,
-                                 int16_t             src_x,
-                                 int16_t             src_y,
-                                 int16_t             mask_x,
-                                 int16_t             mask_y,
-                                 int16_t             dest_x,
-                                 int16_t             dest_y,
-                                 uint16_t            width,
-                                 uint16_t            height)
-{
-    pixman_region32_t r32;
-    pixman_bool_t retval;
-
-    pixman_region32_init (&r32);
-
-    retval = pixman_compute_composite_region32 (
-	&r32, src_image, mask_image, dst_image,
-	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
-	width, height);
-
-    if (retval)
-    {
-	if (!pixman_region16_copy_from_region32 (region, &r32))
-	    retval = FALSE;
-    }
-
-    pixman_region32_fini (&r32);
-    return retval;
-}
-
 pixman_bool_t
 pixman_multiply_overflows_int (unsigned int a,
                                unsigned int b)
@@ -369,303 +167,6 @@ pixman_contract (uint32_t *      dst,
     }
 }
 
-static void
-walk_region_internal (pixman_implementation_t *imp,
-                      pixman_op_t              op,
-                      pixman_image_t *         src_image,
-                      pixman_image_t *         mask_image,
-                      pixman_image_t *         dst_image,
-                      int32_t                  src_x,
-                      int32_t                  src_y,
-                      int32_t                  mask_x,
-                      int32_t                  mask_y,
-                      int32_t                  dest_x,
-                      int32_t                  dest_y,
-                      int32_t                  width,
-                      int32_t                  height,
-                      pixman_bool_t            src_repeat,
-                      pixman_bool_t            mask_repeat,
-                      pixman_region32_t *      region,
-                      pixman_composite_func_t  composite_rect)
-{
-    int n;
-    const pixman_box32_t *pbox;
-    int w, h, w_this, h_this;
-    int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
-
-    pbox = pixman_region32_rectangles (region, &n);
-    while (n--)
-    {
-	h = pbox->y2 - pbox->y1;
-	y_src = pbox->y1 - dest_y + src_y;
-	y_msk = pbox->y1 - dest_y + mask_y;
-	y_dst = pbox->y1;
-
-	while (h)
-	{
-	    h_this = h;
-	    w = pbox->x2 - pbox->x1;
-	    x_src = pbox->x1 - dest_x + src_x;
-	    x_msk = pbox->x1 - dest_x + mask_x;
-	    x_dst = pbox->x1;
-
-	    if (mask_repeat)
-	    {
-		y_msk = MOD (y_msk, mask_image->bits.height);
-		if (h_this > mask_image->bits.height - y_msk)
-		    h_this = mask_image->bits.height - y_msk;
-	    }
-
-	    if (src_repeat)
-	    {
-		y_src = MOD (y_src, src_image->bits.height);
-		if (h_this > src_image->bits.height - y_src)
-		    h_this = src_image->bits.height - y_src;
-	    }
-
-	    while (w)
-	    {
-		w_this = w;
-
-		if (mask_repeat)
-		{
-		    x_msk = MOD (x_msk, mask_image->bits.width);
-		    if (w_this > mask_image->bits.width - x_msk)
-			w_this = mask_image->bits.width - x_msk;
-		}
-
-		if (src_repeat)
-		{
-		    x_src = MOD (x_src, src_image->bits.width);
-		    if (w_this > src_image->bits.width - x_src)
-			w_this = src_image->bits.width - x_src;
-		}
-
-		(*composite_rect) (imp, op,
-				   src_image, mask_image, dst_image,
-				   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
-				   w_this, h_this);
-		w -= w_this;
-
-		x_src += w_this;
-		x_msk += w_this;
-		x_dst += w_this;
-	    }
-
-	    h -= h_this;
-	    y_src += h_this;
-	    y_msk += h_this;
-	    y_dst += h_this;
-	}
-
-	pbox++;
-    }
-}
-
-static void
-get_image_info (pixman_image_t       *image,
-		pixman_format_code_t *code,
-		uint32_t	     *flags)
-{
-    *flags = 0;
-    
-    if (!image)
-    {
-	*code = PIXMAN_null;
-    }
-    else
-    {
-	if (!image->common.transform)
-	{
-	    *flags |= FAST_PATH_ID_TRANSFORM;
-	}
-	else
-	{
-	    if (image->common.transform->matrix[0][1] == 0 &&
-		image->common.transform->matrix[1][0] == 0 &&
-		image->common.transform->matrix[2][0] == 0 &&
-		image->common.transform->matrix[2][1] == 0 &&
-		image->common.transform->matrix[2][2] == pixman_fixed_1)
-	    {
-		*flags |= FAST_PATH_SCALE_TRANSFORM;
-	    }
-	}
-	
-	if (!image->common.alpha_map)
-	    *flags |= FAST_PATH_NO_ALPHA_MAP;
-
-	if (image->common.filter != PIXMAN_FILTER_CONVOLUTION)
-	{
-	    *flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
-
-	    if (image->common.filter == PIXMAN_FILTER_NEAREST)
-		*flags |= FAST_PATH_NEAREST_FILTER;
-	}
-
-	if (image->common.repeat != PIXMAN_REPEAT_PAD)
-	    *flags |= FAST_PATH_NO_PAD_REPEAT;
-
-	if (image->common.repeat != PIXMAN_REPEAT_REFLECT)
-	    *flags |= FAST_PATH_NO_REFLECT_REPEAT;
-
-	*flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT);
-	if (image->type == BITS)
-	{
-	    if (image->bits.read_func || image->bits.write_func)
-		*flags &= ~FAST_PATH_NO_ACCESSORS;
-
-	    if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
-		*flags &= ~FAST_PATH_NO_WIDE_FORMAT;
-	}
-
-	if (image->common.component_alpha)
-	    *flags |= FAST_PATH_COMPONENT_ALPHA;
-	else
-	    *flags |= FAST_PATH_UNIFIED_ALPHA;
-
-	if (_pixman_image_is_solid (image))
-	    *code = PIXMAN_solid;
-	else if (image->common.type == BITS)
-	    *code = image->bits.format;
-	else
-	    *code = PIXMAN_unknown;
-    }
-}
-
-static force_inline pixman_bool_t
-image_covers (pixman_image_t *image,
-              pixman_box32_t *extents,
-              int             x,
-              int             y)
-{
-    if (image->common.type == BITS &&
-	image->common.repeat == PIXMAN_REPEAT_NONE)
-    {
-	if (x > extents->x1 || y > extents->y1 ||
-	    x + image->bits.width < extents->x2 ||
-	    y + image->bits.height < extents->y2)
-	{
-	    return FALSE;
-	}
-    }
-
-    return TRUE;
-}
-
-pixman_bool_t
-_pixman_run_fast_path (const pixman_fast_path_t *paths,
-                       pixman_implementation_t * imp,
-                       pixman_op_t               op,
-                       pixman_image_t *          src,
-                       pixman_image_t *          mask,
-                       pixman_image_t *          dest,
-                       int32_t                   src_x,
-                       int32_t                   src_y,
-                       int32_t                   mask_x,
-                       int32_t                   mask_y,
-                       int32_t                   dest_x,
-                       int32_t                   dest_y,
-                       int32_t                   width,
-                       int32_t                   height)
-{
-    pixman_format_code_t src_format, mask_format, dest_format;
-    uint32_t src_flags, mask_flags, dest_flags;
-    pixman_composite_func_t func;
-    const pixman_fast_path_t *info;
-    pixman_bool_t result;
-    pixman_region32_t region;
-    pixman_box32_t *extents;
-    
-    get_image_info (src,  &src_format,  &src_flags);
-    get_image_info (mask, &mask_format, &mask_flags);
-    get_image_info (dest, &dest_format, &dest_flags);
-    
-    /* Check for pixbufs */
-    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_x == mask_x && src_y == mask_y))
-    {
-	if (src_format == PIXMAN_x8b8g8r8)
-	    src_format = mask_format = PIXMAN_pixbuf;
-	else if (src_format == PIXMAN_x8r8g8b8)
-	    src_format = mask_format = PIXMAN_rpixbuf;
-    }
-
-    pixman_region32_init (&region);
-    
-    if (!pixman_compute_composite_region32 (
-	    &region, src, mask, dest,
-	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
-    {
-	return TRUE;
-    }
-
-    result = FALSE;
-    
-    extents = pixman_region32_extents (&region);
-
-    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
-	src_flags |= FAST_PATH_COVERS_CLIP;
-
-    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
-	mask_flags |= FAST_PATH_COVERS_CLIP;
-
-    func = NULL;
-    for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
-    {
-	if ((info->op == op || info->op == PIXMAN_OP_any)	&&
-	    /* src */
-	    ((info->src_format == src_format) ||
-	     (info->src_format == PIXMAN_any))			&&
-	    (info->src_flags & src_flags) == info->src_flags	&&
-	    /* mask */
-	    ((info->mask_format == mask_format) ||
-	     (info->mask_format == PIXMAN_any))			&&
-	    (info->mask_flags & mask_flags) == info->mask_flags	&&
-	    /* dest */
-	    ((info->dest_format == dest_format) ||
-	     (info->dest_format == PIXMAN_any))			&&
-	    (info->dest_flags & dest_flags) == info->dest_flags)
-	{
-	    func = info->func;
-	    break;
-	}
-    }
-
-    if (func)
-    {
-	pixman_bool_t src_repeat, mask_repeat;
-	
-	src_repeat =
-	    src->type == BITS					&&
-	    src_flags & FAST_PATH_ID_TRANSFORM			&&
-	    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-	    src_format != PIXMAN_solid;
-	
-	mask_repeat =
-	    mask						&&
-	    mask->type == BITS					&&
-	    mask_flags & FAST_PATH_ID_TRANSFORM			&&
-	    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-	    mask_format != PIXMAN_solid;
-	
-	walk_region_internal (imp, op,
-			      src, mask, dest,
-			      src_x, src_y, mask_x, mask_y,
-			      dest_x, dest_y,
-			      width, height,
-			      src_repeat, mask_repeat,
-			      &region,
-			      func);
-	
-	result = TRUE;
-    }
-
-    pixman_region32_fini (&region);
-    return result;
-}
-
 #define N_TMP_BOXES (16)
 
 pixman_bool_t
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 8fd6818..59e44bf 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -160,6 +160,471 @@ unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
     }
 }
 
+/*
+ * Computing composite region
+ */
+static inline pixman_bool_t
+clip_general_image (pixman_region32_t * region,
+                    pixman_region32_t * clip,
+                    int                 dx,
+                    int                 dy)
+{
+    if (pixman_region32_n_rects (region) == 1 &&
+        pixman_region32_n_rects (clip) == 1)
+    {
+	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
+	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
+	int v;
+
+	if (rbox->x1 < (v = cbox->x1 + dx))
+	    rbox->x1 = v;
+	if (rbox->x2 > (v = cbox->x2 + dx))
+	    rbox->x2 = v;
+	if (rbox->y1 < (v = cbox->y1 + dy))
+	    rbox->y1 = v;
+	if (rbox->y2 > (v = cbox->y2 + dy))
+	    rbox->y2 = v;
+	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
+	{
+	    pixman_region32_init (region);
+	    return FALSE;
+	}
+    }
+    else if (!pixman_region32_not_empty (clip))
+    {
+	return FALSE;
+    }
+    else
+    {
+	if (dx || dy)
+	    pixman_region32_translate (region, -dx, -dy);
+
+	if (!pixman_region32_intersect (region, region, clip))
+	    return FALSE;
+
+	if (dx || dy)
+	    pixman_region32_translate (region, dx, dy);
+    }
+
+    return pixman_region32_not_empty (region);
+}
+
+static inline pixman_bool_t
+clip_source_image (pixman_region32_t * region,
+                   pixman_image_t *    image,
+                   int                 dx,
+                   int                 dy)
+{
+    /* Source clips are ignored, unless they are explicitly turned on
+     * and the clip in question was set by an X client. (Because if
+     * the clip was not set by a client, then it is a hierarchy
+     * clip and those should always be ignored for sources).
+     */
+    if (!image->common.clip_sources || !image->common.client_clip)
+	return TRUE;
+
+    return clip_general_image (region,
+                               &image->common.clip_region,
+                               dx, dy);
+}
+
+/*
+ * returns FALSE if the final region is empty.  Indistinguishable from
+ * an allocation failure, but rendering ignores those anyways.
+ */
+static pixman_bool_t
+pixman_compute_composite_region32 (pixman_region32_t * region,
+                                   pixman_image_t *    src_image,
+                                   pixman_image_t *    mask_image,
+                                   pixman_image_t *    dst_image,
+                                   int32_t             src_x,
+                                   int32_t             src_y,
+                                   int32_t             mask_x,
+                                   int32_t             mask_y,
+                                   int32_t             dest_x,
+                                   int32_t             dest_y,
+                                   int32_t             width,
+                                   int32_t             height)
+{
+    region->extents.x1 = dest_x;
+    region->extents.x2 = dest_x + width;
+    region->extents.y1 = dest_y;
+    region->extents.y2 = dest_y + height;
+
+    region->extents.x1 = MAX (region->extents.x1, 0);
+    region->extents.y1 = MAX (region->extents.y1, 0);
+    region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
+    region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
+
+    region->data = 0;
+
+    /* Check for empty operation */
+    if (region->extents.x1 >= region->extents.x2 ||
+        region->extents.y1 >= region->extents.y2)
+    {
+	pixman_region32_init (region);
+	return FALSE;
+    }
+
+    if (dst_image->common.have_clip_region)
+    {
+	if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
+	{
+	    pixman_region32_fini (region);
+	    return FALSE;
+	}
+    }
+
+    if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
+    {
+	if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
+	                         -dst_image->common.alpha_origin_x,
+	                         -dst_image->common.alpha_origin_y))
+	{
+	    pixman_region32_fini (region);
+	    return FALSE;
+	}
+    }
+
+    /* clip against src */
+    if (src_image->common.have_clip_region)
+    {
+	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
+	{
+	    pixman_region32_fini (region);
+	    return FALSE;
+	}
+    }
+    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
+    {
+	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
+	                        dest_x - (src_x - src_image->common.alpha_origin_x),
+	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
+	{
+	    pixman_region32_fini (region);
+	    return FALSE;
+	}
+    }
+    /* clip against mask */
+    if (mask_image && mask_image->common.have_clip_region)
+    {
+	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
+	{
+	    pixman_region32_fini (region);
+	    return FALSE;
+	}
+	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
+	{
+	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
+	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
+	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
+	    {
+		pixman_region32_fini (region);
+		return FALSE;
+	    }
+	}
+    }
+
+    return TRUE;
+}
+
+static void
+walk_region_internal (pixman_implementation_t *imp,
+                      pixman_op_t              op,
+                      pixman_image_t *         src_image,
+                      pixman_image_t *         mask_image,
+                      pixman_image_t *         dst_image,
+                      int32_t                  src_x,
+                      int32_t                  src_y,
+                      int32_t                  mask_x,
+                      int32_t                  mask_y,
+                      int32_t                  dest_x,
+                      int32_t                  dest_y,
+                      int32_t                  width,
+                      int32_t                  height,
+                      pixman_bool_t            src_repeat,
+                      pixman_bool_t            mask_repeat,
+                      pixman_region32_t *      region,
+                      pixman_composite_func_t  composite_rect)
+{
+    int n;
+    const pixman_box32_t *pbox;
+    int w, h, w_this, h_this;
+    int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+
+    pbox = pixman_region32_rectangles (region, &n);
+    while (n--)
+    {
+	h = pbox->y2 - pbox->y1;
+	y_src = pbox->y1 - dest_y + src_y;
+	y_msk = pbox->y1 - dest_y + mask_y;
+	y_dst = pbox->y1;
+
+	while (h)
+	{
+	    h_this = h;
+	    w = pbox->x2 - pbox->x1;
+	    x_src = pbox->x1 - dest_x + src_x;
+	    x_msk = pbox->x1 - dest_x + mask_x;
+	    x_dst = pbox->x1;
+
+	    if (mask_repeat)
+	    {
+		y_msk = MOD (y_msk, mask_image->bits.height);
+		if (h_this > mask_image->bits.height - y_msk)
+		    h_this = mask_image->bits.height - y_msk;
+	    }
+
+	    if (src_repeat)
+	    {
+		y_src = MOD (y_src, src_image->bits.height);
+		if (h_this > src_image->bits.height - y_src)
+		    h_this = src_image->bits.height - y_src;
+	    }
+
+	    while (w)
+	    {
+		w_this = w;
+
+		if (mask_repeat)
+		{
+		    x_msk = MOD (x_msk, mask_image->bits.width);
+		    if (w_this > mask_image->bits.width - x_msk)
+			w_this = mask_image->bits.width - x_msk;
+		}
+
+		if (src_repeat)
+		{
+		    x_src = MOD (x_src, src_image->bits.width);
+		    if (w_this > src_image->bits.width - x_src)
+			w_this = src_image->bits.width - x_src;
+		}
+
+		(*composite_rect) (imp, op,
+				   src_image, mask_image, dst_image,
+				   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
+				   w_this, h_this);
+		w -= w_this;
+
+		x_src += w_this;
+		x_msk += w_this;
+		x_dst += w_this;
+	    }
+
+	    h -= h_this;
+	    y_src += h_this;
+	    y_msk += h_this;
+	    y_dst += h_this;
+	}
+
+	pbox++;
+    }
+}
+
+static void
+get_image_info (pixman_image_t       *image,
+		pixman_format_code_t *code,
+		uint32_t	     *flags)
+{
+    *flags = 0;
+    
+    if (!image)
+    {
+	*code = PIXMAN_null;
+    }
+    else
+    {
+	if (!image->common.transform)
+	{
+	    *flags |= FAST_PATH_ID_TRANSFORM;
+	}
+	else
+	{
+	    if (image->common.transform->matrix[0][1] == 0 &&
+		image->common.transform->matrix[1][0] == 0 &&
+		image->common.transform->matrix[2][0] == 0 &&
+		image->common.transform->matrix[2][1] == 0 &&
+		image->common.transform->matrix[2][2] == pixman_fixed_1)
+	    {
+		*flags |= FAST_PATH_SCALE_TRANSFORM;
+	    }
+	}
+	
+	if (!image->common.alpha_map)
+	    *flags |= FAST_PATH_NO_ALPHA_MAP;
+
+	if (image->common.filter != PIXMAN_FILTER_CONVOLUTION)
+	{
+	    *flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
+
+	    if (image->common.filter == PIXMAN_FILTER_NEAREST)
+		*flags |= FAST_PATH_NEAREST_FILTER;
+	}
+
+	if (image->common.repeat != PIXMAN_REPEAT_PAD)
+	    *flags |= FAST_PATH_NO_PAD_REPEAT;
+
+	if (image->common.repeat != PIXMAN_REPEAT_REFLECT)
+	    *flags |= FAST_PATH_NO_REFLECT_REPEAT;
+
+	*flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NO_WIDE_FORMAT);
+	if (image->type == BITS)
+	{
+	    if (image->bits.read_func || image->bits.write_func)
+		*flags &= ~FAST_PATH_NO_ACCESSORS;
+
+	    if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
+		*flags &= ~FAST_PATH_NO_WIDE_FORMAT;
+	}
+
+	if (image->common.component_alpha)
+	    *flags |= FAST_PATH_COMPONENT_ALPHA;
+	else
+	    *flags |= FAST_PATH_UNIFIED_ALPHA;
+
+	if (_pixman_image_is_solid (image))
+	    *code = PIXMAN_solid;
+	else if (image->common.type == BITS)
+	    *code = image->bits.format;
+	else
+	    *code = PIXMAN_unknown;
+    }
+}
+
+static force_inline pixman_bool_t
+image_covers (pixman_image_t *image,
+              pixman_box32_t *extents,
+              int             x,
+              int             y)
+{
+    if (image->common.type == BITS &&
+	image->common.repeat == PIXMAN_REPEAT_NONE)
+    {
+	if (x > extents->x1 || y > extents->y1 ||
+	    x + image->bits.width < extents->x2 ||
+	    y + image->bits.height < extents->y2)
+	{
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+static pixman_bool_t
+_pixman_run_fast_path (const pixman_fast_path_t *paths,
+                       pixman_implementation_t * imp,
+                       pixman_op_t               op,
+                       pixman_image_t *          src,
+                       pixman_image_t *          mask,
+                       pixman_image_t *          dest,
+                       int32_t                   src_x,
+                       int32_t                   src_y,
+                       int32_t                   mask_x,
+                       int32_t                   mask_y,
+                       int32_t                   dest_x,
+                       int32_t                   dest_y,
+                       int32_t                   width,
+                       int32_t                   height)
+{
+    pixman_format_code_t src_format, mask_format, dest_format;
+    uint32_t src_flags, mask_flags, dest_flags;
+    pixman_composite_func_t func;
+    const pixman_fast_path_t *info;
+    pixman_bool_t result;
+    pixman_region32_t region;
+    pixman_box32_t *extents;
+    
+    get_image_info (src,  &src_format,  &src_flags);
+    get_image_info (mask, &mask_format, &mask_flags);
+    get_image_info (dest, &dest_format, &dest_flags);
+    
+    /* Check for pixbufs */
+    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_x == mask_x && src_y == mask_y))
+    {
+	if (src_format == PIXMAN_x8b8g8r8)
+	    src_format = mask_format = PIXMAN_pixbuf;
+	else if (src_format == PIXMAN_x8r8g8b8)
+	    src_format = mask_format = PIXMAN_rpixbuf;
+    }
+
+    pixman_region32_init (&region);
+    
+    if (!pixman_compute_composite_region32 (
+	    &region, src, mask, dest,
+	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
+    {
+	return TRUE;
+    }
+
+    result = FALSE;
+    
+    extents = pixman_region32_extents (&region);
+
+    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
+	src_flags |= FAST_PATH_COVERS_CLIP;
+
+    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
+	mask_flags |= FAST_PATH_COVERS_CLIP;
+
+    func = NULL;
+    for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
+    {
+	if ((info->op == op || info->op == PIXMAN_OP_any)	&&
+	    /* src */
+	    ((info->src_format == src_format) ||
+	     (info->src_format == PIXMAN_any))			&&
+	    (info->src_flags & src_flags) == info->src_flags	&&
+	    /* mask */
+	    ((info->mask_format == mask_format) ||
+	     (info->mask_format == PIXMAN_any))			&&
+	    (info->mask_flags & mask_flags) == info->mask_flags	&&
+	    /* dest */
+	    ((info->dest_format == dest_format) ||
+	     (info->dest_format == PIXMAN_any))			&&
+	    (info->dest_flags & dest_flags) == info->dest_flags)
+	{
+	    func = info->func;
+	    break;
+	}
+    }
+
+    if (func)
+    {
+	pixman_bool_t src_repeat, mask_repeat;
+	
+	src_repeat =
+	    src->type == BITS					&&
+	    src_flags & FAST_PATH_ID_TRANSFORM			&&
+	    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	    src_format != PIXMAN_solid;
+	
+	mask_repeat =
+	    mask						&&
+	    mask->type == BITS					&&
+	    mask_flags & FAST_PATH_ID_TRANSFORM			&&
+	    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	    mask_format != PIXMAN_solid;
+	
+	walk_region_internal (imp, op,
+			      src, mask, dest,
+			      src_x, src_y, mask_x, mask_y,
+			      dest_x, dest_y,
+			      width, height,
+			      src_repeat, mask_repeat,
+			      &region,
+			      func);
+	
+	result = TRUE;
+    }
+
+    pixman_region32_fini (&region);
+    return result;
+}
+
 static void
 do_composite (pixman_implementation_t *imp,
 	      pixman_op_t	       op,
@@ -663,3 +1128,36 @@ pixman_format_supported_destination (pixman_format_code_t format)
     return pixman_format_supported_source (format);
 }
 
+PIXMAN_EXPORT pixman_bool_t
+pixman_compute_composite_region (pixman_region16_t * region,
+                                 pixman_image_t *    src_image,
+                                 pixman_image_t *    mask_image,
+                                 pixman_image_t *    dst_image,
+                                 int16_t             src_x,
+                                 int16_t             src_y,
+                                 int16_t             mask_x,
+                                 int16_t             mask_y,
+                                 int16_t             dest_x,
+                                 int16_t             dest_y,
+                                 uint16_t            width,
+                                 uint16_t            height)
+{
+    pixman_region32_t r32;
+    pixman_bool_t retval;
+
+    pixman_region32_init (&r32);
+
+    retval = pixman_compute_composite_region32 (
+	&r32, src_image, mask_image, dst_image,
+	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
+	width, height);
+
+    if (retval)
+    {
+	if (!pixman_region16_copy_from_region32 (region, &r32))
+	    retval = FALSE;
+    }
+
+    pixman_region32_fini (&r32);
+    return retval;
+}
commit 0eeb197599cca78a645f8a5498b0124ef170c523
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 7 15:13:03 2009 -0500

    Move compositing to its own function, do_composite()

diff --git a/pixman/pixman.c b/pixman/pixman.c
index b2e1a83..8fd6818 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -160,6 +160,37 @@ unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
     }
 }
 
+static void
+do_composite (pixman_implementation_t *imp,
+	      pixman_op_t	       op,
+	      pixman_image_t	      *src,
+	      pixman_image_t	      *mask,
+	      pixman_image_t	      *dest,
+	      int		       src_x,
+	      int		       src_y,
+	      int		       mask_x,
+	      int		       mask_y,
+	      int		       dest_x,
+	      int		       dest_y,
+	      int		       width,
+	      int		       height)
+{
+    while (imp)
+    {
+	if (_pixman_run_fast_path (imp->fast_paths, imp,
+				   op, src, mask, dest,
+				   src_x, src_y,
+				   mask_x, mask_y,
+				   dest_x, dest_y,
+				   width, height))
+	{
+	    return;
+	}
+
+	imp = imp->delegate;
+    }
+}
+
 /*
  * Work around GCC bug causing crashes in Mozilla with SSE2
  *
@@ -217,7 +248,6 @@ pixman_image_composite32 (pixman_op_t      op,
     int mask_dx, mask_dy;
     uint32_t *dest_bits;
     int dest_dx, dest_dy;
-    pixman_implementation_t *i;
     pixman_bool_t need_workaround;
 
     _pixman_image_validate (src);
@@ -253,18 +283,12 @@ pixman_image_composite32 (pixman_op_t      op,
 	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
     }
 
-    for (i = imp; i != NULL; i = i->delegate)
-    {
-	if (_pixman_run_fast_path (i->fast_paths, imp,
-				   op, src, mask, dest,
-				   src_x, src_y,
-				   mask_x, mask_y,
-				   dest_x, dest_y,
-				   width, height))
-	{
-	    break;
-	}
-    }
+    do_composite (imp, op,
+		  src, mask, dest,
+		  src_x, src_y,
+		  mask_x, mask_y,
+		  dest_x, dest_y,
+		  width, height);
     
     if (need_workaround)
     {
commit f831552bce70f2619ea8db00983d80dd1abd0003
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 00:58:51 2009 -0400

    Optimize for the common case wrt. the workaround.
    
    In the common case no images need the workaround, so we check for that
    first, and only if an image does need a workaround do we check which
    one of the images actually need it.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index c49a50b..b2e1a83 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -117,41 +117,47 @@ apply_workaround (pixman_image_t *image,
 		  int *           save_dx,
 		  int *           save_dy)
 {
-    /* Some X servers generate images that point to the
-     * wrong place in memory, but then set the clip region
-     * to point to the right place. Because of an old bug
-     * in pixman, this would actually work.
-     *
-     * Here we try and undo the damage
-     */
-    int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
-    pixman_box32_t *extents;
-    uint8_t *t;
-    int dx, dy;
-
-    extents = pixman_region32_extents (&(image->common.clip_region));
-    dx = extents->x1;
-    dy = extents->y1;
-
-    *save_bits = image->bits.bits;
-
-    *x -= dx;
-    *y -= dy;
-    pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
-
-    t = (uint8_t *)image->bits.bits;
-    t += dy * image->bits.rowstride * 4 + dx * bpp;
-    image->bits.bits = (uint32_t *)t;
-
-    *save_dx = dx;
-    *save_dy = dy;
+    if (image && image->common.need_workaround)
+    {
+	/* Some X servers generate images that point to the
+	 * wrong place in memory, but then set the clip region
+	 * to point to the right place. Because of an old bug
+	 * in pixman, this would actually work.
+	 *
+	 * Here we try and undo the damage
+	 */
+	int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
+	pixman_box32_t *extents;
+	uint8_t *t;
+	int dx, dy;
+	
+	extents = pixman_region32_extents (&(image->common.clip_region));
+	dx = extents->x1;
+	dy = extents->y1;
+	
+	*save_bits = image->bits.bits;
+	
+	*x -= dx;
+	*y -= dy;
+	pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
+	
+	t = (uint8_t *)image->bits.bits;
+	t += dy * image->bits.rowstride * 4 + dx * bpp;
+	image->bits.bits = (uint32_t *)t;
+	
+	*save_dx = dx;
+	*save_dy = dy;
+    }
 }
 
 static void
 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
 {
-    image->bits.bits = bits;
-    pixman_region32_translate (&image->common.clip_region, dx, dy);
+    if (image && image->common.need_workaround)
+    {
+	image->bits.bits = bits;
+	pixman_region32_translate (&image->common.clip_region, dx, dy);
+    }
 }
 
 /*
@@ -212,6 +218,7 @@ pixman_image_composite32 (pixman_op_t      op,
     uint32_t *dest_bits;
     int dest_dx, dest_dy;
     pixman_implementation_t *i;
+    pixman_bool_t need_workaround;
 
     _pixman_image_validate (src);
     if (mask)
@@ -234,12 +241,17 @@ pixman_image_composite32 (pixman_op_t      op,
     if (!imp)
 	imp = _pixman_choose_implementation ();
 
-    if (src->common.need_workaround)
+    need_workaround =
+	(src->common.need_workaround)			||
+	(mask && mask->common.need_workaround)		||
+	(dest->common.need_workaround);
+   
+    if (need_workaround)
+    {
 	apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
-    if (mask && mask->common.need_workaround)
 	apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
-    if (dest->common.need_workaround)
 	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
+    }
 
     for (i = imp; i != NULL; i = i->delegate)
     {
@@ -253,13 +265,16 @@ pixman_image_composite32 (pixman_op_t      op,
 	    break;
 	}
     }
-		
-    if (src->common.need_workaround)
-	unapply_workaround (src, src_bits, src_dx, src_dy);
-    if (mask && mask->common.need_workaround)
-	unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
-    if (dest->common.need_workaround)
-	unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
+    
+    if (need_workaround)
+    {
+	if (src->common.need_workaround)
+	    unapply_workaround (src, src_bits, src_dx, src_dy);
+	if (mask && mask->common.need_workaround)
+	    unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
+	if (dest->common.need_workaround)
+	    unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
+    }
 }
 
 PIXMAN_EXPORT pixman_bool_t
commit fa4df6225d4fa0b740c0ce69361e2f7cee1686f9
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 00:48:12 2009 -0400

    Eliminate all the composite methods.
    
    They are no longer necessary because we will just walk the fast path
    tables, and the general composite path is treated as another fast
    path.
    
    This unfortunately means that sse2_composite() can no longer be
    responsible for realigning the stack to 16 bytes, so we have to move
    that to pixman_image_composite().

diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c
index c0a75d5..557301e 100644
--- a/pixman/pixman-arm-neon.c
+++ b/pixman/pixman-arm-neon.c
@@ -435,39 +435,6 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
     { PIXMAN_OP_NONE },
 };
 
-static void
-arm_neon_composite (pixman_implementation_t *imp,
-                    pixman_op_t              op,
-                    pixman_image_t *         src,
-                    pixman_image_t *         mask,
-                    pixman_image_t *         dest,
-                    int32_t                  src_x,
-                    int32_t                  src_y,
-                    int32_t                  mask_x,
-                    int32_t                  mask_y,
-                    int32_t                  dest_x,
-                    int32_t                  dest_y,
-                    int32_t                  width,
-                    int32_t                  height)
-{
-    if (_pixman_run_fast_path (arm_neon_fast_paths, imp,
-                               op, src, mask, dest,
-                               src_x, src_y,
-                               mask_x, mask_y,
-                               dest_x, dest_y,
-                               width, height))
-    {
-	return;
-    }
-
-    _pixman_implementation_composite (imp->delegate, op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-}
-
 static pixman_bool_t
 arm_neon_blt (pixman_implementation_t *imp,
               uint32_t *               src_bits,
@@ -555,7 +522,6 @@ _pixman_implementation_create_arm_neon (void)
     imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
     imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
 
-    imp->composite = arm_neon_composite;
     imp->blt = arm_neon_blt;
     imp->fill = arm_neon_fill;
 
diff --git a/pixman/pixman-arm-simd.c b/pixman/pixman-arm-simd.c
index 965f810..09a2888 100644
--- a/pixman/pixman-arm-simd.c
+++ b/pixman/pixman-arm-simd.c
@@ -438,46 +438,11 @@ static const pixman_fast_path_t arm_simd_fast_paths[] =
     { PIXMAN_OP_NONE },
 };
 
-static void
-arm_simd_composite (pixman_implementation_t *imp,
-                    pixman_op_t              op,
-                    pixman_image_t *         src,
-                    pixman_image_t *         mask,
-                    pixman_image_t *         dest,
-                    int32_t                  src_x,
-                    int32_t                  src_y,
-                    int32_t                  mask_x,
-                    int32_t                  mask_y,
-                    int32_t                  dest_x,
-                    int32_t                  dest_y,
-                    int32_t                  width,
-                    int32_t                  height)
-{
-    if (_pixman_run_fast_path (arm_simd_fast_paths, imp,
-                               op, src, mask, dest,
-                               src_x, src_y,
-                               mask_x, mask_y,
-                               dest_x, dest_y,
-                               width, height))
-    {
-	return;
-    }
-
-    _pixman_implementation_composite (imp->delegate, op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-}
-
 pixman_implementation_t *
 _pixman_implementation_create_arm_simd (void)
 {
     pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
     pixman_implementation_t *imp = _pixman_implementation_create (general, arm_simd_fast_paths);
 
-    imp->composite = arm_simd_composite;
-
     return imp;
 }
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 642848e..4d26b0f 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -1627,39 +1627,6 @@ static const pixman_fast_path_t c_fast_paths[] =
 };
 
 static void
-fast_path_composite (pixman_implementation_t *imp,
-                     pixman_op_t              op,
-                     pixman_image_t *         src,
-                     pixman_image_t *         mask,
-                     pixman_image_t *         dest,
-                     int32_t                  src_x,
-                     int32_t                  src_y,
-                     int32_t                  mask_x,
-                     int32_t                  mask_y,
-                     int32_t                  dest_x,
-                     int32_t                  dest_y,
-                     int32_t                  width,
-                     int32_t                  height)
-{
-    if (_pixman_run_fast_path (c_fast_paths, imp,
-			       op, src, mask, dest,
-			       src_x, src_y,
-			       mask_x, mask_y,
-			       dest_x, dest_y,
-			       width, height))
-    {
-	return;
-    }
-
-    _pixman_implementation_composite (imp->delegate, op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-}
-
-static void
 pixman_fill8 (uint32_t *bits,
               int       stride,
               int       x,
@@ -1772,7 +1739,6 @@ _pixman_implementation_create_fast_path (void)
     pixman_implementation_t *general = _pixman_implementation_create_general ();
     pixman_implementation_t *imp = _pixman_implementation_create (general, c_fast_paths);
 
-    imp->composite = fast_path_composite;
     imp->fill = fast_path_fill;
 
     return imp;
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 32afd2e..bddf79a 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -270,33 +270,6 @@ static const pixman_fast_path_t general_fast_path[] =
     { PIXMAN_OP_NONE }
 };
 
-static void
-general_composite (pixman_implementation_t * imp,
-                   pixman_op_t               op,
-                   pixman_image_t *          src,
-                   pixman_image_t *          mask,
-                   pixman_image_t *          dest,
-                   int32_t                   src_x,
-                   int32_t                   src_y,
-                   int32_t                   mask_x,
-                   int32_t                   mask_y,
-                   int32_t                   dest_x,
-                   int32_t                   dest_y,
-                   int32_t                   width,
-                   int32_t                   height)
-{
-    pixman_bool_t result;
-
-    result = _pixman_run_fast_path (general_fast_path, imp,
-				    op, src, mask, dest,
-				    src_x, src_y,
-				    mask_x, mask_y,
-				    dest_x, dest_y,
-				    width, height);
-
-    assert (result);
-}
-
 static pixman_bool_t
 general_blt (pixman_implementation_t *imp,
              uint32_t *               src_bits,
@@ -339,7 +312,6 @@ _pixman_implementation_create_general (void)
     _pixman_setup_combiner_functions_32 (imp);
     _pixman_setup_combiner_functions_64 (imp);
 
-    imp->composite = general_composite;
     imp->blt = general_blt;
     imp->fill = general_fill;
 
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index ca1e18f..bc3749e 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -28,30 +28,6 @@
 #include "pixman-private.h"
 
 static void
-delegate_composite (pixman_implementation_t * imp,
-                    pixman_op_t               op,
-                    pixman_image_t *          src,
-                    pixman_image_t *          mask,
-                    pixman_image_t *          dest,
-                    int32_t                   src_x,
-                    int32_t                   src_y,
-                    int32_t                   mask_x,
-                    int32_t                   mask_y,
-                    int32_t                   dest_x,
-                    int32_t                   dest_y,
-                    int32_t                   width,
-                    int32_t                   height)
-{
-    _pixman_implementation_composite (imp->delegate,
-                                      op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-}
-
-static void
 delegate_combine_32 (pixman_implementation_t * imp,
                      pixman_op_t               op,
                      uint32_t *                dest,
@@ -155,7 +131,6 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
 
     /* Fill out function pointers with ones that just delegate
      */
-    imp->composite = delegate_composite;
     imp->blt = delegate_blt;
     imp->fill = delegate_fill;
 
@@ -216,27 +191,6 @@ _pixman_implementation_combine_64_ca (pixman_implementation_t * imp,
     (*imp->combine_64_ca[op]) (imp, op, dest, src, mask, width);
 }
 
-void
-_pixman_implementation_composite (pixman_implementation_t * imp,
-                                  pixman_op_t               op,
-                                  pixman_image_t *          src,
-                                  pixman_image_t *          mask,
-                                  pixman_image_t *          dest,
-                                  int32_t                   src_x,
-                                  int32_t                   src_y,
-                                  int32_t                   mask_x,
-                                  int32_t                   mask_y,
-                                  int32_t                   dest_x,
-                                  int32_t                   dest_y,
-                                  int32_t                   width,
-                                  int32_t                   height)
-{
-    (*imp->composite) (imp, op,
-		       src, mask, dest,
-		       src_x, src_y, mask_x, mask_y, dest_x, dest_y,
-		       width, height);
-}
-
 pixman_bool_t
 _pixman_implementation_blt (pixman_implementation_t * imp,
                             uint32_t *                src_bits,
diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c
index 9bbe317..e084e7f 100644
--- a/pixman/pixman-mmx.c
+++ b/pixman/pixman-mmx.c
@@ -3288,37 +3288,6 @@ static const pixman_fast_path_t mmx_fast_paths[] =
     { PIXMAN_OP_NONE },
 };
 
-static void
-mmx_composite (pixman_implementation_t *imp,
-               pixman_op_t              op,
-               pixman_image_t *         src,
-               pixman_image_t *         mask,
-               pixman_image_t *         dest,
-               int32_t                  src_x,
-               int32_t                  src_y,
-               int32_t                  mask_x,
-               int32_t                  mask_y,
-               int32_t                  dest_x,
-               int32_t                  dest_y,
-               int32_t                  width,
-               int32_t                  height)
-{
-    if (_pixman_run_fast_path (mmx_fast_paths, imp,
-                               op, src, mask, dest,
-                               src_x, src_y,
-                               mask_x, mask_y,
-                               dest_x, dest_y,
-                               width, height))
-    {
-	return;
-    }
-
-    _pixman_implementation_composite (imp->delegate,
-                                      op, src, mask, dest, src_x, src_y,
-                                      mask_x, mask_y, dest_x, dest_y,
-                                      width, height);
-}
-
 static pixman_bool_t
 mmx_blt (pixman_implementation_t *imp,
          uint32_t *               src_bits,
@@ -3398,7 +3367,6 @@ _pixman_implementation_create_mmx (void)
     imp->combine_32_ca[PIXMAN_OP_XOR] = mmx_combine_xor_ca;
     imp->combine_32_ca[PIXMAN_OP_ADD] = mmx_combine_add_ca;
 
-    imp->composite = mmx_composite;
     imp->blt = mmx_blt;
     imp->fill = mmx_fill;
 
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 8d29010..435d195 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -444,8 +444,7 @@ struct pixman_implementation_t
     pixman_implementation_t *	toplevel;
     pixman_implementation_t *	delegate;
     const pixman_fast_path_t *	fast_paths;
-
-    pixman_composite_func_t	composite;
+    
     pixman_blt_func_t		blt;
     pixman_fill_func_t		fill;
 
@@ -487,21 +486,6 @@ _pixman_implementation_combine_64_ca (pixman_implementation_t *imp,
                                       const uint64_t *         src,
                                       const uint64_t *         mask,
                                       int                      width);
-void
-_pixman_implementation_composite (pixman_implementation_t *imp,
-                                  pixman_op_t              op,
-                                  pixman_image_t *         src,
-                                  pixman_image_t *         mask,
-                                  pixman_image_t *         dest,
-                                  int32_t                  src_x,
-                                  int32_t                  src_y,
-                                  int32_t                  mask_x,
-                                  int32_t                  mask_y,
-                                  int32_t                  dest_x,
-                                  int32_t                  dest_y,
-                                  int32_t                  width,
-                                  int32_t                  height);
-
 
 pixman_bool_t
 _pixman_implementation_blt (pixman_implementation_t *imp,
diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c
index 85fb897..c8481dc 100644
--- a/pixman/pixman-sse2.c
+++ b/pixman/pixman-sse2.c
@@ -5842,61 +5842,6 @@ static const pixman_fast_path_t sse2_fast_paths[] =
     { PIXMAN_OP_NONE },
 };
 
-/*
- * Work around GCC bug causing crashes in Mozilla with SSE2
- *
- * When using -msse, gcc generates movdqa instructions assuming that
- * the stack is 16 byte aligned. Unfortunately some applications, such
- * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
- * causes the movdqa instructions to fail.
- *
- * The __force_align_arg_pointer__ makes gcc generate a prologue that
- * realigns the stack pointer to 16 bytes.
- *
- * On x86-64 this is not necessary because the standard ABI already
- * calls for a 16 byte aligned stack.
- *
- * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
- */
-#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
-__attribute__((__force_align_arg_pointer__))
-#endif
-static void
-sse2_composite (pixman_implementation_t *imp,
-                pixman_op_t              op,
-                pixman_image_t *         src,
-                pixman_image_t *         mask,
-                pixman_image_t *         dest,
-                int32_t                  src_x,
-                int32_t                  src_y,
-                int32_t                  mask_x,
-                int32_t                  mask_y,
-                int32_t                  dest_x,
-                int32_t                  dest_y,
-                int32_t                  width,
-                int32_t                  height)
-{
-    if (_pixman_run_fast_path (sse2_fast_paths, imp,
-                               op, src, mask, dest,
-                               src_x, src_y,
-                               mask_x, mask_y,
-                               dest_x, dest_y,
-                               width, height))
-    {
-	return;
-    }
-
-    _pixman_implementation_composite (imp->delegate, op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-}
-
-#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
-__attribute__((__force_align_arg_pointer__))
-#endif
 static pixman_bool_t
 sse2_blt (pixman_implementation_t *imp,
           uint32_t *               src_bits,
@@ -6014,7 +5959,6 @@ _pixman_implementation_create_sse2 (void)
     imp->combine_32_ca[PIXMAN_OP_XOR] = sse2_combine_xor_ca;
     imp->combine_32_ca[PIXMAN_OP_ADD] = sse2_combine_add_ca;
 
-    imp->composite = sse2_composite;
     imp->blt = sse2_blt;
     imp->fill = sse2_fill;
 
diff --git a/pixman/pixman.c b/pixman/pixman.c
index f70823e..c49a50b 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -154,6 +154,25 @@ unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
     pixman_region32_translate (&image->common.clip_region, dx, dy);
 }
 
+/*
+ * Work around GCC bug causing crashes in Mozilla with SSE2
+ *
+ * When using -msse, gcc generates movdqa instructions assuming that
+ * the stack is 16 byte aligned. Unfortunately some applications, such
+ * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
+ * causes the movdqa instructions to fail.
+ *
+ * The __force_align_arg_pointer__ makes gcc generate a prologue that
+ * realigns the stack pointer to 16 bytes.
+ *
+ * On x86-64 this is not necessary because the standard ABI already
+ * calls for a 16 byte aligned stack.
+ *
+ * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
+ */
+#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
+__attribute__((__force_align_arg_pointer__))
+#endif
 PIXMAN_EXPORT void
 pixman_image_composite (pixman_op_t      op,
                         pixman_image_t * src,
commit c3d7b5125585a7d974ccd904100777a0e18d425f
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 00:23:11 2009 -0400

    Delete unused _pixman_walk_composite_region() function

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index c956f49..8d29010 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -674,22 +674,6 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
                        int32_t                   height);
 
 void
-_pixman_walk_composite_region (pixman_implementation_t *imp,
-                               pixman_op_t              op,
-                               pixman_image_t *         src_image,
-                               pixman_image_t *         mask_image,
-                               pixman_image_t *         dst_image,
-                               int32_t                  src_x,
-                               int32_t                  src_y,
-                               int32_t                  mask_x,
-                               int32_t                  mask_y,
-                               int32_t                  dest_x,
-                               int32_t                  dest_y,
-                               int32_t                  width,
-                               int32_t                  height,
-                               pixman_composite_func_t  composite_rect);
-
-void
 pixman_expand (uint64_t *           dst,
                const uint32_t *     src,
                pixman_format_code_t format,
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index db06f7c..6e2fd98 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -462,42 +462,6 @@ walk_region_internal (pixman_implementation_t *imp,
     }
 }
 
-void
-_pixman_walk_composite_region (pixman_implementation_t *imp,
-                               pixman_op_t              op,
-                               pixman_image_t *         src_image,
-                               pixman_image_t *         mask_image,
-                               pixman_image_t *         dst_image,
-                               int32_t                  src_x,
-                               int32_t                  src_y,
-                               int32_t                  mask_x,
-                               int32_t                  mask_y,
-                               int32_t                  dest_x,
-                               int32_t                  dest_y,
-                               int32_t                  width,
-                               int32_t                  height,
-                               pixman_composite_func_t  composite_rect)
-{
-    pixman_region32_t region;
-
-    pixman_region32_init (&region);
-
-    if (pixman_compute_composite_region32 (
-            &region, src_image, mask_image, dst_image,
-            src_x, src_y, mask_x, mask_y, dest_x, dest_y,
-            width, height))
-    {
-	walk_region_internal (imp, op,
-	                      src_image, mask_image, dst_image,
-	                      src_x, src_y, mask_x, mask_y, dest_x, dest_y,
-	                      width, height, FALSE, FALSE,
-	                      &region,
-	                      composite_rect);
-
-	pixman_region32_fini (&region);
-    }
-}
-
 static void
 get_image_info (pixman_image_t       *image,
 		pixman_format_code_t *code,
commit 488480301c7ca9cb4e41c8d0f489fb56e5d9efdd
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 7 15:28:57 2009 -0500

    Don't call _pixman_implementation_composite() anymore.
    
    Instead just call _pixman_run_fast_path(). Since we view
    general_composite() as a fast path now, we know that it will find
    *some* compositing routine.

diff --git a/pixman/pixman.c b/pixman/pixman.c
index 9ab875d..f70823e 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -192,6 +192,7 @@ pixman_image_composite32 (pixman_op_t      op,
     int mask_dx, mask_dy;
     uint32_t *dest_bits;
     int dest_dx, dest_dy;
+    pixman_implementation_t *i;
 
     _pixman_image_validate (src);
     if (mask)
@@ -221,13 +222,19 @@ pixman_image_composite32 (pixman_op_t      op,
     if (dest->common.need_workaround)
 	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
 
-    _pixman_implementation_composite (imp, op,
-                                      src, mask, dest,
-                                      src_x, src_y,
-                                      mask_x, mask_y,
-                                      dest_x, dest_y,
-                                      width, height);
-
+    for (i = imp; i != NULL; i = i->delegate)
+    {
+	if (_pixman_run_fast_path (i->fast_paths, imp,
+				   op, src, mask, dest,
+				   src_x, src_y,
+				   mask_x, mask_y,
+				   dest_x, dest_y,
+				   width, height))
+	{
+	    break;
+	}
+    }
+		
     if (src->common.need_workaround)
 	unapply_workaround (src, src_bits, src_dx, src_dy);
     if (mask && mask->common.need_workaround)
commit 06ae5ed5971fe616b96bb97a63abf6cc27c5b669
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Mon Sep 14 23:58:40 2009 -0400

    Delete unused sources_cover() function

diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 9306c17..db06f7c 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -588,29 +588,6 @@ image_covers (pixman_image_t *image,
     return TRUE;
 }
 
-static force_inline pixman_bool_t
-sources_cover (pixman_image_t *src,
-	       pixman_image_t *mask,
-	       pixman_box32_t *extents,
-	       int             src_x,
-	       int             src_y,
-	       int             mask_x,
-	       int             mask_y,
-	       int             dest_x,
-	       int             dest_y)
-{
-    if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y))
-	return FALSE;
-
-    if (!mask)
-	return TRUE;
-
-    if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
-	return FALSE;
-
-    return TRUE;
-}
-
 pixman_bool_t
 _pixman_run_fast_path (const pixman_fast_path_t *paths,
                        pixman_implementation_t * imp,
commit 543a04a3bbd2c622842739ab923ff8761c05ed83
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Mon Sep 14 23:47:39 2009 -0400

    Store a pointer to the array of fast paths in the implementation struct.
    
    Also add an empty fast path table to the vmx implementation, so that
    we can assume sure the pointer is never NULL.

diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c
index 26f7267..c0a75d5 100644
--- a/pixman/pixman-arm-neon.c
+++ b/pixman/pixman-arm-neon.c
@@ -383,7 +383,7 @@ pixman_blt_neon (uint32_t *src_bits,
     }
 }
 
-static const pixman_fast_path_t arm_neon_fast_path_array[] =
+static const pixman_fast_path_t arm_neon_fast_paths[] =
 {
     PIXMAN_STD_FAST_PATH (SRC,  r5g6b5,   null,     r5g6b5,   neon_composite_src_0565_0565),
     PIXMAN_STD_FAST_PATH (SRC,  b5g6r5,   null,     b5g6r5,   neon_composite_src_0565_0565),
@@ -435,8 +435,6 @@ static const pixman_fast_path_t arm_neon_fast_path_array[] =
     { PIXMAN_OP_NONE },
 };
 
-const pixman_fast_path_t *const arm_neon_fast_paths = arm_neon_fast_path_array;
-
 static void
 arm_neon_composite (pixman_implementation_t *imp,
                     pixman_op_t              op,
@@ -551,7 +549,8 @@ pixman_implementation_t *
 _pixman_implementation_create_arm_neon (void)
 {
     pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
-    pixman_implementation_t *imp = _pixman_implementation_create (general);
+    pixman_implementation_t *imp =
+	_pixman_implementation_create (general, arm_neon_fast_paths);
 
     imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
     imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
diff --git a/pixman/pixman-arm-simd.c b/pixman/pixman-arm-simd.c
index dd8dc5c..965f810 100644
--- a/pixman/pixman-arm-simd.c
+++ b/pixman/pixman-arm-simd.c
@@ -419,7 +419,7 @@ arm_composite_over_n_8_8888 (pixman_implementation_t * impl,
     }
 }
 
-static const pixman_fast_path_t arm_simd_fast_path_array[] =
+static const pixman_fast_path_t arm_simd_fast_paths[] =
 {
     PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, arm_composite_over_8888_8888),
     PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, arm_composite_over_8888_8888),
@@ -438,8 +438,6 @@ static const pixman_fast_path_t arm_simd_fast_path_array[] =
     { PIXMAN_OP_NONE },
 };
 
-const pixman_fast_path_t *const arm_simd_fast_paths = arm_simd_fast_path_array;
-
 static void
 arm_simd_composite (pixman_implementation_t *imp,
                     pixman_op_t              op,
@@ -477,7 +475,7 @@ pixman_implementation_t *
 _pixman_implementation_create_arm_simd (void)
 {
     pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
-    pixman_implementation_t *imp = _pixman_implementation_create (general);
+    pixman_implementation_t *imp = _pixman_implementation_create (general, arm_simd_fast_paths);
 
     imp->composite = arm_simd_composite;
 
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 72630b4..642848e 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -1770,7 +1770,7 @@ pixman_implementation_t *
 _pixman_implementation_create_fast_path (void)
 {
     pixman_implementation_t *general = _pixman_implementation_create_general ();
-    pixman_implementation_t *imp = _pixman_implementation_create (general);
+    pixman_implementation_t *imp = _pixman_implementation_create (general, c_fast_paths);
 
     imp->composite = fast_path_composite;
     imp->fill = fast_path_fill;
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 83500b9..32afd2e 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -266,13 +266,8 @@ general_composite_rect  (pixman_implementation_t *imp,
 
 static const pixman_fast_path_t general_fast_path[] =
 {
-    {   PIXMAN_OP_any,
-	PIXMAN_any,		0,
-	PIXMAN_any,		0,
-	PIXMAN_any,		0,
-	general_composite_rect,
-    },
-    {	PIXMAN_OP_NONE	}
+    { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any,	0, PIXMAN_any, 0, general_composite_rect },
+    { PIXMAN_OP_NONE }
 };
 
 static void
@@ -298,7 +293,7 @@ general_composite (pixman_implementation_t * imp,
 				    mask_x, mask_y,
 				    dest_x, dest_y,
 				    width, height);
-    
+
     assert (result);
 }
 
@@ -339,7 +334,7 @@ general_fill (pixman_implementation_t *imp,
 pixman_implementation_t *
 _pixman_implementation_create_general (void)
 {
-    pixman_implementation_t *imp = _pixman_implementation_create (NULL);
+    pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
 
     _pixman_setup_combiner_functions_32 (imp);
     _pixman_setup_combiner_functions_64 (imp);
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index 6488332..ca1e18f 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -136,7 +136,8 @@ delegate_fill (pixman_implementation_t *imp,
 }
 
 pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate)
+_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;
@@ -145,6 +146,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate)
     if (!imp)
 	return NULL;
 
+    assert (fast_paths);
+
     /* Make sure the whole delegate chain has the right toplevel */
     imp->delegate = delegate;
     for (d = imp; d != NULL; d = d->delegate)
@@ -164,6 +167,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate)
 	imp->combine_64_ca[i] = delegate_combine_64_ca;
     }
 
+    imp->fast_paths = fast_paths;
+    
     return imp;
 }
 
diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c
index a4affa5..9bbe317 100644
--- a/pixman/pixman-mmx.c
+++ b/pixman/pixman-mmx.c
@@ -3372,7 +3372,7 @@ pixman_implementation_t *
 _pixman_implementation_create_mmx (void)
 {
     pixman_implementation_t *general = _pixman_implementation_create_fast_path ();
-    pixman_implementation_t *imp = _pixman_implementation_create (general);
+    pixman_implementation_t *imp = _pixman_implementation_create (general, mmx_fast_paths);
 
     imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 8910526..c956f49 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -372,7 +372,6 @@ pixman_rasterize_edges_accessors (pixman_image_t *image,
 /*
  * Implementations
  */
-
 typedef struct pixman_implementation_t pixman_implementation_t;
 
 typedef void (*pixman_combine_32_func_t) (pixman_implementation_t *imp,
@@ -428,23 +427,37 @@ typedef pixman_bool_t (*pixman_fill_func_t) (pixman_implementation_t *imp,
 void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp);
 void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp);
 
-struct pixman_implementation_t
+typedef struct
 {
-    pixman_implementation_t *toplevel;
-    pixman_implementation_t *delegate;
-
-    pixman_composite_func_t  composite;
-    pixman_blt_func_t        blt;
-    pixman_fill_func_t       fill;
+    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_composite_func_t func;
+} pixman_fast_path_t;
 
-    pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS];
-    pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS];
-    pixman_combine_64_func_t combine_64[PIXMAN_N_OPERATORS];
-    pixman_combine_64_func_t combine_64_ca[PIXMAN_N_OPERATORS];
+struct pixman_implementation_t
+{
+    pixman_implementation_t *	toplevel;
+    pixman_implementation_t *	delegate;
+    const pixman_fast_path_t *	fast_paths;
+
+    pixman_composite_func_t	composite;
+    pixman_blt_func_t		blt;
+    pixman_fill_func_t		fill;
+
+    pixman_combine_32_func_t	combine_32[PIXMAN_N_OPERATORS];
+    pixman_combine_32_func_t	combine_32_ca[PIXMAN_N_OPERATORS];
+    pixman_combine_64_func_t	combine_64[PIXMAN_N_OPERATORS];
+    pixman_combine_64_func_t	combine_64_ca[PIXMAN_N_OPERATORS];
 };
 
 pixman_implementation_t *
-_pixman_implementation_create (pixman_implementation_t *delegate);
+_pixman_implementation_create (pixman_implementation_t *delegate,
+			       const pixman_fast_path_t *fast_paths);
 
 void
 _pixman_implementation_combine_32 (pixman_implementation_t *imp,
@@ -489,6 +502,7 @@ _pixman_implementation_composite (pixman_implementation_t *imp,
                                   int32_t                  width,
                                   int32_t                  height);
 
+
 pixman_bool_t
 _pixman_implementation_blt (pixman_implementation_t *imp,
                             uint32_t *               src_bits,
@@ -603,18 +617,6 @@ _pixman_choose_implementation (void);
     (FAST_PATH_NO_ACCESSORS		|				\
      FAST_PATH_NO_WIDE_FORMAT)
 
-typedef struct
-{
-    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_composite_func_t func;
-} pixman_fast_path_t;
-
 #define FAST_PATH(op, src, src_flags, mask, mask_flags, dest, dest_flags, func) \
     PIXMAN_OP_ ## op,							\
     PIXMAN_ ## src,							\
diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c
index 2bade74..85fb897 100644
--- a/pixman/pixman-sse2.c
+++ b/pixman/pixman-sse2.c
@@ -5956,7 +5956,7 @@ pixman_implementation_t *
 _pixman_implementation_create_sse2 (void)
 {
     pixman_implementation_t *mmx = _pixman_implementation_create_mmx ();
-    pixman_implementation_t *imp = _pixman_implementation_create (mmx);
+    pixman_implementation_t *imp = _pixman_implementation_create (mmx, sse2_fast_paths);
 
     /* SSE2 constants */
     mask_565_r  = create_mask_2x32_128 (0x00f80000, 0x00f80000);
diff --git a/pixman/pixman-vmx.c b/pixman/pixman-vmx.c
index 06325a7..e811cf7 100644
--- a/pixman/pixman-vmx.c
+++ b/pixman/pixman-vmx.c
@@ -1607,11 +1607,16 @@ vmx_combine_add_ca (pixman_implementation_t *imp,
     }
 }
 
+static const pixman_fast_path_t vmx_fast_paths[] =
+{
+    {   PIXMAN_OP_NONE	},
+};
+
 pixman_implementation_t *
 _pixman_implementation_create_vmx (void)
 {
     pixman_implementation_t *fast = _pixman_implementation_create_fast_path ();
-    pixman_implementation_t *imp = _pixman_implementation_create (fast);
+    pixman_implementation_t *imp = _pixman_implementation_create (fast, vmx_fast_paths);
 
     /* Set up function pointers */
 
commit 376f2a3f853f829c78983a51bffc1bacb9bec9a3
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Sep 15 00:20:22 2009 -0400

    Make fast_composite_scaled_nearest() another fast path.
    
    This requires another couple of flags
    
         FAST_PATH_SCALE_TRANSFORM
         FAST_PATH_NEAREST_FILTER

diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 170e9d6..72630b4 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -1033,7 +1033,7 @@ fast_composite_add_n_8_8 (pixman_implementation_t *imp,
 #define UPDATE_BITMASK(n) ((n) << 1)
 #endif
 
-#define TEST_BIT(p, n)						\
+#define TEST_BIT(p, n)					\
     (*((p) + ((n) >> 5)) & CREATE_BITMASK ((n) & 31))
 #define SET_BIT(p, n)							\
     do { *((p) + ((n) >> 5)) |= CREATE_BITMASK ((n) & 31); } while (0);
@@ -1345,64 +1345,6 @@ fast_composite_src_8888_x888 (pixman_implementation_t *imp,
     }
 }
 
-static const pixman_fast_path_t c_fast_paths[] =
-{
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5,   fast_composite_over_n_1_0565),
-    PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5,   fast_composite_over_n_1_0565),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca),
-    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca),
-    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888),
-    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888),
-    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888),
-    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565),
-    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888),
-    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888),
-    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565),
-    PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888),
-    PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888),
-    PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8000_8000),
-    PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1000_1000),
-    PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca),
-    PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill),
-    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888),
-    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888),
-    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888),
-    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888),
-    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
-    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
-    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
-    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
-    PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8),
-    PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8),
-
-    { PIXMAN_OP_NONE },
-};
-
 static force_inline pixman_bool_t
 repeat (pixman_repeat_t repeat, int *c, int size)
 {
@@ -1591,6 +1533,99 @@ fast_composite_scaled_nearest (pixman_implementation_t *imp,
     }
 }
 
+static const pixman_fast_path_t c_fast_paths[] =
+{
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, fast_composite_over_n_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, fast_composite_over_n_8_0565),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, r8g8b8, fast_composite_over_n_8_0888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, b8g8r8, fast_composite_over_n_8_0888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, fast_composite_over_n_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, fast_composite_over_n_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, fast_composite_over_n_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, fast_composite_over_n_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8r8g8b8, fast_composite_over_n_1_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8r8g8b8, fast_composite_over_n_1_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, a8b8g8r8, fast_composite_over_n_1_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, x8b8g8r8, fast_composite_over_n_1_8888),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, r5g6b5,   fast_composite_over_n_1_0565),
+    PIXMAN_STD_FAST_PATH (OVER, solid, a1, b5g6r5,   fast_composite_over_n_1_0565),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, fast_composite_over_n_8888_8888_ca),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, fast_composite_over_n_8888_8888_ca),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, fast_composite_over_n_8888_0565_ca),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, fast_composite_over_n_8888_8888_ca),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, fast_composite_over_n_8888_8888_ca),
+    PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, fast_composite_over_n_8888_0565_ca),
+    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, x8r8g8b8, fast_composite_over_x888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, a8, a8r8g8b8, fast_composite_over_x888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, x8b8g8r8, fast_composite_over_x888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, a8, a8b8g8r8, fast_composite_over_x888_8_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, fast_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, fast_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, fast_composite_over_8888_0565),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888),
+    PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565),
+    PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888),
+    PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888),
+    PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8000_8000),
+    PIXMAN_STD_FAST_PATH (ADD, a1, null, a1, fast_composite_add_1000_1000),
+    PIXMAN_STD_FAST_PATH_CA (ADD, solid, a8r8g8b8, a8r8g8b8, fast_composite_add_n_8888_8888_ca),
+    PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, fast_composite_add_n_8_8),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8r8g8b8, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8r8g8b8, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8b8g8r8, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, x8b8g8r8, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, a8, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, solid, null, r5g6b5, fast_composite_solid_fill),
+    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888),
+    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, fast_composite_src_8888_x888),
+    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888),
+    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, fast_composite_src_8888_x888),
+    PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
+    PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, fast_composite_src_x888_0565),
+    PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
+    PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, fast_composite_src_x888_0565),
+    PIXMAN_STD_FAST_PATH (IN, a8, null, a8, fast_composite_in_8_8),
+    PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, fast_composite_in_n_8_8),
+
+#define SCALED_NEAREST_FLAGS						\
+    (FAST_PATH_SCALE_TRANSFORM	|					\
+     FAST_PATH_NO_ALPHA_MAP	|					\
+     FAST_PATH_NEAREST_FILTER	|					\
+     FAST_PATH_NO_ACCESSORS	|					\
+     FAST_PATH_NO_WIDE_FORMAT)
+
+#define NEAREST_FAST_PATH(op,s,d)		\
+    {   PIXMAN_OP_ ## op,			\
+	PIXMAN_ ## s, SCALED_NEAREST_FLAGS,	\
+	PIXMAN_null, 0,				\
+	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,	\
+	fast_composite_scaled_nearest,		\
+    }
+
+    NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8),
+    NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8),
+    NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8),
+    NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8),
+
+    NEAREST_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8),
+    NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8),
+    NEAREST_FAST_PATH (SRC, x8b8g8r8, a8b8g8r8),
+    NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8),
+
+    NEAREST_FAST_PATH (OVER, x8r8g8b8, x8r8g8b8),
+    NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8),
+    NEAREST_FAST_PATH (OVER, x8b8g8r8, x8b8g8r8),
+    NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8),
+
+    NEAREST_FAST_PATH (OVER, x8r8g8b8, a8r8g8b8),
+    NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8),
+    NEAREST_FAST_PATH (OVER, x8b8g8r8, a8b8g8r8),
+    NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8),
+
+    {   PIXMAN_OP_NONE	},
+};
+
 static void
 fast_path_composite (pixman_implementation_t *imp,
                      pixman_op_t              op,
@@ -1606,41 +1641,12 @@ fast_path_composite (pixman_implementation_t *imp,
                      int32_t                  width,
                      int32_t                  height)
 {
-    if (src->type == BITS
-        && src->common.transform
-        && !mask
-        && (op == PIXMAN_OP_SRC || op == PIXMAN_OP_OVER)
-        && !src->common.alpha_map && !dest->common.alpha_map
-        && (src->common.filter == PIXMAN_FILTER_NEAREST)
-	&& (dest->bits.format == PIXMAN_a8r8g8b8 || dest->bits.format == PIXMAN_x8r8g8b8)
-	&& (src->bits.format == PIXMAN_a8r8g8b8 || src->bits.format == PIXMAN_x8r8g8b8)
-        && !src->bits.read_func && !src->bits.write_func
-        && !dest->bits.read_func && !dest->bits.write_func)
-    {
-	/* ensure that the transform matrix only has a scale */
-	if (src->common.transform->matrix[0][1] == 0 &&
-	    src->common.transform->matrix[1][0] == 0 &&
-	    src->common.transform->matrix[2][0] == 0 &&
-	    src->common.transform->matrix[2][1] == 0 &&
-	    src->common.transform->matrix[2][2] == pixman_fixed_1)
-	{
-	    _pixman_walk_composite_region (imp, op,
-	                                   src, mask, dest,
-	                                   src_x, src_y,
-	                                   mask_x, mask_y,
-	                                   dest_x, dest_y,
-	                                   width, height,
-	                                   fast_composite_scaled_nearest);
-	    return;
-	}
-    }
-
     if (_pixman_run_fast_path (c_fast_paths, imp,
-                               op, src, mask, dest,
-                               src_x, src_y,
-                               mask_x, mask_y,
-                               dest_x, dest_y,
-                               width, height))
+			       op, src, mask, dest,
+			       src_x, src_y,
+			       mask_x, mask_y,
+			       dest_x, dest_y,
+			       width, height))
     {
 	return;
     }
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 0ed3662..8910526 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -568,16 +568,18 @@ _pixman_choose_implementation (void);
 
 #define PIXMAN_OP_any		(PIXMAN_N_OPERATORS + 1)
 
-#define FAST_PATH_ID_TRANSFORM			(1 << 0)
-#define FAST_PATH_NO_ALPHA_MAP			(1 << 1)
-#define FAST_PATH_NO_CONVOLUTION_FILTER		(1 << 2)
-#define FAST_PATH_NO_PAD_REPEAT			(1 << 3)
-#define FAST_PATH_NO_REFLECT_REPEAT		(1 << 4)
-#define FAST_PATH_NO_ACCESSORS			(1 << 5)
-#define FAST_PATH_NO_WIDE_FORMAT		(1 << 6)
-#define FAST_PATH_COVERS_CLIP			(1 << 7)
-#define FAST_PATH_COMPONENT_ALPHA		(1 << 8)
-#define FAST_PATH_UNIFIED_ALPHA			(1 << 9)
+#define FAST_PATH_ID_TRANSFORM			(1 <<  0)
+#define FAST_PATH_NO_ALPHA_MAP			(1 <<  1)
+#define FAST_PATH_NO_CONVOLUTION_FILTER		(1 <<  2)
+#define FAST_PATH_NO_PAD_REPEAT			(1 <<  3)
+#define FAST_PATH_NO_REFLECT_REPEAT		(1 <<  4)
+#define FAST_PATH_NO_ACCESSORS			(1 <<  5)
+#define FAST_PATH_NO_WIDE_FORMAT		(1 <<  6)
+#define FAST_PATH_COVERS_CLIP			(1 <<  7)
+#define FAST_PATH_COMPONENT_ALPHA		(1 <<  8)
+#define FAST_PATH_UNIFIED_ALPHA			(1 <<  9)
+#define FAST_PATH_SCALE_TRANSFORM		(1 << 10)
+#define FAST_PATH_NEAREST_FILTER		(1 << 11)
 
 #define _FAST_PATH_STANDARD_FLAGS					\
     (FAST_PATH_ID_TRANSFORM		|				\
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 66bdb30..9306c17 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -512,14 +512,32 @@ get_image_info (pixman_image_t       *image,
     else
     {
 	if (!image->common.transform)
+	{
 	    *flags |= FAST_PATH_ID_TRANSFORM;
-
+	}
+	else
+	{
+	    if (image->common.transform->matrix[0][1] == 0 &&
+		image->common.transform->matrix[1][0] == 0 &&
+		image->common.transform->matrix[2][0] == 0 &&
+		image->common.transform->matrix[2][1] == 0 &&
+		image->common.transform->matrix[2][2] == pixman_fixed_1)
+	    {
+		*flags |= FAST_PATH_SCALE_TRANSFORM;
+	    }
+	}
+	
 	if (!image->common.alpha_map)
 	    *flags |= FAST_PATH_NO_ALPHA_MAP;
 
 	if (image->common.filter != PIXMAN_FILTER_CONVOLUTION)
+	{
 	    *flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
 
+	    if (image->common.filter == PIXMAN_FILTER_NEAREST)
+		*flags |= FAST_PATH_NEAREST_FILTER;
+	}
+
 	if (image->common.repeat != PIXMAN_REPEAT_PAD)
 	    *flags |= FAST_PATH_NO_PAD_REPEAT;
 
commit 87430cfc35c6e51bb1a947795e0ddb198c460253
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sun Sep 13 05:29:48 2009 -0400

    Make general_composite_rect() just another fast path.
    
    We introduce a new PIXMAN_OP_any fake operator and a PIXMAN_any fake
    format that match anything. Then general_composite_rect() can be used
    as another fast path.
    
    Because general_composite_rect() does not require the sources to cover
    the clip region, we add a new flag FAST_PATH_COVERS_CLIP which is part
    of the set of standard flags for fast paths.
    
    Because this flag cannot be computed until after the clip region is
    available, we have to call pixman_compute_composite_region32() before
    checking for fast paths. This will resolve itself when we get to the
    point where _pixman_run_fast_path() is only called once per composite
    operation.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index c96a3f9..83500b9 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -264,6 +264,17 @@ general_composite_rect  (pixman_implementation_t *imp,
 	free (scanline_buffer);
 }
 
+static const pixman_fast_path_t general_fast_path[] =
+{
+    {   PIXMAN_OP_any,
+	PIXMAN_any,		0,
+	PIXMAN_any,		0,
+	PIXMAN_any,		0,
+	general_composite_rect,
+    },
+    {	PIXMAN_OP_NONE	}
+};
+
 static void
 general_composite (pixman_implementation_t * imp,
                    pixman_op_t               op,
@@ -279,10 +290,16 @@ general_composite (pixman_implementation_t * imp,
                    int32_t                   width,
                    int32_t                   height)
 {
-    _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
-                                   mask_x, mask_y, dest_x, dest_y,
-				   width, height,
-                                   general_composite_rect);
+    pixman_bool_t result;
+
+    result = _pixman_run_fast_path (general_fast_path, imp,
+				    op, src, mask, dest,
+				    src_x, src_y,
+				    mask_x, mask_y,
+				    dest_x, dest_y,
+				    width, height);
+    
+    assert (result);
 }
 
 static pixman_bool_t
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index c99b101..0ed3662 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -564,6 +564,9 @@ _pixman_choose_implementation (void);
 #define PIXMAN_pixbuf		PIXMAN_FORMAT (0, 2, 0, 0, 0, 0)
 #define PIXMAN_rpixbuf		PIXMAN_FORMAT (0, 3, 0, 0, 0, 0)
 #define PIXMAN_unknown		PIXMAN_FORMAT (0, 4, 0, 0, 0, 0)
+#define PIXMAN_any		PIXMAN_FORMAT (0, 5, 0, 0, 0, 0)	
+
+#define PIXMAN_OP_any		(PIXMAN_N_OPERATORS + 1)
 
 #define FAST_PATH_ID_TRANSFORM			(1 << 0)
 #define FAST_PATH_NO_ALPHA_MAP			(1 << 1)
@@ -572,7 +575,7 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_NO_REFLECT_REPEAT		(1 << 4)
 #define FAST_PATH_NO_ACCESSORS			(1 << 5)
 #define FAST_PATH_NO_WIDE_FORMAT		(1 << 6)
-#define FAST_PATH_reserved			(1 << 7)
+#define FAST_PATH_COVERS_CLIP			(1 << 7)
 #define FAST_PATH_COMPONENT_ALPHA		(1 << 8)
 #define FAST_PATH_UNIFIED_ALPHA			(1 << 9)
 
@@ -583,7 +586,8 @@ _pixman_choose_implementation (void);
      FAST_PATH_NO_PAD_REPEAT		|				\
      FAST_PATH_NO_REFLECT_REPEAT	|				\
      FAST_PATH_NO_ACCESSORS		|				\
-     FAST_PATH_NO_WIDE_FORMAT)
+     FAST_PATH_NO_WIDE_FORMAT		|				\
+     FAST_PATH_COVERS_CLIP)
 
 #define FAST_PATH_STD_SRC_FLAGS						\
     _FAST_PATH_STANDARD_FLAGS
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 5441b6b..66bdb30 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -614,7 +614,9 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
     pixman_composite_func_t func;
     const pixman_fast_path_t *info;
     pixman_bool_t result;
-
+    pixman_region32_t region;
+    pixman_box32_t *extents;
+    
     get_image_info (src,  &src_format,  &src_flags);
     get_image_info (mask, &mask_format, &mask_flags);
     get_image_info (dest, &dest_format, &dest_flags);
@@ -631,15 +633,40 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
 	    src_format = mask_format = PIXMAN_rpixbuf;
     }
 
+    pixman_region32_init (&region);
+    
+    if (!pixman_compute_composite_region32 (
+	    &region, src, mask, dest,
+	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
+    {
+	return TRUE;
+    }
+
+    result = FALSE;
+    
+    extents = pixman_region32_extents (&region);
+
+    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
+	src_flags |= FAST_PATH_COVERS_CLIP;
+
+    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
+	mask_flags |= FAST_PATH_COVERS_CLIP;
+
     func = NULL;
     for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
     {
-	if (info->op == op					&&
-	    (info->src_format == src_format)			&&
+	if ((info->op == op || info->op == PIXMAN_OP_any)	&&
+	    /* src */
+	    ((info->src_format == src_format) ||
+	     (info->src_format == PIXMAN_any))			&&
 	    (info->src_flags & src_flags) == info->src_flags	&&
-	    (info->mask_format == mask_format)			&&
+	    /* mask */
+	    ((info->mask_format == mask_format) ||
+	     (info->mask_format == PIXMAN_any))			&&
 	    (info->mask_flags & mask_flags) == info->mask_flags	&&
-	    (info->dest_format == dest_format)			&&
+	    /* dest */
+	    ((info->dest_format == dest_format) ||
+	     (info->dest_format == PIXMAN_any))			&&
 	    (info->dest_flags & dest_flags) == info->dest_flags)
 	{
 	    func = info->func;
@@ -647,54 +674,36 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
 	}
     }
 
-    result = FALSE;
-    
     if (func)
     {
-	pixman_region32_t region;
-	pixman_region32_init (&region);
-
-	if (pixman_compute_composite_region32 (
-	        &region, src, mask, dest,
-	        src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
-	{
-	    pixman_box32_t *extents = pixman_region32_extents (&region);
-
-	    if (sources_cover (
-		    src, mask, extents,
-		    src_x, src_y, mask_x, mask_y, dest_x, dest_y))
-	    {
-		pixman_bool_t src_repeat, mask_repeat;
-
-		src_repeat =
-		    src->type == BITS					&&
-		    src_flags & FAST_PATH_ID_TRANSFORM			&&
-		    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-		    src_format != PIXMAN_solid;
-		
-		mask_repeat =
-		    mask						&&
-		    mask->type == BITS					&&
-		    mask_flags & FAST_PATH_ID_TRANSFORM			&&
-		    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
-		    mask_format != PIXMAN_solid;
-		
-		walk_region_internal (imp, op,
-		                      src, mask, dest,
-		                      src_x, src_y, mask_x, mask_y,
-		                      dest_x, dest_y,
-		                      width, height,
-		                      src_repeat, mask_repeat,
-		                      &region,
-		                      func);
-
-		result = TRUE;
-	    }
-
-	    pixman_region32_fini (&region);
-	}
+	pixman_bool_t src_repeat, mask_repeat;
+	
+	src_repeat =
+	    src->type == BITS					&&
+	    src_flags & FAST_PATH_ID_TRANSFORM			&&
+	    src->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	    src_format != PIXMAN_solid;
+	
+	mask_repeat =
+	    mask						&&
+	    mask->type == BITS					&&
+	    mask_flags & FAST_PATH_ID_TRANSFORM			&&
+	    mask->common.repeat == PIXMAN_REPEAT_NORMAL		&&
+	    mask_format != PIXMAN_solid;
+	
+	walk_region_internal (imp, op,
+			      src, mask, dest,
+			      src_x, src_y, mask_x, mask_y,
+			      dest_x, dest_y,
+			      width, height,
+			      src_repeat, mask_repeat,
+			      &region,
+			      func);
+	
+	result = TRUE;
     }
 
+    pixman_region32_fini (&region);
     return result;
 }
 


More information about the xorg-commit mailing list