pixman: Branch 'master' - 9 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Sun Aug 8 11:04:40 PDT 2010


 pixman/pixman-access.c     |   40 ++--
 pixman/pixman-bits-image.c |  401 +++++++++++++++++++++++++--------------------
 pixman/pixman-fast-path.c  |    9 -
 pixman/pixman-image.c      |   36 +++-
 pixman/pixman-private.h    |   51 +++--
 pixman/pixman.c            |  288 +++++++++++++++++++++++---------
 test/scaling-crash-test.c  |  193 +++++++++++++++------
 7 files changed, 655 insertions(+), 363 deletions(-)

New commits:
commit 41584f8fe140b7374a5ef5d437b070c1f32763bb
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 14:14:21 2010 -0400

    Store the various bits image fetchers in a table with formats and flags.
    
    Similarly to how the fast paths are done, put the various bits_image
    fetchers in a table, so that we can quickly find the best one based on
    the image's flags and format.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 7129e86..a32ebcc 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -906,62 +906,88 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image,
     }
 }
 
+typedef struct
+{
+    pixman_format_code_t	format;
+    uint32_t			flags;
+    fetch_scanline_t		fetch_32;
+    fetch_scanline_t		fetch_64;
+} fetcher_info_t;
+
+static const fetcher_info_t fetcher_info[] =
+{
+    { PIXMAN_solid,
+      FAST_PATH_NO_ALPHA_MAP,
+      bits_image_fetch_solid_32,
+      bits_image_fetch_solid_64
+    },
+
+    { PIXMAN_any,
+      (FAST_PATH_NO_ALPHA_MAP			|
+       FAST_PATH_ID_TRANSFORM			|
+       FAST_PATH_NO_CONVOLUTION_FILTER		|
+       FAST_PATH_NO_PAD_REPEAT			|
+       FAST_PATH_NO_REFLECT_REPEAT),
+      bits_image_fetch_untransformed_32,
+      bits_image_fetch_untransformed_64
+    },
+
+#define FAST_BILINEAR_FLAGS						\
+    (FAST_PATH_NO_ALPHA_MAP		|				\
+     FAST_PATH_NO_ACCESSORS		|				\
+     FAST_PATH_HAS_TRANSFORM		|				\
+     FAST_PATH_AFFINE_TRANSFORM		|				\
+     FAST_PATH_X_UNIT_POSITIVE		|				\
+     FAST_PATH_Y_UNIT_ZERO		|				\
+     FAST_PATH_NONE_REPEAT		|				\
+     FAST_PATH_BILINEAR_FILTER)
+
+    { PIXMAN_a8r8g8b8,
+      FAST_BILINEAR_FLAGS,
+      bits_image_fetch_bilinear_no_repeat_8888,
+      _pixman_image_get_scanline_generic_64
+    },
+
+    { PIXMAN_x8r8g8b8,
+      FAST_BILINEAR_FLAGS,
+      bits_image_fetch_bilinear_no_repeat_8888,
+      _pixman_image_get_scanline_generic_64
+    },
+
+    { PIXMAN_any,
+      (FAST_PATH_NO_ALPHA_MAP |
+       FAST_PATH_HAS_TRANSFORM |
+       FAST_PATH_AFFINE_TRANSFORM),
+      bits_image_fetch_affine_no_alpha,
+      _pixman_image_get_scanline_generic_64
+    },
+
+    { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
+
+    { PIXMAN_null },
+};
+
 static void
 bits_image_property_changed (pixman_image_t *image)
 {
-    bits_image_t *bits = (bits_image_t *)image;
+    uint32_t flags = image->common.flags;
+    pixman_format_code_t format = image->common.extended_format_code;
+    const fetcher_info_t *info;
 
-    _pixman_bits_image_setup_accessors (bits);
+    _pixman_bits_image_setup_accessors (&image->bits);
 
-    if (bits->common.alpha_map)
-    {
-	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 = bits_image_fetch_general;
-    }
-    else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
-             bits->width == 1 &&
-             bits->height == 1)
-    {
-	image->common.get_scanline_64 = bits_image_fetch_solid_64;
-	image->common.get_scanline_32 = bits_image_fetch_solid_32;
-    }
-    else if (!bits->common.transform &&
-             bits->common.filter != PIXMAN_FILTER_CONVOLUTION &&
-             (bits->common.repeat == PIXMAN_REPEAT_NONE ||
-              bits->common.repeat == PIXMAN_REPEAT_NORMAL))
-    {
-	image->common.get_scanline_64 = bits_image_fetch_untransformed_64;
-	image->common.get_scanline_32 = bits_image_fetch_untransformed_32;
-    }
-    else if (bits->common.transform					&&
-	     bits->common.transform->matrix[2][0] == 0			&&
-	     bits->common.transform->matrix[2][1] == 0			&&
-	     bits->common.transform->matrix[2][2] == pixman_fixed_1	&&
-	     bits->common.transform->matrix[0][0] > 0			&&
-	     bits->common.transform->matrix[1][0] == 0			&&
-	     !bits->read_func						&&
-	     (bits->common.filter == PIXMAN_FILTER_BILINEAR ||
-	      bits->common.filter == PIXMAN_FILTER_GOOD	    ||
-	      bits->common.filter == PIXMAN_FILTER_BEST)		&&
-	     bits->common.repeat == PIXMAN_REPEAT_NONE			&&
-	     (bits->format == PIXMAN_a8r8g8b8	||
-	      bits->format == PIXMAN_x8r8g8b8))
-    {
-	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 = bits_image_fetch_bilinear_no_repeat_8888;
-    }
-    else if (bits->common.transform					&&
-	     bits->common.transform->matrix[2][0] == 0			&&
-	     bits->common.transform->matrix[2][1] == 0			&&
-	     bits->common.transform->matrix[2][2] == pixman_fixed_1)
+    info = fetcher_info;
+    while (info->format != PIXMAN_null)
     {
-	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 = bits_image_fetch_affine_no_alpha;
-    }
-    else
-    {
-	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 = bits_image_fetch_general;
+	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;
+	    break;
+	}
+
+	info++;
     }
 }
 
commit 8e33643f44c397a37b822a95e071880d9a8e792a
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 12:53:56 2010 -0400

    Add some new FAST_PATH flags
    
    The flags are:
    
     *  AFFINE_TRANSFORM, for affine transforms
    
     *  Y_UNIT_ZERO, for when the 10 entry in the transformation is zero
    
     *  FILTER_BILINEAR, for when the image has a bilinear filter
    
     *  NO_NORMAL_REPEAT, for when the repeat mode is not NORMAL
    
     *  HAS_TRANSFORM, for when the transform is not NULL
    
    Also add some new FAST_PATH_REPEAT_* macros. These are just shorthands
    for the image not having any of the other repeat modes. For example
    REPEAT_NORMAL is (NO_NONE | NO_PAD | NO_REFLECT).

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index d27256d..7129e86 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -954,7 +954,6 @@ bits_image_property_changed (pixman_image_t *image)
 	     bits->common.transform->matrix[2][0] == 0			&&
 	     bits->common.transform->matrix[2][1] == 0			&&
 	     bits->common.transform->matrix[2][2] == pixman_fixed_1)
-	     
     {
 	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 	image->common.get_scanline_32 = bits_image_fetch_affine_no_alpha;
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 7858a6d..097f3b1 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -1873,15 +1873,12 @@ static const pixman_fast_path_t c_fast_paths[] =
      FAST_PATH_NO_ACCESSORS	|					\
      FAST_PATH_NO_WIDE_FORMAT)
 
