Patch 1.

-- 
Best Regards,
Taekyun Kim
From 03b65ed8deb473e096b8880ac461147fc5ac6b83 Mon Sep 17 00:00:00 2001
From: Taekyun Kim <[email protected]>
Date: Tue, 31 May 2011 15:18:16 +0900
Subject: [PATCH 1/2] REPEAT_NORMAL support for bilinear fast path template

The basic idea is to break down normal repeat into a set of
non-repeat scanline compositions and stitching them together.

To avoid function call overhead, when width of source image is
too small, extend source scanline into temporary buffer, so total
function calls per scanline can be reduced.

Bilinear may interpolate last and first pixels. In this case, we
use temporary wrap around buffer.

We can now give "flags" to template  instead of some boolean
values. have_mask and mask_is_solid is now substituted by
FLAG_HAVE_SOLID_MASK and FLAG_HAVE_NON_SOLID_MASK. Flags can be
easily extended to write more optimized special case handling
codes.
---
 pixman/pixman-arm-common.h |   27 +++-
 pixman/pixman-fast-path.h  |  365 +++++++++++++++++++++++++++++++++++++++-----
 pixman/pixman-sse2.c       |   10 +-
 3 files changed, 350 insertions(+), 52 deletions(-)

diff --git a/pixman/pixman-arm-common.h b/pixman/pixman-arm-common.h
index 6cd8be5..85b51bf 100644
--- a/pixman/pixman-arm-common.h
+++ b/pixman/pixman-arm-common.h
@@ -398,13 +398,20 @@ scaled_bilinear_scanline_##cputype##_##name##_##op (                          \
                                                                               \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                 \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, COVER, FALSE, FALSE)     \
+                       src_type, uint32_t, dst_type, COVER,                   \
+                       FLAG_NONE)                                             \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                  \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, NONE, FALSE, FALSE)      \
+                       src_type, uint32_t, dst_type, NONE,                    \
+                       FLAG_NONE)                                             \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                   \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, PAD, FALSE, FALSE)
+                       src_type, uint32_t, dst_type, PAD,                     \
+                       FLAG_NONE)                                             \
+FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op,                \
+                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
+                       src_type, uint32_t, dst_type, NORMAL,                  \
+                       FLAG_NONE)
 
 
 #define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, cputype, name, op,  \
@@ -443,12 +450,18 @@ scaled_bilinear_scanline_##cputype##_##name##_##op (                          \
                                                                               \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                 \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint8_t, dst_type, COVER, TRUE, FALSE)       \
+                       src_type, uint8_t, dst_type, COVER,                    \
+                       FLAG_HAVE_NON_SOLID_MASK)                              \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                  \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint8_t, dst_type, NONE, TRUE, FALSE)        \
+                       src_type, uint8_t, dst_type, NONE,                     \
+                       FLAG_HAVE_NON_SOLID_MASK)                              \
 FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                   \
                        scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
-
+                       src_type, uint8_t, dst_type, PAD,                      \
+                       FLAG_HAVE_NON_SOLID_MASK)                              \
+FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op,                \
+                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
+                       src_type, uint8_t, dst_type, NORMAL,                   \
+                       FLAG_HAVE_NON_SOLID_MASK)
 #endif
diff --git a/pixman/pixman-fast-path.h b/pixman/pixman-fast-path.h
index 1885d47..b994d40 100644
--- a/pixman/pixman-fast-path.h
+++ b/pixman/pixman-fast-path.h
@@ -30,6 +30,37 @@
 
 #define PIXMAN_REPEAT_COVER -1
 
