summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-03-12 15:41:01 +0100
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-03-17 11:03:05 -0400
commit5750408e48259f42373a5233231104d9bd3eb35a (patch)
tree91c34072dfdc3736fee726731fb378c0dda9af16
parentcba6fbbddce5edfd8e28ef570c493b044761f870 (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.h2
-rw-r--r--pixman/pixman.c84
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 (&region);
- 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