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