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