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