Hi,
I send pixman patch for NEON optimizations for several bilinear scaled
scanline functions.
Following functions are optimized.

over_8888_n_8888
add_8888_n_8888
src_8888_8_8888
over_8888_8_8888
add_8888_8_8888

This patch is based on pixman master branch with latest commit id =
a2153222677327be43251012f462d19a7e98ce14. (Soeren's commit on April 3)
Because there can be some conflicts with latest commit of siarhei's bilinear
optimizations.

It sill have lots of places to optimize, for example, preloading mask and
destination pixels, better handling of two, one pixel case.
However it gives us reasonable performance than before.
Review would be appreciated.

Performance Data on S5PC110:

== bilinear scaled SRC for comparison ==

transl: op=1, src=20028888, mask=- dst=20028888, speed=72.87 MPix/s

== bilinear scaled OVER ==

(before) transl: op=3, src=20028888, mask=- dst=20028888, speed=6.73 MPix/s
(after) transl: op=3, src=20028888, mask=- dst=20028888, speed=35.47 MPix/s

== bilinear scaled ADD ==

(before) transl: op=12, src=20028888, mask=- dst=20028888, speed=6.91 MPix/s
(after) transl: op=12, src=20028888, mask=- dst=20028888, speed=43.18 MPix/s

== bilinear scaled mask SRC ==

(before) transl: op=1, src=20028888, mask=8 dst=20028888, speed=5.74 MPix/s
(after) transl: op=1, src=20028888, mask=8 dst=20028888, speed=52.01 MPix/s

== bilinear scaled mask OVER ==

(before) transl: op=3, src=20028888, mask=8 dst=20028888, speed=6.33 MPix/s
(after) transl: op=3, src=20028888, mask=8 dst=20028888, speed=30.00 MPix/s

== bilinear scaled mask ADD ==

(before) transl: op=12, src=20028888, mask=8 dst=20028888, speed=6.41 MPix/s
(after) transl: op=12, src=20028888, mask=8 dst=20028888, speed=33.47 MPix/s
-- 
Best Regards,
Taekyun Kim
From f46c4ab6bcbc8bfd0f9a0dcd7427fcf323cb2445 Mon Sep 17 00:00:00 2001
From: Taekyun Kim <[email protected]>
Date: Tue, 12 Apr 2011 11:52:57 +0900
Subject: [PATCH] NEON optimizations for bilinear scaled scanline functions
 	over_8888_n_8888
 	add_8888_n_8888
 	src_8888_8_8888
 	over_8888_8_8888
 	add_8888_8_8888

---
 pixman/pixman-arm-common.h   |   86 ++++++-----
 pixman/pixman-arm-neon-asm.S |  342 ++++++++++++++++++++++++++++++++++++++----
 pixman/pixman-arm-neon.c     |   61 ++++++--
 3 files changed, 405 insertions(+), 84 deletions(-)

diff --git a/pixman/pixman-arm-common.h b/pixman/pixman-arm-common.h
index c3bf986..c45fb34 100644
--- a/pixman/pixman-arm-common.h
+++ b/pixman/pixman-arm-common.h
@@ -363,47 +363,49 @@ FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                    \
 
 /*****************************************************************************/
 
-#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST(flags, cputype, name, op,     \
-                                                src_type, dst_type)           \
-void                                                                          \
-pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (               \
-                                                dst_type *       dst,         \
-                                                const src_type * top,         \
-                                                const src_type * bottom,      \
-                                                int              wt,          \
-                                                int              wb,          \
-                                                pixman_fixed_t   x,           \
-                                                pixman_fixed_t   ux,          \
-                                                int              width);      \
-                                                                              \
-static force_inline void                                                      \
-scaled_bilinear_scanline_##cputype##_##name##_##op (                          \
-                                                dst_type *       dst,         \
-                                                const uint32_t * mask,        \
-                                                const src_type * src_top,     \
-                                                const src_type * src_bottom,  \
-                                                int32_t          w,           \
-                                                int              wt,          \
-                                                int              wb,          \
-                                                pixman_fixed_t   vx,          \
-                                                pixman_fixed_t   unit_x,      \
-                                                pixman_fixed_t   max_vx,      \
-                                                pixman_bool_t    zero_src)    \
-{                                                                             \
-    if ((flags & SKIP_ZERO_SRC) && zero_src)                                  \
-	return;                                                               \
-    pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (           \
-                            dst, src_top, src_bottom, wt, wb, vx, unit_x, w); \
-}                                                                             \
-                                                                              \
-FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                 \
-                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, COVER, FALSE, FALSE)     \
-FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                  \
-                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, NONE, FALSE, FALSE)      \
-FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                   \
-                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
-                       src_type, uint32_t, dst_type, PAD, FALSE, FALSE)
+#define PIXMAN_ARM_BIND_SCALED_BILINEAR(flags, cputype, name, op,                   \
+                                        src_type, mask_type, dst_type,              \
+                                        have_mask, mask_is_solid)                   \
+void                                                                                \
+pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (                     \
+                                                dst_type *       dst,               \
+                                                const mask_type *mask,              \
+                                                const src_type * top,               \
+                                                const src_type * bottom,            \
+                                                int              wt,                \
+                                                int              wb,                \
+                                                pixman_fixed_t   x,                 \
+                                                pixman_fixed_t   ux,                \
+                                                int              width);            \
+                                                                                    \
+static force_inline void                                                            \
+scaled_bilinear_scanline_##cputype##_##name##_##op (                                \
+                                                dst_type *       dst,               \
+                                                const mask_type *mask,              \
+                                                const src_type * src_top,           \
+                                                const src_type * src_bottom,        \
+                                                int32_t          w,                 \
+                                                int              wt,                \
+                                                int              wb,                \
+                                                pixman_fixed_t   vx,                \
+                                                pixman_fixed_t   unit_x,            \
+                                                pixman_fixed_t   max_vx,            \
+                                                pixman_bool_t    zero_src)          \
+{                                                                                   \
+    if ((flags & SKIP_ZERO_SRC) && zero_src)                                        \
+	return;                                                                         \
+    pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (                 \
+                            dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
+}                                                                                   \
+                                                                                    \
+FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                       \
+                   scaled_bilinear_scanline_##cputype##_##name##_##op,              \
+                   src_type, mask_type, dst_type, COVER, have_mask, mask_is_solid)  \
+FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                        \
+                   scaled_bilinear_scanline_##cputype##_##name##_##op,              \
+                   src_type, mask_type, dst_type, NONE, have_mask, mask_is_solid)   \
+FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                         \
+                   scaled_bilinear_scanline_##cputype##_##name##_##op,              \
+                   src_type, mask_type, dst_type, PAD, have_mask, mask_is_solid)
 
 #endif
