From 7ea67a4d2f5f19d7e247bc0bed3daaf2bb6903f7 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Wed, 8 Jul 2026 21:36:08 +0800 Subject: [PATCH 5/5] vp8 update --- vp8/common/ppc/copy_altivec.c | 70 +++++++++++ vp8/common/ppc/idct_altivec.c | 173 ++++++++++++++++++++++++++++ vp8/common/ppc/loopfilter_altivec.c | 129 +++++++++++++++++++++ vp8/common/rtcd_defs.pl | 28 ++--- vp8/vp8_common.mk | 9 ++ 5 files changed, 395 insertions(+), 14 deletions(-) create mode 100644 vp8/common/ppc/copy_altivec.c create mode 100644 vp8/common/ppc/idct_altivec.c create mode 100644 vp8/common/ppc/loopfilter_altivec.c diff --git a/vp8/common/ppc/copy_altivec.c b/vp8/common/ppc/copy_altivec.c new file mode 100644 index 000000000..1c2b45d38 --- /dev/null +++ b/vp8/common/ppc/copy_altivec.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * Copyright (c) 2025 Contributors to libvpx PowerPC port. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "./vp8_rtcd.h" +#include "vpx_ports/mem.h" + +void vp8_copy_mem16x16_altivec(unsigned char *src, int src_stride, + unsigned char *dst, int dst_stride) { + int r; + + for (r = 0; r < 16; ++r) { + vector unsigned char v0, v1, v2; + v1 = vec_ld(0, src); + v2 = vec_ld(15, src); + v0 = vec_perm(v1, v2, vec_lvsl(0, src)); + vec_st(v0, 0, dst); + src += src_stride; + dst += dst_stride; + } +} + +void vp8_copy_mem8x8_altivec(unsigned char *src, int src_stride, + unsigned char *dst, int dst_stride) { + int r; + + for (r = 0; r < 8; ++r) { + vector unsigned char v0, v1, v2; + unsigned long long val; + + v1 = vec_ld(0, src); + v2 = vec_ld(7, src); + v0 = vec_perm(v1, v2, vec_lvsl(0, src)); + + val = ((unsigned long long *)&v0)[0]; + *(unsigned long long *)dst = val; + + src += src_stride; + dst += dst_stride; + } +} + +void vp8_copy_mem8x4_altivec(unsigned char *src, int src_stride, + unsigned char *dst, int dst_stride) { + int r; + + for (r = 0; r < 4; ++r) { + vector unsigned char v0, v1, v2; + unsigned long long val; + + v1 = vec_ld(0, src); + v2 = vec_ld(7, src); + v0 = vec_perm(v1, v2, vec_lvsl(0, src)); + + val = ((unsigned long long *)&v0)[0]; + *(unsigned long long *)dst = val; + + src += src_stride; + dst += dst_stride; + } +} diff --git a/vp8/common/ppc/idct_altivec.c b/vp8/common/ppc/idct_altivec.c new file mode 100644 index 000000000..2cc18ca5c --- /dev/null +++ b/vp8/common/ppc/idct_altivec.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * Copyright (c) 2025 Contributors to libvpx PowerPC port. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "./vp8_rtcd.h" + +static const int cospi8sqrt2minus1 = 20091; +static const int sinpi8sqrt2 = 35468; + +void vp8_short_idct4x4llm_altivec(short *input, unsigned char *pred_ptr, + int pred_stride, unsigned char *dst_ptr, + int dst_stride) { + int i; + int a1, b1, c1, d1; + short output[16]; + short *ip = input; + short *op = output; + int temp1, temp2; + int shortpitch = 4; + + for (i = 0; i < 4; ++i) { + a1 = ip[0] + ip[8]; + b1 = ip[0] - ip[8]; + + temp1 = (ip[4] * sinpi8sqrt2) >> 16; + temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16); + c1 = temp1 - temp2; + + temp1 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16); + temp2 = (ip[12] * sinpi8sqrt2) >> 16; + d1 = temp1 + temp2; + + op[shortpitch * 0] = a1 + d1; + op[shortpitch * 3] = a1 - d1; + + op[shortpitch * 1] = b1 + c1; + op[shortpitch * 2] = b1 - c1; + + ip++; + op++; + } + + ip = output; + op = output; + + for (i = 0; i < 4; ++i) { + a1 = ip[0] + ip[2]; + b1 = ip[0] - ip[2]; + + temp1 = (ip[1] * sinpi8sqrt2) >> 16; + temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16); + c1 = temp1 - temp2; + + temp1 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16); + temp2 = (ip[3] * sinpi8sqrt2) >> 16; + d1 = temp1 + temp2; + + op[0] = (a1 + d1 + 4) >> 3; + op[3] = (a1 - d1 + 4) >> 3; + + op[1] = (b1 + c1 + 4) >> 3; + op[2] = (b1 - c1 + 4) >> 3; + + ip += shortpitch; + op += shortpitch; + } + + ip = output; + + vector unsigned char vzero = vec_splat_u8(0); + + for (i = 0; i < 4; ++i) { + vector signed short vpred, vip, vresult; + vector unsigned char vpred_ub, vresult_ub; + unsigned int result_val; + + vpred_ub = vec_lde(0, pred_ptr); + vpred_ub = vec_perm(vpred_ub, vpred_ub, vec_lvsl(0, pred_ptr)); + vpred = (vector signed short)vec_mergeh(vzero, vpred_ub); + + vip = vec_ld(0, ip); + vresult = vec_add(vpred, vip); + vresult_ub = vec_packsu(vresult, vresult); + + result_val = ((unsigned int *)&vresult_ub)[0]; + *(unsigned int *)dst_ptr = result_val; + + ip += 4; + dst_ptr += dst_stride; + pred_ptr += pred_stride; + } +} + +void vp8_dc_only_idct_add_altivec(short input_dc, unsigned char *pred_ptr, + int pred_stride, unsigned char *dst_ptr, + int dst_stride) { + int a1 = ((input_dc + 4) >> 3); + int r, c; + + for (r = 0; r < 4; ++r) { + for (c = 0; c < 4; ++c) { + int a = a1 + pred_ptr[c]; + + if (a < 0) a = 0; + + if (a > 255) a = 255; + + dst_ptr[c] = (unsigned char)a; + } + + dst_ptr += dst_stride; + pred_ptr += pred_stride; + } +} + +void vp8_short_inv_walsh4x4_altivec(short *input, short *mb_dqcoeff) { + short output[16]; + int i; + int a1, b1, c1, d1; + int a2, b2, c2, d2; + short *ip = input; + short *op = output; + + for (i = 0; i < 4; ++i) { + a1 = ip[0] + ip[12]; + b1 = ip[4] + ip[8]; + c1 = ip[4] - ip[8]; + d1 = ip[0] - ip[12]; + + op[0] = a1 + b1; + op[4] = c1 + d1; + op[8] = a1 - b1; + op[12] = d1 - c1; + ip++; + op++; + } + + ip = output; + op = output; + + for (i = 0; i < 4; ++i) { + a1 = ip[0] + ip[3]; + b1 = ip[1] + ip[2]; + c1 = ip[1] - ip[2]; + d1 = ip[0] - ip[3]; + + a2 = a1 + b1; + b2 = c1 + d1; + c2 = a1 - b1; + d2 = d1 - c1; + + op[0] = (a2 + 3) >> 3; + op[1] = (b2 + 3) >> 3; + op[2] = (c2 + 3) >> 3; + op[3] = (d2 + 3) >> 3; + + ip += 4; + op += 4; + } + + for (i = 0; i < 16; ++i) { + mb_dqcoeff[i * 16] = output[i]; + } +} diff --git a/vp8/common/ppc/loopfilter_altivec.c b/vp8/common/ppc/loopfilter_altivec.c new file mode 100644 index 000000000..213c6da57 --- /dev/null +++ b/vp8/common/ppc/loopfilter_altivec.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * Copyright (c) 2012 Cameron Kaiser. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "./vp8_rtcd.h" +#include "vp8/common/loopfilter.h" +#include "vp8/common/onyxc_int.h" + +/* + * The actual declarations of these C routines are in ../loopfilter.h. + */ + +typedef void loop_filter_function_y_ppc +( + unsigned char *s, // source pointer + int p, // pitch + const unsigned char *flimit, + const unsigned char *limit, + const unsigned char *thresh +); + +typedef void loop_filter_function_uv_ppc +( + unsigned char *u, // source pointer + unsigned char *v, // source pointer + int p, // pitch + const unsigned char *flimit, + const unsigned char *limit, + const unsigned char *thresh +); + +typedef void loop_filter_function_s_ppc +( + unsigned char *s, // source pointer + int p, // pitch + const unsigned char *flimit +); + +// We can't use the regular prototypes for these, they're too old. +loop_filter_function_y_ppc mbloop_filter_horizontal_edge_y_ppc; +loop_filter_function_y_ppc mbloop_filter_vertical_edge_y_ppc; +loop_filter_function_y_ppc loop_filter_horizontal_edge_y_ppc; +loop_filter_function_y_ppc loop_filter_vertical_edge_y_ppc; + +loop_filter_function_uv_ppc mbloop_filter_horizontal_edge_uv_ppc; +loop_filter_function_uv_ppc mbloop_filter_vertical_edge_uv_ppc; +loop_filter_function_uv_ppc loop_filter_horizontal_edge_uv_ppc; +loop_filter_function_uv_ppc loop_filter_vertical_edge_uv_ppc; + +loop_filter_function_s_ppc loop_filter_simple_horizontal_edge_ppc; +loop_filter_function_s_ppc loop_filter_simple_vertical_edge_ppc; + +// Horizontal MB filtering +void vp8_loop_filter_mbh_altivec(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, + int y_stride, int uv_stride, loop_filter_info *lfi) +{ + mbloop_filter_horizontal_edge_y_ppc(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr); + + if (u_ptr || v_ptr) + mbloop_filter_horizontal_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr); +} + +// Vertical MB Filtering +void vp8_loop_filter_mbv_altivec(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, + int y_stride, int uv_stride, loop_filter_info *lfi) +{ + mbloop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr); + + if (u_ptr || v_ptr) + mbloop_filter_vertical_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr); +} + +// Horizontal B Filtering +void vp8_loop_filter_bh_altivec(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, + int y_stride, int uv_stride, loop_filter_info *lfi) +{ + // These should all be done at once with one call, instead of 3 + loop_filter_horizontal_edge_y_ppc(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr); + loop_filter_horizontal_edge_y_ppc(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr); + loop_filter_horizontal_edge_y_ppc(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr); + + if (u_ptr || v_ptr) + loop_filter_horizontal_edge_uv_ppc(u_ptr + 4 * uv_stride, v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr); +} + +void vp8_loop_filter_simple_bh_altivec(unsigned char *y_ptr, int y_stride, const unsigned char *blimit) +{ + loop_filter_simple_horizontal_edge_ppc(y_ptr + 4 * y_stride, y_stride, blimit); + loop_filter_simple_horizontal_edge_ppc(y_ptr + 8 * y_stride, y_stride, blimit); + loop_filter_simple_horizontal_edge_ppc(y_ptr + 12 * y_stride, y_stride, blimit); +} + +// Vertical B Filtering +void vp8_loop_filter_bv_altivec(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, + int y_stride, int uv_stride, loop_filter_info *lfi) +{ + loop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->blim, lfi->lim, lfi->hev_thr); + + if (u_ptr || v_ptr) + loop_filter_vertical_edge_uv_ppc(u_ptr + 4, v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr); +} + +void vp8_loop_filter_simple_bv_altivec(unsigned char *y_ptr, int y_stride, const unsigned char *blimit) +{ + loop_filter_simple_vertical_edge_ppc(y_ptr + 4, y_stride, blimit); + loop_filter_simple_vertical_edge_ppc(y_ptr + 8, y_stride, blimit); + loop_filter_simple_vertical_edge_ppc(y_ptr + 12, y_stride, blimit); +} + +// Miscellaneous simple filters + +void vp8_loop_filter_simple_mbh_altivec(unsigned char *y_ptr, int y_stride, const unsigned char *blimit) +{ + loop_filter_simple_horizontal_edge_ppc(y_ptr, y_stride, blimit); +} + +void vp8_loop_filter_simple_mbv_altivec(unsigned char *y_ptr, int y_stride, const unsigned char *blimit) +{ + loop_filter_simple_vertical_edge_ppc(y_ptr, y_stride, blimit); +} diff --git a/vp8/common/rtcd_defs.pl b/vp8/common/rtcd_defs.pl index 2da3f505e..bfc569da3 100644 --- a/vp8/common/rtcd_defs.pl +++ b/vp8/common/rtcd_defs.pl @@ -47,20 +47,20 @@ # Loopfilter # add_proto qw/void vp8_loop_filter_mbv/, "unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, int y_stride, int uv_stride, struct loop_filter_info *lfi"; -specialize qw/vp8_loop_filter_mbv sse2 neon dspr2 msa mmi lsx/; +specialize qw/vp8_loop_filter_mbv altivec sse2 neon dspr2 msa mmi lsx/; add_proto qw/void vp8_loop_filter_bv/, "unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, int y_stride, int uv_stride, struct loop_filter_info *lfi"; -specialize qw/vp8_loop_filter_bv sse2 neon dspr2 msa mmi lsx/; +specialize qw/vp8_loop_filter_bv altivec sse2 neon dspr2 msa mmi lsx/; add_proto qw/void vp8_loop_filter_mbh/, "unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, int y_stride, int uv_stride, struct loop_filter_info *lfi"; -specialize qw/vp8_loop_filter_mbh sse2 neon dspr2 msa mmi lsx/; +specialize qw/vp8_loop_filter_mbh altivec sse2 neon dspr2 msa mmi lsx/; add_proto qw/void vp8_loop_filter_bh/, "unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, int y_stride, int uv_stride, struct loop_filter_info *lfi"; -specialize qw/vp8_loop_filter_bh sse2 neon dspr2 msa mmi lsx/; +specialize qw/vp8_loop_filter_bh altivec sse2 neon dspr2 msa mmi lsx/; add_proto qw/void vp8_loop_filter_simple_mbv/, "unsigned char *y_ptr, int y_stride, const unsigned char *blimit"; -specialize qw/vp8_loop_filter_simple_mbv sse2 neon msa mmi/; +specialize qw/vp8_loop_filter_simple_mbv altivec sse2 neon msa mmi/; $vp8_loop_filter_simple_mbv_c=vp8_loop_filter_simple_vertical_edge_c; $vp8_loop_filter_simple_mbv_sse2=vp8_loop_filter_simple_vertical_edge_sse2; $vp8_loop_filter_simple_mbv_neon=vp8_loop_filter_mbvs_neon; @@ -68,7 +68,7 @@ $vp8_loop_filter_simple_mbv_mmi=vp8_loop_filter_simple_vertical_edge_mmi; add_proto qw/void vp8_loop_filter_simple_mbh/, "unsigned char *y_ptr, int y_stride, const unsigned char *blimit"; -specialize qw/vp8_loop_filter_simple_mbh sse2 neon msa mmi/; +specialize qw/vp8_loop_filter_simple_mbh altivec sse2 neon msa mmi/; $vp8_loop_filter_simple_mbh_c=vp8_loop_filter_simple_horizontal_edge_c; $vp8_loop_filter_simple_mbh_sse2=vp8_loop_filter_simple_horizontal_edge_sse2; $vp8_loop_filter_simple_mbh_neon=vp8_loop_filter_mbhs_neon; @@ -76,7 +76,7 @@ $vp8_loop_filter_simple_mbh_mmi=vp8_loop_filter_simple_horizontal_edge_mmi; add_proto qw/void vp8_loop_filter_simple_bv/, "unsigned char *y_ptr, int y_stride, const unsigned char *blimit"; -specialize qw/vp8_loop_filter_simple_bv sse2 neon msa mmi/; +specialize qw/vp8_loop_filter_simple_bv altivec sse2 neon msa mmi/; $vp8_loop_filter_simple_bv_c=vp8_loop_filter_bvs_c; $vp8_loop_filter_simple_bv_sse2=vp8_loop_filter_bvs_sse2; $vp8_loop_filter_simple_bv_neon=vp8_loop_filter_bvs_neon; @@ -84,7 +84,7 @@ $vp8_loop_filter_simple_bv_mmi=vp8_loop_filter_bvs_mmi; add_proto qw/void vp8_loop_filter_simple_bh/, "unsigned char *y_ptr, int y_stride, const unsigned char *blimit"; -specialize qw/vp8_loop_filter_simple_bh sse2 neon msa mmi/; +specialize qw/vp8_loop_filter_simple_bh altivec sse2 neon msa mmi/; $vp8_loop_filter_simple_bh_c=vp8_loop_filter_bhs_c; $vp8_loop_filter_simple_bh_sse2=vp8_loop_filter_bhs_sse2; $vp8_loop_filter_simple_bh_neon=vp8_loop_filter_bhs_neon; @@ -96,7 +96,7 @@ # #idct16 add_proto qw/void vp8_short_idct4x4llm/, "short *input, unsigned char *pred_ptr, int pred_stride, unsigned char *dst_ptr, int dst_stride"; -specialize qw/vp8_short_idct4x4llm mmx neon dspr2 msa mmi/; +specialize qw/vp8_short_idct4x4llm altivec mmx neon dspr2 msa mmi/; #iwalsh1 add_proto qw/void vp8_short_inv_walsh4x4_1/, "short *input, short *mb_dqcoeff"; @@ -104,23 +104,23 @@ #iwalsh16 add_proto qw/void vp8_short_inv_walsh4x4/, "short *input, short *mb_dqcoeff"; -specialize qw/vp8_short_inv_walsh4x4 sse2 neon dspr2 msa mmi/; +specialize qw/vp8_short_inv_walsh4x4 altivec sse2 neon dspr2 msa mmi/; #idct1_scalar_add add_proto qw/void vp8_dc_only_idct_add/, "short input_dc, unsigned char *pred_ptr, int pred_stride, unsigned char *dst_ptr, int dst_stride"; -specialize qw/vp8_dc_only_idct_add mmx neon dspr2 msa mmi lsx/; +specialize qw/vp8_dc_only_idct_add altivec mmx neon dspr2 msa mmi lsx/; # # RECON # add_proto qw/void vp8_copy_mem16x16/, "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride"; -specialize qw/vp8_copy_mem16x16 sse2 neon dspr2 msa mmi/; +specialize qw/vp8_copy_mem16x16 altivec sse2 neon dspr2 msa mmi/; add_proto qw/void vp8_copy_mem8x8/, "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride"; -specialize qw/vp8_copy_mem8x8 mmx neon dspr2 msa mmi/; +specialize qw/vp8_copy_mem8x8 altivec mmx neon dspr2 msa mmi/; add_proto qw/void vp8_copy_mem8x4/, "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride"; -specialize qw/vp8_copy_mem8x4 mmx neon dspr2 msa mmi/; +specialize qw/vp8_copy_mem8x4 altivec mmx neon dspr2 msa mmi/; # # Postproc diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk index 1bbcc987d..842133eff 100644 --- a/vp8/vp8_common.mk +++ b/vp8/vp8_common.mk @@ -149,4 +149,13 @@ VP8_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/mbloopfilter_neon.c VP8_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/shortidct4x4llm_neon.c VP8_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/sixtappredict_neon.c +# common (altivec) +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/idct_altivec.c +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/copy_altivec.c +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/loopfilter_altivec.c +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/loopfilter_filters_altivec.s +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/filter_altivec.s +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/filter_bilinear_altivec.s +VP8_COMMON_SRCS-$(HAVE_ALTIVEC) += common/ppc/recon_altivec.s + $(eval $(call rtcd_h_template,vp8_rtcd,vp8/common/rtcd_defs.pl)) --- a/vpx_ports/ppc_cpudetect.c 2026-07-09 21:33:23.000000000 +0800 +++ b/vpx_ports/ppc_cpudetect.c 2026-07-09 22:57:36.000000000 +0800 @@ -11,8 +11,11 @@ #include #include #include + +#ifdef __linux__ #include #include +#endif #include "./vpx_config.h" #include "vpx_ports/ppc.h"