Patch 1

-- 
Best Regards,
Taekyun Kim
From 8c9595afee02aa605b5cb7429653a29354001a09 Mon Sep 17 00:00:00 2001
From: Taekyun Kim <[email protected]>
Date: Wed, 11 May 2011 21:10:58 +0900
Subject: [PATCH 1/5] REPEAT_NORMAL support for nearest/bilinear fast path template

Break down repeat into a set of non-repeat scanline composition.
Bilinear may require (tail, head) source pixels to interpolate
at the end of source scanline.
In this case, we give wrap-around temp buffers to scanline function.
So scanline functions do not need to concern about repeat.
To avoid frequent function calls, we construct pre-repeated temporary
source scanline buffers if src width is smaller than some constant.
---
 pixman/pixman-fast-path.h |  173 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 160 insertions(+), 13 deletions(-)

diff --git a/pixman/pixman-fast-path.h b/pixman/pixman-fast-path.h
index 1885d47..096b2ce 100644
--- a/pixman/pixman-fast-path.h
+++ b/pixman/pixman-fast-path.h
@@ -29,6 +29,7 @@
 #include "pixman-private.h"
 
 #define PIXMAN_REPEAT_COVER -1
+#define PIXMAN_REPEAT_NORMAL_MIN_WIDTH	8
 
 static force_inline pixman_bool_t
 repeat (pixman_repeat_t repeat, int *c, int size)
@@ -271,7 +272,6 @@ fast_composite_scaled_nearest  ## scale_func_name (pixman_implementation_t *imp,
     src_type_t *src_first_line;									\
     int       y;										\
     pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */		\
-    pixman_fixed_t max_vy;									\
     pixman_vector_t v;										\
     pixman_fixed_t vx, vy;									\
     pixman_fixed_t unit_x, unit_y;								\
@@ -314,16 +314,6 @@ fast_composite_scaled_nearest  ## scale_func_name (pixman_implementation_t *imp,
     vx = v.vector[0];										\
     vy = v.vector[1];										\
 												\
-    if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL)					\
-    {												\
-	/* Clamp repeating positions inside the actual samples */				\
-	max_vx = src_image->bits.width << 16;							\
-	max_vy = src_image->bits.height << 16;							\
-												\
-	repeat (PIXMAN_REPEAT_NORMAL, &vx, max_vx);						\
-	repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy);						\
-    }												\
-												\
     if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD ||					\
 	PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE)					\
     {												\
@@ -344,8 +334,6 @@ fast_composite_scaled_nearest  ## scale_func_name (pixman_implementation_t *imp,
 												\
 	y = vy >> 16;										\
 	vy += unit_y;										\
-	if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL)				\
-	    repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy);						\
 	if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD)					\
 	{											\
 	    repeat (PIXMAN_REPEAT_PAD, &y, src_image->bits.height);				\
@@ -390,6 +378,54 @@ fast_composite_scaled_nearest  ## scale_func_name (pixman_implementation_t *imp,
 			       dst + left_pad + width, zero, right_pad, 0, 0, 0, TRUE);		\
 	    }											\
 	}											\
