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 #include "./vpx_dsp_rtcd.h"
14 
loop_filter_neon(uint8x8_t dblimit,uint8x8_t dlimit,uint8x8_t dthresh,uint8x8_t d3u8,uint8x8_t d4u8,uint8x8_t d5u8,uint8x8_t d6u8,uint8x8_t d7u8,uint8x8_t d16u8,uint8x8_t d17u8,uint8x8_t d18u8,uint8x8_t * d4ru8,uint8x8_t * d5ru8,uint8x8_t * d6ru8,uint8x8_t * d7ru8)15 static INLINE void loop_filter_neon(
16         uint8x8_t dblimit,    // flimit
17         uint8x8_t dlimit,     // limit
18         uint8x8_t dthresh,    // thresh
19         uint8x8_t d3u8,       // p3
20         uint8x8_t d4u8,       // p2
21         uint8x8_t d5u8,       // p1
22         uint8x8_t d6u8,       // p0
23         uint8x8_t d7u8,       // q0
24         uint8x8_t d16u8,      // q1
25         uint8x8_t d17u8,      // q2
26         uint8x8_t d18u8,      // q3
27         uint8x8_t *d4ru8,     // p1
28         uint8x8_t *d5ru8,     // p0
29         uint8x8_t *d6ru8,     // q0
30         uint8x8_t *d7ru8) {   // q1
31     uint8x8_t d19u8, d20u8, d21u8, d22u8, d23u8, d27u8, d28u8;
32     int16x8_t q12s16;
33     int8x8_t d19s8, d20s8, d21s8, d26s8, d27s8, d28s8;
34 
35     d19u8 = vabd_u8(d3u8, d4u8);
36     d20u8 = vabd_u8(d4u8, d5u8);
37     d21u8 = vabd_u8(d5u8, d6u8);
38     d22u8 = vabd_u8(d16u8, d7u8);
39     d3u8  = vabd_u8(d17u8, d16u8);
40     d4u8  = vabd_u8(d18u8, d17u8);
41 
42     d19u8 = vmax_u8(d19u8, d20u8);
43     d20u8 = vmax_u8(d21u8, d22u8);
44     d3u8  = vmax_u8(d3u8,  d4u8);
45     d23u8 = vmax_u8(d19u8, d20u8);
46 
47     d17u8 = vabd_u8(d6u8, d7u8);
48 
49     d21u8 = vcgt_u8(d21u8, dthresh);
50     d22u8 = vcgt_u8(d22u8, dthresh);
51     d23u8 = vmax_u8(d23u8, d3u8);
52 
53     d28u8 = vabd_u8(d5u8, d16u8);
54     d17u8 = vqadd_u8(d17u8, d17u8);
55 
56     d23u8 = vcge_u8(dlimit, d23u8);
57 
58     d18u8 = vdup_n_u8(0x80);
59     d5u8  = veor_u8(d5u8,  d18u8);
60     d6u8  = veor_u8(d6u8,  d18u8);
61     d7u8  = veor_u8(d7u8,  d18u8);
62     d16u8 = veor_u8(d16u8, d18u8);
63 
64     d28u8 = vshr_n_u8(d28u8, 1);
65     d17u8 = vqadd_u8(d17u8, d28u8);
66 
67     d19u8 = vdup_n_u8(3);
68 
69     d28s8 = vsub_s8(vreinterpret_s8_u8(d7u8),
70                     vreinterpret_s8_u8(d6u8));
71 
72     d17u8 = vcge_u8(dblimit, d17u8);
73 
74     d27s8 = vqsub_s8(vreinterpret_s8_u8(d5u8),
75                      vreinterpret_s8_u8(d16u8));
76 
77     d22u8 = vorr_u8(d21u8, d22u8);
78 
79     q12s16 = vmull_s8(d28s8, vreinterpret_s8_u8(d19u8));
80 
81     d27u8 = vand_u8(vreinterpret_u8_s8(d27s8), d22u8);
82     d23u8 = vand_u8(d23u8, d17u8);
83 
84     q12s16 = vaddw_s8(q12s16, vreinterpret_s8_u8(d27u8));
85 
86     d17u8 = vdup_n_u8(4);
87 
88     d27s8 = vqmovn_s16(q12s16);
89     d27u8 = vand_u8(vreinterpret_u8_s8(d27s8), d23u8);
90     d27s8 = vreinterpret_s8_u8(d27u8);
91 
92     d28s8 = vqadd_s8(d27s8, vreinterpret_s8_u8(d19u8));
93     d27s8 = vqadd_s8(d27s8, vreinterpret_s8_u8(d17u8));
94     d28s8 = vshr_n_s8(d28s8, 3);
95     d27s8 = vshr_n_s8(d27s8, 3);
96 
97     d19s8 = vqadd_s8(vreinterpret_s8_u8(d6u8), d28s8);
98     d26s8 = vqsub_s8(vreinterpret_s8_u8(d7u8), d27s8);
99 
100     d27s8 = vrshr_n_s8(d27s8, 1);
101     d27s8 = vbic_s8(d27s8, vreinterpret_s8_u8(d22u8));
102 
103     d21s8 = vqadd_s8(vreinterpret_s8_u8(d5u8), d27s8);
104     d20s8 = vqsub_s8(vreinterpret_s8_u8(d16u8), d27s8);
105 
106     *d4ru8 = veor_u8(vreinterpret_u8_s8(d21s8), d18u8);
107     *d5ru8 = veor_u8(vreinterpret_u8_s8(d19s8), d18u8);
108     *d6ru8 = veor_u8(vreinterpret_u8_s8(d26s8), d18u8);
109     *d7ru8 = veor_u8(vreinterpret_u8_s8(d20s8), d18u8);
110     return;
111 }
112 
vpx_lpf_horizontal_4_neon(uint8_t * src,int pitch,const uint8_t * blimit,const uint8_t * limit,const uint8_t * thresh)113 void vpx_lpf_horizontal_4_neon(
114         uint8_t *src,
115         int pitch,
116         const uint8_t *blimit,
117         const uint8_t *limit,
118         const uint8_t *thresh) {
119     int i;
120     uint8_t *s, *psrc;
121     uint8x8_t dblimit, dlimit, dthresh;
122     uint8x8_t d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8;
123 
124     dblimit = vld1_u8(blimit);
125     dlimit = vld1_u8(limit);
126     dthresh = vld1_u8(thresh);
127 
128     psrc = src - (pitch << 2);
129     for (i = 0; i < 1; i++) {
130         s = psrc + i * 8;
131 
132         d3u8 = vld1_u8(s);
133         s += pitch;
134         d4u8 = vld1_u8(s);
135         s += pitch;
136         d5u8 = vld1_u8(s);
137         s += pitch;
138         d6u8 = vld1_u8(s);
139         s += pitch;
140         d7u8 = vld1_u8(s);
141         s += pitch;
142         d16u8 = vld1_u8(s);
143         s += pitch;
144         d17u8 = vld1_u8(s);
145         s += pitch;
146         d18u8 = vld1_u8(s);
147 
148         loop_filter_neon(dblimit, dlimit, dthresh,
149                          d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8,
150                          &d4u8, &d5u8, &d6u8, &d7u8);
151 
152         s -= (pitch * 5);
153         vst1_u8(s, d4u8);
154         s += pitch;
155         vst1_u8(s, d5u8);
156         s += pitch;
157         vst1_u8(s, d6u8);
158         s += pitch;
159         vst1_u8(s, d7u8);
160     }
161     return;
162 }
163 
vpx_lpf_vertical_4_neon(uint8_t * src,int pitch,const uint8_t * blimit,const uint8_t * limit,const uint8_t * thresh)164 void vpx_lpf_vertical_4_neon(
165         uint8_t *src,
166         int pitch,
167         const uint8_t *blimit,
168         const uint8_t *limit,
169         const uint8_t *thresh) {
170     int i, pitch8;
171     uint8_t *s;
172     uint8x8_t dblimit, dlimit, dthresh;
173     uint8x8_t d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8;
174     uint32x2x2_t d2tmp0, d2tmp1, d2tmp2, d2tmp3;
175     uint16x4x2_t d2tmp4, d2tmp5, d2tmp6, d2tmp7;
176     uint8x8x2_t d2tmp8, d2tmp9, d2tmp10, d2tmp11;
177     uint8x8x4_t d4Result;
178 
179     dblimit = vld1_u8(blimit);
180     dlimit = vld1_u8(limit);
181     dthresh = vld1_u8(thresh);
182 
183     pitch8 = pitch * 8;
184     for (i = 0; i < 1; i++, src += pitch8) {
185         s = src - (i + 1) * 4;
186 
187         d3u8 = vld1_u8(s);
188         s += pitch;
189         d4u8 = vld1_u8(s);
190         s += pitch;
191         d5u8 = vld1_u8(s);
192         s += pitch;
193         d6u8 = vld1_u8(s);
194         s += pitch;
195         d7u8 = vld1_u8(s);
196         s += pitch;
197         d16u8 = vld1_u8(s);
198         s += pitch;
199         d17u8 = vld1_u8(s);
200         s += pitch;
201         d18u8 = vld1_u8(s);
202 
203         d2tmp0 = vtrn_u32(vreinterpret_u32_u8(d3u8),
204                       vreinterpret_u32_u8(d7u8));
205         d2tmp1 = vtrn_u32(vreinterpret_u32_u8(d4u8),
206                       vreinterpret_u32_u8(d16u8));
207         d2tmp2 = vtrn_u32(vreinterpret_u32_u8(d5u8),
208                       vreinterpret_u32_u8(d17u8));
209         d2tmp3 = vtrn_u32(vreinterpret_u32_u8(d6u8),
210                       vreinterpret_u32_u8(d18u8));
211 
212         d2tmp4 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[0]),
213                           vreinterpret_u16_u32(d2tmp2.val[0]));
214         d2tmp5 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[0]),
215                           vreinterpret_u16_u32(d2tmp3.val[0]));
216         d2tmp6 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[1]),
217                           vreinterpret_u16_u32(d2tmp2.val[1]));
218         d2tmp7 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[1]),
219                           vreinterpret_u16_u32(d2tmp3.val[1]));
220 
221         d2tmp8 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[0]),
222                          vreinterpret_u8_u16(d2tmp5.val[0]));
223         d2tmp9 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[1]),
224                          vreinterpret_u8_u16(d2tmp5.val[1]));
225         d2tmp10 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[0]),
226                           vreinterpret_u8_u16(d2tmp7.val[0]));
227         d2tmp11 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[1]),
228                           vreinterpret_u8_u16(d2tmp7.val[1]));
229 
230         d3u8 = d2tmp8.val[0];
231         d4u8 = d2tmp8.val[1];
232         d5u8 = d2tmp9.val[0];
233         d6u8 = d2tmp9.val[1];
234         d7u8 = d2tmp10.val[0];
235         d16u8 = d2tmp10.val[1];
236         d17u8 = d2tmp11.val[0];
237         d18u8 = d2tmp11.val[1];
238 
239         loop_filter_neon(dblimit, dlimit, dthresh,
240                          d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8,
241                          &d4u8, &d5u8, &d6u8, &d7u8);
242 
243         d4Result.val[0] = d4u8;
244         d4Result.val[1] = d5u8;
245         d4Result.val[2] = d6u8;
246         d4Result.val[3] = d7u8;
247 
248         src -= 2;
249         vst4_lane_u8(src, d4Result, 0);
250         src += pitch;
251         vst4_lane_u8(src, d4Result, 1);
252         src += pitch;
253         vst4_lane_u8(src, d4Result, 2);
254         src += pitch;
255         vst4_lane_u8(src, d4Result, 3);
256         src += pitch;
257         vst4_lane_u8(src, d4Result, 4);
258         src += pitch;
259         vst4_lane_u8(src, d4Result, 5);
260         src += pitch;
261         vst4_lane_u8(src, d4Result, 6);
262         src += pitch;
263         vst4_lane_u8(src, d4Result, 7);
264     }
265     return;
266 }
267