diff --git a/pixman/pixman-arm-neon-asm.S b/pixman/pixman-arm-neon-asm.S
index 1d3e64e..4cdacfa 100644
--- a/pixman/pixman-arm-neon-asm.S
+++ b/pixman/pixman-arm-neon-asm.S
@@ -1358,10 +1358,11 @@ generate_composite_function \
      *
      * output: updated dest in {d28, d29, d30, d31}
      */
-    vmvn.8      q12, q12
-    vmvn.8      d26, d26
+    vmvn.8      d24, d24
+    vmvn.8      d25, d25
     vmull.u8    q8,  d24, d4
     vmull.u8    q9,  d25, d5
+    vmvn.8      d26, d26
     vmvn.8      d27, d3
     vmull.u8    q10, d26, d6
     vmull.u8    q11, d27, d7
@@ -2553,8 +2554,259 @@ fname:
 .endif
 .endm
 
-.macro bilinear_interpolate_last_pixel src_fmt, dst_fmt
+
+/*
+ * Macros to support bilinear scaled scanline function with mask enabled
+ * for operator OVER and ADD extending previous siarhei's bilinear macro template.
+ *
+ * << General scanline function procedures >>
+ *  1. bilinear interpolate source pixels
+ *  2. load mask pixels
+ *  3. load destination pixels
+ *  4. duplicate mask to fill whole register
+ *  5. interleave source & destination pixels
+ *  6. apply mask to source pixels
+ *  7. combine source & destination pixels
+ *  8. store destination pixels
+ *
+ * All registers with single number (i.e. src0, tmp0) are 64-bits registers.
+ * Registers with double numbers are 128-bits registers.
+ * All temp registers can be used freely outside the code block.
+ * Assume that symbol(register .req) OUT and MASK are defined at caller of these macro blocks.
+ *
+ * TODOs
+ *  Support 0565 pixel format
+ *  Optimization for two and last pixel cases
+ *
+ * Remarks
+ *  There can be lots of pipeline stalls inside code block and between code blocks.
+ *  Further optimizations will be done by new macro templates using head/tail_head/tail scheme.
+ */
+
+
+/*
+ * Macros for loading mask pixels into register 'mask'.
+ * vdup must be done in somewhere else.
+ */
+.macro bilinear_load_mask_n numpix, mask
+.endm
+
+.macro bilinear_load_mask_8 numpix, mask
+.if numpix == 4
+    vld1.32     {mask[0]}, [MASK]!
+.elseif numpix == 2
+    vld1.16     {mask[0]}, [MASK]!
+.elseif numpix == 1
+    vld1.8      {mask[0]}, [MASK]!
+.else
+    .error bilinear_load_mask_8 numpix is unsupported
+.endif
+.endm
+
+.macro bilinear_load_mask mask_fmt, numpix, mask
+    bilinear_load_mask_&mask_fmt numpix, mask
+.endm
+
+
+/*
+ * Macros for loading destination pixels into register 'dst0' and 'dst1'.
+ * Interleave should be done somewhere else.
+ */
+.macro bilinear_load_dst_0565_src numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_load_dst_8888_src numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_load_dst_8888 numpix, dst0, dst1, dst01
+.if numpix == 4
+    vld1.32     {dst0, dst1}, [OUT]
+.elseif numpix == 2
+    vld1.32     {dst0}, [OUT]
+.elseif numpix == 1
+    vld1.32     {dst0[0]}, [OUT]
+.else
+    .error bilinear_load_dst_8888 numpix is unsupported
+.endif
+.endm
+
+.macro bilinear_load_dst_8888_over numpix, dst0, dst1, dst01
+    bilinear_load_dst_8888 numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_load_dst_8888_add numpix, dst0, dst1, dst01
+    bilinear_load_dst_8888 numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_load_dst dst_fmt, op, numpix, dst0, dst1, dst01
+    bilinear_load_dst_&dst_fmt&_&op numpix, dst0, dst1, dst01
+.endm
+
+/*
+ * Macros for duplicating partially loaded mask to fill entire register.
+ * We will apply mask to interleaved source pixels, that is
+ *  (r0, r1, r2, r3, g0, g1, g2, g3) x (m0, m1, m2, m3, m0, m1, m2, m3)
+ *  (b0, b1, b2, b3, a0, a1, a2, a3) x (m0, m1, m2, m3, m0, m1, m2, m3)
+ * So, we need to duplicate loaded mask into whole register.
+ *
+ * For two pixel case
+ *  (r0, r1, x, x, g0, g1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1)
+ *  (b0, b1, x, x, a0, a1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1)
+ * We can do some optimizations for this including one pixel cases.
+ */
+.macro bilinear_duplicate_mask_n numpix, mask
+.endm
+
+.macro bilinear_duplicate_mask_8 numpix, mask
+.if numpix == 4
+    vdup.32     mask, mask[0]
+.elseif numpix == 2
+    vdup.16     mask, mask[0]
+.elseif numpix == 1
+    vdup.8      mask, mask[0]
+.else
+    .error bilinear_duplicate_mask_8 is unsupported
+.endif
+.endm
+
+.macro bilinear_duplicate_mask mask_fmt, numpix, mask
+    bilinear_duplicate_mask_&mask_fmt numpix, mask
+.endm
+
+/*
+ * Macros for interleaving src and dst pixels to rrrr gggg bbbb aaaa form.
+ * Interleave should be done when maks is enabled or operator is 'over'.
+ */
+.macro bilinear_interleave src0, src1, dst0, dst1
+    vuzp.8      src0, src1
+    vuzp.8      dst0, dst1
+    vuzp.8      src0, src1
+    vuzp.8      dst0, dst1
+.endm
+
+.macro bilinear_interleave_src_dst_n_src numpix, src0, src1, src01, dst0, dst1, dst01
+.endm
+
+.macro bilinear_interleave_src_dst_n_over numpix, src0, src1, src01, dst0, dst1, dst01
+    bilinear_interleave src0, src1, dst0, dst1
+.endm
+
+.macro bilinear_interleave_src_dst_n_add numpix, src0, src1, src01, dst0, dst1, dst01
+.endm
+
+.macro bilinear_interleave_src_dst_8_src numpix, src0, src1, src01, dst0, dst1, dst01
+    bilinear_interleave src0, src1, dst0, dst1
+.endm
+
+.macro bilinear_interleave_src_dst_8_over numpix, src0, src1, src01, dst0, dst1, dst01
+    bilinear_interleave src0, src1, dst0, dst1
+.endm
+
+.macro bilinear_interleave_src_dst_8_add numpix, src0, src1, src01, dst0, dst1, dst01
+    bilinear_interleave src0, src1, dst0, dst1
+.endm
+
+.macro bilinear_interleave_src_dst mask_fmt, op, numpix, src0, src1, src01, dst0, dst1, dst01
+    bilinear_interleave_src_dst_&mask_fmt&_&op numpix, src0, src1, src01, dst0, dst1, dst01
+.endm
+
+
+/*
+ * Macros for applying masks to src pixels. (see combine_mask_u() function)
+ * src, dst should be in interleaved form, mask register should be in form (m0, m1, m2, m3)
+ */
+.macro bilinear_apply_mask_to_src_n numpix, src0, src1, src01, mask, tmp01, tmp23, tmp45, tmp67
+.endm
+
+.macro bilinear_apply_mask_to_src_8 numpix, src0, src1, src01, mask, tmp01, tmp23, tmp45, tmp67
+    vmull.u8        tmp01, src0, mask
+    vmull.u8        tmp23, src1, mask
+    /* bubbles */
+    vrshr.u16       tmp45, tmp01, #8
+    vrshr.u16       tmp67, tmp23, #8
+    /* bubbles */
+    vraddhn.u16     src0, tmp45, tmp01
+    vraddhn.u16     src1, tmp67, tmp23
+.endm
+
+.macro bilinear_apply_mask_to_src mask_fmt, numpix, src0, src1, src01, mask, tmp01, tmp23, tmp45, tmp67
+    bilinear_apply_mask_to_src_&mask_fmt numpix, src0, src1, src01, mask, tmp01, tmp23, tmp45, tmp67
+.endm
+
+
+/*
+ * Macros for combining src and destination pixels.
+ * Interleave or not is depending on operator 'op'.
+ */
+.macro bilinear_combine_src numpix, src0, src1, src01, dst0, dst1, dst01, tmp01, tmp23, tmp45, tmp67, tmp8
+.endm
+
+.macro bilinear_combine_over numpix, src0, src1, src01, dst0, dst1, dst01, tmp01, tmp23, tmp45, tmp67, tmp8
+    vdup.32     tmp8, src1[1]
+    /* bubbles */
+    vmvn.8      tmp8, tmp8
+    /* bubbles */
+    vmull.u8    tmp01, dst0, tmp8
+    /* bubbles */
+    vmull.u8    tmp23, dst1, tmp8
+    /* bubbles */
+    vrshr.u16   tmp45, tmp01, #8
+    vrshr.u16   tmp67, tmp23, #8
+    /* bubbles */
+    vraddhn.u16 dst0, tmp45, tmp01
+    vraddhn.u16 dst1, tmp67, tmp23
+    /* bubbles */
+    vqadd.u8    src01, dst01, src01
+.endm
+
+.macro bilinear_combine_add numpix, src0, src1, src01, dst0, dst1, dst01, tmp01, tmp23, tmp45, tmp67, tmp8
+    vqadd.u8    src01, dst01, src01
+.endm
+
+.macro bilinear_combine op, numpix, src0, src1, src01, dst0, dst1, dst01, tmp01, tmp23, tmp45, tmp67, tmp8
+    bilinear_combine_&op numpix, src0, src1, src01, dst0, dst1, dst01, tmp01, tmp23, tmp45, tmp67, tmp8
+.endm
+
+/*
+ * Macros for final deinterleaving of destination pixels if needed.
+ */
+.macro bilinear_deinterleave numpix, dst0, dst1, dst01
+    vuzp.8      dst0, dst1
+    /* bubbles */
+    vuzp.8      dst0, dst1
+.endm
+
+.macro bilinear_deinterleave_dst_n_src numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst_n_over numpix, dst0, dst1, dst01
+    bilinear_deinterleave numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst_n_add numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst_8_src numpix, dst0, dst1, dst01
+    bilinear_deinterleave numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst_8_over numpix, dst0, dst1, dst01
+    bilinear_deinterleave numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst_8_add numpix, dst0, dst1, dst01
+    bilinear_deinterleave numpix, dst0, dst1, dst01
+.endm
+
+.macro bilinear_deinterleave_dst mask_fmt, op, numpix, dst0, dst1, dst01
+    bilinear_deinterleave_dst_&mask_fmt&_&op numpix, dst0, dst1, dst01
+.endm
+
+
+.macro bilinear_interpolate_last_pixel src_fmt, mask_fmt, dst_fmt, op
     bilinear_load_&src_fmt d0, d1, d2
