mirror of
https://gitee.com/open-loongarch/buildroot.git
synced 2026-10-25 21:07:11 +08:00
655 lines
28 KiB
Diff
655 lines
28 KiB
Diff
From e1310e44ee7091de9fda143d4cd861b0c6340fe2 Mon Sep 17 00:00:00 2001
|
|
From: wanglu <wanglu@loongson.cn>
|
|
Date: Thu, 30 Mar 2023 16:28:21 +0800
|
|
Subject: [PATCH 09/10] swscale: [LA] Add yuv2rgb_X_template_lsx.
|
|
|
|
Change-Id: I71e6e56f43e5f3837cebe056c12081ea627508a2
|
|
Signed-off-by: wanglu <wanglu@loongson.cn>
|
|
---
|
|
libswscale/loongarch/Makefile | 3 +-
|
|
libswscale/loongarch/output_lasx.c | 4 -
|
|
libswscale/loongarch/output_lsx.c | 578 ++++++++++++++++++
|
|
libswscale/loongarch/swscale_init_loongarch.c | 1 +
|
|
libswscale/loongarch/swscale_loongarch.h | 2 +
|
|
5 files changed, 583 insertions(+), 5 deletions(-)
|
|
create mode 100644 libswscale/loongarch/output_lsx.c
|
|
|
|
diff --git a/libswscale/loongarch/Makefile b/libswscale/loongarch/Makefile
|
|
index f52e526514..8bb9254ca0 100644
|
|
--- a/libswscale/loongarch/Makefile
|
|
+++ b/libswscale/loongarch/Makefile
|
|
@@ -8,4 +8,5 @@ LSX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale.o \
|
|
loongarch/swscale_lsx.o \
|
|
loongarch/input.o \
|
|
loongarch/output.o \
|
|
- loongarch/yuv2rgb_lsx.o
|
|
+ loongarch/yuv2rgb_lsx.o \
|
|
+ loongarch/output_lsx.o
|
|
diff --git a/libswscale/loongarch/output_lasx.c b/libswscale/loongarch/output_lasx.c
|
|
index 4d4bba60c1..28ab970b1a 100644
|
|
--- a/libswscale/loongarch/output_lasx.c
|
|
+++ b/libswscale/loongarch/output_lasx.c
|
|
@@ -550,10 +550,6 @@ yuv2rgb_2_template_lasx(SwsContext *c, const int16_t *buf[2],
|
|
DUP2_ARG2(__lasx_xvldx, ubuf1, c_dex, vbuf1, c_dex, u1, v1);
|
|
DUP2_ARG2(__lasx_xvsllwil_w_h, y0, 0, y1, 0, y0_l, y1_l);
|
|
DUP2_ARG1(__lasx_xvexth_w_h, y0, y1, y0_h, y1_h);
|
|
- //DUP2_ARG1(__lasx_vext2xv_w_h, y0, y1, y0_l, y1_l);
|
|
- //y0 = __lasx_xvpermi_d(y0, 0x4E);
|
|
- //y1 = __lasx_xvpermi_d(y1, 0x4E);
|
|
- //DUP2_ARG1(__lasx_vext2xv_w_h, y0, y1, y0_h, y1_h);
|
|
DUP4_ARG1(__lasx_vext2xv_w_h, u0, u1, v0, v1, u0, u1, v0, v1);
|
|
y0_l = __lasx_xvmul_w(y0_l, v_yalpha1);
|
|
y0_h = __lasx_xvmul_w(y0_h, v_yalpha1);
|
|
diff --git a/libswscale/loongarch/output_lsx.c b/libswscale/loongarch/output_lsx.c
|
|
new file mode 100644
|
|
index 0000000000..5da9325c97
|
|
--- /dev/null
|
|
+++ b/libswscale/loongarch/output_lsx.c
|
|
@@ -0,0 +1,578 @@
|
|
+/*
|
|
+ * Copyright (C) 2023 Loongson Technology Corporation Limited
|
|
+ * Contributed by Lu Wang <wanglu@loongson.cn>
|
|
+ *
|
|
+ * This file is part of FFmpeg.
|
|
+ *
|
|
+ * FFmpeg is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * FFmpeg is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with FFmpeg; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#include "swscale_loongarch.h"
|
|
+#include "libavutil/loongarch/loongson_intrinsics.h"
|
|
+
|
|
+
|
|
+/*Copy from libswscale/output.c*/
|
|
+static av_always_inline void
|
|
+yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2,
|
|
+ unsigned A1, unsigned A2,
|
|
+ const void *_r, const void *_g, const void *_b, int y,
|
|
+ enum AVPixelFormat target, int hasAlpha)
|
|
+{
|
|
+ if (target == AV_PIX_FMT_ARGB || target == AV_PIX_FMT_RGBA ||
|
|
+ target == AV_PIX_FMT_ABGR || target == AV_PIX_FMT_BGRA) {
|
|
+ uint32_t *dest = (uint32_t *) _dest;
|
|
+ const uint32_t *r = (const uint32_t *) _r;
|
|
+ const uint32_t *g = (const uint32_t *) _g;
|
|
+ const uint32_t *b = (const uint32_t *) _b;
|
|
+
|
|
+#if CONFIG_SMALL
|
|
+ dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1];
|
|
+ dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2];
|
|
+#else
|
|
+#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
|
|
+ int sh = (target == AV_PIX_FMT_RGB32_1 ||
|
|
+ target == AV_PIX_FMT_BGR32_1) ? 0 : 24;
|
|
+ av_assert2((((r[Y1] + g[Y1] + b[Y1]) >> sh) & 0xFF) == 0xFF);
|
|
+#endif
|
|
+ dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1];
|
|
+ dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2];
|
|
+#endif
|
|
+ } else if (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) {
|
|
+ uint8_t *dest = (uint8_t *) _dest;
|
|
+ const uint8_t *r = (const uint8_t *) _r;
|
|
+ const uint8_t *g = (const uint8_t *) _g;
|
|
+ const uint8_t *b = (const uint8_t *) _b;
|
|
+
|
|
+#define r_b ((target == AV_PIX_FMT_RGB24) ? r : b)
|
|
+#define b_r ((target == AV_PIX_FMT_RGB24) ? b : r)
|
|
+
|
|
+ dest[i * 6 + 0] = r_b[Y1];
|
|
+ dest[i * 6 + 1] = g[Y1];
|
|
+ dest[i * 6 + 2] = b_r[Y1];
|
|
+ dest[i * 6 + 3] = r_b[Y2];
|
|
+ dest[i * 6 + 4] = g[Y2];
|
|
+ dest[i * 6 + 5] = b_r[Y2];
|
|
+#undef r_b
|
|
+#undef b_r
|
|
+ } else if (target == AV_PIX_FMT_RGB565 || target == AV_PIX_FMT_BGR565 ||
|
|
+ target == AV_PIX_FMT_RGB555 || target == AV_PIX_FMT_BGR555 ||
|
|
+ target == AV_PIX_FMT_RGB444 || target == AV_PIX_FMT_BGR444) {
|
|
+ uint16_t *dest = (uint16_t *) _dest;
|
|
+ const uint16_t *r = (const uint16_t *) _r;
|
|
+ const uint16_t *g = (const uint16_t *) _g;
|
|
+ const uint16_t *b = (const uint16_t *) _b;
|
|
+ int dr1, dg1, db1, dr2, dg2, db2;
|
|
+
|
|
+ if (target == AV_PIX_FMT_RGB565 || target == AV_PIX_FMT_BGR565) {
|
|
+ dr1 = ff_dither_2x2_8[ y & 1 ][0];
|
|
+ dg1 = ff_dither_2x2_4[ y & 1 ][0];
|
|
+ db1 = ff_dither_2x2_8[(y & 1) ^ 1][0];
|
|
+ dr2 = ff_dither_2x2_8[ y & 1 ][1];
|
|
+ dg2 = ff_dither_2x2_4[ y & 1 ][1];
|
|
+ db2 = ff_dither_2x2_8[(y & 1) ^ 1][1];
|
|
+ } else if (target == AV_PIX_FMT_RGB555 || target == AV_PIX_FMT_BGR555) {
|
|
+ dr1 = ff_dither_2x2_8[ y & 1 ][0];
|
|
+ dg1 = ff_dither_2x2_8[ y & 1 ][1];
|
|
+ db1 = ff_dither_2x2_8[(y & 1) ^ 1][0];
|
|
+ dr2 = ff_dither_2x2_8[ y & 1 ][1];
|
|
+ dg2 = ff_dither_2x2_8[ y & 1 ][0];
|
|
+ db2 = ff_dither_2x2_8[(y & 1) ^ 1][1];
|
|
+ } else {
|
|
+ dr1 = ff_dither_4x4_16[ y & 3 ][0];
|
|
+ dg1 = ff_dither_4x4_16[ y & 3 ][1];
|
|
+ db1 = ff_dither_4x4_16[(y & 3) ^ 3][0];
|
|
+ dr2 = ff_dither_4x4_16[ y & 3 ][1];
|
|
+ dg2 = ff_dither_4x4_16[ y & 3 ][0];
|
|
+ db2 = ff_dither_4x4_16[(y & 3) ^ 3][1];
|
|
+ }
|
|
+
|
|
+ dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
|
|
+ dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
|
|
+ } else { /* 8/4 bits */
|
|
+ uint8_t *dest = (uint8_t *) _dest;
|
|
+ const uint8_t *r = (const uint8_t *) _r;
|
|
+ const uint8_t *g = (const uint8_t *) _g;
|
|
+ const uint8_t *b = (const uint8_t *) _b;
|
|
+ int dr1, dg1, db1, dr2, dg2, db2;
|
|
+
|
|
+ if (target == AV_PIX_FMT_RGB8 || target == AV_PIX_FMT_BGR8) {
|
|
+ const uint8_t * const d64 = ff_dither_8x8_73[y & 7];
|
|
+ const uint8_t * const d32 = ff_dither_8x8_32[y & 7];
|
|
+ dr1 = dg1 = d32[(i * 2 + 0) & 7];
|
|
+ db1 = d64[(i * 2 + 0) & 7];
|
|
+ dr2 = dg2 = d32[(i * 2 + 1) & 7];
|
|
+ db2 = d64[(i * 2 + 1) & 7];
|
|
+ } else {
|
|
+ const uint8_t * const d64 = ff_dither_8x8_73 [y & 7];
|
|
+ const uint8_t * const d128 = ff_dither_8x8_220[y & 7];
|
|
+ dr1 = db1 = d128[(i * 2 + 0) & 7];
|
|
+ dg1 = d64[(i * 2 + 0) & 7];
|
|
+ dr2 = db2 = d128[(i * 2 + 1) & 7];
|
|
+ dg2 = d64[(i * 2 + 1) & 7];
|
|
+ }
|
|
+
|
|
+ if (target == AV_PIX_FMT_RGB4 || target == AV_PIX_FMT_BGR4) {
|
|
+ dest[i] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1] +
|
|
+ ((r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]) << 4);
|
|
+ } else {
|
|
+ dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
|
|
+ dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+#define WRITE_YUV2RGB_LSX(vec_y1, vec_y2, vec_u, vec_v, t1, t2, t3, t4) \
|
|
+{ \
|
|
+ Y1 = __lsx_vpickve2gr_w(vec_y1, t1); \
|
|
+ Y2 = __lsx_vpickve2gr_w(vec_y2, t2); \
|
|
+ U = __lsx_vpickve2gr_w(vec_u, t3); \
|
|
+ V = __lsx_vpickve2gr_w(vec_v, t4); \
|
|
+ r = c->table_rV[V]; \
|
|
+ g = (c->table_gU[U] + c->table_gV[V]); \
|
|
+ b = c->table_bU[U]; \
|
|
+ yuv2rgb_write(dest, count, Y1, Y2, 0, 0, \
|
|
+ r, g, b, y, target, 0); \
|
|
+ count++; \
|
|
+}
|
|
+
|
|
+static void
|
|
+yuv2rgb_X_template_lsx(SwsContext *c, const int16_t *lumFilter,
|
|
+ const int16_t **lumSrc, int lumFilterSize,
|
|
+ const int16_t *chrFilter, const int16_t **chrUSrc,
|
|
+ const int16_t **chrVSrc, int chrFilterSize,
|
|
+ const int16_t **alpSrc, uint8_t *dest, int dstW,
|
|
+ int y, enum AVPixelFormat target, int hasAlpha)
|
|
+{
|
|
+ int i, j;
|
|
+ int count = 0;
|
|
+ int t = 1 << 18;
|
|
+ int len = dstW >> 5;
|
|
+ int res = dstW & 31;
|
|
+ int len_count = (dstW + 1) >> 1;
|
|
+ const void *r, *g, *b;
|
|
+ int head = YUVRGB_TABLE_HEADROOM;
|
|
+ __m128i headroom = __lsx_vreplgr2vr_w(head);
|
|
+
|
|
+ for (i = 0; i < len; i++) {
|
|
+ int Y1, Y2, U, V, count_lum = count << 1;
|
|
+ __m128i l_src1, l_src2, l_src3, l_src4, u_src1, u_src2, v_src1, v_src2;
|
|
+ __m128i yl_ev, yl_ev1, yl_ev2, yl_od1, yl_od2, yh_ev1, yh_ev2, yh_od1, yh_od2;
|
|
+ __m128i u_ev1, u_ev2, u_od1, u_od2, v_ev1, v_ev2, v_od1, v_od2, temp;
|
|
+
|
|
+ yl_ev = __lsx_vldrepl_w(&t, 0);
|
|
+ yl_ev1 = yl_ev;
|
|
+ yl_od1 = yl_ev;
|
|
+ yh_ev1 = yl_ev;
|
|
+ yh_od1 = yl_ev;
|
|
+ u_ev1 = yl_ev;
|
|
+ v_ev1 = yl_ev;
|
|
+ u_od1 = yl_ev;
|
|
+ v_od1 = yl_ev;
|
|
+ yl_ev2 = yl_ev;
|
|
+ yl_od2 = yl_ev;
|
|
+ yh_ev2 = yl_ev;
|
|
+ yh_od2 = yl_ev;
|
|
+ u_ev2 = yl_ev;
|
|
+ v_ev2 = yl_ev;
|
|
+ u_od2 = yl_ev;
|
|
+ v_od2 = yl_ev;
|
|
+
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ temp = __lsx_vldrepl_h((lumFilter + j), 0);
|
|
+ DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 0, lumSrc[j] + count_lum,
|
|
+ 16, l_src1, l_src2);
|
|
+ DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 32, lumSrc[j] + count_lum,
|
|
+ 48, l_src3, l_src4);
|
|
+ yl_ev1 = __lsx_vmaddwev_w_h(yl_ev1, temp, l_src1);
|
|
+ yl_od1 = __lsx_vmaddwod_w_h(yl_od1, temp, l_src1);
|
|
+ yh_ev1 = __lsx_vmaddwev_w_h(yh_ev1, temp, l_src3);
|
|
+ yh_od1 = __lsx_vmaddwod_w_h(yh_od1, temp, l_src3);
|
|
+ yl_ev2 = __lsx_vmaddwev_w_h(yl_ev2, temp, l_src2);
|
|
+ yl_od2 = __lsx_vmaddwod_w_h(yl_od2, temp, l_src2);
|
|
+ yh_ev2 = __lsx_vmaddwev_w_h(yh_ev2, temp, l_src4);
|
|
+ yh_od2 = __lsx_vmaddwod_w_h(yh_od2, temp, l_src4);
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0,
|
|
+ u_src1, v_src1);
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 16, chrVSrc[j] + count, 16,
|
|
+ u_src2, v_src2);
|
|
+ temp = __lsx_vldrepl_h((chrFilter + j), 0);
|
|
+ u_ev1 = __lsx_vmaddwev_w_h(u_ev1, temp, u_src1);
|
|
+ u_od1 = __lsx_vmaddwod_w_h(u_od1, temp, u_src1);
|
|
+ v_ev1 = __lsx_vmaddwev_w_h(v_ev1, temp, v_src1);
|
|
+ v_od1 = __lsx_vmaddwod_w_h(v_od1, temp, v_src1);
|
|
+ u_ev2 = __lsx_vmaddwev_w_h(u_ev2, temp, u_src2);
|
|
+ u_od2 = __lsx_vmaddwod_w_h(u_od2, temp, u_src2);
|
|
+ v_ev2 = __lsx_vmaddwev_w_h(v_ev2, temp, v_src2);
|
|
+ v_od2 = __lsx_vmaddwod_w_h(v_od2, temp, v_src2);
|
|
+ }
|
|
+ yl_ev1 = __lsx_vsrai_w(yl_ev1, 19);
|
|
+ yh_ev1 = __lsx_vsrai_w(yh_ev1, 19);
|
|
+ yl_od1 = __lsx_vsrai_w(yl_od1, 19);
|
|
+ yh_od1 = __lsx_vsrai_w(yh_od1, 19);
|
|
+ u_ev1 = __lsx_vsrai_w(u_ev1, 19);
|
|
+ v_ev1 = __lsx_vsrai_w(v_ev1, 19);
|
|
+ u_od1 = __lsx_vsrai_w(u_od1, 19);
|
|
+ v_od1 = __lsx_vsrai_w(v_od1, 19);
|
|
+ yl_ev2 = __lsx_vsrai_w(yl_ev2, 19);
|
|
+ yh_ev2 = __lsx_vsrai_w(yh_ev2, 19);
|
|
+ yl_od2 = __lsx_vsrai_w(yl_od2, 19);
|
|
+ yh_od2 = __lsx_vsrai_w(yh_od2, 19);
|
|
+ u_ev2 = __lsx_vsrai_w(u_ev2, 19);
|
|
+ v_ev2 = __lsx_vsrai_w(v_ev2, 19);
|
|
+ u_od2 = __lsx_vsrai_w(u_od2, 19);
|
|
+ v_od2 = __lsx_vsrai_w(v_od2, 19);
|
|
+ u_ev1 = __lsx_vadd_w(u_ev1, headroom);
|
|
+ v_ev1 = __lsx_vadd_w(v_ev1, headroom);
|
|
+ u_od1 = __lsx_vadd_w(u_od1, headroom);
|
|
+ v_od1 = __lsx_vadd_w(v_od1, headroom);
|
|
+ u_ev2 = __lsx_vadd_w(u_ev2, headroom);
|
|
+ v_ev2 = __lsx_vadd_w(v_ev2, headroom);
|
|
+ u_od2 = __lsx_vadd_w(u_od2, headroom);
|
|
+ v_od2 = __lsx_vadd_w(v_od2, headroom);
|
|
+
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 0, 0, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 1, 1, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 2, 2, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 3, 3, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 0, 0, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 1, 1, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 2, 2, 3, 3);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 3, 3, 3, 3);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_ev2, v_ev2, 0, 0, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_od2, v_od2, 1, 1, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_ev2, v_ev2, 2, 2, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev1, yh_od1, u_od2, v_od2, 3, 3, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_ev2, v_ev2, 0, 0, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_od2, v_od2, 1, 1, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_ev2, v_ev2, 2, 2, 3, 3);
|
|
+ WRITE_YUV2RGB_LSX(yh_ev2, yh_od2, u_od2, v_od2, 3, 3, 3, 3);
|
|
+ }
|
|
+
|
|
+ if (res >= 16) {
|
|
+ int Y1, Y2, U, V, count_lum = count << 1;
|
|
+ __m128i l_src1, l_src2, u_src1, v_src1;
|
|
+ __m128i yl_ev, yl_ev1, yl_ev2, yl_od1, yl_od2;
|
|
+ __m128i u_ev1, u_od1, v_ev1, v_od1, temp;
|
|
+
|
|
+ yl_ev = __lsx_vldrepl_w(&t, 0);
|
|
+ yl_ev1 = yl_ev;
|
|
+ yl_od1 = yl_ev;
|
|
+ u_ev1 = yl_ev;
|
|
+ v_ev1 = yl_ev;
|
|
+ u_od1 = yl_ev;
|
|
+ v_od1 = yl_ev;
|
|
+ yl_ev2 = yl_ev;
|
|
+ yl_od2 = yl_ev;
|
|
+
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ temp = __lsx_vldrepl_h((lumFilter + j), 0);
|
|
+ DUP2_ARG2(__lsx_vld, lumSrc[j] + count_lum, 0, lumSrc[j] + count_lum,
|
|
+ 16, l_src1, l_src2);
|
|
+ yl_ev1 = __lsx_vmaddwev_w_h(yl_ev1, temp, l_src1);
|
|
+ yl_od1 = __lsx_vmaddwod_w_h(yl_od1, temp, l_src1);
|
|
+ yl_ev2 = __lsx_vmaddwev_w_h(yl_ev2, temp, l_src2);
|
|
+ yl_od2 = __lsx_vmaddwod_w_h(yl_od2, temp, l_src2);
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0,
|
|
+ u_src1, v_src1);
|
|
+ temp = __lsx_vldrepl_h((chrFilter + j), 0);
|
|
+ u_ev1 = __lsx_vmaddwev_w_h(u_ev1, temp, u_src1);
|
|
+ u_od1 = __lsx_vmaddwod_w_h(u_od1, temp, u_src1);
|
|
+ v_ev1 = __lsx_vmaddwev_w_h(v_ev1, temp, v_src1);
|
|
+ v_od1 = __lsx_vmaddwod_w_h(v_od1, temp, v_src1);
|
|
+ }
|
|
+ yl_ev1 = __lsx_vsrai_w(yl_ev1, 19);
|
|
+ yl_od1 = __lsx_vsrai_w(yl_od1, 19);
|
|
+ u_ev1 = __lsx_vsrai_w(u_ev1, 19);
|
|
+ v_ev1 = __lsx_vsrai_w(v_ev1, 19);
|
|
+ u_od1 = __lsx_vsrai_w(u_od1, 19);
|
|
+ v_od1 = __lsx_vsrai_w(v_od1, 19);
|
|
+ yl_ev2 = __lsx_vsrai_w(yl_ev2, 19);
|
|
+ yl_od2 = __lsx_vsrai_w(yl_od2, 19);
|
|
+ u_ev1 = __lsx_vadd_w(u_ev1, headroom);
|
|
+ v_ev1 = __lsx_vadd_w(v_ev1, headroom);
|
|
+ u_od1 = __lsx_vadd_w(u_od1, headroom);
|
|
+ v_od1 = __lsx_vadd_w(v_od1, headroom);
|
|
+
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 0, 0, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 1, 1, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_ev1, v_ev1, 2, 2, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev1, yl_od1, u_od1, v_od1, 3, 3, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 0, 0, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 1, 1, 2, 2);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_ev1, v_ev1, 2, 2, 3, 3);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev2, yl_od2, u_od1, v_od1, 3, 3, 3, 3);
|
|
+ res -= 16;
|
|
+ }
|
|
+
|
|
+ if (res >= 8) {
|
|
+ int Y1, Y2, U, V, count_lum = count << 1;
|
|
+ __m128i l_src1, u_src, v_src;
|
|
+ __m128i yl_ev, yl_od;
|
|
+ __m128i u_ev, u_od, v_ev, v_od, temp;
|
|
+
|
|
+ yl_ev = __lsx_vldrepl_w(&t, 0);
|
|
+ yl_od = yl_ev;
|
|
+ u_ev = yl_ev;
|
|
+ v_ev = yl_ev;
|
|
+ u_od = yl_ev;
|
|
+ v_od = yl_ev;
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ temp = __lsx_vldrepl_h((lumFilter + j), 0);
|
|
+ l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0);
|
|
+ yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1);
|
|
+ yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1);
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0,
|
|
+ u_src, v_src);
|
|
+ temp = __lsx_vldrepl_h((chrFilter + j), 0);
|
|
+ u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src);
|
|
+ u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src);
|
|
+ v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src);
|
|
+ v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src);
|
|
+ }
|
|
+ yl_ev = __lsx_vsrai_w(yl_ev, 19);
|
|
+ yl_od = __lsx_vsrai_w(yl_od, 19);
|
|
+ u_ev = __lsx_vsrai_w(u_ev, 19);
|
|
+ v_ev = __lsx_vsrai_w(v_ev, 19);
|
|
+ u_od = __lsx_vsrai_w(u_od, 19);
|
|
+ v_od = __lsx_vsrai_w(v_od, 19);
|
|
+ u_ev = __lsx_vadd_w(u_ev, headroom);
|
|
+ v_ev = __lsx_vadd_w(v_ev, headroom);
|
|
+ u_od = __lsx_vadd_w(u_od, headroom);
|
|
+ v_od = __lsx_vadd_w(v_od, headroom);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 1, 1, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 2, 2, 1, 1);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 3, 3, 1, 1);
|
|
+ res -= 8;
|
|
+ }
|
|
+
|
|
+ if (res >= 4) {
|
|
+ int Y1, Y2, U, V, count_lum = count << 1;
|
|
+ __m128i l_src1, u_src, v_src;
|
|
+ __m128i yl_ev, yl_od;
|
|
+ __m128i u_ev, u_od, v_ev, v_od, temp;
|
|
+
|
|
+ yl_ev = __lsx_vldrepl_w(&t, 0);
|
|
+ yl_od = yl_ev;
|
|
+ u_ev = yl_ev;
|
|
+ v_ev = yl_ev;
|
|
+ u_od = yl_ev;
|
|
+ v_od = yl_ev;
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ temp = __lsx_vldrepl_h((lumFilter + j), 0);
|
|
+ l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0);
|
|
+ yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1);
|
|
+ yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1);
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0,
|
|
+ u_src, v_src);
|
|
+ temp = __lsx_vldrepl_h((chrFilter + j), 0);
|
|
+ u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src);
|
|
+ u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src);
|
|
+ v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src);
|
|
+ v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src);
|
|
+ }
|
|
+ yl_ev = __lsx_vsrai_w(yl_ev, 19);
|
|
+ yl_od = __lsx_vsrai_w(yl_od, 19);
|
|
+ u_ev = __lsx_vsrai_w(u_ev, 19);
|
|
+ v_ev = __lsx_vsrai_w(v_ev, 19);
|
|
+ u_od = __lsx_vsrai_w(u_od, 19);
|
|
+ v_od = __lsx_vsrai_w(v_od, 19);
|
|
+ u_ev = __lsx_vadd_w(u_ev, headroom);
|
|
+ v_ev = __lsx_vadd_w(v_ev, headroom);
|
|
+ u_od = __lsx_vadd_w(u_od, headroom);
|
|
+ v_od = __lsx_vadd_w(v_od, headroom);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_od, v_od, 1, 1, 0, 0);
|
|
+ res -= 4;
|
|
+ }
|
|
+
|
|
+ if (res >= 2) {
|
|
+ int Y1, Y2, U, V, count_lum = count << 1;
|
|
+ __m128i l_src1, u_src, v_src;
|
|
+ __m128i yl_ev, yl_od;
|
|
+ __m128i u_ev, u_od, v_ev, v_od, temp;
|
|
+
|
|
+ yl_ev = __lsx_vldrepl_w(&t, 0);
|
|
+ yl_od = yl_ev;
|
|
+ u_ev = yl_ev;
|
|
+ v_ev = yl_ev;
|
|
+ u_od = yl_ev;
|
|
+ v_od = yl_ev;
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ temp = __lsx_vldrepl_h((lumFilter + j), 0);
|
|
+ l_src1 = __lsx_vld(lumSrc[j] + count_lum, 0);
|
|
+ yl_ev = __lsx_vmaddwev_w_h(yl_ev, temp, l_src1);
|
|
+ yl_od = __lsx_vmaddwod_w_h(yl_od, temp, l_src1);
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ DUP2_ARG2(__lsx_vld, chrUSrc[j] + count, 0, chrVSrc[j] + count, 0,
|
|
+ u_src, v_src);
|
|
+ temp = __lsx_vldrepl_h((chrFilter + j), 0);
|
|
+ u_ev = __lsx_vmaddwev_w_h(u_ev, temp, u_src);
|
|
+ u_od = __lsx_vmaddwod_w_h(u_od, temp, u_src);
|
|
+ v_ev = __lsx_vmaddwev_w_h(v_ev, temp, v_src);
|
|
+ v_od = __lsx_vmaddwod_w_h(v_od, temp, v_src);
|
|
+ }
|
|
+ yl_ev = __lsx_vsrai_w(yl_ev, 19);
|
|
+ yl_od = __lsx_vsrai_w(yl_od, 19);
|
|
+ u_ev = __lsx_vsrai_w(u_ev, 19);
|
|
+ v_ev = __lsx_vsrai_w(v_ev, 19);
|
|
+ u_od = __lsx_vsrai_w(u_od, 19);
|
|
+ v_od = __lsx_vsrai_w(v_od, 19);
|
|
+ u_ev = __lsx_vadd_w(u_ev, headroom);
|
|
+ v_ev = __lsx_vadd_w(v_ev, headroom);
|
|
+ u_od = __lsx_vadd_w(u_od, headroom);
|
|
+ v_od = __lsx_vadd_w(v_od, headroom);
|
|
+ WRITE_YUV2RGB_LSX(yl_ev, yl_od, u_ev, v_ev, 0, 0, 0, 0);
|
|
+ res -= 2;
|
|
+ }
|
|
+
|
|
+ for (; count < len_count; count++) {
|
|
+ int Y1 = 1 << 18;
|
|
+ int Y2 = Y1;
|
|
+ int U = Y1;
|
|
+ int V = Y1;
|
|
+
|
|
+ for (j = 0; j < lumFilterSize; j++) {
|
|
+ Y1 += lumSrc[j][count * 2] * lumFilter[j];
|
|
+ Y2 += lumSrc[j][count * 2 + 1] * lumFilter[j];
|
|
+ }
|
|
+ for (j = 0; j < chrFilterSize; j++) {
|
|
+ U += chrUSrc[j][count] * chrFilter[j];
|
|
+ V += chrVSrc[j][count] * chrFilter[j];
|
|
+ }
|
|
+ Y1 >>= 19;
|
|
+ Y2 >>= 19;
|
|
+ U >>= 19;
|
|
+ V >>= 19;
|
|
+ r = c->table_rV[V + YUVRGB_TABLE_HEADROOM];
|
|
+ g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] +
|
|
+ c->table_gV[V + YUVRGB_TABLE_HEADROOM]);
|
|
+ b = c->table_bU[U + YUVRGB_TABLE_HEADROOM];
|
|
+
|
|
+ yuv2rgb_write(dest, count, Y1, Y2, 0, 0,
|
|
+ r, g, b, y, target, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+#define YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \
|
|
+static void name ## ext ## _X_lsx(SwsContext *c, const int16_t *lumFilter, \
|
|
+ const int16_t **lumSrc, int lumFilterSize, \
|
|
+ const int16_t *chrFilter, const int16_t **chrUSrc, \
|
|
+ const int16_t **chrVSrc, int chrFilterSize, \
|
|
+ const int16_t **alpSrc, uint8_t *dest, int dstW, \
|
|
+ int y) \
|
|
+{ \
|
|
+ name ## base ## _X_template_lsx(c, lumFilter, lumSrc, lumFilterSize, \
|
|
+ chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
|
|
+ alpSrc, dest, dstW, y, fmt, hasAlpha); \
|
|
+}
|
|
+
|
|
+
|
|
+#if CONFIG_SMALL
|
|
+#else
|
|
+#if CONFIG_SWSCALE_ALPHA
|
|
+#endif
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, x32_1, AV_PIX_FMT_RGB32_1, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, x32, AV_PIX_FMT_RGB32, 0)
|
|
+#endif
|
|
+YUV2RGBWRAPPERX(yuv2, rgb, rgb24, AV_PIX_FMT_RGB24, 0)
|
|
+YUV2RGBWRAPPERX(yuv2, rgb, bgr24, AV_PIX_FMT_BGR24, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 16, AV_PIX_FMT_RGB565, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 15, AV_PIX_FMT_RGB555, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 12, AV_PIX_FMT_RGB444, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 8, AV_PIX_FMT_RGB8, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 4, AV_PIX_FMT_RGB4, 0)
|
|
+YUV2RGBWRAPPERX(yuv2rgb,, 4b, AV_PIX_FMT_RGB4_BYTE, 0)
|
|
+
|
|
+av_cold void ff_sws_init_output_lsx(SwsContext *c)
|
|
+{
|
|
+
|
|
+ if(c->flags & SWS_FULL_CHR_H_INT) {
|
|
+ } else {
|
|
+ switch (c->dstFormat) {
|
|
+ case AV_PIX_FMT_RGB32:
|
|
+ case AV_PIX_FMT_BGR32:
|
|
+#if CONFIG_SMALL
|
|
+#else
|
|
+#if CONFIG_SWSCALE_ALPHA
|
|
+ if (c->needAlpha) {
|
|
+ } else
|
|
+#endif /* CONFIG_SWSCALE_ALPHA */
|
|
+ {
|
|
+ c->yuv2packedX = yuv2rgbx32_X_lsx;
|
|
+ }
|
|
+#endif /* !CONFIG_SMALL */
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB32_1:
|
|
+ case AV_PIX_FMT_BGR32_1:
|
|
+#if CONFIG_SMALL
|
|
+#else
|
|
+#if CONFIG_SWSCALE_ALPHA
|
|
+ if (c->needAlpha) {
|
|
+ } else
|
|
+#endif /* CONFIG_SWSCALE_ALPHA */
|
|
+ {
|
|
+ c->yuv2packedX = yuv2rgbx32_1_X_lsx;
|
|
+ }
|
|
+#endif /* !CONFIG_SMALL */
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB24:
|
|
+ c->yuv2packedX = yuv2rgb24_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_BGR24:
|
|
+ c->yuv2packedX = yuv2bgr24_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB565LE:
|
|
+ case AV_PIX_FMT_RGB565BE:
|
|
+ case AV_PIX_FMT_BGR565LE:
|
|
+ case AV_PIX_FMT_BGR565BE:
|
|
+ c->yuv2packedX = yuv2rgb16_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB555LE:
|
|
+ case AV_PIX_FMT_RGB555BE:
|
|
+ case AV_PIX_FMT_BGR555LE:
|
|
+ case AV_PIX_FMT_BGR555BE:
|
|
+ c->yuv2packedX = yuv2rgb15_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB444LE:
|
|
+ case AV_PIX_FMT_RGB444BE:
|
|
+ case AV_PIX_FMT_BGR444LE:
|
|
+ case AV_PIX_FMT_BGR444BE:
|
|
+ c->yuv2packedX = yuv2rgb12_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB8:
|
|
+ case AV_PIX_FMT_BGR8:
|
|
+ c->yuv2packedX = yuv2rgb8_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB4:
|
|
+ case AV_PIX_FMT_BGR4:
|
|
+ c->yuv2packedX = yuv2rgb4_X_lsx;
|
|
+ break;
|
|
+ case AV_PIX_FMT_RGB4_BYTE:
|
|
+ case AV_PIX_FMT_BGR4_BYTE:
|
|
+ c->yuv2packedX = yuv2rgb4b_X_lsx;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/libswscale/loongarch/swscale_init_loongarch.c b/libswscale/loongarch/swscale_init_loongarch.c
|
|
index a3d056812d..e08f68f7ba 100644
|
|
--- a/libswscale/loongarch/swscale_init_loongarch.c
|
|
+++ b/libswscale/loongarch/swscale_init_loongarch.c
|
|
@@ -28,6 +28,7 @@ av_cold void ff_sws_init_swscale_loongarch(SwsContext *c)
|
|
{
|
|
int cpu_flags = av_get_cpu_flags();
|
|
if (have_lsx(cpu_flags)) {
|
|
+ ff_sws_init_output_lsx(c);
|
|
if (c->srcBpc == 8) {
|
|
if (c->dstBpc <= 14) {
|
|
c->hyScale = c->hcScale = ff_hscale_8_to_15_lsx;
|
|
diff --git a/libswscale/loongarch/swscale_loongarch.h b/libswscale/loongarch/swscale_loongarch.h
|
|
index 3d502e6ab0..7e6cc87ddf 100644
|
|
--- a/libswscale/loongarch/swscale_loongarch.h
|
|
+++ b/libswscale/loongarch/swscale_loongarch.h
|
|
@@ -77,6 +77,8 @@ int yuv420_argb32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[],
|
|
int yuv420_abgr32_lsx(SwsContext *c, const uint8_t *src[], int srcStride[],
|
|
int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]);
|
|
|
|
+av_cold void ff_sws_init_output_lsx(SwsContext *c);
|
|
+
|
|
void ff_hscale_8_to_15_lasx(SwsContext *c, int16_t *dst, int dstW,
|
|
const uint8_t *src, const int16_t *filter,
|
|
const int32_t *filterPos, int filterSize);
|
|
--
|
|
2.20.1
|
|
|