2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
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.
13 #include "./vpx_config.h"
15 static const uint8_t bifilter4_coeff[8][2] = { { 128, 0 }, { 112, 16 },
16 { 96, 32 }, { 80, 48 },
17 { 64, 64 }, { 48, 80 },
18 { 32, 96 }, { 16, 112 } };
20 static INLINE uint8x8_t load_and_shift(const unsigned char *a) {
21 return vreinterpret_u8_u64(vshl_n_u64(vreinterpret_u64_u8(vld1_u8(a)), 32));
24 static INLINE void store4x4(unsigned char *dst, int dst_stride,
25 const uint8x8_t a0, const uint8x8_t a1) {
26 if (!((uintptr_t)dst & 0x3) && !(dst_stride & 0x3)) {
27 vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a0), 0);
29 vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a0), 1);
31 vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a1), 0);
33 vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a1), 1);
35 // Store to the aligned local buffer and memcpy instead of vget_lane_u8
36 // which is really really slow.
37 uint32_t output_buffer[4];
38 vst1_lane_u32(output_buffer, vreinterpret_u32_u8(a0), 0);
39 vst1_lane_u32(output_buffer + 1, vreinterpret_u32_u8(a0), 1);
40 vst1_lane_u32(output_buffer + 2, vreinterpret_u32_u8(a1), 0);
41 vst1_lane_u32(output_buffer + 3, vreinterpret_u32_u8(a1), 1);
43 memcpy(dst, output_buffer, 4);
45 memcpy(dst, output_buffer + 1, 4);
47 memcpy(dst, output_buffer + 2, 4);
49 memcpy(dst, output_buffer + 3, 4);
53 void vp8_bilinear_predict4x4_neon(unsigned char *src_ptr,
54 int src_pixels_per_line, int xoffset,
55 int yoffset, unsigned char *dst_ptr,
59 if (xoffset == 0) { // skip_1stpass_filter
60 uint8x8_t a0, a1, a2, a3, a4;
62 a0 = load_and_shift(src_ptr);
63 src_ptr += src_pixels_per_line;
64 a1 = vld1_u8(src_ptr);
65 src_ptr += src_pixels_per_line;
66 a2 = load_and_shift(src_ptr);
67 src_ptr += src_pixels_per_line;
68 a3 = vld1_u8(src_ptr);
69 src_ptr += src_pixels_per_line;
70 a4 = vld1_u8(src_ptr);
72 e0 = vext_u8(a0, a1, 4);
73 e1 = vext_u8(a2, a3, 4);
76 uint8x8_t a0, a1, a2, a3, a4, b4;
79 uint32x2x2_t c0, c1, c2, c3;
80 uint16x8_t d0, d1, d2;
81 const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
82 const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
84 a0 = vld1_u8(src_ptr);
85 src_ptr += src_pixels_per_line;
86 a1 = vld1_u8(src_ptr);
87 src_ptr += src_pixels_per_line;
88 a2 = vld1_u8(src_ptr);
89 src_ptr += src_pixels_per_line;
90 a3 = vld1_u8(src_ptr);
91 src_ptr += src_pixels_per_line;
92 a4 = vld1_u8(src_ptr);
94 a01 = vcombine_u8(a0, a1);
95 a23 = vcombine_u8(a2, a3);
97 b01 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a01), 8));
98 b23 = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(a23), 8));
99 b4 = vreinterpret_u8_u64(vshr_n_u64(vreinterpret_u64_u8(a4), 8));
101 c0 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a01)),
102 vreinterpret_u32_u8(vget_high_u8(a01)));
103 c1 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(a23)),
104 vreinterpret_u32_u8(vget_high_u8(a23)));
105 c2 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b01)),
106 vreinterpret_u32_u8(vget_high_u8(b01)));
107 c3 = vzip_u32(vreinterpret_u32_u8(vget_low_u8(b23)),
108 vreinterpret_u32_u8(vget_high_u8(b23)));
110 d0 = vmull_u8(vreinterpret_u8_u32(c0.val[0]), filter0);
111 d1 = vmull_u8(vreinterpret_u8_u32(c1.val[0]), filter0);
112 d2 = vmull_u8(a4, filter0);
114 d0 = vmlal_u8(d0, vreinterpret_u8_u32(c2.val[0]), filter1);
115 d1 = vmlal_u8(d1, vreinterpret_u8_u32(c3.val[0]), filter1);
116 d2 = vmlal_u8(d2, b4, filter1);
118 e0 = vqrshrn_n_u16(d0, 7);
119 e1 = vqrshrn_n_u16(d1, 7);
120 e2 = vqrshrn_n_u16(d2, 7);
124 if (yoffset == 0) { // skip_2ndpass_filter
125 store4x4(dst_ptr, dst_pitch, e0, e1);
128 const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
129 const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
131 uint16x8_t b0 = vmull_u8(e0, filter0);
132 uint16x8_t b1 = vmull_u8(e1, filter0);
134 const uint8x8_t a0 = vext_u8(e0, e1, 4);
135 const uint8x8_t a1 = vext_u8(e1, e2, 4);
137 b0 = vmlal_u8(b0, a0, filter1);
138 b1 = vmlal_u8(b1, a1, filter1);
140 f0 = vqrshrn_n_u16(b0, 7);
141 f1 = vqrshrn_n_u16(b1, 7);
143 store4x4(dst_ptr, dst_pitch, f0, f1);
147 void vp8_bilinear_predict8x4_neon(unsigned char *src_ptr,
148 int src_pixels_per_line, int xoffset,
149 int yoffset, unsigned char *dst_ptr,
151 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8;
152 uint8x8_t d7u8, d9u8, d11u8, d22u8, d23u8, d24u8, d25u8, d26u8;
153 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
154 uint16x8_t q1u16, q2u16, q3u16, q4u16;
155 uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
157 if (xoffset == 0) { // skip_1stpass_filter
158 d22u8 = vld1_u8(src_ptr);
159 src_ptr += src_pixels_per_line;
160 d23u8 = vld1_u8(src_ptr);
161 src_ptr += src_pixels_per_line;
162 d24u8 = vld1_u8(src_ptr);
163 src_ptr += src_pixels_per_line;
164 d25u8 = vld1_u8(src_ptr);
165 src_ptr += src_pixels_per_line;
166 d26u8 = vld1_u8(src_ptr);
168 q1u8 = vld1q_u8(src_ptr);
169 src_ptr += src_pixels_per_line;
170 q2u8 = vld1q_u8(src_ptr);
171 src_ptr += src_pixels_per_line;
172 q3u8 = vld1q_u8(src_ptr);
173 src_ptr += src_pixels_per_line;
174 q4u8 = vld1q_u8(src_ptr);
175 src_ptr += src_pixels_per_line;
176 q5u8 = vld1q_u8(src_ptr);
178 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
179 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
181 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
182 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
183 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
184 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
185 q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
187 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
188 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
189 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
190 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
191 d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
193 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
194 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
195 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
196 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
197 q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
199 d22u8 = vqrshrn_n_u16(q6u16, 7);
200 d23u8 = vqrshrn_n_u16(q7u16, 7);
201 d24u8 = vqrshrn_n_u16(q8u16, 7);
202 d25u8 = vqrshrn_n_u16(q9u16, 7);
203 d26u8 = vqrshrn_n_u16(q10u16, 7);
207 if (yoffset == 0) { // skip_2ndpass_filter
208 vst1_u8((uint8_t *)dst_ptr, d22u8);
209 dst_ptr += dst_pitch;
210 vst1_u8((uint8_t *)dst_ptr, d23u8);
211 dst_ptr += dst_pitch;
212 vst1_u8((uint8_t *)dst_ptr, d24u8);
213 dst_ptr += dst_pitch;
214 vst1_u8((uint8_t *)dst_ptr, d25u8);
216 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
217 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
219 q1u16 = vmull_u8(d22u8, d0u8);
220 q2u16 = vmull_u8(d23u8, d0u8);
221 q3u16 = vmull_u8(d24u8, d0u8);
222 q4u16 = vmull_u8(d25u8, d0u8);
224 q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
225 q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
226 q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
227 q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
229 d2u8 = vqrshrn_n_u16(q1u16, 7);
230 d3u8 = vqrshrn_n_u16(q2u16, 7);
231 d4u8 = vqrshrn_n_u16(q3u16, 7);
232 d5u8 = vqrshrn_n_u16(q4u16, 7);
234 vst1_u8((uint8_t *)dst_ptr, d2u8);
235 dst_ptr += dst_pitch;
236 vst1_u8((uint8_t *)dst_ptr, d3u8);
237 dst_ptr += dst_pitch;
238 vst1_u8((uint8_t *)dst_ptr, d4u8);
239 dst_ptr += dst_pitch;
240 vst1_u8((uint8_t *)dst_ptr, d5u8);
245 void vp8_bilinear_predict8x8_neon(unsigned char *src_ptr,
246 int src_pixels_per_line, int xoffset,
247 int yoffset, unsigned char *dst_ptr,
249 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8, d11u8;
250 uint8x8_t d22u8, d23u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8, d30u8;
251 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
252 uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16;
253 uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
255 if (xoffset == 0) { // skip_1stpass_filter
256 d22u8 = vld1_u8(src_ptr);
257 src_ptr += src_pixels_per_line;
258 d23u8 = vld1_u8(src_ptr);
259 src_ptr += src_pixels_per_line;
260 d24u8 = vld1_u8(src_ptr);
261 src_ptr += src_pixels_per_line;
262 d25u8 = vld1_u8(src_ptr);
263 src_ptr += src_pixels_per_line;
264 d26u8 = vld1_u8(src_ptr);
265 src_ptr += src_pixels_per_line;
266 d27u8 = vld1_u8(src_ptr);
267 src_ptr += src_pixels_per_line;
268 d28u8 = vld1_u8(src_ptr);
269 src_ptr += src_pixels_per_line;
270 d29u8 = vld1_u8(src_ptr);
271 src_ptr += src_pixels_per_line;
272 d30u8 = vld1_u8(src_ptr);
274 q1u8 = vld1q_u8(src_ptr);
275 src_ptr += src_pixels_per_line;
276 q2u8 = vld1q_u8(src_ptr);
277 src_ptr += src_pixels_per_line;
278 q3u8 = vld1q_u8(src_ptr);
279 src_ptr += src_pixels_per_line;
280 q4u8 = vld1q_u8(src_ptr);
281 src_ptr += src_pixels_per_line;
283 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
284 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
286 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
287 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
288 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
289 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
291 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
292 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
293 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
294 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
296 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
297 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
298 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
299 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
301 d22u8 = vqrshrn_n_u16(q6u16, 7);
302 d23u8 = vqrshrn_n_u16(q7u16, 7);
303 d24u8 = vqrshrn_n_u16(q8u16, 7);
304 d25u8 = vqrshrn_n_u16(q9u16, 7);
306 // first_pass filtering on the rest 5-line data
307 q1u8 = vld1q_u8(src_ptr);
308 src_ptr += src_pixels_per_line;
309 q2u8 = vld1q_u8(src_ptr);
310 src_ptr += src_pixels_per_line;
311 q3u8 = vld1q_u8(src_ptr);
312 src_ptr += src_pixels_per_line;
313 q4u8 = vld1q_u8(src_ptr);
314 src_ptr += src_pixels_per_line;
315 q5u8 = vld1q_u8(src_ptr);
317 q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
318 q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
319 q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
320 q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
321 q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
323 d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
324 d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
325 d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
326 d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
327 d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
329 q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
330 q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
331 q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
332 q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
333 q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
335 d26u8 = vqrshrn_n_u16(q6u16, 7);
336 d27u8 = vqrshrn_n_u16(q7u16, 7);
337 d28u8 = vqrshrn_n_u16(q8u16, 7);
338 d29u8 = vqrshrn_n_u16(q9u16, 7);
339 d30u8 = vqrshrn_n_u16(q10u16, 7);
343 if (yoffset == 0) { // skip_2ndpass_filter
344 vst1_u8((uint8_t *)dst_ptr, d22u8);
345 dst_ptr += dst_pitch;
346 vst1_u8((uint8_t *)dst_ptr, d23u8);
347 dst_ptr += dst_pitch;
348 vst1_u8((uint8_t *)dst_ptr, d24u8);
349 dst_ptr += dst_pitch;
350 vst1_u8((uint8_t *)dst_ptr, d25u8);
351 dst_ptr += dst_pitch;
352 vst1_u8((uint8_t *)dst_ptr, d26u8);
353 dst_ptr += dst_pitch;
354 vst1_u8((uint8_t *)dst_ptr, d27u8);
355 dst_ptr += dst_pitch;
356 vst1_u8((uint8_t *)dst_ptr, d28u8);
357 dst_ptr += dst_pitch;
358 vst1_u8((uint8_t *)dst_ptr, d29u8);
360 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
361 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
363 q1u16 = vmull_u8(d22u8, d0u8);
364 q2u16 = vmull_u8(d23u8, d0u8);
365 q3u16 = vmull_u8(d24u8, d0u8);
366 q4u16 = vmull_u8(d25u8, d0u8);
367 q5u16 = vmull_u8(d26u8, d0u8);
368 q6u16 = vmull_u8(d27u8, d0u8);
369 q7u16 = vmull_u8(d28u8, d0u8);
370 q8u16 = vmull_u8(d29u8, d0u8);
372 q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
373 q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
374 q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
375 q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
376 q5u16 = vmlal_u8(q5u16, d27u8, d1u8);
377 q6u16 = vmlal_u8(q6u16, d28u8, d1u8);
378 q7u16 = vmlal_u8(q7u16, d29u8, d1u8);
379 q8u16 = vmlal_u8(q8u16, d30u8, d1u8);
381 d2u8 = vqrshrn_n_u16(q1u16, 7);
382 d3u8 = vqrshrn_n_u16(q2u16, 7);
383 d4u8 = vqrshrn_n_u16(q3u16, 7);
384 d5u8 = vqrshrn_n_u16(q4u16, 7);
385 d6u8 = vqrshrn_n_u16(q5u16, 7);
386 d7u8 = vqrshrn_n_u16(q6u16, 7);
387 d8u8 = vqrshrn_n_u16(q7u16, 7);
388 d9u8 = vqrshrn_n_u16(q8u16, 7);
390 vst1_u8((uint8_t *)dst_ptr, d2u8);
391 dst_ptr += dst_pitch;
392 vst1_u8((uint8_t *)dst_ptr, d3u8);
393 dst_ptr += dst_pitch;
394 vst1_u8((uint8_t *)dst_ptr, d4u8);
395 dst_ptr += dst_pitch;
396 vst1_u8((uint8_t *)dst_ptr, d5u8);
397 dst_ptr += dst_pitch;
398 vst1_u8((uint8_t *)dst_ptr, d6u8);
399 dst_ptr += dst_pitch;
400 vst1_u8((uint8_t *)dst_ptr, d7u8);
401 dst_ptr += dst_pitch;
402 vst1_u8((uint8_t *)dst_ptr, d8u8);
403 dst_ptr += dst_pitch;
404 vst1_u8((uint8_t *)dst_ptr, d9u8);
409 void vp8_bilinear_predict16x16_neon(unsigned char *src_ptr,
410 int src_pixels_per_line, int xoffset,
411 int yoffset, unsigned char *dst_ptr,
414 unsigned char tmp[272];
416 uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8;
417 uint8x8_t d10u8, d11u8, d12u8, d13u8, d14u8, d15u8, d16u8, d17u8, d18u8;
418 uint8x8_t d19u8, d20u8, d21u8;
419 uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
420 uint8x16_t q11u8, q12u8, q13u8, q14u8, q15u8;
421 uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16, q6u16, q7u16, q8u16;
422 uint16x8_t q9u16, q10u16, q11u16, q12u16, q13u16, q14u16;
424 if (xoffset == 0) { // secondpass_bfilter16x16_only
425 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
426 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
428 q11u8 = vld1q_u8(src_ptr);
429 src_ptr += src_pixels_per_line;
430 for (i = 4; i > 0; i--) {
431 q12u8 = vld1q_u8(src_ptr);
432 src_ptr += src_pixels_per_line;
433 q13u8 = vld1q_u8(src_ptr);
434 src_ptr += src_pixels_per_line;
435 q14u8 = vld1q_u8(src_ptr);
436 src_ptr += src_pixels_per_line;
437 q15u8 = vld1q_u8(src_ptr);
438 src_ptr += src_pixels_per_line;
440 q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
441 q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
442 q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
443 q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
444 q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
445 q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
446 q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
447 q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
449 q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
450 q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
451 q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
452 q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
453 q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
454 q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
455 q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
456 q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
458 d2u8 = vqrshrn_n_u16(q1u16, 7);
459 d3u8 = vqrshrn_n_u16(q2u16, 7);
460 d4u8 = vqrshrn_n_u16(q3u16, 7);
461 d5u8 = vqrshrn_n_u16(q4u16, 7);
462 d6u8 = vqrshrn_n_u16(q5u16, 7);
463 d7u8 = vqrshrn_n_u16(q6u16, 7);
464 d8u8 = vqrshrn_n_u16(q7u16, 7);
465 d9u8 = vqrshrn_n_u16(q8u16, 7);
467 q1u8 = vcombine_u8(d2u8, d3u8);
468 q2u8 = vcombine_u8(d4u8, d5u8);
469 q3u8 = vcombine_u8(d6u8, d7u8);
470 q4u8 = vcombine_u8(d8u8, d9u8);
474 vst1q_u8((uint8_t *)dst_ptr, q1u8);
475 dst_ptr += dst_pitch;
476 vst1q_u8((uint8_t *)dst_ptr, q2u8);
477 dst_ptr += dst_pitch;
478 vst1q_u8((uint8_t *)dst_ptr, q3u8);
479 dst_ptr += dst_pitch;
480 vst1q_u8((uint8_t *)dst_ptr, q4u8);
481 dst_ptr += dst_pitch;
486 if (yoffset == 0) { // firstpass_bfilter16x16_only
487 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
488 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
490 for (i = 4; i > 0; i--) {
491 d2u8 = vld1_u8(src_ptr);
492 d3u8 = vld1_u8(src_ptr + 8);
493 d4u8 = vld1_u8(src_ptr + 16);
494 src_ptr += src_pixels_per_line;
495 d5u8 = vld1_u8(src_ptr);
496 d6u8 = vld1_u8(src_ptr + 8);
497 d7u8 = vld1_u8(src_ptr + 16);
498 src_ptr += src_pixels_per_line;
499 d8u8 = vld1_u8(src_ptr);
500 d9u8 = vld1_u8(src_ptr + 8);
501 d10u8 = vld1_u8(src_ptr + 16);
502 src_ptr += src_pixels_per_line;
503 d11u8 = vld1_u8(src_ptr);
504 d12u8 = vld1_u8(src_ptr + 8);
505 d13u8 = vld1_u8(src_ptr + 16);
506 src_ptr += src_pixels_per_line;
508 q7u16 = vmull_u8(d2u8, d0u8);
509 q8u16 = vmull_u8(d3u8, d0u8);
510 q9u16 = vmull_u8(d5u8, d0u8);
511 q10u16 = vmull_u8(d6u8, d0u8);
512 q11u16 = vmull_u8(d8u8, d0u8);
513 q12u16 = vmull_u8(d9u8, d0u8);
514 q13u16 = vmull_u8(d11u8, d0u8);
515 q14u16 = vmull_u8(d12u8, d0u8);
517 d2u8 = vext_u8(d2u8, d3u8, 1);
518 d5u8 = vext_u8(d5u8, d6u8, 1);
519 d8u8 = vext_u8(d8u8, d9u8, 1);
520 d11u8 = vext_u8(d11u8, d12u8, 1);
522 q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
523 q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
524 q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
525 q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
527 d3u8 = vext_u8(d3u8, d4u8, 1);
528 d6u8 = vext_u8(d6u8, d7u8, 1);
529 d9u8 = vext_u8(d9u8, d10u8, 1);
530 d12u8 = vext_u8(d12u8, d13u8, 1);
532 q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
533 q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
534 q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
535 q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
537 d14u8 = vqrshrn_n_u16(q7u16, 7);
538 d15u8 = vqrshrn_n_u16(q8u16, 7);
539 d16u8 = vqrshrn_n_u16(q9u16, 7);
540 d17u8 = vqrshrn_n_u16(q10u16, 7);
541 d18u8 = vqrshrn_n_u16(q11u16, 7);
542 d19u8 = vqrshrn_n_u16(q12u16, 7);
543 d20u8 = vqrshrn_n_u16(q13u16, 7);
544 d21u8 = vqrshrn_n_u16(q14u16, 7);
546 q7u8 = vcombine_u8(d14u8, d15u8);
547 q8u8 = vcombine_u8(d16u8, d17u8);
548 q9u8 = vcombine_u8(d18u8, d19u8);
549 q10u8 = vcombine_u8(d20u8, d21u8);
551 vst1q_u8((uint8_t *)dst_ptr, q7u8);
552 dst_ptr += dst_pitch;
553 vst1q_u8((uint8_t *)dst_ptr, q8u8);
554 dst_ptr += dst_pitch;
555 vst1q_u8((uint8_t *)dst_ptr, q9u8);
556 dst_ptr += dst_pitch;
557 vst1q_u8((uint8_t *)dst_ptr, q10u8);
558 dst_ptr += dst_pitch;
563 d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
564 d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
566 d2u8 = vld1_u8(src_ptr);
567 d3u8 = vld1_u8(src_ptr + 8);
568 d4u8 = vld1_u8(src_ptr + 16);
569 src_ptr += src_pixels_per_line;
570 d5u8 = vld1_u8(src_ptr);
571 d6u8 = vld1_u8(src_ptr + 8);
572 d7u8 = vld1_u8(src_ptr + 16);
573 src_ptr += src_pixels_per_line;
574 d8u8 = vld1_u8(src_ptr);
575 d9u8 = vld1_u8(src_ptr + 8);
576 d10u8 = vld1_u8(src_ptr + 16);
577 src_ptr += src_pixels_per_line;
578 d11u8 = vld1_u8(src_ptr);
579 d12u8 = vld1_u8(src_ptr + 8);
580 d13u8 = vld1_u8(src_ptr + 16);
581 src_ptr += src_pixels_per_line;
583 // First Pass: output_height lines x output_width columns (17x16)
585 for (i = 3; i > 0; i--) {
586 q7u16 = vmull_u8(d2u8, d0u8);
587 q8u16 = vmull_u8(d3u8, d0u8);
588 q9u16 = vmull_u8(d5u8, d0u8);
589 q10u16 = vmull_u8(d6u8, d0u8);
590 q11u16 = vmull_u8(d8u8, d0u8);
591 q12u16 = vmull_u8(d9u8, d0u8);
592 q13u16 = vmull_u8(d11u8, d0u8);
593 q14u16 = vmull_u8(d12u8, d0u8);
595 d2u8 = vext_u8(d2u8, d3u8, 1);
596 d5u8 = vext_u8(d5u8, d6u8, 1);
597 d8u8 = vext_u8(d8u8, d9u8, 1);
598 d11u8 = vext_u8(d11u8, d12u8, 1);
600 q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
601 q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
602 q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
603 q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
605 d3u8 = vext_u8(d3u8, d4u8, 1);
606 d6u8 = vext_u8(d6u8, d7u8, 1);
607 d9u8 = vext_u8(d9u8, d10u8, 1);
608 d12u8 = vext_u8(d12u8, d13u8, 1);
610 q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
611 q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
612 q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
613 q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
615 d14u8 = vqrshrn_n_u16(q7u16, 7);
616 d15u8 = vqrshrn_n_u16(q8u16, 7);
617 d16u8 = vqrshrn_n_u16(q9u16, 7);
618 d17u8 = vqrshrn_n_u16(q10u16, 7);
619 d18u8 = vqrshrn_n_u16(q11u16, 7);
620 d19u8 = vqrshrn_n_u16(q12u16, 7);
621 d20u8 = vqrshrn_n_u16(q13u16, 7);
622 d21u8 = vqrshrn_n_u16(q14u16, 7);
624 d2u8 = vld1_u8(src_ptr);
625 d3u8 = vld1_u8(src_ptr + 8);
626 d4u8 = vld1_u8(src_ptr + 16);
627 src_ptr += src_pixels_per_line;
628 d5u8 = vld1_u8(src_ptr);
629 d6u8 = vld1_u8(src_ptr + 8);
630 d7u8 = vld1_u8(src_ptr + 16);
631 src_ptr += src_pixels_per_line;
632 d8u8 = vld1_u8(src_ptr);
633 d9u8 = vld1_u8(src_ptr + 8);
634 d10u8 = vld1_u8(src_ptr + 16);
635 src_ptr += src_pixels_per_line;
636 d11u8 = vld1_u8(src_ptr);
637 d12u8 = vld1_u8(src_ptr + 8);
638 d13u8 = vld1_u8(src_ptr + 16);
639 src_ptr += src_pixels_per_line;
641 q7u8 = vcombine_u8(d14u8, d15u8);
642 q8u8 = vcombine_u8(d16u8, d17u8);
643 q9u8 = vcombine_u8(d18u8, d19u8);
644 q10u8 = vcombine_u8(d20u8, d21u8);
646 vst1q_u8((uint8_t *)tmpp, q7u8);
648 vst1q_u8((uint8_t *)tmpp, q8u8);
650 vst1q_u8((uint8_t *)tmpp, q9u8);
652 vst1q_u8((uint8_t *)tmpp, q10u8);
656 // First-pass filtering for rest 5 lines
657 d14u8 = vld1_u8(src_ptr);
658 d15u8 = vld1_u8(src_ptr + 8);
659 d16u8 = vld1_u8(src_ptr + 16);
660 src_ptr += src_pixels_per_line;
662 q9u16 = vmull_u8(d2u8, d0u8);
663 q10u16 = vmull_u8(d3u8, d0u8);
664 q11u16 = vmull_u8(d5u8, d0u8);
665 q12u16 = vmull_u8(d6u8, d0u8);
666 q13u16 = vmull_u8(d8u8, d0u8);
667 q14u16 = vmull_u8(d9u8, d0u8);
669 d2u8 = vext_u8(d2u8, d3u8, 1);
670 d5u8 = vext_u8(d5u8, d6u8, 1);
671 d8u8 = vext_u8(d8u8, d9u8, 1);
673 q9u16 = vmlal_u8(q9u16, d2u8, d1u8);
674 q11u16 = vmlal_u8(q11u16, d5u8, d1u8);
675 q13u16 = vmlal_u8(q13u16, d8u8, d1u8);
677 d3u8 = vext_u8(d3u8, d4u8, 1);
678 d6u8 = vext_u8(d6u8, d7u8, 1);
679 d9u8 = vext_u8(d9u8, d10u8, 1);
681 q10u16 = vmlal_u8(q10u16, d3u8, d1u8);
682 q12u16 = vmlal_u8(q12u16, d6u8, d1u8);
683 q14u16 = vmlal_u8(q14u16, d9u8, d1u8);
685 q1u16 = vmull_u8(d11u8, d0u8);
686 q2u16 = vmull_u8(d12u8, d0u8);
687 q3u16 = vmull_u8(d14u8, d0u8);
688 q4u16 = vmull_u8(d15u8, d0u8);
690 d11u8 = vext_u8(d11u8, d12u8, 1);
691 d14u8 = vext_u8(d14u8, d15u8, 1);
693 q1u16 = vmlal_u8(q1u16, d11u8, d1u8);
694 q3u16 = vmlal_u8(q3u16, d14u8, d1u8);
696 d12u8 = vext_u8(d12u8, d13u8, 1);
697 d15u8 = vext_u8(d15u8, d16u8, 1);
699 q2u16 = vmlal_u8(q2u16, d12u8, d1u8);
700 q4u16 = vmlal_u8(q4u16, d15u8, d1u8);
702 d10u8 = vqrshrn_n_u16(q9u16, 7);
703 d11u8 = vqrshrn_n_u16(q10u16, 7);
704 d12u8 = vqrshrn_n_u16(q11u16, 7);
705 d13u8 = vqrshrn_n_u16(q12u16, 7);
706 d14u8 = vqrshrn_n_u16(q13u16, 7);
707 d15u8 = vqrshrn_n_u16(q14u16, 7);
708 d16u8 = vqrshrn_n_u16(q1u16, 7);
709 d17u8 = vqrshrn_n_u16(q2u16, 7);
710 d18u8 = vqrshrn_n_u16(q3u16, 7);
711 d19u8 = vqrshrn_n_u16(q4u16, 7);
713 q5u8 = vcombine_u8(d10u8, d11u8);
714 q6u8 = vcombine_u8(d12u8, d13u8);
715 q7u8 = vcombine_u8(d14u8, d15u8);
716 q8u8 = vcombine_u8(d16u8, d17u8);
717 q9u8 = vcombine_u8(d18u8, d19u8);
719 vst1q_u8((uint8_t *)tmpp, q5u8);
721 vst1q_u8((uint8_t *)tmpp, q6u8);
723 vst1q_u8((uint8_t *)tmpp, q7u8);
725 vst1q_u8((uint8_t *)tmpp, q8u8);
727 vst1q_u8((uint8_t *)tmpp, q9u8);
730 d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
731 d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
734 q11u8 = vld1q_u8(tmpp);
736 for (i = 4; i > 0; i--) {
737 q12u8 = vld1q_u8(tmpp);
739 q13u8 = vld1q_u8(tmpp);
741 q14u8 = vld1q_u8(tmpp);
743 q15u8 = vld1q_u8(tmpp);
746 q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
747 q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
748 q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
749 q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
750 q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
751 q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
752 q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
753 q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
755 q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
756 q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
757 q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
758 q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
759 q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
760 q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
761 q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
762 q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
764 d2u8 = vqrshrn_n_u16(q1u16, 7);
765 d3u8 = vqrshrn_n_u16(q2u16, 7);
766 d4u8 = vqrshrn_n_u16(q3u16, 7);
767 d5u8 = vqrshrn_n_u16(q4u16, 7);
768 d6u8 = vqrshrn_n_u16(q5u16, 7);
769 d7u8 = vqrshrn_n_u16(q6u16, 7);
770 d8u8 = vqrshrn_n_u16(q7u16, 7);
771 d9u8 = vqrshrn_n_u16(q8u16, 7);
773 q1u8 = vcombine_u8(d2u8, d3u8);
774 q2u8 = vcombine_u8(d4u8, d5u8);
775 q3u8 = vcombine_u8(d6u8, d7u8);
776 q4u8 = vcombine_u8(d8u8, d9u8);
780 vst1q_u8((uint8_t *)dst_ptr, q1u8);
781 dst_ptr += dst_pitch;
782 vst1q_u8((uint8_t *)dst_ptr, q2u8);
783 dst_ptr += dst_pitch;
784 vst1q_u8((uint8_t *)dst_ptr, q3u8);
785 dst_ptr += dst_pitch;
786 vst1q_u8((uint8_t *)dst_ptr, q4u8);
787 dst_ptr += dst_pitch;