From http://www.jwz.org/xscreensaver/xscreensaver-5.18.tar.gz
[xscreensaver] / hacks / interference.c
index d856f30eb5213945c4bee39cb9aac8f168315f8c..6060798181928ddc2482e2a95a5e8a8fa95ea2a2 100644 (file)
@@ -24,6 +24,9 @@
  *
  * Created      : Wed Apr 22 09:30:30 1998, hmallat
  * Last modified: Wed Apr 22 09:30:30 1998, hmallat
+ * Last modified: Sun Aug 31 23:40:14 2003, 
+ *              david slimp <rock808@DavidSlimp.com>
+ *             added -hue option to specify base color hue
  *
  * TODO:
  *
 
 #include "screenhack.h"
 
-# include <X11/Xutil.h>
-
 /* I thought it would be faster this way, but it turns out not to be... -jwz */
 #undef USE_XIMAGE
-#undef HAVE_XSHM_EXTENSION
-#undef HAVE_XDBE
+
+#ifndef USE_XIMAGE
+# undef HAVE_XSHM_EXTENSION  /* only applicable when using XImages */
+#endif /* USE_XIMAGE */
 
 
-#ifdef HAVE_XDBE
-# include <X11/extensions/Xdbe.h>
-#endif /* HAVE_XDBE */
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# include "xdbe.h"
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 
 #ifdef HAVE_XSHM_EXTENSION
 # include "xshm.h"
 #endif /* HAVE_XSHM_EXTENSION */
 
