4cee0acbb64d1c365a1139d30335a0b551b1809f
[platform/upstream/gst-plugins-good.git] / gst / goom / mmx.c
1 #include "config.h"
2
3 #if defined (HAVE_CPU_I386) || defined (HAVE_CPU_X86_64)
4
5 #define BUFFPOINTNB 16
6 #define BUFFPOINTMASK 0xffff
7 #define BUFFINCR 0xff
8
9 #include "mmx.h"
10 #include "goom_graphic.h"
11
12 #define sqrtperte 16
13 // faire : a % sqrtperte <=> a & pertemask
14 #define PERTEMASK 0xf
15 // faire : a / sqrtperte <=> a >> PERTEDEC
16 #define PERTEDEC 4
17
18 int
19 mmx_supported (void)
20 {
21   return (mm_support () & 0x1);
22 }
23
24 void
25 zoom_filter_mmx (int prevX, int prevY,
26     Pixel * expix1, Pixel * expix2,
27     int *brutS, int *brutD, int buffratio, int precalCoef[16][16])
28 {
29   unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
30
31   int bufsize = prevX * prevY;
32   int loop;
33
34   __asm__ __volatile__ ("pxor %mm7,%mm7");
35
36   for (loop = 0; loop < bufsize; loop++) {
37     /*      int couleur; */
38     int px, py;
39     int pos;
40     int coeffs;
41
42     int myPos = loop << 1, myPos2 = myPos + 1;
43     int brutSmypos = brutS[myPos];
44
45     px = brutSmypos + (((brutD[myPos] -
46                 brutSmypos) * buffratio) >> BUFFPOINTNB);
47     brutSmypos = brutS[myPos2];
48     py = brutSmypos + (((brutD[myPos2] -
49                 brutSmypos) * buffratio) >> BUFFPOINTNB);
50
51     if ((py >= ay) || (px >= ax)) {
52       pos = coeffs = 0;
53     } else {
54       pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
55       // coef en modulo 15
56       coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
57     }
58
59     __asm__ __volatile__ ("movd %2, %%mm6 \n\t"
60         /* recuperation des deux premiers pixels dans mm0 et mm1 */
61         "movq (%3,%1,4), %%mm0 \n\t"    /* b1-v1-r1-a1-b2-v2-r2-a2 */
62         "movq %%mm0, %%mm1 \n\t"        /* b1-v1-r1-a1-b2-v2-r2-a2 */
63         /* depackage du premier pixel */
64         "punpcklbw %%mm7, %%mm0 \n\t"   /* 00-b2-00-v2-00-r2-00-a2 */
65         "movq %%mm6, %%mm5 \n\t"        /* ??-??-??-??-c4-c3-c2-c1 */
66         /* depackage du 2ieme pixel */
67         "punpckhbw %%mm7, %%mm1 \n\t"   /* 00-b1-00-v1-00-r1-00-a1 */
68         /* extraction des coefficients... */
69         "punpcklbw %%mm5, %%mm6 \n\t"   /* c4-c4-c3-c3-c2-c2-c1-c1 */
70         "movq %%mm6, %%mm4 \n\t"        /* c4-c4-c3-c3-c2-c2-c1-c1 */
71         "movq %%mm6, %%mm5 \n\t"        /* c4-c4-c3-c3-c2-c2-c1-c1 */
72         "punpcklbw %%mm5, %%mm6 \n\t"   /* c2-c2-c2-c2-c1-c1-c1-c1 */
73         "punpckhbw %%mm5, %%mm4 \n\t"   /* c4-c4-c4-c4-c3-c3-c3-c3 */
74         "movq %%mm6, %%mm3 \n\t"        /* c2-c2-c2-c2-c1-c1-c1-c1 */
75         "punpcklbw %%mm7, %%mm6 \n\t"   /* 00-c1-00-c1-00-c1-00-c1 */
76         "punpckhbw %%mm7, %%mm3 \n\t"   /* 00-c2-00-c2-00-c2-00-c2 */
77         /* multiplication des pixels par les coefficients */
78         "pmullw %%mm6, %%mm0 \n\t"      /* c1*b2-c1*v2-c1*r2-c1*a2 */
79         "pmullw %%mm3, %%mm1 \n\t"      /* c2*b1-c2*v1-c2*r1-c2*a1 */
80         "paddw %%mm1, %%mm0 \n\t"
81         /* ...extraction des 2 derniers coefficients */
82         "movq %%mm4, %%mm5 \n\t"        /* c4-c4-c4-c4-c3-c3-c3-c3 */
83         "punpcklbw %%mm7, %%mm4 \n\t"   /* 00-c3-00-c3-00-c3-00-c3 */
84         "punpckhbw %%mm7, %%mm5 \n\t"   /* 00-c4-00-c4-00-c4-00-c4 */
85         /* ajouter la longueur de ligne a esi */
86         "addl 8(%%ebp),%1 \n\t"
87         /* recuperation des 2 derniers pixels */
88         "movq (%3,%1,4), %%mm1 \n\t" "movq %%mm1, %%mm2 \n\t"
89         /* depackage des pixels */
90         "punpcklbw %%mm7, %%mm1 \n\t" "punpckhbw %%mm7, %%mm2 \n\t"
91         /* multiplication pas les coeffs */
92         "pmullw %%mm4, %%mm1 \n\t" "pmullw %%mm5, %%mm2 \n\t"
93         /* ajout des valeurs obtenues ? la valeur finale */
94         "paddw %%mm1, %%mm0 \n\t" "paddw %%mm2, %%mm0 \n\t"
95         /* division par 256 = 16+16+16+16, puis repackage du pixel final */
96         "psrlw $8, %%mm0 \n\t"
97         "packuswb %%mm7, %%mm0 \n\t" "movd %%mm0,%0 \n\t":"=g" (expix2[loop])
98         :"r" (pos), "r" (coeffs), "r" (expix1)
99
100         );
101
102     emms ();
103   }
104 }
105
106 #define DRAWMETHOD_PLUS_MMX(_out,_backbuf,_col) \
107 { \
108         movd_m2r(_backbuf, mm0); \
109         paddusb_m2r(_col, mm0); \
110         movd_r2m(mm0, _out); \
111 }
112
113 #define DRAWMETHOD DRAWMETHOD_PLUS_MMX(*p,*p,col)
114
115 void
116 draw_line_mmx (Pixel * data, int x1, int y1, int x2, int y2, int col,
117     int screenx, int screeny)
118 {
119   int x, y, dx, dy, yy, xx;
120   Pixel *p;
121
122   if ((y1 < 0) || (y2 < 0) || (x1 < 0) || (x2 < 0) || (y1 >= screeny)
123       || (y2 >= screeny) || (x1 >= screenx) || (x2 >= screenx))
124     goto end_of_line;
125
126   dx = x2 - x1;
127   dy = y2 - y1;
128   if (x1 >= x2) {
129     int tmp;
130
131     tmp = x1;
132     x1 = x2;
133     x2 = tmp;
134     tmp = y1;
135     y1 = y2;
136     y2 = tmp;
137     dx = x2 - x1;
138     dy = y2 - y1;
139   }
140
141   /* vertical line */
142   if (dx == 0) {
143     if (y1 < y2) {
144       p = &(data[(screenx * y1) + x1]);
145       for (y = y1; y <= y2; y++) {
146         DRAWMETHOD;
147         p += screenx;
148       }
149     } else {
150       p = &(data[(screenx * y2) + x1]);
151       for (y = y2; y <= y1; y++) {
152         DRAWMETHOD;
153         p += screenx;
154       }
155     }
156     goto end_of_line;
157   }
158   /* horizontal line */
159   if (dy == 0) {
160     if (x1 < x2) {
161       p = &(data[(screenx * y1) + x1]);
162       for (x = x1; x <= x2; x++) {
163         DRAWMETHOD;
164         p++;
165       }
166       goto end_of_line;
167     } else {
168       p = &(data[(screenx * y1) + x2]);
169       for (x = x2; x <= x1; x++) {
170         DRAWMETHOD;
171         p++;
172       }
173       goto end_of_line;
174     }
175   }
176   /* 1    */
177   /*  \   */
178   /*   \  */
179   /*    2 */
180   if (y2 > y1) {
181     /* steep */
182     if (dy > dx) {
183       dx = ((dx << 16) / dy);
184       x = x1 << 16;
185       for (y = y1; y <= y2; y++) {
186         xx = x >> 16;
187         p = &(data[(screenx * y) + xx]);
188         DRAWMETHOD;
189         if (xx < (screenx - 1)) {
190           p++;
191           /* DRAWMETHOD; */
192         }
193         x += dx;
194       }
195       goto end_of_line;
196     }
197     /* shallow */
198     else {
199       dy = ((dy << 16) / dx);
200       y = y1 << 16;
201       for (x = x1; x <= x2; x++) {
202         yy = y >> 16;
203         p = &(data[(screenx * yy) + x]);
204         DRAWMETHOD;
205         if (yy < (screeny - 1)) {
206           p += screeny;
207           /* DRAWMETHOD; */
208         }
209         y += dy;
210       }
211     }
212   }
213   /*    2 */
214   /*   /  */
215   /*  /   */
216   /* 1    */
217   else {
218     /* steep */
219     if (-dy > dx) {
220       dx = ((dx << 16) / -dy);
221       x = (x1 + 1) << 16;
222       for (y = y1; y >= y2; y--) {
223         xx = x >> 16;
224         p = &(data[(screenx * y) + xx]);
225         DRAWMETHOD;
226         if (xx < (screenx - 1)) {
227           p--;
228           /* DRAWMETHOD; */
229         }
230         x += dx;
231       }
232       goto end_of_line;
233     }
234     /* shallow */
235     else {
236       dy = ((dy << 16) / dx);
237       y = y1 << 16;
238       for (x = x1; x <= x2; x++) {
239         yy = y >> 16;
240         p = &(data[(screenx * yy) + x]);
241         DRAWMETHOD;
242         if (yy < (screeny - 1)) {
243           p += screeny;
244           /* DRAWMETHOD; */
245         }
246         y += dy;
247       }
248       goto end_of_line;
249     }
250   }
251 end_of_line:
252   emms ();
253   /* __asm__ __volatile__ ("emms"); */
254 }
255
256 #endif /* HAVE_CPU_I386 || HAVE_CPU_X86_64 */