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