pixman: Branch 'master' - 2 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Sun Jul 12 10:35:13 PDT 2009


 pixman/pixman-bits-image.c |   58 +++++++++++++++++++++++++++++
 pixman/pixman-image.c      |    3 +
 pixman/pixman-private.h    |    1 
 pixman/pixman-utils.c      |   89 ++++++++++-----------------------------------
 4 files changed, 83 insertions(+), 68 deletions(-)

New commits:
commit 03c6b294a4517f5dfbc87504fceb3a88efef6a17
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sun Jul 12 03:55:23 2009 -0400

    Only destroy the regions when pixman_compute_composite_region() returns TRUE

diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index fddfb85..e2abcc2 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -498,9 +498,9 @@ _pixman_walk_composite_region (pixman_implementation_t *imp,
 			      width, height, FALSE, FALSE,
 			      &region,
 			      composite_rect);
-    }
 
-    pixman_region32_fini (&region);
+	pixman_region32_fini (&region);
+    }
 }
 
     
@@ -686,7 +686,8 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
 	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))
+		&region, src, mask, dest,
+		src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
 	{
 	    pixman_box32_t *extents = pixman_region32_extents (&region);
 
@@ -705,9 +706,9 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
 	    
 		result = TRUE;
 	    }
-	}
 	    
-	pixman_region32_fini (&region);
+	    pixman_region32_fini (&region);
+	}
     }
     
     return result;
commit 2af5f64e938f0d3b81f3f014441cdff650fe5457
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Jul 11 03:25:25 2009 -0400

    Move workaround logic to pixman-bits-image.c.
    
    Instead of computing whether a workaround is needed on every call to
    _pixman_run_fast_path(), just cache this information in the image.
    
    Also, when workarounds are needed, clip against the source geometry to
    prevent out of bound reads.

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index 8036705..977b172 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -727,6 +727,61 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image, int x, int y,
     }
 }
 
+static pixman_bool_t out_of_bounds_workaround = TRUE;
+
+/* Old X servers rely on out-of-bounds accesses when they are asked
+ * to composite with a window as the source. They create a pixman image
+ * pointing to some bogus position in memory, but then they set a clip
+ * region to the position where the actual bits are.
+ *
+ * Due to a bug in old versions of pixman, where it would not clip
+ * against the image bounds when a clip region was set, this would
+ * actually work. So by default we allow certain out-of-bound access
+ * to happen unless explicitly disabled.
+ *
+ * Fixed X servers should call this function to disable the workaround.
+ */
+PIXMAN_EXPORT void
+pixman_disable_out_of_bounds_workaround (void)
+{
+    out_of_bounds_workaround = FALSE;
+}
+
+static pixman_bool_t
+source_image_needs_out_of_bounds_workaround (bits_image_t *image)
+{
+    if (image->common.clip_sources			&&
+	image->common.repeat == PIXMAN_REPEAT_NONE	&&
+	out_of_bounds_workaround)
+    {
+	const pixman_box32_t *boxes;
+	int n;
+
+	if (!image->common.client_clip)
+	{
+	    /* There is no client clip, so the drawable in question
+	     * is a window if the clip region is different from the
+	     * full drawable
+	     */
+	    boxes = pixman_region32_rectangles (&image->common.clip_region, &n);
+	    if (n == 1)
+	    {
+		if (boxes[0].x1 == 0 && boxes[0].y1 == 0 &&
+		    boxes[0].x2 == image->width &&
+		    boxes[0].y2 == image->height)
+		{
+		    /* pixmap */
+		    return FALSE;
+		}
+	    }
+	}
+
+	return TRUE;
+    }
+	
+    return FALSE;
+}
+
 static void
 bits_image_property_changed (pixman_image_t *image)
 {
@@ -766,6 +821,9 @@ bits_image_property_changed (pixman_image_t *image)
 
     bits->store_scanline_64 = bits_image_store_scanline_64;
     bits->store_scanline_32 = bits_image_store_scanline_32;
+
+    bits->common.need_workaround =
+	source_image_needs_out_of_bounds_workaround (bits);
 }
 
 static uint32_t *
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index f95bf3f..d7020f2 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -115,6 +115,7 @@ _pixman_image_allocate (void)
 	common->client_clip = FALSE;
 	common->destroy_func = NULL;
 	common->destroy_data = NULL;
+	common->need_workaround = FALSE;
     }
 
     return image;
