]> granicus.if.org Git - libvpx/blob - vp8/common/arm/neon/bilinearpredict_neon.c
ppc: Add vpx_sadnxmx4d_vsx for n,m = {8, 16, 32 ,64}
[libvpx] / vp8 / common / arm / neon / bilinearpredict_neon.c
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
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 } };
19
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));
22 }
23
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);
28     dst += dst_stride;
29     vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a0), 1);
30     dst += dst_stride;
31     vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a1), 0);
32     dst += dst_stride;
33     vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(a1), 1);
34   } else {
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);
42
43     memcpy(dst, output_buffer, 4);
44     dst += dst_stride;
45     memcpy(dst, output_buffer + 1, 4);
46     dst += dst_stride;
47     memcpy(dst, output_buffer + 2, 4);
48     dst += dst_stride;
49     memcpy(dst, output_buffer + 3, 4);
50   }
51 }
52
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,
56                                   int dst_pitch) {
57   uint8x8_t e0, e1, e2;
58
59   if (xoffset == 0) {  // skip_1stpass_filter
60     uint8x8_t a0, a1, a2, a3, a4;
61
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);
71
72     e0 = vext_u8(a0, a1, 4);
73     e1 = vext_u8(a2, a3, 4);
74     e2 = a4;
75   } else {
76     uint8x8_t a0, a1, a2, a3, a4, b4;
77     uint8x16_t a01, a23;
78     uint8x16_t b01, b23;
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]);
83
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);
93
94     a01 = vcombine_u8(a0, a1);
95     a23 = vcombine_u8(a2, a3);
96
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));
100
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)));
109
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);
113
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);
117
118     e0 = vqrshrn_n_u16(d0, 7);
119     e1 = vqrshrn_n_u16(d1, 7);
120     e2 = vqrshrn_n_u16(d2, 7);
121   }
122
123   // secondpass_filter
124   if (yoffset == 0) {  // skip_2ndpass_filter
125     store4x4(dst_ptr, dst_pitch, e0, e1);
126   } else {
127     uint8x8_t f0, f1;
128     const uint8x8_t filter0 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
129     const uint8x8_t filter1 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
130
131     uint16x8_t b0 = vmull_u8(e0, filter0);
132     uint16x8_t b1 = vmull_u8(e1, filter0);
133
134     const uint8x8_t a0 = vext_u8(e0, e1, 4);
135     const uint8x8_t a1 = vext_u8(e1, e2, 4);
136
137     b0 = vmlal_u8(b0, a0, filter1);
138     b1 = vmlal_u8(b1, a1, filter1);
139
140     f0 = vqrshrn_n_u16(b0, 7);
141     f1 = vqrshrn_n_u16(b1, 7);
142
143     store4x4(dst_ptr, dst_pitch, f0, f1);
144   }
145 }
146
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,
150                                   int dst_pitch) {
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;
156
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);
167   } else {
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);
177
178     d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
179     d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
180
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);
186
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);
192
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);
198
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);
204   }
205
206   // secondpass_filter
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);
215   } else {
216     d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
217     d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
218
219     q1u16 = vmull_u8(d22u8, d0u8);
220     q2u16 = vmull_u8(d23u8, d0u8);
221     q3u16 = vmull_u8(d24u8, d0u8);
222     q4u16 = vmull_u8(d25u8, d0u8);
223
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);
228
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);
233
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);
241   }
242   return;
243 }
244
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,
248                                   int dst_pitch) {
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;
254
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);
273   } else {
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;
282
283     d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
284     d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
285
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);
290
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);
295
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);
300
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);
305
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);
316
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);
322
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);
328
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);
334
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);
340   }
341
342   // secondpass_filter
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);
359   } else {
360     d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
361     d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
362
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);
371
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);
380
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);
389
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);
405   }
406   return;
407 }
408
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,
412                                     int dst_pitch) {
413   int i;
414   unsigned char tmp[272];
415   unsigned char *tmpp;
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;
423
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]);
427
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;
439
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);
448
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);
457
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);
466
467       q1u8 = vcombine_u8(d2u8, d3u8);
468       q2u8 = vcombine_u8(d4u8, d5u8);
469       q3u8 = vcombine_u8(d6u8, d7u8);
470       q4u8 = vcombine_u8(d8u8, d9u8);
471
472       q11u8 = q15u8;
473
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;
482     }
483     return;
484   }
485
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]);
489
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;
507
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);
516
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);
521
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);
526
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);
531
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);
536
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);
545
546       q7u8 = vcombine_u8(d14u8, d15u8);
547       q8u8 = vcombine_u8(d16u8, d17u8);
548       q9u8 = vcombine_u8(d18u8, d19u8);
549       q10u8 = vcombine_u8(d20u8, d21u8);
550
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;
559     }
560     return;
561   }
562
563   d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
564   d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
565
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;
582
583   // First Pass: output_height lines x output_width columns (17x16)
584   tmpp = tmp;
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);
594
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);
599
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);
604
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);
609
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);
614
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);
623
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;
640
641     q7u8 = vcombine_u8(d14u8, d15u8);
642     q8u8 = vcombine_u8(d16u8, d17u8);
643     q9u8 = vcombine_u8(d18u8, d19u8);
644     q10u8 = vcombine_u8(d20u8, d21u8);
645
646     vst1q_u8((uint8_t *)tmpp, q7u8);
647     tmpp += 16;
648     vst1q_u8((uint8_t *)tmpp, q8u8);
649     tmpp += 16;
650     vst1q_u8((uint8_t *)tmpp, q9u8);
651     tmpp += 16;
652     vst1q_u8((uint8_t *)tmpp, q10u8);
653     tmpp += 16;
654   }
655
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;
661
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);
668
669   d2u8 = vext_u8(d2u8, d3u8, 1);
670   d5u8 = vext_u8(d5u8, d6u8, 1);
671   d8u8 = vext_u8(d8u8, d9u8, 1);
672
673   q9u16 = vmlal_u8(q9u16, d2u8, d1u8);
674   q11u16 = vmlal_u8(q11u16, d5u8, d1u8);
675   q13u16 = vmlal_u8(q13u16, d8u8, d1u8);
676
677   d3u8 = vext_u8(d3u8, d4u8, 1);
678   d6u8 = vext_u8(d6u8, d7u8, 1);
679   d9u8 = vext_u8(d9u8, d10u8, 1);
680
681   q10u16 = vmlal_u8(q10u16, d3u8, d1u8);
682   q12u16 = vmlal_u8(q12u16, d6u8, d1u8);
683   q14u16 = vmlal_u8(q14u16, d9u8, d1u8);
684
685   q1u16 = vmull_u8(d11u8, d0u8);
686   q2u16 = vmull_u8(d12u8, d0u8);
687   q3u16 = vmull_u8(d14u8, d0u8);
688   q4u16 = vmull_u8(d15u8, d0u8);
689
690   d11u8 = vext_u8(d11u8, d12u8, 1);
691   d14u8 = vext_u8(d14u8, d15u8, 1);
692
693   q1u16 = vmlal_u8(q1u16, d11u8, d1u8);
694   q3u16 = vmlal_u8(q3u16, d14u8, d1u8);
695
696   d12u8 = vext_u8(d12u8, d13u8, 1);
697   d15u8 = vext_u8(d15u8, d16u8, 1);
698
699   q2u16 = vmlal_u8(q2u16, d12u8, d1u8);
700   q4u16 = vmlal_u8(q4u16, d15u8, d1u8);
701
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);
712
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);
718
719   vst1q_u8((uint8_t *)tmpp, q5u8);
720   tmpp += 16;
721   vst1q_u8((uint8_t *)tmpp, q6u8);
722   tmpp += 16;
723   vst1q_u8((uint8_t *)tmpp, q7u8);
724   tmpp += 16;
725   vst1q_u8((uint8_t *)tmpp, q8u8);
726   tmpp += 16;
727   vst1q_u8((uint8_t *)tmpp, q9u8);
728
729   // secondpass_filter
730   d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
731   d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
732
733   tmpp = tmp;
734   q11u8 = vld1q_u8(tmpp);
735   tmpp += 16;
736   for (i = 4; i > 0; i--) {
737     q12u8 = vld1q_u8(tmpp);
738     tmpp += 16;
739     q13u8 = vld1q_u8(tmpp);
740     tmpp += 16;
741     q14u8 = vld1q_u8(tmpp);
742     tmpp += 16;
743     q15u8 = vld1q_u8(tmpp);
744     tmpp += 16;
745
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);
754
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);
763
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);
772
773     q1u8 = vcombine_u8(d2u8, d3u8);
774     q2u8 = vcombine_u8(d4u8, d5u8);
775     q3u8 = vcombine_u8(d6u8, d7u8);
776     q4u8 = vcombine_u8(d8u8, d9u8);
777
778     q11u8 = q15u8;
779
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;
788   }
789   return;
790 }