+/* To avoid too short repeated scanline function calls, extend source
+ * scanlines having width less than below constant value.
+ */
+#define REPEAT_NORMAL_MIN_WIDTH			8
+
+/* Flags describing input parameters to fast path macro template.
+ * Turning on some flag values may indicate that
+ * "some property X is available so template can use this" or
+ * "some property X should be handled by template".
+ *
+ * FLAG_SCANLINE_SUPPORT_REPEAT_NORMAL
+ *  Scanline function can handle repeat normal inside the scanline
+ *  function.
+ *
+ * FLAG_HAVE_SOLID_MASK
+ *  Input mask is solid so template should handle this.
+ *
+ * FLAG_HAVE_NON_SOLID_MASK
+ *  Input mask is bits mask so template should handle this.
+ *
+ * FLAG_HAVE_SOLID_MASK and FLAG_HAVE_NON_SOLID_MASK are mutually
+ * exclusive. (It's not allowed to turn both flags on)
+ *
+ * FLAG_SCANLINE_SUPPORT_REPEAT_NORMAL is not used yet,
+ * but functions supporting these flags can be implemented later.
+ */
+#define FLAG_NONE				(0)
+#define FLAG_SCANLINE_SUPPORT_REPEAT_NORMAL	(1 <<   1)
+#define FLAG_HAVE_SOLID_MASK			(1 <<   2)
+#define FLAG_HAVE_NON_SOLID_MASK		(1 <<   3)
+
 static force_inline pixman_bool_t
 repeat (pixman_repeat_t repeat, int *c, int size)
 {
@@ -661,7 +692,7 @@ bilinear_pad_repeat_get_scanline_bounds (int32_t         source_image_width,
  *       multiplication instructions.
  */
 #define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t,	\
-				  dst_type_t, repeat_mode, have_mask, mask_is_solid)		\
+				  dst_type_t, repeat_mode, flags)				\
 static void											\
 fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,		\
 						   pixman_op_t              op,			\
@@ -677,38 +708,30 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 						   int32_t                  width,		\
 						   int32_t                  height)		\
 {												\
-    dst_type_t *dst_line;									\
-    mask_type_t *mask_line;									\
-    src_type_t *src_first_line;									\
-    int       y1, y2;										\
-    pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */		\
-    pixman_vector_t v;										\
-    pixman_fixed_t vx, vy;									\
-    pixman_fixed_t unit_x, unit_y;								\
-    int32_t left_pad, left_tz, right_tz, right_pad;						\
+    src_type_t *    src_first_line;								\
+    src_type_t *    prev_src_line0 = NULL;							\
+    src_type_t *    prev_src_line1 = NULL;							\
+    src_type_t      extended_src_line0[REPEAT_NORMAL_MIN_WIDTH*2];				\
+    src_type_t      extended_src_line1[REPEAT_NORMAL_MIN_WIDTH*2];				\
+    int32_t         src_stride;									\
 												\
-    dst_type_t *dst;										\
-    mask_type_t solid_mask;									\
-    const mask_type_t *mask = &solid_mask;							\
-    int src_stride, mask_stride, dst_stride;							\
+    mask_type_t *   mask;									\
+    mask_type_t *   mask_line;									\
+    mask_type_t     solid_mask;									\
+    int32_t         mask_stride;								\
 												\
-    PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1);	\
-    if (have_mask)										\
-    {												\
-	if (mask_is_solid)									\
-	{											\
-	    solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format);	\
-	    mask_stride = 0;									\
-	}											\
-	else											\
-	{											\
-	    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t,			\
-				   mask_stride, mask_line, 1);					\
-	}											\
-    }												\
-    /* pass in 0 instead of src_x and src_y because src_x and src_y need to be			\
-     * transformed from destination space to source space */					\
-    PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1);		\
+    dst_type_t *    dst;									\
+    dst_type_t *    dst_line;									\
+    int32_t         dst_stride;									\
+												\
+    int32_t         y1, y2;									\
+    pixman_vector_t v;										\
+    pixman_fixed_t  vx, vy;									\
+    pixman_fixed_t  unit_x, unit_y;								\
+    int32_t         src_width;									\
+    int32_t         src_width_fixed;								\
+												\
+    int32_t left_pad, left_tz, right_tz, right_pad;						\
 												\
     /* reference point is the center of the pixel */						\
     v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2;				\
@@ -724,13 +747,31 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
     v.vector[0] -= pixman_fixed_1 / 2;								\
     v.vector[1] -= pixman_fixed_1 / 2;								\
 												\
-    vy = v.vector[1];										\
+    PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1);		\
+    PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1);	\
 												\
