Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vp8 / common / arm / neon / loopfiltersimpleverticaledge_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 "./vpx_config.h"
13 #include "vpx_ports/arm.h"
14
15 #ifdef VPX_INCOMPATIBLE_GCC
16 static INLINE void write_2x4(unsigned char *dst, int pitch,
17                              const uint8x8x2_t result) {
18     /*
19      * uint8x8x2_t result
20     00 01 02 03 | 04 05 06 07
21     10 11 12 13 | 14 15 16 17
22     ---
23     * after vtrn_u8
24     00 10 02 12 | 04 14 06 16
25     01 11 03 13 | 05 15 07 17
26     */
27     const uint8x8x2_t r01_u8 = vtrn_u8(result.val[0],
28                                        result.val[1]);
29     const uint16x4_t x_0_4 = vreinterpret_u16_u8(r01_u8.val[0]);
30     const uint16x4_t x_1_5 = vreinterpret_u16_u8(r01_u8.val[1]);
31     vst1_lane_u16((uint16_t *)dst, x_0_4, 0);
32     dst += pitch;
33     vst1_lane_u16((uint16_t *)dst, x_1_5, 0);
34     dst += pitch;
35     vst1_lane_u16((uint16_t *)dst, x_0_4, 1);
36     dst += pitch;
37     vst1_lane_u16((uint16_t *)dst, x_1_5, 1);
38     dst += pitch;
39     vst1_lane_u16((uint16_t *)dst, x_0_4, 2);
40     dst += pitch;
41     vst1_lane_u16((uint16_t *)dst, x_1_5, 2);
42     dst += pitch;
43     vst1_lane_u16((uint16_t *)dst, x_0_4, 3);
44     dst += pitch;
45     vst1_lane_u16((uint16_t *)dst, x_1_5, 3);
46 }
47
48 static INLINE void write_2x8(unsigned char *dst, int pitch,
49                              const uint8x8x2_t result,
50                              const uint8x8x2_t result2) {
51   write_2x4(dst, pitch, result);
52   dst += pitch * 8;
53   write_2x4(dst, pitch, result2);
54 }
55 #else
56 static INLINE void write_2x8(unsigned char *dst, int pitch,
57                              const uint8x8x2_t result,
58                              const uint8x8x2_t result2) {
59   vst2_lane_u8(dst, result, 0);
60   dst += pitch;
61   vst2_lane_u8(dst, result, 1);
62   dst += pitch;
63   vst2_lane_u8(dst, result, 2);
64   dst += pitch;
65   vst2_lane_u8(dst, result, 3);
66   dst += pitch;
67   vst2_lane_u8(dst, result, 4);
68   dst += pitch;
69   vst2_lane_u8(dst, result, 5);
70   dst += pitch;
71   vst2_lane_u8(dst, result, 6);
72   dst += pitch;
73   vst2_lane_u8(dst, result, 7);
74   dst += pitch;
75
76   vst2_lane_u8(dst, result2, 0);
77   dst += pitch;
78   vst2_lane_u8(dst, result2, 1);
79   dst += pitch;
80   vst2_lane_u8(dst, result2, 2);
81   dst += pitch;
82   vst2_lane_u8(dst, result2, 3);
83   dst += pitch;
84   vst2_lane_u8(dst, result2, 4);
85   dst += pitch;
86   vst2_lane_u8(dst, result2, 5);
87   dst += pitch;
88   vst2_lane_u8(dst, result2, 6);
89   dst += pitch;
90   vst2_lane_u8(dst, result2, 7);
91 }
92 #endif  // VPX_INCOMPATIBLE_GCC
93
94
95 #ifdef VPX_INCOMPATIBLE_GCC
96 static INLINE
97 uint8x8x4_t read_4x8(unsigned char *src, int pitch, uint8x8x4_t x) {
98     const uint8x8_t a = vld1_u8(src);
99     const uint8x8_t b = vld1_u8(src + pitch * 1);
100     const uint8x8_t c = vld1_u8(src + pitch * 2);
101     const uint8x8_t d = vld1_u8(src + pitch * 3);
102     const uint8x8_t e = vld1_u8(src + pitch * 4);
103     const uint8x8_t f = vld1_u8(src + pitch * 5);
104     const uint8x8_t g = vld1_u8(src + pitch * 6);
105     const uint8x8_t h = vld1_u8(src + pitch * 7);
106     const uint32x2x2_t r04_u32 = vtrn_u32(vreinterpret_u32_u8(a),
107                                           vreinterpret_u32_u8(e));
108     const uint32x2x2_t r15_u32 = vtrn_u32(vreinterpret_u32_u8(b),
109                                           vreinterpret_u32_u8(f));
110     const uint32x2x2_t r26_u32 = vtrn_u32(vreinterpret_u32_u8(c),
111                                           vreinterpret_u32_u8(g));
112     const uint32x2x2_t r37_u32 = vtrn_u32(vreinterpret_u32_u8(d),
113                                           vreinterpret_u32_u8(h));
114     const uint16x4x2_t r02_u16 = vtrn_u16(vreinterpret_u16_u32(r04_u32.val[0]),
115                                           vreinterpret_u16_u32(r26_u32.val[0]));
116     const uint16x4x2_t r13_u16 = vtrn_u16(vreinterpret_u16_u32(r15_u32.val[0]),
117                                           vreinterpret_u16_u32(r37_u32.val[0]));
118     const uint8x8x2_t r01_u8 = vtrn_u8(vreinterpret_u8_u16(r02_u16.val[0]),
119                                        vreinterpret_u8_u16(r13_u16.val[0]));
120     const uint8x8x2_t r23_u8 = vtrn_u8(vreinterpret_u8_u16(r02_u16.val[1]),
121                                        vreinterpret_u8_u16(r13_u16.val[1]));
122     /*
123      * after vtrn_u32
124     00 01 02 03 | 40 41 42 43
125     10 11 12 13 | 50 51 52 53
126     20 21 22 23 | 60 61 62 63
127     30 31 32 33 | 70 71 72 73
128     ---
129     * after vtrn_u16
130     00 01 20 21 | 40 41 60 61
131     02 03 22 23 | 42 43 62 63
132     10 11 30 31 | 50 51 70 71
133     12 13 32 33 | 52 52 72 73
134
135     00 01 20 21 | 40 41 60 61
136     10 11 30 31 | 50 51 70 71
137     02 03 22 23 | 42 43 62 63
138     12 13 32 33 | 52 52 72 73
139     ---
140     * after vtrn_u8
141     00 10 20 30 | 40 50 60 70
142     01 11 21 31 | 41 51 61 71
143     02 12 22 32 | 42 52 62 72
144     03 13 23 33 | 43 53 63 73
145     */
146     x.val[0] = r01_u8.val[0];
147     x.val[1] = r01_u8.val[1];
148     x.val[2] = r23_u8.val[0];
149     x.val[3] = r23_u8.val[1];
150
151     return x;
152 }
153 #else
154 static INLINE
155 uint8x8x4_t read_4x8(unsigned char *src, int pitch, uint8x8x4_t x) {
156     x = vld4_lane_u8(src, x, 0);
157     src += pitch;
158     x = vld4_lane_u8(src, x, 1);
159     src += pitch;
160     x = vld4_lane_u8(src, x, 2);
161     src += pitch;
162     x = vld4_lane_u8(src, x, 3);
163     src += pitch;
164     x = vld4_lane_u8(src, x, 4);
165     src += pitch;
166     x = vld4_lane_u8(src, x, 5);
167     src += pitch;
168     x = vld4_lane_u8(src, x, 6);
169     src += pitch;
170     x = vld4_lane_u8(src, x, 7);
171     return x;
172 }
173 #endif  // VPX_INCOMPATIBLE_GCC
174
175 static INLINE void vp8_loop_filter_simple_vertical_edge_neon(
176         unsigned char *s,
177         int p,
178         const unsigned char *blimit) {
179     unsigned char *src1;
180     uint8x16_t qblimit, q0u8;
181     uint8x16_t q3u8, q4u8, q5u8, q6u8, q7u8, q11u8, q12u8, q14u8, q15u8;
182     int16x8_t q2s16, q13s16, q11s16;
183     int8x8_t d28s8, d29s8;
184     int8x16_t q2s8, q3s8, q10s8, q11s8, q14s8;
185     uint8x8x4_t d0u8x4;  // d6, d7, d8, d9
186     uint8x8x4_t d1u8x4;  // d10, d11, d12, d13
187     uint8x8x2_t d2u8x2;  // d12, d13
188     uint8x8x2_t d3u8x2;  // d14, d15
189
190     qblimit = vdupq_n_u8(*blimit);
191
192     src1 = s - 2;
193     d0u8x4 = read_4x8(src1, p, d0u8x4);
194     src1 += p * 8;
195     d1u8x4 = read_4x8(src1, p, d1u8x4);
196
197     q3u8 = vcombine_u8(d0u8x4.val[0], d1u8x4.val[0]);  // d6 d10
198     q4u8 = vcombine_u8(d0u8x4.val[2], d1u8x4.val[2]);  // d8 d12
199     q5u8 = vcombine_u8(d0u8x4.val[1], d1u8x4.val[1]);  // d7 d11
200     q6u8 = vcombine_u8(d0u8x4.val[3], d1u8x4.val[3]);  // d9 d13
201
202     q15u8 = vabdq_u8(q5u8, q4u8);
203     q14u8 = vabdq_u8(q3u8, q6u8);
204
205     q15u8 = vqaddq_u8(q15u8, q15u8);
206     q14u8 = vshrq_n_u8(q14u8, 1);
207     q0u8 = vdupq_n_u8(0x80);
208     q11s16 = vdupq_n_s16(3);
209     q15u8 = vqaddq_u8(q15u8, q14u8);
210
211     q3u8 = veorq_u8(q3u8, q0u8);
212     q4u8 = veorq_u8(q4u8, q0u8);
213     q5u8 = veorq_u8(q5u8, q0u8);
214     q6u8 = veorq_u8(q6u8, q0u8);
215
216     q15u8 = vcgeq_u8(qblimit, q15u8);
217
218     q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q4u8)),
219                      vget_low_s8(vreinterpretq_s8_u8(q5u8)));
220     q13s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q4u8)),
221                       vget_high_s8(vreinterpretq_s8_u8(q5u8)));
222
223     q14s8 = vqsubq_s8(vreinterpretq_s8_u8(q3u8),
224                       vreinterpretq_s8_u8(q6u8));
225
226     q2s16 = vmulq_s16(q2s16, q11s16);
227     q13s16 = vmulq_s16(q13s16, q11s16);
228
229     q11u8 = vdupq_n_u8(3);
230     q12u8 = vdupq_n_u8(4);
231
232     q2s16 = vaddw_s8(q2s16, vget_low_s8(q14s8));
233     q13s16 = vaddw_s8(q13s16, vget_high_s8(q14s8));
234
235     d28s8 = vqmovn_s16(q2s16);
236     d29s8 = vqmovn_s16(q13s16);
237     q14s8 = vcombine_s8(d28s8, d29s8);
238
239     q14s8 = vandq_s8(q14s8, vreinterpretq_s8_u8(q15u8));
240
241     q2s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q11u8));
242     q3s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q12u8));
243     q2s8 = vshrq_n_s8(q2s8, 3);
244     q14s8 = vshrq_n_s8(q3s8, 3);
245
246     q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q5u8), q2s8);
247     q10s8 = vqsubq_s8(vreinterpretq_s8_u8(q4u8), q14s8);
248
249     q6u8 = veorq_u8(vreinterpretq_u8_s8(q11s8), q0u8);
250     q7u8 = veorq_u8(vreinterpretq_u8_s8(q10s8), q0u8);
251
252     d2u8x2.val[0] = vget_low_u8(q6u8);   // d12
253     d2u8x2.val[1] = vget_low_u8(q7u8);   // d14
254     d3u8x2.val[0] = vget_high_u8(q6u8);  // d13
255     d3u8x2.val[1] = vget_high_u8(q7u8);  // d15
256
257     src1 = s - 1;
258     write_2x8(src1, p, d2u8x2, d3u8x2);
259 }
260
261 void vp8_loop_filter_bvs_neon(
262         unsigned char *y_ptr,
263         int y_stride,
264         const unsigned char *blimit) {
265     y_ptr += 4;
266     vp8_loop_filter_simple_vertical_edge_neon(y_ptr, y_stride, blimit);
267     y_ptr += 4;
268     vp8_loop_filter_simple_vertical_edge_neon(y_ptr, y_stride, blimit);
269     y_ptr += 4;
270     vp8_loop_filter_simple_vertical_edge_neon(y_ptr, y_stride, blimit);
271     return;
272 }
273
274 void vp8_loop_filter_mbvs_neon(
275         unsigned char *y_ptr,
276         int y_stride,
277         const unsigned char *blimit) {
278     vp8_loop_filter_simple_vertical_edge_neon(y_ptr, y_stride, blimit);
279     return;
280 }