summaryrefslogtreecommitdiffstats
path: root/hacks/glx/flurry.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/flurry.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/glx/flurry.c')
-rw-r--r--hacks/glx/flurry.c549
1 files changed, 549 insertions, 0 deletions
diff --git a/hacks/glx/flurry.c b/hacks/glx/flurry.c
new file mode 100644
index 0000000..c9008a9
--- /dev/null
+++ b/hacks/glx/flurry.c
@@ -0,0 +1,549 @@
+/* -*- Mode: C; tab-width: 4 c-basic-offset: 4 indent-tabs-mode: t -*- */
+/*
+ * vim: ts=8 sw=4 noet
+ */
+
+/*
+
+Copyright (c) 2002, Calum Robinson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* 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.
+
+* Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+*/
+
+/* flurry */
+
+#if 0
+static const char sccsid[] = "@(#)flurry.c 4.07 97/11/24 xlockmore";
+#endif
+
+#define DEF_PRESET "random"
+#define DEF_BRIGHTNESS "8"
+
+# define DEFAULTS "*delay: 10000 \n" \
+ "*showFPS: False \n"
+
+# define release_flurry 0
+# define flurry_handle_event xlockmore_no_events
+# include "xlockmore.h" /* from the xscreensaver distribution */
+
+#ifdef USE_GL
+
+static char *preset_str;
+
+static XrmOptionDescRec opts[] = {
+ { "-preset", ".preset", XrmoptionSepArg, 0 }
+};
+
+static argtype vars[] = {
+ {&preset_str, "preset", "Preset", DEF_PRESET, t_String},
+};
+
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+ENTRYPOINT ModeSpecOpt flurry_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef USE_MODULES
+ModStruct flurry_description = {
+ "flurry",
+ "init_flurry",
+ "draw_flurry",
+ NULL,
+ "draw_flurry",
+ "init_flurry",
+ "free_flurry",
+ &flurry_opts,
+ 1000, 1, 2, 1, 4, 1.0,
+ "",
+ "Flurry",
+ 0,
+ NULL
+};
+
+#endif
+
+#include "flurry.h"
+
+global_info_t *flurry_info = NULL;
+
+static
+double currentTime(void) {
+ struct timeval tv;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+ struct timezone tzp;
+ gettimeofday(&tv, &tzp);
+# else
+ gettimeofday(&tv);
+# endif
+
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+}
+
+double TimeInSecondsSinceStart (const global_info_t *global) {
+ return currentTime() - global->gTimeCounter;
+}
+
+#if 0
+#ifdef __ppc__
+static int IsAltiVecAvailable(void)
+{
+ return 0;
+}
+#endif
+#endif
+
+
+static
+void delete_flurry_info(flurry_info_t *flurry)
+{
+ int i;
+
+ free(flurry->s);
+ free(flurry->star);
+ for (i=0;i<MAX_SPARKS;i++)
+ {
+ free(flurry->spark[i]);
+ }
+ /* free(flurry); */
+}
+
+static
+flurry_info_t *new_flurry_info(global_info_t *global, int streams, ColorModes colour, float thickness, float speed, double bf)
+{
+ int i,k;
+ flurry_info_t *flurry = (flurry_info_t *)malloc(sizeof(flurry_info_t));
+
+ if (!flurry) return NULL;
+
+ flurry->flurryRandomSeed = RandFlt(0.0, 300.0);
+
+ flurry->fOldTime = 0;
+ flurry->dframe = 0;
+ flurry->fTime = TimeInSecondsSinceStart(global) + flurry->flurryRandomSeed;
+ flurry->fDeltaTime = flurry->fTime - flurry->fOldTime;
+
+ flurry->numStreams = streams;
+ flurry->streamExpansion = thickness;
+ flurry->currentColorMode = colour;
+ flurry->briteFactor = bf;
+
+ flurry->s = malloc(sizeof(SmokeV));
+ InitSmoke(flurry->s);
+
+ flurry->star = malloc(sizeof(Star));
+ InitStar(flurry->star);
+ flurry->star->rotSpeed = speed;
+
+ for (i = 0;i < MAX_SPARKS; i++)
+ {
+ flurry->spark[i] = malloc(sizeof(Spark));
+ InitSpark(flurry->spark[i]);
+ flurry->spark[i]->mystery = 1800 * (i + 1) / 13; /* 100 * (i + 1) / (flurry->numStreams + 1); */
+ UpdateSpark(global, flurry, flurry->spark[i]);
+ }
+
+ for (i=0;i<NUMSMOKEPARTICLES/4;i++) {
+ for(k=0;k<4;k++) {
+ flurry->s->p[i].dead.i[k] = 1;
+ }
+ }
+
+ flurry->next = NULL;
+
+ return flurry;
+}
+
+static
+void GLSetupRC(global_info_t *global)
+{
+ /* setup the defaults for OpenGL */
+ glDisable(GL_DEPTH_TEST);
+ glAlphaFunc(GL_GREATER,0.0f);
+ glEnable(GL_ALPHA_TEST);
+ glShadeModel(GL_FLAT);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_BLEND);
+
+ glViewport(0,0,(int) global->sys_glWidth,(int) global->sys_glHeight);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0,global->sys_glWidth,0,global->sys_glHeight,-1,1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+#if 0
+#ifdef __ppc__
+ global->optMode = OPT_MODE_SCALAR_FRSQRTE;
+
+#ifdef __VEC__
+ if (IsAltiVecAvailable()) global->optMode = OPT_MODE_VECTOR_UNROLLED;
+#endif
+
+#else
+ global->optMode = OPT_MODE_SCALAR_BASE;
+#endif
+#endif /* 0 */
+}
+
+static
+void GLRenderScene(global_info_t *global, flurry_info_t *flurry, double b)
+{
+ int i;
+
+ flurry->dframe++;
+
+ flurry->fOldTime = flurry->fTime;
+ flurry->fTime = TimeInSecondsSinceStart(global) + flurry->flurryRandomSeed;
+ flurry->fDeltaTime = flurry->fTime - flurry->fOldTime;
+
+ flurry->drag = (float) pow(0.9965,flurry->fDeltaTime*85.0);
+
+ UpdateStar(global, flurry, flurry->star);
+
+#ifdef DRAW_SPARKS
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+#endif
+
+ for (i=0;i<flurry->numStreams;i++) {
+ flurry->spark[i]->color[0]=1.0;
+ flurry->spark[i]->color[1]=1.0;
+ flurry->spark[i]->color[2]=1.0;
+ flurry->spark[i]->color[2]=1.0;
+ UpdateSpark(global, flurry, flurry->spark[i]);
+#ifdef DRAW_SPARKS
+ DrawSpark(global, flurry, flurry->spark[i]);
+#endif
+ }
+
+ switch(global->optMode) {
+ case OPT_MODE_SCALAR_BASE:
+ UpdateSmoke_ScalarBase(global, flurry, flurry->s);
+ break;
+#if 0
+#ifdef __ppc__
+ case OPT_MODE_SCALAR_FRSQRTE:
+ UpdateSmoke_ScalarFrsqrte(global, flurry, flurry->s);
+ break;
+#endif
+#ifdef __VEC__
+ case OPT_MODE_VECTOR_SIMPLE:
+ UpdateSmoke_VectorBase(global, flurry, flurry->s);
+ break;
+ case OPT_MODE_VECTOR_UNROLLED:
+ UpdateSmoke_VectorUnrolled(global, flurry, flurry->s);
+ break;
+#endif
+#endif /* 0 */
+
+ default:
+ break;
+ }
+
+ /* glDisable(GL_BLEND); */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glEnable(GL_TEXTURE_2D);
+
+ switch(global->optMode) {
+ case OPT_MODE_SCALAR_BASE:
+#if 0
+#ifdef __ppc__
+ case OPT_MODE_SCALAR_FRSQRTE:
+#endif
+#endif /* 0 */
+ DrawSmoke_Scalar(global, flurry, flurry->s, b);
+ break;
+#if 0
+#ifdef __VEC__
+ case OPT_MODE_VECTOR_SIMPLE:
+ case OPT_MODE_VECTOR_UNROLLED:
+ DrawSmoke_Vector(global, flurry, flurry->s, b);
+ break;
+#endif
+#endif /* 0 */
+ default:
+ break;
+ }
+
+ glDisable(GL_TEXTURE_2D);
+}
+
+static
+void GLResize(global_info_t *global, float w, float h)
+{
+ global->sys_glWidth = w;
+ global->sys_glHeight = h;
+}
+
+/* new window size or exposure */
+ENTRYPOINT void reshape_flurry(ModeInfo *mi, int width, int height)
+{
+ global_info_t *global = flurry_info + MI_SCREEN(mi);
+
+ glXMakeCurrent(MI_DISPLAY(mi), global->window, *(global->glx_context));
+
+ glViewport(0.0, 0.0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, width, 0, height,-1,1);
+ glMatrixMode(GL_MODELVIEW);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glFlush();
+ GLResize(global, (float)width, (float)height);
+}
+
+ENTRYPOINT void
+init_flurry(ModeInfo * mi)
+{
+ int screen = MI_SCREEN(mi);
+ int i;
+ global_info_t *global;
+ enum {
+ PRESET_INSANE = -1,
+ PRESET_WATER = 0,
+ PRESET_FIRE,
+ PRESET_PSYCHEDELIC,
+ PRESET_RGB,
+ PRESET_BINARY,
+ PRESET_CLASSIC,
+ PRESET_MAX
+ } preset_num;
+
+ MI_INIT (mi, flurry_info);
+
+ global = &flurry_info[screen];
+
+ global->gTimeCounter = currentTime();
+
+ global->window = MI_WINDOW(mi);
+
+ global->flurry = NULL;
+
+ if (!preset_str || !*preset_str) preset_str = DEF_PRESET;
+ if (!strcmp(preset_str, "random")) {
+ preset_num = random() % PRESET_MAX;
+ } else if (!strcmp(preset_str, "water")) {
+ preset_num = PRESET_WATER;
+ } else if (!strcmp(preset_str, "fire")) {
+ preset_num = PRESET_FIRE;
+ } else if (!strcmp(preset_str, "psychedelic")) {
+ preset_num = PRESET_PSYCHEDELIC;
+ } else if (!strcmp(preset_str, "rgb")) {
+ preset_num = PRESET_RGB;
+ } else if (!strcmp(preset_str, "binary")) {
+ preset_num = PRESET_BINARY;
+ } else if (!strcmp(preset_str, "classic")) {
+ preset_num = PRESET_CLASSIC;
+ } else if (!strcmp(preset_str, "insane")) {
+ preset_num = PRESET_INSANE;
+ } else {
+ fprintf(stderr, "%s: unknown preset %s\n", progname, preset_str);
+ exit(1);
+ }
+
+ switch (preset_num) {
+ case PRESET_WATER: {
+ for (i = 0; i < 9; i++) {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 1, blueColorMode, 100.0, 2.0, 2.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ }
+ break;
+ }
+ case PRESET_FIRE: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 12, slowCyclicColorMode, 10000.0, 0.2, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ break;
+ }
+ case PRESET_PSYCHEDELIC: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 10, rainbowColorMode, 200.0, 2.0, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ break;
+ }
+ case PRESET_RGB: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 3, redColorMode, 100.0, 0.8, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+
+ flurry = new_flurry_info(global, 3, greenColorMode, 100.0, 0.8, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+
+ flurry = new_flurry_info(global, 3, blueColorMode, 100.0, 0.8, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ break;
+ }
+ case PRESET_BINARY: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 16, tiedyeColorMode, 1000.0, 0.5, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+
+ flurry = new_flurry_info(global, 16, tiedyeColorMode, 1000.0, 1.5, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ break;
+ }
+ case PRESET_CLASSIC: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 5, tiedyeColorMode, 10000.0, 1.0, 1.0);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+ break;
+ }
+ case PRESET_INSANE: {
+ flurry_info_t *flurry;
+
+ flurry = new_flurry_info(global, 64, tiedyeColorMode, 1000.0, 0.5, 0.5);
+ flurry->next = global->flurry;
+ global->flurry = flurry;
+
+ break;
+ }
+ default: {
+ fprintf(stderr, "%s: unknown preset %s\n", progname, preset_str);
+ exit(1);
+ }
+ }
+
+ if ((global->glx_context = init_GL(mi)) != NULL) {
+ reshape_flurry(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+ GLSetupRC(global);
+ } else {
+ MI_CLEARWINDOW(mi);
+ }
+
+ global->first = 1;
+ global->oldFrameTime = -1;
+}
+
+ENTRYPOINT void
+draw_flurry(ModeInfo * mi)
+{
+ double newFrameTime;
+ double deltaFrameTime = 0;
+ double brite;
+ GLfloat alpha;
+
+ global_info_t *global = flurry_info + MI_SCREEN(mi);
+ flurry_info_t *flurry;
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+
+ newFrameTime = currentTime();
+ if (global->oldFrameTime == -1) {
+ /* special case the first frame -- clear to black */
+ alpha = 1.0;
+ } else {
+ /*
+ * this clamps the speed at below 60fps and, here
+ * at least, produces a reasonably accurate 50fps.
+ * (probably part CPU speed and part scheduler).
+ *
+ * Flurry is designed to run at this speed; much higher
+ * than that and the blending causes the display to
+ * saturate, which looks really ugly.
+ */
+ if (newFrameTime - global->oldFrameTime < 1/60.0) {
+ usleep(MAX_(1,(int)(20000 * (newFrameTime - global->oldFrameTime))));
+ return;
+
+ }
+ deltaFrameTime = newFrameTime - global->oldFrameTime;
+ alpha = 5.0 * deltaFrameTime;
+ }
+ global->oldFrameTime = newFrameTime;
+
+ if (alpha > 0.2) alpha = 0.2;
+
+ if (!global->glx_context)
+ return;
+
+ if (global->first) {
+ MakeTexture();
+ global->first = 0;
+ }
+ glDrawBuffer(GL_BACK);
+ glXMakeCurrent(display, window, *(global->glx_context));
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glColor4f(0.0, 0.0, 0.0, alpha);
+ glRectd(0, 0, global->sys_glWidth, global->sys_glHeight);
+
+ brite = pow(deltaFrameTime,0.75) * 10;
+ for (flurry = global->flurry; flurry; flurry=flurry->next) {
+ GLRenderScene(global, flurry, brite * flurry->briteFactor);
+ }
+
+ if (mi->fps_p) do_fps (mi);
+
+ glFinish();
+ glXSwapBuffers(display, window);
+}
+
+ENTRYPOINT void
+free_flurry(ModeInfo * mi)
+{
+ global_info_t *global = &flurry_info[MI_SCREEN(mi)];
+ flurry_info_t *flurry;
+
+ if (global->glx_context) {
+ glXMakeCurrent(MI_DISPLAY(mi), global->window, *(global->glx_context));
+ }
+
+ for (flurry = global->flurry; flurry; flurry=flurry->next) {
+ delete_flurry_info(flurry);
+ }
+}
+
+XSCREENSAVER_MODULE ("Flurry", flurry)
+
+#endif