mmx/prefetch implementation of plane_copy
[x262.git] / common / i386 / mc-c.c
1 /*****************************************************************************
2  * mc.c: h264 encoder library (Motion Compensation)
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: mc-c.c,v 1.5 2004/06/18 01:59:58 chenm001 Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "common/common.h"
29
30 /* NASM functions */
31 extern void x264_pixel_avg_w4_mmxext( uint8_t *,  int, uint8_t *, int, uint8_t *, int, int );
32 extern void x264_pixel_avg_w8_mmxext( uint8_t *,  int, uint8_t *, int, uint8_t *, int, int );
33 extern void x264_pixel_avg_w16_mmxext( uint8_t *,  int, uint8_t *, int, uint8_t *, int, int );
34 extern void x264_pixel_avg_w16_sse2( uint8_t *,  int, uint8_t *, int, uint8_t *, int, int );
35 extern void x264_pixel_avg_weight_4x4_mmxext( uint8_t *, int, uint8_t *, int, int );
36 extern void x264_pixel_avg_weight_w8_mmxext( uint8_t *, int, uint8_t *, int, int, int );
37 extern void x264_pixel_avg_weight_w16_mmxext( uint8_t *, int, uint8_t *, int, int, int );
38 extern void x264_mc_copy_w4_mmx( uint8_t *, int, uint8_t *, int, int );
39 extern void x264_mc_copy_w8_mmx( uint8_t *, int, uint8_t *, int, int );
40 extern void x264_mc_copy_w16_mmx( uint8_t *, int, uint8_t *, int, int );
41 extern void x264_mc_copy_w16_sse2( uint8_t *, int, uint8_t *, int, int );
42 extern void x264_plane_copy_mmxext( uint8_t *, int, uint8_t *, int, int w, int h);
43
44 #define AVG(W,H) \
45 static void x264_pixel_avg_ ## W ## x ## H ## _mmxext( uint8_t *dst, int i_dst, uint8_t *src, int i_src ) \
46 { \
47     x264_pixel_avg_w ## W ## _mmxext( dst, i_dst, dst, i_dst, src, i_src, H ); \
48 }
49 AVG(16,16)
50 AVG(16,8)
51 AVG(8,16)
52 AVG(8,8)
53 AVG(8,4)
54 AVG(4,8)
55 AVG(4,4)
56 AVG(4,2)
57
58 #define AVG_WEIGHT(W,H) \
59 void x264_pixel_avg_weight_ ## W ## x ## H ## _mmxext( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_weight_dst ) \
60 { \
61     x264_pixel_avg_weight_w ## W ## _mmxext( dst, i_dst, src, i_src, i_weight_dst, H ); \
62 }
63 AVG_WEIGHT(16,16)
64 AVG_WEIGHT(16,8)
65 AVG_WEIGHT(8,16)
66 AVG_WEIGHT(8,8)
67 AVG_WEIGHT(8,4)
68
69 static void (* const x264_pixel_avg_wtab_mmxext[5])( uint8_t *, int, uint8_t *, int, uint8_t *, int, int ) =
70 {
71     NULL,
72     x264_pixel_avg_w4_mmxext,
73     x264_pixel_avg_w8_mmxext,
74     NULL,
75     x264_pixel_avg_w16_mmxext
76 };
77 static void (* const x264_mc_copy_wtab_mmx[5])( uint8_t *, int, uint8_t *, int, int ) =
78 {
79     NULL,
80     x264_mc_copy_w4_mmx,
81     x264_mc_copy_w8_mmx,
82     NULL,
83     x264_mc_copy_w16_mmx
84 };
85 static const int hpel_ref0[16] = {0,1,1,1,0,1,1,1,2,3,3,3,0,1,1,1};
86 static const int hpel_ref1[16] = {0,0,0,0,2,2,3,2,2,2,3,2,2,2,3,2};
87
88 void mc_luma_mmx( uint8_t *src[4], int i_src_stride,
89                   uint8_t *dst,    int i_dst_stride,
90                   int mvx,int mvy,
91                   int i_width, int i_height )
92 {
93     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
94     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
95     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
96
97     if( qpel_idx & 5 ) /* qpel interpolation needed */
98     {
99         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
100         x264_pixel_avg_wtab_mmxext[i_width>>2](
101                 dst, i_dst_stride, src1, i_src_stride,
102                 src2, i_src_stride, i_height );
103     }
104     else
105     {
106         x264_mc_copy_wtab_mmx[i_width>>2](
107                 dst, i_dst_stride, src1, i_src_stride, i_height );
108     }
109 }
110
111 uint8_t *get_ref_mmx( uint8_t *src[4], int i_src_stride,
112                       uint8_t *dst,   int *i_dst_stride,
113                       int mvx,int mvy,
114                       int i_width, int i_height )
115 {
116     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
117     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
118     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
119
120     if( qpel_idx & 5 ) /* qpel interpolation needed */
121     {
122         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
123         x264_pixel_avg_wtab_mmxext[i_width>>2](
124                 dst, *i_dst_stride, src1, i_src_stride,
125                 src2, i_src_stride, i_height );
126         return dst;
127
128     }
129     else
130     {
131         *i_dst_stride = i_src_stride;
132         return src1;
133     }
134 }
135
136
137 void x264_mc_mmxext_init( x264_mc_functions_t *pf )
138 {
139     pf->mc_luma   = mc_luma_mmx;
140     pf->get_ref   = get_ref_mmx;
141
142     pf->avg[PIXEL_16x16] = x264_pixel_avg_16x16_mmxext;
143     pf->avg[PIXEL_16x8]  = x264_pixel_avg_16x8_mmxext;
144     pf->avg[PIXEL_8x16]  = x264_pixel_avg_8x16_mmxext;
145     pf->avg[PIXEL_8x8]   = x264_pixel_avg_8x8_mmxext;
146     pf->avg[PIXEL_8x4]   = x264_pixel_avg_8x4_mmxext;
147     pf->avg[PIXEL_4x8]   = x264_pixel_avg_4x8_mmxext;
148     pf->avg[PIXEL_4x4]   = x264_pixel_avg_4x4_mmxext;
149     pf->avg[PIXEL_4x2]   = x264_pixel_avg_4x2_mmxext;
150     
151     pf->avg_weight[PIXEL_16x16] = x264_pixel_avg_weight_16x16_mmxext;
152     pf->avg_weight[PIXEL_16x8]  = x264_pixel_avg_weight_16x8_mmxext;
153     pf->avg_weight[PIXEL_8x16]  = x264_pixel_avg_weight_8x16_mmxext;
154     pf->avg_weight[PIXEL_8x8]   = x264_pixel_avg_weight_8x8_mmxext;
155     pf->avg_weight[PIXEL_8x4]   = x264_pixel_avg_weight_8x4_mmxext;
156     pf->avg_weight[PIXEL_4x4]   = x264_pixel_avg_weight_4x4_mmxext;
157     // avg_weight_4x8 is rare and 4x2 is not used
158
159     pf->copy[PIXEL_16x16] = x264_mc_copy_w16_mmx;
160     pf->copy[PIXEL_8x8]   = x264_mc_copy_w8_mmx;
161     pf->copy[PIXEL_4x4]   = x264_mc_copy_w4_mmx;
162
163     pf->plane_copy = x264_plane_copy_mmxext;
164 }
165 void x264_mc_sse2_init( x264_mc_functions_t *pf )
166 {
167     /* todo: use sse2 */
168     pf->mc_luma   = mc_luma_mmx;
169     pf->get_ref   = get_ref_mmx;
170 }