contrib: libmpeg2 simplistic NEON acceleration for motion compensation
[vlc.git] / extras / contrib / src / Patches / libmpeg2-mc-neon.patch
1 Index: include/mpeg2.h
2 ===================================================================
3 --- include/mpeg2.h     (révision 1193)
4 +++ include/mpeg2.h     (copie de travail)
5 @@ -164,6 +164,7 @@
6  #define MPEG2_ACCEL_SPARC_VIS 1
7  #define MPEG2_ACCEL_SPARC_VIS2 2
8  #define MPEG2_ACCEL_ARM 1
9 +#define MPEG2_ACCEL_ARM_NEON 2
10  #define MPEG2_ACCEL_DETECT 0x80000000
11  
12  uint32_t mpeg2_accel (uint32_t accel);
13 Index: libmpeg2/motion_comp_neon.c
14 ===================================================================
15 --- libmpeg2/motion_comp_neon.c (révision 0)
16 +++ libmpeg2/motion_comp_neon.c (révision 0)
17 @@ -0,0 +1,302 @@
18 +/*
19 + * motion_comp_neon.c
20 + * Copyright (C) 2009 Rémi Denis-Courmont
21 + *
22 + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
23 + * See http://libmpeg2.sourceforge.net/ for updates.
24 + *
25 + * mpeg2dec is free software; you can redistribute it and/or modify
26 + * it under the terms of the GNU General Public License as published by
27 + * the Free Software Foundation; either version 2 of the License, or
28 + * (at your option) any later version.
29 + *
30 + * mpeg2dec is distributed in the hope that it will be useful,
31 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33 + * GNU General Public License for more details.
34 + *
35 + * You should have received a copy of the GNU General Public License along
36 + * with mpeg2dec; if not, write to the Free Software Foundation, Inc.,
37 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 + */
39 +
40 +#include "config.h"
41 +
42 +#if defined(ARCH_ARM_NEON)
43 +
44 +#include <stdint.h>
45 +#include <string.h>
46 +
47 +#include "mpeg2.h"
48 +#include "attributes.h"
49 +#include "mpeg2_internal.h"
50 +
51 +/* dest = ref */
52 +static void MC_put_o_16_neon (uint8_t * dest, const uint8_t * ref,
53 +                             const int stride, int height)
54 +{
55 +    do {
56 +       memcpy (dest, ref, 16);
57 +       ref += stride;
58 +       dest += stride;
59 +    } while (--height);
60 +}
61 +
62 +static void MC_put_o_8_neon (uint8_t * dest, const uint8_t * ref,
63 +                            const int stride, int height)
64 +{
65 +    do {
66 +       memcpy (dest, ref, 8);
67 +       ref += stride;
68 +       dest += stride;
69 +    } while (--height);
70 +}
71 +
72 +/* dest = (src1 + src2 + 1) / 2 */
73 +static void MC_avg_1_16_neon (uint8_t * dest, const uint8_t * src1,
74 +                             const uint8_t * src2,
75 +                             const int stride, unsigned height)
76 +{
77 +    do {
78 +       asm volatile (
79 +           "vld1.u8 {q0}, [%[src1]]\n"
80 +           "vld1.u8 {q1}, [%[src2]]\n"
81 +           "vrhadd.u8 q0, q0, q1\n"
82 +           /* XXX: three cycles stall */
83 +           "vst1.u8 {q0}, [%[dest]]\n"
84 +           :
85 +           : [dest]"r"(dest), [src1]"r"(src1), [src2]"r"(src2)
86 +           : "memory", "q0", "q1");
87 +       src1 += stride;
88 +       src2 += stride;
89 +       dest += stride;
90 +    } while (--height);
91 +}
92 +
93 +static void MC_avg_1_8_neon (uint8_t * dest, const uint8_t * src1,
94 +                            const uint8_t * src2,
95 +                            const int stride, unsigned height)
96 +{
97 +    do {
98 +       asm volatile (
99 +           "vld1.u8 {d0}, [%[src1]]\n"
100 +           "vld1.u8 {d1}, [%[src2]]\n"
101 +           "vrhadd.u8 d0, d0, d1\n"
102 +           "vst1.u8 {d0}, [%[dest]]\n"
103 +           :
104 +           : [dest]"r"(dest), [src1]"r"(src1), [src2]"r"(src2)
105 +           : "memory", "q0");
106 +       
107 +       src1 += stride;
108 +       src2 += stride;
109 +       dest += stride;
110 +    } while (--height);
111 +}
112 +
113 +/* dest = (dest + ((src1 + src2 + 1) / 2) + 1) / 2 */
114 +static void MC_avg_2_16_neon (uint8_t * dest, const uint8_t * src1,
115 +                             const uint8_t * src2,
116 +                             const int stride, unsigned height)
117 +{
118 +    do {
119 +       asm volatile (
120 +           "vld1.u8 {q0}, [%[src1]]\n"
121 +           "vld1.u8 {q1}, [%[src2]]\n"
122 +           "vrhadd.u8 q0, q0, q1\n"
123 +           "vld1.u8 {q2}, [%[dest]]\n"
124 +           /* XXX: one cycle stall */
125 +           "vrhadd.u8 q0, q0, q2\n"
126 +           /* XXX: three cycles stall */
127 +           "vst1.u8 {q0}, [%[dest]]\n"
128 +           :
129 +           : [dest]"r"(dest), [src1]"r"(src1), [src2]"r"(src2)
130 +           : "memory", "q0", "q1", "q2");
131 +       src1 += stride;
132 +       src2 += stride;
133 +       dest += stride;
134 +    } while (--height);
135 +}
136 +
137 +static void MC_avg_2_8_neon (uint8_t * dest, const uint8_t * src1,
138 +                            const uint8_t * src2,
139 +                            const int stride, unsigned height)
140 +{
141 +    do {
142 +       asm volatile (
143 +           "vld1.u8 {d0}, [%[src1]]\n"
144 +           "vld1.u8 {d1}, [%[src2]]\n"
145 +           "vrhadd.u8 d0, d0, d1\n"
146 +           "vld1.u8 {d2}, [%[dest]]\n"
147 +           "vrhadd.u8 d0, d0, d2\n"
148 +           "vst1.u8 {d0}, [%[dest]]\n"
149 +           :
150 +           : [dest]"r"(dest), [src1]"r"(src1), [src2]"r"(src2)
151 +           : "memory", "q0", "d2");
152 +       src1 += stride;
153 +       src2 += stride;
154 +       dest += stride;
155 +    } while (--height);
156 +}
157 +
158 +static void MC_avg_o_16_neon (uint8_t * dest, const uint8_t * ref,
159 +                             const int stride, int height)
160 +{
161 +    MC_avg_1_16_neon (dest, dest, ref, stride, height);
162 +}
163 +
164 +static void MC_avg_o_8_neon (uint8_t * dest, const uint8_t * ref,
165 +                            const int stride, int height)
166 +{
167 +    MC_avg_1_8_neon (dest, dest, ref, stride, height);
168 +}
169 +
170 +static void MC_put_x_16_neon (uint8_t * dest, const uint8_t * ref,
171 +                             const int stride, int height)
172 +{
173 +    MC_avg_1_16_neon (dest, ref, ref + 1, stride, height);
174 +}
175 +
176 +static void MC_put_x_8_neon (uint8_t * dest, const uint8_t * ref,
177 +                            const int stride, int height)
178 +{
179 +    MC_avg_1_8_neon (dest, ref, ref + 1, stride, height);
180 +}
181 +
182 +static void MC_avg_x_16_neon (uint8_t * dest, const uint8_t * ref,
183 +                             const int stride, int height)
184 +{
185 +    MC_avg_2_16_neon (dest, ref, ref + 1, stride, height);
186 +}
187 +
188 +static void MC_avg_x_8_neon (uint8_t * dest, const uint8_t * ref,
189 +                            const int stride, int height)
190 +{
191 +    MC_avg_2_8_neon (dest, ref, ref + 1, stride, height);
192 +}
193 +
194 +static void MC_put_y_16_neon (uint8_t * dest, const uint8_t * ref,
195 +                             const int stride, int height)
196 +{
197 +    MC_avg_1_16_neon (dest, ref, ref + stride, stride, height);
198 +}
199 +static void MC_put_y_8_neon (uint8_t * dest, const uint8_t * ref,
200 +                            const int stride, int height)
201 +{
202 +    MC_avg_1_8_neon (dest, ref, ref + stride, stride, height);
203 +}
204 +
205 +static void MC_avg_y_16_neon (uint8_t * dest, const uint8_t * ref,
206 +                             const int stride, int height)
207 +{
208 +    MC_avg_2_16_neon (dest, ref, ref + stride, stride, height);
209 +}
210 +
211 +static void MC_avg_y_8_neon (uint8_t * dest, const uint8_t * ref,
212 +                            const int stride, int height)
213 +{
214 +    MC_avg_2_8_neon (dest, ref, ref + stride, stride, height);
215 +}
216 +
217 +static void MC_put_xy_16_neon (uint8_t * dest, const uint8_t * ref,
218 +                              const int stride, int height)
219 +{
220 +    do {
221 +       asm volatile (
222 +           "vld1.u8 {q0}, [%[ref]]\n"
223 +           "vld1.u8 {q1}, [%[refx]]\n"
224 +           "vrhadd.u8 q0, q0, q1\n"
225 +           "vld1.u8 {q2}, [%[refy]]\n"
226 +           "vld1.u8 {q3}, [%[refxy]]\n"
227 +           "vrhadd.u8 q2, q2, q3\n"
228 +           /* XXX: three cycles stall */
229 +           "vrhadd.u8 q0, q0, q2\n"
230 +           /* XXX: three cycles stall */
231 +           "vst1.u8 {q0}, [%[dest]]\n"
232 +           :
233 +           : [dest]"r"(dest), [ref]"r"(ref), [refx]"r"(ref + 1),
234 +                      [refy]"r"(ref + stride), [refxy]"r"(ref + stride + 1)
235 +           : "memory", "q0", "q1", "q2", "q3");
236 +       ref += stride;
237 +       dest += stride;
238 +    } while (--height);
239 +}
240 +
241 +static void MC_put_xy_8_neon (uint8_t * dest, const uint8_t * ref,
242 +                             const int stride, int height)
243 +{
244 +    do {
245 +       asm volatile (
246 +           "vld1.u8 {d0}, [%[ref]]\n"
247 +           "vld1.u8 {d1}, [%[refx]]\n"
248 +           "vrhadd.u8 d0, d0, d1\n"
249 +           "vld1.u8 {d2}, [%[refy]]\n"
250 +           "vld1.u8 {d3}, [%[refxy]]\n"
251 +           "vrhadd.u8 d2, d2, d3\n"
252 +           /* XXX: three cycles stall */
253 +           "vrhadd.u8 d0, d0, d2\n"
254 +           /* XXX: three cycles stall */
255 +           "vst1.u8 {d0}, [%[dest]]\n"
256 +           :
257 +           : [dest]"r"(dest), [ref]"r"(ref), [refx]"r"(ref + 1),
258 +                      [refy]"r"(ref + stride), [refxy]"r"(ref + stride + 1)
259 +           : "memory", "q0", "q1");
260 +       ref += stride;
261 +       dest += stride;
262 +    } while (--height);
263 +}
264 +
265 +static void MC_avg_xy_16_neon (uint8_t * dest, const uint8_t * ref,
266 +                              const int stride, int height)
267 +{
268 +    do {
269 +       asm volatile (
270 +           "vld1.u8 {q0}, [%[ref]]\n"
271 +           "vld1.u8 {q1}, [%[refx]]\n"
272 +           "vrhadd.u8 q0, q0, q1\n"
273 +           "vld1.u8 {q2}, [%[refy]]\n"
274 +           "vld1.u8 {q3}, [%[refxy]]\n"
275 +           "vrhadd.u8 q2, q2, q3\n"
276 +           "vld1.u8 {q4}, [%[dest]]\n"
277 +           /* XXX: one cycle stall */
278 +           "vrhadd.u8 q0, q0, q2\n"
279 +           /* XXX: three cycles stall */
280 +           "vrhadd.u8 q0, q4, q0\n"
281 +           "vst1.u8 {q0}, [%[dest]]\n"
282 +           :
283 +           : [dest]"r"(dest), [ref]"r"(ref), [refx]"r"(ref + 1),
284 +                      [refy]"r"(ref + stride), [refxy]"r"(ref + stride + 1)
285 +           : "memory", "q0", "q1", "q2", "q3", "q4");
286 +       ref += stride;
287 +       dest += stride;
288 +    } while (--height);
289 +}
290 +
291 +static void MC_avg_xy_8_neon (uint8_t * dest, const uint8_t * ref,
292 +                             const int stride, int height)
293 +{
294 +    do {
295 +       asm volatile (
296 +           "vld1.u8 {d0}, [%[ref]]\n"
297 +           "vld1.u8 {d1}, [%[refx]]\n"
298 +           "vrhadd.u8 d0, d0, d1\n"
299 +           "vld1.u8 {d2}, [%[refy]]\n"
300 +           "vld1.u8 {d3}, [%[refxy]]\n"
301 +           "vrhadd.u8 d2, d2, d3\n"
302 +           "vld1.u8 {d4}, [%[dest]]\n"
303 +           /* XXX: one cycle stall */
304 +           "vrhadd.u8 d0, d0, d2\n"
305 +           /* XXX: three cycles stall */
306 +           "vrhadd.u8 d0, d4, d0\n"
307 +           "vst1.u8 {d0}, [%[dest]]\n"
308 +           :
309 +           : [dest]"r"(dest), [ref]"r"(ref), [refx]"r"(ref + 1),
310 +                      [refy]"r"(ref + stride), [refxy]"r"(ref + stride + 1)
311 +           : "memory", "q0", "q1", "d4");
312 +       ref += stride;
313 +       dest += stride;
314 +    } while (--height);
315 +}
316 +
317 +MPEG2_MC_EXTERN (neon)
318 +
319 +#endif /* ARCH_ARM_NEON */
320
321 Modification de propriétés sur libmpeg2/motion_comp_neon.c
322 ___________________________________________________________________
323 Ajouté : svn:eol-style
324    + native
325
326 Index: libmpeg2/mpeg2_internal.h
327 ===================================================================
328 --- libmpeg2/mpeg2_internal.h   (révision 1193)
329 +++ libmpeg2/mpeg2_internal.h   (copie de travail)
330 @@ -313,5 +313,6 @@
331  extern mpeg2_mc_t mpeg2_mc_alpha;
332  extern mpeg2_mc_t mpeg2_mc_vis;
333  extern mpeg2_mc_t mpeg2_mc_arm;
334 +extern mpeg2_mc_t mpeg2_mc_neon;
335  
336  #endif /* LIBMPEG2_MPEG2_INTERNAL_H */
337 Index: libmpeg2/motion_comp.c
338 ===================================================================
339 --- libmpeg2/motion_comp.c      (révision 1193)
340 +++ libmpeg2/motion_comp.c      (copie de travail)
341 @@ -58,6 +58,11 @@
342      else
343  #endif
344  #ifdef ARCH_ARM
345 +#ifdef ARCH_ARM_NEON
346 +    if (accel & MPEG2_ACCEL_ARM_NEON)
347 +        mpeg2_mc = mpeg2_mc_neon;
348 +    else
349 +#endif
350      if (accel & MPEG2_ACCEL_ARM) {
351         mpeg2_mc = mpeg2_mc_arm;
352      } else
353 Index: libmpeg2/Makefile.am
354 ===================================================================
355 --- libmpeg2/Makefile.am        (révision 1193)
356 +++ libmpeg2/Makefile.am        (copie de travail)
357 @@ -14,7 +14,7 @@
358                           motion_comp_vis.c motion_comp_arm.c \
359                           cpu_accel.c cpu_state.c
360  if ARCH_ARM
361 -libmpeg2arch_la_SOURCES += motion_comp_arm_s.S
362 +libmpeg2arch_la_SOURCES += motion_comp_arm_s.S motion_comp_neon.c
363  endif
364  libmpeg2arch_la_CFLAGS = $(OPT_CFLAGS) $(ARCH_OPT_CFLAGS) $(LIBMPEG2_CFLAGS)
365  
366 Index: configure.ac
367 ===================================================================
368 --- configure.ac        (révision 1193)
369 +++ configure.ac        (copie de travail)
370 @@ -103,7 +103,14 @@
371         AC_DEFINE([ARCH_ALPHA],,[alpha architecture]);;
372      arm*)
373         arm_conditional=:
374 -       AC_DEFINE([ARCH_ARM],,[ARM architecture]);;
375 +       AC_DEFINE([ARCH_ARM],,[ARM architecture])
376 +        AC_MSG_CHECKING([if inline ARM Advanced SIMD assembly is supported])
377 +        AC_TRY_COMPILE([],
378 +           [asm ("vqmovun.s64 d0, q1":::"d0");],
379 +           [AC_DEFINE([ARCH_ARM_NEON],, [ARM Advanced SIMD assembly])
380 +            AC_MSG_RESULT(yes)],
381 +           [AC_MSG_RESULT(no)])
382 +        ;;
383      esac
384  elif test x"$CC" = x"tendracc"; then
385      dnl TenDRA portability checking compiler