1 /*
2 * Copyright (c) 2014 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 <arm_neon.h>
12 #include <string.h>
13
14 #include "./vpx_config.h"
15 #include "./vp8_rtcd.h"
16 #include "vpx_dsp/arm/mem_neon.h"
17
18 static const uint8_t bifilter4_coeff[8][2] = { { 128, 0 }, { 112, 16 },
19 { 96, 32 }, { 80, 48 },
20 { 64, 64 }, { 48, 80 },
21 { 32, 96 }, { 16, 112 } };
22
load_and_shift(const unsigned char * a)23 static INLINE uint8x8_t load_and_shift(const unsigned char *a) {
24 return vreinterpret_u8_u64(vshl_n_u64(vreinterpret_u64_u8(vld1_u8(a)), 32));
25 }
26
vp8_bilinear_predict4x4_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)27 void vp8_bilinear_predict4x4_neon(unsigned char *src_ptr,
28 int src_pixels_per_line, int xoffset,
29 int yoffset, unsigned char *dst_ptr,
30 int dst_pitch) {
31 uint8x8_t e0, e1, e2;
32
33 if (xoffset == 0) { // skip_1stpass_filter
34 uint8x8_t a0, a1, a2, a3, a4;
35
36 a0 = load_and_shift(src_ptr);
37 src_ptr += src_pixels_per_line;
38 a1 = vld1_u8(src_ptr);
39 src_ptr += src_pixels_per_line;
40 a2 = load_and_shift(src_ptr);
41 src_ptr += src_pixels_per_line;
42 a3 = vld1_u8(src_ptr);
43 src_ptr += src_pixels_per_line;
44 a4 = vld1_u8(src_ptr);
45
46 e0 = vext_u8(a0, a1, 4);
47 e1 = vext_u8(a2, a3, 4);
48 e2 = a4;
49 } else {
50 uint8x8_t a0, a1, a2, a3, a4, b4;
51 uint8x16_t a01, a23;
52 uint8x16_t b01, b23;
53 uint32x2x2_t c0, c1, c2, c3;
54 uint16x8_t d0, d1, d2;
55 const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
56 const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
57
58 a0 = vld1_u8(src_ptr);
59 src_ptr += src_pixels_per_line;
60 a1 = vld1_u8(src_ptr);
61 src_ptr += src_pixels_per_line;
62 a2 = vld1_u8(src_ptr);
63 src_ptr += src_pixels_per_line;
64 a3 = vld1_u8(src_ptr);
65 src_ptr += src_pixels_per_line;
66 a4 = vld1_u8(src_ptr);
67
68 a01 = vcombine_u8(a0, a1);
69 a23 = vcombine_u8(a2, a3);
70
71 b01 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a01), 8));
72 b23 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a23), 8));
73 b4 = vreinterpret_u8_u64(vshr_n_u64(vreinterpret_u64_u8(a4), 8));
74
75 c0 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a01)),
76 vreinterpret_u32_u8(vget_high_u8(a01)));
77 c1 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a23)),
78 vreinterpret_u32_u8(vget_high_u8(a23)));
79 c2 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b01)),
80 vreinterpret_u32_u8(vget_high_u8(b01)));
81 c3 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b23)),
82 vreinterpret_u32_u8(vget_high_u8(b23)));
83
84 d0 = vmull_u8(vreinterpret_u8_u32(c0.val[0]), filter0);
85 d1 = vmull_u8(vreinterpret_u8_u32(c1.val[0]), filter0);
86 d2 = vmull_u8(a4, filter0);
87
88 d0 = vmlal_u8(d0, vreinterpret_u8_u32(c2.val[0]), filter1);
89 d1 = vmlal_u8(d1, vreinterpret_u8_u32(c3.val[0]), filter1);
90 d2 = vmlal_u8(d2, b4, filter1);
91
92 e0 = vqrshrn_n_u16(d0, 7);
93 e1 = vqrshrn_n_u16(d1, 7);
94 e2 = vqrshrn_n_u16(d2, 7);
95 }
96
97 // secondpass_filter
98 if (yoffset == 0) { // skip_2ndpass_filter
99 store_unaligned_u8q(dst_ptr, dst_pitch, vcombine_u8(e0, e1));
100 } else {
101 uint8x8_t f0, f1;
102 const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
103 const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
104
105 uint16x8_t b0 = vmull_u8(e0, filter0);
106 uint16x8_t b1 = vmull_u8(e1, filter0);
107
108 const uint8x8_t a0 = vext_u8(e0, e1, 4);
109 const uint8x8_t a1 = vext_u8(e1, e2, 4);
110
111 b0 = vmlal_u8(b0, a0, filter1);
112 b1 = vmlal_u8(b1, a1, filter1);
113
114 f0 = vqrshrn_n_u16(b0, 7);
115 f1 = vqrshrn_n_u16(b1, 7);
116
117 store_unaligned_u8q(dst_ptr, dst_pitch, vcombine_u8(f0, f1));
118 }
119 }
120
vp8_bilinear_predict8x4_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)121 void vp8_bilinear_predict8x4_neon(unsigned char *src_ptr,
122 int src_pixels_per_line, int xoffset,
123 int yoffset, unsigned char *dst_ptr,
124 int dst_pitch) {
125 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8;
126 uint8x8_t d7u8, d9u8, d11u8, d22u8, d23u8, d24u8, d25u8, d26u8;
127 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
128 uint16x8_t q1u16, q2u16, q3u16, q4u16;
129 uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
130
131 if (xoffset == 0) { // skip_1stpass_filter
132 d22u8 = vld1_u8(src_ptr);
133 src_ptr += src_pixels_per_line;
134 d23u8 = vld1_u8(src_ptr);
135 src_ptr += src_pixels_per_line;
136 d24u8 = vld1_u8(src_ptr);
137 src_ptr += src_pixels_per_line;
138 d25u8 = vld1_u8(src_ptr);
139 src_ptr += src_pixels_per_line;
140 d26u8 = vld1_u8(src_ptr);
141 } else {
142 q1u8 = vld1q_u8(src_ptr);
143 src_ptr += src_pixels_per_line;
144 q2u8 = vld1q_u8(src_ptr);
145 src_ptr += src_pixels_per_line;
146 q3u8 = vld1q_u8(src_ptr);
147 src_ptr += src_pixels_per_line;
148 q4u8 = vld1q_u8(src_ptr);
149 src_ptr += src_pixels_per_line;
150 q5u8 = vld1q_u8(src_ptr);
151
152 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
153 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
154
155 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
156 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
157 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
158 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
159 q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
160
161 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
162 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
163 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
164 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
165 d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
166
167 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
168 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
169 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
170 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
171 q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
172
173 d22u8 = vqrshrn_n_u16(q6u16, 7);
174 d23u8 = vqrshrn_n_u16(q7u16, 7);
175 d24u8 = vqrshrn_n_u16(q8u16, 7);
176 d25u8 = vqrshrn_n_u16(q9u16, 7);
177 d26u8 = vqrshrn_n_u16(q10u16, 7);
178 }
179
180 // secondpass_filter
181 if (yoffset == 0) { // skip_2ndpass_filter
182 vst1_u8((uint8_t *)dst_ptr, d22u8);
183 dst_ptr += dst_pitch;
184 vst1_u8((uint8_t *)dst_ptr, d23u8);
185 dst_ptr += dst_pitch;
186 vst1_u8((uint8_t *)dst_ptr, d24u8);
187 dst_ptr += dst_pitch;
188 vst1_u8((uint8_t *)dst_ptr, d25u8);
189 } else {
190 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
191 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
192
193 q1u16 = vmull_u8(d22u8, d0u8);
194 q2u16 = vmull_u8(d23u8, d0u8);
195 q3u16 = vmull_u8(d24u8, d0u8);
196 q4u16 = vmull_u8(d25u8, d0u8);
197
198 q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
199 q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
200 q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
201 q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
202
203 d2u8 = vqrshrn_n_u16(q1u16, 7);
204 d3u8 = vqrshrn_n_u16(q2u16, 7);
205 d4u8 = vqrshrn_n_u16(q3u16, 7);
206 d5u8 = vqrshrn_n_u16(q4u16, 7);
207
208 vst1_u8((uint8_t *)dst_ptr, d2u8);
209 dst_ptr += dst_pitch;
210 vst1_u8((uint8_t *)dst_ptr, d3u8);
211 dst_ptr += dst_pitch;
212 vst1_u8((uint8_t *)dst_ptr, d4u8);
213 dst_ptr += dst_pitch;
214 vst1_u8((uint8_t *)dst_ptr, d5u8);
215 }
216 return;
217 }
218
vp8_bilinear_predict8x8_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)219 void vp8_bilinear_predict8x8_neon(unsigned char *src_ptr,
220 int src_pixels_per_line, int xoffset,
221 int yoffset, unsigned char *dst_ptr,
222 int dst_pitch) {
223 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8, d11u8;
224 uint8x8_t d22u8, d23u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8, d30u8;
225 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
226 uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16;
227 uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
228
229 if (xoffset == 0) { // skip_1stpass_filter
230 d22u8 = vld1_u8(src_ptr);
231 src_ptr += src_pixels_per_line;
232 d23u8 = vld1_u8(src_ptr);
233 src_ptr += src_pixels_per_line;
234 d24u8 = vld1_u8(src_ptr);
235 src_ptr += src_pixels_per_line;
236 d25u8 = vld1_u8(src_ptr);
237 src_ptr += src_pixels_per_line;
238 d26u8 = vld1_u8(src_ptr);
239 src_ptr += src_pixels_per_line;
240 d27u8 = vld1_u8(src_ptr);
241 src_ptr += src_pixels_per_line;
242 d28u8 = vld1_u8(src_ptr);
243 src_ptr += src_pixels_per_line;
244 d29u8 = vld1_u8(src_ptr);
245 src_ptr += src_pixels_per_line;
246 d30u8 = vld1_u8(src_ptr);
247 } else {
248 q1u8 = vld1q_u8(src_ptr);
249 src_ptr += src_pixels_per_line;
250 q2u8 = vld1q_u8(src_ptr);
251 src_ptr += src_pixels_per_line;
252 q3u8 = vld1q_u8(src_ptr);
253 src_ptr += src_pixels_per_line;
254 q4u8 = vld1q_u8(src_ptr);
255 src_ptr += src_pixels_per_line;
256
257 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
258 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
259
260 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
261 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
262 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
263 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
264
265 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
266 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
267 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
268 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
269
270 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
271 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
272 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
273 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
274
275 d22u8 = vqrshrn_n_u16(q6u16, 7);
276 d23u8 = vqrshrn_n_u16(q7u16, 7);
277 d24u8 = vqrshrn_n_u16(q8u16, 7);
278 d25u8 = vqrshrn_n_u16(q9u16, 7);
279
280 // first_pass filtering on the rest 5-line data
281 q1u8 = vld1q_u8(src_ptr);
282 src_ptr += src_pixels_per_line;
283 q2u8 = vld1q_u8(src_ptr);
284 src_ptr += src_pixels_per_line;
285 q3u8 = vld1q_u8(src_ptr);
286 src_ptr += src_pixels_per_line;
287 q4u8 = vld1q_u8(src_ptr);
288 src_ptr += src_pixels_per_line;
289 q5u8 = vld1q_u8(src_ptr);
290
291 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
292 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
293 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
294 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
295 q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
296
297 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
298 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
299 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
300 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
301 d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
302
303 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
304 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
305 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
306 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
307 q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
308
309 d26u8 = vqrshrn_n_u16(q6u16, 7);
310 d27u8 = vqrshrn_n_u16(q7u16, 7);
311 d28u8 = vqrshrn_n_u16(q8u16, 7);
312 d29u8 = vqrshrn_n_u16(q9u16, 7);
313 d30u8 = vqrshrn_n_u16(q10u16, 7);
314 }
315
316 // secondpass_filter
317 if (yoffset == 0) { // skip_2ndpass_filter
318 vst1_u8((uint8_t *)dst_ptr, d22u8);
319 dst_ptr += dst_pitch;
320 vst1_u8((uint8_t *)dst_ptr, d23u8);
321 dst_ptr += dst_pitch;
322 vst1_u8((uint8_t *)dst_ptr, d24u8);
323 dst_ptr += dst_pitch;
324 vst1_u8((uint8_t *)dst_ptr, d25u8);
325 dst_ptr += dst_pitch;
326 vst1_u8((uint8_t *)dst_ptr, d26u8);
327 dst_ptr += dst_pitch;
328 vst1_u8((uint8_t *)dst_ptr, d27u8);
329 dst_ptr += dst_pitch;
330 vst1_u8((uint8_t *)dst_ptr, d28u8);
331 dst_ptr += dst_pitch;
332 vst1_u8((uint8_t *)dst_ptr, d29u8);
333 } else {
334 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
335 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
336
337 q1u16 = vmull_u8(d22u8, d0u8);
338 q2u16 = vmull_u8(d23u8, d0u8);
339 q3u16 = vmull_u8(d24u8, d0u8);
340 q4u16 = vmull_u8(d25u8, d0u8);
341 q5u16 = vmull_u8(d26u8, d0u8);
342 q6u16 = vmull_u8(d27u8, d0u8);
343 q7u16 = vmull_u8(d28u8, d0u8);
344 q8u16 = vmull_u8(d29u8, d0u8);
345
346 q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
347 q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
348 q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
349 q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
350 q5u16 = vmlal_u8(q5u16, d27u8, d1u8);
351 q6u16 = vmlal_u8(q6u16, d28u8, d1u8);
352 q7u16 = vmlal_u8(q7u16, d29u8, d1u8);
353 q8u16 = vmlal_u8(q8u16, d30u8, d1u8);
354
355 d2u8 = vqrshrn_n_u16(q1u16, 7);
356 d3u8 = vqrshrn_n_u16(q2u16, 7);
357 d4u8 = vqrshrn_n_u16(q3u16, 7);
358 d5u8 = vqrshrn_n_u16(q4u16, 7);
359 d6u8 = vqrshrn_n_u16(q5u16, 7);
360 d7u8 = vqrshrn_n_u16(q6u16, 7);
361 d8u8 = vqrshrn_n_u16(q7u16, 7);
362 d9u8 = vqrshrn_n_u16(q8u16, 7);
363
364 vst1_u8((uint8_t *)dst_ptr, d2u8);
365 dst_ptr += dst_pitch;
366 vst1_u8((uint8_t *)dst_ptr, d3u8);
367 dst_ptr += dst_pitch;
368 vst1_u8((uint8_t *)dst_ptr, d4u8);
369 dst_ptr += dst_pitch;
370 vst1_u8((uint8_t *)dst_ptr, d5u8);
371 dst_ptr += dst_pitch;
372 vst1_u8((uint8_t *)dst_ptr, d6u8);
373 dst_ptr += dst_pitch;
374 vst1_u8((uint8_t *)dst_ptr, d7u8);
375 dst_ptr += dst_pitch;
376 vst1_u8((uint8_t *)dst_ptr, d8u8);
377 dst_ptr += dst_pitch;
378 vst1_u8((uint8_t *)dst_ptr, d9u8);
379 }
380 return;
381 }
382
vp8_bilinear_predict16x16_neon(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)383 void vp8_bilinear_predict16x16_neon(unsigned char *src_ptr,
384 int src_pixels_per_line, int xoffset,
385 int yoffset, unsigned char *dst_ptr,
386 int dst_pitch) {
387 int i;
388 unsigned char tmp[272];
389 unsigned char *tmpp;
390 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8;
391 uint8x8_t d10u8, d11u8, d12u8, d13u8, d14u8, d15u8, d16u8, d17u8, d18u8;
392 uint8x8_t d19u8, d20u8, d21u8;
393 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
394 uint8x16_t q11u8, q12u8, q13u8, q14u8, q15u8;
395 uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16, q6u16, q7u16, q8u16;
396 uint16x8_t q9u16, q10u16, q11u16, q12u16, q13u16, q14u16;
397
398 if (xoffset == 0) { // secondpass_bfilter16x16_only
399 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
400 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
401
402 q11u8 = vld1q_u8(src_ptr);
403 src_ptr += src_pixels_per_line;
404 for (i = 4; i > 0; i--) {
405 q12u8 = vld1q_u8(src_ptr);
406 src_ptr += src_pixels_per_line;
407 q13u8 = vld1q_u8(src_ptr);
408 src_ptr += src_pixels_per_line;
409 q14u8 = vld1q_u8(src_ptr);
410 src_ptr += src_pixels_per_line;
411 q15u8 = vld1q_u8(src_ptr);
412 src_ptr += src_pixels_per_line;
413
414 q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
415 q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
416 q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
417 q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
418 q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
419 q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
420 q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
421 q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
422
423 q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
424 q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
425 q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
426 q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
427 q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
428 q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
429 q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
430 q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
431
432 d2u8 = vqrshrn_n_u16(q1u16, 7);
433 d3u8 = vqrshrn_n_u16(q2u16, 7);
434 d4u8 = vqrshrn_n_u16(q3u16, 7);
435 d5u8 = vqrshrn_n_u16(q4u16, 7);
436 d6u8 = vqrshrn_n_u16(q5u16, 7);
437 d7u8 = vqrshrn_n_u16(q6u16, 7);
438 d8u8 = vqrshrn_n_u16(q7u16, 7);
439 d9u8 = vqrshrn_n_u16(q8u16, 7);
440
441 q1u8 = vcombine_u8(d2u8, d3u8);
442 q2u8 = vcombine_u8(d4u8, d5u8);
443 q3u8 = vcombine_u8(d6u8, d7u8);
444 q4u8 = vcombine_u8(d8u8, d9u8);
445
446 q11u8 = q15u8;
447
448 vst1q_u8((uint8_t *)dst_ptr, q1u8);
449 dst_ptr += dst_pitch;
450 vst1q_u8((uint8_t *)dst_ptr, q2u8);
451 dst_ptr += dst_pitch;
452 vst1q_u8((uint8_t *)dst_ptr, q3u8);
453 dst_ptr += dst_pitch;
454 vst1q_u8((uint8_t *)dst_ptr, q4u8);
455 dst_ptr += dst_pitch;
456 }
457 return;
458 }
459
460 if (yoffset == 0) { // firstpass_bfilter16x16_only
461 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
462 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
463
464 for (i = 4; i > 0; i--) {
465 d2u8 = vld1_u8(src_ptr);
466 d3u8 = vld1_u8(src_ptr + 8);
467 d4u8 = vld1_u8(src_ptr + 16);
468 src_ptr += src_pixels_per_line;
469 d5u8 = vld1_u8(src_ptr);
470 d6u8 = vld1_u8(src_ptr + 8);
471 d7u8 = vld1_u8(src_ptr + 16);
472 src_ptr += src_pixels_per_line;
473 d8u8 = vld1_u8(src_ptr);
474 d9u8 = vld1_u8(src_ptr + 8);
475 d10u8 = vld1_u8(src_ptr + 16);
476 src_ptr += src_pixels_per_line;
477 d11u8 = vld1_u8(src_ptr);
478 d12u8 = vld1_u8(src_ptr + 8);
479 d13u8 = vld1_u8(src_ptr + 16);
480 src_ptr += src_pixels_per_line;
481
482 q7u16 = vmull_u8(d2u8, d0u8);
483 q8u16 = vmull_u8(d3u8, d0u8);
484 q9u16 = vmull_u8(d5u8, d0u8);
485 q10u16 = vmull_u8(d6u8, d0u8);
486 q11u16 = vmull_u8(d8u8, d0u8);
487 q12u16 = vmull_u8(d9u8, d0u8);
488 q13u16 = vmull_u8(d11u8, d0u8);
489 q14u16 = vmull_u8(d12u8, d0u8);
490
491 d2u8 = vext_u8(d2u8, d3u8, 1);
492 d5u8 = vext_u8(d5u8, d6u8, 1);
493 d8u8 = vext_u8(d8u8, d9u8, 1);
494 d11u8 = vext_u8(d11u8, d12u8, 1);
495
496 q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
497 q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
498 q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
499 q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
500
501 d3u8 = vext_u8(d3u8, d4u8, 1);
502 d6u8 = vext_u8(d6u8, d7u8, 1);
503 d9u8 = vext_u8(d9u8, d10u8, 1);
504 d12u8 = vext_u8(d12u8, d13u8, 1);
505
506 q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
507 q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
508 q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
509 q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
510
511 d14u8 = vqrshrn_n_u16(q7u16, 7);
512 d15u8 = vqrshrn_n_u16(q8u16, 7);
513 d16u8 = vqrshrn_n_u16(q9u16, 7);
514 d17u8 = vqrshrn_n_u16(q10u16, 7);
515 d18u8 = vqrshrn_n_u16(q11u16, 7);
516 d19u8 = vqrshrn_n_u16(q12u16, 7);
517 d20u8 = vqrshrn_n_u16(q13u16, 7);
518 d21u8 = vqrshrn_n_u16(q14u16, 7);
519
520 q7u8 = vcombine_u8(d14u8, d15u8);
521 q8u8 = vcombine_u8(d16u8, d17u8);
522 q9u8 = vcombine_u8(d18u8, d19u8);
523 q10u8 = vcombine_u8(d20u8, d21u8);
524
525 vst1q_u8((uint8_t *)dst_ptr, q7u8);
526 dst_ptr += dst_pitch;
527 vst1q_u8((uint8_t *)dst_ptr, q8u8);
528 dst_ptr += dst_pitch;
529 vst1q_u8((uint8_t *)dst_ptr, q9u8);
530 dst_ptr += dst_pitch;
531 vst1q_u8((uint8_t *)dst_ptr, q10u8);
532 dst_ptr += dst_pitch;
533 }
534 return;
535 }
536
537 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
538 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
539
540 d2u8 = vld1_u8(src_ptr);
541 d3u8 = vld1_u8(src_ptr + 8);
542 d4u8 = vld1_u8(src_ptr + 16);
543 src_ptr += src_pixels_per_line;
544 d5u8 = vld1_u8(src_ptr);
545 d6u8 = vld1_u8(src_ptr + 8);
546 d7u8 = vld1_u8(src_ptr + 16);
547 src_ptr += src_pixels_per_line;
548 d8u8 = vld1_u8(src_ptr);
549 d9u8 = vld1_u8(src_ptr + 8);
550 d10u8 = vld1_u8(src_ptr + 16);
551 src_ptr += src_pixels_per_line;
552 d11u8 = vld1_u8(src_ptr);
553 d12u8 = vld1_u8(src_ptr + 8);
554 d13u8 = vld1_u8(src_ptr + 16);
555 src_ptr += src_pixels_per_line;
556
557 // First Pass: output_height lines x output_width columns (17x16)
558 tmpp = tmp;
559 for (i = 3; i > 0; i--) {
560 q7u16 = vmull_u8(d2u8, d0u8);
561 q8u16 = vmull_u8(d3u8, d0u8);
562 q9u16 = vmull_u8(d5u8, d0u8);
563 q10u16 = vmull_u8(d6u8, d0u8);
564 q11u16 = vmull_u8(d8u8, d0u8);
565 q12u16 = vmull_u8(d9u8, d0u8);
566 q13u16 = vmull_u8(d11u8, d0u8);
567 q14u16 = vmull_u8(d12u8, d0u8);
568
569 d2u8 = vext_u8(d2u8, d3u8, 1);
570 d5u8 = vext_u8(d5u8, d6u8, 1);
571 d8u8 = vext_u8(d8u8, d9u8, 1);
572 d11u8 = vext_u8(d11u8, d12u8, 1);
573
574 q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
575 q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
576 q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
577 q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
578
579 d3u8 = vext_u8(d3u8, d4u8, 1);
580 d6u8 = vext_u8(d6u8, d7u8, 1);
581 d9u8 = vext_u8(d9u8, d10u8, 1);
582 d12u8 = vext_u8(d12u8, d13u8, 1);
583
584 q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
585 q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
586 q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
587 q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
588
589 d14u8 = vqrshrn_n_u16(q7u16, 7);
590 d15u8 = vqrshrn_n_u16(q8u16, 7);
591 d16u8 = vqrshrn_n_u16(q9u16, 7);
592 d17u8 = vqrshrn_n_u16(q10u16, 7);
593 d18u8 = vqrshrn_n_u16(q11u16, 7);
594 d19u8 = vqrshrn_n_u16(q12u16, 7);
595 d20u8 = vqrshrn_n_u16(q13u16, 7);
596 d21u8 = vqrshrn_n_u16(q14u16, 7);
597
598 d2u8 = vld1_u8(src_ptr);
599 d3u8 = vld1_u8(src_ptr + 8);
600 d4u8 = vld1_u8(src_ptr + 16);
601 src_ptr += src_pixels_per_line;
602 d5u8 = vld1_u8(src_ptr);
603 d6u8 = vld1_u8(src_ptr + 8);
604 d7u8 = vld1_u8(src_ptr + 16);
605 src_ptr += src_pixels_per_line;
606 d8u8 = vld1_u8(src_ptr);
607 d9u8 = vld1_u8(src_ptr + 8);
608 d10u8 = vld1_u8(src_ptr + 16);
609 src_ptr += src_pixels_per_line;
610 d11u8 = vld1_u8(src_ptr);
611 d12u8 = vld1_u8(src_ptr + 8);
612 d13u8 = vld1_u8(src_ptr + 16);
613 src_ptr += src_pixels_per_line;
614
615 q7u8 = vcombine_u8(d14u8, d15u8);
616 q8u8 = vcombine_u8(d16u8, d17u8);
617 q9u8 = vcombine_u8(d18u8, d19u8);
618 q10u8 = vcombine_u8(d20u8, d21u8);
619
620 vst1q_u8((uint8_t *)tmpp, q7u8);
621 tmpp += 16;
622 vst1q_u8((uint8_t *)tmpp, q8u8);
623 tmpp += 16;
624 vst1q_u8((uint8_t *)tmpp, q9u8);
625 tmpp += 16;
626 vst1q_u8((uint8_t *)tmpp, q10u8);
627 tmpp += 16;
628 }
629
630 // First-pass filtering for rest 5 lines
631 d14u8 = vld1_u8(src_ptr);
632 d15u8 = vld1_u8(src_ptr + 8);
633 d16u8 = vld1_u8(src_ptr + 16);
634 src_ptr += src_pixels_per_line;
635
636 q9u16 = vmull_u8(d2u8, d0u8);
637 q10u16 = vmull_u8(d3u8, d0u8);
638 q11u16 = vmull_u8(d5u8, d0u8);
639 q12u16 = vmull_u8(d6u8, d0u8);
640 q13u16 = vmull_u8(d8u8, d0u8);
641 q14u16 = vmull_u8(d9u8, d0u8);
642
643 d2u8 = vext_u8(d2u8, d3u8, 1);
644 d5u8 = vext_u8(d5u8, d6u8, 1);
645 d8u8 = vext_u8(d8u8, d9u8, 1);
646
647 q9u16 = vmlal_u8(q9u16, d2u8, d1u8);
648 q11u16 = vmlal_u8(q11u16, d5u8, d1u8);
649 q13u16 = vmlal_u8(q13u16, d8u8, d1u8);
650
651 d3u8 = vext_u8(d3u8, d4u8, 1);
652 d6u8 = vext_u8(d6u8, d7u8, 1);
653 d9u8 = vext_u8(d9u8, d10u8, 1);
654
655 q10u16 = vmlal_u8(q10u16, d3u8, d1u8);
656 q12u16 = vmlal_u8(q12u16, d6u8, d1u8);
657 q14u16 = vmlal_u8(q14u16, d9u8, d1u8);
658
659 q1u16 = vmull_u8(d11u8, d0u8);
660 q2u16 = vmull_u8(d12u8, d0u8);
661 q3u16 = vmull_u8(d14u8, d0u8);
662 q4u16 = vmull_u8(d15u8, d0u8);
663
664 d11u8 = vext_u8(d11u8, d12u8, 1);
665 d14u8 = vext_u8(d14u8, d15u8, 1);
666
667 q1u16 = vmlal_u8(q1u16, d11u8, d1u8);
668 q3u16 = vmlal_u8(q3u16, d14u8, d1u8);
669
670 d12u8 = vext_u8(d12u8, d13u8, 1);
671 d15u8 = vext_u8(d15u8, d16u8, 1);
672
673 q2u16 = vmlal_u8(q2u16, d12u8, d1u8);
674 q4u16 = vmlal_u8(q4u16, d15u8, d1u8);
675
676 d10u8 = vqrshrn_n_u16(q9u16, 7);
677 d11u8 = vqrshrn_n_u16(q10u16, 7);
678 d12u8 = vqrshrn_n_u16(q11u16, 7);
679 d13u8 = vqrshrn_n_u16(q12u16, 7);
680 d14u8 = vqrshrn_n_u16(q13u16, 7);
681 d15u8 = vqrshrn_n_u16(q14u16, 7);
682 d16u8 = vqrshrn_n_u16(q1u16, 7);
683 d17u8 = vqrshrn_n_u16(q2u16, 7);
684 d18u8 = vqrshrn_n_u16(q3u16, 7);
685 d19u8 = vqrshrn_n_u16(q4u16, 7);
686
687 q5u8 = vcombine_u8(d10u8, d11u8);
688 q6u8 = vcombine_u8(d12u8, d13u8);
689 q7u8 = vcombine_u8(d14u8, d15u8);
690 q8u8 = vcombine_u8(d16u8, d17u8);
691 q9u8 = vcombine_u8(d18u8, d19u8);
692
693 vst1q_u8((uint8_t *)tmpp, q5u8);
694 tmpp += 16;
695 vst1q_u8((uint8_t *)tmpp, q6u8);
696 tmpp += 16;
697 vst1q_u8((uint8_t *)tmpp, q7u8);
698 tmpp += 16;
699 vst1q_u8((uint8_t *)tmpp, q8u8);
700 tmpp += 16;
701 vst1q_u8((uint8_t *)tmpp, q9u8);
702
703 // secondpass_filter
704 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
705 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
706
707 tmpp = tmp;
708 q11u8 = vld1q_u8(tmpp);
709 tmpp += 16;
710 for (i = 4; i > 0; i--) {
711 q12u8 = vld1q_u8(tmpp);
712 tmpp += 16;
713 q13u8 = vld1q_u8(tmpp);
714 tmpp += 16;
715 q14u8 = vld1q_u8(tmpp);
716 tmpp += 16;
717 q15u8 = vld1q_u8(tmpp);
718 tmpp += 16;
719
720 q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
721 q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
722 q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
723 q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
724 q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
725 q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
726 q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
727 q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
728
729 q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
730 q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
731 q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
732 q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
733 q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
734 q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
735 q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
736 q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
737
738 d2u8 = vqrshrn_n_u16(q1u16, 7);
739 d3u8 = vqrshrn_n_u16(q2u16, 7);
740 d4u8 = vqrshrn_n_u16(q3u16, 7);
741 d5u8 = vqrshrn_n_u16(q4u16, 7);
742 d6u8 = vqrshrn_n_u16(q5u16, 7);
743 d7u8 = vqrshrn_n_u16(q6u16, 7);
744 d8u8 = vqrshrn_n_u16(q7u16, 7);
745 d9u8 = vqrshrn_n_u16(q8u16, 7);
746
747 q1u8 = vcombine_u8(d2u8, d3u8);
748 q2u8 = vcombine_u8(d4u8, d5u8);
749 q3u8 = vcombine_u8(d6u8, d7u8);
750 q4u8 = vcombine_u8(d8u8, d9u8);
751
752 q11u8 = q15u8;
753
754 vst1q_u8((uint8_t *)dst_ptr, q1u8);
755 dst_ptr += dst_pitch;
756 vst1q_u8((uint8_t *)dst_ptr, q2u8);
757 dst_ptr += dst_pitch;
758 vst1q_u8((uint8_t *)dst_ptr, q3u8);
759 dst_ptr += dst_pitch;
760 vst1q_u8((uint8_t *)dst_ptr, q4u8);
761 dst_ptr += dst_pitch;
762 }
763 return;
764 }
765