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 *
zoomFilterNew(void)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
ShiftRight(int x,const unsigned char s)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
calculatePXandPY(GoomData * gd,int x,int y,int * px,int * py)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
setPixelRGB(Uint * buffer,Uint x,Uint y,Color c,guint32 resolx,guint32 resoly)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
setPixelRGB_(Uint * buffer,Uint x,Color c,guint32 resolx,guint32 resoly)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 static inline void
getPixelRGB_(Uint * buffer,Uint x,Color * c,guint32 resolx,guint32 resoly)254 getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly)
255 {
256 register unsigned char *tmp8;
257
258 #ifdef _DEBUG
259 if (x >= resolx * resoly) {
260 printf ("getPixel ERROR : hors du tableau... %i\n", x);
261 exit (1);
262 }
263 #endif
264
265 #ifdef __BIG_ENDIAN__
266 c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
267 c->r = *(unsigned char *) (++tmp8);
268 c->v = *(unsigned char *) (++tmp8);
269 c->b = *(unsigned char *) (++tmp8);
270
271 #else
272 /* ATTENTION AU PETIT INDIEN */
273 tmp8 = (unsigned char *) (buffer + x);
274 c->b = *(unsigned char *) (tmp8++);
275 c->v = *(unsigned char *) (tmp8++);
276 c->r = *(unsigned char *) (tmp8);
277 /* *c = (Color) buffer[x+y*WIDTH] ; */
278 #endif
279 }
280
281 static void
zoomFilterSetResolution(GoomData * gd,ZoomFilterData * zf)282 zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf)
283 {
284 unsigned short us;
285
286 if (zf->buffsize >= gd->buffsize) {
287 zf->res_x = gd->resolx;
288 zf->res_y = gd->resoly;
289 zf->middleX = gd->resolx / 2;
290 zf->middleY = gd->resoly - 1;
291
292 return;
293 }
294 #ifndef USE_ASM
295 if (zf->buffer)
296 free (zf->buffer);
297 zf->buffer = 0;
298 #else
299 if (coeffs)
300 free (freecoeffs);
301 coeffs = 0;
302 #endif
303 zf->middleX = gd->resolx / 2;
304 zf->middleY = gd->resoly - 1;
305 zf->res_x = gd->resolx;
306 zf->res_y = gd->resoly;
307
308 if (zf->firedec)
309 free (zf->firedec);
310 zf->firedec = 0;
311
312 zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int);
313
314 #ifdef USE_ASM
315 freecoeffs = (unsigned int *)
316 malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
317 coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
318
319 #else
320 zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5);
321 zf->pos10 = zf->buffer;
322 zf->c[0] = zf->pos10 + zf->buffsize;
323 zf->c[1] = zf->c[0] + zf->buffsize;
324 zf->c[2] = zf->c[1] + zf->buffsize;
325 zf->c[3] = zf->c[2] + zf->buffsize;
326 #endif
327 zf->firedec = (int *) malloc (zf->res_y * sizeof (int));
328
329 if (firstTime) {
330 firstTime = 0;
331
332 /* generation d'une table de sinus */
333 for (us = 0; us < 0xffff; us++) {
334 sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
335 }
336 }
337 }
338
339 void
zoomFilterDestroy(ZoomFilterData * zf)340 zoomFilterDestroy (ZoomFilterData * zf)
341 {
342 if (zf) {
343 if (zf->firedec)
344 free (zf->firedec);
345 if (zf->buffer)
346 free (zf->buffer);
347 free (zf);
348 }
349 }
350
351 /*===============================================================*/
352 void
zoomFilterFastRGB(GoomData * goomdata,ZoomFilterData * zf,int zfd_update)353 zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update)
354 {
355 guint32 prevX = goomdata->resolx;
356 guint32 prevY = goomdata->resoly;
357
358 guint32 *pix1 = goomdata->p1;
359 guint32 *pix2 = goomdata->p2;
360 unsigned int *pos10;
361 unsigned int **c;
362
363 Uint x, y;
364
365 /* static unsigned int prevX = 0, prevY = 0; */
366
367 #ifdef USE_ASM
368 expix1 = pix1;
369 expix2 = pix2;
370 #else
371 Color couleur;
372 Color col1, col2, col3, col4;
373 Uint position;
374 #endif
375
376 if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) {
377 zoomFilterSetResolution (goomdata, zf);
378 }
379
380 pos10 = zf->pos10;
381 c = zf->c;
382
383 if (zfd_update) {
384 guchar sqrtperte = zf->sqrtperte;
385 gint start_y = 0;
386
387 if (zf->reverse)
388 zf->vitesse = 256 - zf->vitesse;
389
390 /* generation du buffer */
391 for (y = 0; y < zf->res_y; y++) {
392 gint y_16 = y << 4;
393 gint max_px = (prevX - 1) * sqrtperte;
394 gint max_py = (prevY - 1) * sqrtperte;
395
396 for (x = 0; x < zf->res_x; x++) {
397 gint px, py;
398 guchar coefv, coefh;
399
400 /* calculer px et py en fonction de */
401 /* x,y,middleX,middleY et theMode */
402 calculatePXandPY (goomdata, x, y, &px, &py);
403
404 if ((px == x << 4) && (py == y_16))
405 py += 8;
406
407 if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) {
408 #ifdef USE_ASM
409 coeffs[(y * prevX + x) * 2] = 0;
410 coeffs[(y * prevX + x) * 2 + 1] = 0;
411 #else
412 pos10[start_y + x] = 0;
413 c[0][start_y + x] = 0;
414 c[1][start_y + x] = 0;
415 c[2][start_y + x] = 0;
416 c[3][start_y + x] = 0;
417 #endif
418 } else {
419 int npx10;
420 int npy10;
421 int pos;
422
423 npx10 = (px / sqrtperte);
424 npy10 = (py / sqrtperte);
425
426 /* if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
427 if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
428 */
429 coefh = px % sqrtperte;
430 coefv = py % sqrtperte;
431 #ifdef USE_ASM
432 pos = (y * prevX + x) * 2;
433 coeffs[pos] = (npx10 + prevX * npy10) * 4;
434
435 if (!(coefh || coefv))
436 coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
437 else
438 coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
439
440 coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
441 coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
442 coeffs[pos + 1] |= (coefh * coefv) << 24;
443 #else
444 pos = start_y + x;
445 pos10[pos] = npx10 + prevX * npy10;
446
447 if (!(coefh || coefv))
448 c[0][pos] = sqrtperte * sqrtperte - 1;
449 else
450 c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
451
452 c[1][pos] = coefh * (sqrtperte - coefv);
453 c[2][pos] = (sqrtperte - coefh) * coefv;
454 c[3][pos] = coefh * coefv;
455 #endif
456 }
457 }
458 /* Advance start of line index */
459 start_y += prevX;
460 }
461 }
462 #ifdef USE_ASM
463 #ifdef MMX
464 zoom_width = prevX;
465 mmx_zoom_size = prevX * prevY;
466 mmx_zoom ();
467 #endif
468
469 #ifdef POWERPC
470 zoom_width = prevX;
471 if (useAltivec) {
472 ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
473 ppc_zoom_altivec ();
474 } else {
475 ppcsize4 = ((unsigned int) (prevX * prevY));
476 ppc_zoom ();
477 }
478 #endif
479 #else
480 for (position = 0; position < prevX * prevY; position++) {
481 getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx,
482 goomdata->resoly);
483 getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx,
484 goomdata->resoly);
485 getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx,
486 goomdata->resoly);
487 getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx,
488 goomdata->resoly);
489
490 couleur.r = col1.r * c[0][position]
491 + col2.r * c[1][position]
492 + col3.r * c[2][position]
493 + col4.r * c[3][position];
494 couleur.r >>= zf->pertedec;
495
496 couleur.v = col1.v * c[0][position]
497 + col2.v * c[1][position]
498 + col3.v * c[2][position]
499 + col4.v * c[3][position];
500 couleur.v >>= zf->pertedec;
501
502 couleur.b = col1.b * c[0][position]
503 + col2.b * c[1][position]
504 + col3.b * c[2][position]
505 + col4.b * c[3][position];
506 couleur.b >>= zf->pertedec;
507
508 setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly);
509 }
510 #endif
511 }
512
513
514 void
pointFilter(GoomData * goomdata,Color c,float t1,float t2,float t3,float t4,Uint cycle)515 pointFilter (GoomData * goomdata, Color c,
516 float t1, float t2, float t3, float t4, Uint cycle)
517 {
518 Uint *pix1 = goomdata->p1;
519 ZoomFilterData *zf = goomdata->zfd;
520 Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3)));
521 Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4)));
522
523 if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2)
524 && (y < goomdata->resoly - 2)) {
525 setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly);
526 setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly);
527 setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly);
528 setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly);
529 setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly);
530 }
531 }
532