http://svn.poeml.de/viewvc/ppc/src-unpacked/xscreensaver/xscreensaver-4.12.tar.bz2...
[xscreensaver] / hacks / rd-bomb.c
index 867ecf03a2f17680bc40dc521294a6447ff7d909..071786a0511f85b05b16b54063cb190b1b49755a 100644 (file)
@@ -1,5 +1,5 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1997
- *  Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1992, 1995, 1997, 1998, 1999, 2003
+ *  Jamie Zawinski <jwz@jwz.org>
  *
  *  reaction/diffusion textures
  *  Copyright (c) 1997 Scott Draves spot@transmeta.com
 #include <math.h>
 
 #include "screenhack.h"
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XSHM_EXTENSION
+# include "xshm.h"
+#endif /* HAVE_XSHM_EXTENSION */
 
 /* costs ~6% speed */
 #define dither_when_mapped 1
 
-int verbose;
-int ncolors = 0;
-XColor *colors = 0;
-Display *display;
-Visual *visual;
+static int verbose;
+static int ncolors = 0;
+static XColor *colors = 0;
+static Display *display;
+static Visual *visual;
 #if dither_when_mapped
-unsigned char *mc = 0;
+static unsigned char *mc = 0;
 #endif
-Colormap cmap = 0;
-Window window;
-int mapped;
-int pdepth;
-void random_colors(void);
+static Colormap cmap = 0;
+static Window window;
+static int mapped;
+static int pdepth;
+static void random_colors(void);
 
 /* -----------------------------------------------------------
    pixel hack, 8-bit pixel grid, first/next frame interface
@@ -58,22 +63,29 @@ void random_colors(void);
 /* why strip bit? */
 #define R (ya_random()&((1<<30)-1))
 
-int frame = 0, epoch_time;
-ushort *r1, *r2, *r1b, *r2b;
-int width, height, npix;
-int radius;
-int reaction = 0;
-int diffusion = 0;
+static int frame = 0, epoch_time;
+static ushort *r1, *r2, *r1b, *r2b;
+static int width, height, npix;
+static int radius;
+static int reaction = 0;
+static int diffusion = 0;
 
 /* returns number of pixels that the pixack produces.  called once. */
