diff options
Diffstat (limited to 'gst/goom2k1/filters.c')
-rw-r--r-- | gst/goom2k1/filters.c | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/gst/goom2k1/filters.c b/gst/goom2k1/filters.c new file mode 100644 index 00000000..b898e89c --- /dev/null +++ b/gst/goom2k1/filters.c @@ -0,0 +1,606 @@ +/* filter.c version 0.7 + * contient les filtres applicable a un buffer + * creation : 01/10/2000 + * -ajout de sinFilter() + * -ajout de zoomFilter() + * -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs + * -optimisation de sinFilter (utilisant une table de sin) + * -asm + * -optimisation de la procedure de génération du buffer de transformation + * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100] +*/ + +/*#define _DEBUG_PIXEL; */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "filters.h" +#include "graphic.h" +#include "goom_tools.h" +#include "goom_core.h" +#include <stdlib.h> +#include <math.h> +#include <stdio.h> + +#ifdef MMX +#define USE_ASM +#endif +#ifdef POWERPC +#define USE_ASM +#endif + +#ifdef USE_ASM +#define EFFECT_DISTORS 4 +#else +#define EFFECT_DISTORS 10 +#endif + + +#ifdef USE_ASM + +#ifdef MMX +int mmx_zoom (); +guint32 mmx_zoom_size; +#endif /* MMX */ + +#ifdef POWERPC +extern unsigned int useAltivec; +extern void ppc_zoom (void); +extern void ppc_zoom_altivec (void); +unsigned int ppcsize4; +#endif /* PowerPC */ + + +unsigned int *coeffs = 0, *freecoeffs = 0; +guint32 *expix1 = 0; /* pointeur exporte vers p1 */ +guint32 *expix2 = 0; /* pointeur exporte vers p2 */ +guint32 zoom_width; +#endif /* ASM */ + + +static int firstTime = 1; +static int sintable[0xffff]; + +ZoomFilterData * +zoomFilterNew () +{ + ZoomFilterData *zf = malloc (sizeof (ZoomFilterData)); + + zf->vitesse = 128; + zf->pertedec = 8; + zf->sqrtperte = 16; + zf->middleX = 1; + zf->middleY = 1; + zf->reverse = 0; + zf->mode = WAVE_MODE; + zf->hPlaneEffect = 0; + zf->vPlaneEffect = 0; + zf->noisify = 0; + zf->buffsize = 0; + zf->res_x = 0; + zf->res_y = 0; + + zf->buffer = NULL; + zf->firedec = NULL; + + zf->wave = 0; + zf->wavesp = 0; + + return zf; +} + +/* retourne x>>s , en testant le signe de x */ +static inline int +ShiftRight (int x, const unsigned char s) +{ + if (x < 0) + return -(-x >> s); + else + return x >> s; +} + +/* + calculer px et py en fonction de x,y,middleX,middleY et theMode + px et py indique la nouvelle position (en sqrtperte ieme de pixel) + (valeur * 16) +*/ +void +calculatePXandPY (GoomData * gd, int x, int y, int *px, int *py) +{ + ZoomFilterData *zf = gd->zfd; + int middleX, middleY; + guint32 resoly = zf->res_y; + int vPlaneEffect = zf->vPlaneEffect; + int hPlaneEffect = zf->hPlaneEffect; + int vitesse = zf->vitesse; + char theMode = zf->mode; + + if (theMode == WATER_MODE) { + int wavesp = zf->wavesp; + int wave = zf->wave; + int yy = y + RAND (gd) % 4 + wave / 10; + + yy -= RAND (gd) % 4; + if (yy < 0) + yy = 0; + if (yy >= resoly) + yy = resoly - 1; + + *px = (x << 4) + zf->firedec[yy] + (wave / 10); + *py = (y << 4) + 132 - ((vitesse < 132) ? vitesse : 131); + + wavesp += RAND (gd) % 3; + wavesp -= RAND (gd) % 3; + if (wave < -10) + wavesp += 2; + if (wave > 10) + wavesp -= 2; + wave += (wavesp / 10) + RAND (gd) % 3; + wave -= RAND (gd) % 3; + if (wavesp > 100) + wavesp = (wavesp * 9) / 10; + + zf->wavesp = wavesp; + zf->wave = wave; + } else { + int dist; + register int vx, vy; + int fvitesse = vitesse << 4; + + middleX = zf->middleX; + middleY = zf->middleY; + + if (zf->noisify) { + x += RAND (gd) % zf->noisify; + x -= RAND (gd) % zf->noisify; + y += RAND (gd) % zf->noisify; + y -= RAND (gd) % zf->noisify; + } + + if (hPlaneEffect) + vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY); + else + vx = (x - middleX) << 9; + + if (vPlaneEffect) + vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX); + else + vy = (y - middleY) << 9; + + switch (theMode) { + case WAVE_MODE: + dist = + ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy, + 9) * ShiftRight (vy, 9); + fvitesse *= + 1024 + + ShiftRight (sintable[(unsigned short) (0xffff * dist * + EFFECT_DISTORS)], 6); + fvitesse /= 1024; + break; + case CRYSTAL_BALL_MODE: + dist = + ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy, + 9) * ShiftRight (vy, 9); + fvitesse += (dist * EFFECT_DISTORS >> 10); + break; + case AMULETTE_MODE: + dist = + ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy, + 9) * ShiftRight (vy, 9); + fvitesse -= (dist * EFFECT_DISTORS >> 4); + break; + case SCRUNCH_MODE: + dist = + ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy, + 9) * ShiftRight (vy, 9); + fvitesse -= (dist * EFFECT_DISTORS >> 9); + break; + } + if (vx < 0) + *px = (middleX << 4) - (-(vx * fvitesse) >> 16); + else + *px = (middleX << 4) + ((vx * fvitesse) >> 16); + if (vy < 0) + *py = (middleY << 4) - (-(vy * fvitesse) >> 16); + else + *py = (middleY << 4) + ((vy * fvitesse) >> 16); + } +} + +/*#define _DEBUG */ + +static inline void +setPixelRGB (Uint * buffer, Uint x, Uint y, Color c, + guint32 resolx, guint32 resoly) +{ +/* buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */ +#ifdef _DEBUG_PIXEL + if (x + y * resolx >= resolx * resoly) { + fprintf (stderr, "setPixel ERROR : hors du tableau... %i, %i\n", x, y); + /*exit (1) ; */ + } +#endif + +#ifdef USE_DGA + buffer[y * resolx + x] = (c.b << 16) | (c.v << 8) | c.r; +#else + buffer[y * resolx + x] = (c.r << 16) | (c.v << 8) | c.b; +#endif +} + + +static inline void +setPixelRGB_ (Uint * buffer, Uint x, Color c, guint32 resolx, guint32 resoly) +{ +#ifdef _DEBUG + if (x >= resolx * resoly) { + printf ("setPixel ERROR : hors du tableau... %i >= %i*%i (%i)\n", x, resolx, + resoly, resolx * resoly); + exit (1); + } +#endif + +#ifdef USE_DGA + buffer[x] = (c.b << 16) | (c.v << 8) | c.r; +#else + buffer[x] = (c.r << 16) | (c.v << 8) | c.b; +#endif +} + + + +static inline void +getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c, + guint32 resolx, guint32 resoly) +{ + register unsigned char *tmp8; + +#ifdef _DEBUG + if (x + y * resolx >= resolx * resoly) { + printf ("getPixel ERROR : hors du tableau... %i, %i\n", x, y); + exit (1); + } +#endif + +#ifdef __BIG_ENDIAN__ + c->b = *(unsigned char *) (tmp8 = + (unsigned char *) (buffer + (x + y * resolx))); + c->r = *(unsigned char *) (++tmp8); + c->v = *(unsigned char *) (++tmp8); + c->b = *(unsigned char *) (++tmp8); + +#else + /* ATTENTION AU PETIT INDIEN */ + c->b = *(unsigned char *) (tmp8 = + (unsigned char *) (buffer + (x + y * resolx))); + c->v = *(unsigned char *) (++tmp8); + c->r = *(unsigned char *) (++tmp8); +/* *c = (Color) buffer[x+y*WIDTH] ; */ +#endif +} + + +static inline void +getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly) +{ + register unsigned char *tmp8; + +#ifdef _DEBUG + if (x >= resolx * resoly) { + printf ("getPixel ERROR : hors du tableau... %i\n", x); + exit (1); + } +#endif + +#ifdef __BIG_ENDIAN__ + c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x)); + c->r = *(unsigned char *) (++tmp8); + c->v = *(unsigned char *) (++tmp8); + c->b = *(unsigned char *) (++tmp8); + +#else + /* ATTENTION AU PETIT INDIEN */ + tmp8 = (unsigned char *) (buffer + x); + c->b = *(unsigned char *) (tmp8++); + c->v = *(unsigned char *) (tmp8++); + c->r = *(unsigned char *) (tmp8); +/* *c = (Color) buffer[x+y*WIDTH] ; */ +#endif +} + +static void +zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf) +{ + unsigned short us; + + if (zf->buffsize >= gd->buffsize) { + zf->res_x = gd->resolx; + zf->res_y = gd->resoly; + zf->middleX = gd->resolx / 2; + zf->middleY = gd->resoly - 1; + + return; + } +#ifndef USE_ASM + if (zf->buffer) + free (zf->buffer); + zf->buffer = 0; +#else + if (coeffs) + free (freecoeffs); + coeffs = 0; +#endif + zf->middleX = gd->resolx / 2; + zf->middleY = gd->resoly - 1; + zf->res_x = gd->resolx; + zf->res_y = gd->resoly; + + if (zf->firedec) + free (zf->firedec); + zf->firedec = 0; + + zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int); + +#ifdef USE_ASM + freecoeffs = (unsigned int *) + malloc (resx * resy * 2 * sizeof (unsigned int) + 128); + coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128); + +#else + zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5); + zf->pos10 = zf->buffer; + zf->c[0] = zf->pos10 + zf->buffsize; + zf->c[1] = zf->c[0] + zf->buffsize; + zf->c[2] = zf->c[1] + zf->buffsize; + zf->c[3] = zf->c[2] + zf->buffsize; +#endif + zf->firedec = (int *) malloc (zf->res_y * sizeof (int)); + + if (firstTime) { + firstTime = 0; + + /* generation d'une table de sinus */ + for (us = 0; us < 0xffff; us++) { + sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff)); + } + } + + { + int loopv; + + for (loopv = zf->res_y; loopv != 0;) { + int decc = 0; + int spdc = 0; + int accel = 0; + + loopv--; + zf->firedec[loopv] = decc; + decc += spdc / 10; + spdc += RAND (gd) % 3; + spdc -= RAND (gd) % 3; + + if (decc > 4) + spdc -= 1; + if (decc < -4) + spdc += 1; + + if (spdc > 30) + spdc = spdc - RAND (gd) % 3 + accel / 10; + if (spdc < -30) + spdc = spdc + RAND (gd) % 3 + accel / 10; + + if (decc > 8 && spdc > 1) + spdc -= RAND (gd) % 3 - 2; + + if (decc < -8 && spdc < -1) + spdc += RAND (gd) % 3 + 2; + + if (decc > 8 || decc < -8) + decc = decc * 8 / 9; + + accel += RAND (gd) % 2; + accel -= RAND (gd) % 2; + if (accel > 20) + accel -= 2; + if (accel < -20) + accel += 2; + } + } +} + +void +zoomFilterDestroy (ZoomFilterData * zf) +{ + if (zf) { + if (zf->firedec) + free (zf->firedec); + if (zf->buffer) + free (zf->buffer); + free (zf); + } +} + +/*===============================================================*/ +void +zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update) +{ + guint32 prevX = goomdata->resolx; + guint32 prevY = goomdata->resoly; + + guint32 *pix1 = goomdata->p1; + guint32 *pix2 = goomdata->p2; + unsigned int *pos10; + unsigned int **c; + + Uint x, y; + +/* static unsigned int prevX = 0, prevY = 0; */ + +#ifdef USE_ASM + expix1 = pix1; + expix2 = pix2; +#else + Color couleur; + Color col1, col2, col3, col4; + Uint position; +#endif + + if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) { + zoomFilterSetResolution (goomdata, zf); + } + + pos10 = zf->pos10; + c = zf->c; + + if (zfd_update) { + guchar sqrtperte = zf->sqrtperte; + gint start_y = 0; + + if (zf->reverse) + zf->vitesse = 256 - zf->vitesse; + + /* generation du buffer */ + for (y = 0; y < zf->res_y; y++) { + gint y_16 = y << 4; + gint max_px = (prevX - 1) * sqrtperte; + gint max_py = (prevY - 1) * sqrtperte; + + for (x = 0; x < zf->res_x; x++) { + gint px, py; + guchar coefv, coefh; + + /* calculer px et py en fonction de */ + /* x,y,middleX,middleY et theMode */ + calculatePXandPY (goomdata, x, y, &px, &py); + + if ((px == x << 4) && (py == y_16)) + py += 8; + + if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) { +#ifdef USE_ASM + coeffs[(y * prevX + x) * 2] = 0; + coeffs[(y * prevX + x) * 2 + 1] = 0; +#else + pos10[start_y + x] = 0; + c[0][start_y + x] = 0; + c[1][start_y + x] = 0; + c[2][start_y + x] = 0; + c[3][start_y + x] = 0; +#endif + } else { + int npx10; + int npy10; + int pos; + + npx10 = (px / sqrtperte); + npy10 = (py / sqrtperte); + +/* if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10); + if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10); +*/ + coefh = px % sqrtperte; + coefv = py % sqrtperte; +#ifdef USE_ASM + pos = (y * prevX + x) * 2; + coeffs[pos] = (npx10 + prevX * npy10) * 4; + + if (!(coefh || coefv)) + coeffs[pos + 1] = (sqrtperte * sqrtperte - 1); + else + coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv)); + + coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8; + coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16; + coeffs[pos + 1] |= (coefh * coefv) << 24; +#else + pos = start_y + x; + pos10[pos] = npx10 + prevX * npy10; + + if (!(coefh || coefv)) + c[0][pos] = sqrtperte * sqrtperte - 1; + else + c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv); + + c[1][pos] = coefh * (sqrtperte - coefv); + c[2][pos] = (sqrtperte - coefh) * coefv; + c[3][pos] = coefh * coefv; +#endif + } + } + /* Advance start of line index */ + start_y += prevX; + } + } +#ifdef USE_ASM +#ifdef MMX + zoom_width = prevX; + mmx_zoom_size = prevX * prevY; + mmx_zoom (); +#endif + +#ifdef POWERPC + zoom_width = prevX; + if (useAltivec) { + ppcsize4 = ((unsigned int) (prevX * prevY)) / 4; + ppc_zoom_altivec (); + } else { + ppcsize4 = ((unsigned int) (prevX * prevY)); + ppc_zoom (); + } +#endif +#else + for (position = 0; position < prevX * prevY; position++) { + getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx, + goomdata->resoly); + getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx, + goomdata->resoly); + getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx, + goomdata->resoly); + getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx, + goomdata->resoly); + + couleur.r = col1.r * c[0][position] + + col2.r * c[1][position] + + col3.r * c[2][position] + + col4.r * c[3][position]; + couleur.r >>= zf->pertedec; + + couleur.v = col1.v * c[0][position] + + col2.v * c[1][position] + + col3.v * c[2][position] + + col4.v * c[3][position]; + couleur.v >>= zf->pertedec; + + couleur.b = col1.b * c[0][position] + + col2.b * c[1][position] + + col3.b * c[2][position] + + col4.b * c[3][position]; + couleur.b >>= zf->pertedec; + + setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly); + } +#endif +} + + +void +pointFilter (GoomData * goomdata, Color c, + float t1, float t2, float t3, float t4, Uint cycle) +{ + Uint *pix1 = goomdata->p1; + ZoomFilterData *zf = goomdata->zfd; + Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3))); + Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4))); + + if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2) + && (y < goomdata->resoly - 2)) { + setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly); + setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly); + setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly); + setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly); + setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly); + } +} |