| /* 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; |
| } |