+    bilinear_load_mask mask_fmt, 1, d4
+    bilinear_load_dst dst_fmt, op, 1, d18, d19, q9
     vmull.u8  q1, d0, d28
     vmlal.u8  q1, d1, d29
     vshr.u16  d30, d24, #8
@@ -2563,16 +2815,23 @@ fname:
     vmlsl.u16 q0, d2, d30
     vmlal.u16 q0, d3, d30
     /* 5 cycles bubble */
+    bilinear_duplicate_mask mask_fmt, 1, d4
     vshrn.u32 d0, q0, #16
     /* 3 cycles bubble */
     vmovn.u16 d0, q0
     /* 1 cycle bubble */
+    bilinear_interleave_src_dst mask_fmt, op, 1, d0, d1, q0, d18, d19, q9
+    bilinear_apply_mask_to_src mask_fmt, 1, d0, d1, q0, d4, q3, q8, q10, q11
+    bilinear_combine op, 1, d0, d1, q0, d18, d19, q9, q3, q8, q10, q11, d5
+    bilinear_deinterleave_dst mask_fmt, op, 1, d0, d1, q0
     bilinear_store_&dst_fmt 1, q2, q3
 .endm
 
-.macro bilinear_interpolate_two_pixels src_fmt, dst_fmt
+.macro bilinear_interpolate_two_pixels src_fmt, mask_fmt, dst_fmt, op
     bilinear_load_and_vertical_interpolate_two_&src_fmt \
                 q1, q11, d0, d1, d20, d21, d22, d23