+    if (flags & FLAG_HAVE_NON_SOLID_MASK)							\
+    {												\
+	PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t,				\
+			       mask_stride, mask_line, 1);					\
+    }												\
+    else if (flags & FLAG_HAVE_SOLID_MASK)							\
+    {												\
+	solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format);		\
+	mask_stride = 0;									\
+    }												\
+    else											\
+    {												\
+	mask = NULL;										\
+	mask_stride = 0;									\
+    }												\
+    												\
     if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD ||					\
 	PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE)					\
     {												\
 	bilinear_pad_repeat_get_scanline_bounds (src_image->bits.width, v.vector[0], unit_x,	\
 					&left_pad, &left_tz, &width, &right_tz, &right_pad);	\
+												\
 	if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD)					\
 	{											\
 	    /* PAD repeat does not need special handling for 'transition zones' and */		\
@@ -739,16 +780,35 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 	    right_pad += right_tz;								\
 	    left_tz = right_tz = 0;								\
 	}											\
+												\
 	v.vector[0] += left_pad * unit_x;							\
     }												\
 												\
+    if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL &&				\
+	!(flags & FLAG_SCANLINE_SUPPORT_REPEAT_NORMAL) &&					\
+	src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH)					\
+    {												\
+	/* We will construct extended source scanlines in this case */				\
+	src_width = 0;										\
+												\
+	while (src_width < REPEAT_NORMAL_MIN_WIDTH)						\
+	    src_width += src_image->bits.width;							\
+    }												\
+    else											\
+    {												\
+	src_width = src_image->bits.width;							\
+    }												\
+												\
+    vy = v.vector[1];										\
+    src_width_fixed = pixman_int_to_fixed (src_width);						\
+												\
     while (--height >= 0)									\
     {												\
 	int weight1, weight2;									\
 	dst = dst_line;										\
 	dst_line += dst_stride;									\
 	vx = v.vector[0];									\
-	if (have_mask && !mask_is_solid)							\
+	if (flags & FLAG_HAVE_NON_SOLID_MASK)							\
 	{											\
 	    mask = mask_line;									\
 	    mask_line += mask_stride;								\
@@ -786,7 +846,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 		scanline_func (dst, mask,							\
 			       buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, FALSE);		\
 		dst += left_pad;								\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += left_pad;								\
 	    }											\
 	    if (width > 0)									\
@@ -794,7 +854,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 		scanline_func (dst, mask,							\
 			       src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE);	\
 		dst += width;									\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += width;								\
 	    }											\
 	    if (right_pad > 0)									\
@@ -841,7 +901,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 		scanline_func (dst, mask,							\
 			       buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, TRUE);		\
 		dst += left_pad;								\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += left_pad;								\
 	    }											\
 	    if (left_tz > 0)									\
@@ -854,7 +914,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 			       buf1, buf2, left_tz, weight1, weight2,				\
 			       pixman_fixed_frac (vx), unit_x, 0, FALSE);			\
 		dst += left_tz;									\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += left_tz;								\
 		vx += left_tz * unit_x;								\
 	    }											\
@@ -863,7 +923,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 		scanline_func (dst, mask,							\
 			       src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE);	\
 		dst += width;									\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += width;								\
 		vx += width * unit_x;								\
 	    }											\
@@ -877,7 +937,7 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp,
 			       buf1, buf2, right_tz, weight1, weight2,				\
 			       pixman_fixed_frac (vx), unit_x, 0, FALSE);			\
 		dst += right_tz;								\
-		if (have_mask && !mask_is_solid)						\
+		if (flags & FLAG_HAVE_NON_SOLID_MASK)						\
 		    mask += right_tz;								\
 	    }											\
 	    if (right_pad > 0)									\
