]> git.sesse.net Git - vlc/blob - plugins/motion/motionmmxext.c
Some heavy changes today:
[vlc] / plugins / motion / motionmmxext.c
1 /*****************************************************************************
2  * motionmmxext.c : MMX EXT motion compensation module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: motionmmxext.c,v 1.15 2001/12/30 07:09:55 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 <videolan/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( "MMXEXT motion compensation module" )
48     ADD_CAPABILITY( MOTION, 200 )
49     ADD_REQUIREMENT( MMXEXT )
50     ADD_SHORTCUT( "mmxext" )
51     ADD_SHORTCUT( "motionmmxext" )
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_Probe: tests probe the CPU and return a score
63  *****************************************************************************/
64 static int motion_Probe( probedata_t *p_data )
65 {
66     return( 200 );
67 }
68
69 /*****************************************************************************
70  * Motion compensation in MMXEXT (OK I know this does 3DNow too and it's ugly)
71  *****************************************************************************/
72
73 #define CPU_MMXEXT 0
74 #define CPU_3DNOW 1
75
76
77 //CPU_MMXEXT/CPU_3DNOW adaptation layer
78
79 #define pavg_r2r(src,dest)                                                  \
80 do {                                                                        \
81     if (cpu == CPU_MMXEXT)                                                  \
82         pavgb_r2r (src, dest);                                              \
83     else                                                                    \
84         pavgusb_r2r (src, dest);                                            \
85 } while (0)
86
87 #define pavg_m2r(src,dest)                                                  \
88 do {                                                                        \
89     if (cpu == CPU_MMXEXT)                                                  \
90         pavgb_m2r (src, dest);                                              \
91     else                                                                    \
92         pavgusb_m2r (src, dest);                                            \
93 } while (0)
94
95
96 //CPU_MMXEXT code
97
98
99 static __inline__ void MC_put1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
100                               int stride)
101 {
102     do {
103         movq_m2r (*ref, mm0);
104         movq_r2m (mm0, *dest);
105         ref += stride;
106         dest += stride;
107     } while (--height);
108 }
109
110 static __inline__ void MC_put1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
111                                int stride)
112 {
113     do {
114         movq_m2r (*ref, mm0);
115         movq_m2r (*(ref+8), mm1);
116         ref += stride;
117         movq_r2m (mm0, *dest);
118         movq_r2m (mm1, *(dest+8));
119         dest += stride;
120     } while (--height);
121 }
122
123 static __inline__ void MC_avg1_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
124                               int stride, int cpu)
125 {
126     do {
127         movq_m2r (*ref, mm0);
128         pavg_m2r (*dest, mm0);
129         ref += stride;
130         movq_r2m (mm0, *dest);
131         dest += stride;
132     } while (--height);
133 }
134
135 static __inline__ void MC_avg1_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
136                                int stride, int cpu)
137 {
138     do {
139         movq_m2r (*ref, mm0);
140         movq_m2r (*(ref+8), mm1);
141         pavg_m2r (*dest, mm0);
142         pavg_m2r (*(dest+8), mm1);
143         movq_r2m (mm0, *dest);
144         ref += stride;
145         movq_r2m (mm1, *(dest+8));
146         dest += stride;
147     } while (--height);
148 }
149
150 static __inline__ void MC_put2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
151                               int stride, int offset, int cpu)
152 {
153     do {
154         movq_m2r (*ref, mm0);
155         pavg_m2r (*(ref+offset), mm0);
156         ref += stride;
157         movq_r2m (mm0, *dest);
158         dest += stride;
159     } while (--height);
160 }
161
162 static __inline__ void MC_put2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
163                                int stride, int offset, int cpu)
164 {
165     do {
166         movq_m2r (*ref, mm0);
167         movq_m2r (*(ref+8), mm1);
168         pavg_m2r (*(ref+offset), mm0);
169         pavg_m2r (*(ref+offset+8), mm1);
170         movq_r2m (mm0, *dest);
171         ref += stride;
172         movq_r2m (mm1, *(dest+8));
173         dest += stride;
174     } while (--height);
175 }
176
177 static __inline__ void MC_avg2_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
178                               int stride, int offset, int cpu)
179 {
180     do {
181         movq_m2r (*ref, mm0);
182         pavg_m2r (*(ref+offset), mm0);
183         pavg_m2r (*dest, mm0);
184         ref += stride;
185         movq_r2m (mm0, *dest);
186         dest += stride;
187     } while (--height);
188 }
189
190 static __inline__ void MC_avg2_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
191                                int stride, int offset, int cpu)
192 {
193     do {
194         movq_m2r (*ref, mm0);
195         movq_m2r (*(ref+8), mm1);
196         pavg_m2r (*(ref+offset), mm0);
197         pavg_m2r (*(ref+offset+8), mm1);
198         pavg_m2r (*dest, mm0);
199         pavg_m2r (*(dest+8), mm1);
200         ref += stride;
201         movq_r2m (mm0, *dest);
202         movq_r2m (mm1, *(dest+8));
203         dest += stride;
204     } while (--height);
205 }
206
207 static mmx_t mask_one = {0x0101010101010101LL};
208
209 static __inline__ void MC_put4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
210                               int stride, int cpu)
211 {
212     movq_m2r (*ref, mm0);
213     movq_m2r (*(ref+1), mm1);
214     movq_r2r (mm0, mm7);
215     pxor_r2r (mm1, mm7);
216     pavg_r2r (mm1, mm0);
217     ref += stride;
218
219     do {
220         movq_m2r (*ref, mm2);
221         movq_r2r (mm0, mm5);
222
223         movq_m2r (*(ref+1), mm3);
224         movq_r2r (mm2, mm6);
225
226         pxor_r2r (mm3, mm6);
227         pavg_r2r (mm3, mm2);
228
229         por_r2r (mm6, mm7);
230         pxor_r2r (mm2, mm5);
231
232         pand_r2r (mm5, mm7);
233         pavg_r2r (mm2, mm0);
234
235         pand_m2r (mask_one, mm7);
236
237         psubusb_r2r (mm7, mm0);
238
239         ref += stride;
240         movq_r2m (mm0, *dest);
241         dest += stride;
242
243         movq_r2r (mm6, mm7);        // unroll !
244         movq_r2r (mm2, mm0);        // unroll !
245     } while (--height);
246 }
247
248 static __inline__ void MC_put4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
249                                int stride, int cpu)
250 {
251     do {
252         movq_m2r (*ref, mm0);
253         movq_m2r (*(ref+stride+1), mm1);
254         movq_r2r (mm0, mm7);
255         movq_m2r (*(ref+1), mm2);
256         pxor_r2r (mm1, mm7);
257         movq_m2r (*(ref+stride), mm3);
258         movq_r2r (mm2, mm6);
259         pxor_r2r (mm3, mm6);
260         pavg_r2r (mm1, mm0);
261         pavg_r2r (mm3, mm2);
262         por_r2r (mm6, mm7);
263         movq_r2r (mm0, mm6);
264         pxor_r2r (mm2, mm6);
265         pand_r2r (mm6, mm7);
266         pand_m2r (mask_one, mm7);
267         pavg_r2r (mm2, mm0);
268         psubusb_r2r (mm7, mm0);
269         movq_r2m (mm0, *dest);
270
271         movq_m2r (*(ref+8), mm0);
272         movq_m2r (*(ref+stride+9), mm1);
273         movq_r2r (mm0, mm7);
274         movq_m2r (*(ref+9), mm2);
275         pxor_r2r (mm1, mm7);
276         movq_m2r (*(ref+stride+8), mm3);
277         movq_r2r (mm2, mm6);
278         pxor_r2r (mm3, mm6);
279         pavg_r2r (mm1, mm0);
280         pavg_r2r (mm3, mm2);
281         por_r2r (mm6, mm7);
282         movq_r2r (mm0, mm6);
283         pxor_r2r (mm2, mm6);
284         pand_r2r (mm6, mm7);
285         pand_m2r (mask_one, mm7);
286         pavg_r2r (mm2, mm0);
287         psubusb_r2r (mm7, mm0);
288         ref += stride;
289         movq_r2m (mm0, *(dest+8));
290         dest += stride;
291     } while (--height);
292 }
293
294 static __inline__ void MC_avg4_8 (int height, yuv_data_t * dest, yuv_data_t * ref,
295                               int stride, int cpu)
296 {
297     do {
298         movq_m2r (*ref, mm0);
299         movq_m2r (*(ref+stride+1), mm1);
300         movq_r2r (mm0, mm7);
301         movq_m2r (*(ref+1), mm2);
302         pxor_r2r (mm1, mm7);
303         movq_m2r (*(ref+stride), mm3);
304         movq_r2r (mm2, mm6);
305         pxor_r2r (mm3, mm6);
306         pavg_r2r (mm1, mm0);
307         pavg_r2r (mm3, mm2);
308         por_r2r (mm6, mm7);
309         movq_r2r (mm0, mm6);
310         pxor_r2r (mm2, mm6);
311         pand_r2r (mm6, mm7);
312         pand_m2r (mask_one, mm7);
313         pavg_r2r (mm2, mm0);
314         psubusb_r2r (mm7, mm0);
315         movq_m2r (*dest, mm1);
316         pavg_r2r (mm1, mm0);
317         ref += stride;
318         movq_r2m (mm0, *dest);
319         dest += stride;
320     } while (--height);
321 }
322
323 static __inline__ void MC_avg4_16 (int height, yuv_data_t * dest, yuv_data_t * ref,
324                                int stride, int cpu)
325 {
326     do {
327         movq_m2r (*ref, mm0);
328         movq_m2r (*(ref+stride+1), mm1);
329         movq_r2r (mm0, mm7);
330         movq_m2r (*(ref+1), mm2);
331         pxor_r2r (mm1, mm7);
332         movq_m2r (*(ref+stride), mm3);
333         movq_r2r (mm2, mm6);
334         pxor_r2r (mm3, mm6);
335         pavg_r2r (mm1, mm0);
336         pavg_r2r (mm3, mm2);
337         por_r2r (mm6, mm7);
338         movq_r2r (mm0, mm6);
339         pxor_r2r (mm2, mm6);
340         pand_r2r (mm6, mm7);
341         pand_m2r (mask_one, mm7);
342         pavg_r2r (mm2, mm0);
343         psubusb_r2r (mm7, mm0);
344         movq_m2r (*dest, mm1);
345         pavg_r2r (mm1, mm0);
346         movq_r2m (mm0, *dest);
347
348         movq_m2r (*(ref+8), mm0);
349         movq_m2r (*(ref+stride+9), mm1);
350         movq_r2r (mm0, mm7);
351         movq_m2r (*(ref+9), mm2);
352         pxor_r2r (mm1, mm7);
353         movq_m2r (*(ref+stride+8), mm3);
354         movq_r2r (mm2, mm6);
355         pxor_r2r (mm3, mm6);
356         pavg_r2r (mm1, mm0);
357         pavg_r2r (mm3, mm2);
358         por_r2r (mm6, mm7);
359         movq_r2r (mm0, mm6);
360         pxor_r2r (mm2, mm6);
361         pand_r2r (mm6, mm7);
362         pand_m2r (mask_one, mm7);
363         pavg_r2r (mm2, mm0);
364         psubusb_r2r (mm7, mm0);
365         movq_m2r (*(dest+8), mm1);
366         pavg_r2r (mm1, mm0);
367         ref += stride;
368         movq_r2m (mm0, *(dest+8));
369         dest += stride;
370     } while (--height);
371 }
372
373 static void MC_avg_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
374                               int stride, int height)
375 {
376     MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
377 }
378
379 static void MC_avg_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
380                              int stride, int height)
381 {
382     MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
383 }
384
385 static void MC_put_16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
386                               int stride, int height)
387 {
388     MC_put1_16 (height, dest, ref, stride);
389 }
390
391 static void MC_put_8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
392                              int stride, int height)
393 {
394     MC_put1_8 (height, dest, ref, stride);
395 }
396
397 static void MC_avg_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
398                                int stride, int height)
399 {
400     MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
401 }
402
403 static void MC_avg_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
404                               int stride, int height)
405 {
406     MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
407 }
408
409 static void MC_put_x16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
410                                int stride, int height)
411 {
412     MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
413 }
414
415 static void MC_put_x8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
416                               int stride, int height)
417 {
418     MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
419 }
420
421 static void MC_avg_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
422                                int stride, int height)
423 {
424     MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
425 }
426
427 static void MC_avg_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
428                               int stride, int height)
429 {
430     MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
431 }
432
433 static void MC_put_y16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
434                                int stride, int height)
435 {
436     MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
437 }
438
439 static void MC_put_y8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
440                               int stride, int height)
441 {
442     MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
443 }
444
445 static void MC_avg_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
446                                 int stride, int height)
447 {
448     MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
449 }
450
451 static void MC_avg_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
452                                int stride, int height)
453 {
454     MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
455 }
456
457 static void MC_put_xy16_mmxext (yuv_data_t * dest, yuv_data_t * ref,
458                                 int stride, int height)
459 {
460     MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
461 }
462
463 static void MC_put_xy8_mmxext (yuv_data_t * dest, yuv_data_t * ref,
464                                int stride, int height)
465 {
466     MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
467 }
468
469
470 static void MC_avg_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
471                               int stride, int height)
472 {
473     MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
474 }
475
476 static void MC_avg_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
477                              int stride, int height)
478 {
479     MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
480 }
481
482 static void MC_put_16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
483                               int stride, int height)
484 {
485     MC_put1_16 (height, dest, ref, stride);
486 }
487
488 static void MC_put_8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
489                              int stride, int height)
490 {
491     MC_put1_8 (height, dest, ref, stride);
492 }
493
494 static void MC_avg_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
495                                int stride, int height)
496 {
497     MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
498 }
499
500 static void MC_avg_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
501                               int stride, int height)
502 {
503     MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
504 }
505
506 static void MC_put_x16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
507                                int stride, int height)
508 {
509     MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
510 }
511
512 static void MC_put_x8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
513                               int stride, int height)
514 {
515     MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
516 }
517
518 static void MC_avg_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
519                                int stride, int height)
520 {
521     MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
522 }
523
524 static void MC_avg_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
525                               int stride, int height)
526 {
527     MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
528 }
529
530 static void MC_put_y16_3dnow (yuv_data_t * dest, yuv_data_t * ref,
531                                int stride, int height)
532 {
533     MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
534 }
535
536 static void MC_put_y8_3dnow (yuv_data_t * dest, yuv_data_t * ref,
537                               int stride, int height)
538 {
539     MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
540 }
541
542 /*****************************************************************************
543  * Functions exported as capabilities. They are declared as static so that
544  * we don't pollute the namespace too much.
545  *****************************************************************************/
546 static void motion_getfunctions( function_list_t * p_function_list )
547 {
548     static void (* ppppf_motion[2][2][4])( yuv_data_t *, yuv_data_t *,
549                                            int, int ) =
550     {
551         {
552             /* Copying functions */
553             {
554                 /* Width == 16 */
555                 MC_put_16_mmxext, MC_put_x16_mmxext, MC_put_y16_mmxext, MC_put_xy16_mmxext
556             },
557             {
558                 /* Width == 8 */
559                 MC_put_8_mmxext,  MC_put_x8_mmxext,  MC_put_y8_mmxext, MC_put_xy8_mmxext
560             }
561         },
562         {
563             /* Averaging functions */
564             {
565                 /* Width == 16 */
566                 MC_avg_16_mmxext, MC_avg_x16_mmxext, MC_avg_y16_mmxext, MC_avg_xy16_mmxext
567             },
568             {
569                 /* Width == 8 */
570                 MC_avg_8_mmxext,  MC_avg_x8_mmxext,  MC_avg_y8_mmxext,  MC_avg_xy8_mmxext
571             }
572         }
573     };
574
575     p_function_list->pf_probe = motion_Probe;
576
577 #define list p_function_list->functions.motion
578     memcpy( list.ppppf_motion, ppppf_motion, sizeof( void * ) * 16 );
579 #undef list
580
581     return;
582 }
583