This commit is contained in:
2025-08-27 15:09:05 +09:00
parent 57961d84de
commit a13f66d917
9896 changed files with 2193048 additions and 730 deletions
+13
View File
@@ -0,0 +1,13 @@
OBJS-$(CONFIG_SWSCALE) += loongarch/swscale_init_loongarch.o
LASX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale_lasx.o \
loongarch/input_lasx.o \
loongarch/yuv2rgb_lasx.o \
loongarch/rgb2rgb_lasx.o \
loongarch/output_lasx.o
LSX-OBJS-$(CONFIG_SWSCALE) += loongarch/swscale.o \
loongarch/swscale_lsx.o \
loongarch/input.o \
loongarch/output.o \
loongarch/output_lsx.o \
loongarch/input_lsx.o \
loongarch/yuv2rgb_lsx.o
+780
View File
@@ -0,0 +1,780 @@
/*
* Loongson LSX optimized swscale
*
* 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 "libavcodec/loongarch/loongson_asm.S"
/* void planar_rgb_to_y_lsx(uint8_t *_dst, const uint8_t *src[4],
* int width, int32_t *rgb2yuv)
*/
function planar_rgb_to_y_lsx
ld.d a5, a1, 0
ld.d a6, a1, 8
ld.d a7, a1, 16
ld.w t1, a3, 0 // ry
ld.w t2, a3, 4 // gy
ld.w t3, a3, 8 // by
li.w t4, 9
li.w t5, 524544
li.w t7, 4
li.w t8, 8
vldi vr7, 0
vreplgr2vr.w vr1, t1
vreplgr2vr.w vr2, t2
vreplgr2vr.w vr3, t3
vreplgr2vr.w vr4, t4
vreplgr2vr.w vr5, t5
bge a2, t8, .WIDTH8
bge a2, t7, .WIDTH4
blt zero, a2, .WIDTH
b .END
.WIDTH8:
vld vr8, a5, 0
vld vr9, a6, 0
vld vr10, a7, 0
vilvl.b vr11, vr7, vr8
vilvl.b vr12, vr7, vr9
vilvl.b vr13, vr7, vr10
vilvl.h vr14, vr7, vr11
vilvl.h vr15, vr7, vr12
vilvl.h vr16, vr7, vr13
vilvh.h vr17, vr7, vr11
vilvh.h vr18, vr7, vr12
vilvh.h vr19, vr7, vr13
vmul.w vr20, vr1, vr16
vmul.w vr21, vr1, vr19
vmadd.w vr20, vr2, vr14
vmadd.w vr20, vr3, vr15
vmadd.w vr21, vr2, vr17
vmadd.w vr21, vr3, vr18
vadd.w vr20, vr20, vr5
vadd.w vr21, vr21, vr5
vsra.w vr20, vr20, vr4
vsra.w vr21, vr21, vr4
vpickev.h vr20, vr21, vr20
vst vr20, a0, 0
addi.d a2, a2, -8
addi.d a5, a5, 8
addi.d a6, a6, 8
addi.d a7, a7, 8
addi.d a0, a0, 16
bge a2, t8, .WIDTH8
bge a2, t7, .WIDTH4
blt zero, a2, .WIDTH
b .END
.WIDTH4:
vld vr8, a5, 0
vld vr9, a6, 0
vld vr10, a7, 0
vilvl.b vr11, vr7, vr8
vilvl.b vr12, vr7, vr9
vilvl.b vr13, vr7, vr10
vilvl.h vr14, vr7, vr11
vilvl.h vr15, vr7, vr12
vilvl.h vr16, vr7, vr13
vmul.w vr17, vr1, vr16
vmadd.w vr17, vr2, vr14
vmadd.w vr17, vr3, vr15
vadd.w vr17, vr17, vr5
vsra.w vr17, vr17, vr4
vpickev.h vr17, vr17, vr17
vstelm.d vr17, a0, 0, 0
addi.d a2, a2, -4
addi.d a5, a5, 4
addi.d a6, a6, 4
addi.d a7, a7, 4
addi.d a0, a0, 8
bge a2, t7, .WIDTH4
blt zero, a2, .WIDTH
b .END
.WIDTH:
ld.bu t0, a5, 0
ld.bu t4, a6, 0
ld.bu t6, a7, 0
mul.w t8, t6, t1
mul.w t7, t0, t2
add.w t8, t8, t7
mul.w t7, t4, t3
add.w t8, t8, t7
add.w t8, t8, t5
srai.w t8, t8, 9
st.h t8, a0, 0
addi.d a2, a2, -1
addi.d a5, a5, 1
addi.d a6, a6, 1
addi.d a7, a7, 1
addi.d a0, a0, 2
blt zero, a2, .WIDTH
.END:
endfunc
/* void planar_rgb_to_uv_lsx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4],
* int width, int32_t *rgb2yuv)
*/
function planar_rgb_to_uv_lsx
addi.d sp, sp, -24
st.d s1, sp, 0
st.d s2, sp, 8
st.d s3, sp, 16
ld.d a5, a2, 0
ld.d a6, a2, 8
ld.d a7, a2, 16
ld.w t1, a4, 12 // ru
ld.w t2, a4, 16 // gu
ld.w t3, a4, 20 // bu
ld.w s1, a4, 24 // rv
ld.w s2, a4, 28 // gv
ld.w s3, a4, 32 // bv
li.w t4, 9
li.w t5, 4194560
li.w t7, 4
li.w t8, 8
vldi vr0, 0
vreplgr2vr.w vr1, t1
vreplgr2vr.w vr2, t2
vreplgr2vr.w vr3, t3
vreplgr2vr.w vr4, s1
vreplgr2vr.w vr5, s2
vreplgr2vr.w vr6, s3
vreplgr2vr.w vr7, t4
vreplgr2vr.w vr8, t5
bge a2, t8, .LOOP_WIDTH8
bge a2, t7, .LOOP_WIDTH4
blt zero, a2, .LOOP_WIDTH
b .LOOP_END
.LOOP_WIDTH8:
vld vr9, a5, 0
vld vr10, a6, 0
vld vr11, a7, 0
vilvl.b vr9, vr0, vr9
vilvl.b vr10, vr0, vr10
vilvl.b vr11, vr0, vr11
vilvl.h vr12, vr0, vr9
vilvl.h vr13, vr0, vr10
vilvl.h vr14, vr0, vr11
vilvh.h vr15, vr0, vr9
vilvh.h vr16, vr0, vr10
vilvh.h vr17, vr0, vr11
vmul.w vr18, vr1, vr14
vmul.w vr19, vr1, vr17
vmul.w vr20, vr4, vr14
vmul.w vr21, vr4, vr17
vmadd.w vr18, vr2, vr12
vmadd.w vr18, vr3, vr13
vmadd.w vr19, vr2, vr15
vmadd.w vr19, vr3, vr16
vmadd.w vr20, vr5, vr12
vmadd.w vr20, vr6, vr13
vmadd.w vr21, vr5, vr15
vmadd.w vr21, vr6, vr16
vadd.w vr18, vr18, vr8
vadd.w vr19, vr19, vr8
vadd.w vr20, vr20, vr8
vadd.w vr21, vr21, vr8
vsra.w vr18, vr18, vr7
vsra.w vr19, vr19, vr7
vsra.w vr20, vr20, vr7
vsra.w vr21, vr21, vr7
vpickev.h vr18, vr19, vr18
vpickev.h vr20, vr21, vr20
vst vr18, a0, 0
vst vr20, a1, 0
addi.d a3, a3, -8
addi.d a5, a5, 8
addi.d a6, a6, 8
addi.d a7, a7, 8
addi.d a0, a0, 16
addi.d a1, a1, 16
bge a3, t8, .LOOP_WIDTH8
bge a3, t7, .LOOP_WIDTH4
blt zero, a3, .LOOP_WIDTH
b .LOOP_END
.LOOP_WIDTH4:
vld vr9, a5, 0
vld vr10, a6, 0
vld vr11, a7, 0
vilvl.b vr9, vr0, vr9
vilvl.b vr10, vr0, vr10
vilvl.b vr11, vr0, vr11
vilvl.h vr12, vr0, vr9
vilvl.h vr13, vr0, vr10
vilvl.h vr14, vr0, vr11
vmul.w vr18, vr1, vr14
vmul.w vr19, vr4, vr14
vmadd.w vr18, vr2, vr12
vmadd.w vr18, vr3, vr13
vmadd.w vr19, vr5, vr12
vmadd.w vr19, vr6, vr13
vadd.w vr18, vr18, vr8
vadd.w vr19, vr19, vr8
vsra.w vr18, vr18, vr7
vsra.w vr19, vr19, vr7
vpickev.h vr18, vr18, vr18
vpickev.h vr19, vr19, vr19
vstelm.d vr18, a0, 0, 0
vstelm.d vr19, a1, 0, 0
addi.d a3, a3, -4
addi.d a5, a5, 4
addi.d a6, a6, 4
addi.d a7, a7, 4
addi.d a0, a0, 8
addi.d a1, a1, 8
bge a3, t7, .LOOP_WIDTH4
blt zero, a3, .LOOP_WIDTH
b .LOOP_END
.LOOP_WIDTH:
ld.bu t0, a5, 0
ld.bu t4, a6, 0
ld.bu t6, a7, 0
mul.w t8, t6, t1
mul.w t7, t0, t2
add.w t8, t8, t7
mul.w t7, t4, t3
add.w t8, t8, t7
add.w t8, t8, t5
srai.w t8, t8, 9
st.h t8, a0, 0
mul.w t8, t6, s1
mul.w t7, t0, s2
add.w t8, t8, t7
mul.w t7, t4, s3
add.w t8, t8, t7
add.w t8, t8, t5
srai.w t8, t8, 9
st.h t8, a1, 0
addi.d a3, a3, -1
addi.d a5, a5, 1
addi.d a6, a6, 1
addi.d a7, a7, 1
addi.d a0, a0, 2
addi.d a1, a1, 2
blt zero, a3, .LOOP_WIDTH
.LOOP_END:
ld.d s1, sp, 0
ld.d s2, sp, 8
ld.d s3, sp, 16
addi.d sp, sp, 24
endfunc
/*
* void yuy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
* const uint8_t *src2, int width, uint32_t *unused, void *opq)
*/
function yuy2ToUV_lsx
andi t0, a5, 7
srli.d a5, a5, 3
beqz a5, 2f
1:
vld vr0, a3, 1
vld vr1, a3, 17
addi.d a5, a5, -1
addi.d a3, a3, 32
vpickev.b vr2, vr1, vr0
vpickev.b vr0, vr2, vr2
vpickod.b vr1, vr2, vr2
fst.d f0, a0, 0
fst.d f1, a1, 0
addi.d a0, a0, 8
addi.d a1, a1, 8
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
function yuy2ToUV_lasx
andi t0, a5, 15
srli.d a5, a5, 4
beqz a5, 2f
1:
xvld xr0, a3, 1
xvld xr1, a3, 33
addi.d a5, a5, -1
addi.d a3, a3, 64
xvpickev.b xr2, xr1, xr0
xvpermi.d xr2, xr2, 0xd8
xvpickev.b xr0, xr2, xr2
xvpermi.d xr0, xr0, 0xd8
xvpickod.b xr1, xr2, xr2
xvpermi.d xr1, xr1, 0xd8
vst vr0, a0, 0
vst vr1, a1, 0
addi.d a0, a0, 16
addi.d a1, a1, 16
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
/*
* void yvy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
* const uint8_t *src2, int width, uint32_t *unused, void *opq)
*/
function yvy2ToUV_lsx
andi t0, a5, 7
srli.d a5, a5, 3
beqz a5, 2f
1:
vld vr0, a3, 1
vld vr1, a3, 17
addi.d a5, a5, -1
addi.d a3, a3, 32
vpickev.b vr2, vr1, vr0
vpickev.b vr0, vr2, vr2
vpickod.b vr1, vr2, vr2
fst.d f0, a1, 0
fst.d f1, a0, 0
addi.d a0, a0, 8
addi.d a1, a1, 8
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a1, 0
st.b t2, a0, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
function yvy2ToUV_lasx
andi t0, a5, 15
srli.d a5, a5, 4
beqz a5, 2f
1:
xvld xr0, a3, 1
xvld xr1, a3, 33
addi.d a5, a5, -1
addi.d a3, a3, 64
xvpickev.b xr2, xr1, xr0
xvpermi.d xr2, xr2, 0xd8
xvpickev.b xr0, xr2, xr2
xvpermi.d xr0, xr0, 0xd8
xvpickod.b xr1, xr2, xr2
xvpermi.d xr1, xr1, 0xd8
vst vr0, a1, 0
vst vr1, a0, 0
addi.d a0, a0, 16
addi.d a1, a1, 16
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a1, 0
st.b t2, a0, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
/*
* void uyvyToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
* const uint8_t *src2, int width, uint32_t *unused, void *opq)
*/
function uyvyToUV_lsx
andi t0, a5, 7
srli.d a5, a5, 3
beqz a5, 2f
1:
vld vr0, a3, 0
vld vr1, a3, 16
addi.d a5, a5, -1
addi.d a3, a3, 32
vpickev.b vr2, vr1, vr0
vpickev.b vr0, vr2, vr2
vpickod.b vr1, vr2, vr2
fst.d f0, a0, 0
fst.d f1, a1, 0
addi.d a0, a0, 8
addi.d a1, a1, 8
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
function uyvyToUV_lasx
andi t0, a5, 15
srli.d a5, a5, 4
beqz a5, 2f
1:
xvld xr0, a3, 0
xvld xr1, a3, 32
addi.d a5, a5, -1
addi.d a3, a3, 64
xvpickev.b xr2, xr1, xr0
xvpermi.d xr2, xr2, 0xd8
xvpickev.b xr0, xr2, xr2
xvpermi.d xr0, xr0, 0xd8
xvpickod.b xr1, xr2, xr2
xvpermi.d xr1, xr1, 0xd8
vst vr0, a0, 0
vst vr1, a1, 0
addi.d a0, a0, 16
addi.d a1, a1, 16
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 1
ld.b t2, a3, 3
addi.d a3, a3, 4
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
/*
* void nv12ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
* const uint8_t *src2, int width, uint32_t *unused, void *opq)
*/
function nv12ToUV_lsx
andi t0, a5, 15
srli.d a5, a5, 4
beqz a5, 2f
1:
vld vr0, a3, 0
vld vr1, a3, 16
addi.d a5, a5, -1
addi.d a3, a3, 32
vpickev.b vr2, vr1, vr0
vpickod.b vr3, vr1, vr0
vst vr2, a0, 0
vst vr3, a1, 0
addi.d a0, a0, 16
addi.d a1, a1, 16
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 0
ld.b t2, a3, 1
addi.d a3, a3, 2
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
function nv12ToUV_lasx
andi t0, a5, 31
srli.d a5, a5, 5
beqz a5, 2f
1:
xvld xr0, a3, 0
xvld xr1, a3, 32
addi.d a5, a5, -1
addi.d a3, a3, 64
xvpickev.b xr2, xr1, xr0
xvpickod.b xr3, xr1, xr0
xvpermi.d xr2, xr2, 0xd8
xvpermi.d xr3, xr3, 0xd8
xvst xr2, a0, 0
xvst xr3, a1, 0
addi.d a0, a0, 32
addi.d a1, a1, 32
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 0
ld.b t2, a3, 1
addi.d a3, a3, 2
addi.d t0, t0, -1
st.b t1, a0, 0
st.b t2, a1, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
/*
* void nv21ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
* const uint8_t *src2, int width, uint32_t *unused, void *opq)
*/
function nv21ToUV_lsx
andi t0, a5, 15
srli.d a5, a5, 4
beqz a5, 2f
1:
vld vr0, a3, 0
vld vr1, a3, 16
addi.d a5, a5, -1
addi.d a3, a3, 32
vpickev.b vr2, vr1, vr0
vpickod.b vr3, vr1, vr0
vst vr2, a1, 0
vst vr3, a0, 0
addi.d a0, a0, 16
addi.d a1, a1, 16
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 0
ld.b t2, a3, 1
addi.d a3, a3, 2
addi.d t0, t0, -1
st.b t1, a1, 0
st.b t2, a0, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
function nv21ToUV_lasx
andi t0, a5, 31
srli.d a5, a5, 5
beqz a5, 2f
1:
xvld xr0, a3, 0
xvld xr1, a3, 32
addi.d a5, a5, -1
addi.d a3, a3, 64
xvpickev.b xr2, xr1, xr0
xvpickod.b xr3, xr1, xr0
xvpermi.d xr2, xr2, 0xd8
xvpermi.d xr3, xr3, 0xd8
xvst xr2, a1, 0
xvst xr3, a0, 0
addi.d a0, a0, 32
addi.d a1, a1, 32
bnez a5, 1b
2:
beqz t0, 4f
3:
ld.b t1, a3, 0
ld.b t2, a3, 1
addi.d a3, a3, 2
addi.d t0, t0, -1
st.b t1, a1, 0
st.b t2, a0, 0
addi.d a0, a0, 1
addi.d a1, a1, 1
bnez t0, 3b
4:
endfunc
/*
*void abgrToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
* const uint8_t *unused2, int width, uint32_t *unused, void *opq)
*/
function abgrToA_lsx
andi t0, a4, 7
srli.d a4, a4, 3
vxor.v vr0, vr0, vr0
beqz a4, 2f
1:
vld vr1, a1, 0
vld vr2, a1, 16
addi.d a4, a4, -1
addi.d a1, a1, 32
vpickev.b vr3, vr2, vr1
vpackev.b vr3, vr0, vr3
vslli.h vr1, vr3, 6
vsrli.h vr2, vr3, 2
vor.v vr3, vr2, vr1
vst vr3, a0, 0
addi.d a0, a0, 16
bnez a4, 1b
2:
beqz t0, 4f
3:
ld.b t1, a1, 3
addi.d t0, t0, -1
addi.d a1, a1, 4
andi t1, t1, 0xff
slli.w t2, t1, 6
srli.w t3, t1, 2
or t1, t2, t3
st.h t1, a0, 0
addi.d a0, a0, 2
bnez t0, 3b
4:
endfunc
function abgrToA_lasx
andi t0, a4, 15
srli.d a4, a4, 4
xvxor.v xr0, xr0, xr0
beqz a4, 2f
1:
xvld xr1, a1, 0
xvld xr2, a1, 32
addi.d a4, a4, -1
addi.d a1, a1, 64
xvpickev.b xr3, xr2, xr1
xvpermi.d xr3, xr3, 0xd8
xvpackev.b xr3, xr0, xr3
xvslli.h xr1, xr3, 6
xvsrli.h xr2, xr3, 2
xvor.v xr3, xr2, xr1
xvst xr3, a0, 0
addi.d a0, a0, 32
bnez a4, 1b
2:
beqz t0, 4f
3:
ld.b t1, a1, 3
addi.d t0, t0, -1
addi.d a1, a1, 4
andi t1, t1, 0xff
slli.w t2, t1, 6
srli.w t3, t1, 2
or t1, t2, t3
st.h t1, a0, 0
addi.d a0, a0, 2
bnez t0, 3b
4:
endfunc
/*
*void rgbaToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
* const uint8_t *unused2, int width, uint32_t *unused, void *opq)
*/
function rgbaToA_lsx
andi t0, a4, 7
srli.d a4, a4, 3
vxor.v vr0, vr0, vr0
beqz a4, 2f
1:
vld vr1, a1, 3
vld vr2, a1, 19
addi.d a4, a4, -1
addi.d a1, a1, 32
vpickev.b vr3, vr2, vr1
vpackev.b vr3, vr0, vr3
vslli.h vr1, vr3, 6
vsrli.h vr2, vr3, 2
vor.v vr3, vr2, vr1
vst vr3, a0, 0
addi.d a0, a0, 16
bnez a4, 1b
2:
beqz t0, 4f
3:
ld.b t1, a1, 3
addi.d t0, t0, -1
addi.d a1, a1, 4
andi t1, t1, 0xff
slli.w t2, t1, 6
srli.w t3, t1, 2
or t1, t2, t3
st.h t1, a0, 0
addi.d a0, a0, 2
bnez t0, 3b
4:
endfunc
function rgbaToA_lasx
andi t0, a4, 15
srli.d a4, a4, 4
xvxor.v xr0, xr0, xr0
beqz a4, 2f
1:
xvld xr1, a1, 3
xvld xr2, a1, 35
addi.d a4, a4, -1
addi.d a1, a1, 64
xvpickev.b xr3, xr2, xr1
xvpermi.d xr3, xr3, 0xd8
xvpackev.b xr3, xr0, xr3
xvslli.h xr1, xr3, 6
xvsrli.h xr2, xr3, 2
xvor.v xr3, xr2, xr1
xvst xr3, a0, 0
addi.d a0, a0, 32
bnez a4, 1b
2:
beqz t0, 4f
3:
ld.b t1, a1, 3
addi.d t0, t0, -1
addi.d a1, a1, 4
andi t1, t1, 0xff
slli.w t2, t1, 6
srli.w t3, t1, 2
or t1, t2, t3
st.h t1, a0, 0
addi.d a0, a0, 2
bnez t0, 3b
4:
endfunc
+245
View File
@@ -0,0 +1,245 @@
/*
* Copyright (C) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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"
void planar_rgb_to_uv_lasx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4],
int width, int32_t *rgb2yuv, void *opq)
{
int i;
uint16_t *dstU = (uint16_t *)_dstU;
uint16_t *dstV = (uint16_t *)_dstV;
int set = 0x4001 << (RGB2YUV_SHIFT - 7);
int len = width - 15;
int32_t tem_ru = rgb2yuv[RU_IDX], tem_gu = rgb2yuv[GU_IDX];
int32_t tem_bu = rgb2yuv[BU_IDX], tem_rv = rgb2yuv[RV_IDX];
int32_t tem_gv = rgb2yuv[GV_IDX], tem_bv = rgb2yuv[BV_IDX];
int shift = RGB2YUV_SHIFT - 6;
const uint8_t *src0 = src[0], *src1 = src[1], *src2 = src[2];
__m256i ru, gu, bu, rv, gv, bv;
__m256i mask = {0x0D0C090805040100, 0x1D1C191815141110,
0x0D0C090805040100, 0x1D1C191815141110};
__m256i temp = __lasx_xvreplgr2vr_w(set);
__m256i sra = __lasx_xvreplgr2vr_w(shift);
ru = __lasx_xvreplgr2vr_w(tem_ru);
gu = __lasx_xvreplgr2vr_w(tem_gu);
bu = __lasx_xvreplgr2vr_w(tem_bu);
rv = __lasx_xvreplgr2vr_w(tem_rv);
gv = __lasx_xvreplgr2vr_w(tem_gv);
bv = __lasx_xvreplgr2vr_w(tem_bv);
for (i = 0; i < len; i += 16) {
__m256i _g, _b, _r;
__m256i g_l, g_h, b_l, b_h, r_l, r_h;
__m256i v_l, v_h, u_l, u_h, u_lh, v_lh;
_g = __lasx_xvldx(src0, i);
_b = __lasx_xvldx(src1, i);
_r = __lasx_xvldx(src2, i);
g_l = __lasx_vext2xv_wu_bu(_g);
b_l = __lasx_vext2xv_wu_bu(_b);
r_l = __lasx_vext2xv_wu_bu(_r);
_g = __lasx_xvpermi_d(_g, 0x01);
_b = __lasx_xvpermi_d(_b, 0x01);
_r = __lasx_xvpermi_d(_r, 0x01);
g_h = __lasx_vext2xv_wu_bu(_g);
b_h = __lasx_vext2xv_wu_bu(_b);
r_h = __lasx_vext2xv_wu_bu(_r);
u_l = __lasx_xvmadd_w(temp, ru, r_l);
u_h = __lasx_xvmadd_w(temp, ru, r_h);
v_l = __lasx_xvmadd_w(temp, rv, r_l);
v_h = __lasx_xvmadd_w(temp, rv, r_h);
u_l = __lasx_xvmadd_w(u_l, gu, g_l);
u_l = __lasx_xvmadd_w(u_l, bu, b_l);
u_h = __lasx_xvmadd_w(u_h, gu, g_h);
u_h = __lasx_xvmadd_w(u_h, bu, b_h);
v_l = __lasx_xvmadd_w(v_l, gv, g_l);
v_l = __lasx_xvmadd_w(v_l, bv, b_l);
v_h = __lasx_xvmadd_w(v_h, gv, g_h);
v_h = __lasx_xvmadd_w(v_h, bv, b_h);
u_l = __lasx_xvsra_w(u_l, sra);
u_h = __lasx_xvsra_w(u_h, sra);
v_l = __lasx_xvsra_w(v_l, sra);
v_h = __lasx_xvsra_w(v_h, sra);
u_lh = __lasx_xvshuf_b(u_h, u_l, mask);
v_lh = __lasx_xvshuf_b(v_h, v_l, mask);
u_lh = __lasx_xvpermi_d(u_lh, 0xD8);
v_lh = __lasx_xvpermi_d(v_lh, 0xD8);
__lasx_xvst(u_lh, (dstU + i), 0);
__lasx_xvst(v_lh, (dstV + i), 0);
}
if (width - i >= 8) {
__m256i _g, _b, _r;
__m256i g_l, b_l, r_l;
__m256i v_l, u_l, u, v;
_g = __lasx_xvldrepl_d((src0 + i), 0);
_b = __lasx_xvldrepl_d((src1 + i), 0);
_r = __lasx_xvldrepl_d((src2 + i), 0);
g_l = __lasx_vext2xv_wu_bu(_g);
b_l = __lasx_vext2xv_wu_bu(_b);
r_l = __lasx_vext2xv_wu_bu(_r);
u_l = __lasx_xvmadd_w(temp, ru, r_l);
v_l = __lasx_xvmadd_w(temp, rv, r_l);
u_l = __lasx_xvmadd_w(u_l, gu, g_l);
u_l = __lasx_xvmadd_w(u_l, bu, b_l);
v_l = __lasx_xvmadd_w(v_l, gv, g_l);
v_l = __lasx_xvmadd_w(v_l, bv, b_l);
u_l = __lasx_xvsra_w(u_l, sra);
v_l = __lasx_xvsra_w(v_l, sra);
u = __lasx_xvshuf_b(u_l, u_l, mask);
v = __lasx_xvshuf_b(v_l, v_l, mask);
__lasx_xvstelm_d(u, (dstU + i), 0, 0);
__lasx_xvstelm_d(u, (dstU + i), 8, 2);
__lasx_xvstelm_d(v, (dstV + i), 0, 0);
__lasx_xvstelm_d(v, (dstV + i), 8, 2);
i += 8;
}
for (; i < width; i++) {
int g = src[0][i];
int b = src[1][i];
int r = src[2][i];
dstU[i] = (tem_ru * r + tem_gu * g + tem_bu * b + set) >> shift;
dstV[i] = (tem_rv * r + tem_gv * g + tem_bv * b + set) >> shift;
}
}
void planar_rgb_to_y_lasx(uint8_t *_dst, const uint8_t *src[4], int width,
int32_t *rgb2yuv, void *opq)
{
int i;
int shift = (RGB2YUV_SHIFT - 6);
int set = 0x801 << (RGB2YUV_SHIFT - 7);
int len = width - 15;
uint16_t *dst = (uint16_t *)_dst;
int32_t tem_ry = rgb2yuv[RY_IDX], tem_gy = rgb2yuv[GY_IDX];
int32_t tem_by = rgb2yuv[BY_IDX];
const uint8_t *src0 = src[0], *src1 = src[1], *src2 = src[2];
__m256i mask = {0x0D0C090805040100, 0x1D1C191815141110,
0x0D0C090805040100, 0x1D1C191815141110};
__m256i temp = __lasx_xvreplgr2vr_w(set);
__m256i sra = __lasx_xvreplgr2vr_w(shift);
__m256i ry = __lasx_xvreplgr2vr_w(tem_ry);
__m256i gy = __lasx_xvreplgr2vr_w(tem_gy);
__m256i by = __lasx_xvreplgr2vr_w(tem_by);
for (i = 0; i < len; i += 16) {
__m256i _g, _b, _r;
__m256i g_l, g_h, b_l, b_h, r_l, r_h;
__m256i y_l, y_h, y_lh;
_g = __lasx_xvldx(src0, i);
_b = __lasx_xvldx(src1, i);
_r = __lasx_xvldx(src2, i);
g_l = __lasx_vext2xv_wu_bu(_g);
b_l = __lasx_vext2xv_wu_bu(_b);
r_l = __lasx_vext2xv_wu_bu(_r);
_g = __lasx_xvpermi_d(_g, 0x01);
_b = __lasx_xvpermi_d(_b, 0x01);
_r = __lasx_xvpermi_d(_r, 0x01);
g_h = __lasx_vext2xv_wu_bu(_g);
b_h = __lasx_vext2xv_wu_bu(_b);
r_h = __lasx_vext2xv_wu_bu(_r);
y_l = __lasx_xvmadd_w(temp, ry, r_l);
y_h = __lasx_xvmadd_w(temp, ry, r_h);
y_l = __lasx_xvmadd_w(y_l, gy, g_l);
y_l = __lasx_xvmadd_w(y_l, by, b_l);
y_h = __lasx_xvmadd_w(y_h, gy, g_h);
y_h = __lasx_xvmadd_w(y_h, by, b_h);
y_l = __lasx_xvsra_w(y_l, sra);
y_h = __lasx_xvsra_w(y_h, sra);
y_lh = __lasx_xvshuf_b(y_h, y_l, mask);
y_lh = __lasx_xvpermi_d(y_lh, 0xD8);
__lasx_xvst(y_lh, (dst + i), 0);
}
if (width - i >= 8) {
__m256i _g, _b, _r;
__m256i g_l, b_l, r_l;
__m256i y_l, y;
_g = __lasx_xvldrepl_d((src0 + i), 0);
_b = __lasx_xvldrepl_d((src1 + i), 0);
_r = __lasx_xvldrepl_d((src2 + i), 0);
g_l = __lasx_vext2xv_wu_bu(_g);
b_l = __lasx_vext2xv_wu_bu(_b);
r_l = __lasx_vext2xv_wu_bu(_r);
y_l = __lasx_xvmadd_w(temp, ry, r_l);
y_l = __lasx_xvmadd_w(y_l, gy, g_l);
y_l = __lasx_xvmadd_w(y_l, by, b_l);
y_l = __lasx_xvsra_w(y_l, sra);
y = __lasx_xvshuf_b(y_l, y_l, mask);
__lasx_xvstelm_d(y, (dst + i), 0, 0);
__lasx_xvstelm_d(y, (dst + i), 8, 2);
i += 8;
}
for (; i < width; i++) {
int g = src[0][i];
int b = src[1][i];
int r = src[2][i];
dst[i] = (tem_ry * r + tem_gy * g + tem_by * b + set) >> shift;
}
}
av_cold void ff_sws_init_input_lasx(SwsInternal *c)
{
enum AVPixelFormat srcFormat = c->opts.src_format;
switch (srcFormat) {
case AV_PIX_FMT_YUYV422:
c->chrToYV12 = yuy2ToUV_lasx;
break;
case AV_PIX_FMT_YVYU422:
c->chrToYV12 = yvy2ToUV_lasx;
break;
case AV_PIX_FMT_UYVY422:
c->chrToYV12 = uyvyToUV_lasx;
break;
case AV_PIX_FMT_NV12:
case AV_PIX_FMT_NV16:
case AV_PIX_FMT_NV24:
c->chrToYV12 = nv12ToUV_lasx;
break;
case AV_PIX_FMT_NV21:
case AV_PIX_FMT_NV42:
c->chrToYV12 = nv21ToUV_lasx;
break;
case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GBRP:
c->readChrPlanar = planar_rgb_to_uv_lasx;
break;
}
if (c->needAlpha) {
switch (srcFormat) {
case AV_PIX_FMT_BGRA:
case AV_PIX_FMT_RGBA:
c->alpToYV12 = rgbaToA_lasx;
break;
case AV_PIX_FMT_ABGR:
case AV_PIX_FMT_ARGB:
c->alpToYV12 = abgrToA_lasx;
break;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2024 Loongson Technology Corporation Limited
* Contributed by Shiyou Yin<yinshiyou-hf@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"
av_cold void ff_sws_init_input_lsx(SwsInternal *c)
{
enum AVPixelFormat srcFormat = c->opts.src_format;
switch (srcFormat) {
case AV_PIX_FMT_YUYV422:
c->chrToYV12 = yuy2ToUV_lsx;
break;
case AV_PIX_FMT_YVYU422:
c->chrToYV12 = yvy2ToUV_lsx;
break;
case AV_PIX_FMT_UYVY422:
c->chrToYV12 = uyvyToUV_lsx;
break;
case AV_PIX_FMT_NV12:
case AV_PIX_FMT_NV16:
case AV_PIX_FMT_NV24:
c->chrToYV12 = nv12ToUV_lsx;
break;
case AV_PIX_FMT_NV21:
case AV_PIX_FMT_NV42:
c->chrToYV12 = nv21ToUV_lsx;
break;
case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GBRP:
c->readChrPlanar = planar_rgb_to_uv_lsx;
break;
}
if (c->needAlpha) {
switch (srcFormat) {
case AV_PIX_FMT_BGRA:
case AV_PIX_FMT_RGBA:
c->alpToYV12 = rgbaToA_lsx;
break;
case AV_PIX_FMT_ABGR:
case AV_PIX_FMT_ARGB:
c->alpToYV12 = abgrToA_lsx;
break;
}
}
}
+388
View File
@@ -0,0 +1,388 @@
/*
* Loongson LSX optimized swscale
*
* 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 "libavcodec/loongarch/loongson_asm.S"
/* static void yuv2planeX_8_lsx(const int16_t *filter, int filterSize,
* const int16_t **src, uint8_t *dest, int dstW,
* const uint8_t *dither, int offset)
*/
function yuv2planeX_8_lsx
addi.w t1, a6, 1
addi.w t2, a6, 2
addi.w t3, a6, 3
addi.w t4, a6, 4
addi.w t5, a6, 5
addi.w t6, a6, 6
addi.w t7, a6, 7
andi t0, a6, 7
andi t1, t1, 7
andi t2, t2, 7
andi t3, t3, 7
andi t4, t4, 7
andi t5, t5, 7
andi t6, t6, 7
andi t7, t7, 7
ldx.bu t0, a5, t0
ldx.bu t1, a5, t1
ldx.bu t2, a5, t2
ldx.bu t3, a5, t3
ldx.bu t4, a5, t4
ldx.bu t5, a5, t5
ldx.bu t6, a5, t6
ldx.bu t7, a5, t7
vreplgr2vr.w vr0, t0
vreplgr2vr.w vr1, t1
vreplgr2vr.w vr2, t2
vreplgr2vr.w vr3, t3
vreplgr2vr.w vr4, t4
vreplgr2vr.w vr5, t5
vreplgr2vr.w vr6, t6
vreplgr2vr.w vr7, t7
vilvl.w vr0, vr2, vr0
vilvl.w vr4, vr6, vr4
vilvl.w vr1, vr3, vr1
vilvl.w vr5, vr7, vr5
vilvl.d vr12, vr4, vr0
vilvl.d vr13, vr5, vr1
li.w t5, 0
li.w t8, 8
bge a4, t8, .WIDTH8
blt zero, a4, .WIDTH
b .END
.WIDTH8:
li.d t1, 0
li.d t4, 0
vslli.w vr2, vr12, 12
vslli.w vr3, vr13, 12
move t3, a0
.FILTERSIZE8:
ldx.d t2, a2, t1
vldx vr4, t2, t5
vldrepl.h vr5, t3, 0
vmaddwev.w.h vr2, vr4, vr5
vmaddwod.w.h vr3, vr4, vr5
addi.d t1, t1, 8
addi.d t3, t3, 2
addi.d t4, t4, 1
blt t4, a1, .FILTERSIZE8
vsrai.w vr2, vr2, 19
vsrai.w vr3, vr3, 19
vclip255.w vr2, vr2
vclip255.w vr3, vr3
vpickev.h vr2, vr3, vr2
vpickev.b vr2, vr2, vr2
vbsrl.v vr3, vr2, 4
vilvl.b vr2, vr3, vr2
fst.d f2, a3, 0
addi.d t5, t5, 16
addi.d a4, a4, -8
addi.d a3, a3, 8
bge a4, t8, .WIDTH8
blt zero, a4, .WIDTH
b .END
.WIDTH:
li.d t1, 0
li.d t4, 0
vslli.w vr2, vr12, 12
vslli.w vr3, vr13, 12
.FILTERSIZE:
ldx.d t2, a2, t1
vldx vr4, t2, t5
vldrepl.h vr5, a0, 0
vmaddwev.w.h vr2, vr4, vr5
vmaddwod.w.h vr3, vr4, vr5
addi.d t1, t1, 8
addi.d a0, a0, 2
addi.d t4, t4, 1
blt t4, a1, .FILTERSIZE
vsrai.w vr2, vr2, 19
vsrai.w vr3, vr3, 19
vclip255.w vr2, vr2
vclip255.w vr3, vr3
vpickev.h vr2, vr3, vr2
vpickev.b vr2, vr2, vr2
vbsrl.v vr3, vr2, 4
vilvl.b vr2, vr3, vr2
.DEST:
vstelm.b vr2, a3, 0, 0
vbsrl.v vr2, vr2, 1
addi.d a4, a4, -1
addi.d a3, a3, 1
blt zero, a4, .DEST
.END:
endfunc
/*
* void yuv2plane1_8_lsx(const int16_t *src, uint8_t *dest, int dstW,
* const uint8_t *dither, int offset)
*/
function yuv2plane1_8_lsx
addi.w t1, a4, 1
addi.w t2, a4, 2
addi.w t3, a4, 3
addi.w t4, a4, 4
addi.w t5, a4, 5
addi.w t6, a4, 6
addi.w t7, a4, 7
andi t0, a4, 7
andi t1, t1, 7
andi t2, t2, 7
andi t3, t3, 7
andi t4, t4, 7
andi t5, t5, 7
andi t6, t6, 7
andi t7, t7, 7
ldx.bu t0, a3, t0
ldx.bu t1, a3, t1
ldx.bu t2, a3, t2
ldx.bu t3, a3, t3
ldx.bu t4, a3, t4
ldx.bu t5, a3, t5
ldx.bu t6, a3, t6
ldx.bu t7, a3, t7
vinsgr2vr.h vr1, t0, 0
vinsgr2vr.h vr1, t1, 1
vinsgr2vr.h vr1, t2, 2
vinsgr2vr.h vr1, t3, 3
vinsgr2vr.h vr1, t4, 4
vinsgr2vr.h vr1, t5, 5
vinsgr2vr.h vr1, t6, 6
vinsgr2vr.h vr1, t7, 7
vsub.h vr0, vr0, vr0
vilvl.h vr2, vr0, vr1
vilvh.h vr3, vr0, vr1
andi t8, a2, 7
srli.d a2, a2, 3
beqz a2, 2f
1:
vld vr1, a0, 0
addi.d a0, a0, 16
vshuf4i.d vr0, vr1, 8
vexth.w.h vr4, vr0
vexth.w.h vr5, vr1
vadd.w vr4, vr2, vr4
vadd.w vr5, vr3, vr5
vsrai.w vr4, vr4, 7
vsrai.w vr5, vr5, 7
vclip255.w vr4, vr4
vclip255.w vr5, vr5
vpickev.h vr1, vr5, vr4
vpickev.b vr1, vr1, vr1
fst.d f1, a1, 0
addi.d a1, a1, 8
addi.d a2, a2, -1
bnez a2, 1b
2:
beqz t8, 4f
3:
add.w a4, a4, t8
addi.w t1, a4, 1
addi.w t2, a4, 2
addi.w t3, a4, 3
addi.w t4, a4, 4
addi.w t5, a4, 5
addi.w t6, a4, 6
addi.w t7, a4, 7
andi t0, a4, 7
andi t1, t1, 7
andi t2, t2, 7
andi t3, t3, 7
andi t4, t4, 7
andi t5, t5, 7
andi t6, t6, 7
andi t7, t7, 7
ldx.bu t0, a3, t0
ldx.bu t1, a3, t1
ldx.bu t2, a3, t2
ldx.bu t3, a3, t3
ldx.bu t4, a3, t4
ldx.bu t5, a3, t5
ldx.bu t6, a3, t6
ldx.bu t7, a3, t7
vinsgr2vr.h vr1, t0, 0
vinsgr2vr.h vr1, t1, 1
vinsgr2vr.h vr1, t2, 2
vinsgr2vr.h vr1, t3, 3
vinsgr2vr.h vr1, t4, 4
vinsgr2vr.h vr1, t5, 5
vinsgr2vr.h vr1, t6, 6
vinsgr2vr.h vr1, t7, 7
vsub.h vr0, vr0, vr0
vilvl.h vr2, vr0, vr1
vilvh.h vr3, vr0, vr1
addi.d a0, a0, -16
add.d a0, a0, t8
add.d a0, a0, t8
addi.d a1, a1, -8
add.d a1, a1, t8
vld vr1, a0, 0
vshuf4i.d vr0, vr1, 8
vexth.w.h vr4, vr0
vexth.w.h vr5, vr1
vadd.w vr4, vr2, vr4
vadd.w vr5, vr3, vr5
vsrai.w vr4, vr4, 7
vsrai.w vr5, vr5, 7
vclip255.w vr4, vr4
vclip255.w vr5, vr5
vpickev.h vr1, vr5, vr4
vpickev.b vr1, vr1, vr1
fst.d f1, a1, 0
4:
endfunc
function yuv2plane1_8_lasx
addi.w t1, a4, 1
addi.w t2, a4, 2
addi.w t3, a4, 3
addi.w t4, a4, 4
addi.w t5, a4, 5
addi.w t6, a4, 6
addi.w t7, a4, 7
andi t0, a4, 7
andi t1, t1, 7
andi t2, t2, 7
andi t3, t3, 7
andi t4, t4, 7
andi t5, t5, 7
andi t6, t6, 7
andi t7, t7, 7
ldx.bu t0, a3, t0
ldx.bu t1, a3, t1
ldx.bu t2, a3, t2
ldx.bu t3, a3, t3
ldx.bu t4, a3, t4
ldx.bu t5, a3, t5
ldx.bu t6, a3, t6
ldx.bu t7, a3, t7
vinsgr2vr.h vr1, t0, 0
vinsgr2vr.h vr1, t1, 1
vinsgr2vr.h vr1, t2, 2
vinsgr2vr.h vr1, t3, 3
vinsgr2vr.h vr1, t4, 4
vinsgr2vr.h vr1, t5, 5
vinsgr2vr.h vr1, t6, 6
vinsgr2vr.h vr1, t7, 7
xvpermi.q xr1, xr1, 0
xvsub.h xr0, xr0, xr0
xvilvl.h xr2, xr0, xr1
xvilvh.h xr3, xr0, xr1
andi t8, a2, 15
srli.d a2, a2, 4
beqz a2, 2f
1:
xvld xr1, a0, 0
addi.d a0, a0, 32
xvpermi.d xr0, xr1, 0xa0
xvexth.w.h xr4, xr0
xvexth.w.h xr5, xr1
xvadd.w xr4, xr2, xr4
xvadd.w xr5, xr3, xr5
xvsrai.w xr4, xr4, 7
xvsrai.w xr5, xr5, 7
xvclip255.w xr4, xr4
xvclip255.w xr5, xr5
xvpickev.h xr1, xr5, xr4
xvpickev.b xr0, xr1, xr1
xvpermi.q xr1, xr0, 1
fst.d f0, a1, 0
fst.d f1, a1, 8
addi.d a1, a1, 16
addi.d a2, a2, -1
bnez a2, 1b
2:
beqz t8, 4f
3:
add.w a4, a4, t8
addi.w t1, a4, 1
addi.w t2, a4, 2
addi.w t3, a4, 3
addi.w t4, a4, 4
addi.w t5, a4, 5
addi.w t6, a4, 6
addi.w t7, a4, 7
andi t0, a4, 7
andi t1, t1, 7
andi t2, t2, 7
andi t3, t3, 7
andi t4, t4, 7
andi t5, t5, 7
andi t6, t6, 7
andi t7, t7, 7
ldx.bu t0, a3, t0
ldx.bu t1, a3, t1
ldx.bu t2, a3, t2
ldx.bu t3, a3, t3
ldx.bu t4, a3, t4
ldx.bu t5, a3, t5
ldx.bu t6, a3, t6
ldx.bu t7, a3, t7
vinsgr2vr.h vr1, t0, 0
vinsgr2vr.h vr1, t1, 1
vinsgr2vr.h vr1, t2, 2
vinsgr2vr.h vr1, t3, 3
vinsgr2vr.h vr1, t4, 4
vinsgr2vr.h vr1, t5, 5
vinsgr2vr.h vr1, t6, 6
vinsgr2vr.h vr1, t7, 7
xvpermi.q xr1, xr1, 0
xvsub.h xr0, xr0, xr0
xvilvl.h xr2, xr0, xr1
xvilvh.h xr3, xr0, xr1
addi.d a0, a0, -32
add.d a0, a0, t8
add.d a0, a0, t8
addi.d a1, a1, -16
add.d a1, a1, t8
xvld xr1, a0, 0
xvpermi.d xr0, xr1, 0xa0
xvexth.w.h xr4, xr0
xvexth.w.h xr5, xr1
xvadd.w xr4, xr2, xr4
xvadd.w xr5, xr3, xr5
xvsrai.w xr4, xr4, 7
xvsrai.w xr5, xr5, 7
xvclip255.w xr4, xr4
xvclip255.w xr5, xr5
xvpickev.h xr1, xr5, xr4
xvpickev.b xr0, xr1, xr1
xvpermi.q xr1, xr0, 1
fst.d f0, a1, 0
fst.d f1, a1, 8
4:
endfunc
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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"
void ff_interleave_bytes_lasx(const uint8_t *src1, const uint8_t *src2,
uint8_t *dest, int width, int height,
int src1Stride, int src2Stride, int dstStride)
{
int h;
int len = width & (0xFFFFFFF0);
for (h = 0; h < height; h++) {
int w, index = 0;
__m256i src_1, src_2, dst;
for (w = 0; w < len; w += 16) {
DUP2_ARG2(__lasx_xvld, src1 + w, 0, src2 + w, 0, src_1, src_2);
src_1 = __lasx_xvpermi_d(src_1, 0xD8);
src_2 = __lasx_xvpermi_d(src_2, 0xD8);
dst = __lasx_xvilvl_b(src_2, src_1);
__lasx_xvst(dst, dest + index, 0);
index += 32;
}
for (; w < width; w++) {
dest[(w << 1) + 0] = src1[w];
dest[(w << 1) + 1] = src2[w];
}
dest += dstStride;
src1 += src1Stride;
src2 += src2Stride;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,176 @@
/*
* Copyright (C) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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 "libswscale/swscale_internal.h"
#include "libswscale/rgb2rgb.h"
#include "libavutil/loongarch/cpu.h"
av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c)
{
/* This code is currently disabled because of changes in the base
* implementation of these functions. This code should be enabled
* again once those changes are ported to this architecture. */
#if 0
int cpu_flags = av_get_cpu_flags();
if (have_lsx(cpu_flags)) {
if (c->dstBpc <= 14) {
if (c->opts.src_range) {
c->lumConvertRange = lumRangeFromJpeg_lsx;
c->chrConvertRange = chrRangeFromJpeg_lsx;
} else {
c->lumConvertRange = lumRangeToJpeg_lsx;
c->chrConvertRange = chrRangeToJpeg_lsx;
}
}
}
#if HAVE_LASX
if (have_lasx(cpu_flags)) {
if (c->dstBpc <= 14) {
if (c->opts.src_range) {
c->lumConvertRange = lumRangeFromJpeg_lasx;
c->chrConvertRange = chrRangeFromJpeg_lasx;
} else {
c->lumConvertRange = lumRangeToJpeg_lasx;
c->chrConvertRange = chrRangeToJpeg_lasx;
}
}
}
#endif // #if HAVE_LASX
#endif
}
av_cold void ff_sws_init_swscale_loongarch(SwsInternal *c)
{
int cpu_flags = av_get_cpu_flags();
if (have_lsx(cpu_flags)) {
ff_sws_init_output_lsx(c, &c->yuv2plane1, &c->yuv2planeX,
&c->yuv2nv12cX, &c->yuv2packed1,
&c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
ff_sws_init_input_lsx(c);
if (c->srcBpc == 8) {
if (c->dstBpc <= 14) {
c->hyScale = c->hcScale = ff_hscale_8_to_15_lsx;
} else {
c->hyScale = c->hcScale = ff_hscale_8_to_19_lsx;
}
} else {
c->hyScale = c->hcScale = c->dstBpc > 14 ? ff_hscale_16_to_19_lsx
: ff_hscale_16_to_15_lsx;
}
}
#if HAVE_LASX
if (have_lasx(cpu_flags)) {
ff_sws_init_output_lasx(c, &c->yuv2plane1, &c->yuv2planeX,
&c->yuv2nv12cX, &c->yuv2packed1,
&c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
ff_sws_init_input_lasx(c);
if (c->srcBpc == 8) {
if (c->dstBpc <= 14) {
c->hyScale = c->hcScale = ff_hscale_8_to_15_lasx;
} else {
c->hyScale = c->hcScale = ff_hscale_8_to_19_lasx;
}
} else {
c->hyScale = c->hcScale = c->dstBpc > 14 ? ff_hscale_16_to_19_lasx
: ff_hscale_16_to_15_lasx;
}
}
#endif // #if HAVE_LASX
}
av_cold void rgb2rgb_init_loongarch(void)
{
#if HAVE_LASX
int cpu_flags = av_get_cpu_flags();
if (have_lasx(cpu_flags))
interleaveBytes = ff_interleave_bytes_lasx;
#endif // #if HAVE_LASX
}
av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsInternal *c)
{
int cpu_flags = av_get_cpu_flags();
#if HAVE_LASX
if (have_lasx(cpu_flags)) {
if (c->opts.src_format == AV_PIX_FMT_YUV420P) {
switch (c->opts.dst_format) {
case AV_PIX_FMT_RGB24:
return yuv420_rgb24_lasx;
case AV_PIX_FMT_BGR24:
return yuv420_bgr24_lasx;
case AV_PIX_FMT_RGBA:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_rgba32_lasx;
case AV_PIX_FMT_ARGB:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_argb32_lasx;
case AV_PIX_FMT_BGRA:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_bgra32_lasx;
case AV_PIX_FMT_ABGR:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_abgr32_lasx;
}
}
}
#endif // #if HAVE_LASX
if (have_lsx(cpu_flags)) {
if (c->opts.src_format == AV_PIX_FMT_YUV420P) {
switch (c->opts.dst_format) {
case AV_PIX_FMT_RGB24:
return yuv420_rgb24_lsx;
case AV_PIX_FMT_BGR24:
return yuv420_bgr24_lsx;
case AV_PIX_FMT_RGBA:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_rgba32_lsx;
case AV_PIX_FMT_ARGB:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_argb32_lsx;
case AV_PIX_FMT_BGRA:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_bgra32_lsx;
case AV_PIX_FMT_ABGR:
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) {
break;
} else
return yuv420_abgr32_lsx;
}
}
}
return NULL;
}
+972
View File
@@ -0,0 +1,972 @@
/*
* Copyright (C) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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"
#include "libavutil/intreadwrite.h"
#define SCALE_8_16(_sh) \
{ \
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_d(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_d(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_d(src + filterPos[3], 0); \
src4 = __lasx_xvldrepl_d(src + filterPos[4], 0); \
src5 = __lasx_xvldrepl_d(src + filterPos[5], 0); \
src6 = __lasx_xvldrepl_d(src + filterPos[6], 0); \
src7 = __lasx_xvldrepl_d(src + filterPos[7], 0); \
src8 = __lasx_xvldrepl_d(src + filterPos[8], 0); \
src9 = __lasx_xvldrepl_d(src + filterPos[9], 0); \
src10 = __lasx_xvldrepl_d(src + filterPos[10], 0); \
src11 = __lasx_xvldrepl_d(src + filterPos[11], 0); \
src12 = __lasx_xvldrepl_d(src + filterPos[12], 0); \
src13 = __lasx_xvldrepl_d(src + filterPos[13], 0); \
src14 = __lasx_xvldrepl_d(src + filterPos[14], 0); \
src15 = __lasx_xvldrepl_d(src + filterPos[15], 0); \
DUP4_ARG2(__lasx_xvld, filter, 0, filter, 32, filter, 64, \
filter, 96, filter0, filter1, filter2, filter3); \
DUP4_ARG2(__lasx_xvld, filter, 128, filter, 160, \
filter, 192, filter, 224, filter4, \
filter5, filter6, filter7); \
DUP4_ARG2(__lasx_xvilvl_d, src1, src0, src3, src2, \
src5, src4, src7, src6, src0, src2, src4, src6); \
DUP4_ARG2(__lasx_xvilvl_d, src9, src8, src11, src10, \
src13, src12, src15, src14, src8, src10, src12, src14); \
DUP4_ARG1(__lasx_vext2xv_hu_bu, src0, src2, src4, src6, \
src0, src2, src4, src6); \
DUP4_ARG1(__lasx_vext2xv_hu_bu, src8, src10, src12, \
src14, src8, src10, src12, src14); \
DUP4_ARG2(__lasx_xvdp2_w_h, filter0, src0, filter1, src2, \
filter2, src4, filter3, src6, src0, src1, src2, src3); \
DUP4_ARG2(__lasx_xvdp2_w_h, filter4, src8, filter5, src10, \
filter6, src12, filter7, src14, src4, src5, src6, src7);\
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src2 = __lasx_xvhaddw_d_w(src2, src2); \
src3 = __lasx_xvhaddw_d_w(src3, src3); \
src4 = __lasx_xvhaddw_d_w(src4, src4); \
src5 = __lasx_xvhaddw_d_w(src5, src5); \
src6 = __lasx_xvhaddw_d_w(src6, src6); \
src7 = __lasx_xvhaddw_d_w(src7, src7); \
DUP4_ARG2(__lasx_xvpickev_w, src1, src0, src3, src2, \
src5, src4, src7, src6, src0, src1, src2, src3); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src2 = __lasx_xvhaddw_d_w(src2, src2); \
src3 = __lasx_xvhaddw_d_w(src3, src3); \
src0 = __lasx_xvpickev_w(src1, src0); \
src1 = __lasx_xvpickev_w(src3, src2); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src1 = __lasx_xvsrai_w(src1, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
src1 = __lasx_xvmin_w(src1, vmax); \
src0 = __lasx_xvperm_w(src0, shuf); \
src1 = __lasx_xvperm_w(src1, shuf); \
src0 = __lasx_xvpickev_h(src1, src0); \
src0 = __lasx_xvpermi_d(src0, 0xd8); \
__lasx_xvst(src0, dst, 0); \
filterPos += 16; \
filter += 128; \
dst += 16; \
}
#define SCALE_8_8(_sh) \
{ \
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_d(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_d(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_d(src + filterPos[3], 0); \
src4 = __lasx_xvldrepl_d(src + filterPos[4], 0); \
src5 = __lasx_xvldrepl_d(src + filterPos[5], 0); \
src6 = __lasx_xvldrepl_d(src + filterPos[6], 0); \
src7 = __lasx_xvldrepl_d(src + filterPos[7], 0); \
DUP4_ARG2(__lasx_xvld, filter, 0, filter, 32, filter, 64, \
filter, 96, filter0, filter1, filter2, filter3); \
filterPos += 8; \
filter += 64; \
DUP4_ARG2(__lasx_xvilvl_d, src1, src0, src3, src2, \
src5, src4, src7, src6, src0, src2, src4, src6); \
DUP4_ARG1(__lasx_vext2xv_hu_bu, src0, src2, src4, src6, \
src0, src2, src4, src6); \
DUP4_ARG2(__lasx_xvdp2_w_h, filter0, src0, filter1, src2, \
filter2, src4, filter3, src6, src0, src1, src2,src3); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src2 = __lasx_xvhaddw_d_w(src2, src2); \
src3 = __lasx_xvhaddw_d_w(src3, src3); \
src0 = __lasx_xvpickev_w(src1, src0); \
src1 = __lasx_xvpickev_w(src3, src2); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src0 = __lasx_xvpickev_w(src1, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
src0 = __lasx_xvperm_w(src0, shuf); \
}
#define SCALE_8_4(_sh) \
{ \
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_d(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_d(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_d(src + filterPos[3], 0); \
filter0 = __lasx_xvld(filter, 0); \
filter1 = __lasx_xvld(filter, 32); \
filterPos += 4; \
filter += 32; \
src0 = __lasx_xvilvl_d(src1, src0); \
src2 = __lasx_xvilvl_d(src3, src2); \
src0 = __lasx_vext2xv_hu_bu(src0); \
src2 = __lasx_vext2xv_hu_bu(src2); \
src0 = __lasx_xvdp2_w_h(src0, filter0); \
src1 = __lasx_xvdp2_w_h(src2, filter1); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src0 = __lasx_xvpickev_w(src1, src0); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src0 = __lasx_xvpickev_w(src0, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
src0 = __lasx_xvperm_w(src0, shuf); \
}
#define SCALE_8_2(_sh) \
{ \
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_d(src + filterPos[1], 0); \
filter0 = __lasx_xvld(filter, 0); \
src0 = __lasx_xvilvl_d(src1, src0); \
src0 = __lasx_vext2xv_hu_bu(src0); \
src0 = __lasx_xvdp2_w_h(filter0, src0); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src0 = __lasx_xvhaddw_q_d(src0, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
dst[0] = __lasx_xvpickve2gr_w(src0, 0); \
dst[1] = __lasx_xvpickve2gr_w(src0, 4); \
filterPos += 2; \
filter += 16; \
dst += 2; \
}
#define SCALE_4_16(_sh) \
{ \
src0 = __lasx_xvldrepl_w(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_w(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_w(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_w(src + filterPos[3], 0); \
src4 = __lasx_xvldrepl_w(src + filterPos[4], 0); \
src5 = __lasx_xvldrepl_w(src + filterPos[5], 0); \
src6 = __lasx_xvldrepl_w(src + filterPos[6], 0); \
src7 = __lasx_xvldrepl_w(src + filterPos[7], 0); \
src8 = __lasx_xvldrepl_w(src + filterPos[8], 0); \
src9 = __lasx_xvldrepl_w(src + filterPos[9], 0); \
src10 = __lasx_xvldrepl_w(src + filterPos[10], 0); \
src11 = __lasx_xvldrepl_w(src + filterPos[11], 0); \
src12 = __lasx_xvldrepl_w(src + filterPos[12], 0); \
src13 = __lasx_xvldrepl_w(src + filterPos[13], 0); \
src14 = __lasx_xvldrepl_w(src + filterPos[14], 0); \
src15 = __lasx_xvldrepl_w(src + filterPos[15], 0); \
DUP4_ARG2(__lasx_xvld, filter, 0, filter, 32, filter, 64, \
filter, 96, filter0, filter1, filter2, filter3); \
DUP4_ARG2(__lasx_xvilvl_w, src1, src0, src3, src2, src5, \
src4, src7, src6, src0, src2, src4, src6); \
DUP4_ARG2(__lasx_xvilvl_w, src9, src8, src11, src10, src13, \
src12, src15, src14, src8, src10, src12, src14); \
DUP4_ARG2(__lasx_xvilvl_d, src2, src0, src6, src4, src10, \
src8, src14, src12, src0, src1, src2, src3); \
DUP4_ARG1(__lasx_vext2xv_hu_bu, src0, src1, src2, src3, \
src0, src1, src2, src3); \
DUP4_ARG2(__lasx_xvdp2_w_h, filter0, src0, filter1, src1, \
filter2, src2, filter3, src3, src0, src1, src2, src3); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src2 = __lasx_xvhaddw_d_w(src2, src2); \
src3 = __lasx_xvhaddw_d_w(src3, src3); \
src0 = __lasx_xvpickev_w(src1, src0); \
src1 = __lasx_xvpickev_w(src3, src2); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src1 = __lasx_xvsrai_w(src1, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
src1 = __lasx_xvmin_w(src1, vmax); \
src0 = __lasx_xvpickev_h(src1, src0); \
src0 = __lasx_xvperm_w(src0, shuf); \
__lasx_xvst(src0, dst, 0); \
filterPos += 16; \
filter += 64; \
dst += 16; \
}
#define SCALE_4_8(_sh) \
{ \
src0 = __lasx_xvldrepl_w(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_w(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_w(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_w(src + filterPos[3], 0); \
src4 = __lasx_xvldrepl_w(src + filterPos[4], 0); \
src5 = __lasx_xvldrepl_w(src + filterPos[5], 0); \
src6 = __lasx_xvldrepl_w(src + filterPos[6], 0); \
src7 = __lasx_xvldrepl_w(src + filterPos[7], 0); \
filter0 = __lasx_xvld(filter, 0); \
filter1 = __lasx_xvld(filter, 32); \
filterPos += 8; \
filter += 32; \
DUP4_ARG2(__lasx_xvilvl_w, src1, src0, src3, src2, src5, \
src4, src7, src6, src0, src2, src4, src6); \
src0 = __lasx_xvilvl_d(src2, src0); \
src1 = __lasx_xvilvl_d(src6, src4); \
\
src0 = __lasx_vext2xv_hu_bu(src0); \
src1 = __lasx_vext2xv_hu_bu(src1); \
src0 = __lasx_xvdp2_w_h(filter0, src0); \
src1 = __lasx_xvdp2_w_h(filter1, src1); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src1 = __lasx_xvhaddw_d_w(src1, src1); \
src0 = __lasx_xvpickev_w(src1, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
}
#define SCALE_4_4(_sh) \
{ \
src0 = __lasx_xvldrepl_w(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_w(src + filterPos[1], 0); \
src2 = __lasx_xvldrepl_w(src + filterPos[2], 0); \
src3 = __lasx_xvldrepl_w(src + filterPos[3], 0); \
filter0 = __lasx_xvld(filter, 0); \
filterPos += 4; \
filter += 16; \
src0 = __lasx_xvilvl_w(src1, src0); \
src1 = __lasx_xvilvl_w(src3, src2); \
\
src0 = __lasx_xvilvl_d(src1, src0); \
src0 = __lasx_vext2xv_hu_bu(src0); \
src0 = __lasx_xvdp2_w_h(filter0, src0); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
src0 = __lasx_xvpickev_w(src0, src0); \
src0 = __lasx_xvpermi_d(src0, 0xd8); \
}
#define SCALE_4_2(_sh) \
{ \
src0 = __lasx_xvldrepl_w(src + filterPos[0], 0); \
src1 = __lasx_xvldrepl_w(src + filterPos[1], 0); \
filter0 = __lasx_xvld(filter, 0); \
src0 = __lasx_xvilvl_w(src1, src0); \
src0 = __lasx_vext2xv_hu_bu(src0); \
src0 = __lasx_xvdp2_w_h(filter0, src0); \
src0 = __lasx_xvhaddw_d_w(src0, src0); \
src0 = __lasx_xvsrai_w(src0, _sh); \
src0 = __lasx_xvmin_w(src0, vmax); \
dst[0] = __lasx_xvpickve2gr_w(src0, 0); \
dst[1] = __lasx_xvpickve2gr_w(src0, 2); \
filterPos += 2; \
filter += 8; \
dst += 2; \
}
#define SCALE_16 \
{ \
int dex = j << 1; \
src0 = __lasx_xvldrepl_d((srcPos1 + j), 0); \
src1 = __lasx_xvldrepl_d((srcPos2 + j), 0); \
src2 = __lasx_xvldrepl_d((srcPos3 + j), 0); \
src3 = __lasx_xvldrepl_d((srcPos4 + j), 0); \
DUP4_ARG2(__lasx_xvldx, filterStart1, dex, filterStart2, dex, \
filterStart3, dex, filterStart4, dex, filter0, \
filter1, filter2, filter3); \
src0 = __lasx_xvpermi_q(src0, src1, 0x02); \
src1 = __lasx_xvpermi_q(src2, src3, 0x02); \
filter0 = __lasx_xvpermi_q(filter0, filter1, 0x02); \
filter1 = __lasx_xvpermi_q(filter2, filter3, 0x02); \
src0 = __lasx_xvilvl_b(zero, src0); \
src1 = __lasx_xvilvl_b(zero, src1); \
out0 = __lasx_xvdp2_w_h(filter0, src0); \
out1 = __lasx_xvdp2_w_h(filter1, src1); \
src0 = __lasx_xvhaddw_d_w(out0, out0); \
src1 = __lasx_xvhaddw_d_w(out1, out1); \
out0 = __lasx_xvpackev_d(src1, src0); \
out1 = __lasx_xvpackod_d(src1, src0); \
out0 = __lasx_xvadd_w(out0, out1); \
out = __lasx_xvadd_w(out, out0); \
}
void ff_hscale_8_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
int i;
int max = (1 << 15) - 1;
if (filterSize == 8) {
__m256i src0, src1, src2, src3, src4, src5, src6, src7;
__m256i src8, src9, src10, src11, src12, src13, src14, src15;
__m256i filter0, filter1, filter2, filter3;
__m256i filter4, filter5, filter6, filter7;
__m256i vmax = __lasx_xvreplgr2vr_w(max);
__m256i shuf = {0x0000000400000000, 0x0000000500000001,
0x0000000600000002, 0x0000000700000003};
int len = dstW >> 4;
int res = dstW & 15;
while (len--) {
SCALE_8_16(7);
}
if (res & 8) {
SCALE_8_8(7);
src0 = __lasx_xvpickev_h(src0, src0);
__lasx_xvstelm_d(src0, dst, 0, 0);
__lasx_xvstelm_d(src0, dst, 8, 2);
dst += 8;
}
if (res & 4) {
SCALE_8_4(7);
src0 = __lasx_xvpickev_h(src0, src0);
__lasx_xvstelm_d(src0, dst, 0, 0);
dst += 4;
}
if (res & 2) {
SCALE_8_2(7);
}
if (res & 1) {
int val = 0;
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0);
filter0 = __lasx_xvld(filter, 0);
src0 = __lasx_vext2xv_hu_bu(src0);
src0 = __lasx_xvdp2_w_h(filter0, src0);
src0 = __lasx_xvhaddw_d_w(src0, src0);
src0 = __lasx_xvhaddw_q_d(src0, src0);
val = __lasx_xvpickve2gr_w(src0, 0);
dst[0] = FFMIN(val >> 7, max);
}
} else if (filterSize == 4) {
__m256i src0, src1, src2, src3, src4, src5, src6, src7;
__m256i src8, src9, src10, src11, src12, src13, src14, src15;
__m256i filter0, filter1, filter2, filter3;
__m256i vmax = __lasx_xvreplgr2vr_w(max);
__m256i shuf = {0x0000000400000000, 0x0000000500000001,
0x0000000600000002, 0x0000000700000003};
int len = dstW >> 4;
int res = dstW & 15;
while (len--) {
SCALE_4_16(7);
}
if (res & 8) {
SCALE_4_8(7);
src0 = __lasx_xvpickev_h(src1, src0);
src0 = __lasx_xvperm_w(src0, shuf);
__lasx_xvstelm_d(src0, dst, 0, 0);
__lasx_xvstelm_d(src0, dst, 8, 1);
dst += 8;
}
if (res & 4) {
SCALE_4_4(7);
src0 = __lasx_xvpickev_h(src0, src0);
__lasx_xvstelm_d(src0, dst, 0, 0);
dst += 4;
}
if (res & 2) {
SCALE_4_2(7);
}
if (res & 1) {
int val = 0;
const uint8_t *srcPos = src + filterPos[0];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[0] = FFMIN(val >> 7, max);
}
} else if (filterSize > 8) {
int filterlen = filterSize - 7;
int len = dstW >> 2;
int res = dstW & 3;
__m256i zero = __lasx_xvldi(0);
while (len--) {
__m256i src0, src1, src2, src3;
__m256i filter0, filter1, filter2, filter3, out0, out1;
__m256i out = zero;
const uint8_t *srcPos1 = src + filterPos[0];
const uint8_t *srcPos2 = src + filterPos[1];
const uint8_t *srcPos3 = src + filterPos[2];
const uint8_t *srcPos4 = src + filterPos[3];
const int16_t *filterStart1 = filter;
const int16_t *filterStart2 = filterStart1 + filterSize;
const int16_t *filterStart3 = filterStart2 + filterSize;
const int16_t *filterStart4 = filterStart3 + filterSize;
int j, val1 = 0, val2 = 0, val3 = 0, val4 = 0;
for (j = 0; j < filterlen; j += 8) {
SCALE_16
}
val1 = __lasx_xvpickve2gr_w(out, 0);
val2 = __lasx_xvpickve2gr_w(out, 4);
val3 = __lasx_xvpickve2gr_w(out, 2);
val4 = __lasx_xvpickve2gr_w(out, 6);
for (; j < filterSize; j++) {
val1 += ((int)srcPos1[j]) * filterStart1[j];
val2 += ((int)srcPos2[j]) * filterStart2[j];
val3 += ((int)srcPos3[j]) * filterStart3[j];
val4 += ((int)srcPos4[j]) * filterStart4[j];
}
dst[0] = FFMIN(val1 >> 7, max);
dst[1] = FFMIN(val2 >> 7, max);
dst[2] = FFMIN(val3 >> 7, max);
dst[3] = FFMIN(val4 >> 7, max);
dst += 4;
filterPos += 4;
filter = filterStart4 + filterSize;
}
for(i = 0; i < res; i++) {
int j, val = 0;
const uint8_t *srcPos = src + filterPos[i];
__m256i src1, filter0, out0;
for (j = 0; j < filterlen; j += 8) {
src1 = __lasx_xvldrepl_d((srcPos + j), 0);
filter0 = __lasx_xvld(filter + j, 0);
src1 = __lasx_xvilvl_b(zero, src1);
out0 = __lasx_xvdp2_w_h(filter0, src1);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val += __lasx_xvpickve2gr_w(out0, 0);
}
for (; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> 7, max);
filter += filterSize;
}
} else {
for (i = 0; i < dstW; i++) {
int val = 0;
const uint8_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> 7, max);
filter += filterSize;
}
}
}
void ff_hscale_8_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
int i;
int max = (1 << 19) - 1;
int32_t *dst = (int32_t *) _dst;
if (filterSize == 8) {
__m256i src0, src1, src2, src3, src4, src5, src6, src7;
__m256i filter0, filter1, filter2, filter3;
__m256i vmax = __lasx_xvreplgr2vr_w(max);
__m256i shuf = {0x0000000400000000, 0x0000000500000001,
0x0000000600000002, 0x0000000700000003};
int len = dstW >> 3;
int res = dstW & 7;
while (len--) {
SCALE_8_8(3);
__lasx_xvst(src0, dst, 0);
dst += 8;
}
if (res & 4) {
SCALE_8_4(3);
__lasx_xvstelm_d(src0, dst, 0, 0);
__lasx_xvstelm_d(src0, dst, 8, 1);
dst += 4;
}
if (res & 2) {
SCALE_8_2(3);
}
if (res & 1) {
int val = 0;
__m256i src0, filter0, out0;
src0 = __lasx_xvldrepl_d(src + filterPos[0], 0);
filter0 = __lasx_xvld(filter, 0);
src0 = __lasx_vext2xv_hu_bu(src0);
out0 = __lasx_xvdp2_w_h(filter0, src0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val = __lasx_xvpickve2gr_w(out0, 0);
dst[0] = FFMIN(val >> 3, max);
}
} else if (filterSize == 4) {
__m256i src0, src1, src2, src3, src4, src5, src6, src7;
__m256i filter0, filter1;
__m256i vmax = __lasx_xvreplgr2vr_w(max);
__m256i shuf = {0x0000000100000000, 0x0000000500000004,
0x0000000300000002, 0x0000000700000006};
int len = dstW >> 3;
int res = dstW & 7;
while (len--) {
SCALE_4_8(3);
src0 = __lasx_xvperm_w(src0, shuf);
__lasx_xvst(src0, dst, 0);
dst += 8;
}
if (res & 4) {
SCALE_4_4(3);
__lasx_xvstelm_d(src0, dst, 0, 0);
__lasx_xvstelm_d(src0, dst, 8, 1);
dst += 4;
}
if (res & 2) {
SCALE_4_2(3);
}
if (res & 1) {
int val = 0;
const uint8_t *srcPos = src + filterPos[0];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[0] = FFMIN(val >> 3, max);
}
} else if (filterSize > 8) {
int len = dstW >> 2;
int res = dstW & 3;
int filterlen = filterSize - 7;
__m256i zero = __lasx_xvldi(0);
while (len--) {
__m256i src0, src1, src2, src3;
__m256i filter0, filter1, filter2, filter3, out0, out1;
__m256i out = zero;
const uint8_t *srcPos1 = src + filterPos[0];
const uint8_t *srcPos2 = src + filterPos[1];
const uint8_t *srcPos3 = src + filterPos[2];
const uint8_t *srcPos4 = src + filterPos[3];
const int16_t *filterStart1 = filter;
const int16_t *filterStart2 = filterStart1 + filterSize;
const int16_t *filterStart3 = filterStart2 + filterSize;
const int16_t *filterStart4 = filterStart3 + filterSize;
int j, val1 = 0, val2 = 0, val3 = 0, val4 = 0;
for (j = 0; j < filterlen; j += 8) {
SCALE_16
}
val1 = __lasx_xvpickve2gr_w(out, 0);
val2 = __lasx_xvpickve2gr_w(out, 4);
val3 = __lasx_xvpickve2gr_w(out, 2);
val4 = __lasx_xvpickve2gr_w(out, 6);
for (; j < filterSize; j++) {
val1 += ((int)srcPos1[j]) * filterStart1[j];
val2 += ((int)srcPos2[j]) * filterStart2[j];
val3 += ((int)srcPos3[j]) * filterStart3[j];
val4 += ((int)srcPos4[j]) * filterStart4[j];
}
dst[0] = FFMIN(val1 >> 3, max);
dst[1] = FFMIN(val2 >> 3, max);
dst[2] = FFMIN(val3 >> 3, max);
dst[3] = FFMIN(val4 >> 3, max);
dst += 4;
filterPos += 4;
filter = filterStart4 + filterSize;
}
for (i = 0; i < res; i++) {
int j, val = 0;
const uint8_t *srcPos = src + filterPos[i];
__m256i src1, filter0, out0;
for (j = 0; j < filterlen; j += 8) {
src1 = __lasx_xvldrepl_d((srcPos + j), 0);
filter0 = __lasx_xvld(filter + j, 0);
src1 = __lasx_xvilvl_b(zero, src1);
out0 = __lasx_xvdp2_w_h(filter0, src1);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val += __lasx_xvpickve2gr_w(out0, 0);
}
for (; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> 3, max);
filter += filterSize;
}
} else {
for (i = 0; i < dstW; i++) {
int val = 0;
const uint8_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> 3, max);
filter += filterSize;
}
}
}
#undef SCALE_16
#define SCALE_8 \
{ \
__m256i src0, src1, src2, src3, filter0, filter1, out0, out1; \
DUP4_ARG2(__lasx_xvld, src + filterPos[0], 0, src + filterPos[1], 0, \
src + filterPos[2], 0, src + filterPos[3], 0, src0, src1, src2,\
src3); \
filter0 = __lasx_xvld(filter, 0); \
filter1 = __lasx_xvld(filter, 32); \
src0 = __lasx_xvpermi_q(src0, src1, 0x02); \
src2 = __lasx_xvpermi_q(src2, src3, 0x02); \
out0 = __lasx_xvdp2_w_hu_h(src0, filter0); \
out1 = __lasx_xvdp2_w_hu_h(src2, filter1); \
src0 = __lasx_xvhaddw_d_w(out0, out0); \
src1 = __lasx_xvhaddw_d_w(out1, out1); \
out0 = __lasx_xvpackev_d(src1, src0); \
out1 = __lasx_xvpackod_d(src1, src0); \
out0 = __lasx_xvadd_w(out0, out1); \
out0 = __lasx_xvsra_w(out0, shift); \
out0 = __lasx_xvmin_w(out0, v_max); \
dst[0] = __lasx_xvpickve2gr_w(out0, 0); \
dst[1] = __lasx_xvpickve2gr_w(out0, 4); \
dst[2] = __lasx_xvpickve2gr_w(out0, 2); \
dst[3] = __lasx_xvpickve2gr_w(out0, 6); \
filterPos += 4; \
filter += 32; \
dst += 4; \
}
#define SCALE_16 \
{ \
int dex = j << 1; \
DUP4_ARG2(__lasx_xvldx, srcPos1, dex, srcPos2, dex, srcPos3, dex, \
srcPos4, dex, src0, src1, src2, src3); \
DUP4_ARG2(__lasx_xvldx, filterStart1, dex, filterStart2, dex, \
filterStart3, dex, filterStart4, dex, filter0, \
filter1, filter2, filter3); \
src0 = __lasx_xvpermi_q(src0, src1, 0x02); \
src1 = __lasx_xvpermi_q(src2, src3, 0x02); \
filter0 = __lasx_xvpermi_q(filter0, filter1, 0x02); \
filter1 = __lasx_xvpermi_q(filter2, filter3, 0x02); \
out0 = __lasx_xvdp2_w_hu_h(src0, filter0); \
out1 = __lasx_xvdp2_w_hu_h(src1, filter1); \
src0 = __lasx_xvhaddw_d_w(out0, out0); \
src1 = __lasx_xvhaddw_d_w(out1, out1); \
out0 = __lasx_xvpackev_d(src1, src0); \
out1 = __lasx_xvpackod_d(src1, src0); \
out0 = __lasx_xvadd_w(out0, out1); \
out = __lasx_xvadd_w(out, out0); \
}
void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
int i;
const uint16_t *src = (const uint16_t *) _src;
int sh = desc->comp[0].depth - 1;
int max = (1 << 15) - 1;
int len = dstW >> 2;
int res = dstW & 3;
__m256i shift;
__m256i zero = __lasx_xvldi(0);
if (sh < 15) {
sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 :
(desc->comp[0].depth - 1);
} else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) {
sh = 15;
}
shift = __lasx_xvreplgr2vr_w(sh);
if (filterSize == 8) {
__m256i v_max = __lasx_xvreplgr2vr_w(max);
for (i = 0; i < len; i++) {
SCALE_8
}
for (i = 0; i < res; i++) {
int val = 0;
__m256i src0, filter0, out0;
src0 = __lasx_xvld(src + filterPos[i], 0);
filter0 = __lasx_xvld(filter, 0);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val = __lasx_xvpickve2gr_w(out0, 0);
dst[i] = FFMIN(val >> sh, max);
filter += 8;
}
} else if (filterSize == 4) {
__m256i v_max = __lasx_xvreplgr2vr_w(max);
for (i = 0; i < len; i++) {
__m256i src1, src2, src3, src4, src0, filter0, out0;
src1 = __lasx_xvldrepl_d(src + filterPos[0], 0);
src2 = __lasx_xvldrepl_d(src + filterPos[1], 0);
src3 = __lasx_xvldrepl_d(src + filterPos[2], 0);
src4 = __lasx_xvldrepl_d(src + filterPos[3], 0);
filter0 = __lasx_xvld(filter, 0);
src1 = __lasx_xvextrins_d(src1, src2, 0x10);
src3 = __lasx_xvextrins_d(src3, src4, 0x10);
src0 = __lasx_xvpermi_q(src1, src3, 0x02);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvsra_w(out0, shift);
out0 = __lasx_xvmin_w(out0, v_max);
dst[0] = __lasx_xvpickve2gr_w(out0, 0);
dst[1] = __lasx_xvpickve2gr_w(out0, 2);
dst[2] = __lasx_xvpickve2gr_w(out0, 4);
dst[3] = __lasx_xvpickve2gr_w(out0, 6);
dst += 4;
filterPos += 4;
filter += 16;
}
for (i = 0; i < res; i++) {
int val = 0;
const uint16_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += 4;
}
} else if (filterSize > 8) {
int filterlen = filterSize - 7;
for (i = 0; i < len; i++) {
__m256i src0, src1, src2, src3;
__m256i filter0, filter1, filter2, filter3, out0, out1;
__m256i out = zero;
const uint16_t *srcPos1 = src + filterPos[0];
const uint16_t *srcPos2 = src + filterPos[1];
const uint16_t *srcPos3 = src + filterPos[2];
const uint16_t *srcPos4 = src + filterPos[3];
const int16_t *filterStart1 = filter;
const int16_t *filterStart2 = filterStart1 + filterSize;
const int16_t *filterStart3 = filterStart2 + filterSize;
const int16_t *filterStart4 = filterStart3 + filterSize;
int j, val1 = 0, val2 = 0, val3 = 0, val4 = 0;
for (j = 0; j < filterlen; j += 8) {
SCALE_16
}
val1 = __lasx_xvpickve2gr_w(out, 0);
val2 = __lasx_xvpickve2gr_w(out, 4);
val3 = __lasx_xvpickve2gr_w(out, 2);
val4 = __lasx_xvpickve2gr_w(out, 6);
for (; j < filterSize; j++) {
val1 += ((int)srcPos1[j]) * filterStart1[j];
val2 += ((int)srcPos2[j]) * filterStart2[j];
val3 += ((int)srcPos3[j]) * filterStart3[j];
val4 += ((int)srcPos4[j]) * filterStart4[j];
}
dst[0] = FFMIN(val1 >> sh, max);
dst[1] = FFMIN(val2 >> sh, max);
dst[2] = FFMIN(val3 >> sh, max);
dst[3] = FFMIN(val4 >> sh, max);
dst += 4;
filterPos += 4;
filter = filterStart4 + filterSize;
}
for (i = 0; i < res; i++) {
int j, val = 0;
const uint16_t *srcPos = src + filterPos[i];
__m256i src0, filter0, out0;
for (j = 0; j < filterlen; j += 8) {
int dex = j << 1;
src0 = __lasx_xvldx(srcPos, dex);
filter0 = __lasx_xvldx(filter, dex);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val += __lasx_xvpickve2gr_w(out0, 0);
}
for (; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += filterSize;
}
} else {
for (i = 0; i < dstW; i++) {
int val = 0;
const uint16_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += filterSize;
}
}
}
void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
int i;
int32_t *dst = (int32_t *) _dst;
const uint16_t *src = (const uint16_t *) _src;
int sh = desc->comp[0].depth - 5;
int max = (1 << 19) - 1;
int len = dstW >> 2;
int res = dstW & 3;
__m256i shift;
__m256i zero = __lasx_xvldi(0);
if ((isAnyRGB(c->opts.src_format) || c->opts.src_format == AV_PIX_FMT_PAL8)
&& desc->comp[0].depth<16) {
sh = 9;
} else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
sh = 11;
}
shift = __lasx_xvreplgr2vr_w(sh);
if (filterSize == 8) {
__m256i v_max = __lasx_xvreplgr2vr_w(max);
for (i = 0; i < len; i++) {
SCALE_8
}
for (i = 0; i < res; i++) {
int val = 0;
__m256i src0, filter0, out0;
src0 = __lasx_xvld(src + filterPos[i], 0);
filter0 = __lasx_xvld(filter, 0);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val = __lasx_xvpickve2gr_w(out0, 0);
dst[i] = FFMIN(val >> sh, max);
filter += 8;
}
} else if (filterSize == 4) {
__m256i v_max = __lasx_xvreplgr2vr_w(max);
for (i = 0; i < len; i++) {
__m256i src1, src2, src3, src4, src0, filter0, out0;
src1 = __lasx_xvldrepl_d(src + filterPos[0], 0);
src2 = __lasx_xvldrepl_d(src + filterPos[1], 0);
src3 = __lasx_xvldrepl_d(src + filterPos[2], 0);
src4 = __lasx_xvldrepl_d(src + filterPos[3], 0);
filter0 = __lasx_xvld(filter, 0);
src1 = __lasx_xvextrins_d(src1, src2, 0x10);
src3 = __lasx_xvextrins_d(src3, src4, 0x10);
src0 = __lasx_xvpermi_q(src1, src3, 0x02);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvsra_w(out0, shift);
out0 = __lasx_xvmin_w(out0, v_max);
dst[0] = __lasx_xvpickve2gr_w(out0, 0);
dst[1] = __lasx_xvpickve2gr_w(out0, 2);
dst[2] = __lasx_xvpickve2gr_w(out0, 4);
dst[3] = __lasx_xvpickve2gr_w(out0, 6);
dst += 4;
filterPos += 4;
filter += 16;
}
for (i = 0; i < res; i++) {
int val = 0;
const uint16_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += 4;
}
} else if (filterSize > 8) {
int filterlen = filterSize - 7;
for (i = 0; i < len; i ++) {
__m256i src0, src1, src2, src3;
__m256i filter0, filter1, filter2, filter3, out0, out1;
__m256i out = zero;
const uint16_t *srcPos1 = src + filterPos[0];
const uint16_t *srcPos2 = src + filterPos[1];
const uint16_t *srcPos3 = src + filterPos[2];
const uint16_t *srcPos4 = src + filterPos[3];
const int16_t *filterStart1 = filter;
const int16_t *filterStart2 = filterStart1 + filterSize;
const int16_t *filterStart3 = filterStart2 + filterSize;
const int16_t *filterStart4 = filterStart3 + filterSize;
int j, val1 = 0, val2 = 0, val3 = 0, val4 = 0;
for (j = 0; j < filterlen; j += 8) {
SCALE_16
}
val1 = __lasx_xvpickve2gr_w(out, 0);
val2 = __lasx_xvpickve2gr_w(out, 4);
val3 = __lasx_xvpickve2gr_w(out, 2);
val4 = __lasx_xvpickve2gr_w(out, 6);
for (; j < filterSize; j++) {
val1 += ((int)srcPos1[j]) * filterStart1[j];
val2 += ((int)srcPos2[j]) * filterStart2[j];
val3 += ((int)srcPos3[j]) * filterStart3[j];
val4 += ((int)srcPos4[j]) * filterStart4[j];
}
dst[0] = FFMIN(val1 >> sh, max);
dst[1] = FFMIN(val2 >> sh, max);
dst[2] = FFMIN(val3 >> sh, max);
dst[3] = FFMIN(val4 >> sh, max);
dst += 4;
filterPos += 4;
filter = filterStart4 + filterSize;
}
for (i = 0; i < res; i++) {
int j, val = 0;
const uint16_t *srcPos = src + filterPos[i];
__m256i src0, filter0, out0;
for (j = 0; j < filterlen; j += 8) {
int dex = j << 1;
src0 = __lasx_xvldx(srcPos, dex);
filter0 = __lasx_xvldx(filter, dex);
out0 = __lasx_xvdp2_w_hu_h(src0, filter0);
out0 = __lasx_xvhaddw_d_w(out0, out0);
out0 = __lasx_xvhaddw_q_d(out0, out0);
val += __lasx_xvpickve2gr_w(out0, 0);
}
for (; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += filterSize;
}
} else {
for (i = 0; i < dstW; i++) {
int val = 0;
const uint16_t *srcPos = src + filterPos[i];
for (int j = 0; j < filterSize; j++) {
val += ((int)srcPos[j]) * filter[j];
}
dst[i] = FFMIN(val >> sh, max);
filter += filterSize;
}
}
}
#undef SCALE_8
#undef SCALE_16
@@ -0,0 +1,211 @@
/*
* Copyright (C) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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
*/
#ifndef SWSCALE_LOONGARCH_SWSCALE_LOONGARCH_H
#define SWSCALE_LOONGARCH_SWSCALE_LOONGARCH_H
#include "libswscale/swscale.h"
#include "libswscale/swscale_internal.h"
#include "config.h"
void ff_hscale_8_to_15_lsx(SwsInternal *c, int16_t *dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_8_to_19_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_16_to_15_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_16_to_15_sub_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize, int sh);
void ff_hscale_16_to_19_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_16_to_19_sub_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize, int sh);
void lumRangeFromJpeg_lsx(int16_t *dst, int width);
void chrRangeFromJpeg_lsx(int16_t *dstU, int16_t *dstV, int width);
void lumRangeToJpeg_lsx(int16_t *dst, int width);
void chrRangeToJpeg_lsx(int16_t *dstU, int16_t *dstV, int width);
void planar_rgb_to_uv_lsx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4],
int width, int32_t *rgb2yuv, void *opq);
void planar_rgb_to_y_lsx(uint8_t *_dst, const uint8_t *src[4], int width,
int32_t *rgb2yuv, void *opq);
void yuv2planeX_8_lsx(const int16_t *filter, int filterSize,
const int16_t **src, uint8_t *dest, int dstW,
const uint8_t *dither, int offset);
void yuv2plane1_8_lsx(const int16_t *src, uint8_t *dest, int dstW,
const uint8_t *dither, int offset);
void yuy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void yvy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void uyvyToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void nv12ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void nv21ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void abgrToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
const uint8_t *unused2, int width, uint32_t *unused, void *opq);
void rgbaToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
const uint8_t *unused2, int width, uint32_t *unused, void *opq);
av_cold void ff_sws_init_input_lsx(SwsInternal *c);
av_cold void ff_sws_init_output_lsx(SwsInternal *c,
yuv2planar1_fn *yuv2plane1,
yuv2planarX_fn *yuv2planeX,
yuv2interleavedX_fn *yuv2nv12cX,
yuv2packed1_fn *yuv2packed1,
yuv2packed2_fn *yuv2packed2,
yuv2packedX_fn *yuv2packedX,
yuv2anyX_fn *yuv2anyX);
int yuv420_rgb24_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_bgr24_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_rgba32_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_bgra32_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_argb32_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_abgr32_lsx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
#if HAVE_LASX
void ff_hscale_8_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_8_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize);
void lumRangeFromJpeg_lasx(int16_t *dst, int width);
void chrRangeFromJpeg_lasx(int16_t *dstU, int16_t *dstV, int width);
void lumRangeToJpeg_lasx(int16_t *dst, int width);
void chrRangeToJpeg_lasx(int16_t *dstU, int16_t *dstV, int width);
void planar_rgb_to_uv_lasx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4],
int width, int32_t *rgb2yuv, void *opq);
void planar_rgb_to_y_lasx(uint8_t *_dst, const uint8_t *src[4], int width,
int32_t *rgb2yuv, void *opq);
int yuv420_rgb24_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_bgr24_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_rgba32_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_bgra32_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_argb32_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int yuv420_abgr32_lasx(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
void ff_interleave_bytes_lasx(const uint8_t *src1, const uint8_t *src2,
uint8_t *dest, int width, int height,
int src1Stride, int src2Stride, int dstStride);
void yuv2planeX_8_lasx(const int16_t *filter, int filterSize,
const int16_t **src, uint8_t *dest, int dstW,
const uint8_t *dither, int offset);
void yuv2plane1_8_lasx(const int16_t *src, uint8_t *dest, int dstW,
const uint8_t *dither, int offset);
void yuy2ToUV_lasx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void yvy2ToUV_lasx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void uyvyToUV_lasx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void nv12ToUV_lasx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void nv21ToUV_lasx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1,
const uint8_t *src2, int width, uint32_t *unused, void *opq);
void abgrToA_lasx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
const uint8_t *unused2, int width, uint32_t *unused, void *opq);
void rgbaToA_lasx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1,
const uint8_t *unused2, int width, uint32_t *unused, void *opq);
av_cold void ff_sws_init_input_lasx(SwsInternal *c);
av_cold void ff_sws_init_output_lasx(SwsInternal *c,
yuv2planar1_fn *yuv2plane1,
yuv2planarX_fn *yuv2planeX,
yuv2interleavedX_fn *yuv2nv12cX,
yuv2packed1_fn *yuv2packed1,
yuv2packed2_fn *yuv2packed2,
yuv2packedX_fn *yuv2packedX,
yuv2anyX_fn *yuv2anyX);
#endif // #if HAVE_LASX
#endif /* SWSCALE_LOONGARCH_SWSCALE_LOONGARCH_H */
+57
View File
@@ -0,0 +1,57 @@
/*
* Loongson LSX optimized swscale
*
* 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"
void ff_hscale_16_to_15_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
int sh = desc->comp[0].depth - 1;
if (sh < 15) {
sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 :
(desc->comp[0].depth - 1);
} else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) {
sh = 15;
}
ff_hscale_16_to_15_sub_lsx(c, _dst, dstW, _src, filter, filterPos, filterSize, sh);
}
void ff_hscale_16_to_19_lsx(SwsInternal *c, int16_t *_dst, int dstW,
const uint8_t *_src, const int16_t *filter,
const int32_t *filterPos, int filterSize)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
int bits = desc->comp[0].depth - 1;
int sh = bits - 4;
if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
sh = 9;
} else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
sh = 16 - 1 - 4;
}
ff_hscale_16_to_19_sub_lsx(c, _dst, dstW, _src, filter, filterPos, filterSize, sh);
}
+321
View File
@@ -0,0 +1,321 @@
/*
* Copyright (C) 2022 Loongson Technology Corporation Limited
* Contributed by Hao Chen(chenhao@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"
#define YUV2RGB_LOAD_COE \
/* Load x_offset */ \
__m256i y_offset = __lasx_xvreplgr2vr_d(c->yOffset); \
__m256i u_offset = __lasx_xvreplgr2vr_d(c->uOffset); \
__m256i v_offset = __lasx_xvreplgr2vr_d(c->vOffset); \
/* Load x_coeff */ \
__m256i ug_coeff = __lasx_xvreplgr2vr_d(c->ugCoeff); \
__m256i vg_coeff = __lasx_xvreplgr2vr_d(c->vgCoeff); \
__m256i y_coeff = __lasx_xvreplgr2vr_d(c->yCoeff); \
__m256i ub_coeff = __lasx_xvreplgr2vr_d(c->ubCoeff); \
__m256i vr_coeff = __lasx_xvreplgr2vr_d(c->vrCoeff); \
#define LOAD_YUV_16 \
m_y1 = __lasx_xvld(py_1, 0); \
m_y2 = __lasx_xvld(py_2, 0); \
m_u = __lasx_xvldrepl_d(pu, 0); \
m_v = __lasx_xvldrepl_d(pv, 0); \
m_u = __lasx_xvilvl_b(m_u, m_u); \
m_v = __lasx_xvilvl_b(m_v, m_v); \
DUP4_ARG1(__lasx_vext2xv_hu_bu, m_y1, m_y2, m_u, m_v, \
m_y1, m_y2, m_u, m_v); \
/* YUV2RGB method
* The conversion method is as follows:
* R = Y' * y_coeff + V' * vr_coeff
* G = Y' * y_coeff + V' * vg_coeff + U' * ug_coeff
* B = Y' * y_coeff + U' * ub_coeff
*
* where X' = X * 8 - x_offset
*
*/
#define YUV2RGB \
m_y1 = __lasx_xvslli_h(m_y1, 3); \
m_y2 = __lasx_xvslli_h(m_y2, 3); \
m_u = __lasx_xvslli_h(m_u, 3); \
m_v = __lasx_xvslli_h(m_v, 3); \
m_y1 = __lasx_xvsub_h(m_y1, y_offset); \
m_y2 = __lasx_xvsub_h(m_y2, y_offset); \
m_u = __lasx_xvsub_h(m_u, u_offset); \
m_v = __lasx_xvsub_h(m_v, v_offset); \
y_1 = __lasx_xvmuh_h(m_y1, y_coeff); \
y_2 = __lasx_xvmuh_h(m_y2, y_coeff); \
u2g = __lasx_xvmuh_h(m_u, ug_coeff); \
u2b = __lasx_xvmuh_h(m_u, ub_coeff); \
v2r = __lasx_xvmuh_h(m_v, vr_coeff); \
v2g = __lasx_xvmuh_h(m_v, vg_coeff); \
r1 = __lasx_xvsadd_h(y_1, v2r); \
v2g = __lasx_xvsadd_h(v2g, u2g); \
g1 = __lasx_xvsadd_h(y_1, v2g); \
b1 = __lasx_xvsadd_h(y_1, u2b); \
r2 = __lasx_xvsadd_h(y_2, v2r); \
g2 = __lasx_xvsadd_h(y_2, v2g); \
b2 = __lasx_xvsadd_h(y_2, u2b); \
DUP4_ARG1(__lasx_xvclip255_h, r1, g1, b1, r2, r1, g1, b1, r2); \
DUP2_ARG1(__lasx_xvclip255_h, g2, b2, g2, b2); \
#define YUV2RGB_RES \
m_y1 = __lasx_xvldrepl_d(py_1, 0); \
m_y2 = __lasx_xvldrepl_d(py_2, 0); \
m_u = __lasx_xvldrepl_w(pu, 0); \
m_v = __lasx_xvldrepl_w(pv, 0); \
m_y1 = __lasx_xvilvl_d(m_y2, m_y1); \
m_u = __lasx_xvilvl_b(m_u, m_u); \
m_v = __lasx_xvilvl_b(m_v, m_v); \
m_y1 = __lasx_vext2xv_hu_bu(m_y1); \
m_u = __lasx_vext2xv_hu_bu(m_u); \
m_v = __lasx_vext2xv_hu_bu(m_v); \
m_y1 = __lasx_xvslli_h(m_y1, 3); \
m_u = __lasx_xvslli_h(m_u, 3); \
m_v = __lasx_xvslli_h(m_v, 3); \
m_y1 = __lasx_xvsub_h(m_y1, y_offset); \
m_u = __lasx_xvsub_h(m_u, u_offset); \
m_v = __lasx_xvsub_h(m_v, v_offset); \
y_1 = __lasx_xvmuh_h(m_y1, y_coeff); \
u2g = __lasx_xvmuh_h(m_u, ug_coeff); \
u2b = __lasx_xvmuh_h(m_u, ub_coeff); \
v2r = __lasx_xvmuh_h(m_v, vr_coeff); \
v2g = __lasx_xvmuh_h(m_v, vg_coeff); \
r1 = __lasx_xvsadd_h(y_1, v2r); \
v2g = __lasx_xvsadd_h(v2g, u2g); \
g1 = __lasx_xvsadd_h(y_1, v2g); \
b1 = __lasx_xvsadd_h(y_1, u2b); \
r1 = __lasx_xvclip255_h(r1); \
g1 = __lasx_xvclip255_h(g1); \
b1 = __lasx_xvclip255_h(b1); \
#define RGB_PACK(r, g, b, rgb_l, rgb_h) \
{ \
__m256i rg; \
rg = __lasx_xvpackev_b(g, r); \
DUP2_ARG3(__lasx_xvshuf_b, b, rg, shuf2, b, rg, shuf3, rgb_l, rgb_h); \
}
#define RGB32_PACK(a, r, g, b, rgb_l, rgb_h) \
{ \
__m256i ra, bg, tmp0, tmp1; \
ra = __lasx_xvpackev_b(r, a); \
bg = __lasx_xvpackev_b(b, g); \
tmp0 = __lasx_xvilvl_h(bg, ra); \
tmp1 = __lasx_xvilvh_h(bg, ra); \
rgb_l = __lasx_xvpermi_q(tmp1, tmp0, 0x20); \
rgb_h = __lasx_xvpermi_q(tmp1, tmp0, 0x31); \
}
#define RGB_STORE_RES(rgb_l, rgb_h, image_1, image_2) \
{ \
__lasx_xvstelm_d(rgb_l, image_1, 0, 0); \
__lasx_xvstelm_d(rgb_l, image_1, 8, 1); \
__lasx_xvstelm_d(rgb_h, image_1, 16, 0); \
__lasx_xvstelm_d(rgb_l, image_2, 0, 2); \
__lasx_xvstelm_d(rgb_l, image_2, 8, 3); \
__lasx_xvstelm_d(rgb_h, image_2, 16, 2); \
}
#define RGB_STORE(rgb_l, rgb_h, image) \
{ \
__lasx_xvstelm_d(rgb_l, image, 0, 0); \
__lasx_xvstelm_d(rgb_l, image, 8, 1); \
__lasx_xvstelm_d(rgb_h, image, 16, 0); \
__lasx_xvstelm_d(rgb_l, image, 24, 2); \
__lasx_xvstelm_d(rgb_l, image, 32, 3); \
__lasx_xvstelm_d(rgb_h, image, 40, 2); \
}
#define RGB32_STORE(rgb_l, rgb_h, image) \
{ \
__lasx_xvst(rgb_l, image, 0); \
__lasx_xvst(rgb_h, image, 32); \
}
#define RGB32_STORE_RES(rgb_l, rgb_h, image_1, image_2) \
{ \
__lasx_xvst(rgb_l, image_1, 0); \
__lasx_xvst(rgb_h, image_2, 0); \
}
#define YUV2RGBFUNC(func_name, dst_type, alpha) \
int func_name(SwsInternal *c, const uint8_t *const src[], \
const int srcStride[], int srcSliceY, int srcSliceH, \
uint8_t *const dst[], const int dstStride[]) \
{ \
int x, y, h_size, vshift, res; \
__m256i m_y1, m_y2, m_u, m_v; \
__m256i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \
__m256i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \
__m256i shuf2 = {0x0504120302100100, 0x0A18090816070614, \
0x0504120302100100, 0x0A18090816070614}; \
__m256i shuf3 = {0x1E0F0E1C0D0C1A0B, 0x0101010101010101, \
0x1E0F0E1C0D0C1A0B, 0x0101010101010101}; \
YUV2RGB_LOAD_COE \
y = (c->opts.dst_w + 7) & ~7; \
h_size = y >> 4; \
res = y & 15; \
\
vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \
for (y = 0; y < srcSliceH; y += 2) { \
dst_type *image1 = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\
dst_type *image2 = (dst_type *)(image1 + dstStride[0]);\
const uint8_t *py_1 = src[0] + y * srcStride[0]; \
const uint8_t *py_2 = py_1 + srcStride[0]; \
const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1]; \
const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \
for(x = 0; x < h_size; x++) { \
#define YUV2RGBFUNC32(func_name, dst_type, alpha) \
int func_name(SwsInternal *c, const uint8_t *const src[], \
const int srcStride[], int srcSliceY, int srcSliceH, \
uint8_t *const dst[], const int dstStride[]) \
{ \
int x, y, h_size, vshift, res; \
__m256i m_y1, m_y2, m_u, m_v; \
__m256i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \
__m256i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \
__m256i a = __lasx_xvldi(0xFF); \
\
YUV2RGB_LOAD_COE \
y = (c->opts.dst_w + 7) & ~7; \
h_size = y >> 4; \
res = y & 15; \
\
vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \
for (y = 0; y < srcSliceH; y += 2) { \
int yd = y + srcSliceY; \
dst_type av_unused *r, *g, *b; \
dst_type *image1 = (dst_type *)(dst[0] + (yd) * dstStride[0]); \
dst_type *image2 = (dst_type *)(dst[0] + (yd + 1) * dstStride[0]); \
const uint8_t *py_1 = src[0] + y * srcStride[0]; \
const uint8_t *py_2 = py_1 + srcStride[0]; \
const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1]; \
const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \
for(x = 0; x < h_size; x++) { \
#define DEALYUV2RGBREMAIN \
py_1 += 16; \
py_2 += 16; \
pu += 8; \
pv += 8; \
image1 += 48; \
image2 += 48; \
} \
if (res) { \
#define DEALYUV2RGBREMAIN32 \
py_1 += 16; \
py_2 += 16; \
pu += 8; \
pv += 8; \
image1 += 16; \
image2 += 16; \
} \
if (res) { \
#define END_FUNC() \
} \
} \
return srcSliceH; \
}
YUV2RGBFUNC(yuv420_rgb24_lasx, uint8_t, 0)
LOAD_YUV_16
YUV2RGB
RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h);
RGB_PACK(r2, g2, b2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1);
RGB_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN
YUV2RGB_RES
RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h);
RGB_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
YUV2RGBFUNC(yuv420_bgr24_lasx, uint8_t, 0)
LOAD_YUV_16
YUV2RGB
RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h);
RGB_PACK(b2, g2, r2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1);
RGB_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN
YUV2RGB_RES
RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h);
RGB_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
YUV2RGBFUNC32(yuv420_rgba32_lasx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB
RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h);
RGB32_PACK(r2, g2, b2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN32
YUV2RGB_RES
RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h);
RGB32_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
YUV2RGBFUNC32(yuv420_bgra32_lasx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB
RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h);
RGB32_PACK(b2, g2, r2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN32
YUV2RGB_RES
RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h);
RGB32_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
YUV2RGBFUNC32(yuv420_argb32_lasx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB
RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h);
RGB32_PACK(a, r2, g2, b2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN32
YUV2RGB_RES
RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h);
RGB32_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
YUV2RGBFUNC32(yuv420_abgr32_lasx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB
RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h);
RGB32_PACK(a, b2, g2, r2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
DEALYUV2RGBREMAIN32
YUV2RGB_RES
RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h);
RGB32_STORE_RES(rgb1_l, rgb1_h, image1, image2);
END_FUNC()
+361
View File
@@ -0,0 +1,361 @@
/*
* Copyright (C) 2023 Loongson Technology Co. Ltd.
* Contributed by Bo Jin(jinbo@loongson.cn)
* All rights reserved.
*
* 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"
#define YUV2RGB_LOAD_COE \
/* Load x_offset */ \
__m128i y_offset = __lsx_vreplgr2vr_d(c->yOffset); \
__m128i u_offset = __lsx_vreplgr2vr_d(c->uOffset); \
__m128i v_offset = __lsx_vreplgr2vr_d(c->vOffset); \
/* Load x_coeff */ \
__m128i ug_coeff = __lsx_vreplgr2vr_d(c->ugCoeff); \
__m128i vg_coeff = __lsx_vreplgr2vr_d(c->vgCoeff); \
__m128i y_coeff = __lsx_vreplgr2vr_d(c->yCoeff); \
__m128i ub_coeff = __lsx_vreplgr2vr_d(c->ubCoeff); \
__m128i vr_coeff = __lsx_vreplgr2vr_d(c->vrCoeff); \
#define LOAD_YUV_16 \
m_y1 = __lsx_vld(py_1, 0); \
m_y2 = __lsx_vld(py_2, 0); \
m_u = __lsx_vldrepl_d(pu, 0); \
m_v = __lsx_vldrepl_d(pv, 0); \
DUP2_ARG2(__lsx_vilvl_b, m_u, m_u, m_v, m_v, m_u, m_v); \
DUP2_ARG2(__lsx_vilvh_b, zero, m_u, zero, m_v, m_u_h, m_v_h); \
DUP2_ARG2(__lsx_vilvl_b, zero, m_u, zero, m_v, m_u, m_v); \
DUP2_ARG2(__lsx_vilvh_b, zero, m_y1, zero, m_y2, m_y1_h, m_y2_h); \
DUP2_ARG2(__lsx_vilvl_b, zero, m_y1, zero, m_y2, m_y1, m_y2); \
/* YUV2RGB method
* The conversion method is as follows:
* R = Y' * y_coeff + V' * vr_coeff
* G = Y' * y_coeff + V' * vg_coeff + U' * ug_coeff
* B = Y' * y_coeff + U' * ub_coeff
*
* where X' = X * 8 - x_offset
*
*/
#define YUV2RGB(y1, y2, u, v, r1, g1, b1, r2, g2, b2) \
{ \
y1 = __lsx_vslli_h(y1, 3); \
y2 = __lsx_vslli_h(y2, 3); \
u = __lsx_vslli_h(u, 3); \
v = __lsx_vslli_h(v, 3); \
y1 = __lsx_vsub_h(y1, y_offset); \
y2 = __lsx_vsub_h(y2, y_offset); \
u = __lsx_vsub_h(u, u_offset); \
v = __lsx_vsub_h(v, v_offset); \
y_1 = __lsx_vmuh_h(y1, y_coeff); \
y_2 = __lsx_vmuh_h(y2, y_coeff); \
u2g = __lsx_vmuh_h(u, ug_coeff); \
u2b = __lsx_vmuh_h(u, ub_coeff); \
v2r = __lsx_vmuh_h(v, vr_coeff); \
v2g = __lsx_vmuh_h(v, vg_coeff); \
r1 = __lsx_vsadd_h(y_1, v2r); \
v2g = __lsx_vsadd_h(v2g, u2g); \
g1 = __lsx_vsadd_h(y_1, v2g); \
b1 = __lsx_vsadd_h(y_1, u2b); \
r2 = __lsx_vsadd_h(y_2, v2r); \
g2 = __lsx_vsadd_h(y_2, v2g); \
b2 = __lsx_vsadd_h(y_2, u2b); \
DUP4_ARG1(__lsx_vclip255_h, r1, g1, b1, r2, r1, g1, b1, r2); \
DUP2_ARG1(__lsx_vclip255_h, g2, b2, g2, b2); \
}
#define RGB_PACK(r, g, b, rgb_l, rgb_h) \
{ \
__m128i rg; \
rg = __lsx_vpackev_b(g, r); \
DUP2_ARG3(__lsx_vshuf_b, b, rg, shuf2, b, rg, shuf3, rgb_l, rgb_h); \
}
#define RGB32_PACK(a, r, g, b, rgb_l, rgb_h) \
{ \
__m128i ra, bg; \
ra = __lsx_vpackev_b(r, a); \
bg = __lsx_vpackev_b(b, g); \
rgb_l = __lsx_vilvl_h(bg, ra); \
rgb_h = __lsx_vilvh_h(bg, ra); \
}
#define RGB_STORE(rgb_l, rgb_h, image) \
{ \
__lsx_vstelm_d(rgb_l, image, 0, 0); \
__lsx_vstelm_d(rgb_l, image, 8, 1); \
__lsx_vstelm_d(rgb_h, image, 16, 0); \
}
#define RGB32_STORE(rgb_l, rgb_h, image) \
{ \
__lsx_vst(rgb_l, image, 0); \
__lsx_vst(rgb_h, image, 16); \
}
#define YUV2RGBFUNC(func_name, dst_type, alpha) \
int func_name(SwsInternal *c, const uint8_t *const src[], \
const int srcStride[], int srcSliceY, int srcSliceH, \
uint8_t *const dst[], const int dstStride[]) \
{ \
int x, y, h_size, vshift, res; \
__m128i m_y1, m_y2, m_u, m_v; \
__m128i m_y1_h, m_y2_h, m_u_h, m_v_h; \
__m128i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \
__m128i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \
__m128i shuf2 = {0x0504120302100100, 0x0A18090816070614}; \
__m128i shuf3 = {0x1E0F0E1C0D0C1A0B, 0x0101010101010101}; \
__m128i zero = __lsx_vldi(0); \
\
YUV2RGB_LOAD_COE \
\
h_size = c->opts.dst_w >> 4; \
res = (c->opts.dst_w & 15) >> 1; \
vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \
for (y = 0; y < srcSliceH; y += 2) { \
dst_type av_unused *r, *g, *b; \
dst_type *image1 = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\
dst_type *image2 = (dst_type *)(image1 + dstStride[0]);\
const uint8_t *py_1 = src[0] + y * srcStride[0]; \
const uint8_t *py_2 = py_1 + srcStride[0]; \
const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1]; \
const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \
for(x = 0; x < h_size; x++) { \
#define YUV2RGBFUNC32(func_name, dst_type, alpha) \
int func_name(SwsInternal *c, const uint8_t *const src[], \
const int srcStride[], int srcSliceY, int srcSliceH, \
uint8_t *const dst[], const int dstStride[]) \
{ \
int x, y, h_size, vshift, res; \
__m128i m_y1, m_y2, m_u, m_v; \
__m128i m_y1_h, m_y2_h, m_u_h, m_v_h; \
__m128i y_1, y_2, u2g, v2g, u2b, v2r, rgb1_l, rgb1_h; \
__m128i rgb2_l, rgb2_h, r1, g1, b1, r2, g2, b2; \
__m128i a = __lsx_vldi(0xFF); \
__m128i zero = __lsx_vldi(0); \
\
YUV2RGB_LOAD_COE \
\
h_size = c->opts.dst_w >> 4; \
res = (c->opts.dst_w & 15) >> 1; \
vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \
for (y = 0; y < srcSliceH; y += 2) { \
int yd = y + srcSliceY; \
dst_type av_unused *r, *g, *b; \
dst_type *image1 = (dst_type *)(dst[0] + (yd) * dstStride[0]); \
dst_type *image2 = (dst_type *)(dst[0] + (yd + 1) * dstStride[0]); \
const uint8_t *py_1 = src[0] + y * srcStride[0]; \
const uint8_t *py_2 = py_1 + srcStride[0]; \
const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1]; \
const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \
for(x = 0; x < h_size; x++) { \
#define DEALYUV2RGBREMAIN \
py_1 += 16; \
py_2 += 16; \
pu += 8; \
pv += 8; \
image1 += 48; \
image2 += 48; \
} \
for (x = 0; x < res; x++) { \
int av_unused U, V, Y; \
U = pu[0]; \
V = pv[0]; \
r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM]; \
g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] \
+ c->table_gV[V+YUVRGB_TABLE_HEADROOM]); \
b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM];
#define DEALYUV2RGBREMAIN32 \
py_1 += 16; \
py_2 += 16; \
pu += 8; \
pv += 8; \
image1 += 16; \
image2 += 16; \
} \
for (x = 0; x < res; x++) { \
int av_unused U, V, Y; \
U = pu[0]; \
V = pv[0]; \
r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM]; \
g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] \
+ c->table_gV[V+YUVRGB_TABLE_HEADROOM]); \
b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM]; \
#define PUTRGB24(dst, src) \
Y = src[0]; \
dst[0] = r[Y]; \
dst[1] = g[Y]; \
dst[2] = b[Y]; \
Y = src[1]; \
dst[3] = r[Y]; \
dst[4] = g[Y]; \
dst[5] = b[Y];
#define PUTBGR24(dst, src) \
Y = src[0]; \
dst[0] = b[Y]; \
dst[1] = g[Y]; \
dst[2] = r[Y]; \
Y = src[1]; \
dst[3] = b[Y]; \
dst[4] = g[Y]; \
dst[5] = r[Y];
#define PUTRGB(dst, src) \
Y = src[0]; \
dst[0] = r[Y] + g[Y] + b[Y]; \
Y = src[1]; \
dst[1] = r[Y] + g[Y] + b[Y]; \
#define ENDRES \
pu += 1; \
pv += 1; \
py_1 += 2; \
py_2 += 2; \
image1 += 6; \
image2 += 6; \
#define ENDRES32 \
pu += 1; \
pv += 1; \
py_1 += 2; \
py_2 += 2; \
image1 += 2; \
image2 += 2; \
#define END_FUNC() \
} \
} \
return srcSliceH; \
}
YUV2RGBFUNC(yuv420_rgb24_lsx, uint8_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h);
RGB_PACK(r2, g2, b2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1);
RGB_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB_PACK(r1, g1, b1, rgb1_l, rgb1_h);
RGB_PACK(r2, g2, b2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1 + 24);
RGB_STORE(rgb2_l, rgb2_h, image2 + 24);
DEALYUV2RGBREMAIN
PUTRGB24(image1, py_1);
PUTRGB24(image2, py_2);
ENDRES
END_FUNC()
YUV2RGBFUNC(yuv420_bgr24_lsx, uint8_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h);
RGB_PACK(b2, g2, r2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1);
RGB_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB_PACK(b1, g1, r1, rgb1_l, rgb1_h);
RGB_PACK(b2, g2, r2, rgb2_l, rgb2_h);
RGB_STORE(rgb1_l, rgb1_h, image1 + 24);
RGB_STORE(rgb2_l, rgb2_h, image2 + 24);
DEALYUV2RGBREMAIN
PUTBGR24(image1, py_1);
PUTBGR24(image2, py_2);
ENDRES
END_FUNC()
YUV2RGBFUNC32(yuv420_rgba32_lsx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h);
RGB32_PACK(r2, g2, b2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB32_PACK(r1, g1, b1, a, rgb1_l, rgb1_h);
RGB32_PACK(r2, g2, b2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1 + 8);
RGB32_STORE(rgb2_l, rgb2_h, image2 + 8);
DEALYUV2RGBREMAIN32
PUTRGB(image1, py_1);
PUTRGB(image2, py_2);
ENDRES32
END_FUNC()
YUV2RGBFUNC32(yuv420_bgra32_lsx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h);
RGB32_PACK(b2, g2, r2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB32_PACK(b1, g1, r1, a, rgb1_l, rgb1_h);
RGB32_PACK(b2, g2, r2, a, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1 + 8);
RGB32_STORE(rgb2_l, rgb2_h, image2 + 8);
DEALYUV2RGBREMAIN32
PUTRGB(image1, py_1);
PUTRGB(image2, py_2);
ENDRES32
END_FUNC()
YUV2RGBFUNC32(yuv420_argb32_lsx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h);
RGB32_PACK(a, r2, g2, b2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB32_PACK(a, r1, g1, b1, rgb1_l, rgb1_h);
RGB32_PACK(a, r2, g2, b2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1 + 8);
RGB32_STORE(rgb2_l, rgb2_h, image2 + 8);
DEALYUV2RGBREMAIN32
PUTRGB(image1, py_1);
PUTRGB(image2, py_2);
ENDRES32
END_FUNC()
YUV2RGBFUNC32(yuv420_abgr32_lsx, uint32_t, 0)
LOAD_YUV_16
YUV2RGB(m_y1, m_y2, m_u, m_v, r1, g1, b1, r2, g2, b2);
RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h);
RGB32_PACK(a, b2, g2, r2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1);
RGB32_STORE(rgb2_l, rgb2_h, image2);
YUV2RGB(m_y1_h, m_y2_h, m_u_h, m_v_h, r1, g1, b1, r2, g2, b2);
RGB32_PACK(a, b1, g1, r1, rgb1_l, rgb1_h);
RGB32_PACK(a, b2, g2, r2, rgb2_l, rgb2_h);
RGB32_STORE(rgb1_l, rgb1_h, image1 + 8);
RGB32_STORE(rgb2_l, rgb2_h, image2 + 8);
DEALYUV2RGBREMAIN32
PUTRGB(image1, py_1);
PUTRGB(image2, py_2);
ENDRES32
END_FUNC()