diff options
author | Alexander Larsson <alexl@redhat.com> | 2010-03-12 15:41:01 +0100 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-03-17 11:03:05 -0400 |
commit | 5750408e48259f42373a5233231104d9bd3eb35a (patch) | |
tree | 91c34072dfdc3736fee726731fb378c0dda9af16 | |
parent | cba6fbbddce5edfd8e28ef570c493b044761f870 (diff) |
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.
-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 |