@@ -888,20 +948,208 @@ 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         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 *    src_top = NULL;							\
+	    src_type_t *    src_bottom = NULL;							\
+	    src_type_t      buf1[2];								\
+	    src_type_t      buf2[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;					\
+												\
+	    if (flags & FLAG_SCANLINE_SUPPORT_REPEAT_NORMAL)					\
+	    {											\
+		/* If scanline support REPEAT_NORMAL just pass positive vx and source lines */	\
+		repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed);				\
+		scanline_func (dst, mask, src_line_top, src_line_bottom, width,			\
+    			       weight1, weight2, vx, unit_x, src_width_fixed, FALSE);		\
+		continue;									\
+	    }											\
+												\
+	    if (src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH)				\
+	    {											\
+		/* Reuse previously extended source scanlines if it's not changed */		\
+		if (src_line_top == prev_src_line0)						\
+		    src_top = &extended_src_line0[0];						\
+		else if (src_line_top == prev_src_line1)					\
+		    src_top = &extended_src_line1[0];						\
+												\
+		if (src_line_bottom == prev_src_line0)						\
+		    src_bottom = &extended_src_line0[0];					\
+		else if (src_line_bottom == prev_src_line1)					\
+		    src_bottom = &extended_src_line1[0];					\
+												\
+		/* If there's no reusable scanlines, make new extended source scanlines */	\
+		if (src_top == NULL && src_bottom == NULL)					\
+		{										\
+		    for (i=0; i<REPEAT_NORMAL_MIN_WIDTH; )					\
+		    {										\
+			for (j=0; j<src_image->bits.width; j++, i++)				\
+			{									\
+			    extended_src_line0[i] = src_line_top[j];				\
+			    extended_src_line1[i] = src_line_bottom[j];				\
+			}									\
+		    }										\
+												\
+		    src_top = &extended_src_line0[0];						\
+		    src_bottom = &extended_src_line1[0];					\
+		    prev_src_line0 = src_line_top;						\
+		    prev_src_line1 = src_line_bottom;						\
+		}										\
+		else if (src_top == NULL)							\
+		{										\
+		    if (src_bottom == &extended_src_line0[0])					\
+		    {										\
+			for (i=0; i<REPEAT_NORMAL_MIN_WIDTH; )					\
+			{									\
+			    for (j=0; j<src_image->bits.width; j++, i++)			\
+			    {									\
+				extended_src_line1[i] = src_line_top[j];			\
+			    }									\
+			}									\
+												\
+			src_top = &extended_src_line1[0];					\
+			prev_src_line1 = src_line_top;						\
+		    }										\
+		    else									\
+		    {										\
+			for (i=0; i<REPEAT_NORMAL_MIN_WIDTH; )					\
+			{									\
+			    for (j=0; j<src_image->bits.width; j++, i++)			\
+			    {									\
+				extended_src_line0[i] = src_line_top[j];			\
+			    }									\
+			}									\
+												\
+			src_top = &extended_src_line0[0];					\
+			prev_src_line0 = src_line_top;						\
+		    }										\
+		}										\
+		else if (src_bottom == NULL)							\
+		{										\
+		    if (src_top == &extended_src_line0[0])					\
+		    {										\
+			for (i=0; i<REPEAT_NORMAL_MIN_WIDTH; )					\
+			{									\
+			    for (j=0; j<src_image->bits.width; j++, i++)			\
+			    {									\
+				extended_src_line1[i] = src_line_bottom[j];			\
+			    }									\
+			}									\
+												\
+			src_bottom = &extended_src_line1[0];					\
+			prev_src_line1 = src_line_bottom;					\
+		    }										\
+		    else									\
+		    {										\
+			for (i=0; i<REPEAT_NORMAL_MIN_WIDTH; )					\
+			{									\
+			    for (j=0; j<src_image->bits.width; j++, i++)			\
+			    {									\
+				extended_src_line0[i] = src_line_bottom[j];			\
+			    }									\
+			}									\
+												\
+			src_bottom = &extended_src_line0[0];					\
+			prev_src_line0 = src_line_bottom;					\
+		    }										\
+		}										\
+	    }											\
+	    else										\
+	    {											\
+		src_top = src_line_top;								\
+		src_bottom = src_line_bottom;							\
+	    }											\
+												\
+	    /* 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];							\
+												\
+	    width_remain = width;								\
+												\
+	    while (width_remain > 0)								\
+	    {											\
+		repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed);				\
+												\
+		/* Wrap around part */								\
+		if (pixman_fixed_to_int (vx) == src_width - 1)					\
+		{										\
+		    /* for positive unit_x							\
+		     * num_pixels = max(n) + 1, where vx + n*unit_x < src_width_fixed		\
+		     *										\
+		     * vx is in range [0, src_width_fixed - pixman_fixed_e]			\
+		     * So we are safe from overflow.						\
+		     */										\
+		    num_pixels = ((src_width_fixed - vx - pixman_fixed_e) / unit_x) + 1;	\
+												\
+		    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, src_width_fixed, FALSE);				\
+												\
+		    width_remain -= num_pixels;							\
+		    vx += num_pixels * unit_x;							\
+		    dst += num_pixels;								\
+												\
+		    if (flags & FLAG_HAVE_NON_SOLID_MASK)					\
+			mask += num_pixels;							\
+												\
+		    repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed);			\
+		}										\
+												\
+		/* Normal scanline composite */							\
+		if (pixman_fixed_to_int (vx) != src_width - 1 && width_remain > 0)		\
+		{										\
+		    /* for positive unit_x							\
+		     * num_pixels = max(n) + 1, where vx + n*unit_x < (src_width_fixed - 1)	\
+		     *										\
+		     * vx is in range [0, src_width_fixed - pixman_fixed_e]			\
+		     * So we are safe from overflow here.					\
+		     */										\
+		    num_pixels = ((src_width_fixed - pixman_fixed_1 - vx - pixman_fixed_e)	\
+				  / unit_x) + 1;						\
+												\
+		    if (num_pixels > width_remain)						\
+			num_pixels = width_remain;						\
+												\
+		    scanline_func (dst, mask, src_top, src_bottom, num_pixels,			\
+				   weight1, weight2, vx, unit_x, src_width_fixed, FALSE);	\
+												\
+		    width_remain -= num_pixels;							\
+		    vx += num_pixels * unit_x;							\
+		    dst += num_pixels;								\
+												\
+		    if (flags & FLAG_HAVE_NON_SOLID_MASK)					\
+		        mask += num_pixels;							\
+		}										\
+	    }											\
+	}											\
 	else											\
 	{											\
 	    scanline_func (dst, mask, src_first_line + src_stride * y1,				\
 			   src_first_line + src_stride * y2, width,				\
-			   weight1, weight2, vx, unit_x, max_vx, FALSE);			\
+			   weight1, weight2, vx, unit_x, src_width_fixed, FALSE);		\
 	}											\
     }												\
 }
 
 /* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */
 #define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t,	\
