1 /*
2 * Copyright (c) 2022 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "./vpx_dsp_rtcd.h"
12 #include "vpx_util/loongson_intrinsics.h"
13
avg_width4_lsx(const uint8_t * src,int32_t src_stride,uint8_t * dst,int32_t dst_stride,int32_t height)14 static void avg_width4_lsx(const uint8_t *src, int32_t src_stride, uint8_t *dst,
15 int32_t dst_stride, int32_t height) {
16 int32_t cnt;
17 __m128i src0, src1;
18 __m128i dst0, dst1;
19
20 int32_t src_stride2 = src_stride << 1;
21
22 if ((height % 2) == 0) {
23 for (cnt = (height / 2); cnt--;) {
24 src0 = __lsx_vld(src, 0);
25 src1 = __lsx_vldx(src, src_stride);
26 src += src_stride2;
27
28 dst0 = __lsx_vld(dst, 0);
29 dst1 = __lsx_vldx(dst, dst_stride);
30 DUP2_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, dst0, dst1);
31
32 __lsx_vstelm_w(dst0, dst, 0, 0);
33 dst += dst_stride;
34 __lsx_vstelm_w(dst1, dst, 0, 0);
35 dst += dst_stride;
36 }
37 }
38 }
39
avg_width8_lsx(const uint8_t * src,int32_t src_stride,uint8_t * dst,int32_t dst_stride,int32_t height)40 static void avg_width8_lsx(const uint8_t *src, int32_t src_stride, uint8_t *dst,
41 int32_t dst_stride, int32_t height) {
42 int32_t cnt = (height / 4);
43 __m128i src0, src1, src2, src3;
44 __m128i dst0, dst1, dst2, dst3;
45
46 int32_t src_stride2 = src_stride << 1;
47 int32_t src_stride3 = src_stride2 + src_stride;
48 int32_t src_stride4 = src_stride2 << 1;
49
50 int32_t dst_stride2 = dst_stride << 1;
51 int32_t dst_stride3 = dst_stride2 + dst_stride;
52
53 for (; cnt--;) {
54 src0 = __lsx_vld(src, 0);
55 DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride2, src1, src2);
56 src3 = __lsx_vldx(src, src_stride3);
57 src += src_stride4;
58
59 dst0 = __lsx_vld(dst, 0);
60 DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, dst_stride2, dst1, dst2);
61 dst3 = __lsx_vldx(dst, dst_stride3);
62
63 DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, src2, dst2, src3, dst3,
64 dst0, dst1, dst2, dst3);
65
66 __lsx_vstelm_d(dst0, dst, 0, 0);
67 dst += dst_stride;
68 __lsx_vstelm_d(dst1, dst, 0, 0);
69 dst += dst_stride;
70 __lsx_vstelm_d(dst2, dst, 0, 0);
71 dst += dst_stride;
72 __lsx_vstelm_d(dst3, dst, 0, 0);
73 dst += dst_stride;
74 }
75 }
76
avg_width16_lsx(const uint8_t * src,int32_t src_stride,uint8_t * dst,int32_t dst_stride,int32_t height)77 static void avg_width16_lsx(const uint8_t *src, int32_t src_stride,
78 uint8_t *dst, int32_t dst_stride, int32_t height) {
79 int32_t cnt = (height / 8);
80 __m128i src0, src1, src2, src3, src4, src5, src6, src7;
81 __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7;
82
83 int32_t src_stride2 = src_stride << 1;
84 int32_t src_stride3 = src_stride2 + src_stride;
85 int32_t src_stride4 = src_stride2 << 1;
86
87 int32_t dst_stride2 = dst_stride << 1;
88 int32_t dst_stride3 = dst_stride2 + dst_stride;
89 int32_t dst_stride4 = dst_stride2 << 1;
90
91 for (; cnt--;) {
92 src0 = __lsx_vld(src, 0);
93 DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride2, src1, src2);
94 src3 = __lsx_vldx(src, src_stride3);
95 src += src_stride4;
96 src4 = __lsx_vld(src, 0);
97 DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride2, src5, src6);
98 src7 = __lsx_vldx(src, src_stride3);
99 src += src_stride4;
100
101 dst0 = __lsx_vld(dst, 0);
102 DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, dst_stride2, dst1, dst2);
103 dst3 = __lsx_vldx(dst, dst_stride3);
104 dst += dst_stride4;
105 dst4 = __lsx_vld(dst, 0);
106 DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, dst_stride2, dst5, dst6);
107 dst7 = __lsx_vldx(dst, dst_stride3);
108 dst -= dst_stride4;
109
110 DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, src2, dst2, src3, dst3,
111 dst0, dst1, dst2, dst3);
112 DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, src6, dst6, src7, dst7,
113 dst4, dst5, dst6, dst7);
114
115 __lsx_vst(dst0, dst, 0);
116 __lsx_vstx(dst1, dst, dst_stride);
117 __lsx_vstx(dst2, dst, dst_stride2);
118 __lsx_vstx(dst3, dst, dst_stride3);
119 dst += dst_stride4;
120 __lsx_vst(dst4, dst, 0);
121 __lsx_vstx(dst5, dst, dst_stride);
122 __lsx_vstx(dst6, dst, dst_stride2);
123 __lsx_vstx(dst7, dst, dst_stride3);
124 dst += dst_stride4;
125 }
126 }
127
avg_width32_lsx(const uint8_t * src,int32_t src_stride,uint8_t * dst,int32_t dst_stride,int32_t height)128 static void avg_width32_lsx(const uint8_t *src, int32_t src_stride,
129 uint8_t *dst, int32_t dst_stride, int32_t height) {
130 int32_t cnt = (height / 8);
131 __m128i src0, src1, src2, src3, src4, src5, src6, src7;
132 __m128i src8, src9, src10, src11, src12, src13, src14, src15;
133 __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7;
134 __m128i dst8, dst9, dst10, dst11, dst12, dst13, dst14, dst15;
135
136 int32_t src_stride2 = src_stride << 1;
137 int32_t src_stride3 = src_stride2 + src_stride;
138 int32_t src_stride4 = src_stride2 << 1;
139
140 int32_t dst_stride2 = dst_stride << 1;
141 int32_t dst_stride3 = dst_stride2 + dst_stride;
142 int32_t dst_stride4 = dst_stride2 << 1;
143
144 for (; cnt--;) {
145 uint8_t *dst_tmp = dst;
146 uint8_t *dst_tmp1 = dst_tmp + 16;
147 uint8_t *src_tmp = src + 16;
148
149 src0 = __lsx_vld(src, 0);
150 DUP2_ARG2(__lsx_vld, src, 0, src_tmp, 0, src0, src1);
151 DUP4_ARG2(__lsx_vldx, src, src_stride, src_tmp, src_stride, src,
152 src_stride2, src_tmp, src_stride2, src2, src3, src4, src5);
153 DUP2_ARG2(__lsx_vldx, src, src_stride3, src_tmp, src_stride3, src6, src7);
154 src += src_stride4;
155
156 DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp1, 0, dst0, dst1);
157 DUP4_ARG2(__lsx_vldx, dst_tmp, dst_stride, dst_tmp1, dst_stride, dst_tmp,
158 dst_stride2, dst_tmp1, dst_stride2, dst2, dst3, dst4, dst5);
159 DUP2_ARG2(__lsx_vldx, dst_tmp, dst_stride3, dst_tmp1, dst_stride3, dst6,
160 dst7);
161 dst_tmp += dst_stride4;
162 dst_tmp1 += dst_stride4;
163
164 src_tmp = src + 16;
165 DUP2_ARG2(__lsx_vld, src, 0, src_tmp, 0, src8, src9);
166 DUP4_ARG2(__lsx_vldx, src, src_stride, src_tmp, src_stride, src,
167 src_stride2, src_tmp, src_stride2, src10, src11, src12, src13);
168 DUP2_ARG2(__lsx_vldx, src, src_stride3, src_tmp, src_stride3, src14, src15);
169 src += src_stride4;
170
171 DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp1, 0, dst8, dst9);
172 DUP4_ARG2(__lsx_vldx, dst_tmp, dst_stride, dst_tmp1, dst_stride, dst_tmp,
173 dst_stride2, dst_tmp1, dst_stride2, dst10, dst11, dst12, dst13);
174 DUP2_ARG2(__lsx_vldx, dst_tmp, dst_stride3, dst_tmp1, dst_stride3, dst14,
175 dst15);
176 DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, src2, dst2, src3, dst3,
177 dst0, dst1, dst2, dst3);
178 DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, src6, dst6, src7, dst7,
179 dst4, dst5, dst6, dst7);
180 DUP4_ARG2(__lsx_vavgr_bu, src8, dst8, src9, dst9, src10, dst10, src11,
181 dst11, dst8, dst9, dst10, dst11);
182 DUP4_ARG2(__lsx_vavgr_bu, src12, dst12, src13, dst13, src14, dst14, src15,
183 dst15, dst12, dst13, dst14, dst15);
184
185 dst_tmp = dst + 16;
186 __lsx_vst(dst0, dst, 0);
187 __lsx_vstx(dst2, dst, dst_stride);
188 __lsx_vstx(dst4, dst, dst_stride2);
189 __lsx_vstx(dst6, dst, dst_stride3);
190 __lsx_vst(dst1, dst_tmp, 0);
191 __lsx_vstx(dst3, dst_tmp, dst_stride);
192 __lsx_vstx(dst5, dst_tmp, dst_stride2);
193 __lsx_vstx(dst7, dst_tmp, dst_stride3);
194 dst += dst_stride4;
195
196 __lsx_vst(dst8, dst, 0);
197 __lsx_vstx(dst10, dst, dst_stride);
198 __lsx_vstx(dst12, dst, dst_stride2);
199 __lsx_vstx(dst14, dst, dst_stride3);
200 __lsx_vst(dst9, dst_tmp1, 0);
201 __lsx_vstx(dst11, dst_tmp1, dst_stride);
202 __lsx_vstx(dst13, dst_tmp1, dst_stride2);
203 __lsx_vstx(dst15, dst_tmp1, dst_stride3);
204 dst += dst_stride4;
205 }
206 }
207
avg_width64_lsx(const uint8_t * src,int32_t src_stride,uint8_t * dst,int32_t dst_stride,int32_t height)208 static void avg_width64_lsx(const uint8_t *src, int32_t src_stride,
209 uint8_t *dst, int32_t dst_stride, int32_t height) {
210 int32_t cnt = (height / 4);
211 uint8_t *dst_tmp = dst;
212
213 __m128i src0, src1, src2, src3, src4, src5, src6, src7;
214 __m128i src8, src9, src10, src11, src12, src13, src14, src15;
215 __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7;
216 __m128i dst8, dst9, dst10, dst11, dst12, dst13, dst14, dst15;
217
218 for (; cnt--;) {
219 DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, src0, src1, src2,
220 src3);
221 src += src_stride;
222 DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, src4, src5, src6,
223 src7);
224 src += src_stride;
225 DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, src8, src9, src10,
226 src11);
227 src += src_stride;
228 DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, src12, src13, src14,
229 src15);
230 src += src_stride;
231
232 DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48,
233 dst0, dst1, dst2, dst3);
234 dst_tmp += dst_stride;
235 DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48,
236 dst4, dst5, dst6, dst7);
237 dst_tmp += dst_stride;
238 DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48,
239 dst8, dst9, dst10, dst11);
240 dst_tmp += dst_stride;
241 DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48,
242 dst12, dst13, dst14, dst15);
243 dst_tmp += dst_stride;
244
245 DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, src2, dst2, src3, dst3,
246 dst0, dst1, dst2, dst3);
247 DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, src6, dst6, src7, dst7,
248 dst4, dst5, dst6, dst7);
249 DUP4_ARG2(__lsx_vavgr_bu, src8, dst8, src9, dst9, src10, dst10, src11,
250 dst11, dst8, dst9, dst10, dst11);
251 DUP4_ARG2(__lsx_vavgr_bu, src12, dst12, src13, dst13, src14, dst14, src15,
252 dst15, dst12, dst13, dst14, dst15);
253
254 __lsx_vst(dst0, dst, 0);
255 __lsx_vst(dst1, dst, 16);
256 __lsx_vst(dst2, dst, 32);
257 __lsx_vst(dst3, dst, 48);
258 dst += dst_stride;
259 __lsx_vst(dst4, dst, 0);
260 __lsx_vst(dst5, dst, 16);
261 __lsx_vst(dst6, dst, 32);
262 __lsx_vst(dst7, dst, 48);
263 dst += dst_stride;
264 __lsx_vst(dst8, dst, 0);
265 __lsx_vst(dst9, dst, 16);
266 __lsx_vst(dst10, dst, 32);
267 __lsx_vst(dst11, dst, 48);
268 dst += dst_stride;
269 __lsx_vst(dst12, dst, 0);
270 __lsx_vst(dst13, dst, 16);
271 __lsx_vst(dst14, dst, 32);
272 __lsx_vst(dst15, dst, 48);
273 dst += dst_stride;
274 }
275 }
276
vpx_convolve_avg_lsx(const uint8_t * src,ptrdiff_t src_stride,uint8_t * dst,ptrdiff_t dst_stride,const InterpKernel * filter,int x0_q4,int32_t x_step_q4,int y0_q4,int32_t y_step_q4,int32_t w,int32_t h)277 void vpx_convolve_avg_lsx(const uint8_t *src, ptrdiff_t src_stride,
278 uint8_t *dst, ptrdiff_t dst_stride,
279 const InterpKernel *filter, int x0_q4,
280 int32_t x_step_q4, int y0_q4, int32_t y_step_q4,
281 int32_t w, int32_t h) {
282 (void)filter;
283 (void)x0_q4;
284 (void)x_step_q4;
285 (void)y0_q4;
286 (void)y_step_q4;
287 switch (w) {
288 case 4: {
289 avg_width4_lsx(src, src_stride, dst, dst_stride, h);
290 break;
291 }
292
293 case 8: {
294 avg_width8_lsx(src, src_stride, dst, dst_stride, h);
295 break;
296 }
297 case 16: {
298 avg_width16_lsx(src, src_stride, dst, dst_stride, h);
299 break;
300 }
301 case 32: {
302 avg_width32_lsx(src, src_stride, dst, dst_stride, h);
303 break;
304 }
305 case 64: {
306 avg_width64_lsx(src, src_stride, dst, dst_stride, h);
307 break;
308 }
309 default: {
310 int32_t lp, cnt;
311 for (cnt = h; cnt--;) {
312 for (lp = 0; lp < w; ++lp) {
313 dst[lp] = (((dst[lp] + src[lp]) + 1) >> 1);
314 }
315 src += src_stride;
316 dst += dst_stride;
317 }
318 break;
319 }
320 }
321 }
322