gst-indent
[platform/upstream/gst-plugins-good.git] / gst / goom / filters.c
1 /* filter.c version 0.7
2  * contient les filtres applicable a un buffer
3  * creation : 01/10/2000
4  *  -ajout de sinFilter()
5  *  -ajout de zoomFilter()
6  *  -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs
7  *  -optimisation de sinFilter (utilisant une table de sin)
8  *      -asm
9  *      -optimisation de la procedure de génération du buffer de transformation
10  *              la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
11 */
12
13 /*#define _DEBUG_PIXEL; */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #include "filters.h"
20 #include "graphic.h"
21 #include "goom_tools.h"
22 #include <stdlib.h>
23 #include <math.h>
24 #include <stdio.h>
25
26 #ifdef MMX
27 #define USE_ASM
28 #endif
29 #ifdef POWERPC
30 #define USE_ASM
31 #endif
32
33 #ifdef USE_ASM
34 #define EFFECT_DISTORS 4
35 #else
36 #define EFFECT_DISTORS 10
37 #endif
38
39
40 extern volatile guint32 resolx;
41 extern volatile guint32 resoly;
42
43 #ifdef USE_ASM
44
45 #ifdef MMX
46 int mmx_zoom ();
47 guint32 mmx_zoom_size;
48 #endif /* MMX */
49
50 #ifdef POWERPC
51 extern unsigned int useAltivec;
52 extern void ppc_zoom (void);
53 extern void ppc_zoom_altivec (void);
54 unsigned int ppcsize4;
55 #endif /* PowerPC */
56
57 unsigned int *coeffs = 0, *freecoeffs = 0;
58 guint32 *expix1 = 0;            /* pointeur exporte vers p1 */
59 guint32 *expix2 = 0;            /* pointeur exporte vers p2 */
60 guint32 zoom_width;
61
62 #endif /* ASM */
63
64
65 static int sintable[0xffff];
66 static int vitesse = 127;
67 static char theMode = AMULETTE_MODE;
68 static int vPlaneEffect = 0;
69 static int hPlaneEffect = 0;
70 static char noisify = 2;
71 static int middleX, middleY;
72 static unsigned char sqrtperte = 16;
73
74 static int *firedec = 0;
75
76
77 /* retourne x>>s , en testant le signe de x */
78 inline int
79 ShiftRight (int x, const unsigned char s)
80 {
81   if (x < 0)
82     return -(-x >> s);
83   else
84     return x >> s;
85 }
86
87 /*
88   calculer px et py en fonction de x,y,middleX,middleY et theMode
89   px et py indique la nouvelle position (en sqrtperte ieme de pixel)
90   (valeur * 16)
91 */
92 void
93 calculatePXandPY (int x, int y, int *px, int *py)
94 {
95   if (theMode == WATER_MODE) {
96     static int wave = 0;
97     static int wavesp = 0;
98     int yy;
99
100     yy = y + RAND () % 4 + wave / 10;
101     yy -= RAND () % 4;
102     if (yy < 0)
103       yy = 0;
104     if (yy >= resoly)
105       yy = resoly - 1;
106
107     *px = (x << 4) + firedec[yy] + (wave / 10);
108     *py = (y << 4) + 132 - ((vitesse < 132) ? vitesse : 131);
109
110     wavesp += RAND () % 3;
111     wavesp -= RAND () % 3;
112     if (wave < -10)
113       wavesp += 2;
114     if (wave > 10)
115       wavesp -= 2;
116     wave += (wavesp / 10) + RAND () % 3;
117     wave -= RAND () % 3;
118     if (wavesp > 100)
119       wavesp = (wavesp * 9) / 10;
120   } else {
121     int dist;
122     register int vx, vy;
123     int fvitesse = vitesse << 4;
124
125     if (noisify) {
126       x += RAND () % noisify;
127       x -= RAND () % noisify;
128       y += RAND () % noisify;
129       y -= RAND () % noisify;
130     }
131
132     if (hPlaneEffect)
133       vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY);
134     else
135       vx = (x - middleX) << 9;
136
137     if (vPlaneEffect)
138       vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX);
139     else
140       vy = (y - middleY) << 9;
141
142     switch (theMode) {
143       case WAVE_MODE:
144         dist =
145             ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
146             9) * ShiftRight (vy, 9);
147         fvitesse *=
148             1024 +
149             ShiftRight (sintable[(unsigned short) (0xffff * dist *
150                     EFFECT_DISTORS)], 6);
151         fvitesse /= 1024;
152         break;
153       case CRYSTAL_BALL_MODE:
154         dist =
155             ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
156             9) * ShiftRight (vy, 9);
157         fvitesse += (dist * EFFECT_DISTORS >> 10);
158         break;
159       case AMULETTE_MODE:
160         dist =
161             ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
162             9) * ShiftRight (vy, 9);
163         fvitesse -= (dist * EFFECT_DISTORS >> 4);
164         break;
165       case SCRUNCH_MODE:
166         dist =
167             ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
168             9) * ShiftRight (vy, 9);
169         fvitesse -= (dist * EFFECT_DISTORS >> 9);
170         break;
171     }
172     if (vx < 0)
173       *px = (middleX << 4) - (-(vx * fvitesse) >> 16);
174     else
175       *px = (middleX << 4) + ((vx * fvitesse) >> 16);
176     if (vy < 0)
177       *py = (middleY << 4) - (-(vy * fvitesse) >> 16);
178     else
179       *py = (middleY << 4) + ((vy * fvitesse) >> 16);
180   }
181 }
182
183 /*#define _DEBUG */
184
185 inline void
186 setPixelRGB (Uint * buffer, Uint x, Uint y, Color c)
187 {
188 /*              buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */
189 #ifdef _DEBUG_PIXEL
190   if (x + y * resolx >= resolx * resoly) {
191     fprintf (stderr, "setPixel ERROR : hors du tableau... %i, %i\n", x, y);
192     /*exit (1) ; */
193   }
194 #endif
195
196 #ifdef USE_DGA
197   buffer[y * resolx + x] = (c.b << 16) | (c.v << 8) | c.r;
198 #else
199   buffer[y * resolx + x] = (c.r << 16) | (c.v << 8) | c.b;
200 #endif
201 }
202
203
204 inline void
205 setPixelRGB_ (Uint * buffer, Uint x, Color c)
206 {
207 #ifdef _DEBUG
208   if (x >= resolx * resoly) {
209     printf ("setPixel ERROR : hors du tableau... %i, %i\n", x, y);
210     exit (1);
211   }
212 #endif
213
214 #ifdef USE_DGA
215   buffer[x] = (c.b << 16) | (c.v << 8) | c.r;
216 #else
217   buffer[x] = (c.r << 16) | (c.v << 8) | c.b;
218 #endif
219 }
220
221
222
223 inline void
224 getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c)
225 {
226   register unsigned char *tmp8;
227
228 #ifdef _DEBUG
229   if (x + y * resolx >= resolx * resoly) {
230     printf ("getPixel ERROR : hors du tableau... %i, %i\n", x, y);
231     exit (1);
232   }
233 #endif
234
235 #ifdef __BIG_ENDIAN__
236   c->b = *(unsigned char *) (tmp8 =
237       (unsigned char *) (buffer + (x + y * resolx)));
238   c->r = *(unsigned char *) (++tmp8);
239   c->v = *(unsigned char *) (++tmp8);
240   c->b = *(unsigned char *) (++tmp8);
241
242 #else
243   /* ATTENTION AU PETIT INDIEN  */
244   c->b = *(unsigned char *) (tmp8 =
245       (unsigned char *) (buffer + (x + y * resolx)));
246   c->v = *(unsigned char *) (++tmp8);
247   c->r = *(unsigned char *) (++tmp8);
248 /*      *c = (Color) buffer[x+y*WIDTH] ; */
249 #endif
250 }
251
252
253 inline void
254 getPixelRGB_ (Uint * buffer, Uint x, Color * c)
255 {
256   register unsigned char *tmp8;
257
258 #ifdef _DEBUG
259   if (x >= resolx * resoly) {
260     printf ("getPixel ERROR : hors du tableau... %i\n", x);
261     exit (1);
262   }
263 #endif
264
265 #ifdef __BIG_ENDIAN__
266   c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
267   c->r = *(unsigned char *) (++tmp8);
268   c->v = *(unsigned char *) (++tmp8);
269   c->b = *(unsigned char *) (++tmp8);
270
271 #else
272   /* ATTENTION AU PETIT INDIEN  */
273   c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
274   c->v = *(unsigned char *) (++tmp8);
275   c->r = *(unsigned char *) (++tmp8);
276 /*      *c = (Color) buffer[x+y*WIDTH] ; */
277 #endif
278 }
279
280
281 /*===============================================================*/
282 void
283 zoomFilterFastRGB (Uint * pix1,
284     Uint * pix2, ZoomFilterData * zf, Uint resx, Uint resy)
285 {
286   static guint32 prevX = 0, prevY = 0;
287
288   static char reverse = 0;      /*vitesse inversé..(zoom out) */
289
290   /*    static int perte = 100; // 100 = normal */
291   static unsigned char pertedec = 8;
292   static char firstTime = 1;
293
294   Uint x, y;
295
296 /*  static unsigned int prevX = 0, prevY = 0; */
297
298 #ifdef USE_ASM
299   expix1 = pix1;
300   expix2 = pix2;
301 #else
302   Color couleur;
303   Color col1, col2, col3, col4;
304   Uint position;
305
306   static unsigned int *pos10 = 0;
307   static unsigned int *c1 = 0, *c2 = 0, *c3 = 0, *c4 = 0;
308 #endif
309
310   if ((prevX != resx) || (prevY != resy)) {
311     prevX = resx;
312     prevY = resy;
313 #ifndef USE_ASM
314     if (c1)
315       free (c1);
316     if (c2)
317       free (c2);
318     if (c3)
319       free (c3);
320     if (c4)
321       free (c4);
322     if (pos10)
323       free (pos10);
324     c1 = c2 = c3 = c4 = pos10 = 0;
325 #else
326     if (coeffs)
327       free (freecoeffs);
328     coeffs = 0;
329 #endif
330     middleX = resx / 2;
331     middleY = resy - 1;
332     firstTime = 1;
333     if (firedec)
334       free (firedec);
335     firedec = 0;
336   }
337
338   if (zf) {
339     reverse = zf->reverse;
340     vitesse = zf->vitesse;
341     if (reverse)
342       vitesse = 256 - vitesse;
343 #ifndef USE_ASM
344     sqrtperte = zf->sqrtperte;
345 #endif
346     pertedec = zf->pertedec;
347     middleX = zf->middleX;
348     middleY = zf->middleY;
349     theMode = zf->mode;
350     hPlaneEffect = zf->hPlaneEffect;
351     vPlaneEffect = zf->vPlaneEffect;
352     noisify = zf->noisify;
353   }
354
355   if (firstTime || zf) {
356
357     /* generation d'une table de sinus */
358     if (firstTime) {
359       unsigned short us;
360
361       firstTime = 0;
362 #ifdef USE_ASM
363       freecoeffs = (unsigned int *)
364           malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
365       coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
366
367 #else
368       pos10 = (unsigned int *) malloc (resx * resy * sizeof (unsigned int));
369       c1 = (unsigned int *) malloc (resx * resy * sizeof (unsigned int));
370       c2 = (unsigned int *) malloc (resx * resy * sizeof (unsigned int));
371       c3 = (unsigned int *) malloc (resx * resy * sizeof (unsigned int));
372       c4 = (unsigned int *) malloc (resx * resy * sizeof (unsigned int));
373 #endif
374       for (us = 0; us < 0xffff; us++) {
375         sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
376       }
377
378       {
379         int loopv;
380         firedec = (int *) malloc (prevY * sizeof (int));
381         for (loopv = prevY; loopv != 0;) {
382           static int decc = 0;
383           static int spdc = 0;
384           static int accel = 0;
385
386           loopv--;
387           firedec[loopv] = decc;
388           decc += spdc / 10;
389           spdc += RAND () % 3;
390           spdc -= RAND () % 3;
391
392           if (decc > 4)
393             spdc -= 1;
394           if (decc < -4)
395             spdc += 1;
396
397           if (spdc > 30)
398             spdc = spdc - RAND () % 3 + accel / 10;
399           if (spdc < -30)
400             spdc = spdc + RAND () % 3 + accel / 10;
401
402           if (decc > 8 && spdc > 1)
403             spdc -= RAND () % 3 - 2;
404
405           if (decc < -8 && spdc < -1)
406             spdc += RAND () % 3 + 2;
407
408           if (decc > 8 || decc < -8)
409             decc = decc * 8 / 9;
410
411           accel += RAND () % 2;
412           accel -= RAND () % 2;
413           if (accel > 20)
414             accel -= 2;
415           if (accel < -20)
416             accel += 2;
417         }
418       }
419     }
420
421
422     /* generation du buffer */
423     for (y = 0; y < prevY; y++)
424       for (x = 0; x < prevX; x++) {
425         int px, py;
426         unsigned char coefv, coefh;
427
428         /* calculer px et py en fonction de */
429         /*   x,y,middleX,middleY et theMode */
430         calculatePXandPY (x, y, &px, &py);
431         if ((px == x << 4) && (py == y << 4))
432           py += 8;
433
434         if ((py < 0) || (px < 0) ||
435             (py >= (prevY - 1) * sqrtperte) ||
436             (px >= (prevX - 1) * sqrtperte)) {
437 #ifdef USE_ASM
438           coeffs[(y * prevX + x) * 2] = 0;
439           coeffs[(y * prevX + x) * 2 + 1] = 0;
440 #else
441           pos10[y * prevX + x] = 0;
442           c1[y * prevX + x] = 0;
443           c2[y * prevX + x] = 0;
444           c3[y * prevX + x] = 0;
445           c4[y * prevX + x] = 0;
446 #endif
447         } else {
448           int npx10;
449           int npy10;
450           int pos;
451
452           npx10 = (px / sqrtperte);
453           npy10 = (py / sqrtperte);
454
455 /*                        if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
456                           if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
457 */
458           coefh = px % sqrtperte;
459           coefv = py % sqrtperte;
460 #ifdef USE_ASM
461           pos = (y * prevX + x) * 2;
462           coeffs[pos] = (npx10 + prevX * npy10) * 4;
463
464           if (!(coefh || coefv))
465             coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
466           else
467             coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
468
469           coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
470           coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
471           coeffs[pos + 1] |= (coefh * coefv) << 24;
472 #else
473           pos = y * prevX + x;
474           pos10[pos] = npx10 + prevX * npy10;
475
476           if (!(coefh || coefv))
477             c1[pos] = sqrtperte * sqrtperte - 1;
478           else
479             c1[pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
480
481           c2[pos] = coefh * (sqrtperte - coefv);
482           c3[pos] = (sqrtperte - coefh) * coefv;
483           c4[pos] = coefh * coefv;
484 #endif
485         }
486       }
487   }
488 #ifdef USE_ASM
489
490 #ifdef MMX
491   zoom_width = prevX;
492   mmx_zoom_size = prevX * prevY;
493   mmx_zoom ();
494 #endif
495
496 #ifdef POWERPC
497   zoom_width = prevX;
498   if (useAltivec) {
499     ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
500     ppc_zoom_altivec ();
501   } else {
502     ppcsize4 = ((unsigned int) (prevX * prevY));
503     ppc_zoom ();
504   }
505 #endif
506 #else
507   for (position = 0; position < prevX * prevY; position++) {
508     getPixelRGB_ (pix1, pos10[position], &col1);
509     getPixelRGB_ (pix1, pos10[position] + 1, &col2);
510     getPixelRGB_ (pix1, pos10[position] + prevX, &col3);
511     getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4);
512
513     couleur.r = col1.r * c1[position]
514         + col2.r * c2[position]
515         + col3.r * c3[position]
516         + col4.r * c4[position];
517     couleur.r >>= pertedec;
518
519     couleur.v = col1.v * c1[position]
520         + col2.v * c2[position]
521         + col3.v * c3[position]
522         + col4.v * c4[position];
523     couleur.v >>= pertedec;
524
525     couleur.b = col1.b * c1[position]
526         + col2.b * c2[position]
527         + col3.b * c3[position]
528         + col4.b * c4[position];
529     couleur.b >>= pertedec;
530
531     setPixelRGB_ (pix2, position, couleur);
532   }
533 #endif
534 }
535
536
537 void
538 pointFilter (Uint * pix1, Color c,
539     float t1, float t2, float t3, float t4, Uint cycle)
540 {
541   Uint x = (Uint) ((int) middleX + (int) (t1 * cos ((float) cycle / t3)));
542   Uint y = (Uint) ((int) middleY + (int) (t2 * sin ((float) cycle / t4)));
543
544   if ((x > 1) && (y > 1) && (x < resolx - 2) && (y < resoly - 2)) {
545     setPixelRGB (pix1, x + 1, y, c);
546     setPixelRGB (pix1, x, y + 1, c);
547     setPixelRGB (pix1, x + 1, y + 1, WHITE);
548     setPixelRGB (pix1, x + 2, y + 1, c);
549     setPixelRGB (pix1, x + 1, y + 2, c);
550   }
551 }