-void
-pixack_init(int *size_h, int *size_v) {
+static void
+pixack_init(int *size_h, int *size_v) 
+{
   int sz_base;
   width = get_integer_resource ("width", "Integer");
   height = get_integer_resource ("height", "Integer");
   sz_base = 80 + (R%40);
   if (width <= 0) width = (R%20) ? sz_base : (28 + R%10);
   if (height <= 0) height = (R%20) ? sz_base : (28 + R%10);
+
+  /* jwz: when (and only when) XSHM is in use on an SGI 8-bit visual,
+     we get shear unless width is a multiple of 4.  I don't understand
+     why.  This is undoubtedly the wrong fix... */
+  width &= ~0x7;
+
   /* don't go there */
   if (width < 10) width = 10;
   if (height < 10) height = 10;
@@ -97,8 +109,9 @@ pixack_init(int *size_h, int *size_v) {
 
 
 /* returns the pixels.  called many times. */
-void
-pixack_frame(char *pix_buf) {
+static void
+pixack_frame(char *pix_buf) 
+{
   int i, j;
   int w2 = width + 2;
   ushort *t;
@@ -126,10 +139,10 @@ pixack_frame(char *pix_buf) {
   if (!(frame%epoch_time)) {
     int s;
     if (0 != frame) {
-      int t = epoch_time / 500;
-      if (t > 15)
-       t = 15;
-      sleep(t);
+      int tt = epoch_time / 500;
+      if (tt > 15)
+       tt = 15;
+      sleep(tt);
     }
          
     for (i = 0; i < npix; i++) {
@@ -292,9 +305,12 @@ char *defaults [] = {
   "*verbose:   off",
   "*radius:    -1",
   "*speed:     0.0",
-  "*size:      0.66",
+  "*size:      1.0",
   "*delay:     1",
   "*colors:    -1",
+#ifdef HAVE_XSHM_EXTENSION
+  "*useSHM:    True",
+#endif /* HAVE_XSHM_EXTENSION */
   0
 };
 
@@ -310,22 +326,17 @@ XrmOptionDescRec options [] = {
   { "-size",           ".size",        XrmoptionSepArg, 0 },
   { "-delay",          ".delay",       XrmoptionSepArg, 0 },
   { "-ncolors",                ".colors",      XrmoptionSepArg, 0 },
+#ifdef HAVE_XSHM_EXTENSION
+  { "-shm",            ".useSHM",      XrmoptionNoArg, "True" },
+  { "-no-shm",         ".useSHM",      XrmoptionNoArg, "False" },
+#endif /* HAVE_XSHM_EXTENSION */
   { 0, 0, 0, 0 }
 };
 
 
-/* why doesn't this work???  and more importantly, do i really still have
-   to do this in X? */
-   
-#ifdef HAVE_XSHM_EXTENSION
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-#endif
-
-
-void
-random_colors() {
+static void
+random_colors(void)
+{
   memset(colors, 0, ncolors*sizeof(*colors));
   make_smooth_colormap (display, visual, cmap, colors, &ncolors,
                        True, 0, True);
@@ -368,11 +379,11 @@ screenhack (Display *dpy, Window win)
   double array_x, array_y;
   double array_dx, array_dy;
   int w2;
-  char *p;
+  char *pd;
   int vdepth;
   int npix;
 #ifdef HAVE_XSHM_EXTENSION
-  int use_shm = 0;
+  Bool use_shm = get_boolean_resource("useSHM", "Boolean");
   XShmSegmentInfo shm_info;
 #endif
 
@@ -403,6 +414,11 @@ screenhack (Display *dpy, Window win)
     array_y = (xgwa.height - array_height)/2;
     array_dx = p;
     array_dy = .31415926 * p;
+
+    /* start in a random direction */
+    if (random() & 1) array_dx = -array_dx;
+    if (random() & 1) array_dy = -array_dy;
+
   }
   verbose = get_boolean_resource ("verbose", "Boolean");
   npix = (width + 2) * (height + 2);
@@ -420,6 +436,40 @@ screenhack (Display *dpy, Window win)
            vdepth <= 16 ? 16 :
            32);
 
+  /* Ok, this like, sucks and stuff.  There are some XFree86 systems
+     that have depth-24 visuals, that do not accept depth-32 XImages!
+     Which if you ask me is just absurd, since all it would take is
+     for the server to truncate the bits in that case.  So, this crap
+     here detects the specific case of: we have chosen depth 32;
+     and the server does not support depth 32.  In that case, we
+     try and use depth 16 instead.
+
+     The real fix would be to rewrite this program to deal with
+     depth 24 directly (or even better, arbitrary depths, but that
+     would mean going through the XImage routines instead of messing
+     with the XImage->data directly.)
+
+     jwz, 18-Mar-99: well, the X servers I have access to these days do
+     support 32-deep images on deep visuals, so I no longer have the
+     ability to test this code -- but it was causing problems on the
+     visuals that I do have, and I think that's because I mistakenly
+     wrote `pfv[i].depth' when I meant to write `pfv[i].bits_per_pixel'.
+     The symptom I was seeing was that the grid was 64x64, but the
+     images were being drawn 32x32 -- so there was a black stripe on
+     every other row.  Wow, this code sucks so much.
+   */
+  if (pdepth == 32)
+    {
+      int i, pfvc = 0;
+      Bool ok = False;
+      XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
+      for (i = 0; i < pfvc; i++)
+        if (pfv[i].bits_per_pixel == pdepth)
+          ok = True;
+      if (!ok)
+        pdepth = 16;
+    }
+
   cmap = xgwa.colormap;
   ncolors = get_integer_resource ("colors", "Integer");
 
@@ -447,66 +497,85 @@ screenhack (Display *dpy, Window win)
     }
   }
 
-  p = malloc(npix * (pdepth == 1 ? 1 : (pdepth / 8)));
-  if (!p) {
+  pd = malloc(npix * (pdepth == 1 ? 1 : (pdepth / 8)));
+  if (!pd) {
     fprintf(stderr, "not enough memory for %d pixels.\n", npix);
     exit(1);
   }
 
+  image = 0;
+
 #ifdef HAVE_XSHM_EXTENSION
-  if (use_shm) {
-    printf("p=%X\n", p);
-    free(p);
-    image = XShmCreateImage(dpy, xgwa.visual, vdepth,
-                           ZPixmap, 0, &shm_info, width, height);
-    shm_info.shmid = shmget(IPC_PRIVATE,
-                           image->bytes_per_line * image->height,
-                           IPC_CREAT | 0777);
-    if (shm_info.shmid == -1)
-      printf ("shmget failed!");
-    shm_info.readOnly = False;
-    p = shmat(shm_info.shmid, 0, 0);
-    printf("p=%X %d\n", p, image->bytes_per_line);
-    XShmAttach(dpy, &shm_info);
-    XSync(dpy, False);
-  } else
-#endif
-  image = XCreateImage(dpy, xgwa.visual, vdepth,
-                      ZPixmap, 0, p,
-                      width, height, 8, 0);
+  if (use_shm)
+    {
+      image = create_xshm_image(dpy, xgwa.visual, vdepth,
+                               ZPixmap, 0, &shm_info, width, height);
+      if (!image)
+       use_shm = False;
+      else
+       {
+         free(pd);
+         pd = image->data;
+       }
+    }
+#endif /* HAVE_XSHM_EXTENSION */
+
+  if (!image)
+    {
+      image = XCreateImage(dpy, xgwa.visual, vdepth,
+                          ZPixmap, 0, pd,
+                          width, height, 8, 0);
+    }
 
   while (1) {
+    Bool bump = False;
+
     int i, j;
-    pixack_frame(p);
+    pixack_frame(pd);
     for (i = 0; i < array_width; i += width)
       for (j = 0; j < array_height; j += height)
 #ifdef HAVE_XSHM_EXTENSION
        if (use_shm)
-         XShmPutImage(dpy, win, gc, image, 0, 0, i, j,
+         XShmPutImage(dpy, win, gc, image, 0, 0, i+array_x, j+array_y,
                       width, height, False);
        else
 #endif
-         XPutImage(dpy, win, gc, image, 0, 0, i+array_x, j+array_y, width, height);
+         XPutImage(dpy, win, gc, image, 0, 0, i+array_x, j+array_y,
+                   width, height);
 
     array_x += array_dx;
     array_y += array_dy;
     if (array_x < 0) {
       array_x = 0;
       array_dx = -array_dx;
+      bump = True;
     } else if (array_x > (xgwa.width - array_width)) {
       array_x = (xgwa.width - array_width);
       array_dx = -array_dx;
+      bump = True;
     }
     if (array_y < 0) {
       array_y = 0;
       array_dy = -array_dy;
+      bump = True;
     } else if (array_y > (xgwa.height - array_height)) {
       array_y = (xgwa.height - array_height);
       array_dy = -array_dy;
+      bump = True;
     }
+
+    if (bump) {
+      if (random() & 1) {
+       double swap = array_dx;
+       array_dx = array_dy;
+       array_dy = swap;
+      }
+    }
+
     frame++;
 
     XSync(dpy, False);
+    screenhack_handle_events (dpy);
     if (delay > 0)
       usleep(1000 * delay);
   }