Author: des
Date: Fri Jan  1 04:04:40 2016
New Revision: 293034
URL: https://svnweb.freebsd.org/changeset/base/293034

Log:
  17 years and change after I wrote warp_saver, here's a simple plasma effect
  (currently only three circular patterns) which requires quite a bit of
  fixed-point arithmetic, including sqrt() and cos().  Happy New Year!

Added:
  head/sys/dev/syscons/plasma/
  head/sys/dev/syscons/plasma/fp16.c   (contents, props changed)
  head/sys/dev/syscons/plasma/fp16.h   (contents, props changed)
  head/sys/dev/syscons/plasma/plasma_saver.c   (contents, props changed)
  head/sys/modules/syscons/plasma/
  head/sys/modules/syscons/plasma/Makefile   (contents, props changed)
Modified:
  head/share/man/man4/splash.4
  head/sys/modules/syscons/Makefile

Modified: head/share/man/man4/splash.4
==============================================================================
--- head/share/man/man4/splash.4        Fri Jan  1 03:59:09 2016        
(r293033)
+++ head/share/man/man4/splash.4        Fri Jan  1 04:04:40 2016        
(r293034)
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 29, 2010
+.Dd December 31, 2015
 .Dt SPLASH 4
 .Os
 .Sh NAME
@@ -130,6 +130,8 @@ the screen will also be powered off.
 Animated graphical
 .Fx
 logo.
+.It Pa plasma_saver.ko
+Draws an animated interference pattern.
 .It Pa rain_saver.ko
 Draws a shower on the screen.
 .It Pa snake_saver.ko
@@ -282,6 +284,14 @@ based on the
 code, with some additional inspiration from the
 .Pa daemon_saver
 code.