+        else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL)                         \
+        {                                                                                       \
+            int32_t         new_src_width;                                                      \
+            pixman_fixed_t  new_src_width_fixed;                                                \
+            int32_t         width_remain;                                                       \
+            int32_t         num_pixels;                                                         \
+            int32_t         i, j;                                                               \
+            src_type_t      *src_line;                                                          \
+            src_type_t      expended_src[PIXMAN_REPEAT_NORMAL_MIN_WIDTH*2];                     \
+            vx = v.vector[0];                                                                   \
+            repeat (PIXMAN_REPEAT_NORMAL, &y, src_image->bits.height);                          \
+            src_line = src_first_line + src_stride * y;                                         \
+	    /* Prevent frequent scanline function call by pre-repeating				\
+	     * src into temporary buffer */							\
+            if (src_image->bits.width < PIXMAN_REPEAT_NORMAL_MIN_WIDTH)                         \
+            {                                                                                   \
+                for (i=0; i<PIXMAN_REPEAT_NORMAL_MIN_WIDTH; )                                   \
+                {                                                                               \
+                    for (j=0; j<src_image->bits.width; j++, i++)                                \
+                    {                                                                           \
+                        expended_src[i] = src_line[j];                                          \
+                    }                                                                           \
+                }                                                                               \
+                new_src_width = i;                                                              \
+                src_line = &expended_src[0];                                                    \
+            }                                                                                   \
+            else                                                                                \
+            {                                                                                   \
+                new_src_width = src_image->bits.width;                                          \
+            }                                                                                   \
+            new_src_width_fixed  = pixman_int_to_fixed (new_src_width);                         \
+            width_remain = width;                                                               \
+            while (width_remain > 0 )                                                           \
+            {                                                                                   \
+                repeat (PIXMAN_REPEAT_NORMAL, &vx, new_src_width_fixed);                        \
+		/* num_pixels = max(n), where  vx + (n - 1)*unit_x < width_fixed */		\
+                num_pixels = (new_src_width_fixed - vx + unit_x - pixman_fixed_e) / unit_x;     \
+                if (num_pixels > width_remain)                                                  \
+                    num_pixels = width_remain;                                                  \
+                scanline_func (mask, dst, src_line, num_pixels, vx, unit_x,                     \
+                               new_src_width_fixed, FALSE);                                     \
+                width_remain -= num_pixels;                                                     \
+                vx += num_pixels * unit_x;                                                      \
+                dst += num_pixels;                                                              \
+                if (have_mask && !mask_is_solid)                                                \
+                    mask += num_pixels;                                                         \
+            }                                                                                   \
+        }                                                                                       \
 	else											\
 	{											\
 	    src = src_first_line + src_stride * y;						\
@@ -888,6 +924,84 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 			       buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, TRUE);		\
 	    }											\
 	}											\
