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 #include "goom_fx.h"
20 #include "goom_plugin_info.h"
21 #include "goom_config.h"
22 #include <math.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 //#define CONV_MOTIF_W 32
28 //#define CONV_MOTIF_WMASK 0x1f
29 
30 /* Define if you like the wacky GOOM logo: */
31 #undef DRAW_MOTIF
32 
33 #define CONV_MOTIF_W 128
34 #define CONV_MOTIF_WMASK 0x7f
35 
36 typedef char Motif[CONV_MOTIF_W][CONV_MOTIF_W];
37 
38 #include "motif_goom1.h"
39 #include "motif_goom2.h"
40 
41 #define NB_THETA 512
42 
43 typedef struct _CONV_DATA
44 {
45   PluginParam light;
46   PluginParam factor_adj_p;
47   PluginParam factor_p;
48   PluginParameters params;
49 
50   /* rotozoom */
51   int theta;
52   float ftheta;
53   int h_sin[NB_THETA];
54   int h_cos[NB_THETA];
55   int h_height;
56   float visibility;
57   Motif conv_motif;
58   int inverse_motif;
59 
60 } ConvData;
61 
62 /* init rotozoom tables */
63 static void
compute_tables(VisualFX * _this,PluginInfo * info)64 compute_tables (VisualFX * _this, PluginInfo * info)
65 {
66   ConvData *data = (ConvData *) _this->fx_data;
67   double screen_coef;
68   int i;
69   double h;
70   double radian;
71 
72   if (data->h_height == info->screen.height)
73     return;
74 
75   screen_coef = 2.0 * 300.0 / (double) info->screen.height;
76   data->h_height = info->screen.height;
77 
78   for (i = 0; i < NB_THETA; i++) {
79     radian = 2 * i * G_PI / NB_THETA;
80     h = (0.2 + cos (radian) / 15.0 * sin (radian * 2.0 + 12.123)) * screen_coef;
81     data->h_cos[i] = 0x10000 * (-h * cos (radian) * cos (radian));
82     data->h_sin[i] = 0x10000 * (h * sin (radian + 1.57) * sin (radian));
83   }
84 }
85 
86 static void
set_motif(ConvData * data,Motif motif)87 set_motif (ConvData * data, Motif motif)
88 {
89   int i, j;
90 
91   for (i = 0; i < CONV_MOTIF_W; ++i)
92     for (j = 0; j < CONV_MOTIF_W; ++j)
93       data->conv_motif[i][j] =
94           motif[CONV_MOTIF_W - i - 1][CONV_MOTIF_W - j - 1];
95 }
96 
97 static void
convolve_init(VisualFX * _this,PluginInfo * info)98 convolve_init (VisualFX * _this, PluginInfo * info)
99 {
100   ConvData *data;
101 
102   data = (ConvData *) malloc (sizeof (ConvData));
103   _this->fx_data = (void *) data;
104 
105   secure_f_param (&data->light, "Screen Brightness");
106   data->light.param.fval.max = 300.0f;
107   data->light.param.fval.step = 1.0f;
108   data->light.param.fval.value = 100.0f;
109 
110   secure_f_param (&data->factor_adj_p, "Flash Intensity");
111   data->factor_adj_p.param.fval.max = 200.0f;
112   data->factor_adj_p.param.fval.step = 1.0f;
113   data->factor_adj_p.param.fval.value = 70.0f;
114 
115   secure_f_feedback (&data->factor_p, "Factor");
116 
117   plugin_parameters (&data->params, "Bright Flash", 5);
118   data->params.params[0] = &data->light;
119   data->params.params[1] = &data->factor_adj_p;
120   data->params.params[2] = 0;
121   data->params.params[3] = &data->factor_p;
122   data->params.params[4] = 0;
123 
124   data->h_height = 0;
125 
126   /* init rotozoom tables */
127   compute_tables (_this, info);
128   data->theta = 0;
129   data->ftheta = 0.0;
130   data->visibility = 1.0;
131   set_motif (data, CONV_MOTIF2);
132   data->inverse_motif = 0;
133 
134   _this->params = &data->params;
135 }
136 
137 static void
convolve_free(VisualFX * _this)138 convolve_free (VisualFX * _this)
139 {
140   ConvData *data = (ConvData *) _this->fx_data;
141 
142   goom_plugin_parameters_free (&data->params);
143 
144   free (_this->fx_data);
145 }
146 
147 #ifdef DRAW_MOTIF
148 static void
create_output_with_brightness(VisualFX * _this,Pixel * src,Pixel * dest,PluginInfo * info,int iff)149 create_output_with_brightness (VisualFX * _this, Pixel * src, Pixel * dest,
150     PluginInfo * info, int iff)
151 {
152   ConvData *data = (ConvData *) _this->fx_data;
153 
154   int x, y;
155   int i = 0;                    //info->screen.height * info->screen.width - 1;
156 
157   const int c = data->h_cos[data->theta];
158   const int s = data->h_sin[data->theta];
159 
160   const int xi = -(info->screen.width / 2) * c;
161   const int yi = (info->screen.width / 2) * s;
162 
163   const int xj = -(info->screen.height / 2) * s;
164   const int yj = -(info->screen.height / 2) * c;
165 
166   int xprime = xj;
167   int yprime = yj;
168 
169   int ifftab[16];
170 
171   if (data->inverse_motif) {
172     int i;
173 
174     for (i = 0; i < 16; ++i)
175       ifftab[i] = (double) iff *(1.0 + data->visibility * (15.0 - i) / 15.0);
176   } else {
177     int i;
178 
179     for (i = 0; i < 16; ++i)
180       ifftab[i] = (double) iff / (1.0 + data->visibility * (15.0 - i) / 15.0);
181   }
182 
183   for (y = info->screen.height; y--;) {
184     int xtex, ytex;
185 
186     xtex = xprime + xi + CONV_MOTIF_W * 0x10000 / 2;
187     xprime += s;
188 
189     ytex = yprime + yi + CONV_MOTIF_W * 0x10000 / 2;
190     yprime += c;
191 
192 #ifdef HAVE_MMX
193     __asm__ __volatile__ ("\n\t pxor  %%mm7,  %%mm7"    /* mm7 = 0   */
194         "\n\t movd %[xtex],  %%mm2" "\n\t movd %[ytex],  %%mm3" "\n\t punpckldq %%mm3, %%mm2"   /* mm2 = [ ytex | xtex ] */
195         "\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 ]      */
196         "\n\t movd %[motif], %%mm6"     /* mm6 = motif           */
197         ::[xtex] "g" (xtex),[ytex] "g" (ytex)
198         ,[c] "g" (c),[s] "g" (s)
199         ,[motif] "g" (&data->conv_motif[0][0]));
200 
201     for (x = info->screen.width; x--;) {
202       __asm__ __volatile__ ("\n\t movd  %[src], %%mm0"  /* mm0 = src */
203           "\n\t paddd %%mm4, %%mm2"     /* [ ytex | xtex ] += [ -s | s ] */
204           "\n\t movd  %%esi, %%mm5"     /* save esi into mm5 */
205           "\n\t movq  %%mm2, %%mm3" "\n\t psrld  $16,  %%mm3"   /* mm3 = [ (ytex>>16) | (xtex>>16) ] */
206           "\n\t movd  %%mm3, %%eax"     /* eax = xtex' */
207           "\n\t psrlq $25,   %%mm3" "\n\t movd  %%mm3, %%ecx"   /* ecx = ytex' << 7 */
208           "\n\t andl  $127, %%eax" "\n\t andl  $16256, %%ecx" "\n\t addl  %%ecx, %%eax" "\n\t movd  %%mm6, %%esi"       /* esi = motif */
209           "\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 */
210           "\n\t movd  (%%eax,%%ecx,4), %%mm1"   /* mm1 = [0|0|0|iff2] */
211           "\n\t punpcklwd %%mm1, %%mm1"
212           "\n\t punpcklbw %%mm7, %%mm0"
213           "\n\t punpckldq %%mm1, %%mm1"
214           "\n\t psrlw     $1,    %%mm0"
215           "\n\t psrlw     $2,    %%mm1"
216           "\n\t pmullw    %%mm1, %%mm0"
217           "\n\t psrlw     $5,    %%mm0"
218           "\n\t packuswb  %%mm7, %%mm0"
219           "\n\t movd      %%mm0, %[dest]":[dest] "=g" (dest[i].val)
220           :[src] "g" (src[i].val)
221           ,[ifftab] "g" (&ifftab[0])
222           :"eax", "ecx");
223 
224       i++;
225     }
226 #else
227     for (x = info->screen.width; x--;) {
228 
229       int iff2;
230       unsigned int f0, f1, f2, f3;
231 
232       xtex += c;
233       ytex -= s;
234 
235       iff2 =
236           ifftab[(int) data->conv_motif[(ytex >> 16) & CONV_MOTIF_WMASK][(xtex
237                   >> 16) & CONV_MOTIF_WMASK]];
238 
239 #define sat(a) ((a)>0xFF?0xFF:(a))
240       f0 = src[i].val;
241       f1 = ((f0 >> R_OFFSET) & 0xFF) * iff2 >> 8;
242       f2 = ((f0 >> G_OFFSET) & 0xFF) * iff2 >> 8;
243       f3 = ((f0 >> B_OFFSET) & 0xFF) * iff2 >> 8;
244       dest[i].val =
245           (sat (f1) << R_OFFSET) | (sat (f2) << G_OFFSET) | (sat (f3) <<
246           B_OFFSET);
247 /*
248       f0 = (src[i].cop[0] * iff2) >> 8;
249       f1 = (src[i].cop[1] * iff2) >> 8;
250       f2 = (src[i].cop[2] * iff2) >> 8;
251       f3 = (src[i].cop[3] * iff2) >> 8;
252 
253       dest[i].cop[0] = (f0 & 0xffffff00) ? 0xff : (unsigned char)f0;
254       dest[i].cop[1] = (f1 & 0xffffff00) ? 0xff : (unsigned char)f1;
255       dest[i].cop[2] = (f2 & 0xffffff00) ? 0xff : (unsigned char)f2;
256       dest[i].cop[3] = (f3 & 0xffffff00) ? 0xff : (unsigned char)f3;
257 */
258       i++;
259     }
260 #endif
261   }
262 #ifdef HAVE_MMX
263   __asm__ __volatile__ ("\n\t emms");
264 #endif
265 
266   compute_tables (_this, info);
267 }
268 #endif
269 
270 /*#include <stdint.h>
271 
272 static uint64_t GetTick()
273 {
274   uint64_t x;
275   asm volatile ("RDTSC" : "=A" (x));
276   return x;
277 }*/
278 
279 
280 static void
convolve_apply(VisualFX * _this,Pixel * src,Pixel * dest,PluginInfo * info)281 convolve_apply (VisualFX * _this, Pixel * src, Pixel * dest, PluginInfo * info)
282 {
283 
284   ConvData *data = (ConvData *) _this->fx_data;
285 #ifdef DRAW_MOTIF
286   float ff;
287   int iff;
288 
289   ff = (FVAL (data->factor_p) * FVAL (data->factor_adj_p) +
290       FVAL (data->light)) / 100.0f;
291   iff = (unsigned int) (ff * 256);
292 #endif
293 
294   {
295     double fcycle = (double) info->cycle;
296     double rotate_param, rotate_coef;
297     float INCREASE_RATE = 1.5;
298     float DECAY_RATE = 0.955;
299 
300     if (FVAL (info->sound.last_goom_p) > 0.8)
301       FVAL (data->factor_p) += FVAL (info->sound.goom_power_p) * INCREASE_RATE;
302     FVAL (data->factor_p) *= DECAY_RATE;
303 
304     rotate_param = FVAL (info->sound.last_goom_p);
305     if (rotate_param < 0.0)
306       rotate_param = 0.0;
307     rotate_param += FVAL (info->sound.goom_power_p);
308 
309     rotate_coef = 4.0 + FVAL (info->sound.goom_power_p) * 6.0;
310     data->ftheta = (data->ftheta + rotate_coef * sin (rotate_param * 6.3));
311     data->theta = ((unsigned int) data->ftheta) % NB_THETA;
312     data->visibility =
313         (cos (fcycle * 0.001 + 1.5) * sin (fcycle * 0.008) +
314         cos (fcycle * 0.011 + 5.0) - 0.8 + info->sound.speedvar) * 1.5;
315     if (data->visibility < 0.0)
316       data->visibility = 0.0;
317     data->factor_p.change_listener (&data->factor_p);
318   }
319 
320   if (data->visibility < 0.01) {
321     switch (goom_irand (info->gRandom, 300)) {
322       case 1:
323         set_motif (data, CONV_MOTIF1);
324         data->inverse_motif = 1;
325         break;
326       case 2:
327         set_motif (data, CONV_MOTIF2);
328         data->inverse_motif = 0;
329         break;
330     }
331   }
332 #ifdef DRAW_MOTIF
333   if ((ff > 0.98f) && (ff < 1.02f))
334     memcpy (dest, src, info->screen.size * sizeof (Pixel));
335   else
336     create_output_with_brightness (_this, src, dest, info, iff);
337 #else
338   memcpy (dest, src, info->screen.size * sizeof (Pixel));
339 #endif
340 
341 /*
342 //   Benching suite...
343    {
344     uint64_t before, after;
345     double   timed;
346     static double stimed = 10000.0;
347     before = GetTick();
348     data->visibility = 1.0;
349     create_output_with_brightness(_this,src,dest,info,iff);
350     after  = GetTick();
351     timed = (double)((after-before) / info->screen.size);
352     if (timed < stimed) {
353       stimed = timed;
354       printf ("CLK = %3.0f CPP\n", stimed);
355     }
356   }
357 */
358 }
359 
360 void
convolve_create(VisualFX * vfx)361 convolve_create (VisualFX * vfx)
362 {
363   vfx->init = convolve_init;
364   vfx->free = convolve_free;
365   vfx->apply = convolve_apply;
366   vfx->fx_data = NULL;
367   vfx->params = NULL;
368 }
369