Mercurial > audlegacy
annotate Plugins/Visualization/paranormal/pn/pndisplacement.c @ 1729:3ee4c6d45c27 trunk
[svn] Fixed unused variable and missing type conversion
author | js |
---|---|
date | Sat, 16 Sep 2006 19:37:08 -0700 |
parents | a898e415ad8f |
children |
rev | line source |
---|---|
1507 | 1 /* Paranormal - A highly customizable audio visualization library |
2 * Copyright (C) 2001 Jamie Gennis <jgennis@mindspring.com> | |
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 Free | |
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 */ | |
18 | |
19 #include <math.h> | |
20 #include <glib.h> | |
1585
a898e415ad8f
[svn] An include a day keeps the implicit declaration at bay.
chainsaw
parents:
1507
diff
changeset
|
21 #include <string.h> |
1507 | 22 #include "pndisplacement.h" |
23 #include "pnbooleanoption.h" | |
24 #include "pnstringoption.h" | |
25 #include "pncpu.h" | |
26 | |
27 enum | |
28 { | |
29 PN_PIXEL_DISPLACEMENT_NO_PIXEL = 0xffffffff | |
30 }; | |
31 | |
32 static void pn_displacement_class_init (PnDisplacementClass *class); | |
33 static void pn_displacement_init (PnDisplacement *displacement, | |
34 PnDisplacementClass *class); | |
35 /* PnObject signals */ | |
36 static void pn_displacement_destroy (PnObject *object); | |
37 | |
38 /* PnActuator methods */ | |
39 static void pn_displacement_prepare (PnDisplacement *displacement, | |
40 PnImage *image); | |
41 static void pn_displacement_execute (PnDisplacement *displacement, | |
42 PnImage *image, | |
43 PnAudioData *audio_data); | |
44 | |
45 static PnActuatorClass *parent_class = NULL; | |
46 | |
47 GType | |
48 pn_displacement_get_type (void) | |
49 { | |
50 static GType displacement_type = 0; | |
51 | |
52 if (! displacement_type) | |
53 { | |
54 static const GTypeInfo displacement_info = | |
55 { | |
56 sizeof (PnDisplacementClass), | |
57 NULL, /* base_init */ | |
58 NULL, /* base_finalize */ | |
59 (GClassInitFunc) pn_displacement_class_init, | |
60 NULL, /* class_finalize */ | |
61 NULL, /* class_data */ | |
62 sizeof (PnDisplacement), | |
63 0, /* n_preallocs */ | |
64 (GInstanceInitFunc) pn_displacement_init | |
65 }; | |
66 | |
67 /* FIXME: should this be dynamic? */ | |
68 displacement_type = g_type_register_static (PN_TYPE_ACTUATOR, | |
69 "PnDisplacement", | |
70 &displacement_info, | |
71 0); | |
72 } | |
73 return displacement_type; | |
74 } | |
75 | |
76 static void | |
77 pn_displacement_class_init (PnDisplacementClass *class) | |
78 { | |
79 GObjectClass *gobject_class; | |
80 PnObjectClass *object_class; | |
81 PnUserObjectClass *user_object_class; | |
82 PnActuatorClass *actuator_class; | |
83 | |
84 parent_class = g_type_class_peek_parent (class); | |
85 | |
86 gobject_class = (GObjectClass *) class; | |
87 object_class = (PnObjectClass *) class; | |
88 user_object_class = (PnUserObjectClass *) class; | |
89 actuator_class = (PnActuatorClass *) class; | |
90 | |
91 /* PnObject signals */ | |
92 object_class->destroy = pn_displacement_destroy; | |
93 | |
94 /* PnActuator methods */ | |
95 actuator_class->prepare = (PnActuatorPrepFunc) pn_displacement_prepare; | |
96 actuator_class->execute = (PnActuatorExecFunc) pn_displacement_execute; | |
97 } | |
98 | |
99 static void | |
100 pn_displacement_init (PnDisplacement *displacement, PnDisplacementClass *class) | |
101 { | |
102 PnStringOption *init_script_opt, *frame_script_opt; | |
103 | |
104 /* Set up the name and description */ | |
105 pn_user_object_set_name (PN_USER_OBJECT (displacement), "Transform.Displacement"); | |
106 pn_user_object_set_description (PN_USER_OBJECT (displacement), | |
107 "Displaces the image"); | |
108 | |
109 /* Set up the options */ | |
110 init_script_opt = pn_string_option_new ("init_script", "The initialization script"); | |
111 frame_script_opt = pn_string_option_new ("frame_script", "The per-frame script"); | |
112 | |
113 pn_actuator_add_option (PN_ACTUATOR (displacement), PN_OPTION (init_script_opt)); | |
114 pn_actuator_add_option (PN_ACTUATOR (displacement), PN_OPTION (frame_script_opt)); | |
115 | |
116 /* Create the script objects and symbol table */ | |
117 displacement->init_script = pn_script_new (); | |
118 pn_object_ref (PN_OBJECT (displacement->init_script)); | |
119 pn_object_sink (PN_OBJECT (displacement->init_script)); | |
120 displacement->frame_script = pn_script_new (); | |
121 pn_object_ref (PN_OBJECT (displacement->frame_script)); | |
122 pn_object_sink (PN_OBJECT (displacement->frame_script)); | |
123 displacement->symbol_table = pn_symbol_table_new (); | |
124 pn_object_ref (PN_OBJECT (displacement->symbol_table)); | |
125 pn_object_sink (PN_OBJECT (displacement->symbol_table)); | |
126 | |
127 /* Get the variables from the symbol table */ | |
128 displacement->x_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "x"); | |
129 displacement->y_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "y"); | |
130 displacement->volume_var = pn_symbol_table_ref_variable_by_name (displacement->symbol_table, "volume"); | |
131 } | |
132 | |
133 static void | |
134 pn_displacement_destroy (PnObject *object) | |
135 { | |
136 PnDisplacement *displacement; | |
137 | |
138 displacement = (PnDisplacement *) object; | |
139 | |
140 pn_object_unref (PN_OBJECT (displacement->init_script)); | |
141 pn_object_unref (PN_OBJECT (displacement->frame_script)); | |
142 pn_object_unref (PN_OBJECT (displacement->symbol_table)); | |
143 } | |
144 | |
145 /* FIXME: optimize this */ | |
146 static void | |
147 pn_displacement_prepare (PnDisplacement *displacement, PnImage *image) | |
148 { | |
149 PnStringOption *init_script_opt, *frame_script_opt; | |
150 | |
151 g_return_if_fail (displacement != NULL); | |
152 g_return_if_fail (PN_IS_DISPLACEMENT (displacement)); | |
153 g_return_if_fail (image != NULL); | |
154 g_return_if_fail (PN_IS_IMAGE (image)); | |
155 | |
156 /* Parse the script strings */ | |
157 init_script_opt = | |
158 (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (displacement), | |
159 PN_DISPLACEMENT_OPT_INIT_SCRIPT); | |
160 frame_script_opt = | |
161 (PnStringOption *) pn_actuator_get_option_by_index (PN_ACTUATOR (displacement), | |
162 PN_DISPLACEMENT_OPT_FRAME_SCRIPT); | |
163 | |
164 pn_script_parse_string (displacement->init_script, displacement->symbol_table, | |
165 pn_string_option_get_value (init_script_opt)); | |
166 pn_script_parse_string (displacement->frame_script, displacement->symbol_table, | |
167 pn_string_option_get_value (frame_script_opt)); | |
168 | |
169 /* Set up 0 displacement */ | |
170 PN_VARIABLE_VALUE (displacement->x_var) = 0.0; | |
171 PN_VARIABLE_VALUE (displacement->y_var) = 0.0; | |
172 | |
173 /* Run the init script */ | |
174 pn_script_execute (displacement->init_script); | |
175 | |
176 if (PN_ACTUATOR_CLASS (parent_class)->prepare) | |
177 PN_ACTUATOR_CLASS (parent_class)->prepare (PN_ACTUATOR (displacement), image); | |
178 } | |
179 | |
180 static void | |
181 pn_displacement_exec (PnImage *image, gint offset, guint nw, guint ne, guint sw, guint se, | |
182 gint startx, gint starty, gint endx, gint endy) | |
183 { | |
184 gint i, j, width, height, stride; | |
185 PnColor *src, *dest, zero = {0,0,0,0}; | |
186 guint r, g, b; | |
187 | |
188 width = pn_image_get_width (image); | |
189 height = pn_image_get_height (image); | |
190 stride = pn_image_get_pitch (image) >> 2; | |
191 | |
192 src = pn_image_get_image_buffer (image); | |
193 dest = pn_image_get_transform_buffer (image); | |
194 | |
195 for (j=0; j<height; j++) | |
196 for (i=0; i<width; i++) | |
197 { | |
198 if (i < startx || i >= endx | |
199 || j < starty || j >= endy) | |
200 dest[j * stride + i] = zero; | |
201 else | |
202 { | |
203 r = src[(j * stride + i) + offset].red * nw; | |
204 g = src[(j * stride + i) + offset].green * nw; | |
205 b = src[(j * stride + i) + offset].blue * nw; | |
206 | |
207 r += src[(j * stride + (i + 1)) + offset].red * ne; | |
208 g += src[(j * stride + (i + 1)) + offset].green * ne; | |
209 b += src[(j * stride + (i + 1)) + offset].blue * ne; | |
210 | |
211 r += src[((j + 1) * stride + i) + offset].red * sw; | |
212 g += src[((j + 1) * stride + i) + offset].green * sw; | |
213 b += src[((j + 1) * stride + i) + offset].blue * sw; | |
214 | |
215 r += src[((j + 1) * stride + (i + 1)) + offset].red * se; | |
216 g += src[((j + 1) * stride + (i + 1)) + offset].green * se; | |
217 b += src[((j + 1) * stride + (i + 1)) + offset].blue * se; | |
218 | |
219 dest[j * stride + i].red = r >> 7; | |
220 dest[j * stride + i].green = g >> 7; | |
221 dest[j * stride + i].blue = b >> 7; | |
222 } | |
223 } | |
224 } | |
225 | |
226 #ifdef PN_USE_MMX | |
227 static void | |
228 pn_displacement_exec_mmx (PnImage *image, gint offset, guint nw, guint ne, guint sw, guint se, | |
229 gint startx, gint starty, gint endx, gint endy) | |
230 { | |
231 PnColor *src, *dest, *endptr; | |
232 gint width, height, stride, i; | |
233 guint64 upnw; /* a place to store the unpacked se weight */ | |
234 | |
235 width = pn_image_get_width (image); | |
236 height = pn_image_get_height (image); | |
237 stride = pn_image_get_pitch (image) >> 2; | |
238 | |
239 src = pn_image_get_image_buffer (image); | |
240 dest = pn_image_get_transform_buffer (image); | |
241 | |
242 memset (dest, 0, pn_image_get_pitch (image) * starty); | |
243 for (i=MAX(starty, 0); i<endy; i++) | |
244 { | |
245 memset (dest + i * stride, 0, startx * sizeof (PnColor)); | |
246 memset (dest + i * stride + endx, 0, (width - endx) * sizeof (PnColor)); | |
247 } | |
248 memset (dest + endy * stride, 0, (height - endy) * pn_image_get_pitch (image)); | |
249 | |
250 src += (starty * stride) + offset; | |
251 endptr = src + endx; | |
252 src += startx; | |
253 dest += (starty * stride) + startx; | |
254 | |
255 __asm__ __volatile__ ( | |
256 /* Unpack the weights */ | |
257 "pxor %%mm7,%%mm7\n\t" /* zero mm7 for unpacking */ | |
258 "movd %8,%%mm4\n\t" /* load the weights */ | |
259 "punpcklbw %%mm7,%%mm4\n\t" /* unpack the weights to words */ | |
260 "movq %%mm4,%%mm6\n\t" /* copy the weights for separate expansion */ | |
261 "punpcklwd %%mm4,%%mm4\n\t" /* expand the top weights */ | |
262 "punpckhwd %%mm6,%%mm6\n\t" /* expand the bottom weights */ | |
263 "movq %%mm4,%%mm5\n\t" /* copy the top pixels for separate expansion */ | |
264 "movq %%mm6,%%mm7\n\t" /* copy the bottom pixels for separate expansion */ | |
265 "punpckldq %%mm4,%%mm4\n\t" /* expand the NW weight */ | |
266 "punpckhdq %%mm5,%%mm5\n\t" /* expand the NE weight */ | |
267 "punpckldq %%mm6,%%mm6\n\t" /* expand the SW weight */ | |
268 "punpckhdq %%mm7,%%mm7\n\t" /* expand the SE weight */ | |
269 "movq %%mm7,%4\n\t" /* save the SE weight so we can use mm7 as 0 */ | |
270 "pxor %%mm7,%%mm7\n\t" /* re-zero mm7 */ | |
271 | |
272 "10:\n\t" | |
273 | |
274 /* zero mm7 for unpacking */ | |
275 "pxor %%mm7,%%mm7\n\t" | |
276 | |
277 /* load & unpack the pixels */ | |
278 "movd (%0),%%mm0\n\t" | |
279 "punpcklbw %%mm7,%%mm0\n\t" | |
280 "movd 4(%0),%%mm1\n\t" | |
281 "punpcklbw %%mm7,%%mm1\n\t" | |
282 "movd (%0,%5),%%mm2\n\t" | |
283 "punpcklbw %%mm7,%%mm2\n\t" | |
284 "movd 4(%0,%5),%%mm3\n\t" | |
285 "punpcklbw %%mm7,%%mm3\n\t" | |
286 | |
287 /* reload the unpacked se weight */ | |
288 "movq %4,%%mm7\n\t" | |
289 | |
290 /* weight each pixel */ | |
291 "pmullw %%mm4,%%mm0\n\t" | |
292 "pmullw %%mm5,%%mm1\n\t" | |
293 "pmullw %%mm6,%%mm2\n\t" | |
294 "pmullw %%mm7,%%mm3\n\t" | |
295 | |
296 /* add up the weighted pixels */ | |
297 "paddw %%mm1,%%mm0\n\t" | |
298 "paddw %%mm2,%%mm0\n\t" | |
299 "paddw %%mm3,%%mm0\n\t" | |
300 | |
301 /* normalize the resulting pixel, pack it, and write it */ | |
302 "psrlw $7,%%mm0\n\t" | |
303 "packuswb %%mm0,%%mm0\n\t" | |
304 "movd %%mm0,(%1)\n\t" | |
305 | |
306 /* advance the pointers */ | |
307 "addl $4,%0\n\t" | |
308 "addl $4,%1\n\t" | |
309 | |
310 /* see if we're done with this line */ | |
311 "cmpl %3,%0\n\t" | |
312 "jl 10b\n\t" | |
313 | |
314 /* advance the pointers */ | |
315 "addl %7,%0\n\t" | |
316 "addl %7,%1\n\t" | |
317 "addl %5,%3\n\t" | |
318 | |
319 /* see if we're done */ | |
320 "incl %2\n\t" | |
321 "cmpl %6,%2\n\t" | |
322 "jl 10b\n\t" | |
323 | |
324 "emms\n\t" | |
325 | |
326 : /* no outputs */ | |
327 : "r" (src), /* 0 */ | |
328 "r" (dest), /* 1 */ | |
329 "r" (starty), /* 2 */ | |
330 "m" (endptr), /* 3 */ | |
331 "m" (upnw), /* 4 */ | |
332 "r" (pn_image_get_pitch (image)), /* 5 */ | |
333 "r" (endy), /* 6 */ | |
334 "rm" (((stride - endx) + startx) * sizeof (PnColor)), /* 7 */ | |
335 "rm" ((guint32)((se << 24) | (sw << 16) | (ne << 8) | nw ))); /* 8 */ | |
336 } | |
337 #endif /* PN_USE_MMX */ | |
338 | |
339 static void | |
340 pn_displacement_execute (PnDisplacement *displacement, PnImage *image, PnAudioData *audio_data) | |
341 { | |
342 g_return_if_fail (displacement != NULL); | |
343 g_return_if_fail (PN_IS_DISPLACEMENT (displacement)); | |
344 g_return_if_fail (image != NULL); | |
345 g_return_if_fail (PN_IS_IMAGE (image)); | |
346 g_return_if_fail (audio_data != NULL); | |
347 g_return_if_fail (PN_IS_AUDIO_DATA (audio_data)); | |
348 | |
349 /* set up the volume in-script variable */ | |
350 PN_VARIABLE_VALUE (displacement->volume_var) = pn_audio_data_get_volume (audio_data); | |
351 | |
352 /* run the frame scipt */ | |
353 pn_script_execute (displacement->frame_script); | |
354 | |
355 if (fabs (PN_VARIABLE_VALUE (displacement->x_var)) <= 2.0 | |
356 && fabs (PN_VARIABLE_VALUE (displacement->y_var)) <= 2.0) | |
357 { | |
358 guint nw, ne, sw, se; | |
359 gint startx, starty, endx, endy; | |
360 gint offset; | |
361 gdouble x, y, xfrac, yfrac; | |
362 | |
363 x = -PN_VARIABLE_VALUE (displacement->x_var) * (pn_image_get_width (image) >> 1); | |
364 y = PN_VARIABLE_VALUE (displacement->y_var) * (pn_image_get_height (image) >> 1); | |
365 | |
366 xfrac = modf (x, &x); | |
367 yfrac = modf (y, &y); | |
368 | |
369 if (x < 0.0 || xfrac < 0.0) | |
370 { | |
371 x--; | |
372 xfrac++; | |
373 } | |
374 if (y < 0.0 || yfrac < 0.0) | |
375 { | |
376 y--; | |
377 yfrac++; | |
378 } | |
379 | |
380 se = xfrac * yfrac * 128.0; | |
381 sw = (1.0 - xfrac) * yfrac * 128.0; | |
382 ne = xfrac * (1.0 - yfrac) * 128.0; | |
383 nw = 128 - (se + sw + ne); | |
384 | |
385 offset = (y * (pn_image_get_pitch (image) >> 2)) + x; | |
386 | |
387 startx = -x; | |
388 starty = -y; | |
389 endx = pn_image_get_width (image) - (x+1); | |
390 endy = pn_image_get_height (image) - (y+1); | |
391 | |
392 startx = MAX (startx, 0); | |
393 starty = MAX (starty, 0); | |
394 endx = MIN (endx, pn_image_get_width (image)); | |
395 endy = MIN (endy, pn_image_get_height (image)); | |
396 | |
397 /* I'm too lazy to special case the rightmost & bottommost pixels */ | |
398 if (endx == pn_image_get_width (image)) | |
399 endx--; | |
400 if (endy == pn_image_get_height (image)) | |
401 endy--; | |
402 | |
403 #ifdef PN_USE_MMX | |
404 if (pn_cpu_get_caps () & PN_CPU_CAP_MMX) | |
405 pn_displacement_exec_mmx (image, offset, nw, ne, sw, se, startx, starty, endx, endy); | |
406 else | |
407 #endif /* PN_USE_MMX */ | |
408 pn_displacement_exec (image, offset, nw, ne, sw, se, startx, starty, endx, endy); | |
409 } | |
410 else | |
411 memset (pn_image_get_transform_buffer (image), 0, | |
412 pn_image_get_pitch (image) * pn_image_get_height (image)); | |
413 | |
414 pn_image_apply_transform (image); | |
415 | |
416 if (PN_ACTUATOR_CLASS (parent_class)->execute) | |
417 PN_ACTUATOR_CLASS (parent_class)->execute (PN_ACTUATOR (displacement), image, audio_data); | |
418 } | |
419 | |
420 PnDisplacement* | |
421 pn_displacement_new (void) | |
422 { | |
423 return (PnDisplacement *) g_object_new (PN_TYPE_DISPLACEMENT, NULL); | |
424 } |