1 /* xscreensaver, Copyright (c) 1992, 1995, 1997
2 * Jamie Zawinski <jwz@netscape.com>
4 * reaction/diffusion textures
5 * Copyright (c) 1997 Scott Draves spot@transmeta.com
6 * this code is derived from Bomb
7 * see http://www.cs.cmu.edu/~spot/bomb.html
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation. No representations are made about the suitability of this
14 * software for any purpose. It is provided "as is" without express or
17 * And remember: X Windows is to graphics hacking as roman numerals are to
18 * the square root of pi.
23 #include "screenhack.h"
25 /* why doesn't this work??? */
26 #ifdef HAVE_XSHM_EXTENSION
29 #include <X11/extensions/XShm.h>
32 #define test_pattern_hyper 0
35 #define dither_when_mapped 1
37 char *progclass = "RD";
41 "RD.background: black", /* to placate SGI */
42 "RD.foreground: white",
57 XrmOptionDescRec options [] = {
58 { "-width", ".width", XrmoptionSepArg, 0 },
59 { "-height", ".height", XrmoptionSepArg, 0 },
60 { "-epoch", ".epoch", XrmoptionSepArg, 0 },
61 { "-reaction", ".reaction", XrmoptionSepArg, 0 },
62 { "-diffusion", ".diffusion", XrmoptionSepArg, 0 },
63 { "-verbose", ".verbose", XrmoptionNoArg, "True" },
64 { "-radius", ".radius", XrmoptionSepArg, 0 },
65 { "-speed", ".speed", XrmoptionSepArg, 0 },
66 { "-size", ".size", XrmoptionSepArg, 0 },
67 { "-delay", ".delay", XrmoptionSepArg, 0 },
68 { "-ncolors", ".colors", XrmoptionSepArg, 0 },
73 #define mx ((1<<16)-1)
75 /* you can replace integer mults wish shift/adds with these,
76 but it doesn't help on my 586 */
77 #define x5(n) ((n<<2)+n)
78 #define x7(n) ((n<<3)-n)
81 #define R (ya_random()&((1<<30)-1))
83 /* should factor into RD-specfic and compute-every-pixel general */
85 screenhack (Display *dpy, Window win)
89 XWindowAttributes xgwa;
92 int width, height, radius;
93 int array_width, array_height;
94 double array_x, array_y;
95 double array_dx, array_dy;
97 int frame = 0, epoch_time;
100 ushort *r1, *r2, *r1b, *r2b;
107 #if dither_when_mapped
108 unsigned char *mc = 0;
110 #ifdef HAVE_XSHM_EXTENSION
112 XShmSegmentInfo shm_info;
117 int delay = get_float_resource ("delay", "Integer");
119 XGetWindowAttributes (dpy, win, &xgwa);
120 width = get_integer_resource ("width", "Integer");
121 height = get_integer_resource ("height", "Integer");
123 double s = get_float_resource ("size", "Float");
124 double p = get_float_resource ("speed", "Float");
125 if (s < 0.0 || s > 1.0)
128 array_width = xgwa.width * s;
129 array_height = xgwa.height * s;
131 array_width = (array_width / width) * width;
132 array_height = (array_height / height) * height;
134 if (array_width < width) array_width = width;
135 if (array_height < height) array_height = height;
136 array_x = (xgwa.width - array_width)/2;
137 array_y = (xgwa.height - array_height)/2;
139 array_dy = .31415926 * p;
141 if (width < 10) width = 10;
142 if (height < 10) height = 10;
143 verbose = get_boolean_resource ("verbose", "Boolean");
144 npix = (width + 2) * (height + 2);
145 epoch_time = get_integer_resource ("epoch", "Integer");
147 gcv.function = GXcopy;
148 gc = XCreateGC(dpy, win, GCFunction, &gcv);
149 vdepth = visual_depth(DefaultScreenOfDisplay(dpy), xgwa.visual);
151 /* This code only deals with pixmap depths of 1, 8, 16, and 32.
152 Therefore, we assume that those depths will be supported by the
153 coresponding visual depths (that depth-24 displays accept depth-32
154 pixmaps, and that depth-12 displays accept depth-16 pixmaps.) */
155 pdepth = (vdepth == 1 ? 1 :
160 cmap = xgwa.colormap;
161 ncolors = get_integer_resource ("colors", "Integer");
170 if (mono_p || ncolors < 2) ncolors = 2;
171 if (ncolors <= 2) mono_p = True;
172 colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1));
174 mapped = (vdepth <= 8 &&
175 has_writable_cells(xgwa.screen, xgwa.visual));
178 m = (int *) malloc(sizeof(int) * (1<<16));
179 #if dither_when_mapped
182 mc = (unsigned char *) malloc(1<<16);
183 for (i = 0; i < (1<<16); i++) {
184 di = (i + (ya_random()&255))>>8;
185 if (di > 255) di = 255;
190 p = malloc(npix * (pdepth == 1 ? 1 : (pdepth / 8)));
191 r1 = (ushort *) malloc(sizeof(ushort) * npix);
192 r2 = (ushort *) malloc(sizeof(ushort) * npix);
193 r1b = (ushort *) malloc(sizeof(ushort) * npix);
194 r2b = (ushort *) malloc(sizeof(ushort) * npix);
195 if (!p || !r1 || !r2 || !r1b || !r2b) {
196 fprintf(stderr, "not enough memory for %d pixels.\n", npix);
200 #ifdef HAVE_XSHM_EXTENSION
204 image = XShmCreateImage(dpy, xgwa.visual, vdepth,
205 ZPixmap, 0, &shm_info, width, height);
206 shm_info.shmid = shmget(IPC_PRIVATE,
207 image->bytes_per_line * image->height,
209 if (shm_info.shmid == -1)
210 printf ("shmget failed!");
211 shm_info.readOnly = False;
212 p = shmat(shm_info.shmid, 0, 0);
213 printf("p=%X %d\n", p, image->bytes_per_line);
214 XShmAttach(dpy, &shm_info);
218 image = XCreateImage(dpy, xgwa.visual, vdepth,
220 width, height, 8, 0);
225 #if test_pattern_hyper
234 #ifdef GETTIMEOFDAY_TWO_ARGS
236 gettimeofday(&tp, &tzp);
240 tm2 = tp.tv_sec + tp.tv_usec * 1e-6;
242 printf("fps = %2.4g\n", 100.0 / (tm2 - tm));
246 if (!(frame%epoch_time)) {
249 int t = epoch_time / 500;
255 for (i = 0; i < npix; i++) {
261 memset(colors, 0, ncolors*sizeof(*colors));
262 make_smooth_colormap (dpy, xgwa.visual, cmap, colors, &ncolors,
267 colors[0].flags = DoRed|DoGreen|DoBlue;
268 colors[0].red = colors[0].green = colors[0].blue = 0;
269 XAllocColor(dpy, cmap, &colors[0]);
270 colors[1].flags = DoRed|DoGreen|DoBlue;
271 colors[1].red = colors[1].green = colors[1].blue = 0xFFFF;
272 XAllocColor(dpy, cmap, &colors[1]);
275 /* Scale it up so that there are exactly 255 colors -- that keeps the
276 animation speed consistent, even when there aren't many allocatable
277 colors, and prevents the -mono mode from looking like static. */
278 if (ncolors != 255) {
280 double scale = (double) ncolors / (double) (n+1);
281 XColor *c2 = (XColor *) malloc(sizeof(*c2) * (n+1));
282 for (i = 0; i < n; i++)
283 c2[i] = colors[(int) (i * scale)];
290 XSetWindowBackground(dpy, win, colors[255 % ncolors].pixel);
291 XClearWindow(dpy, win);
293 s = w2 * height/2 + width/2;
294 radius = get_integer_resource ("radius", "Integer");
296 radius = 1 + ((R%10) ? (R%5) : (R % (width/2-2)));
297 for (i = -radius; i < (radius+1); i++)
298 for (j = -radius; j < (radius+1); j++)
299 r2[s + i + j*w2] = mx - (R&63);
300 reaction = get_integer_resource ("reaction", "Integer");
301 if (reaction < 0 || reaction > 2) reaction = R&1;
302 diffusion = get_integer_resource ("diffusion", "Integer");
303 if (diffusion < 0 || diffusion > 2)
304 diffusion = (R%5) ? ((R%3)?0:1) : 2;
305 if (2 == reaction && 2 == diffusion)
306 reaction = diffusion = 0;
309 printf("reaction = %d\ndiffusion = %d\nradius = %d\n",
310 reaction, diffusion, radius);
312 for (i = 0; i <= width+1; i++) {
313 r1[i] = r1[i + w2 * height];
314 r2[i] = r2[i + w2 * height];
315 r1[i + w2 * (height + 1)] = r1[i + w2];
316 r2[i + w2 * (height + 1)] = r2[i + w2];
318 for (i = 0; i <= height+1; i++) {
319 r1[w2 * i] = r1[width + w2 * i];
320 r2[w2 * i] = r2[width + w2 * i];
321 r1[w2 * i + width + 1] = r1[w2 * i + 1];
322 r2[w2 * i + width + 1] = r2[w2 * i + 1];
324 for (i = 0; i < height; i++) {
326 char *q = p + width * i;
327 short *qq = ((short *) p) + width * i;
328 long *qqq = ((long *) p) + width * i;
329 ushort *i1 = r1 + 1 + w2 * ii;
330 ushort *i2 = r2 + 1 + w2 * ii;
331 ushort *o1 = r1b + 1 + w2 * ii;
332 ushort *o2 = r2b + 1 + w2 * ii;
333 for (j = 0; j < width; j++) {
334 #if test_pattern_hyper
335 int r1 = (i * j + (frame&127)*frame)&65535;
337 int uvv, r1 = 0, r2 = 0;
340 r1 = i1[j] + i1[j+1] + i1[j-1] + i1[j+w2] + i1[j-w2];
342 r2 = (i2[j]<<3) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2];
346 r1 = i1[j+1] + i1[j-1] + i1[j+w2] + i1[j-w2];
348 r2 = (i2[j]<<2) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2];
352 r1 = (i1[j]<<1) + (i1[j+1]<<1) + (i1[j-1]<<1) + i1[j+w2] + i1[j-w2];
354 r2 = (i2[j]<<2) + i2[j+1] + i2[j-1] + i2[j+w2] + i2[j-w2];
358 uvv = (((r1 * r2) >> bps) * r2) >> bps;
359 switch (reaction) { /* costs 4% */
361 r1 += 4 * (((28 * (mx-r1)) >> 10) - uvv);
362 r2 += 4 * (uvv - ((80 * r2) >> 10));
365 r1 += 3 * (((27 * (mx-r1)) >> 10) - uvv);
366 r2 += 3 * (uvv - ((80 * r2) >> 10));
369 r1 += 2 * (((28 * (mx-r1)) >> 10) - uvv);
370 r2 += 3 * (uvv - ((80 * r2) >> 10));
373 if (r1 > mx) r1 = mx;
374 if (r2 > mx) r2 = mx;
382 #if dither_when_mapped
383 q[j] = colors[mc[r1] % ncolors].pixel;
385 q[j] = colors[(r1>>8) % ncolors].pixel;
387 else if (pdepth == 8)
388 q[j] = colors[(r1>>8) % ncolors].pixel;
389 else if (pdepth == 16)
390 qq[j] = colors[(r1>>8) % ncolors].pixel;
391 else if (pdepth == 32)
392 qqq[j] = colors[(r1>>8) % ncolors].pixel;
397 t = r1; r1 = r1b; r1b = t;
398 t = r2; r2 = r2b; r2b = t;
399 for (i = 0; i < array_width; i += width)
400 for (j = 0; j < array_height; j += height)
401 #ifdef HAVE_XSHM_EXTENSION
403 XShmPutImage(dpy, win, gc, image, 0, 0, i, j,
404 width, height, False);
407 XPutImage(dpy, win, gc, image, 0, 0, i+array_x, j+array_y, width, height);
413 array_dx = -array_dx;
414 } else if (array_x > (xgwa.width - array_width)) {
415 array_x = (xgwa.width - array_width);
416 array_dx = -array_dx;
420 array_dy = -array_dy;
421 } else if (array_y > (xgwa.height - array_height)) {
422 array_y = (xgwa.height - array_height);
423 array_dy = -array_dy;