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