@@ -381,6 +382,8 @@ pixman_image_set_source_clipping (pixman_image_t  *image,
 				  pixman_bool_t    clip_sources)
 {
     image->common.clip_sources = clip_sources;
+
+    image_property_changed (image);
 }
 
 /* Unlike all the other property setters, this function does not
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index b0056c4..081d35c 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -71,6 +71,7 @@ struct image_common
     pixman_bool_t		clip_sources;	    /* Whether the clip applies when
 						     * the image is used as a source
 						     */
+    pixman_bool_t		need_workaround;
     pixman_transform_t	       *transform;
     pixman_repeat_t		repeat;
     pixman_filter_t		filter;
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index c7b97ef..fddfb85 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -30,26 +30,6 @@
 
 #include "pixman-private.h"
 
-static pixman_bool_t out_of_bounds_workaround = TRUE;
-
-/* Old X servers rely on out-of-bounds accesses when they are asked
- * to composite with a window as the source. They create a pixman image
- * pointing to some bogus position in memory, but then they set a clip
- * region to the position where the actual bits are.
- *
- * Due to a bug in old versions of pixman, where it would not clip
- * against the image bounds when a clip region was set, this would
- * actually work. So by default we allow certain out-of-bound access
- * to happen unless explicitly disabled.
- *
- * Fixed X servers should call this function to disable the workaround.
- */
-PIXMAN_EXPORT void
-pixman_disable_out_of_bounds_workaround (void)
-{
-    out_of_bounds_workaround = FALSE;
-}
-
 /*
  * Computing composite region
  */
@@ -105,13 +85,20 @@ clip_source_image (pixman_region32_t *	region,
 		  int		dx,
 		  int		dy)
 {
-    /* Source clips are ignored, unless they are explicitly turned on
-     * and the clip in question was set by an X client. (Because if
-     * the clip was not set by a client, then it is a hierarchy
-     * clip and those should always be ignored for sources).
+    /* The workaround lets certain fast paths run even when they
+     * would normally be rejected because of out-of-bounds access.
+     * We need to clip against the source geometry in that case
      */
-    if (!picture->common.clip_sources || !picture->common.client_clip)
-	return TRUE;
+    if (!picture->common.need_workaround)
+    {
+	/* Source clips are ignored, unless they are explicitly turned on
+	 * and the clip in question was set by an X client. (Because if
+	 * the clip was not set by a client, then it is a hierarchy
+	 * clip and those should always be ignored for sources).
+	 */
+	if (!picture->common.clip_sources || !picture->common.client_clip)
+	    return TRUE;
+    }
 
     return clip_general_image (region,
 			     &picture->common.clip_region,
@@ -157,7 +144,7 @@ pixman_compute_composite_region32 (pixman_region32_t *	region,
      *      pixman_disable_out_of_bounds_workaround();
      *
      */
-    if (!(dst_image->common.clip_sources && out_of_bounds_workaround))
+    if (!(dst_image->common.need_workaround))
     {
 	region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
 	region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
@@ -610,41 +597,6 @@ image_covers (pixman_image_t *image, pixman_box32_t *extents, int x, int y)
     return TRUE;
 }
 
-static pixman_bool_t
-source_image_needs_out_of_bounds_workaround (pixman_image_t *image)
-{
-    if (!out_of_bounds_workaround)
-	return FALSE;
-    
-    if (image->common.clip_sources		&&
-	!image->common.client_clip		&&
-	image->common.have_clip_region)
-    {
-	const pixman_box32_t *boxes;
-	int n;
-
-	/* There is no client clip, so the drawable in question
-	 * is a window if the clip region is different from the
-	 * full drawable
-	 */
-	boxes = pixman_region32_rectangles (&image->common.clip_region, &n);
-	if (n == 1)
-	{
-	    if (boxes[0].x1 == 0 && boxes[0].y1 == 0 &&
-		boxes[0].x2 == image->bits.width &&
-		boxes[0].y2 == image->bits.height)
-	    {
-		/* pixmap */
-		return FALSE;
-	    }
-	}
-
-	return TRUE;
-    }
-	
-    return FALSE;
-}
-
 pixman_bool_t
 _pixman_run_fast_path (const pixman_fast_path_t *paths,
 		       pixman_implementation_t *imp,
@@ -740,7 +692,7 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
 
 	    if ((image_covers (src, extents, dest_x - src_x, dest_y - src_y)   &&
 		 (!mask || image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))) ||
-		source_image_needs_out_of_bounds_workaround (src))
+		src->common.need_workaround)
 	    {
 		walk_region_internal (imp, op,
 				      src, mask, dest,


More information about the xorg-commit mailing list