From 5750408e48259f42373a5233231104d9bd3eb35a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 12 Mar 2010 15:41:01 +0100 Subject: Add FAST_PATH_SAMPLES_COVER_CLIP and FAST_PATH_16BIT_SAFE FAST_PATH_SAMPLES_COVER_CLIP: This is set of the source sample grid, unrepeated but transformed completely completely covers the clip destination. If this is set you can use a simple scaled that doesn't have to care about the repeat mode. FAST_PATH_16BIT_SAFE: This signifies two things: 1) The size of the src/mask fits in a 16.16 fixed point, so something like: max_vx = src_image->bits.width << 16; Is allowed and is guaranteed to not overflow max_vx 2) When stepping the source space we're guaranteed to never overflow a 16.16 bit fix point variable, even if we step one extra step in the destination space. This means that a loop doing: x = vx >> 16; vx += unit_x; d = src_row[x]; will never overflow vx causing x to be negative. And additionally, if you track vx like above and apply NORMAL repeat after the vx addition with something like: while (vx >= max_vx) vx -= max_vx; This will never overflow the vx even on the final increment that takes vx one past the end of where we will read, which makes the repeat loop safe. --- pixman/pixman-private.h | 2 ++ pixman/pixman.c | 84 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 65314b9..0cf9113 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -580,6 +580,8 @@ _pixman_choose_implementation (void); #define FAST_PATH_IS_OPAQUE (1 << 13) #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_STANDARD_FLAGS \ (FAST_PATH_ID_TRANSFORM | \ diff --git a/pixman/pixman.c b/pixman/pixman.c index 68483a0..56c9536 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -479,24 +479,75 @@ walk_region_internal (pixman_implementation_t *imp, } } -static force_inline pixman_bool_t -image_covers (pixman_image_t *image, - pixman_box32_t *extents, - int x, - int y) +#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) { - if (image->common.type == BITS && - image->common.repeat == PIXMAN_REPEAT_NONE) + 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)) { - if (x > extents->x1 || y > extents->y1 || - x + image->bits.width < extents->x2 || - y + image->bits.height < extents->y2) + 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)) { - return FALSE; + if (extents16.x1 >= 0 && extents16.y1 >= 0 && + extents16.x2 <= image->bits.width && + extents16.y2 <= image->bits.height) + { + flags |= FAST_PATH_SAMPLES_COVER_CLIP; + } } } - return TRUE; + 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 @@ -588,11 +639,10 @@ do_composite (pixman_implementation_t *imp, extents = pixman_region32_extents (®ion); - if (image_covers (src, extents, dest_x - src_x, dest_y - src_y)) - src_flags |= FAST_PATH_COVERS_CLIP; - - if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y)) - mask_flags |= FAST_PATH_COVERS_CLIP; + 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); /* * Check if we can replace our operator by a simpler one -- cgit v1.2.3