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