+The
+.Pa logo_saver ,
+.Pa plasma_saver ,
+.Pa rain_saver
+and
+.Pa warp_saver
+modules were written by
+.An Dag-Erling Sm\(/orgrav Aq Mt [email protected] .
 .Sh CAVEATS
 Both the splash screen and the screen saver work with
 .Xr syscons 4

Added: head/sys/dev/syscons/plasma/fp16.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/syscons/plasma/fp16.c  Fri Jan  1 04:04:40 2016        
(r293034)
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2015 Dag-Erling Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifdef _KERNEL
+#include <sys/libkern.h>
+#else
+#include <stdio.h>
+#include <strings.h>
+#endif
+
+#include "fp16.h"
+
+/*
+ * Compute the quare root of x, using Newton's method with 2^(log2(x)/2)
+ * as the initial estimate.
+ */
+fp16_t
+fp16_sqrt(fp16_t x)
+{
+       fp16_t y, delta;
+       signed int log2x;
+
+       /* special case */
+       if (x == 0)
+               return (0);
+
+       /* shift toward 0 by half the logarithm */
+       log2x = flsl(x) - 1;
+       if (log2x >= 16) {
+               y = x >> (log2x - 16) / 2;
+       } else {
+#if 0
+               y = x << (16 - log2x) / 2;
+#else
+               /* XXX for now, return 0 for anything < 1 */
+               return (0);
+#endif
+       }
+       while (y > 0) {
+               /* delta = y^2 / 2y */
+               delta = fp16_div(fp16_sub(fp16_mul(y, y), x), y * 2);
+               if (delta == 0)
+                       break;
+               y = fp16_sub(y, delta);
+       }
+       return (y);
+}
+
+static fp16_t fp16_cos_table[256] = {
+       65536,  65534,  65531,  65524,  65516,  65505,  65491,  65475,
+       65457,  65436,  65412,  65386,  65358,  65327,  65294,  65258,
+       65220,  65179,  65136,  65091,  65043,  64992,  64939,  64884,
+       64826,  64766,  64703,  64638,  64571,  64501,  64428,  64353,
+       64276,  64197,  64115,  64030,  63943,  63854,  63762,  63668,
+       63571,  63473,  63371,  63268,  63162,  63053,  62942,  62829,
+       62714,  62596,  62475,  62353,  62228,  62100,  61971,  61839,
+       61705,  61568,  61429,  61288,  61144,  60998,  60850,  60700,
+       60547,  60392,  60235,  60075,  59913,  59749,  59583,  59414,
+       59243,  59070,  58895,  58718,  58538,  58356,  58172,  57986,
+       57797,  57606,  57414,  57219,  57022,  56822,  56621,  56417,
+       56212,  56004,  55794,  55582,  55368,  55152,  54933,  54713,
+       54491,  54266,  54040,  53811,  53581,  53348,  53114,  52877,
+       52639,  52398,  52155,  51911,  51665,  51416,  51166,  50914,
+       50660,  50403,  50146,  49886,  49624,  49360,  49095,  48828,
+       48558,  48288,  48015,  47740,  47464,  47186,  46906,  46624,
+       46340,  46055,  45768,  45480,  45189,  44897,  44603,  44308,
+       44011,  43712,  43412,  43110,  42806,  42501,  42194,  41885,
+       41575,  41263,  40950,  40636,  40319,  40002,  39682,  39362,
+       39039,  38716,  38390,  38064,  37736,  37406,  37075,  36743,
+       36409,  36074,  35738,  35400,  35061,  34721,  34379,  34036,
+       33692,  33346,  32999,  32651,  32302,  31952,  31600,  31247,
+       30893,  30538,  30181,  29824,  29465,  29105,  28745,  28383,
+       28020,  27656,  27291,  26925,  26557,  26189,  25820,  25450,
+       25079,  24707,  24334,  23960,  23586,  23210,  22833,  22456,
+       22078,  21699,  21319,  20938,  20557,  20175,  19792,  19408,
+       19024,  18638,  18253,  17866,  17479,  17091,  16702,  16313,
+       15923,  15533,  15142,  14751,  14359,  13966,  13573,  13179,
+       12785,  12390,  11995,  11600,  11204,  10807,  10410,  10013,
+        9616,   9218,   8819,   8421,   8022,   7623,   7223,   6823,
+        6423,   6023,   5622,   5222,   4821,   4420,   4018,   3617,
+        3215,   2814,   2412,   2010,   1608,   1206,    804,    402,
+};
+
+/*
+ * Compute the cosine of theta.
+ */
+fp16_t
+fp16_cos(fp16_t theta)
+{
+       unsigned int i;
+
+       i = 1024 * (theta % FP16_2PI) / FP16_2PI;
+       switch (i / 256) {
+       case 0:
+               return (fp16_cos_table[i % 256]);
+       case 1:
+               return (-fp16_cos_table[255 - i % 256]);
+       case 2:
+               return (-fp16_cos_table[i % 256]);
+       case 3:
+               return (fp16_cos_table[255 - i % 256]);
+       default:
+               /* inconceivable! */
+               return (0);
+       }
+}

Added: head/sys/dev/syscons/plasma/fp16.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/syscons/plasma/fp16.h  Fri Jan  1 04:04:40 2016        
(r293034)
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 2015 Dag-Erling Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef FP16_H_INCLUDED
+#define FP16_H_INCLUDED
+
+typedef signed long long fp16_t;
+
+#define ItoFP16(n)     ((signed long long)(n) << 16)
+#define FP16toI(n)     ((signed long long)(n) >> 16)
+
+#ifndef _KERNEL
+#define FP16toF(n)     ((n) / 65536.0)
+#endif
+
+/* add a and b */
+static inline fp16_t
+fp16_add(fp16_t a, fp16_t b)
+{
+
+       return (a + b);
+}
+
+/* subtract b from a */
+static inline fp16_t
+fp16_sub(fp16_t a, fp16_t b)
+{
+
+       return (a - b);
+}
+
+/* multiply a by b */
+static inline fp16_t
+fp16_mul(fp16_t a, fp16_t b)
+{
+
+       return (a * b >> 16);
+}
+
+/* divide a by b */
+static inline fp16_t
+fp16_div(fp16_t a, fp16_t b)
+{
+
+       return ((a << 16) / b);
+}
+
+/* square root */
+fp16_t fp16_sqrt(fp16_t);
+
+#define FP16_2PI        411774
+#define FP16_PI                 205887
+#define FP16_PI_2       102943
+#define FP16_PI_4        51471
+
+/* cosine */
+fp16_t fp16_cos(fp16_t);
+
+#endif

Added: head/sys/dev/syscons/plasma/plasma_saver.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/syscons/plasma/plasma_saver.c  Fri Jan  1 04:04:40 2016        
(r293034)
@@ -0,0 +1,239 @@
+/*-
+ * Copyright (c) 2015 Dag-Erling Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ * To CJA, in appreciation of Nighthawk brunches past and future.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/syslog.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/splashreg.h>
+#include <dev/syscons/syscons.h>
+
+#define SAVER_NAME      "plasma_saver"
+
+#include "fp16.h"
+
+/*
+ * Preferred video modes
+ */
+static int modes[] = {
+       M_VGA_CG640,
+       M_PC98_PEGC640x480,
+       M_PC98_PEGC640x400,
+       M_VGA_CG320,
+       -1
+};
+
+/*
+ * Display parameters
+ */
+static unsigned char *vid;
+static unsigned int banksize, scrmode, scrw, scrh;
+static unsigned int blanked;
+
+/*
+ * List of foci
+ */
+#define FOCI 3
+static struct {
+       int x, y;               /* coordinates */
+       int vx, vy;             /* velocity */
+} plasma_foci[FOCI];
+
+/*
+ * Palette
+ */
+static struct {
+       unsigned char r, g, b;
+} plasma_pal[256];
+
+/*
+ * Draw a new frame
+ */
+static void
+plasma_update(video_adapter_t *adp)
+{
+       unsigned int x, y;      /* coordinates */
+       signed int dx, dy;      /* horizontal / vertical distance */
+       fp16_t sqd, d;          /* square of distance and distance */
+       fp16_t m;               /* magnitude */
+       unsigned int org, off;  /* origin and offset */
+       unsigned int i;         /* loop index */
+
+       /* switch to bank 0 */
+       vidd_set_win_org(adp, 0);
+       /* for each scan line */
+       for (y = org = off = 0; y < scrh; ++y) {
+               /* for each pixel on scan line */
+               for (x = 0; x < scrw; ++x, ++off) {
+                       /* for each focus */
+                       for (i = m = 0; i < FOCI; ++i) {
+                               dx = x - plasma_foci[i].x;
+                               dy = y - plasma_foci[i].y;
+                               sqd = ItoFP16(dx * dx + dy * dy);
+                               d = fp16_sqrt(sqd);
+                               /* divide by 4 to stretch out the pattern */
+                               m = fp16_add(m, fp16_cos(d / 4));
+                       }
+                       /*
+                        * m is now in the range +/- FOCI, but we need a
+                        * value between 0 and 255.  We scale to +/- 127
+                        * and add 127, which moves it into the range [0,
+                        * 254].
+                        */
+                       m = fp16_mul(m, ItoFP16(127));
+                       m = fp16_div(m, ItoFP16(FOCI));
+                       m = fp16_add(m, ItoFP16(127));
+                       /* switch banks if necessary */
+                       if (off > banksize) {
+                               off -= banksize;
+                               org += banksize;
+                               vidd_set_win_org(adp, org);
+                       }
+                       /* plot */
+                       vid[off] = FP16toI(m);
+               }
+       }
+       /* now move the foci */
+       for (i = 0; i < FOCI; ++i) {
+               plasma_foci[i].x += plasma_foci[i].vx;
+               if (plasma_foci[i].x < 0) {
+                       /* bounce against left wall */
+                       plasma_foci[i].vx = -plasma_foci[i].vx;
+                       plasma_foci[i].x = -plasma_foci[i].x;
+               } else if (plasma_foci[i].x >= scrw) {
+                       /* bounce against right wall */
+                       plasma_foci[i].vx = -plasma_foci[i].vx;
+                       plasma_foci[i].x = scrw - (plasma_foci[i].x - scrw);
+               }
+               plasma_foci[i].y += plasma_foci[i].vy;
+               if (plasma_foci[i].y < 0) {
+                       /* bounce against ceiling */
+                       plasma_foci[i].vy = -plasma_foci[i].vy;
+                       plasma_foci[i].y = -plasma_foci[i].y;
+               } else if (plasma_foci[i].y >= scrh) {
+                       /* bounce against floor */
+                       plasma_foci[i].vy = -plasma_foci[i].vy;
+                       plasma_foci[i].y = scrh - (plasma_foci[i].y - scrh);
+               }
+       }
+}
+
+/*
+ * Start or stop the screensaver
+ */
+static int
+plasma_saver(video_adapter_t *adp, int blank)
+{
+       int pl;
+
+       if (blank) {
+               /* switch to graphics mode */
+               if (blanked <= 0) {
+                       pl = splhigh();
+                       vidd_set_mode(adp, scrmode);
+                       vidd_load_palette(adp, (unsigned char *)plasma_pal);
+                       vidd_set_border(adp, 0);
+                       blanked++;
+                       vid = (unsigned char *)adp->va_window;
+                       banksize = adp->va_window_size;
+                       splx(pl);
+                       vidd_clear(adp);
+               }
+               /* update display */
+               plasma_update(adp);
+       } else {
+               blanked = 0;
+       }
+       return (0);
+}
+
+/*
+ * Initialize on module load
+ */
+static int
+plasma_init(video_adapter_t *adp)
+{
+       video_info_t info;
+       int i;
+
+       /* select video mode */
+       for (i = 0; modes[i] >= 0; ++i)
+               if (vidd_get_info(adp, modes[i], &info) == 0)
+                       break;
+       if (modes[i] < 0) {
+               log(LOG_NOTICE, "%s: no supported video modes\n", SAVER_NAME);
+               return (ENODEV);
+       }
+       scrmode = modes[i];
+       scrw = info.vi_width;
+       scrh = info.vi_height;
+
+       /* initialize the palette */
+       for (i = 0; i < 256; ++i)
+               plasma_pal[i].r = plasma_pal[i].g = plasma_pal[i].b = i;
+
+       /* randomize the foci */
+       for (i = 0; i < FOCI; i++) {
+               plasma_foci[i].x = random() % scrw;
+               plasma_foci[i].y = random() % scrh;
+               plasma_foci[i].vx = random() % 5 - 2;
+               plasma_foci[i].vy = random() % 5 - 2;
+       }
+
+       return (0);
+}
+
+/*
+ * Clean up before module unload
+ */
+static int
+plasma_term(video_adapter_t *adp)
+{
+
+       return (0);
+}
+
+/*
+ * Boilerplate
+ */
+static scrn_saver_t plasma_module = {
+       SAVER_NAME,
+       plasma_init,
+       plasma_term,
+       plasma_saver,
+       NULL
+};
+
+SAVER_MODULE(plasma_saver, plasma_module);

Modified: head/sys/modules/syscons/Makefile
==============================================================================
--- head/sys/modules/syscons/Makefile   Fri Jan  1 03:59:09 2016        
(r293033)
+++ head/sys/modules/syscons/Makefile   Fri Jan  1 04:04:40 2016        
(r293034)
@@ -9,6 +9,7 @@ SUBDIR= ${_apm} \
        ${_fire} \
        green \
        ${_logo} \
+       ${_plasma} \
        ${_rain} \
        ${_snake} \
        ${_star} \
@@ -25,6 +26,7 @@ _daemon=      daemon
 _dragon=       dragon
 _fire=         fire
 _logo=         logo
+_plasma=       plasma
 _rain=         rain
 _snake=                snake
 _star=         star

Added: head/sys/modules/syscons/plasma/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/modules/syscons/plasma/Makefile    Fri Jan  1 04:04:40 2016        
(r293034)
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/syscons/plasma
+
+KMOD=  plasma_saver
+SRCS=  fp16.c plasma_saver.c
+
+.include <bsd.kmod.mk>
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to