From 05875eca09ee23ea04ccb32f87c7c355fd1b88f3 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Tue, 16 Mar 2010 16:55:28 +0100 Subject: [PATCH 1/7] Generic C implementation of pixman_blt with overlapping support Uses memcpy/memmove functions to copy pixels, can handle the case when both source and destination areas are in the same image (this is useful for scrolling). It is assumed that copying direction is only important when using the same image for both source and destination (and src_stride == dst_stride). Copying direction is undefined for the images with different source and destination stride which happen to be in the overlapped areas (but this is an unrealistic case anyway). --- pixman/pixman-general.c | 21 ++++++++++++++++++--- pixman/pixman-private.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index bddf79a..f525744 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -285,9 +285,24 @@ general_blt (pixman_implementation_t *imp, int width, int height) { - /* We can't blit unless we have sse2 or mmx */ - - return FALSE; + uint8_t *dst_bytes = (uint8_t *)dst_bits; + uint8_t *src_bytes = (uint8_t *)src_bits; + int bpp; + + if (src_bpp != dst_bpp || src_bpp & 7) + return FALSE; + + bpp = src_bpp >> 3; + width *= bpp; + src_stride *= 4; + dst_stride *= 4; + pixman_blt_helper (src_bytes + src_y * src_stride + src_x * bpp, + dst_bytes + dst_y * dst_stride + dst_x * bpp, + src_stride, + dst_stride, + width, + height); + return TRUE; } static pixman_bool_t diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d5767af..eeb677d 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -10,6 +10,7 @@ #include "pixman.h" #include +#include #include #include #include @@ -867,4 +868,46 @@ void pixman_timer_register (pixman_timer_t *timer); #endif /* PIXMAN_TIMERS */ +/* a helper function, can blit 8-bit images with src/dst overlapping support */ +static inline void +pixman_blt_helper (uint8_t *src_bytes, + uint8_t *dst_bytes, + int src_stride, + int dst_stride, + int width, + int height) +{ + /* + * The second part of this check is not strictly needed, but it prevents + * unnecessary upside-down processing of areas which belong to different + * images. Upside-down processing can be slower with fixed-distance-ahead + * prefetch and perceived as having more tearing. + */ + if (src_bytes < dst_bytes + width && + src_bytes + src_stride * height > dst_bytes) + { + src_bytes += src_stride * height - src_stride; + dst_bytes += dst_stride * height - dst_stride; + dst_stride = -dst_stride; + src_stride = -src_stride; + /* Horizontal scrolling to the left needs memmove */ + if (src_bytes + width > dst_bytes) + { + while (--height >= 0) + { + memmove (dst_bytes, src_bytes, width); + dst_bytes += dst_stride; + src_bytes += src_stride; + } + return; + } + } + while (--height >= 0) + { + memcpy (dst_bytes, src_bytes, width); + dst_bytes += dst_stride; + src_bytes += src_stride; + } +} + #endif /* PIXMAN_PRIVATE_H */ -- 1.6.6.1