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