diff options
-rw-r--r-- | pixman/pixman-private.h | 2 | ||||
-rw-r--r-- | pixman/pixman.c | 84 |
2 files changed, 69 insertions, 17 deletions
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 65314b91..0cf91134 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 68483a02..56c95368 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 |