]> git.sesse.net Git - vlc/blob - plugins/motion/motion3dnow.c
fed3ca628e8bbbdfb37b5323cfaf78c2292cf65e
[vlc] / plugins / motion / motion3dnow.c
1 /*****************************************************************************
2  * motion3dnow.c : 3D Now! motion compensation module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: motion3dnow.c,v 1.11 2002/06/01 12:32:00 sam Exp $
6  *
7  * Authors: Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
8  *          Michel Lespinasse <walken@zoy.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32
33 #include "mmx.h"
34
35 /*****************************************************************************
36  * Local and extern prototypes.
37  *****************************************************************************/
38 static void motion_getfunctions( function_list_t * p_function_list );
39
40 /*****************************************************************************
41  * Build configuration tree.
42  *****************************************************************************/
43 MODULE_CONFIG_START
44 MODULE_CONFIG_STOP
45
46 MODULE_INIT_START
47     SET_DESCRIPTION( _("3D Now! motion compensation module") )
48     ADD_CAPABILITY( MOTION, 150 )
49     ADD_REQUIREMENT( 3DNOW )
50     ADD_SHORTCUT( "3dn" )
51     ADD_SHORTCUT( "3dnow" )
52 MODULE_INIT_STOP
53
54 MODULE_ACTIVATE_START
55     motion_getfunctions( &p_module->p_functions->motion );
56 MODULE_ACTIVATE_STOP
57
58 MODULE_DEACTIVATE_START
59 MODULE_DEACTIVATE_STOP
60
61 /*****************************************************************************
62  * Motion compensation in 3D Now! (OK I know this does MMXEXT too and it's ugly)
63  *****************************************************************************/
64
65 #define CPU_MMXEXT 0
66 #define CPU_3DNOW 1
67
68
69 //CPU_MMXEXT/CPU_3DNOW adaptation layer
70
71 #define pavg_r2r(src,dest)                                                  \
72 do {                                                                        \
73     if (cpu == CPU_MMXEXT)                                                  \
74         pavgb_r2r (src, dest);                                              \
75     else                                                                    \
76         pavgusb_r2r (src, dest);                                            \
77 } while (0)
78
79 #define pavg_m2r(src,dest)                                                  \
80 do {                                                                        \
81     if (cpu == CPU_MMXEXT)                                                  \
82         pavgb_m2r (src, dest);                                              \
83     else                                                                    \
84         pavgusb_m2r (src, dest);                                            \
85 } while (0)
86
87
88 //CPU_MMXEXT code
89
90
91 static inline void MC_put1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
92                               int stride)
93 {
94     do {
95         movq_m2r (*ref, mm0);
96         movq_r2m (mm0, *dest);
97         ref += stride;
98         dest += stride;
99     } while (--height);
100 }
101
102 static inline void MC_put1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
103                                int stride)
104 {
105     do {
106         movq_m2r (*ref, mm0);
107         movq_m2r (*(ref+8), mm1);
108         ref += stride;
109         movq_r2m (mm0, *dest);
110         movq_r2m (mm1, *(dest+8));
111         dest += stride;
112     } while (--height);
113 }
114
115 static inline void MC_avg1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
116                               int stride, int cpu)
117 {
118     do {
119         movq_m2r (*ref, mm0);
120         pavg_m2r (*dest, mm0);
121         ref += stride;
122         movq_r2m (mm0, *dest);
123         dest += stride;
124     } while (--height);
125 }
126
127 static inline void MC_avg1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
128                                int stride, int cpu)
129 {
130     do {
131         movq_m2r (*ref, mm0);
132         movq_m2r (*(ref+8), mm1);
133         pavg_m2r (*dest, mm0);
134         pavg_m2r (*(dest+8), mm1);
135         movq_r2m (mm0, *dest);
136         ref += stride;
137         movq_r2m (mm1, *(dest+8));
138         dest += stride;
139     } while (--height);
140 }
141
142 static inline void MC_put2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
143                               int stride, int offset, int cpu)
144 {
145     do {
146         movq_m2r (*ref, mm0);
147         pavg_m2r (*(ref+offset), mm0);
148         ref += stride;
149         movq_r2m (mm0, *dest);
150         dest += stride;
151     } while (--height);
152 }
153
154 static inline void MC_put2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
155                                int stride, int offset, int cpu)
156 {
157     do {
158         movq_m2r (*ref, mm0);
159         movq_m2r (*(ref+8), mm1);
160         pavg_m2r (*(ref+offset), mm0);
161         pavg_m2r (*(ref+offset+8), mm1);
162         movq_r2m (mm0, *dest);
163         ref += stride;
164         movq_r2m (mm1, *(dest+8));
165         dest += stride;
166     } while (--height);
167 }
168
169 static inline void MC_avg2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
170                               int stride, int offset, int cpu)
171 {
172     do {
173         movq_m2r (*ref, mm0);
174         pavg_m2r (*(ref+offset), mm0);
175         pavg_m2r (*dest, mm0);
176         ref += stride;
177         movq_r2m (mm0, *dest);
178         dest += stride;
179     } while (--height);
180 }
181
182 static inline void MC_avg2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
183                                int stride, int offset, int cpu)
184 {
185     do {
186         movq_m2r (*ref, mm0);
187         movq_m2r (*(ref+8), mm1);
188         pavg_m2r (*(ref+offset), mm0);
189         pavg_m2r (*(ref+offset+8), mm1);
190         pavg_m2r (*dest, mm0);
191         pavg_m2r (*(dest+8), mm1);
192         ref += stride;
193         movq_r2m (mm0, *dest);
194         movq_r2m (mm1, *(dest+8));
195         dest += stride;
196     } while (--height);
197 }
198
199 static mmx_t mask_one = {0x0101010101010101LL};
200
201 static inline void MC_put4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
202                               int stride, int cpu)
203 {
204     movq_m2r (*ref, mm0);
205     movq_m2r (*(ref+1), mm1);
206     movq_r2r (mm0, mm7);
207     pxor_r2r (mm1, mm7);
208     pavg_r2r (mm1, mm0);
209     ref += stride;
210
211     do {
212         movq_m2r (*ref, mm2);
213         movq_r2r (mm0, mm5);
214
215         movq_m2r (*(ref+1), mm3);
216         movq_r2r (mm2, mm6);
217
218         pxor_r2r (mm3, mm6);
219         pavg_r2r (mm3, mm2);
220
221         por_r2r (mm6, mm7);
222         pxor_r2r (mm2, mm5);
223
224         pand_r2r (mm5, mm7);
225         pavg_r2r (mm2, mm0);
226
227         pand_m2r (mask_one, mm7);
228
229         psubusb_r2r (mm7, mm0);
230
231         ref += stride;
232         movq_r2m (mm0, *dest);
233         dest += stride;
234
235         movq_r2r (mm6, mm7);        // unroll !
236         movq_r2r (mm2, mm0);        // unroll !
237     } while (--height);
238 }
239
240 static inline void MC_put4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
241                                int stride, int cpu)
242 {
243     do {
244         movq_m2r (*ref, mm0);
245         movq_m2r (*(ref+stride+1), mm1);
246         movq_r2r (mm0, mm7);
247         movq_m2r (*(ref+1), mm2);
248         pxor_r2r (mm1, mm7);
249         movq_m2r (*(ref+stride), mm3);
250         movq_r2r (mm2, mm6);
251         pxor_r2r (mm3, mm6);
252         pavg_r2r (mm1, mm0);
253         pavg_r2r (mm3, mm2);
254         por_r2r (mm6, mm7);
255         movq_r2r (mm0, mm6);
256         pxor_r2r (mm2, mm6);
257         pand_r2r (mm6, mm7);
258         pand_m2r (mask_one, mm7);
259         pavg_r2r (mm2, mm0);
260         psubusb_r2r (mm7, mm0);
261         movq_r2m (mm0, *dest);
262
263         movq_m2r (*(ref+8), mm0);
264         movq_m2r (*(ref+stride+9), mm1);
265         movq_r2r (mm0, mm7);
266         movq_m2r (*(ref+9), mm2);
267         pxor_r2r (mm1, mm7);
268         movq_m2r (*(ref+stride+8), mm3);
269         movq_r2r (mm2, mm6);
270         pxor_r2r (mm3, mm6);
271         pavg_r2r (mm1, mm0);
272         pavg_r2r (mm3, mm2);
273         por_r2r (mm6, mm7);
274         movq_r2r (mm0, mm6);
275         pxor_r2r (mm2, mm6);
276         pand_r2r (mm6, mm7);
277         pand_m2r (mask_one, mm7);
278         pavg_r2r (mm2, mm0);
279         psubusb_r2r (mm7, mm0);
280         ref += stride;
281         movq_r2m (mm0, *(dest+8));
282         dest += stride;
283     } while (--height);
284 }
285
286 static inline void MC_avg4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
287                               int stride, int cpu)
288 {
289     do {
290         movq_m2r (*ref, mm0);
291         movq_m2r (*(ref+stride+1), mm1);
292         movq_r2r (mm0, mm7);
293         movq_m2r (*(ref+1), mm2);
294         pxor_r2r (mm1, mm7);
295         movq_m2r (*(ref+stride), mm3);
296         movq_r2r (mm2, mm6);
297         pxor_r2r (mm3, mm6);
298         pavg_r2r (mm1, mm0);
299         pavg_r2r (mm3, mm2);
300         por_r2r (mm6, mm7);
301         movq_r2r (mm0, mm6);
302         pxor_r2r (mm2, mm6);
303         pand_r2r (mm6, mm7);
304         pand_m2r (mask_one, mm7);
305         pavg_r2r (mm2, mm0);
306         psubusb_r2r (mm7, mm0);
307         movq_m2r (*dest, mm1);
308         pavg_r2r (mm1, mm0);
309         ref += stride;
310         movq_r2m (mm0, *dest);
311         dest += stride;
312     } while (--height);
313 }
314
315 static inline void MC_avg4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
316                                int stride, int cpu)
317 {
318     do {
319         movq_m2r (*ref, mm0);
320         movq_m2r (*(ref+stride+1), mm1);
321         movq_r2r (mm0, mm7);
322         movq_m2r (*(ref+1), mm2);
323         pxor_r2r (mm1, mm7);
324         movq_m2r (*(ref+stride), mm3);
325         movq_r2r (mm2, mm6);
326         pxor_r2r (mm3, mm6);
327         pavg_r2r (mm1, mm0);
328         pavg_r2r (mm3, mm2);
329         por_r2r (mm6, mm7);
330         movq_r2r (mm0, mm6);
331         pxor_r2r (mm2, mm6);
332         pand_r2r (mm6, mm7);
333         pand_m2r (mask_one, mm7);
334         pavg_r2r (mm2, mm0);
335         psubusb_r2r (mm7, mm0);
336         movq_m2r (*dest, mm1);
337         pavg_r2r (mm1, mm0);
338         movq_r2m (mm0, *dest);
339
340         movq_m2r (*(ref+8), mm0);
341         movq_m2r (*(ref+stride+9), mm1);
342         movq_r2r (mm0, mm7);
343         movq_m2r (*(ref+9), mm2);
344         pxor_r2r (mm1, mm7);
345         movq_m2r (*(ref+stride+8), mm3);
346         movq_r2r (mm2, mm6);
347         pxor_r2r (mm3, mm6);
348         pavg_r2r (mm1, mm0);
349         pavg_r2r (mm3, mm2);
350         por_r2r (mm6, mm7);
351         movq_r2r (mm0, mm6);
352         pxor_r2r (mm2, mm6);
353         pand_r2r (mm6, mm7);
354         pand_m2r (mask_one, mm7);
355         pavg_r2r (mm2, mm0);
356         psubusb_r2r (mm7, mm0);
357         movq_m2r (*(dest+8), mm1);
358         pavg_r2r (mm1, mm0);
359         ref += stride;
360         movq_r2m (mm0, *(dest+8));
361         dest += stride;
362     } while (--height);
363 }
364
365 static void MC_avg_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
366                               int stride, int height)
367 {
368     MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
369 }
370
371 static void MC_avg_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
372                              int stride, int height)
373 {
374     MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
375 }
376
377 static void MC_put_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
378                               int stride, int height)
379 {
380     MC_put1_16 (height, dest, ref, stride);
381 }
382
383 static void MC_put_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
384                              int stride, int height)
385 {
386     MC_put1_8 (height, dest, ref, stride);
387 }
388
389 static void MC_avg_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
390                                int stride, int height)
391 {
392     MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
393 }
394
395 static void MC_avg_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
396                               int stride, int height)
397 {
398     MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
399 }
400
401 static void MC_put_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
402                                int stride, int height)
403 {
404     MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
405 }
406
407 static void MC_put_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
408                               int stride, int height)
409 {
410     MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
411 }
412
413 static void MC_avg_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
414                                int stride, int height)
415 {
416     MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
417 }
418
419 static void MC_avg_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
420                               int stride, int height)
421 {
422     MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
423 }
424
425 static void MC_put_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
426                                int stride, int height)
427 {
428     MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
429 }
430
431 static void MC_put_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
432                               int stride, int height)
433 {
434     MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
435 }
436
437 static void MC_avg_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
438                                 int stride, int height)
439 {
440     MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
441 }
442
443 static void MC_avg_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
444                                int stride, int height)
445 {
446     MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
447 }
448
449 static void MC_put_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
450                                 int stride, int height)
451 {
452     MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
453 }
454
455 static void MC_put_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
456                                int stride, int height)
457 {
458     MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
459 }
460
461
462 static void MC_avg_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
463                               int stride, int height)
464 {
465     MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
466 }
467
468 static void MC_avg_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
469                              int stride, int height)
470 {
471     MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
472 }
473
474 static void MC_put_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
475                               int stride, int height)
476 {
477     MC_put1_16 (height, dest, ref, stride);
478 }
479
480 static void MC_put_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
481                              int stride, int height)
482 {
483     MC_put1_8 (height, dest, ref, stride);
484 }
485
486 static void MC_avg_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
487                                int stride, int height)
488 {
489     MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
490 }
491
492 static void MC_avg_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
493                               int stride, int height)
494 {
495     MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
496 }
497
498 static void MC_put_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
499                                int stride, int height)
500 {
501     MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
502 }
503
504 static void MC_put_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
505                               int stride, int height)
506 {
507     MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
508 }
509
510 static void MC_avg_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
511                                int stride, int height)
512 {
513     MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
514 }
515
516 static void MC_avg_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
517                               int stride, int height)
518 {
519     MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
520 }
521
522 static void MC_put_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
523                                int stride, int height)
524 {
525     MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
526 }
527
528 static void MC_put_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
529                               int stride, int height)
530 {
531     MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
532 }
533
534 static void MC_avg_xy16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
535                                 int stride, int height)
536 {
537     MC_avg4_16 (height, dest, ref, stride, CPU_3DNOW);
538 }
539
540 static void MC_avg_xy8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
541                                int stride, int height)
542 {
543     MC_avg4_8 (height, dest, ref, stride, CPU_3DNOW);
544 }
545
546 static void MC_put_xy16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
547                                 int stride, int height)
548 {
549     MC_put4_16 (height, dest, ref, stride, CPU_3DNOW);
550 }
551
552 static void MC_put_xy8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
553                                int stride, int height)
554 {
555     MC_put4_8 (height, dest, ref, stride, CPU_3DNOW);
556 }
557
558 /*****************************************************************************
559  * Functions exported as capabilities. They are declared as static so that
560  * we don't pollute the namespace too much.
561  *****************************************************************************/
562 static void motion_getfunctions( function_list_t * p_function_list )
563 {
564     static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *,
565                                            int, int ) =
566     {
567         {
568             /* Copying functions */
569             {
570                 /* Width == 16 */
571                 MC_put_16_3dnow, MC_put_x16_3dnow, MC_put_y16_3dnow, MC_put_xy16_3dnow
572             },
573             {
574                 /* Width == 8 */
575                 MC_put_8_3dnow,  MC_put_x8_3dnow,  MC_put_y8_3dnow, MC_put_xy8_3dnow
576             }
577         },
578         {
579             /* Averaging functions */
580             {
581                 /* Width == 16 */
582                 MC_avg_16_3dnow, MC_avg_x16_3dnow, MC_avg_y16_3dnow, MC_avg_xy16_3dnow
583             },
584             {
585                 /* Width == 8 */
586                 MC_avg_8_3dnow,  MC_avg_x8_3dnow,  MC_avg_y8_3dnow,  MC_avg_xy8_3dnow
587             }
588         }
589     };
590
591 #define list p_function_list->functions.motion
592     memcpy( list.ppppf_motion, ppppf_motion, sizeof( void * ) * 16 );
593 #undef list
594
595     return;
596 }
597