-char *progclass="Interference";
-
-char *defaults [] = {
+static const char *interference_defaults [] = {
+  ".background:  black",
+  ".foreground:  white",
   "*count:       3",     /* number of waves */
   "*gridsize:    4",     /* pixel size, smaller values for better resolution */
   "*ncolors:     128",   /* number of colours used */
+  "*hue:         0",     /* hue to use for base color (0-360) */
   "*speed:       30",    /* speed of wave origins moving around */
   "*delay:       30000", /* or something */
   "*color-shift: 60",    /* h in hsv space, smaller values for smaller
@@ -78,9 +82,10 @@ char *defaults [] = {
   "*gray:        false", /* color or grayscale */
   "*mono:        false", /* monochrome, not very much fun */
 
-#ifdef HAVE_XDBE
+  "*doubleBuffer: True",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
   "*useDBE:      True", /* use double buffering extension */
-#endif /* HAVE_XDBE */
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM:      True", /* use shared memory extension */
@@ -88,20 +93,19 @@ char *defaults [] = {
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec interference_options [] = {
   { "-count",       ".count",       XrmoptionSepArg, 0 }, 
   { "-ncolors",     ".ncolors",     XrmoptionSepArg, 0 }, 
   { "-gridsize",    ".gridsize",    XrmoptionSepArg, 0 }, 
+  { "-hue",         ".hue",         XrmoptionSepArg, 0 },
   { "-speed",       ".speed",       XrmoptionSepArg, 0 },
   { "-delay",       ".delay",       XrmoptionSepArg, 0 },
   { "-color-shift", ".color-shift", XrmoptionSepArg, 0 },
   { "-radius",      ".radius",      XrmoptionSepArg, 0 },
   { "-gray",        ".gray",        XrmoptionNoArg,  "True" },
   { "-mono",        ".mono",        XrmoptionNoArg,  "True" },
-#ifdef HAVE_XDBE
-  { "-db",          ".useDBE",      XrmoptionNoArg,  "True" },
-  { "-no-db",       ".useDBE",      XrmoptionNoArg,  "False" },
-#endif /* HAVE_XDBE */
+  { "-db",         ".doubleBuffer", XrmoptionNoArg,  "True" },
+  { "-no-db",      ".doubleBuffer", XrmoptionNoArg,  "False" },
 #ifdef HAVE_XSHM_EXTENSION
   { "-shm",    ".useSHM",      XrmoptionNoArg, "True" },
   { "-no-shm", ".useSHM",      XrmoptionNoArg, "False" },
@@ -109,8 +113,6 @@ XrmOptionDescRec options [] = {
   { 0, 0, 0, 0 }
 };
 
-int options_size = (sizeof (options) / sizeof (XrmOptionDescRec));
-
 struct inter_source {
   int x; 
   int y;
@@ -125,16 +127,16 @@ struct inter_context {
   Display* dpy;
   Window   win;
 
-  Pixmap   dbuf;
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  XdbeBackBuffer back_buf;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+  Pixmap   pix_buf;
+
   GC       copy_gc;
 #ifdef USE_XIMAGE
   XImage  *ximage;
 #endif /* USE_XIMAGE */
 
-#ifdef HAVE_XDBE
-  Status   has_dbe;
-#endif /* HAVE_XDBE */
-
 #ifdef HAVE_XSHM_EXTENSION
   Bool use_shm;
   XShmSegmentInfo shm_info;
@@ -146,6 +148,7 @@ struct inter_context {
   int count;
   int grid_size;
   int colors;
+  float hue;
   int speed;
   int delay;
   int shift;
@@ -158,9 +161,6 @@ struct inter_context {
   int h;
   Colormap cmap;
   XColor* pal;
-#ifdef HAVE_XDBE
-  XdbeBackBuffer buf;
-#endif /* HAVE_XDBE */
   GC* gcs;
 
   /*
@@ -174,77 +174,83 @@ struct inter_context {
   struct inter_source* source;
 };
 
-#ifdef HAVE_XDBE
-# define TARGET(c) ((c)->has_dbe ? (c)->buf : (c)->dbuf)
-#else  /* HAVE_XDBE */
-# define TARGET(c) ((c)->dbuf)
-#endif /* !HAVE_XDBE */
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# define TARGET(c) ((c)->back_buf ? (c)->back_buf : \
+                    (c)->pix_buf ? (c)->pix_buf : (c)->win)
+#else  /* HAVE_DOUBLE_BUFFER_EXTENSION */
+# define TARGET(c) ((c)->pix_buf ? (c)->pix_buf : (c)->win)
+#endif /* !HAVE_DOUBLE_BUFFER_EXTENSION */
 
-void inter_init(Display* dpy, Window win, struct inter_context* c) 
+static void inter_init(Display* dpy, Window win, struct inter_context* c) 
 {
   XWindowAttributes xgwa;
   double H[3], S[3], V[3];
   int i;
   int mono;
   int gray;
-#ifdef HAVE_XDBE
-  int major, minor;
-  int use_dbe;
-#endif /* HAVE_XDBE */
-
   XGCValues val;
   unsigned long valmask = 0;
+  Bool dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean");
+
+# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+  dbuf = False;
+# endif
+
+  memset (c, 0, sizeof(*c));
 
   c->dpy = dpy;
   c->win = win;
 
+  c->delay = get_integer_resource(dpy, "delay", "Integer");
+
+
   XGetWindowAttributes(c->dpy, c->win, &xgwa);
   c->w = xgwa.width;
   c->h = xgwa.height;
   c->cmap = xgwa.colormap;
 
-#ifdef HAVE_XDBE
-  use_dbe = get_boolean_resource("useDBE", "Boolean");
-  if(!use_dbe) {
-    c->has_dbe = False;
-  } else {
-    c->has_dbe = XdbeQueryExtension(dpy, &major, &minor);
-  }
-#endif /* HAVE_XDBE */
-
 #ifdef HAVE_XSHM_EXTENSION
-  c->use_shm = get_boolean_resource("useSHM", "Boolean");
+  c->use_shm = get_boolean_resource(dpy, "useSHM", "Boolean");
 #endif /*  HAVE_XSHM_EXTENSION */
 
-#ifdef HAVE_XDBE
-  if (!c->has_dbe)
-#endif /* HAVE_XDBE */
+  if (dbuf)
     {
-      c->dbuf = XCreatePixmap(dpy, win, xgwa.width, xgwa.height, xgwa.depth);
-      val.function = GXcopy;
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+      c->back_buf = xdbe_get_backbuffer (c->dpy, c->win, XdbeUndefined);
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+      if (!c->back_buf)
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+        c->pix_buf = XCreatePixmap (dpy, win, xgwa.width, xgwa.height,
+                                    xgwa.depth);
     }
 
-  c->copy_gc = XCreateGC(c->dpy, c->dbuf, GCFunction, &val);
+  val.function = GXcopy;
+  c->copy_gc = XCreateGC(c->dpy, TARGET(c), GCFunction, &val);
 
-  c->count = get_integer_resource("count", "Integer");
+  c->count = get_integer_resource(dpy, "count", "Integer");
   if(c->count < 1)
     c->count = 1;
-  c->grid_size = get_integer_resource("gridsize", "Integer");
+  c->grid_size = get_integer_resource(dpy, "gridsize", "Integer");
   if(c->grid_size < 1)
     c->grid_size = 1;
-  mono = get_boolean_resource("mono", "Boolean");
+  mono = get_boolean_resource(dpy, "mono", "Boolean");
   if(!mono) {
-    c->colors = get_integer_resource("ncolors", "Integer");
+    c->colors = get_integer_resource(dpy, "ncolors", "Integer");
     if(c->colors < 2)
       c->colors = 2;
   }
-  c->speed = get_integer_resource("speed", "Integer");
-  c->shift = get_float_resource("color-shift", "Float");
+  c->hue = get_integer_resource(dpy, "hue", "Float");
+  while (c->hue < 0 || c->hue >= 360)
+    c->hue = frand(360.0);
+  c->speed = get_integer_resource(dpy, "speed", "Integer");
+  c->shift = get_float_resource(dpy, "color-shift", "Float");
   while(c->shift >= 360.0)
     c->shift -= 360.0;
   while(c->shift <= -360.0)
     c->shift += 360.0;
-  c->radius = get_integer_resource("radius", "Integer");;
+  c->radius = get_integer_resource(dpy, "radius", "Integer");;
   if(c->radius < 1)
     c->radius = 1;
 
@@ -278,11 +284,9 @@ void inter_init(Display* dpy, Window win, struct inter_context* c)
   if(!mono) {
     c->pal = calloc(c->colors, sizeof(XColor));
 
-    srand48(time(NULL));
-
-    gray = get_boolean_resource("gray", "Boolean");
+    gray = get_boolean_resource(dpy, "gray", "Boolean");
     if(!gray) {
-      H[0] = drand48()*360.0; 
+      H[0] = c->hue;
       H[1] = H[0] + c->shift < 360.0 ? H[0]+c->shift : H[0] + c->shift-360.0; 
       H[2] = H[1] + c->shift < 360.0 ? H[1]+c->shift : H[1] + c->shift-360.0; 
       S[0] = S[1] = S[2] = 1.0;
@@ -312,11 +316,6 @@ void inter_init(Display* dpy, Window win, struct inter_context* c)
     c->pal[1].pixel = WhitePixel(c->dpy, DefaultScreen(c->dpy));
   }    
 
-#ifdef HAVE_XDBE
-  if(c->has_dbe)
-    c->buf = XdbeAllocateBackBufferName(c->dpy, c->win, XdbeUndefined);
-#endif /* HAVE_XDBE */
-
   valmask = GCForeground;
   c->gcs = calloc(c->colors, sizeof(GC));
   for(i = 0; i < c->colors; i++) {
@@ -337,8 +336,8 @@ void inter_init(Display* dpy, Window win, struct inter_context* c)
 
   c->source = calloc(c->count, sizeof(struct inter_source));
   for(i = 0; i < c->count; i++) {
-    c->source[i].x_theta = drand48()*2.0*3.14159;
-    c->source[i].y_theta = drand48()*2.0*3.14159;
+    c->source[i].x_theta = frand(2.0)*3.14159;
+    c->source[i].y_theta = frand(2.0)*3.14159;
   }
 
 }
@@ -355,14 +354,11 @@ void inter_init(Display* dpy, Window win, struct inter_context* c)
  * it, go ahead! 
  */
 
-void do_inter(struct inter_context* c) 
+static void do_inter(struct inter_context* c) 
 {
   int i, j, k;
   int result;
   int dist;
-#ifdef HAVE_XDBE
-  XdbeSwapInfo info[1];
-#endif /* HAVE_XDBE */
   int g;
 
   int dx, dy;
@@ -387,7 +383,7 @@ void do_inter(struct inter_context* c)
        dx = i*g + g/2 - c->source[k].x;
        dy = j*g + g/2 - c->source[k].y;
        dist = sqrt(dx*dx + dy*dy); /* what's the performance penalty here? */
-       result += (dist > c->radius ? 0 : c->wave_height[dist]);
+       result += (dist >= c->radius ? 0 : c->wave_height[dist]);
       }
       result %= c->colors;
 
@@ -424,33 +420,57 @@ void do_inter(struct inter_context* c)
 #endif /* USE_XIMAGE */
   }
 
-#ifdef HAVE_XDBE
-  if(c->has_dbe)
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  if (c->back_buf)
     {
+      XdbeSwapInfo info[1];
       info[0].swap_window = c->win;
       info[0].swap_action = XdbeUndefined;
       XdbeSwapBuffers(c->dpy, info, 1);
     }
   else
-#endif /* HAVE_XDBE */
-    {
-      XCopyArea (c->dpy, c->dbuf, c->win, c->copy_gc,
-                0, 0, c->w, c->h, 0, 0);
-    }
-  XSync(c->dpy, False);
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+    if (c->pix_buf)
+      {
+        XCopyArea (c->dpy, c->pix_buf, c->win, c->copy_gc,
+                   0, 0, c->w, c->h, 0, 0);
+      }
 }
 
-void screenhack(Display *dpy, Window win) 
+static void *
+interference_init (Display *dpy, Window win)
 {
-  struct inter_context c;
-  int delay;
+  struct inter_context *c = (struct inter_context *) calloc (1, sizeof(*c));
+  inter_init(dpy, win, c);
+  return c;
+}
 
-  delay = get_integer_resource("delay", "Integer");
+static unsigned long
+interference_draw (Display *dpy, Window win, void *closure)
+{
+  struct inter_context *c = (struct inter_context *) closure;
+  do_inter(c);
+  return c->delay;
+}
 
-  inter_init(dpy, win, &c);
-  while(1) {
-    do_inter(&c); 
-    screenhack_handle_events (dpy);
-    if(delay) usleep(delay);
-  }
+static void
+interference_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct inter_context *c = (struct inter_context *) closure;
+  c->w = w;
+  c->h = h;
+}
+
+static Bool
+interference_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
 }
+
+static void
+interference_free (Display *dpy, Window window, void *closure)
+{
+}
+
+XSCREENSAVER_MODULE ("Interference", interference)