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