From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/flipscreen3d.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 hacks/glx/flipscreen3d.c (limited to 'hacks/glx/flipscreen3d.c') diff --git a/hacks/glx/flipscreen3d.c b/hacks/glx/flipscreen3d.c new file mode 100644 index 0000000..e4db5df --- /dev/null +++ b/hacks/glx/flipscreen3d.c @@ -0,0 +1,518 @@ +/* + * flipscreen3d - takes snapshots of the screen and flips it around + * + * version 1.0 - Oct 24, 2001 + * + * Copyright (C) 2001 Ben Buxton (bb@cactii.net) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*useSHM: True \n" \ + "*suppressRotationAnimation: True\n" \ + +# define free_screenflip 0 +# define release_screenflip 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +# include "gltrackball.h" +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + +#define DEF_ROTATE "True" +static int rotate; + +#define QW 12 +#define QH 12 + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static XrmOptionDescRec opts[] = { + {"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" }, +}; + + +static argtype vars[] = { + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, +}; + + + +ENTRYPOINT ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#ifdef USE_MODULES +ModStruct screenflip_description = +{"screenflip", "init_screenflip", "draw_screenflip", NULL, + "draw_screenflip", "init_screenflip", NULL, &screenflip_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Screenflips", 0, NULL}; + +#endif + + +typedef struct { + GLXContext *glx_context; + Window window; + + int winw, winh; + int tw, th; /* texture width, height */ + GLfloat min_tx, min_ty; + GLfloat max_tx, max_ty; + GLfloat qx, qy, qw, qh; /* the quad we'll draw */ + + int regrab; + int fadetime; /* fade before regrab */ + + trackball_state *trackball; + Bool button_down_p; + + GLfloat show_colors[4]; + GLfloat stretch_val_x, stretch_val_y; + GLfloat stretch_val_dx, stretch_val_dy; + + GLfloat curx, cury, curz; + + GLfloat rx, ry, rz; + GLfloat rot, drot, odrot, ddrot, orot; + float theta, rho, dtheta, drho, gamma, dgamma; + + GLuint texid; + Bool mipmap_p; + Bool waiting_for_image_p; + Bool first_image_p; + + GLfloat anisotropic; + +} Screenflip; + +static Screenflip *screenflip = NULL; + +#include "grab-ximage.h" + +static const GLfloat viewer[] = {0.0, 0.0, 15.0}; + + +static void getSnapshot (ModeInfo *); + + +ENTRYPOINT Bool +screenflip_handle_event (ModeInfo *mi, XEvent *event) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + + if (gltrackball_event_handler (event, c->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &c->button_down_p)) + return True; + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) + { + if (!c->waiting_for_image_p) + { + getSnapshot (mi); + return True; + } + } + + return False; +} + + +/* draw the texture mapped quad (actually two back to back)*/ +static void showscreen(Screenflip *c, int frozen, int wire) +{ + GLfloat x, y, w, h; + + if (c->fadetime) { +/* r -= 0.02; g -= 0.02; b -= 0.02; */ + c->show_colors[3] -= 0.02; + if (c->show_colors[3] < 0) { + c->regrab = 1; + c->fadetime = 0; + } + } else if (c->show_colors[3] < 0) { + c->show_colors[0] = c->show_colors[1] = + c->show_colors[2] = c->show_colors[3] = 1; + c->stretch_val_x = c->stretch_val_y = + c->stretch_val_dx = c->stretch_val_dy = 0; + } + if (c->stretch_val_dx == 0 && !frozen && !(random() % 25)) + c->stretch_val_dx = (float)(random() % 100) / 5000; + if (c->stretch_val_dy == 0 && !frozen && !(random() % 25)) + c->stretch_val_dy = (float)(random() % 100) / 5000; + + x = c->qx; + y = c->qy; + w = c->qx+c->qw; + h = c->qy-c->qh; + + if (!frozen) { + w *= sin (c->stretch_val_x) + 1; + x *= sin (c->stretch_val_x) + 1; + if (!c->button_down_p) { + if (!c->fadetime) c->stretch_val_x += c->stretch_val_dx; + if (c->stretch_val_x > 2*M_PI && !(random() % 5)) + c->stretch_val_dx = (float)(random() % 100) / 5000; + else + c->stretch_val_x -= 2*M_PI; + } + + if (!c->button_down_p && !c->fadetime) c->stretch_val_y += c->stretch_val_dy; + h *= sin (c->stretch_val_y) / 2 + 1; + y *= sin (c->stretch_val_y) / 2 + 1; + if (!c->button_down_p) { + if (c->stretch_val_y > 2*M_PI && !(random() % 5)) + c->stretch_val_dy = (float)(random() % 100) / 5000; + else + c->stretch_val_y -= 2*M_PI; + } + } + + glColor4f(c->show_colors[0], c->show_colors[1], + c->show_colors[2], c->show_colors[3]); + + if (!wire) + { + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); + } + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + + glNormal3f(0, 0, 1); + glTexCoord2f(c->max_tx, c->max_ty); glVertex3f(w, h, 0); + glTexCoord2f(c->max_tx, c->min_ty); glVertex3f(w, y, 0); + glTexCoord2f(c->min_tx, c->min_ty); glVertex3f(x, y, 0); + glTexCoord2f(c->min_tx, c->max_ty); glVertex3f(x, h, 0); + + glNormal3f(0, 0, -1); + glTexCoord2f(c->min_tx, c->min_ty); glVertex3f(x, y, -0.05); + glTexCoord2f(c->max_tx, c->min_ty); glVertex3f(w, y, -0.05); + glTexCoord2f(c->max_tx, c->max_ty); glVertex3f(w, h, -0.05); + glTexCoord2f(c->min_tx, c->max_ty); glVertex3f(x, h, -0.05); + glEnd(); + + + glDisable(GL_TEXTURE_2D); + glDepthMask(GL_TRUE); + + glBegin(GL_LINE_LOOP); + glVertex3f(x, y, 0); + glVertex3f(x, h, 0); + glVertex3f(w, h, 0); + glVertex3f(w, y, 0); + glEnd(); + glDisable(GL_BLEND); + +} + +/* This function is responsible for 'zooming back' the square after + * a new chunk has been grabbed with getSnapshot(), and positioning + * it suitably on the screen. Once positioned (where we begin to rotate), + * it just does a glTranslatef() and returns 1 + */ + +static int inposition(Screenflip *c) +{ + GLfloat wx; + GLfloat wy; + wx = 0 - (c->qw/2); + wy = (c->qh/2); + + if (c->curx == 0) c->curx = c->qx; + if (c->cury == 0) c->cury = c->qy; + if (c->regrab) { + c->curz = 0; + c->curx = c->qx; + c->cury = c->qy; + c->regrab = 0; + } + if (c->curz > -10 || c->curx > wx + 0.1 || c->curx < wx - 0.1 || + c->cury > wy + 0.1 || c->cury < wy - 0.1) { + if (c->curz > -10) + c->curz -= 0.05; + if (c->curx > wx) { + c->qx -= 0.02; + c->curx -= 0.02; + } + if (c->curx < wx) { + c->qx += 0.02; + c->curx += 0.02; + } + if (c->cury > wy) { + c->qy -= 0.02; + c->cury -= 0.02; + } + if (c->cury < wy) { + c->qy += 0.02; + c->cury += 0.02; + } + glTranslatef(0, 0, c->curz); + return 0; + } + glTranslatef(0, 0, c->curz); + return 1; + +} + +#if 0 +static void drawgrid(void) +{ + int i; + + glColor3f(0, 0.7, 0); + glBegin(GL_LINES); + for (i = 0 ; i <= 50; i+=2) { + glVertex3f( -25, -15, i-70); + glVertex3f( 25, -15, i-70); + glVertex3f( i-25, -15, -70); + glVertex3f( i-25, -15, -20); + } + glEnd(); +} +#endif + + +static void display(Screenflip *c, int wire) +{ + int frozen; + GLfloat rot = current_device_rotation(); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glPushMatrix(); + +/* + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = c->winw / (GLfloat) c->winh; + glScalef (s, 1/s, 1); + } +*/ + + if (inposition(c)) { + frozen = 0; + glTranslatef(5 * sin(c->theta), 5 * sin(c->rho), 10 * cos(c->gamma) - 10); +/* randomly change the speed */ + if (!c->button_down_p && !(random() % 300)) { + if (random() % 2) + c->drho = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + c->dtheta = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + c->dgamma = 1/60 - (float)(random() % 100)/3000; + } + glRotatef(rot, 0, 0, 1); + gltrackball_rotate (c->trackball); + glRotatef(-rot, 0, 0, 1); + if (rotate) glRotatef(c->rot, c->rx, c->ry, c->rz); +/* update variables with each frame */ + if(!c->button_down_p && !c->fadetime) { + c->theta += c->dtheta; + c->rho += c->drho; + c->gamma += c->dgamma; + c->rot += c->drot; + c->drot += c->ddrot; + } +/* dont let our rotation speed get too high */ + if (c->drot > 5 && c->ddrot > 0) + c->ddrot = 0 - (GLfloat)(random() % 100) / 1000; + else if (c->drot < -5 && c->ddrot < 0) + c->ddrot = (GLfloat)(random() % 100) / 1000; + } else { /* reset some paramaters */ + c->ddrot = 0.05 - (GLfloat)(random() % 100) / 1000; + c->theta = c->rho = c->gamma = 0; + c->rot = 0; + frozen = 1; + } + if (!c->button_down_p && !c->fadetime && (c->rot >= 360 || c->rot <= -360) && !(random() % 7)) { /* rotate change */ + c->rx = (GLfloat)(random() % 100) / 100; + c->ry = (GLfloat)(random() % 100) / 100; + c->rz = (GLfloat)(random() % 100) / 100; + } + if (c->odrot * c->drot < 0 && c->tw < c->winw && !(random() % 10)) { + c->fadetime = 1; /* randomly fade and get new snapshot */ + } + c->orot = c->rot; + c->odrot = c->drot; + if (c->rot > 360 || c->rot < -360) /* dont overflow rotation! */ + c->rot -= c->rot; + showscreen(c, frozen, wire); + glPopMatrix(); + glFlush(); +} + +ENTRYPOINT void reshape_screenflip(ModeInfo *mi, int width, int height) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + glViewport(0,0,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1, 2.0, 85); + glMatrixMode(GL_MODELVIEW); + c->winw = width; + c->winh = height; +} + +static void +image_loaded_cb (const char *filename, XRectangle *geometry, + int image_width, int image_height, + int texture_width, int texture_height, + void *closure) +{ + Screenflip *c = (Screenflip *) closure; + + c->tw = texture_width; + c->th = texture_height; + c->min_tx = (GLfloat) geometry->x / c->tw; + c->min_ty = (GLfloat) geometry->y / c->th; + c->max_tx = (GLfloat) (geometry->x + geometry->width) / c->tw; + c->max_ty = (GLfloat) (geometry->y + geometry->height) / c->th; + + c->qx = -QW/2 + ((GLfloat) geometry->x * QW / image_width); + c->qy = QH/2 - ((GLfloat) geometry->y * QH / image_height); + c->qw = QW * ((GLfloat) geometry->width / image_width); + c->qh = QH * ((GLfloat) geometry->height / image_height); + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (c->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); + + if (c->anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + c->anisotropic); + + c->waiting_for_image_p = False; + c->first_image_p = False; +} + + +static void getSnapshot (ModeInfo *modeinfo) +{ + Screenflip *c = &screenflip[MI_SCREEN(modeinfo)]; + + if (MI_IS_WIREFRAME(modeinfo)) + return; + + c->waiting_for_image_p = True; + c->mipmap_p = True; + load_texture_async (modeinfo->xgwa.screen, modeinfo->window, + *c->glx_context, 0, 0, c->mipmap_p, c->texid, + image_loaded_cb, c); +} + +ENTRYPOINT void init_screenflip(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + Screenflip *c; + + MI_INIT(mi, screenflip); + c = &screenflip[screen]; + c->window = MI_WINDOW(mi); + + c->trackball = gltrackball_init (False); + + if ((c->glx_context = init_GL(mi)) != NULL) { + reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + c->winh = MI_WIN_HEIGHT(mi); + c->winw = MI_WIN_WIDTH(mi); + c->qw = QW; + c->qh = QH; + c->qx = -6; + c->qy = 6; + + c->rx = c->ry = 1; + c->odrot = 1; + + c->show_colors[0] = c->show_colors[1] = + c->show_colors[2] = c->show_colors[3] = 1; + + if (! MI_IS_WIREFRAME(mi)) + { + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glDisable(GL_LIGHTING); + } + + if (strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &c->anisotropic); + else + c->anisotropic = 0.0; + + glGenTextures(1, &c->texid); + + c->first_image_p = True; + getSnapshot(mi); +} + +ENTRYPOINT void draw_screenflip(ModeInfo *mi) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!c->glx_context) + return; + + /* Wait for the first image; for subsequent images, load them in the + background while animating. */ + if (c->waiting_for_image_p && c->first_image_p) + return; + + glXMakeCurrent(disp, w, *(c->glx_context)); + + glBindTexture(GL_TEXTURE_2D, c->texid); + + if (c->regrab) + getSnapshot(mi); + + display(c, MI_IS_WIREFRAME(mi)); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +XSCREENSAVER_MODULE_2 ("FlipScreen3D", flipscreen3d, screenflip) + +#endif -- cgit v1.2.3-55-g7522