-				  dst_type_t, repeat_mode, have_mask, mask_is_solid)		\
+				 dst_type_t, repeat_mode, flags)				\
 	FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t,\
-				  dst_type_t, repeat_mode, have_mask, mask_is_solid)
+				  dst_type_t, repeat_mode, flags)
 
 #define SCALED_BILINEAR_FLAGS						\
     (FAST_PATH_SCALE_TRANSFORM	|					\
@@ -941,6 +1189,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 +1231,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 +1273,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),			\
diff --git a/pixman/pixman-sse2.c b/pixman/pixman-sse2.c
index 533b858..59f7ba6 100644
--- a/pixman/pixman-sse2.c
+++ b/pixman/pixman-sse2.c
@@ -5665,15 +5665,19 @@ scaled_bilinear_scanline_sse2_8888_8888_SRC (uint32_t *       dst,
 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_cover_SRC,
 			       scaled_bilinear_scanline_sse2_8888_8888_SRC,
 			       uint32_t, uint32_t, uint32_t,
-			       COVER, FALSE, FALSE)
+			       COVER, FLAG_NONE)
 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_pad_SRC,
 			       scaled_bilinear_scanline_sse2_8888_8888_SRC,
 			       uint32_t, uint32_t, uint32_t,
-			       PAD, FALSE, FALSE)
+			       PAD, FLAG_NONE)
 FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_none_SRC,
 			       scaled_bilinear_scanline_sse2_8888_8888_SRC,
 			       uint32_t, uint32_t, uint32_t,
-			       NONE, FALSE, FALSE)
+			       NONE, FLAG_NONE)
+FAST_BILINEAR_MAINLOOP_COMMON (sse2_8888_8888_normal_SRC,
+			       scaled_bilinear_scanline_sse2_8888_8888_SRC,
+			       uint32_t, uint32_t, uint32_t,
+			       NORMAL, FLAG_NONE)
 
 static const pixman_fast_path_t sse2_fast_paths[] =
 {
-- 
1.7.1

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

Reply via email to