svn commit: r293034 - in head: share/man/man4 sys/dev/syscons/plasma sys/modules/syscons sys/modules/syscons/plasma

Dag-Erling Smørgrav des at FreeBSD.org
Fri Jan 1 04:04:42 UTC 2016


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 des at FreeBSD.org .
 .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>


More information about the svn-src-head mailing list