X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Flcdscrub.c;h=5fd165e3c1d45f73d03aa7fc7c2f663fcf40fc16;hp=e7f220c08aa28e242a2a1e1e574409ae3239ea61;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hpb=88cfe534a698a0562e81345957a50714af1453bc diff --git a/hacks/lcdscrub.c b/hacks/lcdscrub.c index e7f220c0..5fd165e3 100644 --- a/hacks/lcdscrub.c +++ b/hacks/lcdscrub.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2008-2013 Jamie Zawinski +/* xscreensaver, Copyright (c) 2008-2015 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ struct state { DIAG_W, DIAG_B, WHITE, BLACK, RGB, + RANDOM, END } mode; unsigned int enabled_mask; int count; @@ -35,6 +36,8 @@ struct state { int delay; int spread; int cycles; + XImage *collisions; + long ncollisions; }; @@ -56,6 +59,8 @@ lcdscrub_init (Display *dpy, Window window) { struct state *st = (struct state *) calloc (1, sizeof(*st)); XGCValues gcv; + unsigned long fgp, bgp; + st->dpy = dpy; st->window = window; st->delay = get_integer_resource (st->dpy, "delay", "Integer"); @@ -63,15 +68,20 @@ lcdscrub_init (Display *dpy, Window window) st->cycles = get_integer_resource (st->dpy, "cycles", "Integer"); XGetWindowAttributes (st->dpy, st->window, &st->xgwa); - gcv.foreground = BlackPixelOfScreen (st->xgwa.screen); - gcv.background = WhitePixelOfScreen (st->xgwa.screen); + fgp = get_pixel_resource (st->dpy, st->xgwa.colormap, + "foreground", "Foreground"); + bgp = get_pixel_resource (st->dpy, st->xgwa.colormap, + "background", "Background"); + + gcv.foreground = bgp; + gcv.background = fgp; st->bg = XCreateGC (st->dpy, st->window, GCForeground, &gcv); st->bg2 = XCreateGC (st->dpy, st->window, GCForeground, &gcv); - gcv.foreground = WhitePixelOfScreen (st->xgwa.screen); - gcv.background = BlackPixelOfScreen (st->xgwa.screen); + gcv.foreground = fgp; + gcv.background = bgp; st->fg = XCreateGC (st->dpy, st->window, GCForeground, &gcv); -#ifdef HAVE_COCOA +#ifdef HAVE_JWXYZ jwxyz_XSetAntiAliasing (st->dpy, st->fg, False); jwxyz_XSetAntiAliasing (st->dpy, st->bg, False); jwxyz_XSetAntiAliasing (st->dpy, st->bg2, False); @@ -89,6 +99,7 @@ lcdscrub_init (Display *dpy, Window window) PREF("modeW", WHITE); PREF("modeB", BLACK); PREF("modeRGB", RGB); + PREF("modeRandom", RANDOM); # undef PREF if (! st->enabled_mask) { @@ -101,6 +112,143 @@ lcdscrub_init (Display *dpy, Window window) return st; } + +/* A test harness for visualizing different random number generators. + This doesn't really belong in lcdscrub, but it was a convenient + place to put it. + */ +#if 0 /* mwc1616 */ + +static unsigned long mwc1616_x = 1; +static unsigned long mwc1616_y = 2; + +static void +mwc1616_srand (unsigned long seed) +{ + mwc1616_x = seed | 1; + mwc1616_y = seed | 2; +} + +static unsigned long +mwc1616 (void) +{ + mwc1616_x = 18000 * (mwc1616_x & 0xFFFF) + (mwc1616_x >> 16); + mwc1616_y = 30903 * (mwc1616_y & 0xFFFF) + (mwc1616_y >> 16); + return (mwc1616_x << 16) + (mwc1616_y & 0xFFFF); +} + +# undef random +# undef srand +# define srand mwc1616_srand +# define random() ((unsigned int) (mwc1616() & (unsigned int) (~0))) + + +#elif 0 /* xorshift128plus */ + + +static uint64_t xo_state0 = 1; +static uint64_t xo_state1 = 2; + +static void +xorshift128plus_srand (unsigned long seed) +{ + xo_state0 = seed | 1; + xo_state1 = seed | 2; +} + +static uint64_t +xorshift128plus (void) +{ + register uint64_t s1 = xo_state0; + register uint64_t s0 = xo_state1; + xo_state0 = s0; + s1 ^= s1 << 23; + s1 ^= s1 >> 17; + s1 ^= s0; + s1 ^= s0 >> 26; + xo_state1 = s1; + return s1; +} + +# undef random +# undef srand +# define srand xorshift128plus_srand +# define random() ((unsigned int) (xorshift128plus() & (unsigned int) (~0))) + + +#else /* ya_random */ +# undef srand +# define srand(n) + +#endif /* ya_random */ + + + +/* If you see patterns in this image, the PRNG sucks. + */ +static void +lcdscrub_random (struct state *st) +{ + unsigned long steps_per_frame = 3000000; + unsigned long segments = 0x8000; /* 2^15 */ + + if (! st->collisions) + { + struct timeval tp; +# if GETTIMEOFDAY_TWO_ARGS + gettimeofday (&tp, 0); +# else + gettimeofday (&tp); +# endif + srand ((unsigned int) (tp.tv_sec ^ tp.tv_usec)); + + st->collisions = + XCreateImage (st->dpy, st->xgwa.visual, 1, XYPixmap, + 0, NULL, segments, segments, 8, 0); + if (! st->collisions) abort(); + st->collisions->data = (char *) + calloc (segments, st->collisions->bytes_per_line); /* 128 MB */ + if (! st->collisions->data) abort(); + } + + while (--steps_per_frame) + { + unsigned long x = random() & (segments-1); + unsigned long y = random() & (segments-1); + unsigned long p = XGetPixel (st->collisions, x, y) ? 0 : 1; + XPutPixel (st->collisions, x, y, p); + st->ncollisions += (p ? 1 : -1); + } + + { + int w, h; + Pixmap p; + GC gc; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + w = st->xgwa.width; + h = st->xgwa.height; + + p = XCreatePixmap (st->dpy, st->window, w, h, 1); + gc = XCreateGC (st->dpy, p, 0, 0); + XSetBackground (st->dpy, gc, 0); + XSetForeground (st->dpy, gc, 1); + XPutImage (st->dpy, p, gc, st->collisions, 0, 0, 0, 0, w, h); + XFreeGC (st->dpy, gc); + + gc = st->fg; + XClearWindow (st->dpy, st->window); + XSetClipMask (st->dpy, gc, p); + XFillRectangle (st->dpy, st->window, gc, 0, 0, w, h); + XFreePixmap (st->dpy, p); + } + + /* + fprintf(stderr, "%.2f\n", st->ncollisions / (float) (segments*segments)); + */ +} + + static unsigned long lcdscrub_draw (Display *dpy, Window window, void *closure) { @@ -167,6 +315,9 @@ lcdscrub_draw (Display *dpy, Window window, void *closure) XFillRectangle (st->dpy, st->window, bg, 0, 0, st->xgwa.width, st->xgwa.height); break; + case RANDOM: + lcdscrub_random (st); + break; default: abort(); break; @@ -199,6 +350,12 @@ lcdscrub_free (Display *dpy, Window window, void *closure) XFreeGC (dpy, st->fg); XFreeGC (dpy, st->bg); XFreeGC (dpy, st->bg2); + if (st->collisions) + { + free (st->collisions->data); + st->collisions->data = 0; + XDestroyImage (st->collisions); + } free (st); } @@ -206,6 +363,7 @@ lcdscrub_free (Display *dpy, Window window, void *closure) static const char *lcdscrub_defaults [] = { ".background: black", ".foreground: white", + "*fpsSolid: True", "*delay: 100000", "*spread: 8", "*cycles: 60", @@ -218,6 +376,7 @@ static const char *lcdscrub_defaults [] = { "*modeW: True", "*modeB: True", "*modeRGB: True", + "*modeRandom: False", 0 }; @@ -234,6 +393,7 @@ static XrmOptionDescRec lcdscrub_options [] = { { "-no-w", ".modeW", XrmoptionNoArg, "False" }, { "-no-b", ".modeB", XrmoptionNoArg, "False" }, { "-no-rgb", ".modeRGB", XrmoptionNoArg, "False" }, + { "-random", ".modeRandom", XrmoptionNoArg, "True" }, { 0, 0, 0, 0 } };