+        else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL)                         \
+        {                                                                                       \
+	    int32_t	    new_src_width;							\
+	    pixman_fixed_t  new_src_width_fixed;						\
+            int32_t         num_pixels;                                                         \
+	    int32_t	    width_remain;							\
+	    int32_t	    i, j;								\
+            src_type_t      *src_line_top;                                                      \
+            src_type_t      *src_line_bottom;                                                   \
+            src_type_t      buf1[2];								\
+            src_type_t      buf2[2];								\
+	    src_type_t	    expended_top[PIXMAN_REPEAT_NORMAL_MIN_WIDTH*2];			\
+	    src_type_t	    expended_bottom[PIXMAN_REPEAT_NORMAL_MIN_WIDTH*2];			\
+            repeat (PIXMAN_REPEAT_NORMAL, &y1, src_image->bits.height);                         \
+            repeat (PIXMAN_REPEAT_NORMAL, &y2, src_image->bits.height);                         \
+            src_line_top = src_first_line + src_stride * y1;                                    \
+            src_line_bottom = src_first_line + src_stride * y2;                                 \
+	    /* Top & Bottom wrap around buffer */						\
+            buf1[0] = src_line_top[src_image->bits.width - 1];					\
+            buf1[1] = src_line_top[0];								\
+            buf2[0] = src_line_bottom[src_image->bits.width - 1];				\
+            buf2[1] = src_line_bottom[0];							\
+	    if (src_image->bits.width < PIXMAN_REPEAT_NORMAL_MIN_WIDTH)				\
+	    {											\
+		for (i=0; i<PIXMAN_REPEAT_NORMAL_MIN_WIDTH; )					\
+		{										\
+		    for (j=0; j<src_image->bits.width; j++, i++ )				\
+		    {										\
+			expended_top[i] = src_line_top[j];					\
+			expended_bottom[i] = src_line_bottom[j];				\
+		    }										\
+		}										\
+		new_src_width = i;								\
+		src_line_top = &expended_top[0];						\
+		src_line_bottom = &expended_bottom[0];						\
+	    }											\
+	    else										\
+	    {											\
+		new_src_width = src_image->bits.width;						\
+	    }											\
+	    new_src_width_fixed = pixman_int_to_fixed(new_src_width);				\
+	    width_remain = width;								\
+            while (width_remain > 0)                                                            \
+            {                                                                                   \
+                repeat (PIXMAN_REPEAT_NORMAL, &vx, new_src_width_fixed);			\
+		/* Wrap around part */								\
+                if (pixman_fixed_to_int (vx) == new_src_width - 1)				\
+                {                                                                               \
+                    num_pixels  = (new_src_width_fixed - vx + unit_x - pixman_fixed_e) / unit_x;\
+                    if (num_pixels > width_remain)                                              \
+                        num_pixels = width_remain;                                              \
+	            scanline_func (dst, mask, buf1, buf2, num_pixels,				\
+			           weight1, weight2, pixman_fixed_frac(vx),                     \
+                                   unit_x, max_vx, FALSE);                                      \
+                    width_remain -= num_pixels;                                                 \
+                    vx += num_pixels * unit_x;                                                  \
+                    dst += num_pixels;                                                          \
+                    if (have_mask && !mask_is_solid)						\
+		        mask += num_pixels;							\
+                    repeat (PIXMAN_REPEAT_NORMAL, &vx, new_src_width_fixed);			\
+                }                                                                               \
+		/* Normal scanline composite */							\
+                if (pixman_fixed_to_int (vx) != new_src_width - 1 && width_remain > 0)		\
+                {                                                                               \
+                    num_pixels = (new_src_width_fixed - pixman_fixed_1 - vx			\
+				  + unit_x - pixman_fixed_e) / unit_x;				\
+                    if (num_pixels > width_remain)                                              \
+                        num_pixels = width_remain;                                              \
+	            scanline_func (dst, mask, src_line_top, src_line_bottom, num_pixels,	\
+			           weight1, weight2, vx, unit_x, max_vx, FALSE);		\
+                    width_remain -= num_pixels;                                                 \
+                    vx += num_pixels * unit_x;                                                  \
+                    dst += num_pixels;                                                          \
+                    if (have_mask && !mask_is_solid)						\
+		        mask += num_pixels;							\
+                }                                                                               \
+            }                                                                                   \
+        }                                                                                       \
 	else											\
 	{											\
 	    scanline_func (dst, mask, src_first_line + src_stride * y1,				\
@@ -941,6 +1055,17 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 	fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op,	\
     }
 
+#define SIMPLE_BILINEAR_FAST_PATH_NORMAL(op,s,d,func)			\
+    {   PIXMAN_OP_ ## op,						\
+	PIXMAN_ ## s,							\
+	(SCALED_BILINEAR_FLAGS		|				\
+	 FAST_PATH_NORMAL_REPEAT	|				\
+	 FAST_PATH_X_UNIT_POSITIVE),					\
+	PIXMAN_null, 0,							\
+	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				\
+	fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op,	\
+    }
+
 #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD(op,s,d,func)		\
     {   PIXMAN_OP_ ## op,						\
 	PIXMAN_ ## s,							\
@@ -972,6 +1097,17 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 	fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op,	\
     }
 
+#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NORMAL(op,s,d,func)		\
+    {   PIXMAN_OP_ ## op,						\
+	PIXMAN_ ## s,							\
+	(SCALED_BILINEAR_FLAGS		|				\
+	 FAST_PATH_NORMAL_REPEAT	|				\
+	 FAST_PATH_X_UNIT_POSITIVE),					\
+	PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA),		\
+	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				\
+	fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op,	\
+    }
+
 #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD(op,s,d,func)		\
     {   PIXMAN_OP_ ## op,						\
 	PIXMAN_ ## s,							\
@@ -1003,6 +1139,17 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 	fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op,	\
     }
 
+#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NORMAL(op,s,d,func)	\
+    {   PIXMAN_OP_ ## op,						\
+	PIXMAN_ ## s,							\
+	(SCALED_BILINEAR_FLAGS		|				\
+	 FAST_PATH_NORMAL_REPEAT	|				\
+	 FAST_PATH_X_UNIT_POSITIVE),					\
+	PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA),	\
+	PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS,				\
+	fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op,	\
+    }
+
 /* Prefer the use of 'cover' variant, because it is faster */
 #define SIMPLE_BILINEAR_FAST_PATH(op,s,d,func)				\
     SIMPLE_BILINEAR_FAST_PATH_COVER (op,s,d,func),			\
-- 
1.7.1

_______________________________________________
Pixman mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/pixman

Reply via email to