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