diff options
Diffstat (limited to 'gst/goom/convolve_fx.c')
-rw-r--r-- | gst/goom/convolve_fx.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/gst/goom/convolve_fx.c b/gst/goom/convolve_fx.c new file mode 100644 index 0000000..980e113 --- /dev/null +++ b/gst/goom/convolve_fx.c @@ -0,0 +1,368 @@ +/* Goom Project + * Copyright (C) <2003> iOS-Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "goom_fx.h" +#include "goom_plugin_info.h" +#include "goom_config.h" +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +//#define CONV_MOTIF_W 32 +//#define CONV_MOTIF_WMASK 0x1f + +/* Define if you like the wacky GOOM logo: */ +#undef DRAW_MOTIF + +#define CONV_MOTIF_W 128 +#define CONV_MOTIF_WMASK 0x7f + +typedef char Motif[CONV_MOTIF_W][CONV_MOTIF_W]; + +#include "motif_goom1.h" +#include "motif_goom2.h" + +#define NB_THETA 512 + +typedef struct _CONV_DATA +{ + PluginParam light; + PluginParam factor_adj_p; + PluginParam factor_p; + PluginParameters params; + + /* rotozoom */ + int theta; + float ftheta; + int h_sin[NB_THETA]; + int h_cos[NB_THETA]; + int h_height; + float visibility; + Motif conv_motif; + int inverse_motif; + +} ConvData; + +/* init rotozoom tables */ +static void +compute_tables (VisualFX * _this, PluginInfo * info) +{ + ConvData *data = (ConvData *) _this->fx_data; + double screen_coef; + int i; + double h; + double radian; + + if (data->h_height == info->screen.height) + return; + + screen_coef = 2.0 * 300.0 / (double) info->screen.height; + data->h_height = info->screen.height; + + for (i = 0; i < NB_THETA; i++) { + radian = 2 * i * G_PI / NB_THETA; + h = (0.2 + cos (radian) / 15.0 * sin (radian * 2.0 + 12.123)) * screen_coef; + data->h_cos[i] = 0x10000 * (-h * cos (radian) * cos (radian)); + data->h_sin[i] = 0x10000 * (h * sin (radian + 1.57) * sin (radian)); + } +} + +static void +set_motif (ConvData * data, Motif motif) +{ + int i, j; + + for (i = 0; i < CONV_MOTIF_W; ++i) + for (j = 0; j < CONV_MOTIF_W; ++j) + data->conv_motif[i][j] = + motif[CONV_MOTIF_W - i - 1][CONV_MOTIF_W - j - 1]; +} + +static void +convolve_init (VisualFX * _this, PluginInfo * info) +{ + ConvData *data; + + data = (ConvData *) malloc (sizeof (ConvData)); + _this->fx_data = (void *) data; + + secure_f_param (&data->light, "Screen Brightness"); + data->light.param.fval.max = 300.0f; + data->light.param.fval.step = 1.0f; + data->light.param.fval.value = 100.0f; + + secure_f_param (&data->factor_adj_p, "Flash Intensity"); + data->factor_adj_p.param.fval.max = 200.0f; + data->factor_adj_p.param.fval.step = 1.0f; + data->factor_adj_p.param.fval.value = 70.0f; + + secure_f_feedback (&data->factor_p, "Factor"); + + plugin_parameters (&data->params, "Bright Flash", 5); + data->params.params[0] = &data->light; + data->params.params[1] = &data->factor_adj_p; + data->params.params[2] = 0; + data->params.params[3] = &data->factor_p; + data->params.params[4] = 0; + + data->h_height = 0; + + /* init rotozoom tables */ + compute_tables (_this, info); + data->theta = 0; + data->ftheta = 0.0; + data->visibility = 1.0; + set_motif (data, CONV_MOTIF2); + data->inverse_motif = 0; + + _this->params = &data->params; +} + +static void +convolve_free (VisualFX * _this) +{ + ConvData *data = (ConvData *) _this->fx_data; + + goom_plugin_parameters_free (&data->params); + + free (_this->fx_data); +} + +#ifdef DRAW_MOTIF +static void +create_output_with_brightness (VisualFX * _this, Pixel * src, Pixel * dest, + PluginInfo * info, int iff) +{ + ConvData *data = (ConvData *) _this->fx_data; + + int x, y; + int i = 0; //info->screen.height * info->screen.width - 1; + + const int c = data->h_cos[data->theta]; + const int s = data->h_sin[data->theta]; + + const int xi = -(info->screen.width / 2) * c; + const int yi = (info->screen.width / 2) * s; + + const int xj = -(info->screen.height / 2) * s; + const int yj = -(info->screen.height / 2) * c; + + int xprime = xj; + int yprime = yj; + + int ifftab[16]; + + if (data->inverse_motif) { + int i; + + for (i = 0; i < 16; ++i) + ifftab[i] = (double) iff *(1.0 + data->visibility * (15.0 - i) / 15.0); + } else { + int i; + + for (i = 0; i < 16; ++i) + ifftab[i] = (double) iff / (1.0 + data->visibility * (15.0 - i) / 15.0); + } + + for (y = info->screen.height; y--;) { + int xtex, ytex; + + xtex = xprime + xi + CONV_MOTIF_W * 0x10000 / 2; + xprime += s; + + ytex = yprime + yi + CONV_MOTIF_W * 0x10000 / 2; + yprime += c; + +#ifdef HAVE_MMX + __asm__ __volatile__ ("\n\t pxor %%mm7, %%mm7" /* mm7 = 0 */ + "\n\t movd %[xtex], %%mm2" "\n\t movd %[ytex], %%mm3" "\n\t punpckldq %%mm3, %%mm2" /* mm2 = [ ytex | xtex ] */ + "\n\t movd %[c], %%mm4" "\n\t movd %[s], %%mm6" "\n\t pxor %%mm5, %%mm5" "\n\t psubd %%mm6, %%mm5" "\n\t punpckldq %%mm5, %%mm4" /* mm4 = [ -s | c ] */ + "\n\t movd %[motif], %%mm6" /* mm6 = motif */ + ::[xtex] "g" (xtex),[ytex] "g" (ytex) + ,[c] "g" (c),[s] "g" (s) + ,[motif] "g" (&data->conv_motif[0][0])); + + for (x = info->screen.width; x--;) { + __asm__ __volatile__ ("\n\t movd %[src], %%mm0" /* mm0 = src */ + "\n\t paddd %%mm4, %%mm2" /* [ ytex | xtex ] += [ -s | s ] */ + "\n\t movd %%esi, %%mm5" /* save esi into mm5 */ + "\n\t movq %%mm2, %%mm3" "\n\t psrld $16, %%mm3" /* mm3 = [ (ytex>>16) | (xtex>>16) ] */ + "\n\t movd %%mm3, %%eax" /* eax = xtex' */ + "\n\t psrlq $25, %%mm3" "\n\t movd %%mm3, %%ecx" /* ecx = ytex' << 7 */ + "\n\t andl $127, %%eax" "\n\t andl $16256, %%ecx" "\n\t addl %%ecx, %%eax" "\n\t movd %%mm6, %%esi" /* esi = motif */ + "\n\t xorl %%ecx, %%ecx" "\n\t movb (%%eax,%%esi), %%cl" "\n\t movl %[ifftab], %%eax" "\n\t movd %%mm5, %%esi" /* restore esi from mm5 */ + "\n\t movd (%%eax,%%ecx,4), %%mm1" /* mm1 = [0|0|0|iff2] */ + "\n\t punpcklwd %%mm1, %%mm1" + "\n\t punpcklbw %%mm7, %%mm0" + "\n\t punpckldq %%mm1, %%mm1" + "\n\t psrlw $1, %%mm0" + "\n\t psrlw $2, %%mm1" + "\n\t pmullw %%mm1, %%mm0" + "\n\t psrlw $5, %%mm0" + "\n\t packuswb %%mm7, %%mm0" + "\n\t movd %%mm0, %[dest]":[dest] "=g" (dest[i].val) + :[src] "g" (src[i].val) + ,[ifftab] "g" (&ifftab[0]) + :"eax", "ecx"); + + i++; + } +#else + for (x = info->screen.width; x--;) { + + int iff2; + unsigned int f0, f1, f2, f3; + + xtex += c; + ytex -= s; + + iff2 = + ifftab[(int) data->conv_motif[(ytex >> 16) & CONV_MOTIF_WMASK][(xtex + >> 16) & CONV_MOTIF_WMASK]]; + +#define sat(a) ((a)>0xFF?0xFF:(a)) + f0 = src[i].val; + f1 = ((f0 >> R_OFFSET) & 0xFF) * iff2 >> 8; + f2 = ((f0 >> G_OFFSET) & 0xFF) * iff2 >> 8; + f3 = ((f0 >> B_OFFSET) & 0xFF) * iff2 >> 8; + dest[i].val = + (sat (f1) << R_OFFSET) | (sat (f2) << G_OFFSET) | (sat (f3) << + B_OFFSET); +/* + f0 = (src[i].cop[0] * iff2) >> 8; + f1 = (src[i].cop[1] * iff2) >> 8; + f2 = (src[i].cop[2] * iff2) >> 8; + f3 = (src[i].cop[3] * iff2) >> 8; + + dest[i].cop[0] = (f0 & 0xffffff00) ? 0xff : (unsigned char)f0; + dest[i].cop[1] = (f1 & 0xffffff00) ? 0xff : (unsigned char)f1; + dest[i].cop[2] = (f2 & 0xffffff00) ? 0xff : (unsigned char)f2; + dest[i].cop[3] = (f3 & 0xffffff00) ? 0xff : (unsigned char)f3; +*/ + i++; + } +#endif + } +#ifdef HAVE_MMX + __asm__ __volatile__ ("\n\t emms"); +#endif + + compute_tables (_this, info); +} +#endif + +/*#include <stdint.h> + +static uint64_t GetTick() +{ + uint64_t x; + asm volatile ("RDTSC" : "=A" (x)); + return x; +}*/ + + +static void +convolve_apply (VisualFX * _this, Pixel * src, Pixel * dest, PluginInfo * info) +{ + + ConvData *data = (ConvData *) _this->fx_data; +#ifdef DRAW_MOTIF + float ff; + int iff; + + ff = (FVAL (data->factor_p) * FVAL (data->factor_adj_p) + + FVAL (data->light)) / 100.0f; + iff = (unsigned int) (ff * 256); +#endif + + { + double fcycle = (double) info->cycle; + double rotate_param, rotate_coef; + float INCREASE_RATE = 1.5; + float DECAY_RATE = 0.955; + + if (FVAL (info->sound.last_goom_p) > 0.8) + FVAL (data->factor_p) += FVAL (info->sound.goom_power_p) * INCREASE_RATE; + FVAL (data->factor_p) *= DECAY_RATE; + + rotate_param = FVAL (info->sound.last_goom_p); + if (rotate_param < 0.0) + rotate_param = 0.0; + rotate_param += FVAL (info->sound.goom_power_p); + + rotate_coef = 4.0 + FVAL (info->sound.goom_power_p) * 6.0; + data->ftheta = (data->ftheta + rotate_coef * sin (rotate_param * 6.3)); + data->theta = ((unsigned int) data->ftheta) % NB_THETA; + data->visibility = + (cos (fcycle * 0.001 + 1.5) * sin (fcycle * 0.008) + + cos (fcycle * 0.011 + 5.0) - 0.8 + info->sound.speedvar) * 1.5; + if (data->visibility < 0.0) + data->visibility = 0.0; + data->factor_p.change_listener (&data->factor_p); + } + + if (data->visibility < 0.01) { + switch (goom_irand (info->gRandom, 300)) { + case 1: + set_motif (data, CONV_MOTIF1); + data->inverse_motif = 1; + break; + case 2: + set_motif (data, CONV_MOTIF2); + data->inverse_motif = 0; + break; + } + } +#ifdef DRAW_MOTIF + if ((ff > 0.98f) && (ff < 1.02f)) + memcpy (dest, src, info->screen.size * sizeof (Pixel)); + else + create_output_with_brightness (_this, src, dest, info, iff); +#else + memcpy (dest, src, info->screen.size * sizeof (Pixel)); +#endif + +/* +// Benching suite... + { + uint64_t before, after; + double timed; + static double stimed = 10000.0; + before = GetTick(); + data->visibility = 1.0; + create_output_with_brightness(_this,src,dest,info,iff); + after = GetTick(); + timed = (double)((after-before) / info->screen.size); + if (timed < stimed) { + stimed = timed; + printf ("CLK = %3.0f CPP\n", stimed); + } + } +*/ +} + +void +convolve_create (VisualFX * vfx) +{ + vfx->init = convolve_init; + vfx->free = convolve_free; + vfx->apply = convolve_apply; + vfx->fx_data = NULL; + vfx->params = NULL; +} |