-#define HAS_NORMAL_REPEAT_FLAGS						\
-    (FAST_PATH_NO_REFLECT_REPEAT |					\
-     FAST_PATH_NO_PAD_REPEAT     |					\
-     FAST_PATH_NO_NONE_REPEAT)
-
 #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func)				\
     {   PIXMAN_OP_ ## op,						\
 	PIXMAN_ ## s,							\
-	SCALED_NEAREST_FLAGS | HAS_NORMAL_REPEAT_FLAGS | FAST_PATH_X_UNIT_POSITIVE, \
+	(SCALED_NEAREST_FLAGS		|				\
+	 FAST_PATH_NORMAL_REPEAT	|				\
+	 FAST_PATH_X_UNIT_POSITIVE),					\
 	PIXMAN_null, 0,							\
 	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				\
 	fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op,	\
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 5c6d415..269c3c1 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -297,21 +297,33 @@ compute_image_info (pixman_image_t *image)
     /* Transform */
     if (!image->common.transform)
     {
-	flags |= (FAST_PATH_ID_TRANSFORM | FAST_PATH_X_UNIT_POSITIVE);
+	flags |= (FAST_PATH_ID_TRANSFORM	|
+		  FAST_PATH_X_UNIT_POSITIVE	|
+		  FAST_PATH_Y_UNIT_ZERO		|
+		  FAST_PATH_AFFINE_TRANSFORM);
     }
     else
     {
-	if (image->common.transform->matrix[0][1] == 0 &&
-	    image->common.transform->matrix[1][0] == 0 &&
-	    image->common.transform->matrix[2][0] == 0 &&
-	    image->common.transform->matrix[2][1] == 0 &&
+	flags |= FAST_PATH_HAS_TRANSFORM;
+
+	if (image->common.transform->matrix[2][0] == 0			&&
+	    image->common.transform->matrix[2][1] == 0			&&
 	    image->common.transform->matrix[2][2] == pixman_fixed_1)
 	{
-	    flags |= FAST_PATH_SCALE_TRANSFORM;
+	    flags |= FAST_PATH_AFFINE_TRANSFORM;
+
+	    if (image->common.transform->matrix[0][1] == 0 &&
+		image->common.transform->matrix[1][0] == 0)
+	    {
+		flags |= FAST_PATH_SCALE_TRANSFORM;
+	    }
 	}
 
 	if (image->common.transform->matrix[0][0] > 0)
 	    flags |= FAST_PATH_X_UNIT_POSITIVE;
+
+	if (image->common.transform->matrix[1][0] == 0)
+	    flags |= FAST_PATH_Y_UNIT_ZERO;
     }
 
     /* Alpha map */
@@ -326,6 +338,12 @@ compute_image_info (pixman_image_t *image)
 	flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
 	break;
 
+    case PIXMAN_FILTER_BILINEAR:
+    case PIXMAN_FILTER_GOOD:
+    case PIXMAN_FILTER_BEST:
+	flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+	break;
+
     case PIXMAN_FILTER_CONVOLUTION:
 	break;
 
@@ -338,15 +356,15 @@ compute_image_info (pixman_image_t *image)
     switch (image->common.repeat)
     {
     case PIXMAN_REPEAT_NONE:
-	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT;
+	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
 	break;
 
     case PIXMAN_REPEAT_REFLECT:
-	flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT;
+	flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
 	break;
 
     case PIXMAN_REPEAT_PAD:
-	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT;
+	flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
 	break;
 
     default:
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index a2736d7..0629c42 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -565,6 +565,31 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_NO_NONE_REPEAT		(1 << 15)
 #define FAST_PATH_SAMPLES_COVER_CLIP		(1 << 16)
 #define FAST_PATH_X_UNIT_POSITIVE		(1 << 17)
+#define FAST_PATH_AFFINE_TRANSFORM		(1 << 18)
+#define FAST_PATH_Y_UNIT_ZERO			(1 << 19)
+#define FAST_PATH_BILINEAR_FILTER		(1 << 20)
+#define FAST_PATH_NO_NORMAL_REPEAT		(1 << 21)
+#define FAST_PATH_HAS_TRANSFORM			(1 << 22)
+
+#define FAST_PATH_PAD_REPEAT						\
+    (FAST_PATH_NO_NONE_REPEAT		|				\
+     FAST_PATH_NO_NORMAL_REPEAT		|				\
+     FAST_PATH_NO_REFLECT_REPEAT)
+
+#define FAST_PATH_NORMAL_REPEAT						\
+    (FAST_PATH_NO_NONE_REPEAT		|				\
+     FAST_PATH_NO_PAD_REPEAT		|				\
+     FAST_PATH_NO_REFLECT_REPEAT)
+
+#define FAST_PATH_NONE_REPEAT						\
+    (FAST_PATH_NO_NORMAL_REPEAT		|				\
+     FAST_PATH_NO_PAD_REPEAT		|				\
+     FAST_PATH_NO_REFLECT_REPEAT)
+
+#define FAST_PATH_REFLECT_REPEAT					\
+    (FAST_PATH_NO_NONE_REPEAT		|				\
+     FAST_PATH_NO_NORMAL_REPEAT		|				\
+     FAST_PATH_NO_PAD_REPEAT)
 
 #define _FAST_PATH_STANDARD_FLAGS					\
     (FAST_PATH_ID_TRANSFORM		|				\
commit 6f62231d1580f5b67f36ec81b6c59a7e2f4978cb
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 12:45:44 2010 -0400

    Remove "_raw_" from all the accessors.
    
    There are no non-raw accessors anymore.

diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index a511e4c..56de711 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -2732,7 +2732,7 @@ store_scanline_generic_64 (bits_image_t *  image,
      */
     pixman_contract (argb8_pixels, (uint64_t *)values, width);
     
-    image->store_scanline_raw_32 (image, x, y, width, argb8_pixels);
+    image->store_scanline_32 (image, x, y, width, argb8_pixels);
     
     free (argb8_pixels);
 }
@@ -2753,7 +2753,7 @@ fetch_scanline_generic_64 (pixman_image_t *image,
     /* Fetch the pixels into the first half of buffer and then expand them in
      * place.
      */
-    image->bits.fetch_scanline_raw_32 (image, x, y, width, buffer, NULL);
+    image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
 
     format = image->bits.format;
     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR	||
@@ -2776,7 +2776,7 @@ fetch_pixel_generic_64 (bits_image_t *image,
 			int	      offset,
 			int           line)
 {
-    uint32_t pixel32 = image->fetch_pixel_raw_32 (image, offset, line);
+    uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
     uint64_t result;
     pixman_format_code_t format;
 
@@ -2808,7 +2808,7 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image,
 			      int           offset,
 			      int           line)
 {
-    uint64_t pixel64 = image->fetch_pixel_raw_64 (image, offset, line);
+    uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line);
     uint32_t result;
     
     pixman_contract (&result, &pixel64, 1);
@@ -2819,12 +2819,12 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image,
 typedef struct
 {
     pixman_format_code_t	format;
-    fetch_scanline_t		fetch_scanline_raw_32;
-    fetch_scanline_t		fetch_scanline_raw_64;
-    fetch_pixel_32_t		fetch_pixel_raw_32;
-    fetch_pixel_64_t		fetch_pixel_raw_64;
-    store_scanline_t		store_scanline_raw_32;
-    store_scanline_t		store_scanline_raw_64;
+    fetch_scanline_t		fetch_scanline_32;
+    fetch_scanline_t		fetch_scanline_64;
+    fetch_pixel_32_t		fetch_pixel_32;
+    fetch_pixel_64_t		fetch_pixel_64;
+    store_scanline_t		store_scanline_32;
+    store_scanline_t		store_scanline_64;
 } format_info_t;
 
 #define FORMAT_INFO(format) 						\
@@ -2951,12 +2951,12 @@ setup_accessors (bits_image_t *image)
     {
 	if (info->format == image->format)
 	{
-	    image->fetch_scanline_raw_32 = info->fetch_scanline_raw_32;
-	    image->fetch_scanline_raw_64 = info->fetch_scanline_raw_64;
-	    image->fetch_pixel_raw_32 = info->fetch_pixel_raw_32;
-	    image->fetch_pixel_raw_64 = info->fetch_pixel_raw_64;
-	    image->store_scanline_raw_32 = info->store_scanline_raw_32;
-	    image->store_scanline_raw_64 = info->store_scanline_raw_64;
+	    image->fetch_scanline_32 = info->fetch_scanline_32;
+	    image->fetch_scanline_64 = info->fetch_scanline_64;
+	    image->fetch_pixel_32 = info->fetch_pixel_32;
+	    image->fetch_pixel_64 = info->fetch_pixel_64;
+	    image->store_scanline_32 = info->store_scanline_32;
+	    image->store_scanline_64 = info->store_scanline_64;
 	    
 	    return;
 	}
@@ -2967,13 +2967,13 @@ setup_accessors (bits_image_t *image)
 
 #ifndef PIXMAN_FB_ACCESSORS
 void
-_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image);
+_pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
 
 void
-_pixman_bits_image_setup_raw_accessors (bits_image_t *image)
+_pixman_bits_image_setup_accessors (bits_image_t *image)
 {
     if (image->read_func || image->write_func)
-	_pixman_bits_image_setup_raw_accessors_accessors (image);
+	_pixman_bits_image_setup_accessors_accessors (image);
     else
 	setup_accessors (image);
 }
@@ -2981,7 +2981,7 @@ _pixman_bits_image_setup_raw_accessors (bits_image_t *image)
 #else
 
 void
-_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image)
+_pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
 {
     setup_accessors (image);
 }
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index f8ddcbc..d27256d 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -43,14 +43,14 @@ _pixman_image_store_scanline_32 (bits_image_t *  image,
                                  int             width,
                                  const uint32_t *buffer)
 {
-    image->store_scanline_raw_32 (image, x, y, width, 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_raw_32 (
+	image->common.alpha_map->store_scanline_32 (
 	    image->common.alpha_map, x, y, width, buffer);
     }
 }
@@ -62,14 +62,14 @@ _pixman_image_store_scanline_64 (bits_image_t *  image,
                                  int             width,
                                  const uint32_t *buffer)
 {
-    image->store_scanline_raw_64 (image, x, y, width, 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_raw_64 (
+	image->common.alpha_map->store_scanline_64 (
 	    image->common.alpha_map, x, y, width, buffer);
     }
 }
@@ -86,7 +86,7 @@ fetch_pixel_no_alpha (bits_image_t *image,
 	return 0;
     }
 
-    return image->fetch_pixel_raw_32 (image, x, y);
+    return image->fetch_pixel_32 (image, x, y);
 }
 
 typedef uint32_t (* get_pixel_t) (bits_image_t *image,
@@ -655,7 +655,7 @@ fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_boun
 	return 0;
     }
 
-    pixel = image->fetch_pixel_raw_32 (image, x, y);
+    pixel = image->fetch_pixel_32 (image, x, y);
 
     if (image->common.alpha_map)
     {
@@ -671,7 +671,7 @@ fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_boun
 	}
 	else
 	{
-	    pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
+	    pixel_a = image->common.alpha_map->fetch_pixel_32 (
 		image->common.alpha_map, x, y);
 
 	    pixel_a = ALPHA_8 (pixel_a);
@@ -760,7 +760,7 @@ bits_image_fetch_solid_32 (pixman_image_t * image,
     uint32_t color;
     uint32_t *end;
 
-    color = image->bits.fetch_pixel_raw_32 (&image->bits, 0, 0);
+    color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
 
     end = buffer + width;
     while (buffer < end)
@@ -779,7 +779,7 @@ bits_image_fetch_solid_64 (pixman_image_t * image,
     uint64_t *buffer = (uint64_t *)b;
     uint64_t *end;
 
-    color = image->bits.fetch_pixel_raw_64 (&image->bits, 0, 0);
+    color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
 
     end = buffer + width;
     while (buffer < end)
@@ -818,9 +818,9 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_raw_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
-	    image->fetch_scanline_raw_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
 	width -= w;
 	buffer += w * (wide? 2 : 1);
@@ -856,9 +856,9 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
 	w = MIN (width, image->width - x);
 
 	if (wide)
-	    image->fetch_scanline_raw_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 	else
-	    image->fetch_scanline_raw_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
 
 	buffer += w * (wide? 2 : 1);
 	x += w;
@@ -911,7 +911,7 @@ bits_image_property_changed (pixman_image_t *image)
 {
     bits_image_t *bits = (bits_image_t *)image;
 
-    _pixman_bits_image_setup_raw_accessors (bits);
+    _pixman_bits_image_setup_accessors (bits);
 
     if (bits->common.alpha_map)
     {
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 15a5bc2..a2736d7 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -175,17 +175,13 @@ struct bits_image
     uint32_t *                 free_me;
     int                        rowstride;  /* in number of uint32_t's */
 
-    /* Fetch a pixel, disregarding alpha maps, transformations etc. */
-    fetch_pixel_32_t	       fetch_pixel_raw_32;
-    fetch_pixel_64_t	       fetch_pixel_raw_64;
+    fetch_scanline_t           fetch_scanline_32;
+    fetch_pixel_32_t	       fetch_pixel_32;
+    store_scanline_t           store_scanline_32;
 
-    /* Fetch raw scanlines, with no regard for transformations, alpha maps etc. */
-    fetch_scanline_t           fetch_scanline_raw_32;
-    fetch_scanline_t           fetch_scanline_raw_64;
-
-    /* Store scanlines with no regard for alpha maps */
-    store_scanline_t           store_scanline_raw_32;
-    store_scanline_t           store_scanline_raw_64;
+    fetch_scanline_t           fetch_scanline_64;
+    fetch_pixel_64_t	       fetch_pixel_64;
+    store_scanline_t           store_scanline_64;
 
     /* Used for indirect access to the bits */
     pixman_read_memory_func_t  read_func;
@@ -205,9 +201,8 @@ union pixman_image
     solid_fill_t       solid;
 };
 
-
 void
-_pixman_bits_image_setup_raw_accessors (bits_image_t *image);
+_pixman_bits_image_setup_accessors (bits_image_t *image);
 
 void
 _pixman_image_get_scanline_generic_64  (pixman_image_t *image,
commit 807fd3c08491c8baffaad993d8b867141fa55319
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 12:34:42 2010 -0400

    Eliminate the store_scanline_{32,64} function pointers.
    
    Now that we can't recurse on alpha maps, they are not needed anymore.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 09b69df..f8ddcbc 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -36,13 +36,12 @@
 #include "pixman-combine32.h"
 
 /* Store functions */
-
-static void
-bits_image_store_scanline_32 (bits_image_t *  image,
-                              int             x,
-                              int             y,
-                              int             width,
-                              const uint32_t *buffer)
+void
+_pixman_image_store_scanline_32 (bits_image_t *  image,
+                                 int             x,
+                                 int             y,
+                                 int             width,
+                                 const uint32_t *buffer)
 {
     image->store_scanline_raw_32 (image, x, y, width, buffer);
 
@@ -51,16 +50,17 @@ bits_image_store_scanline_32 (bits_image_t *  image,
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	image->common.alpha_map->store_scanline_raw_32 (image->common.alpha_map, x, y, width, buffer);
+	image->common.alpha_map->store_scanline_raw_32 (
+	    image->common.alpha_map, x, y, width, buffer);
     }
 }
 
-static void
-bits_image_store_scanline_64 (bits_image_t *  image,
-                              int             x,
-                              int             y,
-                              int             width,
-                              const uint32_t *buffer)
+void
+_pixman_image_store_scanline_64 (bits_image_t *  image,
+                                 int             x,
+                                 int             y,
+                                 int             width,
+                                 const uint32_t *buffer)
 {
     image->store_scanline_raw_64 (image, x, y, width, buffer);
 
@@ -69,30 +69,11 @@ bits_image_store_scanline_64 (bits_image_t *  image,
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	image->common.alpha_map->store_scanline_raw_64 (image->common.alpha_map, x, y, width, buffer);
+	image->common.alpha_map->store_scanline_raw_64 (
+	    image->common.alpha_map, x, y, width, buffer);
     }
 }
 
-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);
-}
-
-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);
-}
-
 /* Fetch functions */
 
 static force_inline uint32_t
@@ -983,9 +964,6 @@ bits_image_property_changed (pixman_image_t *image)
 	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
 	image->common.get_scanline_32 = bits_image_fetch_general;
     }
-
-    bits->store_scanline_64 = bits_image_store_scanline_64;
-    bits->store_scanline_32 = bits_image_store_scanline_32;
 }
 
 static uint32_t *
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 06f6d11..15a5bc2 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -187,10 +187,6 @@ struct bits_image
     store_scanline_t           store_scanline_raw_32;
     store_scanline_t           store_scanline_raw_64;
 
-    /* Store a scanline, taking alpha maps into account */
-    store_scanline_t           store_scanline_32;
-    store_scanline_t           store_scanline_64;
-
     /* Used for indirect access to the bits */
     pixman_read_memory_func_t  read_func;
     pixman_write_memory_func_t write_func;
commit e213d5fd6207873638a86d908d06d7597cb88422
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 12:31:50 2010 -0400

    Split bits_image_fetch_transformed() into two functions.
    
    One function deals with the common affine, no-alpha-map case. The
    other deals with perspective transformations and alpha maps.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 0372217..09b69df 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -95,48 +95,9 @@ _pixman_image_store_scanline_64 (bits_image_t *  image,
 
 /* Fetch functions */
 
-static uint32_t
-fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
-{
-    uint32_t pixel;
-
-    if (check_bounds &&
-	(x < 0 || x >= image->width || y < 0 || y >= image->height))
-    {
-	return 0;
-    }
-
-    pixel = image->fetch_pixel_raw_32 (image, x, y);
-
-    if (image->common.alpha_map)
-    {
-	uint32_t pixel_a;
-
-	x -= image->common.alpha_origin_x;
-	y -= image->common.alpha_origin_y;
-
-	if (x < 0 || x >= image->common.alpha_map->width ||
-	    y < 0 || y >= image->common.alpha_map->height)
-	{
-	    pixel_a = 0;
-	}
-	else
-	{
-	    pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
-		image->common.alpha_map, x, y);
-
-	    pixel_a = ALPHA_8 (pixel_a);
-	}
-
-	pixel &= 0x00ffffff;
-	pixel |= (pixel_a << 24);
-    }
-
-    return pixel;
-}
-
 static force_inline uint32_t
-fetch_pixel_no_alpha (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+fetch_pixel_no_alpha (bits_image_t *image,
+		      int x, int y, pixman_bool_t check_bounds)
 {
     if (check_bounds &&
 	(x < 0 || x >= image->width || y < 0 || y >= image->height))
@@ -654,12 +615,101 @@ bits_image_fetch_pixel_filtered (bits_image_t *image,
 }
 
 static void
-bits_image_fetch_transformed (pixman_image_t * image,
-                              int              offset,
-                              int              line,
-                              int              width,
-                              uint32_t *       buffer,
-                              const uint32_t * mask)
+bits_image_fetch_affine_no_alpha (pixman_image_t * image,
+				  int              offset,
+				  int              line,
+				  int              width,
+				  uint32_t *       buffer,
+				  const uint32_t * mask)
+{
+    pixman_fixed_t x, y;
+    pixman_fixed_t ux, uy;
+    pixman_vector_t v;
+    int i;
+
+    /* reference point is the center of the pixel */
+    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+    v.vector[2] = pixman_fixed_1;
+
+    if (image->common.transform)
+    {
+	if (!pixman_transform_point_3d (image->common.transform, &v))
+	    return;
+
+	ux = image->common.transform->matrix[0][0];
+	uy = image->common.transform->matrix[1][0];
+    }
+    else
+    {
+	ux = pixman_fixed_1;
+	uy = 0;
+    }
+
+    x = v.vector[0];
+    y = v.vector[1];
+
+    for (i = 0; i < width; ++i)
+    {
+	if (!mask || mask[i])
+	{
+	    buffer[i] = bits_image_fetch_pixel_filtered (
+		&image->bits, x, y, fetch_pixel_no_alpha);
+	}
+	
+	x += ux;
+	y += uy;
+    }
+}
+
+/* General fetcher */
+static force_inline uint32_t
+fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+{
+    uint32_t pixel;
+
+    if (check_bounds &&
+	(x < 0 || x >= image->width || y < 0 || y >= image->height))
+    {
+	return 0;
+    }
+
+    pixel = image->fetch_pixel_raw_32 (image, x, y);
+
+    if (image->common.alpha_map)
+    {
+	uint32_t pixel_a;
+
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
+
+	if (x < 0 || x >= image->common.alpha_map->width ||
+	    y < 0 || y >= image->common.alpha_map->height)
+	{
+	    pixel_a = 0;
+	}
+	else
+	{
+	    pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
+		image->common.alpha_map, x, y);
+
+	    pixel_a = ALPHA_8 (pixel_a);
+	}
+
+	pixel &= 0x00ffffff;
+	pixel |= (pixel_a << 24);
+    }
+
+    return pixel;
+}
+
+static void
+bits_image_fetch_general (pixman_image_t * image,
+			  int              offset,
+			  int              line,
+			  int              width,
+			  uint32_t *       buffer,
+			  const uint32_t * mask)
 {
     pixman_fixed_t x, y, w;
     pixman_fixed_t ux, uy, uw;
@@ -671,8 +721,6 @@ bits_image_fetch_transformed (pixman_image_t * image,
     v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
     v.vector[2] = pixman_fixed_1;
 
-    /* when using convolution filters or PIXMAN_REPEAT_PAD one
-     * might get here without a transform */
     if (image->common.transform)
     {
 	if (!pixman_transform_point_3d (image->common.transform, &v))
@@ -693,47 +741,30 @@ bits_image_fetch_transformed (pixman_image_t * image,
     y = v.vector[1];
     w = v.vector[2];
 
-    if (w == pixman_fixed_1 && uw == 0) /* Affine */
+    for (i = 0; i < width; ++i)
     {
-	for (i = 0; i < width; ++i)
+	pixman_fixed_t x0, y0;
+
+	if (!mask || mask[i])
 	{
-	    if (!mask || mask[i])
+	    if (w != 0)
 	    {
-		buffer[i] =
-		    bits_image_fetch_pixel_filtered (&image->bits, x, y, fetch_pixel_general);
+		x0 = ((pixman_fixed_48_16_t)x << 16) / w;
+		y0 = ((pixman_fixed_48_16_t)y << 16) / w;
 	    }
-
-	    x += ux;
-	    y += uy;
-	}
-    }
-    else
-    {
-	for (i = 0; i < width; ++i)
-	{
-	    if (!mask || mask[i])
+	    else
 	    {
-		pixman_fixed_t x0, y0;
-
-		if (w != 0)
-		{
-		    x0 = ((pixman_fixed_48_16_t)x << 16) / w;
-		    y0 = ((pixman_fixed_48_16_t)y << 16) / w;
-		}
-		else
-		{
-		    x0 = 0;
-		    y0 = 0;
-		}
-
-		buffer[i] =
-		    bits_image_fetch_pixel_filtered (&image->bits, x0, y0, fetch_pixel_general);
+		x0 = 0;
+		y0 = 0;
 	    }
 
-	    x += ux;
-	    y += uy;
-	    w += uw;
+	    buffer[i] = bits_image_fetch_pixel_filtered (
+		&image->bits, x0, y0, fetch_pixel_general);
 	}
+
+	x += ux;
+	y += uy;
+	w += uw;
     }
 }
 
@@ -903,10 +934,8 @@ bits_image_property_changed (pixman_image_t *image)
 
     if (bits->common.alpha_map)
     {
-	image->common.get_scanline_64 =
-	    _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 =
-	    bits_image_fetch_transformed;
+	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+	image->common.get_scanline_32 = bits_image_fetch_general;
     }
     else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
              bits->width == 1 &&
@@ -937,17 +966,22 @@ bits_image_property_changed (pixman_image_t *image)
 	     (bits->format == PIXMAN_a8r8g8b8	||
 	      bits->format == PIXMAN_x8r8g8b8))
     {
-	image->common.get_scanline_64 =
-	    _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 =
-	    bits_image_fetch_bilinear_no_repeat_8888;
+	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+	image->common.get_scanline_32 = bits_image_fetch_bilinear_no_repeat_8888;
+    }
+    else if (bits->common.transform					&&
+	     bits->common.transform->matrix[2][0] == 0			&&
+	     bits->common.transform->matrix[2][1] == 0			&&
+	     bits->common.transform->matrix[2][2] == pixman_fixed_1)
+	     
+    {
+	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+	image->common.get_scanline_32 = bits_image_fetch_affine_no_alpha;
     }
     else
     {
-	image->common.get_scanline_64 =
-	    _pixman_image_get_scanline_generic_64;
-	image->common.get_scanline_32 =
-	    bits_image_fetch_transformed;
+	image->common.get_scanline_64 = _pixman_image_get_scanline_generic_64;
+	image->common.get_scanline_32 = bits_image_fetch_general;
     }
 
     bits->store_scanline_64 = bits_image_store_scanline_64;
commit cbb2a0d7929ec27e0a135d7fa11e1acf3942bce2
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 12:11:44 2010 -0400

    Eliminate get_pixel_32() and get_pixel_64() from bits_image.
    
    These functions can simply be passed as arguments to the various pixel
    fetchers. We don't need to store them. Since they are known at compile
    time and the pixel fetchers are force_inline, this is not a
    performance issue.
    
    Also temporarily make all pixel access go through the alpha path.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 81722c2..0372217 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -96,38 +96,47 @@ _pixman_image_store_scanline_64 (bits_image_t *  image,
 /* Fetch functions */
 
 static uint32_t
-bits_image_fetch_pixel_alpha (bits_image_t *image, int x, int y)
+fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
 {
     uint32_t pixel;
-    uint32_t pixel_a;
+
+    if (check_bounds &&
+	(x < 0 || x >= image->width || y < 0 || y >= image->height))
+    {
+	return 0;
+    }
 
     pixel = image->fetch_pixel_raw_32 (image, x, y);
 
-    assert (image->common.alpha_map);
+    if (image->common.alpha_map)
+    {
+	uint32_t pixel_a;
 
-    x -= image->common.alpha_origin_x;
-    y -= image->common.alpha_origin_y;
+	x -= image->common.alpha_origin_x;
+	y -= image->common.alpha_origin_y;
 
-    if (x < 0 || x >= image->common.alpha_map->width ||
-	y < 0 || y >= image->common.alpha_map->height)
-    {
-	pixel_a = 0;
-    }
-    else
-    {
-	pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
-	    image->common.alpha_map, x, y);
-	pixel_a = ALPHA_8 (pixel_a);
-    }
+	if (x < 0 || x >= image->common.alpha_map->width ||
+	    y < 0 || y >= image->common.alpha_map->height)
+	{
+	    pixel_a = 0;
+	}
+	else
+	{
+	    pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
+		image->common.alpha_map, x, y);
 
-    pixel &= 0x00ffffff;
-    pixel |= (pixel_a << 24);
+	    pixel_a = ALPHA_8 (pixel_a);
+	}
+
+	pixel &= 0x00ffffff;
+	pixel |= (pixel_a << 24);
+    }
 
     return pixel;
 }
 
 static force_inline uint32_t
-get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+fetch_pixel_no_alpha (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
 {
     if (check_bounds &&
 	(x < 0 || x >= image->width || y < 0 || y >= image->height))
@@ -135,9 +144,12 @@ get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
 	return 0;
     }
 
-    return image->fetch_pixel_32 (image, x, y);
+    return image->fetch_pixel_raw_32 (image, x, y);
 }
 
+typedef uint32_t (* get_pixel_t) (bits_image_t *image,
+				  int x, int y, pixman_bool_t check_bounds);
+
 static force_inline void
 repeat (pixman_repeat_t repeat, int size, int *coord)
 {
@@ -169,7 +181,8 @@ repeat (pixman_repeat_t repeat, int size, int *coord)
 static force_inline uint32_t
 bits_image_fetch_pixel_nearest (bits_image_t   *image,
 				pixman_fixed_t  x,
-				pixman_fixed_t  y)
+				pixman_fixed_t  y,
+				get_pixel_t	get_pixel)
 {
     int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
     int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
@@ -281,7 +294,8 @@ bilinear_interpolation (uint32_t tl, uint32_t tr,
 static force_inline uint32_t
 bits_image_fetch_pixel_bilinear (bits_image_t   *image,
 				 pixman_fixed_t  x,
-				 pixman_fixed_t  y)
+				 pixman_fixed_t  y,
+				 get_pixel_t	 get_pixel)
 {
     pixman_repeat_t repeat_mode = image->common.repeat;
     int width = image->width;
@@ -538,7 +552,8 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
 static force_inline uint32_t
 bits_image_fetch_pixel_convolution (bits_image_t   *image,
 				    pixman_fixed_t  x,
-				    pixman_fixed_t  y)
+				    pixman_fixed_t  y,
+				    get_pixel_t     get_pixel)
 {
     pixman_fixed_t *params = image->common.filter_params;
     int x_off = (params[0] - pixman_fixed_1) >> 1;
@@ -611,23 +626,24 @@ bits_image_fetch_pixel_convolution (bits_image_t   *image,
 static force_inline uint32_t
 bits_image_fetch_pixel_filtered (bits_image_t *image,
 				 pixman_fixed_t x,
-				 pixman_fixed_t y)
+				 pixman_fixed_t y,
+				 get_pixel_t    get_pixel)
 {
     switch (image->common.filter)
     {
     case PIXMAN_FILTER_NEAREST:
     case PIXMAN_FILTER_FAST:
-	return bits_image_fetch_pixel_nearest (image, x, y);
+	return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
 	break;
 
     case PIXMAN_FILTER_BILINEAR:
     case PIXMAN_FILTER_GOOD:
     case PIXMAN_FILTER_BEST:
-	return bits_image_fetch_pixel_bilinear (image, x, y);
+	return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
 	break;
 
     case PIXMAN_FILTER_CONVOLUTION:
-	return bits_image_fetch_pixel_convolution (image, x, y);
+	return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
 	break;
 
     default:
@@ -684,7 +700,7 @@ bits_image_fetch_transformed (pixman_image_t * image,
 	    if (!mask || mask[i])
 	    {
 		buffer[i] =
-		    bits_image_fetch_pixel_filtered (&image->bits, x, y);
+		    bits_image_fetch_pixel_filtered (&image->bits, x, y, fetch_pixel_general);
 	    }
 
 	    x += ux;
@@ -711,7 +727,7 @@ bits_image_fetch_transformed (pixman_image_t * image,
 		}
 
 		buffer[i] =
-		    bits_image_fetch_pixel_filtered (&image->bits, x0, y0);
+		    bits_image_fetch_pixel_filtered (&image->bits, x0, y0, fetch_pixel_general);
 	    }
 
 	    x += ux;
@@ -885,16 +901,12 @@ bits_image_property_changed (pixman_image_t *image)
 
     _pixman_bits_image_setup_raw_accessors (bits);
 
-    image->bits.fetch_pixel_32 = image->bits.fetch_pixel_raw_32;
-
     if (bits->common.alpha_map)
     {
 	image->common.get_scanline_64 =
 	    _pixman_image_get_scanline_generic_64;
 	image->common.get_scanline_32 =
 	    bits_image_fetch_transformed;
-
-	image->bits.fetch_pixel_32 = bits_image_fetch_pixel_alpha;
     }
     else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
              bits->width == 1 &&
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index f6424e7..06f6d11 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -179,10 +179,6 @@ struct bits_image
     fetch_pixel_32_t	       fetch_pixel_raw_32;
     fetch_pixel_64_t	       fetch_pixel_raw_64;
 
-    /* Fetch a pixel, taking alpha maps into account */
-    fetch_pixel_32_t	       fetch_pixel_32;
-    fetch_pixel_64_t	       fetch_pixel_64;
-
     /* Fetch raw scanlines, with no regard for transformations, alpha maps etc. */
     fetch_scanline_t           fetch_scanline_raw_32;
     fetch_scanline_t           fetch_scanline_raw_64;
commit 6480c92312e1fb6662ad0d10940660a9439667ea
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Jul 2 11:58:23 2010 -0400

    Eliminate recursion from alpha map code
    
    Alpha maps with alpha maps are no longer supported. It's not a useful
    feature and it could could lead to infinite recursion.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 36ea0af..81722c2 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -51,7 +51,7 @@ bits_image_store_scanline_32 (bits_image_t *  image,
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	bits_image_store_scanline_32 (image->common.alpha_map, x, y, width, buffer);
+	image->common.alpha_map->store_scanline_raw_32 (image->common.alpha_map, x, y, width, buffer);
     }
 }
 
@@ -69,7 +69,7 @@ bits_image_store_scanline_64 (bits_image_t *  image,
 	x -= image->common.alpha_origin_x;
 	y -= image->common.alpha_origin_y;
 
-	bits_image_store_scanline_64 (image->common.alpha_map, x, y, width, buffer);
+	image->common.alpha_map->store_scanline_raw_64 (image->common.alpha_map, x, y, width, buffer);
     }
 }
 
commit 1cc750ed92a936d84b47cac696aaffd226e1c02e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Jul 22 04:27:45 2010 -0400

    Replace compute_src_extent_flags() with analyze_extents()
    
    This commit fixes two separate problems: 1. Incorrect computation of
    the FAST_PATH_SAMPLES_COVER_CLIP flag, and 2. FAST_PATH_16BIT_SAFE is
    a nonsensical thing to compute.
    
    == 1. Incorrect computation of SAMPLES_COVER_CLIP:
    
    Previously we were using pixman_transform_bounds() to compute which
    source samples would be used for a composite operation. This is
    incorrect for several reasons:
    
    (a) pixman_transform_bounds() is transforming the integer bounding box
    of the destination samples, where it should be transforming the
    bounding box of the samples themselves. In other words, it is too
    pessimistic in some cases.
    
    (b) pixman_transform_bounds() is not rounding the same way as we do
    during sampling. For example, for a NEAREST filter we subtract
    pixman_fixed_e before rounding off to the nearest sample so that a
    transformed value of 1 will round to the sample at 0.5 and not to the
    one at 1.5. However, pixman_transform_bounds() would simply truncate
    to 1 which would imply that the first sample to be used was the one at
    1.5. In other words, it is too optimistic in some cases.
    
    (c) The result of pixman_transform_bounds() does not account for the
    interpolation filter applied to the source.
    
    == 2. FAST_PATH_16BIT_SAFE is nonsensical
    
    The FAST_PATH_16BIT_SAFE is a flag that indicates that various
    computations can be safely done within a 16.16 fixed-point
    variable. It was used by certain fast paths who relied on those
    computations succeeding. The problem is that many other compositing
    functions were making similar assumptions but not actually requiring
    the flag to be set. Notably, all the general compositing functions
    simply walk the source region using 16.16 variables. If the
    transformation happens to overflow, strange things will happen.
    
    So instead of computing this flag in certain cases, it is better to
    simply detect that overflows will happen and not try to composite at
    all in that case. This has the advantage that most compositing
    functions can be written naturally way.
    
    It does have the disadvantage that we are giving up on some cases that
    previously worked, but those are all corner cases where the areas
    involved were very close to the limits of the coordinate
    system. Relying on these working reliably was always a somewhat
    dubious proposition. The most important case that might have worked
    previously was untransformed compositing involving images larger than
    32 bits. But even in those cases, if you had REPEAT_PAD or
    REPEAT_REFLECT turned on, you would hit bits_image_fetch_transformed()
    which has the 16 bit limitations.
    
    == Fixes
    
    This patch fixes both problems by introducing a new function called
    analyze_extents() that has the responsibility to reject corner cases,
    and to compute flags based on the extents.
    
    It does this through a new compute_sample_extents() function that will
    compute a conservative (but tight) approximation to the bounding box
    of the samples that will actually be needed. By basing the computation
    on the positions of the _sample_ locations in the destination, and by
    taking the interpolation filter into account, it fixes problem one.
    
    The same function is also used with a one-pixel expanded version of
    the destination extents. By checking if the transformed bounding box
    will overflow 16.16 fixed point, it fixes problem two.

diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c
index 6ed1580..7858a6d 100644
--- a/pixman/pixman-fast-path.c
+++ b/pixman/pixman-fast-path.c
@@ -1881,7 +1881,7 @@ static const pixman_fast_path_t c_fast_paths[] =
 #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func)				\
     {   PIXMAN_OP_ ## op,						\
 	PIXMAN_ ## s,							\
-	SCALED_NEAREST_FLAGS | HAS_NORMAL_REPEAT_FLAGS | FAST_PATH_16BIT_SAFE | FAST_PATH_X_UNIT_POSITIVE, \
+	SCALED_NEAREST_FLAGS | HAS_NORMAL_REPEAT_FLAGS | FAST_PATH_X_UNIT_POSITIVE, \
 	PIXMAN_null, 0,							\
 	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				\
 	fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op,	\
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 8718fcb..f6424e7 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -577,8 +577,7 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_NEEDS_WORKAROUND		(1 << 14)
 #define FAST_PATH_NO_NONE_REPEAT		(1 << 15)
 #define FAST_PATH_SAMPLES_COVER_CLIP		(1 << 16)
-#define FAST_PATH_16BIT_SAFE			(1 << 17)
-#define FAST_PATH_X_UNIT_POSITIVE		(1 << 18)
+#define FAST_PATH_X_UNIT_POSITIVE		(1 << 17)
 
 #define _FAST_PATH_STANDARD_FLAGS					\
     (FAST_PATH_ID_TRANSFORM		|				\
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 0333a40..e79e135 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -488,77 +488,6 @@ walk_region_internal (pixman_implementation_t *imp,
     }
 }
 
-#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
-
-static force_inline uint32_t
-compute_src_extents_flags (pixman_image_t *image,
-			   pixman_box32_t *extents,
-			   int             x,
-			   int             y)
-{
-    pixman_box16_t extents16;
-    uint32_t flags;
-
-    flags = FAST_PATH_COVERS_CLIP;
-
-    if (image->common.type != BITS)
-	return flags;
-
-    if (image->common.repeat == PIXMAN_REPEAT_NONE &&
-	(x > extents->x1 || y > extents->y1 ||
-	 x + image->bits.width < extents->x2 ||
-	 y + image->bits.height < extents->y2))
-    {
-	flags &= ~FAST_PATH_COVERS_CLIP;
-    }
-
-    if (IS_16BIT (extents->x1 - x) &&
-	IS_16BIT (extents->y1 - y) &&
-	IS_16BIT (extents->x2 - x) &&
-	IS_16BIT (extents->y2 - y))
-    {
-	extents16.x1 = extents->x1 - x;
-	extents16.y1 = extents->y1 - y;
-	extents16.x2 = extents->x2 - x;
-	extents16.y2 = extents->y2 - y;
-
-	if (!image->common.transform ||
-	    pixman_transform_bounds (image->common.transform, &extents16))
-	{
-	    if (extents16.x1 >= 0  && extents16.y1 >= 0 &&
-		extents16.x2 <= image->bits.width &&
-		extents16.y2 <= image->bits.height)
-	    {
-		flags |= FAST_PATH_SAMPLES_COVER_CLIP;
-	    }
-	}
-    }
-
-    if (IS_16BIT (extents->x1 - x - 1) &&
-	IS_16BIT (extents->y1 - y - 1) &&
-	IS_16BIT (extents->x2 - x + 1) &&
-	IS_16BIT (extents->y2 - y + 1))
-    {
-	extents16.x1 = extents->x1 - x - 1;
-	extents16.y1 = extents->y1 - y - 1;
-	extents16.x2 = extents->x2 - x + 1;
-	extents16.y2 = extents->y2 - y + 1;
-
-	if (/* src space expanded by one in dest space fits in 16 bit */
-	    (!image->common.transform ||
-	     pixman_transform_bounds (image->common.transform, &extents16)) &&
-	    /* And src image size can be used as 16.16 fixed point */
-	    image->bits.width < 0x7fff &&
-	    image->bits.height < 0x7fff)
-	{
-	    /* Then we're "16bit safe" */
-	    flags |= FAST_PATH_16BIT_SAFE;
-	}
-    }
-
-    return flags;
-}
-
 #define N_CACHED_FAST_PATHS 8
 
 typedef struct
@@ -668,6 +597,208 @@ update_cache:
     }
 }
 
+static pixman_bool_t
+compute_sample_extents (pixman_transform_t *transform,
+			pixman_box32_t *extents, int x, int y, 
+			pixman_fixed_t x_off, pixman_fixed_t y_off,
+			pixman_fixed_t width, pixman_fixed_t height)
+{
+    pixman_fixed_t x1, y1, x2, y2;
+    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
+
+    /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
+    x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
+    y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
+    x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
+    y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
+
+    if (!transform)
+    {
+	tx1 = (pixman_fixed_48_16_t)x1;
+	ty1 = (pixman_fixed_48_16_t)y1;
+	tx2 = (pixman_fixed_48_16_t)x2;
+	ty2 = (pixman_fixed_48_16_t)y2;
+    }
+    else
+    {
+	int i;
+
+	for (i = 0; i < 4; ++i)
+	{
+	    pixman_fixed_48_16_t tx, ty;
+	    pixman_vector_t v;
+
+	    v.vector[0] = (i & 0x01)? x1 : x2;
+	    v.vector[1] = (i & 0x02)? y1 : y2;
+	    v.vector[2] = pixman_fixed_1;
+
+	    if (!pixman_transform_point (transform, &v))
+		return FALSE;
+
+	    tx = (pixman_fixed_48_16_t)v.vector[0];
+	    ty = (pixman_fixed_48_16_t)v.vector[1];
+
+	    if (i == 0)
+	    {
+		tx1 = tx;
+		ty1 = ty;
+		tx2 = tx;
+		ty2 = ty;
+	    }
+	    else
+	    {
+		if (tx < tx1)
+		    tx1 = tx;
+		if (ty < ty1)
+		    ty1 = ty;
+		if (tx > tx2)
+		    tx2 = tx;
+		if (ty > ty2)
+		    ty2 = ty;
+	    }
+	}
+    }
+
+    /* Expand the source area by a tiny bit so account of different rounding that
+     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
+     * 0.5 so this won't cause the area computed to be overly pessimistic.
+     */
+    tx1 += x_off - 8 * pixman_fixed_e;
+    ty1 += y_off - 8 * pixman_fixed_e;
+    tx2 += x_off + width + 8 * pixman_fixed_e;
+    ty2 += y_off + height + 8 * pixman_fixed_e;
+
+    if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
+	ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
+	tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
+	ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
+    {
+	return FALSE;
+    }
+    else
+    {
+	extents->x1 = pixman_fixed_to_int (tx1);
+	extents->y1 = pixman_fixed_to_int (ty1);
+	extents->x2 = pixman_fixed_to_int (tx2) + 1;
+	extents->y2 = pixman_fixed_to_int (ty2) + 1;
+
+	return TRUE;
+    }
+}
+
+#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
+
+static pixman_bool_t
+analyze_extent (pixman_image_t *image, int x, int y,
+		const pixman_box32_t *extents, uint32_t *flags)
+{
+    pixman_transform_t *transform;
+    pixman_fixed_t *params;
+    pixman_fixed_t x_off, y_off;
+    pixman_fixed_t width, height;
+    pixman_box32_t ex;
+
+    *flags |= FAST_PATH_COVERS_CLIP;
+    if (!image)
+	return TRUE;
+
+    transform = image->common.transform;
+    if (image->common.type == BITS)
+    {
+	/* During repeat mode calculations we might convert the
+	 * width/height of an image to fixed 16.16, so we need
+	 * them to be smaller than 16 bits.
+	 */
+	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
+	    return FALSE;
+
+	if (image->common.repeat == PIXMAN_REPEAT_NONE &&
+	    (x > extents->x1 || y > extents->y1 ||
+	     x + image->bits.width < extents->x2 ||
+	     y + image->bits.height < extents->y2))
+	{
+	    (*flags) &= ~FAST_PATH_COVERS_CLIP;
+	}
+    }
+
+    /* Some compositing functions walk one step
+     * outside the destination rectangle, so we
+     * check here that the expanded-by-one source
+     * extents in destination space fits in 16 bits
+     */
+    if (!IS_16BIT (extents->x1 - x - 1)		||
+	!IS_16BIT (extents->y1 - y - 1)		||
+	!IS_16BIT (extents->x2 - x + 1)		||
+	!IS_16BIT (extents->y2 - y + 1))
+    {
+	return FALSE;
+    }
+
+    if (image->common.type == BITS)
+    {
+	switch (image->common.filter)
+	{
+	case PIXMAN_FILTER_CONVOLUTION:
+	    params = image->common.filter_params;
+	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
+	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
+	    width = params[0];
+	    height = params[1];
+	    break;
+
+	case PIXMAN_FILTER_GOOD:
+	case PIXMAN_FILTER_BEST:
+	case PIXMAN_FILTER_BILINEAR:
+	    x_off = - pixman_fixed_1 / 2;
+	    y_off = - pixman_fixed_1 / 2;
+	    width = pixman_fixed_1;
+	    height = pixman_fixed_1;
+	    break;
+
+	case PIXMAN_FILTER_FAST:
+	case PIXMAN_FILTER_NEAREST:
+	    x_off = - pixman_fixed_e;
+	    y_off = - pixman_fixed_e;
+	    width = 0;
+	    height = 0;
+	    break;
+
+	default:
+	    return FALSE;
+	}
+    }
+    else
+    {
+	x_off = 0;
+	y_off = 0;
+	width = 0;
+	height = 0;
+    }
+
+    /* Check that the extents expanded by one don't overflow. This ensures that
+     * compositing functions can simply walk the source space using 16.16 variables
+     * without worrying about overflow.
+     */
+    ex.x1 = extents->x1 - 1;
+    ex.y1 = extents->y1 - 1;
+    ex.x2 = extents->x2 + 1;
+    ex.y2 = extents->y2 + 1;
+
+    if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+	return FALSE;
+
+    /* Check whether the non-expanded, transformed extent is entirely within
+     * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
+     */
+    ex = *extents;
+    if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+    {
+	if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
+	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
+    }
+
+    return TRUE;
+}
 
 static void
 do_composite (pixman_op_t	       op,
@@ -737,20 +868,21 @@ do_composite (pixman_op_t	       op,
     }
 
     pixman_region32_init (&region);
-    
+
     if (!pixman_compute_composite_region32 (
 	    &region, src, mask, dest,
 	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
     {
 	goto out;
     }
-    
+
     extents = pixman_region32_extents (&region);
-    
-    src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
 
-    if (mask)
-	mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
+    if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
+	goto out;
+
+    if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
+	goto out;
 
     /*
      * Check if we can replace our operator by a simpler one
@@ -765,7 +897,7 @@ do_composite (pixman_op_t	       op,
 			       src_format, src_flags,
 			       mask_format, mask_flags,
 			       dest_format, dest_flags,
-			       &imp, &func);			       
+			       &imp, &func);
 
     walk_region_internal (imp, op,
 			  src, mask, dest,
commit 5b289d39cfd5e5cd8b1e0a7b654574ed3e7e90ac
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Wed Jul 28 02:11:08 2010 -0400

    Extend scaling-crash-test in various ways
    
    This extends scaling-crash-test to test some more things:
    
    - All combinations of NEAREST/BILINEAR/CONVOLUTION filters and
      NORMAL/PAD/REFLECT repeat modes.
    
    - Tests various scale factors very close to 1/7th such that the source
      area is very close to edge of the source image.
    
    - The same things, only with scale factors very close to 1/32767th.
    
    - Enables the commented-out tests for accessing memory outside the
      source buffer.
    
    Also there is now a border around the source buffer which has a
    different color than the source buffer itself so that if we sample
    outside, it will show up.
    
    Finally, the test now allows the destination buffer to not be changed
    at all. This allows pixman to simply bail out in cases where the
    transformation too strange.

diff --git a/test/scaling-crash-test.c b/test/scaling-crash-test.c
index 4ab01e3..7a94115 100644
--- a/test/scaling-crash-test.c
+++ b/test/scaling-crash-test.c
@@ -8,117 +8,202 @@
  * We have a source image filled with solid color, set NORMAL or PAD repeat,
  * and some transform which results in nearest neighbour scaling.
  *
- * The expected result is the destination image filled with this solid
- * color.
+ * The expected result is either that the destination image filled with this solid
+ * color or, if the transformation is such that we can't composite anything at
+ * all, that nothing has changed in the destination.
+ *
+ * The surrounding memory of the source image is a different solid color so that
+ * we are sure to get failures if we access it.
  */
 static int
-do_test (int32_t		dst_size,
-	 int32_t		src_size,
-	 int32_t		src_offs,
-	 int32_t		scale_factor,
-	 pixman_repeat_t	repeat)
+run_test (int32_t		dst_width,
+	  int32_t		dst_height,
+	  int32_t		src_width,
+	  int32_t		src_height,
+	  int32_t		src_x,
+	  int32_t		src_y,
+	  int32_t		scale_x,
+	  int32_t		scale_y,
+	  pixman_filter_t	filter,
+	  pixman_repeat_t	repeat)
 {
-    int i;
     pixman_image_t *   src_img;
     pixman_image_t *   dst_img;
     pixman_transform_t transform;
     uint32_t *         srcbuf;
     uint32_t *         dstbuf;
+    pixman_box32_t     box = { 0, 0, src_width, src_height };
+    pixman_color_t     color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc };
+    int result;
+    int i;
 
-    srcbuf = (uint32_t *)malloc (src_size * 4);
-    dstbuf = (uint32_t *)malloc (dst_size * 4);
+    static const pixman_fixed_t kernel[] =
+    {
+#define D(f)	(pixman_double_to_fixed (f) + 0x0001)
+
+	pixman_int_to_fixed (5),
+	pixman_int_to_fixed (5),
+	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+	D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0)
+    };
+
+    result = 0;
 
-    /* horizontal test */
-    memset (srcbuf, 0xCC, src_size * 4);
-    memset (dstbuf, 0x33, dst_size * 4);
+    srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4);
+    dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4);
+
+    memset (srcbuf, 0x88, src_width * src_height * 4);
+    memset (dstbuf, 0x33, dst_width * dst_height * 4);
 
     src_img = pixman_image_create_bits (
-        PIXMAN_a8r8g8b8, src_size, 1, srcbuf, src_size * 4);
+        PIXMAN_a8r8g8b8, src_width, src_height,
+	srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4);
+
+    pixman_image_fill_boxes (PIXMAN_OP_SRC, src_img, &color_cc, 1, &box);
+
     dst_img = pixman_image_create_bits (
-        PIXMAN_a8r8g8b8, dst_size, 1, dstbuf, dst_size * 4);
+        PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4);
 
-    pixman_transform_init_scale (&transform, scale_factor, 65536);
+    pixman_transform_init_scale (&transform, scale_x, scale_y);
     pixman_image_set_transform (src_img, &transform);
     pixman_image_set_repeat (src_img, repeat);
-    pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
+    if (filter == PIXMAN_FILTER_CONVOLUTION)
+	pixman_image_set_filter (src_img, filter, kernel, 27);
+    else
+	pixman_image_set_filter (src_img, filter, NULL, 0);
 
     pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
-                            src_offs, 0, 0, 0, 0, 0, dst_size, 1);
+                            src_x, src_y, 0, 0, 0, 0, dst_width, dst_height);
 
     pixman_image_unref (src_img);
     pixman_image_unref (dst_img);
 
-    for (i = 0; i < dst_size; i++)
+    for (i = 0; i < dst_width * dst_height; i++)
     {
-	if (dstbuf[i] != 0xCCCCCCCC)
+	if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
 	{
-	    free (srcbuf);
-	    free (dstbuf);
-	    return 1;
+	    result = 1;
+	    break;
 	}
     }
 
-    /* vertical test */
-    memset (srcbuf, 0xCC, src_size * 4);
-    memset (dstbuf, 0x33, dst_size * 4);
+    free (srcbuf);
+    free (dstbuf);
+    return result;
+}
 
-    src_img = pixman_image_create_bits (
-        PIXMAN_a8r8g8b8, 1, src_size, srcbuf, 4);
-    dst_img = pixman_image_create_bits (
-        PIXMAN_a8r8g8b8, 1, dst_size, dstbuf, 4);
+typedef struct info_t info_t;
+struct info_t
+{
+    int value;
+    char name[28];
+};
 
-    pixman_transform_init_scale (&transform, 65536, scale_factor);
-    pixman_image_set_transform (src_img, &transform);
-    pixman_image_set_repeat (src_img, repeat);
-    pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
+static const info_t filters[] =
+{
+    { PIXMAN_FILTER_NEAREST, "NEAREST" },
+    { PIXMAN_FILTER_BILINEAR, "BILINEAR" },
+    { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
+};
 
-    pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
-                            0, src_offs, 0, 0, 0, 0, 1, dst_size);
+static const info_t repeats[] =
+{
+    { PIXMAN_REPEAT_PAD, "PAD" },
+    { PIXMAN_REPEAT_REFLECT, "REFLECT" },
+    { PIXMAN_REPEAT_NORMAL, "NORMAL" }
+};
 
-    pixman_image_unref (src_img);
-    pixman_image_unref (dst_img);
+static int
+do_test (int32_t		dst_size,
+	 int32_t		src_size,
+	 int32_t		src_offs,
+	 int32_t		scale_factor)
+{
+#define N_ELEMENTS(a)	(sizeof (a) / sizeof ((a)[0]))
+    int i, j;
 
-    for (i = 0; i < dst_size; i++)
+    for (i = 0; i < N_ELEMENTS(filters); ++i)
     {
-	if (dstbuf[i] != 0xCCCCCCCC)
+	for (j = 0; j < N_ELEMENTS (repeats); ++j)
 	{
-	    free (srcbuf);
-	    free (dstbuf);
-	    return 1;
+	    /* horizontal test */
+	    if (run_test (dst_size, 1,
+			  src_size, 1,
+			  src_offs, 0,
+			  scale_factor, 65536,
+			  filters[i].value,
+			  repeats[j].value) != 0)
+	    {
+		printf ("Vertical test failed with %s filter and repeat mode %s\n",
+			filters[i].name, repeats[j].name);
+
+		return 1;
+	    }
+
+	    /* vertical test */
+	    if (run_test (1, dst_size,
+			  1, src_size,
+			  0, src_offs,
+			  65536, scale_factor,
+			  filters[i].value,
+			  repeats[j].value) != 0)
+	    {
+		printf ("Vertical test failed with %s filter and repeat mode %s\n",
+			filters[i].name, repeats[j].name);
+
+		return 1;
+	    }
 	}
     }
 
-    free (srcbuf);
-    free (dstbuf);
     return 0;
 }
 
 int
 main (int argc, char *argv[])
 {
+    int i;
+
     pixman_disable_out_of_bounds_workaround ();
 
     /* can potentially crash */
     assert (do_test (
-	48000, 32767, 1, 65536 * 128, PIXMAN_REPEAT_NORMAL) == 0);
+		48000, 32767, 1, 65536 * 128) == 0);
 
     /* can potentially get into a deadloop */
     assert (do_test (
-	16384, 65536, 32, 32768, PIXMAN_REPEAT_NORMAL) == 0);
+		16384, 65536, 32, 32768) == 0);
 
-#if 0
     /* can potentially access memory outside source image buffer */
     assert (do_test (
-	10, 10, 0, 1, PIXMAN_REPEAT_PAD) == 0);
+		10, 10, 0, 1) == 0);
     assert (do_test (
-	10, 10, 0, 0, PIXMAN_REPEAT_PAD) == 0);
-#endif
+		10, 10, 0, 0) == 0);
+
+    for (i = 0; i < 100; ++i)
+    {
+	pixman_fixed_t one_seventh =
+	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16);
+
+	assert (do_test (
+		    1, 7, 3, one_seventh + i - 50) == 0);
+    }
+
+    for (i = 0; i < 100; ++i)
+    {
+	pixman_fixed_t scale =
+	    (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16);
+
+	assert (do_test (
+		    1, 32767, 16383, scale + i - 50) == 0);
+    }
 
-#if 0
     /* can potentially provide invalid results (out of range matrix stuff) */
     assert (do_test (
-	48000, 32767, 16384, 65536 * 128, PIXMAN_REPEAT_NORMAL) == 0);
-#endif
+	48000, 32767, 16384, 65536 * 128) == 0);
 
     return 0;
 }


More information about the xorg-commit mailing list