+    bilinear_load_mask mask_fmt, 2, d4
+    bilinear_load_dst dst_fmt, op, 2, d18, d19, q9
     vshr.u16  q15, q12, #8
     vadd.u16  q12, q12, q13
     vshll.u16 q0, d2, #8
@@ -2583,11 +2842,16 @@ fname:
     vmlal.u16 q10, d23, d31
     vshrn.u32 d30, q0, #16
     vshrn.u32 d31, q10, #16
+    bilinear_duplicate_mask mask_fmt, 2, d4
     vmovn.u16 d0, q15
+    bilinear_interleave_src_dst mask_fmt, op, 2, d0, d1, q0, d18, d19, q9
+    bilinear_apply_mask_to_src mask_fmt, 2, d0, d1, q0, d4, q3, q8, q10, q11
+    bilinear_combine op, 2, d0, d1, q0, d18, d19, q9, q3, q8, q10, q11, d5
+    bilinear_deinterleave_dst mask_fmt, op, 2, d0, d1, q0
     bilinear_store_&dst_fmt 2, q2, q3
 .endm
 
-.macro bilinear_interpolate_four_pixels src_fmt, dst_fmt
+.macro bilinear_interpolate_four_pixels src_fmt, mask_fmt, dst_fmt, op
     bilinear_load_and_vertical_interpolate_four_&src_fmt \
                 q1, q11, d0, d1, d20, d21, d22, d23 \
                 q3, q9,  d4, d5, d16, d17, d18, d19
