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