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