@@ -2605,6 +2869,8 @@ fname:
     vmlsl.u16 q2, d6, d30
     vmlal.u16 q2, d7, d30
     vshll.u16 q8, d18, #8
+    bilinear_load_mask mask_fmt, 4, d30
+    bilinear_load_dst dst_fmt, op, 4, d2, d3, q1
     pld       [TMP2, PF_OFFS]
     vmlsl.u16 q8, d18, d31
     vmlal.u16 q8, d19, d31
@@ -2613,8 +2879,13 @@ fname:
     vshrn.u32 d1, q10, #16
     vshrn.u32 d4, q2, #16
     vshrn.u32 d5, q8, #16
+    bilinear_duplicate_mask mask_fmt, 4, d30
     vmovn.u16 d0, q0
     vmovn.u16 d1, q2
+    bilinear_interleave_src_dst mask_fmt, op, 4, d0, d1, q0, d2, d3, q1
+    bilinear_apply_mask_to_src mask_fmt, 4, d0, d1, q0, d30, q3, q8, q9, q10
+    bilinear_combine op, 4, d0, d1, q0, d2, d3, q1, q3, q8, q9, q10, d22
+    bilinear_deinterleave_dst mask_fmt, op, 4, d0, d1, q0
     bilinear_store_&dst_fmt 4, q2, q3
 .endm
 
