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