From 49a32b91eda5afc05e8a4a22577f6182987205c6 Mon Sep 17 00:00:00 2001 From: Manuel Rommel Date: Sun, 26 Dec 2010 18:52:49 +0100 Subject: [PATCH] Add Altivec version of mc_weight --- common/ppc/mc.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) diff --git a/common/ppc/mc.c b/common/ppc/mc.c index ddbb6c94..5a51ea51 100644 --- a/common/ppc/mc.c +++ b/common/ppc/mc.c @@ -856,6 +856,318 @@ static void frame_init_lowres_core_altivec( uint8_t *src0, uint8_t *dst0, uint8_ dstc += dst_stride; } } + +static void mc_weight_w2_altivec( uint8_t *dst, int i_dst, uint8_t *src, int i_src, + const x264_weight_t *weight, int i_height ) +{ + LOAD_ZERO; + PREP_LOAD; + PREP_LOAD_SRC( src ); + vec_u8_t srcv; + vec_s16_t weightv; + vec_s16_t scalev, offsetv, denomv, roundv; + vec_s16_u loadv; + + int denom = weight->i_denom; + + loadv.s[0] = weight->i_scale; + scalev = vec_splat( loadv.v, 0 ); + + loadv.s[0] = weight->i_offset; + offsetv = vec_splat( loadv.v, 0 ); + + if( denom >= 1 ) + { + loadv.s[0] = denom; + denomv = vec_splat( loadv.v, 0 ); + + loadv.s[0] = 1<<(denom - 1); + roundv = vec_splat( loadv.v, 0 ); + + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 2, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, roundv ); + weightv = vec_sra( weightv, (vec_u16_t)denomv ); + weightv = vec_add( weightv, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + vec_ste( vec_splat( (vec_u16_t)srcv, 0 ), 0, (uint16_t*)dst ); + } + } + else + { + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 2, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + vec_ste( vec_splat( (vec_u16_t)srcv, 0 ), 0, (uint16_t*)dst ); + } + } +} +static void mc_weight_w4_altivec( uint8_t *dst, int i_dst, uint8_t *src, int i_src, + const x264_weight_t *weight, int i_height ) +{ + LOAD_ZERO; + PREP_LOAD; + PREP_LOAD_SRC( src ); + vec_u8_t srcv; + vec_s16_t weightv; + vec_s16_t scalev, offsetv, denomv, roundv; + vec_s16_u loadv; + + int denom = weight->i_denom; + + loadv.s[0] = weight->i_scale; + scalev = vec_splat( loadv.v, 0 ); + + loadv.s[0] = weight->i_offset; + offsetv = vec_splat( loadv.v, 0 ); + + if( denom >= 1 ) + { + loadv.s[0] = denom; + denomv = vec_splat( loadv.v, 0 ); + + loadv.s[0] = 1<<(denom - 1); + roundv = vec_splat( loadv.v, 0 ); + + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 4, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, roundv ); + weightv = vec_sra( weightv, (vec_u16_t)denomv ); + weightv = vec_add( weightv, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + vec_ste( vec_splat( (vec_u32_t)srcv, 0 ), 0, (uint32_t*)dst ); + } + } + else + { + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 4, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + vec_ste( vec_splat( (vec_u32_t)srcv, 0 ), 0, (uint32_t*)dst ); + } + } +} +static void mc_weight_w8_altivec( uint8_t *dst, int i_dst, uint8_t *src, int i_src, + const x264_weight_t *weight, int i_height ) +{ + LOAD_ZERO; + PREP_LOAD; + PREP_LOAD_SRC( src ); + PREP_STORE8; + vec_u8_t srcv; + vec_s16_t weightv; + vec_s16_t scalev, offsetv, denomv, roundv; + vec_s16_u loadv; + + int denom = weight->i_denom; + + loadv.s[0] = weight->i_scale; + scalev = vec_splat( loadv.v, 0 ); + + loadv.s[0] = weight->i_offset; + offsetv = vec_splat( loadv.v, 0 ); + + if( denom >= 1 ) + { + loadv.s[0] = denom; + denomv = vec_splat( loadv.v, 0 ); + + loadv.s[0] = 1<<(denom - 1); + roundv = vec_splat( loadv.v, 0 ); + + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 8, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, roundv ); + weightv = vec_sra( weightv, (vec_u16_t)denomv ); + weightv = vec_add( weightv, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + VEC_STORE8( srcv, dst ); + } + } + else + { + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 8, vec_u8_t, src ); + weightv = vec_u8_to_s16( srcv ); + + weightv = vec_mladd( weightv, scalev, offsetv ); + + srcv = vec_packsu( weightv, zero_s16v ); + VEC_STORE8( srcv, dst ); + } + } +} +static void mc_weight_w16_altivec( uint8_t *dst, int i_dst, uint8_t *src, int i_src, + const x264_weight_t *weight, int i_height ) +{ + LOAD_ZERO; + PREP_LOAD; + PREP_LOAD_SRC( src ); + vec_u8_t srcv; + vec_s16_t weight_lv, weight_hv; + vec_s16_t scalev, offsetv, denomv, roundv; + vec_s16_u loadv; + + int denom = weight->i_denom; + + loadv.s[0] = weight->i_scale; + scalev = vec_splat( loadv.v, 0 ); + + loadv.s[0] = weight->i_offset; + offsetv = vec_splat( loadv.v, 0 ); + + if( denom >= 1 ) + { + loadv.s[0] = denom; + denomv = vec_splat( loadv.v, 0 ); + + loadv.s[0] = 1<<(denom - 1); + roundv = vec_splat( loadv.v, 0 ); + + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 16, vec_u8_t, src ); + weight_hv = vec_u8_to_s16_h( srcv ); + weight_lv = vec_u8_to_s16_l( srcv ); + + weight_hv = vec_mladd( weight_hv, scalev, roundv ); + weight_lv = vec_mladd( weight_lv, scalev, roundv ); + weight_hv = vec_sra( weight_hv, (vec_u16_t)denomv ); + weight_lv = vec_sra( weight_lv, (vec_u16_t)denomv ); + weight_hv = vec_add( weight_hv, offsetv ); + weight_lv = vec_add( weight_lv, offsetv ); + + srcv = vec_packsu( weight_hv, weight_lv ); + vec_st( srcv, 0, dst ); + } + } + else + { + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + VEC_LOAD( src, srcv, 16, vec_u8_t, src ); + weight_hv = vec_u8_to_s16_h( srcv ); + weight_lv = vec_u8_to_s16_l( srcv ); + + weight_hv = vec_mladd( weight_hv, scalev, offsetv ); + weight_lv = vec_mladd( weight_lv, scalev, offsetv ); + + srcv = vec_packsu( weight_hv, weight_lv ); + vec_st( srcv, 0, dst ); + } + } +} +static void mc_weight_w20_altivec( uint8_t *dst, int i_dst, uint8_t *src, int i_src, + const x264_weight_t *weight, int i_height ) +{ + LOAD_ZERO; + PREP_LOAD_SRC( src ); + vec_u8_t src_1v, src_2v, src_3v; + vec_s16_t weight_lv, weight_hv, weight_3v; + vec_s16_t scalev, offsetv, denomv, roundv; + vec_s16_u loadv; + + int denom = weight->i_denom; + + loadv.s[0] = weight->i_scale; + scalev = vec_splat( loadv.v, 0 ); + + loadv.s[0] = weight->i_offset; + offsetv = vec_splat( loadv.v, 0 ); + + if( denom >= 1 ) + { + loadv.s[0] = denom; + denomv = vec_splat( loadv.v, 0 ); + + loadv.s[0] = 1<<(denom - 1); + roundv = vec_splat( loadv.v, 0 ); + + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + src_1v = vec_ld( 0, src ); + src_2v = vec_ld( 16, src ); + src_3v = vec_ld( 19, src ); + src_1v = vec_perm( src_1v, src_2v, _src_ ); + src_3v = vec_perm( src_2v, src_3v, _src_ ); + weight_hv = vec_u8_to_s16_h( src_1v ); + weight_lv = vec_u8_to_s16_l( src_1v ); + weight_3v = vec_u8_to_s16_h( src_3v ); + + weight_hv = vec_mladd( weight_hv, scalev, roundv ); + weight_lv = vec_mladd( weight_lv, scalev, roundv ); + weight_3v = vec_mladd( weight_3v, scalev, roundv ); + weight_hv = vec_sra( weight_hv, (vec_u16_t)denomv ); + weight_lv = vec_sra( weight_lv, (vec_u16_t)denomv ); + weight_3v = vec_sra( weight_3v, (vec_u16_t)denomv ); + weight_hv = vec_add( weight_hv, offsetv ); + weight_lv = vec_add( weight_lv, offsetv ); + weight_3v = vec_add( weight_3v, offsetv ); + + src_1v = vec_packsu( weight_hv, weight_lv ); + src_3v = vec_packsu( weight_3v, zero_s16v ); + vec_st( src_1v, 0, dst ); + vec_ste( (vec_u32_t)src_3v, 16, (uint32_t*)dst ); + } + } + else + { + for( int y = 0; y < i_height; y++, dst += i_dst, src += i_src ) + { + src_1v = vec_ld( 0, src ); + src_2v = vec_ld( 16, src ); + src_3v = vec_ld( 19, src ); + src_1v = vec_perm( src_1v, src_2v, _src_ ); + src_3v = vec_perm( src_2v, src_3v, _src_ ); + weight_hv = vec_u8_to_s16_h( src_1v ); + weight_lv = vec_u8_to_s16_l( src_1v ); + weight_3v = vec_u8_to_s16_h( src_3v ); + + weight_hv = vec_mladd( weight_hv, scalev, offsetv ); + weight_lv = vec_mladd( weight_lv, scalev, offsetv ); + weight_3v = vec_mladd( weight_3v, scalev, offsetv ); + + src_1v = vec_packsu( weight_hv, weight_lv ); + src_3v = vec_packsu( weight_3v, zero_s16v ); + vec_st( src_1v, 0, dst ); + vec_ste( (vec_u32_t)src_3v, 16, (uint32_t*)dst ); + } + } +} + +static weight_fn_t x264_mc_weight_wtab_altivec[6] = +{ + mc_weight_w2_altivec, + mc_weight_w4_altivec, + mc_weight_w8_altivec, + mc_weight_w16_altivec, + mc_weight_w16_altivec, + mc_weight_w20_altivec, +}; + #endif // !HIGH_BIT_DEPTH void x264_mc_altivec_init( x264_mc_functions_t *pf ) @@ -870,5 +1182,7 @@ void x264_mc_altivec_init( x264_mc_functions_t *pf ) pf->hpel_filter = x264_hpel_filter_altivec; pf->frame_init_lowres_core = frame_init_lowres_core_altivec; + + pf->weight = x264_mc_weight_wtab_altivec; #endif // !HIGH_BIT_DEPTH } -- 2.40.0