@@ -2634,28 +2905,29 @@ fname:
  *                      pixels ahead
  */
 
-.macro generate_bilinear_scanline_func fname, src_fmt, dst_fmt, \
+.macro generate_bilinear_scanline_func fname, src_fmt, mask_fmt, dst_fmt, op, \
                                        bpp_shift, prefetch_distance
 
 pixman_asm_function fname
     OUT       .req      r0
-    TOP       .req      r1
-    BOTTOM    .req      r2
-    WT        .req      r3
-    WB        .req      r4
-    X         .req      r5
-    UX        .req      r6
+    MASK      .req      r1
+    TOP       .req      r2
+    BOTTOM    .req      r3
+    WT        .req      r4
+    WB        .req      r5
+    X         .req      r6
+    UX        .req      r7
     WIDTH     .req      ip
-    TMP1      .req      r3
-    TMP2      .req      r4
-    PF_OFFS   .req      r7
-    TMP3      .req      r8
-    TMP4      .req      r9
+    TMP1      .req      r4
+    TMP2      .req      r5
+    PF_OFFS   .req      r8
+    TMP3      .req      r9
+    TMP4      .req      r10
 
     mov       ip, sp
-    push      {r4, r5, r6, r7, r8, r9}
+    push      {r4, r5, r6, r7, r8, r9, r10}
     mov       PF_OFFS, #prefetch_distance
-    ldmia     ip, {WB, X, UX, WIDTH}
+    ldmia     ip, {WT, WB, X, UX, WIDTH}
     mul       PF_OFFS, PF_OFFS, UX
 
     cmp       WIDTH, #0
@@ -2672,19 +2944,19 @@ pixman_asm_function fname
     blt       1f
     mov       PF_OFFS, PF_OFFS, asr #(16 - bpp_shift)
 0:
-    bilinear_interpolate_four_pixels src_fmt, dst_fmt
+    bilinear_interpolate_four_pixels src_fmt, mask_fmt, dst_fmt, op
     subs      WIDTH, WIDTH, #4
     bge       0b
 1:
     tst       WIDTH, #2
     beq       2f
-    bilinear_interpolate_two_pixels src_fmt, dst_fmt
+    bilinear_interpolate_two_pixels src_fmt, mask_fmt, dst_fmt, op
 2:
     tst       WIDTH, #1
     beq       3f
-    bilinear_interpolate_last_pixel src_fmt, dst_fmt
+    bilinear_interpolate_last_pixel src_fmt, mask_fmt, dst_fmt, op
 3:
-    pop       {r4, r5, r6, r7, r8, r9}
+    pop       {r4, r5, r6, r7, r8, r9, r10}
     bx        lr
 
     .unreq    OUT
@@ -2695,6 +2967,7 @@ pixman_asm_function fname
     .unreq    X
     .unreq    UX
     .unreq    WIDTH
+    .unreq    MASK
     .unreq    TMP1
     .unreq    TMP2
     .unreq    PF_OFFS
@@ -2705,13 +2978,28 @@ pixman_asm_function fname
 .endm
 
 generate_bilinear_scanline_func \
-    pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_neon, 8888, 8888, 2, 28
+    pixman_scaled_bilinear_scanline_8888_n_8888_SRC_asm_neon, 8888, n, 8888, src, 2, 28
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_8888_n_0565_SRC_asm_neon, 8888, n, 0565, src, 2, 28
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_0565_n_x888_SRC_asm_neon, 0565, n, 8888, src, 1, 28
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_0565_n_0565_SRC_asm_neon, 0565, n, 0565, src, 1, 28
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_8888_n_8888_OVER_asm_neon, 8888, n, 8888, over, 2, 28
+
+generate_bilinear_scanline_func \
+    pixman_scaled_bilinear_scanline_8888_n_8888_ADD_asm_neon, 8888, n, 8888, add, 2, 28
 
 generate_bilinear_scanline_func \
