#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"
static int modes[] = {
M_VGA_CG640,
M_VGA_CG320,
-1
};
static unsigned char *vid;
static unsigned int banksize, scrmode, scrw, scrh;
static unsigned int blanked;
#define FOCI 3
static struct {
int x, y;
int vx, vy;
} plasma_foci[FOCI];
static struct {
unsigned char r, g, b;
} plasma_pal[256];
static void
plasma_update(video_adapter_t *adp)
{
unsigned int x, y;
signed int dx, dy;
fp16_t sqd, d;
fp16_t m;
unsigned int org, off;
unsigned int i;
vidd_set_win_org(adp, 0);
for (y = org = off = 0; y < scrh; ++y) {
for (x = 0; x < scrw; ++x, ++off) {
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);
m = fp16_sub(m, fp16_cos(d / 4));
}
m = fp16_mul(m, ItoFP16(127));
m = fp16_div(m, ItoFP16(FOCI));
m = fp16_add(m, ItoFP16(127));
if (off > banksize) {
off -= banksize;
org += banksize;
vidd_set_win_org(adp, org);
}
vid[off] = FP16toI(m);
}
}
for (i = 0; i < FOCI; ++i) {
plasma_foci[i].x += plasma_foci[i].vx;
if (plasma_foci[i].x < 0) {
plasma_foci[i].vx = -plasma_foci[i].vx;
plasma_foci[i].x = -plasma_foci[i].x;
} else if (plasma_foci[i].x >= scrw) {
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) {
plasma_foci[i].vy = -plasma_foci[i].vy;
plasma_foci[i].y = -plasma_foci[i].y;
} else if (plasma_foci[i].y >= scrh) {
plasma_foci[i].vy = -plasma_foci[i].vy;
plasma_foci[i].y = scrh - (plasma_foci[i].y - scrh);
}
}
}
static int
plasma_saver(video_adapter_t *adp, int blank)
{
int pl;
if (blank) {
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);
}
plasma_update(adp);
} else {
blanked = 0;
}
return (0);
}
static int
plasma_init(video_adapter_t *adp)
{
video_info_t info;
int i;
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;
for (i = 0; i < 256; ++i)
plasma_pal[i].r = plasma_pal[i].g = plasma_pal[i].b = i;
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);
}
static int
plasma_term(video_adapter_t *adp)
{
return (0);
}
static scrn_saver_t plasma_module = {
SAVER_NAME,
plasma_init,
plasma_term,
plasma_saver,
NULL
};
SAVER_MODULE(plasma_saver, plasma_module);