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