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