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