2 * screenflip - takes snapshots of the screen and flips it around
4 * version 1.0 - Oct 24, 2001
6 * Copyright (C) 2001 Ben Buxton (bb@cactii.net)
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation. No representations are made about the suitability of this
13 * software for any purpose. It is provided "as is" without express or
17 #include <X11/Intrinsic.h>
21 # define PROGCLASS "Screenflip"
22 # define HACK_INIT init_screenflip
23 # define HACK_DRAW draw_screenflip
24 # define HACK_RESHAPE reshape_screenflip
25 # define screenflip_opts xlockmore_opts
26 /* insert defaults here */
28 #define DEFAULTS "*delay: 20000 \n" \
29 "*showFPS: False \n" \
31 "*wireframe: False \n" \
33 # include "xlockmore.h" /* from the xscreensaver distribution */
34 #else /* !STANDALONE */
35 # include "xlock.h" /* from the xlockmore distribution */
36 #endif /* !STANDALONE */
38 /* lifted from lament.c */
39 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
40 #define RANDSIGN() ((random() & 1) ? 1 : -1)
50 int tw, th; /* texture width, height */
52 GLfloat max_tx, max_ty;
56 GLfloat qw = QW, qh = QH; /* q? are for the quad we'll draw */
57 GLfloat qx = -6 , qy = 6;
60 #define countof(x) (sizeof((x))/sizeof((*x)))
63 static XrmOptionDescRec opts[] = {
64 {"+rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "false" },
65 {"-rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "true" },
69 static argtype vars[] = {
70 {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool},
75 ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL};
79 ModStruct screenflip_description =
80 {"screenflip", "init_screenflip", "draw_screenflip", "release_screenflip",
81 "draw_screenflip", "init_screenflip", NULL, &screenflip_opts,
82 1000, 1, 2, 1, 4, 1.0, "",
83 "Screenflips", 0, NULL};
89 GLXContext *glx_context;
93 static Screenflip *screenflip = NULL;
99 #include "grab-ximage.h"
102 #define M_PI 3.14159265
105 static GLfloat viewer[] = {0.0, 0.0, 15.0};
108 int fadetime = 0; /* fade before regrab */
111 /* draw the texture mapped quad (actually two back to back)*/
112 void showscreen(int frozen, int wire)
114 static GLfloat r = 1, g = 1, b = 1, a = 1;
117 /* static int stretch; */
118 static GLfloat stretch_val_x = 0, stretch_val_y = 0;
119 static GLfloat stretch_val_dx = 0, stretch_val_dy = 0;
120 /* static int stretch_x = 0, stretch_y = 0; */
123 /* r -= 0.02; g -= 0.02; b -= 0.02; */
131 stretch_val_x = stretch_val_y = stretch_val_dx = stretch_val_dy = 0;
133 if (stretch_val_dx == 0 && !frozen && !(random() % 25))
134 stretch_val_dx = (float)(random() % 100) / 5000;
135 if (stretch_val_dy == 0 && !frozen && !(random() % 25))
136 stretch_val_dy = (float)(random() % 100) / 5000;
144 w *= sin (stretch_val_x) + 1;
145 x *= sin (stretch_val_x) + 1;
146 if (!fadetime) stretch_val_x += stretch_val_dx;
147 if (stretch_val_x > 2*M_PI && !(random() % 5))
148 stretch_val_dx = (float)(random() % 100) / 5000;
150 stretch_val_x -= 2*M_PI;
152 if (!fadetime) stretch_val_y += stretch_val_dy;
153 h *= sin (stretch_val_y) / 2 + 1;
154 y *= sin (stretch_val_y) / 2 + 1;
155 if (stretch_val_y > 2*M_PI && !(random() % 5))
156 stretch_val_dy = (float)(random() % 100) / 5000;
158 stretch_val_y -= 2*M_PI;
161 glColor4f(r, g, b, a);
165 glEnable(GL_TEXTURE_2D);
167 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
168 glDepthMask(GL_FALSE);
171 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
175 glTexCoord2f(0, max_ty);
178 glTexCoord2f(max_tx, max_ty);
181 glTexCoord2f(max_tx, 0);
187 glNormal3f(0, 0, -1);
189 glTexCoord2f(0, max_ty);
190 glVertex3f(x, y, -0.05);
193 glVertex3f(x, h, -0.05);
195 glTexCoord2f(max_tx, 0);
196 glVertex3f(w, h, -0.05);
198 glTexCoord2f(max_tx, max_ty);
199 glVertex3f(w, y, -0.05);
204 glDisable(GL_TEXTURE_2D);
205 glDepthMask(GL_TRUE);
207 glBegin(GL_LINE_LOOP);
217 /* This function is responsible for 'zooming back' the square after
218 * a new chunk has been grabbed with getSnapshot(), and positioning
219 * it suitably on the screen. Once positioned (where we begin to rotate),
220 * it just does a glTranslatef() and returns 1
225 static GLfloat curx, cury, curz = 0;
231 if (curx == 0) curx = qx;
232 if (cury == 0) cury = qy;
239 if (curz > -10 || curx > wx + 0.1 || curx < wx - 0.1 ||
240 cury > wy + 0.1 || cury < wy - 0.1) {
259 glTranslatef(0, 0, curz);
262 glTranslatef(0, 0, curz);
271 glColor3f(0, 0.7, 0);
273 for (i = 0 ; i <= 50; i+=2) {
274 glVertex3f( -25, -15, i-70);
275 glVertex3f( 25, -15, i-70);
276 glVertex3f( i-25, -15, -70);
277 glVertex3f( i-25, -15, -20);
282 void display(int wire)
284 static GLfloat rx=1, ry=1, rz=0;
285 static GLfloat rot = 0;
286 static GLfloat drot = 0;
287 static GLfloat odrot = 1;
288 static GLfloat ddrot = 0;
289 static float theta = 0, rho = 0, dtheta = 0, drho = 0, gamma = 0, dgamma = 0;
293 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
295 gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
300 glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10);
301 /* randomly change the speed */
302 if (!(random() % 300)) {
304 drho = 1/60 - (float)(random() % 100)/3000;
306 dtheta = 1/60 - (float)(random() % 100)/3000;
308 dgamma = 1/60 - (float)(random() % 100)/3000;
310 if (rotate) glRotatef(rot, rx, ry, rz);
311 /* update variables with each frame */
319 /* dont let our rotation speed get too high */
320 if (drot > 5 && ddrot > 0)
321 ddrot = 0 - (GLfloat)(random() % 100) / 1000;
322 else if (drot < -5 && ddrot < 0)
323 ddrot = (GLfloat)(random() % 100) / 1000;
324 } else { /* reset some paramaters */
325 ddrot = 0.05 - (GLfloat)(random() % 100) / 1000;
326 theta = rho = gamma = 0;
330 if (!fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate change */
331 rx = (GLfloat)(random() % 100) / 100;
332 ry = (GLfloat)(random() % 100) / 100;
333 rz = (GLfloat)(random() % 100) / 100;
335 if (odrot * drot < 0 && tw < winw && !(random() % 10)) {
336 fadetime = 1; /* randomly fade and get new snapshot */
340 if (rot > 360 || rot < -360) /* dont overflow rotation! */
342 showscreen(frozen, wire);
347 void reshape_screenflip(ModeInfo *mi, int width, int height)
349 glViewport(0,0,(GLint)width, (GLint) height);
350 glMatrixMode(GL_PROJECTION);
352 gluPerspective(45, 1, 2.0, 85);
353 glMatrixMode(GL_MODELVIEW);
358 void getSnapshot (ModeInfo *modeinfo)
363 if (MI_IS_WIREFRAME(modeinfo))
366 ximage = screen_to_ximage (modeinfo->xgwa.screen, modeinfo->window);
369 tw = modeinfo->xgwa.width;
370 th = modeinfo->xgwa.height;
372 #if 0 /* jwz: this makes the image start off the bottom right of the screen */
377 qw *= (GLfloat)tw/winw;
378 qh *= (GLfloat)th/winh;
380 max_tx = (GLfloat) tw / (GLfloat) ximage->width;
381 max_ty = (GLfloat) th / (GLfloat) ximage->height;
384 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
385 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
386 GL_LINEAR_MIPMAP_LINEAR);
389 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
390 ximage->width, ximage->height,
391 GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
394 const char *s = gluErrorString (status);
395 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
396 progname, ximage->width, ximage->height,
397 (s ? s : "(unknown)"));
398 fprintf (stderr, "%s: turning on -wireframe.\n", progname);
399 MI_IS_WIREFRAME(modeinfo) = 1;
402 check_gl_error("mipmapping"); /* should get a return code instead of a
403 GL error, but just in case... */
407 XDestroyImage (ximage);
410 void init_screenflip(ModeInfo *mi)
412 int screen = MI_SCREEN(mi);
415 if (screenflip == NULL) {
416 if ((screenflip = (Screenflip *) calloc(MI_NUM_SCREENS(mi),
417 sizeof(Screenflip))) == NULL)
420 c = &screenflip[screen];
421 c->window = MI_WINDOW(mi);
423 if ((c->glx_context = init_GL(mi)) != NULL) {
424 reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
428 winh = MI_WIN_HEIGHT(mi);
429 winw = MI_WIN_WIDTH(mi);
430 glClearColor(0.0,0.0,0.0,0.0);
432 if (! MI_IS_WIREFRAME(mi))
434 glShadeModel(GL_SMOOTH);
435 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
436 glEnable(GL_DEPTH_TEST);
437 glEnable(GL_CULL_FACE);
438 glCullFace(GL_FRONT);
439 glDisable(GL_LIGHTING);
445 void draw_screenflip(ModeInfo *mi)
447 Screenflip *c = &screenflip[MI_SCREEN(mi)];
448 Window w = MI_WINDOW(mi);
449 Display *disp = MI_DISPLAY(mi);
454 glXMakeCurrent(disp, w, *(c->glx_context));
459 display(MI_IS_WIREFRAME(mi));
461 if(mi->fps_p) do_fps(mi);
463 glXSwapBuffers(disp, w);
466 void release_screenflip(ModeInfo *mi)
468 if (screenflip != NULL) {
469 (void) free((void *) screenflip);