-    pixman_scaled_bilinear_scanline_8888_0565_SRC_asm_neon, 8888, 0565, 2, 28
+    pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_neon, 8888, 8, 8888, src, 2, 28
 
 generate_bilinear_scanline_func \
-    pixman_scaled_bilinear_scanline_0565_x888_SRC_asm_neon, 0565, 8888, 1, 28
+    pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_neon, 8888, 8, 8888, over, 2, 28
 
 generate_bilinear_scanline_func \
-    pixman_scaled_bilinear_scanline_0565_0565_SRC_asm_neon, 0565, 0565, 1, 28
+    pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_neon, 8888, 8, 8888, add, 2, 28
diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c
index 0a10ca1..b57e6a4 100644
--- a/pixman/pixman-arm-neon.c
+++ b/pixman/pixman-arm-neon.c
@@ -127,14 +127,29 @@ PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_0565,
 PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 0565_8_0565,
                                            OVER, uint16_t, uint16_t)
 
-PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_8888, SRC,
-                                         uint32_t, uint32_t)
-PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_0565, SRC,
-                                         uint32_t, uint16_t)
-PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_x888, SRC,
-                                         uint16_t, uint32_t)
-PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_0565, SRC,
-                                         uint16_t, uint16_t)
+PIXMAN_ARM_BIND_SCALED_BILINEAR (0, neon, 8888_n_8888, SRC,
+                                         uint32_t, uint32_t, uint32_t, FALSE, FALSE)
+PIXMAN_ARM_BIND_SCALED_BILINEAR (0, neon, 8888_n_0565, SRC,
+                                         uint32_t, uint32_t, uint16_t, FALSE, FALSE)
+PIXMAN_ARM_BIND_SCALED_BILINEAR (0, neon, 0565_n_x888, SRC,
+                                         uint16_t, uint32_t, uint32_t, FALSE, FALSE)
+PIXMAN_ARM_BIND_SCALED_BILINEAR (0, neon, 0565_n_0565, SRC,
+                                         uint16_t, uint32_t, uint16_t, FALSE, FALSE)
+
+PIXMAN_ARM_BIND_SCALED_BILINEAR (SKIP_ZERO_SRC, neon, 8888_n_8888, OVER,
+                                         uint32_t, uint32_t, uint32_t, FALSE, FALSE)
+
+PIXMAN_ARM_BIND_SCALED_BILINEAR (SKIP_ZERO_SRC, neon, 8888_n_8888, ADD,
+                                         uint32_t, uint32_t, uint32_t, FALSE, FALSE)
+
+PIXMAN_ARM_BIND_SCALED_BILINEAR (0, neon, 8888_8_8888, SRC,
+                                         uint32_t, uint8_t, uint32_t, TRUE, FALSE)
+
+PIXMAN_ARM_BIND_SCALED_BILINEAR (SKIP_ZERO_SRC, neon, 8888_8_8888, OVER,
+                                         uint32_t, uint8_t, uint32_t, TRUE, FALSE)
+
+PIXMAN_ARM_BIND_SCALED_BILINEAR (SKIP_ZERO_SRC, neon, 8888_8_8888, ADD,
+                                         uint32_t, uint8_t, uint32_t, TRUE, FALSE)
 
 void
 pixman_composite_src_n_8_asm_neon (int32_t   w,
@@ -352,15 +367,31 @@ static const pixman_fast_path_t arm_neon_fast_paths[] =
     PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, neon_0565_8_0565),
     PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, neon_0565_8_0565),
 
-    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8888),
-    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8888),
-    SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8888),
+    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_n_8888),
+    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_n_8888),
+    SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_n_8888),
+
+    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_n_0565),
+    SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_n_0565),
+
+    SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_n_x888),
+    SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_n_0565),
+
+    SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_n_8888),
+    SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_n_8888),
+
+    SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_n_8888),
+    SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_n_8888),
+
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, a8r8g8b8, neon_8888_8_8888),
 
-    SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
-    SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
 
-    SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_x888),
-    SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_0565),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
+    SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
 
     { PIXMAN_OP_NONE },
 };
-- 
1.7.0.4

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

Reply via email to