configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new...
[platform/upstream/gst-plugins-good.git] / gst / goom / xmmx.c
1
2 #ifdef HAVE_MMX
3
4 /* a definir pour avoir exactement le meme resultat que la fonction C
5  * (un chouillat plus lent).. mais la difference est assez peu notable.
6  */
7 // #define STRICT_COMPAT
8
9 #define BUFFPOINTNB 16
10 #define BUFFPOINTMASK 0xffff
11 #define BUFFINCR 0xff
12
13 #define sqrtperte 16
14 /* faire : a % sqrtperte <=> a & pertemask*/
15 #define PERTEMASK 0xf
16 /* faire : a / sqrtperte <=> a >> PERTEDEC*/
17 #define PERTEDEC 4
18
19
20 /*#define MMX_TRACE*/
21 #include "mmx.h"
22 /*#include "xmmx.h"*/
23 #include "goom_graphic.h"
24
25 int
26 xmmx_supported (void)
27 {
28   return (mm_support () & 0x8) >> 3;
29 }
30
31 void
32 zoom_filter_xmmx (int prevX, int prevY,
33     Pixel * expix1, Pixel * expix2,
34     int *lbruS, int *lbruD, int buffratio, int precalCoef[16][16])
35 {
36   int bufsize = prevX * prevY;  /* taille du buffer */
37   volatile int loop;            /* variable de boucle */
38
39   mmx_t *brutS = (mmx_t *) lbruS;       /* buffer de transformation source */
40   mmx_t *brutD = (mmx_t *) lbruD;       /* buffer de transformation dest */
41
42   volatile mmx_t prevXY;
43   volatile mmx_t ratiox;
44
45   /*      volatile mmx_t interpix; */
46
47   expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
48       expix1[prevX * prevY - prevX].val = 0;
49
50   prevXY.ud[0] = (prevX - 1) << PERTEDEC;
51   prevXY.ud[1] = (prevY - 1) << PERTEDEC;
52
53   ratiox.d[0] = buffratio;
54   ratiox.d[1] = buffratio;
55
56   asm volatile ("\n\t movq  %[ratio], %%mm6" "\n\t pslld $16,      %%mm6"       /* mm6 = [rat16=buffratio<<16 | rat16=buffratio<<16] */
57       "\n\t pxor  %%mm7,    %%mm7"      /* mm7 = 0 */
58       ::[ratio] "m" (ratiox));
59
60   loop = 0;
61
62   /*
63    * NOTE : mm6 et mm7 ne sont pas modifies dans la boucle.
64    */
65   while (loop < bufsize) {
66     /* Thread #1
67      * pre :  mm6 = [rat16|rat16]
68      * post : mm0 = S + ((D-S)*rat16 format [X|Y]
69      * modified = mm0,mm1,mm2
70      */
71
72     asm volatile ("#1 \n\t movq %[brutS], %%mm0" "#1 \n\t movq %[brutD], %%mm1" "#1 \n\t psubd   %%mm0, %%mm1"  /* mm1 = D - S */
73         "#1 \n\t movq    %%mm1, %%mm2"  /* mm2 = D - S */
74         "#1 \n\t pslld     $16, %%mm1" "#1 \n\t pmullw  %%mm6, %%mm2" "#1 \n\t pmulhuw %%mm6, %%mm1" "#1 \n\t pslld   $16,   %%mm0" "#1 \n\t paddd   %%mm2, %%mm1"      /* mm1 = (D - S) * buffratio >> 16 */
75         "#1 \n\t paddd   %%mm1, %%mm0"  /* mm0 = S + mm1 */
76         "#1 \n\t psrld   $16,   %%mm0"::[brutS] "g" (brutS[loop])
77         ,[brutD] "g" (brutD[loop])
78         );                      /* mm0 = S */
79
80     /*
81      * pre : mm0 : position vector on screen
82      *       prevXY : coordinate of the lower-right point on screen
83      * post : clipped mm0
84      * modified : mm0,mm1,mm2
85      */
86     asm volatile
87         ("#1 \n\t movq %[prevXY], %%mm1" "#1 \n\t pcmpgtd %%mm0,  %%mm1"
88         /* mm0 en X contient (idem pour Y) :
89          *   1111 si prevXY > px
90          *   0000 si prevXY <= px */
91 #ifdef STRICT_COMPAT
92         "#1 \n\t movq      %%mm1, %%mm2"
93         "#1 \n\t punpckhdq %%mm2, %%mm2"
94         "#1 \n\t punpckldq %%mm1, %%mm1" "#1 \n\t pand      %%mm2, %%mm0"
95 #endif
96         "#1 \n\t pand %%mm1, %%mm0"     /* on met a zero la partie qui deborde */
97         ::[prevXY] "m" (prevXY));
98
99     /* Thread #2
100      * pre :  mm0 : clipped position on screen
101      *
102      * post : mm3 : coefs for this position
103      *        mm1 : X vector [0|X]
104      *
105      * modif : eax,esi
106      */
107     __asm__ __volatile__ ("#2 \n\t movd %%mm0,%%esi"
108         "#2 \n\t movq %%mm0,%%mm1"
109         "#2 \n\t andl $15,%%esi"
110         "#2 \n\t psrlq $32,%%mm1"
111         "#2 \n\t shll $6,%%esi"
112         "#2 \n\t movd %%mm1,%%eax"
113         "#2 \n\t addl %[precalCoef],%%esi"
114         "#2 \n\t andl $15,%%eax"
115         "#2 \n\t movd (%%esi,%%eax,4),%%mm3"::[precalCoef]
116         "g" (precalCoef):"eax", "esi");
117
118     /*
119      * extraction des coefficients... (Thread #3)
120      *
121      * pre : coef dans mm3
122      *
123      * post : coef extraits dans mm3 (c1 & c2)
124      *                        et mm4 (c3 & c4)
125      *
126      * modif : mm5
127      */
128
129     /* (Thread #4)
130      * pre : mm0 : Y pos [*|Y]
131      *       mm1 : X pos [*|X]
132      *
133      * post : mm0 : expix1[position]
134      *        mm2 : expix1[position+largeur]
135      *
136      * modif : eax, esi
137      */
138     __asm__ __volatile__ ("#2 \n\t psrld $4, %%mm0" "#2 \n\t psrld $4, %%mm1"   /* PERTEDEC = $4 */
139         "#4 \n\t movd %%mm1,%%eax"
140         "#3 \n\t movq %%mm3,%%mm5"
141         "#4 \n\t mull %[prevX]"
142         "#4 \n\t movd %%mm0,%%esi"
143         "#3 \n\t punpcklbw %%mm5, %%mm3"
144         "#4 \n\t addl %%esi, %%eax"
145         "#3 \n\t movq %%mm3, %%mm4"
146         "#3 \n\t movq %%mm3, %%mm5"
147         "#4 \n\t movl %[expix1], %%esi"
148         "#3 \n\t punpcklbw %%mm5, %%mm3"
149         "#4 \n\t movq (%%esi,%%eax,4),%%mm0"
150         "#3 \n\t punpckhbw %%mm5, %%mm4"
151         "#4 \n\t addl %[prevX],%%eax"
152         "#4 \n\t movq (%%esi,%%eax,4),%%mm2"::[expix1] "g" (expix1)
153         ,[prevX] "g" (prevX)
154         :"eax", "esi");
155
156     /*
157      * pre :       mm0 : expix1[position]
158      *             mm2 : expix1[position+largeur]
159      *       mm3 & mm4 : coefs
160      */
161
162     /* recopie des deux premiers pixels dans mm0 et mm1 */
163     movq_r2r (mm0, mm1);        /* b1-v1-r1-a1-b2-v2-r2-a2 */
164
165     /* depackage du premier pixel */
166     punpcklbw_r2r (mm7, mm0);   /* 00-b2-00-v2-00-r2-00-a2 */
167
168     /* extraction des coefficients... */
169
170     movq_r2r (mm3, mm5);        /* c2-c2-c2-c2-c1-c1-c1-c1 */
171
172     /*^en parrallele^ *//* depackage du 2ieme pixel */
173                                         /*^ */ punpckhbw_r2r (mm7, mm1);
174                                         /* 00-b1-00-v1-00-r1-00-a1 */
175
176     punpcklbw_r2r (mm7, mm5);   /* 00-c1-00-c1-00-c1-00-c1 */
177     punpckhbw_r2r (mm7, mm3);   /* 00-c2-00-c2-00-c2-00-c2 */
178
179     /* multiplication des pixels par les coefficients */
180     pmullw_r2r (mm5, mm0);      /* c1*b2-c1*v2-c1*r2-c1*a2 */
181     pmullw_r2r (mm3, mm1);      /* c2*b1-c2*v1-c2*r1-c2*a1 */
182     paddw_r2r (mm1, mm0);
183
184     /* ...extraction des 2 derniers coefficients */
185     movq_r2r (mm4, mm5);        /* c4-c4-c4-c4-c3-c3-c3-c3 */
186     punpcklbw_r2r (mm7, mm4);   /* 00-c3-00-c3-00-c3-00-c3 */
187     punpckhbw_r2r (mm7, mm5);   /* 00-c4-00-c4-00-c4-00-c4 */
188
189     /* recuperation des 2 derniers pixels */
190     movq_r2r (mm2, mm1);
191
192     /* depackage des pixels */
193     punpcklbw_r2r (mm7, mm1);
194     punpckhbw_r2r (mm7, mm2);
195
196     /* multiplication pas les coeffs */
197     pmullw_r2r (mm4, mm1);
198     pmullw_r2r (mm5, mm2);
199
200     /* ajout des valeurs obtenues à la valeur finale */
201     paddw_r2r (mm1, mm0);
202     paddw_r2r (mm2, mm0);
203
204     /* division par 256 = 16+16+16+16, puis repackage du pixel final */
205     psrlw_i2r (8, mm0);
206     packuswb_r2r (mm7, mm0);
207
208     movd_r2m (mm0, expix2[loop]);
209
210     ++loop;
211   }
212   __asm__ __volatile__ ("femms\n");
213 }
214
215 #define DRAWMETHOD_PLUS_XMMX(_out,_backbuf,_col) \
216 { \
217         movd_m2r(_backbuf, mm0); \
218         paddusb_m2r(_col, mm0); \
219         movd_r2m(mm0, _out); \
220 }
221
222 #define DRAWMETHOD DRAWMETHOD_PLUS_XMMX(*p,*p,col)
223
224 void
225 draw_line_xmmx (Pixel * data, int x1, int y1, int x2, int y2, int col,
226     int screenx, int screeny)
227 {
228   int x, y, dx, dy, yy, xx;
229   Pixel *p;
230
231   if ((y1 < 0) || (y2 < 0) || (x1 < 0) || (x2 < 0) || (y1 >= screeny)
232       || (y2 >= screeny) || (x1 >= screenx) || (x2 >= screenx))
233     goto end_of_line;
234
235   dx = x2 - x1;
236   dy = y2 - y1;
237   if (x1 >= x2) {
238     int tmp;
239
240     tmp = x1;
241     x1 = x2;
242     x2 = tmp;
243     tmp = y1;
244     y1 = y2;
245     y2 = tmp;
246     dx = x2 - x1;
247     dy = y2 - y1;
248   }
249
250   /* vertical line */
251   if (dx == 0) {
252     if (y1 < y2) {
253       p = &(data[(screenx * y1) + x1]);
254       for (y = y1; y <= y2; y++) {
255         DRAWMETHOD;
256         p += screenx;
257       }
258     } else {
259       p = &(data[(screenx * y2) + x1]);
260       for (y = y2; y <= y1; y++) {
261         DRAWMETHOD;
262         p += screenx;
263       }
264     }
265     goto end_of_line;
266   }
267   /* horizontal line */
268   if (dy == 0) {
269     if (x1 < x2) {
270       p = &(data[(screenx * y1) + x1]);
271       for (x = x1; x <= x2; x++) {
272         DRAWMETHOD;
273         p++;
274       }
275       goto end_of_line;
276     } else {
277       p = &(data[(screenx * y1) + x2]);
278       for (x = x2; x <= x1; x++) {
279         DRAWMETHOD;
280         p++;
281       }
282       goto end_of_line;
283     }
284   }
285   /* 1    */
286   /*  \   */
287   /*   \  */
288   /*    2 */
289   if (y2 > y1) {
290     /* steep */
291     if (dy > dx) {
292       dx = ((dx << 16) / dy);
293       x = x1 << 16;
294       for (y = y1; y <= y2; y++) {
295         xx = x >> 16;
296         p = &(data[(screenx * y) + xx]);
297         DRAWMETHOD;
298         if (xx < (screenx - 1)) {
299           p++;
300           /* DRAWMETHOD; */
301         }
302         x += dx;
303       }
304       goto end_of_line;
305     }
306     /* shallow */
307     else {
308       dy = ((dy << 16) / dx);
309       y = y1 << 16;
310       for (x = x1; x <= x2; x++) {
311         yy = y >> 16;
312         p = &(data[(screenx * yy) + x]);
313         DRAWMETHOD;
314         if (yy < (screeny - 1)) {
315           p += screeny;
316           /* DRAWMETHOD; */
317         }
318         y += dy;
319       }
320     }
321   }
322   /*    2 */
323   /*   /  */
324   /*  /   */
325   /* 1    */
326   else {
327     /* steep */
328     if (-dy > dx) {
329       dx = ((dx << 16) / -dy);
330       x = (x1 + 1) << 16;
331       for (y = y1; y >= y2; y--) {
332         xx = x >> 16;
333         p = &(data[(screenx * y) + xx]);
334         DRAWMETHOD;
335         if (xx < (screenx - 1)) {
336           p--;
337           /* DRAWMETHOD; */
338         }
339         x += dx;
340       }
341       goto end_of_line;
342     }
343     /* shallow */
344     else {
345       dy = ((dy << 16) / dx);
346       y = y1 << 16;
347       for (x = x1; x <= x2; x++) {
348         yy = y >> 16;
349         p = &(data[(screenx * yy) + x]);
350         DRAWMETHOD;
351         if (yy < (screeny - 1)) {
352           p += screeny;
353           /* DRAWMETHOD; */
354         }
355         y += dy;
356       }
357       goto end_of_line;
358     }
359   }
360 end_of_line:
361   __asm__ __volatile__ ("femms\n");
362 }
363
364 #endif