loopfilter_16_neon.c revision 7ce0a1d1337c01056ba24006efab21f00e179e04
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#include "./vpx_config.h"
15#include "vpx/vpx_integer.h"
16
17static INLINE void loop_filter_neon_16(
18        uint8x16_t qblimit,  // blimit
19        uint8x16_t qlimit,   // limit
20        uint8x16_t qthresh,  // thresh
21        uint8x16_t q3,       // p3
22        uint8x16_t q4,       // p2
23        uint8x16_t q5,       // p1
24        uint8x16_t q6,       // p0
25        uint8x16_t q7,       // q0
26        uint8x16_t q8,       // q1
27        uint8x16_t q9,       // q2
28        uint8x16_t q10,      // q3
29        uint8x16_t *q5r,     // p1
30        uint8x16_t *q6r,     // p0
31        uint8x16_t *q7r,     // q0
32        uint8x16_t *q8r) {   // q1
33    uint8x16_t q1u8, q2u8, q11u8, q12u8, q13u8, q14u8, q15u8;
34    int16x8_t q2s16, q11s16;
35    uint16x8_t q4u16;
36    int8x16_t q0s8, q1s8, q2s8, q11s8, q12s8, q13s8;
37    int8x8_t d2s8, d3s8;
38
39    q11u8 = vabdq_u8(q3, q4);
40    q12u8 = vabdq_u8(q4, q5);
41    q13u8 = vabdq_u8(q5, q6);
42    q14u8 = vabdq_u8(q8, q7);
43    q3 = vabdq_u8(q9, q8);
44    q4 = vabdq_u8(q10, q9);
45
46    q11u8 = vmaxq_u8(q11u8, q12u8);
47    q12u8 = vmaxq_u8(q13u8, q14u8);
48    q3 = vmaxq_u8(q3, q4);
49    q15u8 = vmaxq_u8(q11u8, q12u8);
50
51    q9 = vabdq_u8(q6, q7);
52
53    // vp8_hevmask
54    q13u8 = vcgtq_u8(q13u8, qthresh);
55    q14u8 = vcgtq_u8(q14u8, qthresh);
56    q15u8 = vmaxq_u8(q15u8, q3);
57
58    q2u8 = vabdq_u8(q5, q8);
59    q9 = vqaddq_u8(q9, q9);
60
61    q15u8 = vcgeq_u8(qlimit, q15u8);
62
63    // vp8_filter() function
64    // convert to signed
65    q10 = vdupq_n_u8(0x80);
66    q8 = veorq_u8(q8, q10);
67    q7 = veorq_u8(q7, q10);
68    q6 = veorq_u8(q6, q10);
69    q5 = veorq_u8(q5, q10);
70
71    q2u8 = vshrq_n_u8(q2u8, 1);
72    q9 = vqaddq_u8(q9, q2u8);
73
74    q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q7)),
75                     vget_low_s8(vreinterpretq_s8_u8(q6)));
76    q11s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q7)),
77                      vget_high_s8(vreinterpretq_s8_u8(q6)));
78
79    q9 = vcgeq_u8(qblimit, q9);
80
81    q1s8 = vqsubq_s8(vreinterpretq_s8_u8(q5),
82                    vreinterpretq_s8_u8(q8));
83
84    q14u8 = vorrq_u8(q13u8, q14u8);
85
86    q4u16 = vdupq_n_u16(3);
87    q2s16 = vmulq_s16(q2s16, vreinterpretq_s16_u16(q4u16));
88    q11s16 = vmulq_s16(q11s16, vreinterpretq_s16_u16(q4u16));
89
90    q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q14u8);
91    q15u8 = vandq_u8(q15u8, q9);
92
93    q1s8 = vreinterpretq_s8_u8(q1u8);
94    q2s16 = vaddw_s8(q2s16, vget_low_s8(q1s8));
95    q11s16 = vaddw_s8(q11s16, vget_high_s8(q1s8));
96
97    q4 = vdupq_n_u8(3);
98    q9 = vdupq_n_u8(4);
99    // vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0))
100    d2s8 = vqmovn_s16(q2s16);
101    d3s8 = vqmovn_s16(q11s16);
102    q1s8 = vcombine_s8(d2s8, d3s8);
103    q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q15u8);
104    q1s8 = vreinterpretq_s8_u8(q1u8);
105
106    q2s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q4));
107    q1s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q9));
108    q2s8 = vshrq_n_s8(q2s8, 3);
109    q1s8 = vshrq_n_s8(q1s8, 3);
110
111    q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q6), q2s8);
112    q0s8 = vqsubq_s8(vreinterpretq_s8_u8(q7), q1s8);
113
114    q1s8 = vrshrq_n_s8(q1s8, 1);
115    q1s8 = vbicq_s8(q1s8, vreinterpretq_s8_u8(q14u8));
116
117    q13s8 = vqaddq_s8(vreinterpretq_s8_u8(q5), q1s8);
118    q12s8 = vqsubq_s8(vreinterpretq_s8_u8(q8), q1s8);
119
120    *q8r = veorq_u8(vreinterpretq_u8_s8(q12s8), q10);
121    *q7r = veorq_u8(vreinterpretq_u8_s8(q0s8),  q10);
122    *q6r = veorq_u8(vreinterpretq_u8_s8(q11s8), q10);
123    *q5r = veorq_u8(vreinterpretq_u8_s8(q13s8), q10);
124    return;
125}
126
127void vpx_lpf_horizontal_4_dual_neon(uint8_t *s, int p /* pitch */,
128                                    const uint8_t *blimit0,
129                                    const uint8_t *limit0,
130                                    const uint8_t *thresh0,
131                                    const uint8_t *blimit1,
132                                    const uint8_t *limit1,
133                                    const uint8_t *thresh1) {
134    uint8x8_t dblimit0, dlimit0, dthresh0, dblimit1, dlimit1, dthresh1;
135    uint8x16_t qblimit, qlimit, qthresh;
136    uint8x16_t q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
137
138    dblimit0 = vld1_u8(blimit0);
139    dlimit0 = vld1_u8(limit0);
140    dthresh0 = vld1_u8(thresh0);
141    dblimit1 = vld1_u8(blimit1);
142    dlimit1 = vld1_u8(limit1);
143    dthresh1 = vld1_u8(thresh1);
144    qblimit = vcombine_u8(dblimit0, dblimit1);
145    qlimit = vcombine_u8(dlimit0, dlimit1);
146    qthresh = vcombine_u8(dthresh0, dthresh1);
147
148    s -= (p << 2);
149
150    q3u8 = vld1q_u8(s);
151    s += p;
152    q4u8 = vld1q_u8(s);
153    s += p;
154    q5u8 = vld1q_u8(s);
155    s += p;
156    q6u8 = vld1q_u8(s);
157    s += p;
158    q7u8 = vld1q_u8(s);
159    s += p;
160    q8u8 = vld1q_u8(s);
161    s += p;
162    q9u8 = vld1q_u8(s);
163    s += p;
164    q10u8 = vld1q_u8(s);
165
166    loop_filter_neon_16(qblimit, qlimit, qthresh,
167                        q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8,
168                        &q5u8, &q6u8, &q7u8, &q8u8);
169
170    s -= (p * 5);
171    vst1q_u8(s, q5u8);
172    s += p;
173    vst1q_u8(s, q6u8);
174    s += p;
175    vst1q_u8(s, q7u8);
176    s += p;
177    vst1q_u8(s, q8u8);
178    return;
179}
180