From: Søren Sandmann Pedersen Date: Sat, 11 Jul 2009 07:25:25 +0000 (-0400) Subject: Move workaround logic to pixman-bits-image.c. X-Git-Tag: 1.0_branch~899 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2af5f64e938f0d3b81f3f014441cdff650fe5457;p=profile%2Fivi%2Fpixman.git 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,