pixman: Branch 'master' - 15 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Tue Jan 18 09:45:45 PST 2011


 pixman/pixman-arm-common.h       |    9 -
 pixman/pixman-bits-image.c       |  230 ++++++++++++++++++++++++++-----
 pixman/pixman-conical-gradient.c |   45 ++++--
 pixman/pixman-fast-path.c        |   22 +-
 pixman/pixman-general.c          |  288 +++++++++++++++++++--------------------
 pixman/pixman-image.c            |   92 +-----------
 pixman/pixman-implementation.c   |   81 ++++++++++
 pixman/pixman-linear-gradient.c  |   86 +++++++----
 pixman/pixman-mmx.c              |   22 +-
 pixman/pixman-private.h          |  169 ++++++++++++++--------
 pixman/pixman-radial-gradient.c  |   44 ++++-
 pixman/pixman-solid-fill.c       |   75 +++-------
 pixman/pixman-sse2.c             |   30 ++--
 pixman/pixman-utils.c            |    6 
 test/alphamap.c                  |   11 -
 15 files changed, 739 insertions(+), 471 deletions(-)

New commits:
commit 7f4eabbeec92e55fd8f812c0e5d8568eacbb633d
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Dec 12 07:34:42 2010 -0500

    Fix destination fetching
    
    When fetching from destinations, we need to ignore transformations,
    repeat and filtering. Currently we don't ignore them, which means all
    kinds of bad things can happen.
    
    This bug fixes this problem by directly calling the scanline fetchers
    for destinations instead of going through the full
    get_scanline_32/64().

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 8cabfdc..98a2b6d 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1377,8 +1377,22 @@ _pixman_bits_image_src_iter_init (pixman_image_t *image,
 static uint32_t *
 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->bits.get_scanline_32 (
-	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+    pixman_image_t *image  = iter->image;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    uint32_t *	    buffer = iter->buffer;
+
+    image->bits.fetch_scanline_32 (image, x, y, width, buffer, mask);
+    if (image->common.alpha_map)
+    {
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
+
+	image->common.alpha_map->fetch_scanline_32 (
+	    (pixman_image_t *)image->common.alpha_map,
+	    x, y, width, buffer, mask);
+    }
 
     return iter->buffer;
 }
@@ -1386,8 +1400,22 @@ dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 static uint32_t *
 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->bits.get_scanline_64 (
-	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+    bits_image_t *  image  = &iter->image->bits;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    uint32_t *	    buffer = iter->buffer;
+
+    image->fetch_scanline_64 (
+	(pixman_image_t *)image, x, y, width, buffer, mask);
+    if (image->common.alpha_map)
+    {
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
+
+	image->common.alpha_map->fetch_scanline_64 (
+	    (pixman_image_t *)image->common.alpha_map, x, y, width, buffer, mask);
+    }
 
     return iter->buffer;
 }
commit 9489c2e04a5361fe19a89a0da9d7be28436c0a4b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sun Dec 12 09:19:13 2010 -0500

    Turn on testing for destination transformation

diff --git a/test/alphamap.c b/test/alphamap.c
index 9fb8969..554b309 100644
--- a/test/alphamap.c
+++ b/test/alphamap.c
@@ -165,20 +165,17 @@ run_test (int s, int d, int sa, int da, int soff, int doff)
     orig_dst = create_image (df, daf, doff, doff);
     dst = create_image (df, daf, doff, doff);
 
-    /* Transformations on destinations should be ignored, so just set some
-     * random one.
+    /* Transformations, repeats and filters on destinations should be ignored,
+     * so just set some random ones.
      */
     pixman_transform_init_identity (&t1);
     pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
     pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
     pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
 
-#if 0
-    /* Unfortunately, this is actually broken at the moment, so we can't
-     * actually turn it on
-     */
     pixman_image_set_transform (dst, &t1);
-#endif
+    pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
+    pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
 
     pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
 			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
commit fffeda703e40ced90ec5ad6d6cd37a44294d3fe4
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Sat Dec 11 08:10:04 2010 -0500

    Skip fetching pixels when possible
    
    Add two new iterator flags, ITER_IGNORE_ALPHA and ITER_IGNORE_RGB that
    are set when the alpha and rgb values are not needed. If both are set,
    then we can skip fetching entirely and just use
    _pixman_iter_get_scanline_noop.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 8d4e4f5..8cabfdc 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1466,7 +1466,16 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image,
 	}
 	else
 	{
-	    iter->get_scanline = dest_get_scanline_narrow;
+	    if ((flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
+		(ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
+	    {
+		iter->get_scanline = _pixman_iter_get_scanline_noop;
+	    }
+	    else
+	    {
+		iter->get_scanline = dest_get_scanline_narrow;
+	    }
+
 	    iter->write_back = dest_write_back_narrow;
 	}
     }
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index e7a7283..16ea3a4 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -107,6 +107,34 @@ general_dest_iter_init (pixman_implementation_t *imp,
     }
 }
 
+typedef struct op_info_t op_info_t;
+struct op_info_t
+{
+    uint8_t src, dst;
+};
+
+#define ITER_IGNORE_BOTH						\
+    (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
+
+static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
+{
+    /* Src                   Dst                   */
+    { ITER_IGNORE_BOTH,      ITER_IGNORE_BOTH      }, /* CLEAR */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_BOTH      }, /* SRC */
+    { ITER_IGNORE_BOTH,      ITER_LOCALIZED_ALPHA  }, /* DST */
+    { 0,                     ITER_LOCALIZED_ALPHA  }, /* OVER */
+    { ITER_LOCALIZED_ALPHA,  0                     }, /* OVER_REVERSE */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* IN */
+    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* IN_REVERSE */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* OUT */
+    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* OUT_REVERSE */
+    { 0,                     0                     }, /* ATOP */
+    { 0,                     0                     }, /* ATOP_REVERSE */
+    { 0,                     0                     }, /* XOR */
+    { ITER_LOCALIZED_ALPHA,  ITER_LOCALIZED_ALPHA  }, /* ADD */
+    { 0,                     0                     }, /* SATURATE */
+};
+
 #define SCANLINE_BUFFER_LENGTH 8192
 
 static void
@@ -130,7 +158,7 @@ general_composite_rect  (pixman_implementation_t *imp,
     pixman_iter_t src_iter, mask_iter, dest_iter;
     pixman_combine_32_func_t compose;
     pixman_bool_t component_alpha;
-    iter_flags_t narrow, dest_flags;
+    iter_flags_t narrow, src_flags;
     int Bpp;
     int i;
 
@@ -159,39 +187,39 @@ general_composite_rect  (pixman_implementation_t *imp,
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
+    /* src iter */
+    src_flags = narrow | op_flags[op].src;
+
     _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
 					  src_x, src_y, width, height,
-					  src_buffer, narrow);
-
-    _pixman_implementation_src_iter_init (imp->toplevel, &mask_iter, mask,
-					  mask_x, mask_y, width, height,
-					  mask_buffer, narrow);
-
-    if (op == PIXMAN_OP_CLEAR		||
-	op == PIXMAN_OP_SRC		||
-	op == PIXMAN_OP_DST		||
-	op == PIXMAN_OP_OVER		||
-	op == PIXMAN_OP_IN_REVERSE	||
-	op == PIXMAN_OP_OUT_REVERSE	||
-	op == PIXMAN_OP_ADD)
-    {
-	dest_flags = narrow | ITER_LOCALIZED_ALPHA;
-    }
-    else
+					  src_buffer, src_flags);
+
+    /* mask iter */
+    if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
+	(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
     {
-	dest_flags = narrow;
+	/* If it doesn't matter what the source is, then it doesn't matter
+	 * what the mask is
+	 */
+	mask = NULL;
     }
 
-    _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
-					   dest_x, dest_y, width, height,
-					   dest_buffer, dest_flags);
-
     component_alpha =
         mask                            &&
         mask->common.type == BITS       &&
         mask->common.component_alpha    &&
         PIXMAN_FORMAT_RGB (mask->bits.format);
 
+    _pixman_implementation_src_iter_init (
+	imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height,
+	mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
+
+    /* dest iter */
+    _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
+					   dest_x, dest_y, width, height,
+					   dest_buffer,
+					   narrow | op_flags[op].dst);
+
     if (narrow)
     {
 	if (component_alpha)
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index e633432..adaf9c6 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -278,6 +278,11 @@ _pixman_implementation_src_iter_init (pixman_implementation_t	*imp,
     {
 	iter->get_scanline = get_scanline_null;
     }
+    else if ((flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
+	     (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
+    {
+	iter->get_scanline = _pixman_iter_get_scanline_noop;
+    }
     else
     {
 	(*imp->src_iter_init) (
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 0aeae2e..1662d2c 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -202,7 +202,9 @@ typedef enum
      * we can treat it as if it were ARGB, which means in some cases we can
      * avoid copying it to a temporary buffer.
      */
-    ITER_LOCALIZED_ALPHA =	(1 << 1)
+    ITER_LOCALIZED_ALPHA =	(1 << 1),
+    ITER_IGNORE_ALPHA =		(1 << 2),
+    ITER_IGNORE_RGB =		(1 << 3)
 } iter_flags_t;
 
 struct pixman_iter_t
commit 3e635d6491d883304662aff3c72558dc9065f1f1
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 16:55:55 2010 -0500

    Add direct-write optimization back
    
    Introduce a new ITER_LOCALIZED_ALPHA flag that indicates that the
    alpha value computed is used only for the alpha channel of the output;
    it doesn't affect the RGB channels.
    
    Then in pixman-bits-image.c, if a destination is either a8r8g8b8 or
    x8r8g8b8 with localized alpha, the iterator will return a pointer
    directly into the image.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 983e23c..8d4e4f5 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1438,6 +1438,12 @@ dest_write_back_wide (pixman_iter_t *iter)
     iter->y++;
 }
 
+static void
+dest_write_back_direct (pixman_iter_t *iter)
+{
+    iter->buffer += iter->image->bits.rowstride;
+}
+
 void
 _pixman_bits_image_dest_iter_init (pixman_image_t *image,
 				   pixman_iter_t *iter,
@@ -1446,8 +1452,23 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image,
 {
     if (flags & ITER_NARROW)
     {
-	iter->get_scanline = dest_get_scanline_narrow;
-	iter->write_back = dest_write_back_narrow;
+	if (((image->common.flags &
+	      (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) ==
+	     (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_NO_ACCESSORS)) &&
+	    (image->bits.format == PIXMAN_a8r8g8b8	||
+	     (image->bits.format == PIXMAN_x8r8g8b8	&&
+	      (flags & ITER_LOCALIZED_ALPHA))))
+	{
+	    iter->buffer = image->bits.bits + y * image->bits.rowstride + x;
+
+	    iter->get_scanline = _pixman_iter_get_scanline_noop;
+	    iter->write_back = dest_write_back_direct;
+	}
+	else
+	{
+	    iter->get_scanline = dest_get_scanline_narrow;
+	    iter->write_back = dest_write_back_narrow;
+	}
     }
     else
     {
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index e2f1dc3..e7a7283 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -130,7 +130,7 @@ general_composite_rect  (pixman_implementation_t *imp,
     pixman_iter_t src_iter, mask_iter, dest_iter;
     pixman_combine_32_func_t compose;
     pixman_bool_t component_alpha;
-    iter_flags_t narrow;
+    iter_flags_t narrow, dest_flags;
     int Bpp;
     int i;
 
@@ -167,9 +167,24 @@ general_composite_rect  (pixman_implementation_t *imp,
 					  mask_x, mask_y, width, height,
 					  mask_buffer, narrow);
 
+    if (op == PIXMAN_OP_CLEAR		||
+	op == PIXMAN_OP_SRC		||
+	op == PIXMAN_OP_DST		||
+	op == PIXMAN_OP_OVER		||
+	op == PIXMAN_OP_IN_REVERSE	||
+	op == PIXMAN_OP_OUT_REVERSE	||
+	op == PIXMAN_OP_ADD)
+    {
+	dest_flags = narrow | ITER_LOCALIZED_ALPHA;
+    }
+    else
+    {
+	dest_flags = narrow;
+    }
+
     _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
 					   dest_x, dest_y, width, height,
-					   dest_buffer, narrow);
+					   dest_buffer, dest_flags);
 
     component_alpha =
         mask                            &&
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index c3321e1..0aeae2e 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -185,7 +185,24 @@ union pixman_image
 typedef struct pixman_iter_t pixman_iter_t;
 typedef enum
 {
-    ITER_NARROW	= (1 << 0),
+    ITER_NARROW =		(1 << 0),
+
+    /* "Localized alpha" is when the alpha channel is used only to compute
+     * the alpha value of the destination. This means that the computation
+     * of the RGB values of the result is independent of the alpha value.
+     *
+     * For example, the OVER operator has localized alpha for the
+     * destination, because the RGB values of the result can be computed
+     * without knowing the destination alpha. Similarly, ADD has localized
+     * alpha for both source and destination because the RGB values of the
+     * result can be computed without knowing the alpha value of source or
+     * destination.
+     *
+     * When he destination is xRGB, this is useful knowledge, because then
+     * we can treat it as if it were ARGB, which means in some cases we can
+     * avoid copying it to a temporary buffer.
+     */
+    ITER_LOCALIZED_ALPHA =	(1 << 1)
 } iter_flags_t;
 
 struct pixman_iter_t
commit 0f1a5c4a27d34dcf4525dc38fcb48c14f653e828
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 15:18:48 2010 -0500

    Get rid of the classify methods
    
    They are not used anymore, and the linear gradient is now doing the
    optimization in a different way.

diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 1aa9de1..a72299b 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -72,7 +72,6 @@ _pixman_image_allocate (void)
 	common->alpha_map = NULL;
 	common->component_alpha = FALSE;
 	common->ref_count = 1;
-	common->classify = NULL;
 	common->property_changed = NULL;
 	common->client_clip = FALSE;
 	common->destroy_func = NULL;
@@ -83,19 +82,6 @@ _pixman_image_allocate (void)
     return image;
 }
 
-source_image_class_t
-_pixman_image_classify (pixman_image_t *image,
-                        int             x,
-                        int             y,
-                        int             width,
-                        int             height)
-{
-    if (image->common.classify)
-	return image->common.classify (image, x, y, width, height);
-    else
-	return SOURCE_IMAGE_CLASS_UNKNOWN;
-}
-
 static void
 image_property_changed (pixman_image_t *image)
 {
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 66d37ab..07303fc 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -31,21 +31,18 @@
 #include <stdlib.h>
 #include "pixman-private.h"
 
-static source_image_class_t
-linear_gradient_classify (pixman_image_t *image,
-                          int             x,
-                          int             y,
-                          int             width,
-                          int             height)
+static pixman_bool_t
+linear_gradient_is_horizontal (pixman_image_t *image,
+			       int             x,
+			       int             y,
+			       int             width,
+			       int             height)
 {
     linear_gradient_t *linear = (linear_gradient_t *)image;
     pixman_vector_t v;
     pixman_fixed_32_32_t l;
     pixman_fixed_48_16_t dx, dy;
     double inc;
-    source_image_class_t class;
-
-    class = SOURCE_IMAGE_CLASS_UNKNOWN;
 
     if (image->common.transform)
     {
@@ -54,7 +51,7 @@ linear_gradient_classify (pixman_image_t *image,
 	    image->common.transform->matrix[2][1] != 0 ||
 	    image->common.transform->matrix[2][2] == 0)
 	{
-	    return class;
+	    return FALSE;
 	}
 
 	v.vector[0] = image->common.transform->matrix[0][1];
@@ -74,7 +71,7 @@ linear_gradient_classify (pixman_image_t *image,
     l = dx * dx + dy * dy;
 
     if (l == 0)
-	return class;	
+	return FALSE;
 
     /*
      * compute how much the input of the gradient walked changes
@@ -86,9 +83,9 @@ linear_gradient_classify (pixman_image_t *image,
 
     /* check that casting to integer would result in 0 */
     if (-1 < inc && inc < 1)
-	class = SOURCE_IMAGE_CLASS_HORIZONTAL;
+	return TRUE;
 
-    return class;
+    return FALSE;
 }
 
 static uint32_t *
@@ -245,8 +242,7 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image,
 				   uint8_t        *buffer,
 				   iter_flags_t    flags)
 {
-    if (linear_gradient_classify (image, x, y, width, height) ==
-	SOURCE_IMAGE_CLASS_HORIZONTAL)
+    if (linear_gradient_is_horizontal (image, x, y, width, height))
     {
 	if (flags & ITER_NARROW)
 	    linear_get_scanline_narrow (iter, NULL);
@@ -290,7 +286,6 @@ pixman_image_create_linear_gradient (pixman_point_fixed_t *        p1,
     linear->p2 = *p2;
 
     image->type = LINEAR;
-    image->common.classify = linear_gradient_classify;
 
     return image;
 }
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index d7c7a62..c3321e1 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -60,17 +60,6 @@ typedef enum
     SOLID
 } image_type_t;
 
-typedef enum
-{
-    SOURCE_IMAGE_CLASS_UNKNOWN,
-    SOURCE_IMAGE_CLASS_HORIZONTAL,
-} source_image_class_t;
-
-typedef source_image_class_t (*classify_func_t) (pixman_image_t *image,
-						int             x,
-						int             y,
-						int             width,
-						int             height);
 typedef void (*property_changed_func_t) (pixman_image_t *image);
 
 struct image_common
@@ -95,7 +84,6 @@ struct image_common
     int                         alpha_origin_x;
     int                         alpha_origin_y;
     pixman_bool_t               component_alpha;
-    classify_func_t             classify;
     property_changed_func_t     property_changed;
 
     pixman_image_destroy_func_t destroy_func;
@@ -249,13 +237,6 @@ _pixman_conical_gradient_iter_init (pixman_image_t *image,
 				    int x, int y, int width, int height,
 				    uint8_t *buffer, iter_flags_t flags);
 
-source_image_class_t
-_pixman_image_classify (pixman_image_t *image,
-                        int             x,
-                        int             y,
-                        int             width,
-                        int             height);
-
 pixman_image_t *
 _pixman_image_allocate (void);
 
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index a431d74..67681f2 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -26,16 +26,6 @@
 #endif
 #include "pixman-private.h"
 
-static source_image_class_t
-solid_fill_classify (pixman_image_t *image,
-                     int             x,
-                     int             y,
-                     int             width,
-                     int             height)
-{
-    return SOURCE_IMAGE_CLASS_HORIZONTAL;
-}
-
 void
 _pixman_solid_fill_iter_init (pixman_image_t *image,
 			      pixman_iter_t  *iter,
@@ -97,8 +87,6 @@ pixman_image_create_solid_fill (pixman_color_t *color)
     img->solid.color_32 = color_to_uint32 (color);
     img->solid.color_64 = color_to_uint64 (color);
 
-    img->common.classify = solid_fill_classify;
-
     return img;
 }
 
commit b66cabb88488413c4787845c7da67901dc988ee6
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 15:14:24 2010 -0500

    Linear: Optimize for horizontal gradients
    
    If the gradient is horizontal, we can reuse the same scanline over and
    over. Add support for this optimization to
    _pixman_linear_gradient_iter_init().

diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index c657243..66d37ab 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -245,10 +245,23 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image,
 				   uint8_t        *buffer,
 				   iter_flags_t    flags)
 {
-    if (flags & ITER_NARROW)
-	iter->get_scanline = linear_get_scanline_narrow;
+    if (linear_gradient_classify (image, x, y, width, height) ==
+	SOURCE_IMAGE_CLASS_HORIZONTAL)
+    {
+	if (flags & ITER_NARROW)
+	    linear_get_scanline_narrow (iter, NULL);
+	else
+	    linear_get_scanline_wide (iter, NULL);
+
+	iter->get_scanline = _pixman_iter_get_scanline_noop;
+    }
     else
-	iter->get_scanline = linear_get_scanline_wide;
+    {
+	if (flags & ITER_NARROW)
+	    iter->get_scanline = linear_get_scanline_narrow;
+	else
+	    iter->get_scanline = linear_get_scanline_wide;
+    }
 }
 
 PIXMAN_EXPORT pixman_image_t *
commit cf14189c6993e42ae71977a4a4061417941ffee8
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 14:59:20 2010 -0500

    Consolidate the various get_scanline_32() into get_scanline_narrow()
    
    The separate get_scanline_32() functions in solid, linear, radial and
    conical images are no longer necessary because all access to these
    images now go through iterators.

diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index d43b454..9d7d2e8 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -50,14 +50,15 @@ coordinates_to_parameter (double x, double y, double angle)
 				      */
 }
 
-static void
-conical_gradient_get_scanline_32 (pixman_image_t *image,
-                                  int             x,
-                                  int             y,
-                                  int             width,
-                                  uint32_t *      buffer,
-                                  const uint32_t *mask)
+static uint32_t *
+conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
+    pixman_image_t *image = iter->image;
+    int x = iter->x;
+    int y = iter->y;
+    int width = iter->width;
+    uint32_t *buffer = iter->buffer;
+
     gradient_t *gradient = (gradient_t *)image;
     conical_gradient_t *conical = (conical_gradient_t *)image;
     uint32_t       *end = buffer + width;
@@ -82,7 +83,7 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
 	v.vector[2] = pixman_fixed_1;
 
 	if (!pixman_transform_point_3d (image->common.transform, &v))
-	    return;
+	    return iter->buffer;
 
 	cx = image->common.transform->matrix[0][0] / 65536.;
 	cy = image->common.transform->matrix[1][0] / 65536.;
@@ -154,14 +155,6 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
 	    rz += cz;
 	}
     }
-}
-
-static uint32_t *
-conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
-{
-    conical_gradient_get_scanline_32 (iter->image, iter->x, iter->y,
-				      iter->width, iter->buffer,
-				      mask);
 
     iter->y++;
     return iter->buffer;
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 4c0792c..c657243 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -91,14 +91,16 @@ linear_gradient_classify (pixman_image_t *image,
     return class;
 }
 
-static void
-linear_get_scanline_32 (pixman_image_t *image,
-			int             x,
-			int             y,
-			int             width,
-			uint32_t *      buffer,
-			const uint32_t *mask)
+static uint32_t *
+linear_get_scanline_narrow (pixman_iter_t  *iter,
+			    const uint32_t *mask)
 {
+    pixman_image_t *image  = iter->image;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    uint32_t *      buffer = iter->buffer;
+
     pixman_vector_t v, unit;
     pixman_fixed_32_32_t l;
     pixman_fixed_48_16_t dx, dy;
@@ -117,7 +119,7 @@ linear_get_scanline_32 (pixman_image_t *image,
     if (image->common.transform)
     {
 	if (!pixman_transform_point_3d (image->common.transform, &v))
-	    return;
+	    return iter->buffer;
 
 	unit.vector[0] = image->common.transform->matrix[0][0];
 	unit.vector[1] = image->common.transform->matrix[1][0];
@@ -217,19 +219,6 @@ linear_get_scanline_32 (pixman_image_t *image,
 	    v.vector[2] += unit.vector[2];
 	}
     }
-}
-
-static uint32_t *
-linear_get_scanline_narrow (pixman_iter_t  *iter,
-			    const uint32_t *mask)
-{
-    pixman_image_t *image  = iter->image;
-    int             x      = iter->x;
-    int             y      = iter->y;
-    int             width  = iter->width;
-    uint32_t *      buffer = iter->buffer;
-
-    linear_get_scanline_32 (image, x, y, width, buffer, mask);
 
     iter->y++;
 
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index d1017d2..6523b82 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -144,13 +144,8 @@ radial_compute_color (double                    a,
     return 0;
 }
 
-static void
-radial_gradient_get_scanline_32 (pixman_image_t *image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 uint32_t *      buffer,
-                                 const uint32_t *mask)
+static uint32_t *
+radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
     /*
      * Implementation of radial gradients following the PDF specification.
@@ -233,6 +228,11 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
      *   <=> for every p, the radiuses associated with the two t solutions
      *       have opposite sign
      */
+    pixman_image_t *image = iter->image;
+    int x = iter->x;
+    int y = iter->y;
+    int width = iter->width;
+    uint32_t *buffer = iter->buffer;
 
     gradient_t *gradient = (gradient_t *)image;
     radial_gradient_t *radial = (radial_gradient_t *)image;
@@ -250,7 +250,7 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
     if (image->common.transform)
     {
 	if (!pixman_transform_point_3d (image->common.transform, &v))
-	    return;
+	    return iter->buffer;
 	
 	unit.vector[0] = image->common.transform->matrix[0][0];
 	unit.vector[1] = image->common.transform->matrix[1][0];
@@ -384,14 +384,6 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
 	    v.vector[2] += unit.vector[2];
 	}
     }
-}
-
-static uint32_t *
-radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
-{
-    radial_gradient_get_scanline_32 (
-	iter->image, iter->x, iter->y, iter->width,
-	iter->buffer, mask);
 
     iter->y++;
     return iter->buffer;
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index 2531dbd..a431d74 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -26,39 +26,6 @@
 #endif
 #include "pixman-private.h"
 
-static void
-solid_fill_get_scanline_32 (pixman_image_t *image,
-                            int             x,
-                            int             y,
-                            int             width,
-                            uint32_t *      buffer,
-                            const uint32_t *mask)
-{
-    uint32_t *end = buffer + width;
-    uint32_t color = image->solid.color_32;
-
-    while (buffer < end)
-	*(buffer++) = color;
-
-    return;
-}
-
-static void
-solid_fill_get_scanline_64 (pixman_image_t *image,
-			    int             x,
-			    int             y,
-			    int             width,
-			    uint32_t *      buffer,
-			    const uint32_t *mask)
-{
-    uint64_t *b = (uint64_t *)buffer;
-    uint64_t *e = b + width;
-    uint64_t color = image->solid.color_64;
-
-    while (b < e)
-	*(b++) = color;
-}
-
 static source_image_class_t
 solid_fill_classify (pixman_image_t *image,
                      int             x,
@@ -77,13 +44,21 @@ _pixman_solid_fill_iter_init (pixman_image_t *image,
 {
     if (flags & ITER_NARROW)
     {
-	solid_fill_get_scanline_32 (
-	    image, x, y, width, (uint32_t *)buffer, NULL);
+	uint32_t *b = (uint32_t *)buffer;
+	uint32_t *e = b + width;
+	uint32_t color = image->solid.color_32;
+
+	while (b < e)
+	    *(b++) = color;
     }
     else
     {
-	solid_fill_get_scanline_64 (
-	    image, x, y, width, (uint32_t *)buffer, NULL);
+	uint64_t *b = (uint64_t *)buffer;
+	uint64_t *e = b + width;
+	uint64_t color = image->solid.color_64;
+
+	while (b < e)
+	    *(b++) = color;
     }
 
     iter->get_scanline = _pixman_iter_get_scanline_noop;
commit 0a6360a7ee0983dd52d368f5352d8c313fb0570b
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 14:44:22 2010 -0500

    Allow NULL property_changed function
    
    Initialize the field to NULL, and then delete the empty functions from
    the solid, linear, radial, and conical images.

diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index a00170b..d43b454 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -156,11 +156,6 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
     }
 }
 
-static void
-conical_gradient_property_changed (pixman_image_t *image)
-{
-}
-
 static uint32_t *
 conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
@@ -221,8 +216,6 @@ pixman_image_create_conical_gradient (pixman_point_fixed_t *        center,
     conical->center = *center;
     conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
 
-    image->common.property_changed = conical_gradient_property_changed;
-
     return image;
 }
 
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index e059286..1aa9de1 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -73,6 +73,7 @@ _pixman_image_allocate (void)
 	common->component_alpha = FALSE;
 	common->ref_count = 1;
 	common->classify = NULL;
+	common->property_changed = NULL;
 	common->client_clip = FALSE;
 	common->destroy_func = NULL;
 	common->destroy_data = NULL;
@@ -416,7 +417,8 @@ _pixman_image_validate (pixman_image_t *image)
 	 * property_changed() can make use of the flags
 	 * to set up accessors etc.
 	 */
-	image->common.property_changed (image);
+	if (image->common.property_changed)
+	    image->common.property_changed (image);
 
 	image->common.dirty = FALSE;
     }
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index a19d9a8..4c0792c 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -219,11 +219,6 @@ linear_get_scanline_32 (pixman_image_t *image,
     }
 }
 
-static void
-linear_gradient_property_changed (pixman_image_t *image)
-{
-}
-
 static uint32_t *
 linear_get_scanline_narrow (pixman_iter_t  *iter,
 			    const uint32_t *mask)
@@ -294,7 +289,6 @@ pixman_image_create_linear_gradient (pixman_point_fixed_t *        p1,
 
     image->type = LINEAR;
     image->common.classify = linear_gradient_classify;
-    image->common.property_changed = linear_gradient_property_changed;
 
     return image;
 }
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index 5121827..d1017d2 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -386,11 +386,6 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
     }
 }
 
-static void
-radial_gradient_property_changed (pixman_image_t *image)
-{
-}
-
 static uint32_t *
 radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
@@ -471,8 +466,6 @@ pixman_image_create_radial_gradient (pixman_point_fixed_t *        inner,
 
     radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius;
 
-    image->common.property_changed = radial_gradient_property_changed;
-
     return image;
 }
 
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index f2df3c7..2531dbd 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -69,11 +69,6 @@ solid_fill_classify (pixman_image_t *image,
     return SOURCE_IMAGE_CLASS_HORIZONTAL;
 }
 
-static void
-solid_fill_property_changed (pixman_image_t *image)
-{
-}
-
 void
 _pixman_solid_fill_iter_init (pixman_image_t *image,
 			      pixman_iter_t  *iter,
@@ -128,7 +123,6 @@ pixman_image_create_solid_fill (pixman_color_t *color)
     img->solid.color_64 = color_to_uint64 (color);
 
     img->common.classify = solid_fill_classify;
-    img->common.property_changed = solid_fill_property_changed;
 
     return img;
 }
commit 34b5633105e5e2838ac8deb32d26e3bbe73a3d1a
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 14:39:01 2010 -0500

    Move get_scanline_32/64 to the bits part of the image struct
    
    At this point these functions are basically a cache that the bits
    image uses for its fetchers, so they can be moved to the bits image.
    
    With the scanline getters only being initialized in the bits image,
    the _pixman_image_get_scanline_generic_64 can be moved to
    pixman-bits-image.c. That gets rid of the final user of
    _pixman_image_get_scanline_32/64, so these can be deleted.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index bf22dbf..983e23c 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -35,6 +35,43 @@
 #include "pixman-private.h"
 #include "pixman-combine32.h"
 
+/*
+ * By default, just evaluate the image at 32bpp and expand.  Individual image
+ * types can plug in a better scanline getter if they want to. For example
+ * we  could produce smoother gradients by evaluating them at higher color
+ * depth, but that's a project for the future.
+ */
+static void
+_pixman_image_get_scanline_generic_64 (pixman_image_t * image,
+                                       int              x,
+                                       int              y,
+                                       int              width,
+                                       uint32_t *       buffer,
+                                       const uint32_t * mask)
+{
+    uint32_t *mask8 = NULL;
+
+    /* Contract the mask image, if one exists, so that the 32-bit fetch
+     * function can use it.
+     */
+    if (mask)
+    {
+	mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
+	if (!mask8)
+	    return;
+
+	pixman_contract (mask8, (uint64_t *)mask, width);
+    }
+
+    /* Fetch the source image into the first half of buffer. */
+    image->bits.get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8);
+
+    /* Expand from 32bpp to 64bpp in place. */
+    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
+
+    free (mask8);
+}
+
 /* Fetch functions */
 
 static force_inline uint32_t
@@ -1298,8 +1335,8 @@ bits_image_property_changed (pixman_image_t *image)
 	if ((info->format == format || info->format == PIXMAN_any)	&&
 	    (info->flags & flags) == info->flags)
 	{
-	    image->common.get_scanline_32 = info->fetch_32;
-	    image->common.get_scanline_64 = info->fetch_64;
+	    image->bits.get_scanline_32 = info->fetch_32;
+	    image->bits.get_scanline_64 = info->fetch_64;
 	    break;
 	}
 
@@ -1310,7 +1347,7 @@ bits_image_property_changed (pixman_image_t *image)
 static uint32_t *
 src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->common.get_scanline_32 (
+    iter->image->bits.get_scanline_32 (
 	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
 
     return iter->buffer;
@@ -1319,7 +1356,7 @@ src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 static uint32_t *
 src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->common.get_scanline_64 (
+    iter->image->bits.get_scanline_64 (
 	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
 
     return iter->buffer;
@@ -1340,7 +1377,7 @@ _pixman_bits_image_src_iter_init (pixman_image_t *image,
 static uint32_t *
 dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->common.get_scanline_32 (
+    iter->image->bits.get_scanline_32 (
 	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
 
     return iter->buffer;
@@ -1349,7 +1386,7 @@ dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
 static uint32_t *
 dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 {
-    iter->image->common.get_scanline_64 (
+    iter->image->bits.get_scanline_64 (
 	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
 
     return iter->buffer;
diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index 35913cb..a00170b 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -159,8 +159,6 @@ conical_gradient_get_scanline_32 (pixman_image_t *image,
 static void
 conical_gradient_property_changed (pixman_image_t *image)
 {
-    image->common.get_scanline_32 = conical_gradient_get_scanline_32;
-    image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
 static uint32_t *
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index b487df0..e059286 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -50,43 +50,6 @@ _pixman_init_gradient (gradient_t *                  gradient,
     return TRUE;
 }
 
-/*
- * By default, just evaluate the image at 32bpp and expand.  Individual image
- * types can plug in a better scanline getter if they want to. For example
- * we  could produce smoother gradients by evaluating them at higher color
- * depth, but that's a project for the future.
- */
-void
-_pixman_image_get_scanline_generic_64 (pixman_image_t * image,
-                                       int              x,
-                                       int              y,
-                                       int              width,
-                                       uint32_t *       buffer,
-                                       const uint32_t * mask)
-{
-    uint32_t *mask8 = NULL;
-
-    /* Contract the mask image, if one exists, so that the 32-bit fetch
-     * function can use it.
-     */
-    if (mask)
-    {
-	mask8 = pixman_malloc_ab (width, sizeof(uint32_t));
-	if (!mask8)
-	    return;
-
-	pixman_contract (mask8, (uint64_t *)mask, width);
-    }
-
-    /* Fetch the source image into the first half of buffer. */
-    _pixman_image_get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8);
-
-    /* Expand from 32bpp to 64bpp in place. */
-    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width);
-
-    free (mask8);
-}
-
 pixman_image_t *
 _pixman_image_allocate (void)
 {
@@ -132,31 +95,6 @@ _pixman_image_classify (pixman_image_t *image,
 	return SOURCE_IMAGE_CLASS_UNKNOWN;
 }
 
-void
-_pixman_image_get_scanline_32 (pixman_image_t *image,
-                               int             x,
-                               int             y,
-                               int             width,
-                               uint32_t *      buffer,
-                               const uint32_t *mask)
-{
-    image->common.get_scanline_32 (image, x, y, width, buffer, mask);
-}
-
-/* Even thought the type of buffer is uint32_t *, the function actually expects
- * a uint64_t *buffer.
- */
-void
-_pixman_image_get_scanline_64 (pixman_image_t *image,
-                               int             x,
-                               int             y,
-                               int             width,
-                               uint32_t *      buffer,
-                               const uint32_t *unused)
-{
-    image->common.get_scanline_64 (image, x, y, width, buffer, unused);
-}
-
 static void
 image_property_changed (pixman_image_t *image)
 {
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 5de3cc8..a19d9a8 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -222,8 +222,6 @@ linear_get_scanline_32 (pixman_image_t *image,
 static void
 linear_gradient_property_changed (pixman_image_t *image)
 {
-    image->common.get_scanline_32 = linear_get_scanline_32;
-    image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
 static uint32_t *
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 9028c16..d7c7a62 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -97,8 +97,6 @@ struct image_common
     pixman_bool_t               component_alpha;
     classify_func_t             classify;
     property_changed_func_t     property_changed;
-    fetch_scanline_t            get_scanline_32;
-    fetch_scanline_t            get_scanline_64;
 
     pixman_image_destroy_func_t destroy_func;
     void *                      destroy_data;
@@ -168,6 +166,9 @@ struct bits_image
     uint32_t *                 free_me;
     int                        rowstride;  /* in number of uint32_t's */
 
+    fetch_scanline_t           get_scanline_32;
+    fetch_scanline_t           get_scanline_64;
+
     fetch_scanline_t           fetch_scanline_32;
     fetch_pixel_32_t	       fetch_pixel_32;
     store_scanline_t           store_scanline_32;
@@ -248,14 +249,6 @@ _pixman_conical_gradient_iter_init (pixman_image_t *image,
 				    int x, int y, int width, int height,
 				    uint8_t *buffer, iter_flags_t flags);
 
-void
-_pixman_image_get_scanline_generic_64  (pixman_image_t *image,
-                                        int             x,
-                                        int             y,
-                                        int             width,
-                                        uint32_t *      buffer,
-                                        const uint32_t *mask);
-
 source_image_class_t
 _pixman_image_classify (pixman_image_t *image,
                         int             x,
@@ -263,25 +256,6 @@ _pixman_image_classify (pixman_image_t *image,
                         int             width,
                         int             height);
 
-void
-_pixman_image_get_scanline_32 (pixman_image_t *image,
-                               int             x,
-                               int             y,
-                               int             width,
-                               uint32_t *      buffer,
-                               const uint32_t *mask);
-
-/* Even thought the type of buffer is uint32_t *, the function actually expects
- * a uint64_t *buffer.
- */
-void
-_pixman_image_get_scanline_64 (pixman_image_t *image,
-                               int             x,
-                               int             y,
-                               int             width,
-                               uint32_t *      buffer,
-                               const uint32_t *unused);
-
 pixman_image_t *
 _pixman_image_allocate (void);
 
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index 161055a..5121827 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -389,8 +389,6 @@ radial_gradient_get_scanline_32 (pixman_image_t *image,
 static void
 radial_gradient_property_changed (pixman_image_t *image)
 {
-    image->common.get_scanline_32 = radial_gradient_get_scanline_32;
-    image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
 static uint32_t *
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index 0af4df0..f2df3c7 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -72,8 +72,6 @@ solid_fill_classify (pixman_image_t *image,
 static void
 solid_fill_property_changed (pixman_image_t *image)
 {
-    image->common.get_scanline_32 = solid_fill_get_scanline_32;
-    image->common.get_scanline_64 = solid_fill_get_scanline_64;
 }
 
 void
commit d6b13f99b41eac535d961b89d4b53f616c910c1e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 10:53:02 2010 -0500

    Use an iterator in pixman_image_get_solid()
    
    This is a step towards getting rid of the
    _pixman_image_get_scanline_32/64() functions.

diff --git a/pixman/pixman-arm-common.h b/pixman/pixman-arm-common.h
index 66f448d..372e9f9 100644
--- a/pixman/pixman-arm-common.h
+++ b/pixman/pixman-arm-common.h
@@ -118,7 +118,8 @@ cputype##_composite_##name (pixman_implementation_t *imp,               \
     int32_t    dst_stride;                                              \
     uint32_t   src;                                                     \
                                                                         \
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);  \
+    src = _pixman_image_get_solid (					\
+	imp, src_image, dst_image->bits.format);			\
                                                                         \
     if ((flags & SKIP_ZERO_SRC) && src == 0)                            \
 	return;                                                         \
@@ -164,7 +165,8 @@ cputype##_composite_##name (pixman_implementation_t *imp,               \
     int32_t    dst_stride, mask_stride;                                 \
     uint32_t   src;                                                     \
                                                                         \
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);  \
+    src = _pixman_image_get_solid (					\
+	imp, src_image, dst_image->bits.format);			\
                                                                         \
     if ((flags & SKIP_ZERO_SRC) && src == 0)                            \
 	return;                                                         \
@@ -212,7 +214,8 @@ cputype##_composite_##name (pixman_implementation_t *imp,               \
     int32_t    dst_stride, src_stride;                                  \
     uint32_t   mask;                                                    \
                                                                         \
-    mask = _pixman_image_get_solid (mask_image, dst_image->bits.format);\
+    mask = _pixman_image_get_solid (					\
+	imp, mask_image, dst_image->bits.format);			\
                                                                         \
     if ((flags & SKIP_ZERO_MASK) && mask == 0)                          \
 	return;                                                         \
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index f103b4c..868175f 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -188,7 +188,7 @@ fast_composite_in_n_8_8 (pixman_implementation_t *imp,
     int32_t w;
     uint16_t t;
 
-    src = _pixman_image_get_solid (src_image, dest_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
 
     srca = src >> 24;
 
@@ -312,7 +312,7 @@ fast_composite_over_n_8_8888 (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -370,7 +370,7 @@ fast_composite_add_n_8888_8888_ca (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -427,7 +427,7 @@ fast_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -494,7 +494,7 @@ fast_composite_over_n_8_0888 (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -559,7 +559,7 @@ fast_composite_over_n_8_0565 (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -626,7 +626,7 @@ fast_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
     int dst_stride, mask_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -1034,7 +1034,7 @@ fast_composite_add_n_8_8 (pixman_implementation_t *imp,
 
     PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
     sa = (src >> 24);
 
     while (height--)
@@ -1146,7 +1146,7 @@ fast_composite_over_n_1_8888 (pixman_implementation_t *imp,
     if (width <= 0)
 	return;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
     srca = src >> 24;
     if (src == 0)
 	return;
@@ -1240,7 +1240,7 @@ fast_composite_over_n_1_0565 (pixman_implementation_t *imp,
     if (width <= 0)
 	return;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
     srca = src >> 24;
     if (src == 0)
 	return;
@@ -1332,7 +1332,7 @@ fast_composite_solid_fill (pixman_implementation_t *imp,
 {
     uint32_t src;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (dst_image->bits.format == PIXMAN_a1)
     {
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 28dc066..b487df0 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -795,12 +795,18 @@ pixman_image_get_format (pixman_image_t *image)
 }
 
 uint32_t
-_pixman_image_get_solid (pixman_image_t *     image,
-                         pixman_format_code_t format)
+_pixman_image_get_solid (pixman_implementation_t *imp,
+			 pixman_image_t *         image,
+                         pixman_format_code_t     format)
 {
     uint32_t result;
+    pixman_iter_t iter;
 
-    _pixman_image_get_scanline_32 (image, 0, 0, 1, &result, NULL);
+    _pixman_implementation_src_iter_init (
+	imp, &iter, image, 0, 0, 1, 1,
+	(uint8_t *)&result, ITER_NARROW);
+
+    result = *iter.get_scanline (&iter, NULL);
 
     /* If necessary, convert RGB <--> BGR. */
     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB)
diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c
index 34637a4..6daa364 100644
--- a/pixman/pixman-mmx.c
+++ b/pixman/pixman-mmx.c
@@ -1108,7 +1108,7 @@ mmx_composite_over_n_8888 (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -1187,7 +1187,7 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -1275,7 +1275,7 @@ mmx_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -1384,7 +1384,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
 
-    mask = _pixman_image_get_solid (mask_image, dst_image->bits.format);
+    mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format);
     mask &= 0xff000000;
     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
     vmask = load8888 (mask);
@@ -1469,7 +1469,7 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp,
 
     PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
-    mask = _pixman_image_get_solid (mask_image, dst_image->bits.format);
+    mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format);
 
     mask &= 0xff000000;
     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
@@ -1764,7 +1764,7 @@ mmx_composite_over_n_8_8888 (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -2038,7 +2038,7 @@ mmx_composite_src_n_8_8888 (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -2173,7 +2173,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -2532,7 +2532,7 @@ mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
 
     CHECKPOINT ();
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -2643,7 +2643,7 @@ mmx_composite_in_n_8_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     sa = src >> 24;
 
@@ -2790,7 +2790,7 @@ mmx_composite_add_n_8_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     sa = src >> 24;
 
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 158c41d..9028c16 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -295,10 +295,6 @@ _pixman_image_reset_clip_region (pixman_image_t *image);
 void
 _pixman_image_validate (pixman_image_t *image);
 
-uint32_t
-_pixman_image_get_solid (pixman_image_t *     image,
-                         pixman_format_code_t format);
-
 #define PIXMAN_IMAGE_GET_LINE(image, x, y, type, out_stride, line, mul)	\
     do									\
     {									\
@@ -473,6 +469,11 @@ struct pixman_implementation_t
     pixman_combine_64_func_t	combine_64_ca[PIXMAN_N_OPERATORS];
 };
 
+uint32_t
+_pixman_image_get_solid (pixman_implementation_t *imp,
+			 pixman_image_t *         image,
+                         pixman_format_code_t     format);
+
 pixman_implementation_t *
 _pixman_implementation_create (pixman_implementation_t *delegate,
 			       const pixman_fast_path_t *fast_paths);
diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c
index 94ba54c..3c0a42f 100644
--- a/pixman/pixman-sse2.c
+++ b/pixman/pixman-sse2.c
@@ -2598,7 +2598,7 @@ sse2_composite_over_n_8888 (pixman_implementation_t *imp,
     __m128i xmm_src, xmm_alpha;
     __m128i xmm_dst, xmm_dst_lo, xmm_dst_hi;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -2681,7 +2681,7 @@ sse2_composite_over_n_0565 (pixman_implementation_t *imp,
     __m128i xmm_src, xmm_alpha;
     __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -2776,7 +2776,7 @@ sse2_composite_add_n_8888_8888_ca (pixman_implementation_t *imp,
 
     __m64 mmx_src, mmx_alpha, mmx_mask, mmx_dest;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
     srca = src >> 24;
 
     if (src == 0)
@@ -2904,7 +2904,7 @@ sse2_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
 
     __m64 mmx_src, mmx_alpha, mmx_mask, mmx_dest;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -3036,7 +3036,7 @@ sse2_composite_over_8888_n_8888 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
 
-    mask = _pixman_image_get_solid (mask_image, PIXMAN_a8r8g8b8);
+    mask = _pixman_image_get_solid (imp, mask_image, PIXMAN_a8r8g8b8);
 
     xmm_mask = create_mask_16_128 (mask >> 24);
 
@@ -3226,7 +3226,7 @@ sse2_composite_over_x888_n_8888 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
 
-    mask = _pixman_image_get_solid (mask_image, PIXMAN_a8r8g8b8);
+    mask = _pixman_image_get_solid (imp, mask_image, PIXMAN_a8r8g8b8);
 
     xmm_mask = create_mask_16_128 (mask >> 24);
     xmm_alpha = mask_00ff;
@@ -3498,7 +3498,7 @@ sse2_composite_over_n_8_8888 (pixman_implementation_t *imp,
 
     __m64 mmx_src, mmx_alpha, mmx_mask, mmx_dest;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -3782,7 +3782,7 @@ sse2_composite_src_n_8_8888 (pixman_implementation_t *imp,
     __m128i xmm_src, xmm_def;
     __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -3918,7 +3918,7 @@ sse2_composite_over_n_8_0565 (pixman_implementation_t *imp,
     __m128i xmm_mask, xmm_mask_lo, xmm_mask_hi;
     __m128i xmm_dst, xmm_dst0, xmm_dst1, xmm_dst2, xmm_dst3;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     srca = src >> 24;
     if (src == 0)
@@ -4318,7 +4318,7 @@ sse2_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
 
     __m64 mmx_src, mmx_alpha, mmx_mask, mmx_dest;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
@@ -4471,7 +4471,7 @@ sse2_composite_in_n_8_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     sa = src >> 24;
 
@@ -4570,7 +4570,7 @@ sse2_composite_in_n_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     xmm_alpha = expand_alpha_1x128 (expand_pixel_32_1x128 (src));
 
@@ -4758,7 +4758,7 @@ sse2_composite_add_n_8_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     sa = src >> 24;
 
@@ -4855,7 +4855,7 @@ sse2_composite_add_n_8 (pixman_implementation_t *imp,
     PIXMAN_IMAGE_GET_LINE (
 	dst_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     src >>= 24;
 
@@ -5480,7 +5480,7 @@ sse2_composite_over_reverse_n_8888 (pixman_implementation_t *imp,
     int dst_stride;
     int32_t w;
 
-    src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+    src = _pixman_image_get_solid (imp, src_image, dst_image->bits.format);
 
     if (src == 0)
 	return;
commit 51a5e949f394560b057911d46aab768f8e07bd54
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 13:26:53 2010 -0500

    Virtualize iterator initialization
    
    Make src_iter_init() and dest_iter_init() virtual methods in the
    implementation struct. This allows individual implementations to plug
    in their own CPU specific scanline fetchers.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 4b837fa..e2f1dc3 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -39,18 +39,12 @@
 #include "pixman-combine32.h"
 #include "pixman-private.h"
 
-static uint32_t *
-src_get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
-{
-    return NULL;
-}
-
 static void
-src_iter_init (pixman_implementation_t *imp,
-	       pixman_iter_t *iter,
-	       pixman_image_t *image,
-	       int x, int y, int width, int height,
-	       uint8_t *buffer, iter_flags_t flags)
+general_src_iter_init (pixman_implementation_t *imp,
+		       pixman_iter_t *iter,
+		       pixman_image_t *image,
+		       int x, int y, int width, int height,
+		       uint8_t *buffer, iter_flags_t flags)
 {
     iter->image = image;
     iter->x = x;
@@ -58,11 +52,7 @@ src_iter_init (pixman_implementation_t *imp,
     iter->width = width;
     iter->buffer = (uint32_t *)buffer;
 
-    if (!image)
-    {
-	iter->get_scanline = src_get_scanline_null;
-    }
-    else if (image->type == SOLID)
+    if (image->type == SOLID)
     {
 	_pixman_solid_fill_iter_init (
 	    image, iter, x, y, width, height, buffer, flags);
@@ -94,11 +84,11 @@ src_iter_init (pixman_implementation_t *imp,
 }
 
 static void
-dest_iter_init (pixman_implementation_t *imp,
-		pixman_iter_t *iter,
-		pixman_image_t *image,
-		int x, int y, int width, int height,
-		uint8_t *buffer, iter_flags_t flags)
+general_dest_iter_init (pixman_implementation_t *imp,
+			pixman_iter_t *iter,
+			pixman_image_t *image,
+			int x, int y, int width, int height,
+			uint8_t *buffer, iter_flags_t flags)
 {
     iter->image = image;
     iter->x = x;
@@ -169,17 +159,17 @@ general_composite_rect  (pixman_implementation_t *imp,
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
-    src_iter_init (imp->toplevel, &src_iter, src,
-		   src_x, src_y, width, height,
-		   src_buffer, narrow);
+    _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
+					  src_x, src_y, width, height,
+					  src_buffer, narrow);
 
-    src_iter_init (imp->toplevel, &mask_iter, mask,
-		   mask_x, mask_y, width, height,
-		   mask_buffer, narrow);
+    _pixman_implementation_src_iter_init (imp->toplevel, &mask_iter, mask,
+					  mask_x, mask_y, width, height,
+					  mask_buffer, narrow);
 
-    dest_iter_init (imp->toplevel, &dest_iter, dest,
-		    dest_x, dest_y, width, height,
-		    dest_buffer, narrow);
+    _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
+					   dest_x, dest_y, width, height,
+					   dest_buffer, narrow);
 
     component_alpha =
         mask                            &&
@@ -272,6 +262,8 @@ _pixman_implementation_create_general (void)
 
     imp->blt = general_blt;
     imp->fill = general_fill;
+    imp->src_iter_init = general_src_iter_init;
+    imp->dest_iter_init = general_dest_iter_init;
 
     return imp;
 }
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index bc3749e..e633432 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -111,6 +111,36 @@ delegate_fill (pixman_implementation_t *imp,
 	imp->delegate, bits, stride, bpp, x, y, width, height, xor);
 }
 
+static void
+delegate_src_iter_init (pixman_implementation_t *imp,
+			pixman_iter_t *	         iter,
+			pixman_image_t *         image,
+			int                      x,
+			int                      y,
+			int                      width,
+			int                      height,
+			uint8_t *		 buffer,
+			iter_flags_t             flags)
+{
+    _pixman_implementation_src_iter_init (
+	imp->delegate, iter, image, x, y, width, height, buffer, flags);
+}
+
+static void
+delegate_dest_iter_init (pixman_implementation_t *imp,
+			 pixman_iter_t *	  iter,
+			 pixman_image_t *         image,
+			 int                      x,
+			 int                      y,
+			 int                      width,
+			 int                      height,
+			 uint8_t *		  buffer,
+			 iter_flags_t             flags)
+{
+    _pixman_implementation_dest_iter_init (
+	imp->delegate, iter, image, x, y, width, height, buffer, flags);
+}
+
 pixman_implementation_t *
 _pixman_implementation_create (pixman_implementation_t *delegate,
 			       const pixman_fast_path_t *fast_paths)
@@ -133,6 +163,8 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
      */
     imp->blt = delegate_blt;
     imp->fill = delegate_fill;
+    imp->src_iter_init = delegate_src_iter_init;
+    imp->dest_iter_init = delegate_dest_iter_init;
 
     for (i = 0; i < PIXMAN_N_OPERATORS; ++i)
     {
@@ -143,7 +175,7 @@ _pixman_implementation_create (pixman_implementation_t *delegate,
     }
 
     imp->fast_paths = fast_paths;
-    
+
     return imp;
 }
 
@@ -225,3 +257,45 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
     return (*imp->fill) (imp, bits, stride, bpp, x, y, width, height, xor);
 }
 
+static uint32_t *
+get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
+{
+    return NULL;
+}
+
+void
+_pixman_implementation_src_iter_init (pixman_implementation_t	*imp,
+				      pixman_iter_t             *iter,
+				      pixman_image_t		*image,
+				      int			 x,
+				      int			 y,
+				      int			 width,
+				      int			 height,
+				      uint8_t			*buffer,
+				      iter_flags_t		 flags)
+{
+    if (!image)
+    {
+	iter->get_scanline = get_scanline_null;
+    }
+    else
+    {
+	(*imp->src_iter_init) (
+	    imp, iter, image, x, y, width, height, buffer, flags);
+    }
+}
+
+void
+_pixman_implementation_dest_iter_init (pixman_implementation_t	*imp,
+				       pixman_iter_t            *iter,
+				       pixman_image_t		*image,
+				       int			 x,
+				       int			 y,
+				       int			 width,
+				       int			 height,
+				       uint8_t			*buffer,
+				       iter_flags_t		 flags)
+{
+    (*imp->dest_iter_init) (
+	imp, iter, image, x, y, width, height, buffer, flags);
+}
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index d42c114..158c41d 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -431,6 +431,15 @@ typedef pixman_bool_t (*pixman_fill_func_t) (pixman_implementation_t *imp,
 					     int                      width,
 					     int                      height,
 					     uint32_t                 xor);
+typedef void (*pixman_iter_init_func_t) (pixman_implementation_t *imp,
+                                         pixman_iter_t           *iter,
+                                         pixman_image_t          *image,
+                                         int                      x,
+                                         int                      y,
+                                         int                      width,
+                                         int                      height,
+                                         uint8_t                 *buffer,
+                                         iter_flags_t             flags);
 
 void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp);
 void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp);
@@ -452,9 +461,11 @@ struct pixman_implementation_t
     pixman_implementation_t *	toplevel;
     pixman_implementation_t *	delegate;
     const pixman_fast_path_t *	fast_paths;
-    
+
     pixman_blt_func_t		blt;
     pixman_fill_func_t		fill;
+    pixman_iter_init_func_t     src_iter_init;
+    pixman_iter_init_func_t     dest_iter_init;
 
     pixman_combine_32_func_t	combine_32[PIXMAN_N_OPERATORS];
     pixman_combine_32_func_t	combine_32_ca[PIXMAN_N_OPERATORS];
@@ -521,6 +532,28 @@ _pixman_implementation_fill (pixman_implementation_t *imp,
                              int                      height,
                              uint32_t                 xor);
 
+void
+_pixman_implementation_src_iter_init (pixman_implementation_t       *imp,
+				      pixman_iter_t                 *iter,
+				      pixman_image_t                *image,
+				      int                            x,
+				      int                            y,
+				      int                            width,
+				      int                            height,
+				      uint8_t                       *buffer,
+				      iter_flags_t                   flags);
+
+void
+_pixman_implementation_dest_iter_init (pixman_implementation_t       *imp,
+				       pixman_iter_t                 *iter,
+				       pixman_image_t                *image,
+				       int                            x,
+				       int                            y,
+				       int                            width,
+				       int                            height,
+				       uint8_t                       *buffer,
+				       iter_flags_t                   flags);
+
 /* Specific implementations */
 pixman_implementation_t *
 _pixman_implementation_create_general (void);
commit 6503c6edccbc6b08ea8efe398da3265126efa896
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 12:40:26 2010 -0500

    Move iterator initialization to the respective image files
    
    Instead of calling _pixman_image_get_scanline_32/64(), move the
    iterator initialization into the respecive image implementations and
    call the scanline generators directly.

diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c
index a3685d1..35913cb 100644
--- a/pixman/pixman-conical-gradient.c
+++ b/pixman/pixman-conical-gradient.c
@@ -163,6 +163,39 @@ conical_gradient_property_changed (pixman_image_t *image)
     image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
+static uint32_t *
+conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    conical_gradient_get_scanline_32 (iter->image, iter->x, iter->y,
+				      iter->width, iter->buffer,
+				      mask);
+
+    iter->y++;
+    return iter->buffer;
+}
+
+static uint32_t *
+conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
+
+    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+
+    return buffer;
+}
+
+void
+_pixman_conical_gradient_iter_init (pixman_image_t *image,
+				    pixman_iter_t *iter,
+				    int x, int y, int width, int height,
+				    uint8_t *buffer, iter_flags_t flags)
+{
+    if (flags & ITER_NARROW)
+	iter->get_scanline = conical_get_scanline_narrow;
+    else
+	iter->get_scanline = conical_get_scanline_wide;
+}
+
 PIXMAN_EXPORT pixman_image_t *
 pixman_image_create_conical_gradient (pixman_point_fixed_t *        center,
                                       pixman_fixed_t                angle,
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 3b7b59d..4b837fa 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -45,24 +45,6 @@ src_get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
     return NULL;
 }
 
-static uint32_t *
-src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
-{
-    _pixman_image_get_scanline_32 (
-	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
-
-    return iter->buffer;
-}
-
-static uint32_t *
-src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
-{
-    _pixman_image_get_scanline_64 (
-	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
-
-    return iter->buffer;
-}
-
 static void
 src_iter_init (pixman_implementation_t *imp,
 	       pixman_iter_t *iter,
@@ -80,18 +62,34 @@ src_iter_init (pixman_implementation_t *imp,
     {
 	iter->get_scanline = src_get_scanline_null;
     }
-    else if (image->type == BITS)
+    else if (image->type == SOLID)
     {
-	_pixman_bits_image_src_iter_init (
+	_pixman_solid_fill_iter_init (
 	    image, iter, x, y, width, height, buffer, flags);
     }
-    else if (flags & ITER_NARROW)
+    else if (image->type == LINEAR)
     {
-	iter->get_scanline = src_get_scanline_narrow;
+	_pixman_linear_gradient_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
+    }
+    else if (image->type == RADIAL)
+    {
+	_pixman_radial_gradient_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
+    }
+    else if (image->type == CONICAL)
+    {
+	_pixman_conical_gradient_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
+    }
+    else if (image->type == BITS)
+    {
+	_pixman_bits_image_src_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
     }
     else
     {
-	iter->get_scanline = src_get_scanline_wide;
+	_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
     }
 }
 
diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c
index 1547882..5de3cc8 100644
--- a/pixman/pixman-linear-gradient.c
+++ b/pixman/pixman-linear-gradient.c
@@ -92,12 +92,12 @@ linear_gradient_classify (pixman_image_t *image,
 }
 
 static void
-linear_gradient_get_scanline_32 (pixman_image_t *image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 uint32_t *      buffer,
-                                 const uint32_t *mask)
+linear_get_scanline_32 (pixman_image_t *image,
+			int             x,
+			int             y,
+			int             width,
+			uint32_t *      buffer,
+			const uint32_t *mask)
 {
     pixman_vector_t v, unit;
     pixman_fixed_32_32_t l;
@@ -222,10 +222,53 @@ linear_gradient_get_scanline_32 (pixman_image_t *image,
 static void
 linear_gradient_property_changed (pixman_image_t *image)
 {
-    image->common.get_scanline_32 = linear_gradient_get_scanline_32;
+    image->common.get_scanline_32 = linear_get_scanline_32;
     image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
+static uint32_t *
+linear_get_scanline_narrow (pixman_iter_t  *iter,
+			    const uint32_t *mask)
+{
+    pixman_image_t *image  = iter->image;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    uint32_t *      buffer = iter->buffer;
+
+    linear_get_scanline_32 (image, x, y, width, buffer, mask);
+
+    iter->y++;
+
+    return iter->buffer;
+}
+
+static uint32_t *
+linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
+
+    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+
+    return buffer;
+}
+
+void
+_pixman_linear_gradient_iter_init (pixman_image_t *image,
+				   pixman_iter_t  *iter,
+				   int             x,
+				   int             y,
+				   int             width,
+				   int             height,
+				   uint8_t        *buffer,
+				   iter_flags_t    flags)
+{
+    if (flags & ITER_NARROW)
+	iter->get_scanline = linear_get_scanline_narrow;
+    else
+	iter->get_scanline = linear_get_scanline_wide;
+}
+
 PIXMAN_EXPORT pixman_image_t *
 pixman_image_create_linear_gradient (pixman_point_fixed_t *        p1,
                                      pixman_point_fixed_t *        p2,
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index d9d19ce..d42c114 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -225,6 +225,30 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image,
 				   uint8_t *buffer, iter_flags_t flags);
 
 void
+_pixman_solid_fill_iter_init (pixman_image_t *image,
+			      pixman_iter_t  *iter,
+			      int x, int y, int width, int height,
+			      uint8_t *buffer, iter_flags_t flags);
+
+void
+_pixman_linear_gradient_iter_init (pixman_image_t *image,
+				   pixman_iter_t  *iter,
+				   int x, int y, int width, int height,
+				   uint8_t *buffer, iter_flags_t flags);
+
+void
+_pixman_radial_gradient_iter_init (pixman_image_t *image,
+				   pixman_iter_t *iter,
+				   int x, int y, int width, int height,
+				   uint8_t *buffer, iter_flags_t flags);
+
+void
+_pixman_conical_gradient_iter_init (pixman_image_t *image,
+				    pixman_iter_t *iter,
+				    int x, int y, int width, int height,
+				    uint8_t *buffer, iter_flags_t flags);
+
+void
 _pixman_image_get_scanline_generic_64  (pixman_image_t *image,
                                         int             x,
                                         int             y,
@@ -537,6 +561,8 @@ _pixman_choose_implementation (void);
 /*
  * Utilities
  */
+uint32_t *
+_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask);
 
 /* These "formats" all have depth 0, so they
  * will never clash with any real ones
diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c
index 7b92307..161055a 100644
--- a/pixman/pixman-radial-gradient.c
+++ b/pixman/pixman-radial-gradient.c
@@ -393,6 +393,39 @@ radial_gradient_property_changed (pixman_image_t *image)
     image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 }
 
+static uint32_t *
+radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    radial_gradient_get_scanline_32 (
+	iter->image, iter->x, iter->y, iter->width,
+	iter->buffer, mask);
+
+    iter->y++;
+    return iter->buffer;
+}
+
+static uint32_t *
+radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
+
+    pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
+
+    return buffer;
+}
+
+void
+_pixman_radial_gradient_iter_init (pixman_image_t *image,
+				   pixman_iter_t *iter,
+				   int x, int y, int width, int height,
+				   uint8_t *buffer, iter_flags_t flags)
+{
+    if (flags & ITER_NARROW)
+	iter->get_scanline = radial_get_scanline_narrow;
+    else
+	iter->get_scanline = radial_get_scanline_wide;
+}
+
 PIXMAN_EXPORT pixman_image_t *
 pixman_image_create_radial_gradient (pixman_point_fixed_t *        inner,
                                      pixman_point_fixed_t *        outer,
diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c
index 1d911e9..0af4df0 100644
--- a/pixman/pixman-solid-fill.c
+++ b/pixman/pixman-solid-fill.c
@@ -76,6 +76,26 @@ solid_fill_property_changed (pixman_image_t *image)
     image->common.get_scanline_64 = solid_fill_get_scanline_64;
 }
 
+void
+_pixman_solid_fill_iter_init (pixman_image_t *image,
+			      pixman_iter_t  *iter,
+			      int x, int y, int width, int height,
+			      uint8_t *buffer, iter_flags_t flags)
+{
+    if (flags & ITER_NARROW)
+    {
+	solid_fill_get_scanline_32 (
+	    image, x, y, width, (uint32_t *)buffer, NULL);
+    }
+    else
+    {
+	solid_fill_get_scanline_64 (
+	    image, x, y, width, (uint32_t *)buffer, NULL);
+    }
+
+    iter->get_scanline = _pixman_iter_get_scanline_noop;
+}
+
 static uint32_t
 color_to_uint32 (const pixman_color_t *color)
 {
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 3ef88b7..cb4e621 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -167,6 +167,12 @@ pixman_contract (uint32_t *      dst,
     }
 }
 
+uint32_t *
+_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
+{
+    return iter->buffer;
+}
+
 #define N_TMP_BOXES (16)
 
 pixman_bool_t
commit 23c6e1d2c007cc661b31e1bcdfd84604d7a9a560
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 12:31:29 2010 -0500

    Eliminate the _pixman_image_store_scanline_32/64 functions
    
    They were only called from next_line_write_narrow/wide, so they could
    simply be absorbed into those functions.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index bcada58..bf22dbf 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -35,45 +35,6 @@
 #include "pixman-private.h"
 #include "pixman-combine32.h"
 
-/* Store functions */
-void
-_pixman_image_store_scanline_32 (bits_image_t *  image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 const uint32_t *buffer)
-{
-    image->store_scanline_32 (image, x, y, width, buffer);
-
-    if (image->common.alpha_map)
-    {
-	x -= image->common.alpha_origin_x;
-	y -= image->common.alpha_origin_y;
-
-	image->common.alpha_map->store_scanline_32 (
-	    image->common.alpha_map, x, y, width, buffer);
-    }
-}
-
-void
-_pixman_image_store_scanline_64 (bits_image_t *  image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 const uint32_t *buffer)
-{
-    image->store_scanline_64 (image, x, y, width, buffer);
-
-    if (image->common.alpha_map)
-    {
-	x -= image->common.alpha_origin_x;
-	y -= image->common.alpha_origin_y;
-
-	image->common.alpha_map->store_scanline_64 (
-	    image->common.alpha_map, x, y, width, buffer);
-    }
-}
-
 /* Fetch functions */
 
 static force_inline uint32_t
@@ -1397,15 +1358,47 @@ dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
 static void
 dest_write_back_narrow (pixman_iter_t *iter)
 {
-    _pixman_image_store_scanline_32 (
-	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+    bits_image_t *  image  = &iter->image->bits;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    const uint32_t *buffer = iter->buffer;
+
+    image->store_scanline_32 (image, x, y, width, buffer);
+
+    if (image->common.alpha_map)
+    {
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
+
+	image->common.alpha_map->store_scanline_32 (
+	    image->common.alpha_map, x, y, width, buffer);
+    }
+
+    iter->y++;
 }
 
 static void
 dest_write_back_wide (pixman_iter_t *iter)
 {
-    _pixman_image_store_scanline_64 (
-	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+    bits_image_t *  image  = &iter->image->bits;
+    int             x      = iter->x;
+    int             y      = iter->y;
+    int             width  = iter->width;
+    const uint32_t *buffer = iter->buffer;
+
+    image->store_scanline_64 (image, x, y, width, buffer);
+
+    if (image->common.alpha_map)
+    {
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
+
+	image->common.alpha_map->store_scanline_64 (
+	    image->common.alpha_map, x, y, width, buffer);
+    }
+
+    iter->y++;
 }
 
 void
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 853fb5a..d9d19ce 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -258,23 +258,6 @@ _pixman_image_get_scanline_64 (pixman_image_t *image,
                                uint32_t *      buffer,
                                const uint32_t *unused);
 
-void
-_pixman_image_store_scanline_32 (bits_image_t *  image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 const uint32_t *buffer);
-
-/* Even though the type of buffer is uint32_t *, the function
- * actually expects a uint64_t *buffer.
- */
-void
-_pixman_image_store_scanline_64 (bits_image_t *  image,
-                                 int             x,
-                                 int             y,
-                                 int             width,
-                                 const uint32_t *buffer);
-
 pixman_image_t *
 _pixman_image_allocate (void);
 
commit b2c9eaa5020d08cfaac6c2296895e5a65c971ffd
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 12:19:50 2010 -0500

    Move initialization of iterators for bits images to pixman-bits-image.c
    
    pixman_iter_t is now defined in pixman-private.h, and iterators for
    bits images are being initialized in pixman-bits-image.c

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index c453e0e..bcada58 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1347,6 +1347,86 @@ bits_image_property_changed (pixman_image_t *image)
 }
 
 static uint32_t *
+src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    iter->image->common.get_scanline_32 (
+	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static uint32_t *
+src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    iter->image->common.get_scanline_64 (
+	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+void
+_pixman_bits_image_src_iter_init (pixman_image_t *image,
+				  pixman_iter_t *iter,
+				  int x, int y, int width, int height,
+				  uint8_t *buffer, iter_flags_t flags)
+{
+    if (flags & ITER_NARROW)
+	iter->get_scanline = src_get_scanline_narrow;
+    else
+	iter->get_scanline = src_get_scanline_wide;
+}
+
+static uint32_t *
+dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    iter->image->common.get_scanline_32 (
+	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static uint32_t *
+dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    iter->image->common.get_scanline_64 (
+	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static void
+dest_write_back_narrow (pixman_iter_t *iter)
+{
+    _pixman_image_store_scanline_32 (
+	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+}
+
+static void
+dest_write_back_wide (pixman_iter_t *iter)
+{
+    _pixman_image_store_scanline_64 (
+	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+}
+
+void
+_pixman_bits_image_dest_iter_init (pixman_image_t *image,
+				   pixman_iter_t *iter,
+				   int x, int y, int width, int height,
+				   uint8_t *buffer, iter_flags_t flags)
+{
+    if (flags & ITER_NARROW)
+    {
+	iter->get_scanline = dest_get_scanline_narrow;
+	iter->write_back = dest_write_back_narrow;
+    }
+    else
+    {
+	iter->get_scanline = dest_get_scanline_wide;
+	iter->write_back = dest_write_back_wide;
+    }
+}
+
+static uint32_t *
 create_bits (pixman_format_code_t format,
              int                  width,
              int                  height,
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index ea27e80..3b7b59d 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -39,23 +39,6 @@
 #include "pixman-combine32.h"
 #include "pixman-private.h"
 
-typedef struct pixman_iter_t pixman_iter_t;
-typedef enum
-{
-    ITER_NARROW	= (1 << 0)
-} iter_flags_t;
-
-struct pixman_iter_t
-{
-    uint32_t *(* get_scanline) (pixman_iter_t *iter, const uint32_t *mask);
-    void      (* write_back)   (pixman_iter_t *iter);
-
-    pixman_image_t *    image;
-    uint32_t *          buffer;
-    int                 x, y;
-    int                 width;
-};
-
 static uint32_t *
 src_get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
 {
@@ -94,43 +77,22 @@ src_iter_init (pixman_implementation_t *imp,
     iter->buffer = (uint32_t *)buffer;
 
     if (!image)
+    {
 	iter->get_scanline = src_get_scanline_null;
+    }
+    else if (image->type == BITS)
+    {
+	_pixman_bits_image_src_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
+    }
     else if (flags & ITER_NARROW)
+    {
 	iter->get_scanline = src_get_scanline_narrow;
+    }
     else
+    {
 	iter->get_scanline = src_get_scanline_wide;
-}
-
-static uint32_t *
-dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
-{
-    _pixman_image_get_scanline_32 (
-	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
-
-    return iter->buffer;
-}
-
-static uint32_t *
-dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
-{
-    _pixman_image_get_scanline_64 (
-	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
-
-    return iter->buffer;
-}
-
-static void
-write_back_narrow (pixman_iter_t *iter)
-{
-    _pixman_image_store_scanline_32 (
-	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
-}
-
-static void
-write_back_wide (pixman_iter_t *iter)
-{
-    _pixman_image_store_scanline_64 (
-	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+    }
 }
 
 static void
@@ -146,15 +108,14 @@ dest_iter_init (pixman_implementation_t *imp,
     iter->width = width;
     iter->buffer = (uint32_t *)buffer;
 
-    if (flags & ITER_NARROW)
+    if (image->type == BITS)
     {
-	iter->get_scanline = dest_get_scanline_narrow;
-	iter->write_back = write_back_narrow;
+	_pixman_bits_image_dest_iter_init (
+	    image, iter, x, y, width, height, buffer, flags);
     }
     else
     {
-	iter->get_scanline = dest_get_scanline_wide;
-	iter->write_back = write_back_wide;
+	_pixman_log_error (FUNC, "Trying to write to a non-writable image");
     }
 }
 
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 383748a..853fb5a 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -193,10 +193,38 @@ union pixman_image
     solid_fill_t       solid;
 };
 
+typedef struct pixman_iter_t pixman_iter_t;
+typedef enum
+{
+    ITER_NARROW	= (1 << 0),
+} iter_flags_t;
+
+struct pixman_iter_t
+{
+    uint32_t *(* get_scanline) (pixman_iter_t *iter, const uint32_t *mask);
+    void      (* write_back)   (pixman_iter_t *iter);
+
+    pixman_image_t *    image;
+    uint32_t *          buffer;
+    int                 x, y;
+    int                 width;
+};
+
 void
 _pixman_bits_image_setup_accessors (bits_image_t *image);
 
 void
+_pixman_bits_image_src_iter_init (pixman_image_t *image,
+				  pixman_iter_t *iter,
+				  int x, int y, int width, int height,
+				  uint8_t *buffer, iter_flags_t flags);
+void
+_pixman_bits_image_dest_iter_init (pixman_image_t *image,
+				   pixman_iter_t *iter,
+				   int x, int y, int width, int height,
+				   uint8_t *buffer, iter_flags_t flags);
+
+void
 _pixman_image_get_scanline_generic_64  (pixman_image_t *image,
                                         int             x,
                                         int             y,
commit 15b1645c7b96498788c9376e3bb7d8a5e7b4e584
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Dec 10 11:30:27 2010 -0500

    Add iterators in the general implementation
    
    We add a new structure called a pixman_iter_t that encapsulates the
    information required to read scanlines from an image. It contains two
    functions, get_scanline() and write_back(). The get_scanline()
    function will generate pixels for the current scanline. For iterators
    for source images, it will also advance to the next scanline. The
    write_back() function is only called for destination images. Its
    function is to write back the modified pixels to the image and then
    advance to the next scanline.
    
    When an iterator is initialized, it is passed this information:
    
       - The image to iterate
    
       - The rectangle to be iterated
    
       - A buffer that the iterator may (but is not required to) use. This
         buffer is guaranteed to have space for at least width pixels.
    
       - A flag indicating whether a8r8g8b8 or a16r16g16b16 pixels should
         be fetched
    
    There are a number of (eventual) benefits to the iterators:
    
       - The initialization of the iterator can be virtualized such that
         implementations can plug in their own CPU specific get_scanline()
         and write_back() functions.
    
       - If an image is horizontal, it can simply plug in an appropriate
         get_scanline(). This way we can get rid of the annoying
         classify() virtual function.
    
       - In general, iterators can remember what they did on the last
         scanline, so for example a REPEAT_NONE image might reuse the same
         data for all the empty scanlines generated by the zero-extension.
    
       - More detailed information can be passed to iterator, allowing
         more specialized fetchers to be used.
    
       - We can fix the bug where destination filters and transformations
         are not currently being ignored as they should be.
    
    However, this initial implementation is not optimized at all. We lose
    several existing optimizations:
    
       - The ability to composite directly in the destination
       - The ability to only fetch one scanline for horizontal images
       - The ability to avoid fetching the src and mask for the CLEAR
         operator
    
    Later patches will re-introduce these optimizations.

diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 8130f16..ea27e80 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -39,6 +39,125 @@
 #include "pixman-combine32.h"
 #include "pixman-private.h"
 
+typedef struct pixman_iter_t pixman_iter_t;
+typedef enum
+{
+    ITER_NARROW	= (1 << 0)
+} iter_flags_t;
+
+struct pixman_iter_t
+{
+    uint32_t *(* get_scanline) (pixman_iter_t *iter, const uint32_t *mask);
+    void      (* write_back)   (pixman_iter_t *iter);
+
+    pixman_image_t *    image;
+    uint32_t *          buffer;
+    int                 x, y;
+    int                 width;
+};
+
+static uint32_t *
+src_get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
+{
+    return NULL;
+}
+
+static uint32_t *
+src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    _pixman_image_get_scanline_32 (
+	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static uint32_t *
+src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    _pixman_image_get_scanline_64 (
+	iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static void
+src_iter_init (pixman_implementation_t *imp,
+	       pixman_iter_t *iter,
+	       pixman_image_t *image,
+	       int x, int y, int width, int height,
+	       uint8_t *buffer, iter_flags_t flags)
+{
+    iter->image = image;
+    iter->x = x;
+    iter->y = y;
+    iter->width = width;
+    iter->buffer = (uint32_t *)buffer;
+
+    if (!image)
+	iter->get_scanline = src_get_scanline_null;
+    else if (flags & ITER_NARROW)
+	iter->get_scanline = src_get_scanline_narrow;
+    else
+	iter->get_scanline = src_get_scanline_wide;
+}
+
+static uint32_t *
+dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
+{
+    _pixman_image_get_scanline_32 (
+	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static uint32_t *
+dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
+{
+    _pixman_image_get_scanline_64 (
+	iter->image, iter->x, iter->y, iter->width, iter->buffer, mask);
+
+    return iter->buffer;
+}
+
+static void
+write_back_narrow (pixman_iter_t *iter)
+{
+    _pixman_image_store_scanline_32 (
+	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+}
+
+static void
+write_back_wide (pixman_iter_t *iter)
+{
+    _pixman_image_store_scanline_64 (
+	&iter->image->bits, iter->x, iter->y++, iter->width, iter->buffer);
+}
+
+static void
+dest_iter_init (pixman_implementation_t *imp,
+		pixman_iter_t *iter,
+		pixman_image_t *image,
+		int x, int y, int width, int height,
+		uint8_t *buffer, iter_flags_t flags)
+{
+    iter->image = image;
+    iter->x = x;
+    iter->y = y;
+    iter->width = width;
+    iter->buffer = (uint32_t *)buffer;
+
+    if (flags & ITER_NARROW)
+    {
+	iter->get_scanline = dest_get_scanline_narrow;
+	iter->write_back = write_back_narrow;
+    }
+    else
+    {
+	iter->get_scanline = dest_get_scanline_wide;
+	iter->write_back = write_back_wide;
+    }
+}
+
 #define SCANLINE_BUFFER_LENGTH 8192
 
 static void
@@ -59,21 +178,25 @@ general_composite_rect  (pixman_implementation_t *imp,
     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
-    fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
+    pixman_iter_t src_iter, mask_iter, dest_iter;
     pixman_combine_32_func_t compose;
-    store_scanline_t store;
-    source_image_class_t src_class, mask_class;
     pixman_bool_t component_alpha;
-    uint32_t *bits;
-    int32_t stride;
-    int narrow, Bpp;
+    iter_flags_t narrow;
+    int Bpp;
     int i;
 
-    narrow =
-	(src->common.flags & FAST_PATH_NARROW_FORMAT)		&&
+    if ((src->common.flags & FAST_PATH_NARROW_FORMAT)		&&
 	(!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT)	&&
-	(dest->common.flags & FAST_PATH_NARROW_FORMAT);
-    Bpp = narrow ? 4 : 8;
+	(dest->common.flags & FAST_PATH_NARROW_FORMAT))
+    {
+	narrow = ITER_NARROW;
+	Bpp = 4;
+    }
+    else
+    {
+	narrow = 0;
+	Bpp = 8;
+    }
 
     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
     {
@@ -87,85 +210,19 @@ general_composite_rect  (pixman_implementation_t *imp,
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
-    src_class = _pixman_image_classify (src,
-                                        src_x, src_y,
-                                        width, height);
-
-    mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
-
-    if (mask)
-    {
-	mask_class = _pixman_image_classify (mask,
-	                                     src_x, src_y,
-	                                     width, height);
-    }
-
-    if (op == PIXMAN_OP_CLEAR)
-	fetch_src = NULL;
-    else if (narrow)
-	fetch_src = _pixman_image_get_scanline_32;
-    else
-	fetch_src = _pixman_image_get_scanline_64;
+    src_iter_init (imp->toplevel, &src_iter, src,
+		   src_x, src_y, width, height,
+		   src_buffer, narrow);
 
-    if (!mask || op == PIXMAN_OP_CLEAR)
-	fetch_mask = NULL;
-    else if (narrow)
-	fetch_mask = _pixman_image_get_scanline_32;
-    else
-	fetch_mask = _pixman_image_get_scanline_64;
+    src_iter_init (imp->toplevel, &mask_iter, mask,
+		   mask_x, mask_y, width, height,
+		   mask_buffer, narrow);
 
-    if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
-	fetch_dest = NULL;
-    else if (narrow)
-	fetch_dest = _pixman_image_get_scanline_32;
-    else
-	fetch_dest = _pixman_image_get_scanline_64;
-
-    if (narrow)
-	store = _pixman_image_store_scanline_32;
-    else
-	store = _pixman_image_store_scanline_64;
-
-    /* Skip the store step and composite directly into the
-     * destination if the output format of the compose func matches
-     * the destination format.
-     *
-     * If the destination format is a8r8g8b8 then we can always do
-     * this. If it is x8r8g8b8, then we can only do it if the
-     * operator doesn't make use of destination alpha.
-     */
-    if ((dest->bits.format == PIXMAN_a8r8g8b8)	||
-	(dest->bits.format == PIXMAN_x8r8g8b8	&&
-	 (op == PIXMAN_OP_OVER		||
-	  op == PIXMAN_OP_ADD		||
-	  op == PIXMAN_OP_SRC		||
-	  op == PIXMAN_OP_CLEAR		||
-	  op == PIXMAN_OP_IN_REVERSE	||
-	  op == PIXMAN_OP_OUT_REVERSE	||
-	  op == PIXMAN_OP_DST)))
-    {
-	if (narrow &&
-	    !dest->common.alpha_map &&
-	    !dest->bits.write_func)
-	{
-	    store = NULL;
-	}
-    }
-
-    if (!store)
-    {
-	bits = dest->bits.bits;
-	stride = dest->bits.rowstride;
-    }
-    else
-    {
-	bits = NULL;
-	stride = 0;
-    }
+    dest_iter_init (imp->toplevel, &dest_iter, dest,
+		    dest_x, dest_y, width, height,
+		    dest_buffer, narrow);
 
     component_alpha =
-        fetch_src                       &&
-        fetch_mask                      &&
         mask                            &&
         mask->common.type == BITS       &&
         mask->common.component_alpha    &&
@@ -189,70 +246,17 @@ general_composite_rect  (pixman_implementation_t *imp,
     if (!compose)
 	return;
 
-    if (!fetch_mask)
-	mask_buffer = NULL;
-
     for (i = 0; i < height; ++i)
     {
-	/* fill first half of scanline with source */
-	if (fetch_src)
-	{
-	    if (fetch_mask)
-	    {
-		/* fetch mask before source so that fetching of
-		   source can be optimized */
-		fetch_mask (mask, mask_x, mask_y + i,
-		            width, (void *)mask_buffer, 0);
-
-		if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
-		    fetch_mask = NULL;
-	    }
-
-	    if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
-	    {
-		fetch_src (src, src_x, src_y + i,
-		           width, (void *)src_buffer, 0);
-		fetch_src = NULL;
-	    }
-	    else
-	    {
-		fetch_src (src, src_x, src_y + i,
-		           width, (void *)src_buffer, (void *)mask_buffer);
-	    }
-	}
-	else if (fetch_mask)
-	{
-	    fetch_mask (mask, mask_x, mask_y + i,
-	                width, (void *)mask_buffer, 0);
-	}
-
-	if (store)
-	{
-	    /* fill dest into second half of scanline */
-	    if (fetch_dest)
-	    {
-		fetch_dest (dest, dest_x, dest_y + i,
-		            width, (void *)dest_buffer, 0);
-	    }
-
-	    /* blend */
-	    compose (imp->toplevel, op,
-		     (void *)dest_buffer,
-		     (void *)src_buffer,
-		     (void *)mask_buffer,
-		     width);
-
-	    /* write back */
-	    store (&(dest->bits), dest_x, dest_y + i, width,
-	           (void *)dest_buffer);
-	}
-	else
-	{
-	    /* blend */
-	    compose (imp->toplevel, op,
-		     bits + (dest_y + i) * stride + dest_x,
-	             (void *)src_buffer, (void *)mask_buffer, width);
-	}
+	uint32_t *s, *m, *d;
+
+	m = mask_iter.get_scanline (&mask_iter, NULL);
+	s = src_iter.get_scanline (&src_iter, m);
+	d = dest_iter.get_scanline (&dest_iter, NULL);
+
+	compose (imp->toplevel, op, d, s, m, width);
+
+	dest_iter.write_back (&dest_iter);
     }
 
     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)


More information about the xorg-commit mailing list