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