rtph264pay: avoid double buffer unmap on error
[platform/upstream/gstreamer.git] / gst / goom / filters.c
1 /* Goom Project
2  * Copyright (C) <2003> iOS-Software
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---
20
21 /* filter.c version 0.7
22 * contient les filtres applicable a un buffer
23 * creation : 01/10/2000
24 *  -ajout de sinFilter()
25 *  -ajout de zoomFilter()
26 *  -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
27 *  -optimisation de sinFilter (utilisant une table de sin)
28 *       -asm
29 *       -optimisation de la procedure de generation du buffer de transformation
30 *               la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
31 */
32
33 /* #define _DEBUG_PIXEL */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <string.h>
40 #include <stdlib.h>
41 #include <math.h>
42 #include <stdio.h>
43
44 #ifdef HAVE_INTTYPES_H
45 #include <inttypes.h>
46 #endif
47
48 #include "goom_filters.h"
49 #include "goom_graphic.h"
50 #include "goom_tools.h"
51 #include "goom_plugin_info.h"
52 #include "goom_fx.h"
53 #include "v3d.h"
54
55 /* TODO : MOVE THIS AWAY !!! */
56 /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
57 static inline void
58 setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c)
59 {
60   Pixel i;
61
62   i.channels.b = c.b;
63   i.channels.g = c.v;
64   i.channels.r = c.r;
65   *(buffer + (x + y * goomInfo->screen.width)) = i;
66 }
67
68 static inline void
69 setPixelRGB_ (Pixel * buffer, Uint x, Color c)
70 {
71   buffer[x].channels.r = c.r;
72   buffer[x].channels.g = c.v;
73   buffer[x].channels.b = c.b;
74 }
75
76 static inline void
77 getPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color * c)
78 {
79   Pixel i = *(buffer + (x + y * goomInfo->screen.width));
80
81   c->b = i.channels.b;
82   c->v = i.channels.g;
83   c->r = i.channels.r;
84 }
85
86 static inline void
87 getPixelRGB_ (Pixel * buffer, Uint x, Color * c)
88 {
89   Pixel i = *(buffer + x);
90
91   c->b = i.channels.b;
92   c->v = i.channels.g;
93   c->r = i.channels.r;
94 }
95
96 /* END TODO */
97
98
99 /* DEPRECATED */
100 // retourne x>>s , en testant le signe de x
101 //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
102 //#define EFFECT_DISTORS 4
103 //#define EFFECT_DISTORS_SL 2
104 //#define INTERLACE_ADD 9
105 //#define INTERLACE_AND 0xf
106 /* END DEPRECATED */
107
108 #define BUFFPOINTNB 16
109 #define BUFFPOINTNBF 16.0f
110 #define BUFFPOINTMASK 0xffff
111
112 #define sqrtperte 16
113 /* faire : a % sqrtperte <=> a & pertemask */
114 #define PERTEMASK 0xf
115 /* faire : a / sqrtperte <=> a >> PERTEDEC */
116 #define PERTEDEC 4
117
118 /* pure c version of the zoom filter */
119 static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX,
120     unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio,
121     int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
122
123 /* simple wrapper to give it the same proto than the others */
124 void
125 zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS,
126     int *brutD, int buffratio, int precalCoef[16][16])
127 {
128   c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
129 }
130
131 static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
132
133
134 typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA
135 {
136
137   PluginParam enabled_bp;
138   PluginParameters params;
139
140   unsigned int *coeffs, *freecoeffs;
141
142   signed int *brutS, *freebrutS;        /* source */
143   signed int *brutD, *freebrutD;        /* dest */
144   signed int *brutT, *freebrutT;        /* temp (en cours de generation) */
145
146   guint32 zoom_width;
147
148   unsigned int prevX, prevY;
149
150   float general_speed;
151   int reverse;                  /* reverse the speed */
152   char theMode;
153   int waveEffect;
154   int hypercosEffect;
155   int vPlaneEffect;
156   int hPlaneEffect;
157   char noisify;
158   int middleX, middleY;
159
160   int mustInitBuffers;
161   int interlace_start;
162
163     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
164   int buffratio;
165   int *firedec;
166
167     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
168   int precalCoef[BUFFPOINTNB][BUFFPOINTNB];
169
170     /** calculatePXandPY statics */
171   int wave;
172   int wavesp;
173
174 } ZoomFilterFXWrapperData;
175
176
177
178
179 static inline void
180 zoomVector (v2g * vecteur, ZoomFilterFXWrapperData * data, float X, float Y)
181 {
182   float vx, vy;
183   float sq_dist = X * X + Y * Y;
184
185   /*    sx = (X < 0.0f) ? -1.0f : 1.0f;
186      sy = (Y < 0.0f) ? -1.0f : 1.0f;
187    */
188   float coefVitesse = (1.0f + data->general_speed) / 50.0f;
189
190   // Effects
191
192   /* Centralized FX */
193
194   switch (data->theMode) {
195     case CRYSTAL_BALL_MODE:
196       coefVitesse -= (sq_dist - 0.3f) / 15.0f;
197       break;
198     case AMULETTE_MODE:
199       coefVitesse += sq_dist * 3.5f;
200       break;
201     case WAVE_MODE:
202       coefVitesse += sin (sq_dist * 20.0f) / 100.0f;
203       break;
204     case SCRUNCH_MODE:
205       coefVitesse += sq_dist / 10.0f;
206       break;
207       //case HYPERCOS1_MODE:
208       break;
209       //case HYPERCOS2_MODE:
210       break;
211       //case YONLY_MODE:
212       break;
213     case SPEEDWAY_MODE:
214       coefVitesse *= 4.0f * Y;
215       break;
216     default:
217       break;
218   }
219
220   if (coefVitesse < -2.01f)
221     coefVitesse = -2.01f;
222   if (coefVitesse > 2.01f)
223     coefVitesse = 2.01f;
224
225   vx = coefVitesse * X;
226   vy = coefVitesse * Y;
227
228   /* Amulette 2 */
229   // vx = X * tan(dist);
230   // vy = Y * tan(dist);
231
232   /* Rotate */
233   //vx = (X+Y)*0.1;
234   //vy = (Y-X)*0.1;
235
236
237   // Effects adds-on
238
239   /* Noise */
240   if (data->noisify) {
241     vx += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
242     vy += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
243   }
244
245   /* Hypercos */
246   if (data->hypercosEffect) {
247     vx += sin (Y * 10.0f) / 120.0f;
248     vy += sin (X * 10.0f) / 120.0f;
249   }
250
251   /* H Plane */
252   if (data->hPlaneEffect)
253     vx += Y * 0.0025f * data->hPlaneEffect;
254
255   /* V Plane */
256   if (data->vPlaneEffect)
257     vy += X * 0.0025f * data->vPlaneEffect;
258
259   /* TODO : Water Mode */
260   //    if (data->waveEffect)
261
262   vecteur->x = vx;
263   vecteur->y = vy;
264 }
265
266
267 /*
268  * Makes a stripe of a transform buffer (brutT)
269  *
270  * The transform is (in order) :
271  * Translation (-data->middleX, -data->middleY)
272  * Homothetie (Center : 0,0   Coeff : 2/data->prevX)
273  */
274 static void
275 makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
276 {
277   // Position of the pixel to compute in pixmap coordinates
278   Uint x, y;
279
280   // Where (verticaly) to stop generating the buffer stripe
281   int maxEnd;
282
283   // Ratio from pixmap to normalized coordinates
284   float ratio = 2.0f / ((float) data->prevX);
285
286   // Ratio from normalized to virtual pixmap coordinates
287   float inv_ratio = BUFFPOINTNBF / ratio;
288   float min = ratio / BUFFPOINTNBF;
289
290   // Y position of the pixel to compute in normalized coordinates
291   float Y = ((float) (data->interlace_start - data->middleY)) * ratio;
292
293   maxEnd = data->prevY;
294   if (maxEnd > (data->interlace_start + INTERLACE_INCR))
295     maxEnd = (data->interlace_start + INTERLACE_INCR);
296
297   for (y = data->interlace_start;
298       (y < data->prevY) && ((signed int) y < maxEnd); y++) {
299     Uint premul_y_prevX = y * data->prevX * 2;
300     float X = -((float) data->middleX) * ratio;
301
302     for (x = 0; x < data->prevX; x++) {
303       v2g vector;
304
305       zoomVector (&vector, data, X, Y);
306
307       /* Finish and avoid null displacement */
308       if (fabs (vector.x) < min)
309         vector.x = (vector.x < 0.0f) ? -min : min;
310       if (fabs (vector.y) < min)
311         vector.y = (vector.y < 0.0f) ? -min : min;
312
313       data->brutT[premul_y_prevX] =
314           ((int) ((X - vector.x) * inv_ratio) +
315           ((int) (data->middleX * BUFFPOINTNB)));
316       data->brutT[premul_y_prevX + 1] =
317           ((int) ((Y - vector.y) * inv_ratio) +
318           ((int) (data->middleY * BUFFPOINTNB)));
319       premul_y_prevX += 2;
320       X += ratio;
321     }
322     Y += ratio;
323   }
324   data->interlace_start += INTERLACE_INCR;
325   if (y >= data->prevY - 1)
326     data->interlace_start = -1;
327 }
328
329
330 /*
331  * calculer px et py en fonction de x,y,middleX,middleY et theMode
332  * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
333  * (valeur * 16)
334  
335  inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
336  {
337      if (data->theMode == WATER_MODE) {
338          int yy;
339          
340          yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
341          if (yy < 0)
342              yy = 0;
343          if (yy >= (signed int)goomInfo->screen.height)
344              yy = goomInfo->screen.height - 1;
345          
346          *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
347          *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
348          
349          data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
350          if (data->wave < -10)
351              data->wavesp += 2;
352          if (data->wave > 10)
353              data->wavesp -= 2;
354          data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
355          if (data->wavesp > 100)
356              data->wavesp = (data->wavesp * 9) / 10;
357      }
358      else {
359          int     dist = 0, vx9, vy9;
360          int     vx, vy;
361          int     ppx, ppy;
362          int     fvitesse = data->vitesse << 4;
363          
364          if (data->noisify) {
365              x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
366              y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
367          }
368          vx = (x - data->middleX) << 9;
369          vy = (y - data->middleY) << 9;
370          
371          if (data->hPlaneEffect)
372              vx += data->hPlaneEffect * (y - data->middleY);
373          
374          if (data->vPlaneEffect)
375              vy += data->vPlaneEffect * (x - data->middleX);
376          
377          if (data->waveEffect) {
378              fvitesse *=
379              1024 +
380              ShiftRight (goomInfo->sintable
381                          [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
382              fvitesse /= 1024;
383          }
384          
385          if (data->hypercosEffect) {
386              vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
387              vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
388          }
389          
390          vx9 = ShiftRight (vx, 9);
391          vy9 = ShiftRight (vy, 9);
392          dist = vx9 * vx9 + vy9 * vy9;
393          
394          switch (data->theMode) {
395              case WAVE_MODE:
396                  fvitesse *=
397                  1024 +
398                  ShiftRight (goomInfo->sintable
399                              [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
400                  fvitesse>>=10;
401                  break;
402              case CRYSTAL_BALL_MODE:
403                  fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
404                  break;
405              case AMULETTE_MODE:
406                  fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
407                  break;
408              case SCRUNCH_MODE:
409                  fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
410                  break;
411              case HYPERCOS1_MODE:
412                  vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
413                  vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
414                  break;
415              case HYPERCOS2_MODE:
416                  vx =
417                  vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
418                  vy =
419                      vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
420                  fvitesse = 128 << 4;
421                  break;
422              case YONLY_MODE:
423                  fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
424                  fvitesse >>= 10;
425                  break;
426              case SPEEDWAY_MODE:
427                  fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
428                  break;
429          }
430          
431          if (fvitesse < -3024)
432              fvitesse = -3024;
433          
434          if (vx < 0)                                                                    // pb avec decalage sur nb negatif
435              ppx = -(-(vx * fvitesse) >> 16);
436          // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
437          //    * * * * * 9 = nb chiffre virgule de vx) 
438          else
439              ppx = ((vx * fvitesse) >> 16);
440          
441          if (vy < 0)
442              ppy = -(-(vy * fvitesse) >> 16);
443          else
444              ppy = ((vy * fvitesse) >> 16);
445          
446          *px = (data->middleX << 4) + ppx;
447          *py = (data->middleY << 4) + ppy;
448      }
449  }
450  */
451
452
453
454 static void
455 c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY,
456     signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16])
457 {
458   int myPos, myPos2;
459   Color couleur;
460
461   unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
462
463   int bufsize = prevX * prevY * 2;
464   int bufwidth = prevX;
465
466   expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
467       expix1[prevX * prevY - prevX].val = 0;
468
469   for (myPos = 0; myPos < bufsize; myPos += 2) {
470     Color col1, col2, col3, col4;
471     int c1, c2, c3, c4, px, py;
472     int pos;
473     int coeffs;
474
475     int brutSmypos = brutS[myPos];
476
477     myPos2 = myPos + 1;
478
479     px = brutSmypos + (((brutD[myPos] -
480                 brutSmypos) * buffratio) >> BUFFPOINTNB);
481     brutSmypos = brutS[myPos2];
482     py = brutSmypos + (((brutD[myPos2] -
483                 brutSmypos) * buffratio) >> BUFFPOINTNB);
484
485     if ((py >= ay) || (px >= ax)) {
486       pos = coeffs = 0;
487     } else {
488       pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
489       /* coef en modulo 15 */
490       coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
491     }
492     getPixelRGB_ (expix1, pos, &col1);
493     getPixelRGB_ (expix1, pos + 1, &col2);
494     getPixelRGB_ (expix1, pos + bufwidth, &col3);
495     getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);
496
497     c1 = coeffs;
498     c2 = (c1 >> 8) & 0xFF;
499     c3 = (c1 >> 16) & 0xFF;
500     c4 = (c1 >> 24) & 0xFF;
501     c1 = c1 & 0xff;
502
503     couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
504     if (couleur.r > 5)
505       couleur.r -= 5;
506     couleur.r >>= 8;
507
508     couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
509     if (couleur.v > 5)
510       couleur.v -= 5;
511     couleur.v >>= 8;
512
513     couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
514     if (couleur.b > 5)
515       couleur.b -= 5;
516     couleur.b >>= 8;
517
518     setPixelRGB_ (expix2, myPos >> 1, couleur);
519   }
520 }
521
522 /** generate the water fx horizontal direction buffer */
523 static void
524 generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo,
525     ZoomFilterFXWrapperData * data)
526 {
527
528   int loopv;
529   int decc = goom_irand (goomInfo->gRandom, 8) - 4;
530   int spdc = goom_irand (goomInfo->gRandom, 8) - 4;
531   int accel = goom_irand (goomInfo->gRandom, 8) - 4;
532
533   for (loopv = data->prevY; loopv != 0;) {
534
535     loopv--;
536     data->firedec[loopv] = decc;
537     decc += spdc / 10;
538     spdc +=
539         goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3);
540
541     if (decc > 4)
542       spdc -= 1;
543     if (decc < -4)
544       spdc += 1;
545
546     if (spdc > 30)
547       spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10;
548     if (spdc < -30)
549       spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10;
550
551     if (decc > 8 && spdc > 1)
552       spdc -= goom_irand (goomInfo->gRandom, 3) - 2;
553
554     if (decc < -8 && spdc < -1)
555       spdc += goom_irand (goomInfo->gRandom, 3) + 2;
556
557     if (decc > 8 || decc < -8)
558       decc = decc * 8 / 9;
559
560     accel +=
561         goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2);
562     if (accel > 20)
563       accel -= 2;
564     if (accel < -20)
565       accel += 2;
566   }
567 }
568
569
570
571 /**
572 * Main work for the dynamic displacement map.
573  * 
574  * Reads data from pix1, write to pix2.
575  *
576  * Useful datas for this FX are stored in ZoomFilterData.
577  * 
578  * If you think that this is a strange function name, let me say that a long time ago,
579  *  there has been a slow version and a gray-level only one. Then came these function,
580  *  fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
581  *  So that is why you have this name, for the nostalgy of the first days of goom
582  *  when it was just a tiny program writen in Turbo Pascal on my i486...
583  */
584 void
585 zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2,
586     ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
587 {
588   Uint x, y;
589
590   ZoomFilterFXWrapperData *data =
591       (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data;
592
593   if (!BVAL (data->enabled_bp))
594     return;
595
596     /** changement de taille **/
597   if ((data->prevX != resx) || (data->prevY != resy)) {
598     data->prevX = resx;
599     data->prevY = resy;
600
601     if (data->brutS)
602       free (data->freebrutS);
603     data->brutS = 0;
604     if (data->brutD)
605       free (data->freebrutD);
606     data->brutD = 0;
607     if (data->brutT)
608       free (data->freebrutT);
609     data->brutT = 0;
610
611     data->middleX = resx / 2;
612     data->middleY = resy / 2;
613     data->mustInitBuffers = 1;
614     if (data->firedec)
615       free (data->firedec);
616     data->firedec = 0;
617   }
618
619   if (data->interlace_start != -2)
620     zf = NULL;
621
622     /** changement de config **/
623   if (zf) {
624     data->reverse = zf->reverse;
625     data->general_speed = (float) (zf->vitesse - 128) / 128.0f;
626     if (data->reverse)
627       data->general_speed = -data->general_speed;
628     data->middleX = zf->middleX;
629     data->middleY = zf->middleY;
630     data->theMode = zf->mode;
631     data->hPlaneEffect = zf->hPlaneEffect;
632     data->vPlaneEffect = zf->vPlaneEffect;
633     data->waveEffect = zf->waveEffect;
634     data->hypercosEffect = zf->hypercosEffect;
635     data->noisify = zf->noisify;
636     data->interlace_start = 0;
637   }
638
639
640   if (data->mustInitBuffers) {
641
642     data->mustInitBuffers = 0;
643     data->freebrutS =
644         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
645     data->brutS =
646         (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);
647
648     data->freebrutD =
649         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
650     data->brutD =
651         (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);
652
653     data->freebrutT =
654         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
655     data->brutT =
656         (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);
657
658     data->buffratio = 0;
659
660     data->firedec = (int *) malloc (data->prevY * sizeof (int));
661     generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data);
662
663     data->interlace_start = 0;
664     makeZoomBufferStripe (data, resy);
665
666     /* Copy the data from temp to dest and source */
667     memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int));
668     memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int));
669   }
670
671   /* generation du buffer de trans */
672   if (data->interlace_start == -1) {
673
674     /* sauvegarde de l'etat actuel dans la nouvelle source
675      * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
676     y = data->prevX * data->prevY * 2;
677     for (x = 0; x < y; x += 2) {
678       int brutSmypos = data->brutS[x];
679       int x2 = x + 1;
680
681       data->brutS[x] =
682           brutSmypos + (((data->brutD[x] -
683                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
684       brutSmypos = data->brutS[x2];
685       data->brutS[x2] =
686           brutSmypos + (((data->brutD[x2] -
687                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
688     }
689     data->buffratio = 0;
690   }
691
692   if (data->interlace_start == -1) {
693     signed int *tmp;
694
695     tmp = data->brutD;
696     data->brutD = data->brutT;
697     data->brutT = tmp;
698     tmp = data->freebrutD;
699     data->freebrutD = data->freebrutT;
700     data->freebrutT = tmp;
701     data->interlace_start = -2;
702   }
703
704   if (data->interlace_start >= 0) {
705     /* creation de la nouvelle destination */
706     makeZoomBufferStripe (data, resy / 16);
707   }
708
709   if (switchIncr != 0) {
710     data->buffratio += switchIncr;
711     if (data->buffratio > BUFFPOINTMASK)
712       data->buffratio = BUFFPOINTMASK;
713   }
714
715   if (switchMult != 1.0f) {
716     data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
717         (float) data->buffratio * switchMult);
718   }
719
720   data->zoom_width = data->prevX;
721
722   goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
723       data->brutS, data->brutD, data->buffratio, data->precalCoef);
724 }
725
726 static void
727 generatePrecalCoef (int precalCoef[16][16])
728 {
729   int coefh, coefv;
730
731   for (coefh = 0; coefh < 16; coefh++) {
732     for (coefv = 0; coefv < 16; coefv++) {
733
734       int i;
735       int diffcoeffh;
736       int diffcoeffv;
737
738       diffcoeffh = sqrtperte - coefh;
739       diffcoeffv = sqrtperte - coefv;
740
741       if (!(coefh || coefv)) {
742         i = 255;
743       } else {
744         int i1, i2, i3, i4;
745
746         i1 = diffcoeffh * diffcoeffv;
747         i2 = coefh * diffcoeffv;
748         i3 = diffcoeffh * coefv;
749         i4 = coefh * coefv;
750
751         // TODO: faire mieux...
752         if (i1)
753           i1--;
754         if (i2)
755           i2--;
756         if (i3)
757           i3--;
758         if (i4)
759           i4--;
760
761         i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
762       }
763       precalCoef[coefh][coefv] = i;
764     }
765   }
766 }
767
768 /* VisualFX Wrapper */
769
770 static void
771 zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info)
772 {
773   ZoomFilterFXWrapperData *data =
774       (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData));
775
776   data->coeffs = 0;
777   data->freecoeffs = 0;
778   data->brutS = 0;
779   data->freebrutS = 0;
780   data->brutD = 0;
781   data->freebrutD = 0;
782   data->brutT = 0;
783   data->freebrutT = 0;
784   data->prevX = 0;
785   data->prevY = 0;
786
787   data->mustInitBuffers = 1;
788   data->interlace_start = -2;
789
790   data->general_speed = 0.0f;
791   data->reverse = 0;
792   data->theMode = AMULETTE_MODE;
793   data->waveEffect = 0;
794   data->hypercosEffect = 0;
795   data->vPlaneEffect = 0;
796   data->hPlaneEffect = 0;
797   data->noisify = 2;
798
799     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
800   data->buffratio = 0;
801   data->firedec = 0;
802
803   data->wave = data->wavesp = 0;
804
805   secure_b_param (&data->enabled_bp, "Enabled", 1);
806
807   plugin_parameters (&data->params, "Zoom Filter", 1);
808   data->params.params[0] = &data->enabled_bp;
809
810   _this->params = &data->params;
811   _this->fx_data = (void *) data;
812
813     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
814   generatePrecalCoef (data->precalCoef);
815 }
816
817 static void
818 zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
819 {
820   ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) _this->fx_data;
821
822   if (data->freebrutT)
823     free (data->freebrutT);
824   if (data->freebrutS)
825     free (data->freebrutS);
826   if (data->freebrutD)
827     free (data->freebrutD);
828   if (data->firedec)
829     free (data->firedec);
830
831   goom_plugin_parameters_free (_this->params);
832
833   free (_this->fx_data);
834 }
835
836 static void
837 zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src,
838     Pixel * dest, PluginInfo * info)
839 {
840 }
841
842 void
843 zoomFilterVisualFXWrapper_create (VisualFX * fx)
844 {
845   fx->init = zoomFilterVisualFXWrapper_init;
846   fx->free = zoomFilterVisualFXWrapper_free;
847   fx->apply = zoomFilterVisualFXWrapper_apply;
848   fx->params = NULL;
849   fx->fx_data = NULL;
850 }
851
852
853 /* TODO : MOVE THIS AWAY */
854
855 void
856 pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2,
857     float t3, float t4, Uint cycle)
858 {
859   Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
860       + (int) (t1 * cos ((float) cycle / t3)));
861   Uint y = (Uint) ((int) (goomInfo->screen.height / 2)
862       + (int) (t2 * sin ((float) cycle / t4)));
863
864   if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2)
865       && (y < goomInfo->screen.height - 2)) {
866     setPixelRGB (goomInfo, pix1, x + 1, y, c);
867     setPixelRGB (goomInfo, pix1, x, y + 1, c);
868     setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
869     setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
870     setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
871   }
872 }