1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* vim: set ai ts=4 sw=4: */
4 #if !defined( lint ) && !defined( SABER )
5 /*static const char sccsid[] = "@(#)gleidescope.c 1.0 03/06/27 xlockmore";*/
8 /* enable -grab switch for animations */
11 #undef DISPLAY_TEXTURE
14 * Permission to use, copy, modify, and distribute this software and its
15 * documentation for any purpose and without fee is hereby granted,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation.
20 * This file is provided AS IS with no warranties of any kind. The author
21 * shall have no liability with respect to the infringement of copyrights,
22 * trade secrets or any patents by this file or any part thereof. In no
23 * event will the author be liable for any lost revenue or profits or
24 * other special, indirect and consequential damages.
28 * 20030627 1.0 acd First Release.
29 * Texture loading code from 'glplanet'
30 * by Jamie Zawinski <jwz@jwz.org>
31 * 20030810 1.1 acd Added size flag.
32 * Now grabs screen / video / picture
33 * (uses code from 'glslideshow' by
34 * Mike Oliphant, Ben Buxton, Jamie Zawinski).
37 * Added fade code (also from glslideshow).
38 * 20031013 1.2 acd Migrated to compile without warnings under
40 * 20031023 1.3 acd Better code to limit twisting speeds.
41 * Tweaked initial rotation values.
42 * Move, Rotate, Zoom now chosen at random if
43 * no preference is given.
44 * Made grid slightly bigger so you can't see
45 * the edge when zooming and moving.
46 * 20061226 1.4 acd Now uses GL Display Lists.
47 * 20070318 1.5 acd Generates textures.
48 * Fixed texture size problem (and introduced another).
49 * 20070412 1.6 acd Textures now have independant sizes.
50 * 20070413 1.7 acd Added Lissajous movement pattern.
51 * 20070414 1.8 acd Added corners movement pattern.
52 * 20080319 1.9 acd Changes to arguments for saner gleidescope.xml.
55 * generate textures myself - render random shapes to 256x256 texture. (done)
56 * lower res for checks and random - use 256 and 4x4 or 8x8 pixels. (disabled for now)
57 * gnome-saver doesn't let you specify source directory so add that to this.
58 * image loading routine is too slow - rotation grinds to a halt - stop using it. (better in version 5)
59 * image loading also looks bad for non-square images - edges are black. (fixed)
60 * possible to see edge of the world on widescreen terminals - use larger grid and hidden hex removal?
61 * fading textures may have different max_tx - use two sets. (done)
62 * choice of movement patterns. (3 implemented, chooseable at compile time)
63 * look into rangle and tangle.
67 **----------------------------------------------------------------------------
69 **----------------------------------------------------------------------------
75 "*showFPS: False \n" \
79 # define refresh_gleidescope 0
80 # include "xlockmore.h" /* from the xscreensaver distribution */
81 #else /* !STANDALONE */
82 # include "xlock.h" /* from the xlockmore distribution */
83 #endif /* !STANDALONE */
88 #include "xpm-ximage.h"
89 #include "grab-ximage.h"
92 void grab_frame(Display *display, Window window);
95 /* acd TODO should all these be in gleidestruct? */
96 /* they can't be, because of the idiotic way the xlockmore "argtype vars"
97 interface works. -jwz */
99 static Bool grab; /* grab images */
101 static Bool move; /* moving camera */
102 static Bool nomove; /* no moving camera */
103 static Bool rotate; /* rotate in place */
104 static Bool norotate; /* no rotate in place */
105 static Bool zoom; /* zooming camera */
106 static Bool nozoom; /* no zooming camera */
107 static char *image; /* name of texture to load */
108 static int duration; /* length of time to display grabbed image */
110 #define MAX_CAM_SPEED 1.0
111 #define MAX_ANGLE_VEL 1.0
112 #define INITIAL_ANGLE_VEL 0.2
113 #define INITIAL_ANGLE_ACC 0.001
114 #define TWISTING_PROBABILITY 1000 /* 1 in ... of change of acceleration */
116 #define RADIANS (M_PI / 180)
117 #define ANGLE_120 (M_PI * 2 / 3)
118 #define ANGLE_240 (M_PI * 4 / 3)
120 static XrmOptionDescRec opts[] =
123 {"-grab", ".gleidescope.grab", XrmoptionNoArg, "true"},
125 {"-move", ".gleidescope.move", XrmoptionNoArg, "true"},
126 {"-no-move", ".gleidescope.nomove", XrmoptionNoArg, "true"},
127 {"-rotate", ".gleidescope.rotate", XrmoptionNoArg, "true"},
128 {"-no-rotate", ".gleidescope.norotate", XrmoptionNoArg, "true"},
129 /*{"-size", ".gleidescope.size", XrmoptionNoArg, "-1"},*/
130 {"-zoom", ".gleidescope.zoom", XrmoptionNoArg, "true"},
131 {"-no-zoom", ".gleidescope.nozoom", XrmoptionNoArg, "true"},
132 {"-image", ".gleidescope.image", XrmoptionSepArg, "DEFAULT"},
133 {"-duration", ".gleidescope.duration", XrmoptionSepArg, "30"},
137 static argtype vars[] = {
139 {&grab, "grab", "Grab", "False", t_Bool},
141 {&move, "move", "Move", "False", t_Bool},
142 {&nomove, "nomove", "noMove", "False", t_Bool},
143 {&rotate, "rotate", "Rotate", "False", t_Bool},
144 {&norotate, "norotate", "noRotate", "False", t_Bool},
145 /*{&size, "size", "Size", "-1", t_Int},*/
146 {&zoom, "zoom", "Zoom", "False", t_Bool},
147 {&nozoom, "nozoom", "noZoom", "False", t_Bool},
148 {&image, "image", "Image", "DEFAULT", t_String},
149 {&duration, "duration", "Duration", "30", t_Int},
152 static OptionStruct desc[] = {
154 {"-grab", "grab images to create animation"},
156 {"-move", "camera will move"},
157 {"-no-move", "camera won't move"},
158 {"-rotate", "camera will rotate"},
159 {"-no-rotate", "camera won't rotate"},
160 /*{"-size", "size of the hexagons (1-10)"},*/
161 {"-zoom", "camera will zoom"},
162 {"-no-zoom", "camera won't zoom"},
163 {"-image", "xpm / xbm image file to use for texture"},
164 {"-duration", "length of time texture will be used"},
167 ENTRYPOINT ModeSpecOpt gleidescope_opts = {
168 sizeof opts / sizeof opts[0], opts,
169 sizeof vars / sizeof vars[0], vars,
174 ModStruct gleidescope_description = {
175 "gleidescope", "init_gleidescope", "draw_gleidescope", "release_gleidescope",
176 "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts,
177 1000, 1, 2, 1, 4, 1.0, "",
178 "GL Kaleidescope", 0, NULL};
182 **-----------------------------------------------------------------------------
184 **-----------------------------------------------------------------------------
187 typedef struct hex_s {
188 GLfloat x, y, z; /* position */
203 GLuint id; /* opengl texture id */
204 GLfloat width, height; /* texture width and height */
205 GLfloat min_tx, min_ty; /* minimum texture sizes */
206 GLfloat max_tx, max_ty; /* maximum texture sizes */
210 Bool waiting_for_image_p;
211 /* r_phase is for triangle rotation speed */
212 GLfloat x_period, y_period, r_period;
213 GLfloat x_phase, y_phase, r_phase;
216 #define MAX_FADE 500 /* number of fade cycles */
219 float cam_x_speed, cam_z_speed, cam_y_speed;
220 int cam_x_phase, cam_z_phase, cam_y_phase;
222 GLXContext *glx_context;
224 texture textures[2]; /* texture handles */
225 GLuint visible; /* index for current texture */
233 float tangle; /* texture angle (degrees) */
234 float tangle_vel; /* texture velocity */
235 float tangle_acc; /* texture acceleration */
237 float rangle; /* rotate angle */
238 float rangle_vel; /* rotate velocity */
239 float rangle_acc; /* rotate acceleration */
248 Bool waiting_for_image_p;
252 #define frandrange(x, y) (x + frand(y - x))
254 #define XOFFSET (0.8660254f) /* sin 60' */
255 #define YOFFSET (1.5000000f) /* cos 60' + 1 */
261 /* generates a grid with edges of given size */
262 /* acd TODO - replace hex[] with this and allow size and distance as parameters */
265 generate_grid(int size)
272 for (y = -size ; y <= size ; y++) {
273 for (x = -i ; x <= i ; x += 2) {
274 printf("{XOFFSET * %d, YOFFSET * %d, 0},\n", x, y);
287 /* acd - this is terrible - 120+ hexes */
288 static const hex_t hex[] = {
289 /* edges of size 7 */
290 /* number of hexagons required to cover screen depends on camera distance */
291 /* at a distance of 10 this is just about enough. */
292 {XOFFSET * -6, YOFFSET * -6, 0},
293 {XOFFSET * -4, YOFFSET * -6, 0},
294 {XOFFSET * -2, YOFFSET * -6, 0},
295 {XOFFSET * 0, YOFFSET * -6, 0},
296 {XOFFSET * 2, YOFFSET * -6, 0},
297 {XOFFSET * 4, YOFFSET * -6, 0},
298 {XOFFSET * 6, YOFFSET * -6, 0},
300 {XOFFSET * -7, YOFFSET * -5, 0},
301 {XOFFSET * -5, YOFFSET * -5, 0},
302 {XOFFSET * -3, YOFFSET * -5, 0},
303 {XOFFSET * -1, YOFFSET * -5, 0},
304 {XOFFSET * 1, YOFFSET * -5, 0},
305 {XOFFSET * 3, YOFFSET * -5, 0},
306 {XOFFSET * 5, YOFFSET * -5, 0},
307 {XOFFSET * 7, YOFFSET * -5, 0},
309 {XOFFSET * -8, YOFFSET * -4, 0},
310 {XOFFSET * -6, YOFFSET * -4, 0},
311 {XOFFSET * -4, YOFFSET * -4, 0},
312 {XOFFSET * -2, YOFFSET * -4, 0},
313 {XOFFSET * 0, YOFFSET * -4, 0},
314 {XOFFSET * 2, YOFFSET * -4, 0},
315 {XOFFSET * 4, YOFFSET * -4, 0},
316 {XOFFSET * 6, YOFFSET * -4, 0},
317 {XOFFSET * 8, YOFFSET * -4, 0},
319 {XOFFSET * -9, YOFFSET * -3, 0},
320 {XOFFSET * -7, YOFFSET * -3, 0},
321 {XOFFSET * -5, YOFFSET * -3, 0},
322 {XOFFSET * -3, YOFFSET * -3, 0},
323 {XOFFSET * -1, YOFFSET * -3, 0},
324 {XOFFSET * 1, YOFFSET * -3, 0},
325 {XOFFSET * 3, YOFFSET * -3, 0},
326 {XOFFSET * 5, YOFFSET * -3, 0},
327 {XOFFSET * 7, YOFFSET * -3, 0},
328 {XOFFSET * 9, YOFFSET * -3, 0},
330 {XOFFSET * -10, YOFFSET * -2, 0},
331 {XOFFSET * -8, YOFFSET * -2, 0},
332 {XOFFSET * -6, YOFFSET * -2, 0},
333 {XOFFSET * -4, YOFFSET * -2, 0},
334 {XOFFSET * -2, YOFFSET * -2, 0},
335 {XOFFSET * 0, YOFFSET * -2, 0},
336 {XOFFSET * 2, YOFFSET * -2, 0},
337 {XOFFSET * 4, YOFFSET * -2, 0},
338 {XOFFSET * 6, YOFFSET * -2, 0},
339 {XOFFSET * 8, YOFFSET * -2, 0},
340 {XOFFSET * 10, YOFFSET * -2, 0},
342 {XOFFSET * -11, YOFFSET * -1, 0},
343 {XOFFSET * -9, YOFFSET * -1, 0},
344 {XOFFSET * -7, YOFFSET * -1, 0},
345 {XOFFSET * -5, YOFFSET * -1, 0},
346 {XOFFSET * -3, YOFFSET * -1, 0},
347 {XOFFSET * -1, YOFFSET * -1, 0},
348 {XOFFSET * 1, YOFFSET * -1, 0},
349 {XOFFSET * 3, YOFFSET * -1, 0},
350 {XOFFSET * 5, YOFFSET * -1, 0},
351 {XOFFSET * 7, YOFFSET * -1, 0},
352 {XOFFSET * 9, YOFFSET * -1, 0},
353 {XOFFSET * 11, YOFFSET * -1, 0},
355 {XOFFSET * -12, YOFFSET * 0, 0},
356 {XOFFSET * -10, YOFFSET * 0, 0},
357 {XOFFSET * -8, YOFFSET * 0, 0},
358 {XOFFSET * -6, YOFFSET * 0, 0},
359 {XOFFSET * -4, YOFFSET * 0, 0},
360 {XOFFSET * -2, YOFFSET * 0, 0},
361 {XOFFSET * 0, YOFFSET * 0, 0},
362 {XOFFSET * 2, YOFFSET * 0, 0},
363 {XOFFSET * 4, YOFFSET * 0, 0},
364 {XOFFSET * 6, YOFFSET * 0, 0},
365 {XOFFSET * 8, YOFFSET * 0, 0},
366 {XOFFSET * 10, YOFFSET * 0, 0},
367 {XOFFSET * 12, YOFFSET * 0, 0},
369 {XOFFSET * -11, YOFFSET * 1, 0},
370 {XOFFSET * -9, YOFFSET * 1, 0},
371 {XOFFSET * -7, YOFFSET * 1, 0},
372 {XOFFSET * -5, YOFFSET * 1, 0},
373 {XOFFSET * -3, YOFFSET * 1, 0},
374 {XOFFSET * -1, YOFFSET * 1, 0},
375 {XOFFSET * 1, YOFFSET * 1, 0},
376 {XOFFSET * 3, YOFFSET * 1, 0},
377 {XOFFSET * 5, YOFFSET * 1, 0},
378 {XOFFSET * 7, YOFFSET * 1, 0},
379 {XOFFSET * 9, YOFFSET * 1, 0},
380 {XOFFSET * 11, YOFFSET * 1, 0},
382 {XOFFSET * -10, YOFFSET * 2, 0},
383 {XOFFSET * -8, YOFFSET * 2, 0},
384 {XOFFSET * -6, YOFFSET * 2, 0},
385 {XOFFSET * -4, YOFFSET * 2, 0},
386 {XOFFSET * -2, YOFFSET * 2, 0},
387 {XOFFSET * 0, YOFFSET * 2, 0},
388 {XOFFSET * 2, YOFFSET * 2, 0},
389 {XOFFSET * 4, YOFFSET * 2, 0},
390 {XOFFSET * 6, YOFFSET * 2, 0},
391 {XOFFSET * 8, YOFFSET * 2, 0},
392 {XOFFSET * 10, YOFFSET * 2, 0},
394 {XOFFSET * -9, YOFFSET * 3, 0},
395 {XOFFSET * -7, YOFFSET * 3, 0},
396 {XOFFSET * -5, YOFFSET * 3, 0},
397 {XOFFSET * -3, YOFFSET * 3, 0},
398 {XOFFSET * -1, YOFFSET * 3, 0},
399 {XOFFSET * 1, YOFFSET * 3, 0},
400 {XOFFSET * 3, YOFFSET * 3, 0},
401 {XOFFSET * 5, YOFFSET * 3, 0},
402 {XOFFSET * 7, YOFFSET * 3, 0},
403 {XOFFSET * 9, YOFFSET * 3, 0},
405 {XOFFSET * -8, YOFFSET * 4, 0},
406 {XOFFSET * -6, YOFFSET * 4, 0},
407 {XOFFSET * -4, YOFFSET * 4, 0},
408 {XOFFSET * -2, YOFFSET * 4, 0},
409 {XOFFSET * 0, YOFFSET * 4, 0},
410 {XOFFSET * 2, YOFFSET * 4, 0},
411 {XOFFSET * 4, YOFFSET * 4, 0},
412 {XOFFSET * 6, YOFFSET * 4, 0},
413 {XOFFSET * 8, YOFFSET * 4, 0},
415 {XOFFSET * -7, YOFFSET * 5, 0},
416 {XOFFSET * -5, YOFFSET * 5, 0},
417 {XOFFSET * -3, YOFFSET * 5, 0},
418 {XOFFSET * -1, YOFFSET * 5, 0},
419 {XOFFSET * 1, YOFFSET * 5, 0},
420 {XOFFSET * 3, YOFFSET * 5, 0},
421 {XOFFSET * 5, YOFFSET * 5, 0},
422 {XOFFSET * 7, YOFFSET * 5, 0},
424 {XOFFSET * -6, YOFFSET * 6, 0},
425 {XOFFSET * -4, YOFFSET * 6, 0},
426 {XOFFSET * -2, YOFFSET * 6, 0},
427 {XOFFSET * 0, YOFFSET * 6, 0},
428 {XOFFSET * 2, YOFFSET * 6, 0},
429 {XOFFSET * 4, YOFFSET * 6, 0},
430 {XOFFSET * 6, YOFFSET * 6, 0},
434 **----------------------------------------------------------------------------
436 **----------------------------------------------------------------------------
439 static gleidestruct *gleidescope = NULL;
443 *load defaults in config structure
445 static void setdefaultconfig(void)
458 gleidescope_handle_event(ModeInfo *mi, XEvent *event)
460 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
463 printf("event:%d\n", event->xany.type);
464 printf("button:%d\n", event->xbutton.button);
466 switch(event->xany.type)
470 if (event->xbutton.button == Button1 ||
471 event->xbutton.button == Button3)
473 /* store initial values of mouse */
474 gp->xstart = event->xbutton.x;
475 gp->ystart = event->xbutton.y;
478 gp->button_down_p = True;
482 else if (event->xbutton.button == Button4)
487 else if (event->xbutton.button == Button5)
497 if (event->xbutton.button == Button1 ||
498 event->xbutton.button == Button3)
501 gp->button_down_p = False;
508 if (gp->button_down_p)
510 /* update mouse position */
511 gp->xmouse += (double)(event->xmotion.x - gp->xstart) / MI_WIDTH(mi);
512 gp->ymouse += (double)(event->xmotion.y - gp->ystart) / MI_HEIGHT(mi);
513 gp->xstart = event->xmotion.x;
514 gp->ystart = event->xmotion.y;
526 image_loaded_cb (const char *filename, XRectangle *geometry,
527 int image_width, int image_height,
528 int texture_width, int texture_height,
531 texture *tp = (texture *) closure;
534 gp->max_tx = (GLfloat) image_width / texture_width;
535 gp->max_ty = (GLfloat) image_height / texture_height;
538 /* new - taken from flipscreen */
539 tp->width = texture_width;
540 tp->height = texture_height;
541 tp->min_tx = (GLfloat) geometry->x / tp->width;
542 tp->min_ty = (GLfloat) geometry->y / tp->height;
543 tp->max_tx = (GLfloat) (geometry->x + geometry->width) / tp->width;
544 tp->max_ty = (GLfloat) (geometry->y + geometry->height) / tp->height;
547 printf("Image w,h: (%d, %d)\n", image_width, image_height);
548 printf("Texture w,h: (%d, %d)\n", texture_width, texture_height);
549 printf("Geom x,y: (%d, %d)\n", geometry->x, geometry->y);
550 printf("Geom w,h: (%d, %d)\n", geometry->width, geometry->height);
551 printf("Max Tx,Ty: (%f, %f)\n", tp->max_tx, tp->max_ty);
554 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
555 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
556 (tp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
558 tp->waiting_for_image_p = False;
559 tp->start_time = time ((time_t *) 0);
563 getSnapshot(ModeInfo *mi, texture *texture)
565 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
568 printf("getSnapshot");
571 if (MI_IS_WIREFRAME(mi))
575 load_texture_async (mi->xgwa.screen, mi->window,
576 *gp->glx_context, 0, 0, gp->mipmap_p,
577 texture->id, image_loaded_cb, texture);
578 texture->start_time = time((time_t *)0);
581 #define TEXTURE_SIZE 256
584 plot(unsigned char *buffer, int x, int y, int r, int g, int b, int a) {
586 if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) {
589 c = ((x * TEXTURE_SIZE) + y) * 4;
590 /*printf("(%d,%d)[%d]\n", x, y, c);*/
599 plot2(unsigned char *buffer, int x, int y, int r, int g, int b, int a) {
601 if (x < 0 || x >= TEXTURE_SIZE || y < 0 || y >= TEXTURE_SIZE) {
604 c = ((x * TEXTURE_SIZE) + y) * 4;
605 /*printf("(%d,%d)[%d]\n", x, y, c);*/
611 if (y + 1 < TEXTURE_SIZE) {
618 if (x + 1 < TEXTURE_SIZE) {
619 c += (TEXTURE_SIZE * 4);
624 if (y + 1 < TEXTURE_SIZE) {
634 /* draw geometric shapes to texture */
635 /* modifies passed in buffer */
637 draw_shapes (unsigned char *buffer) {
644 for (i = 0 ; i < TEXTURE_SIZE * TEXTURE_SIZE * 4 ; i += 4) {
645 buffer[i + 0] = 0x00;
646 buffer[i + 1] = 0x00;
647 buffer[i + 2] = 0x00;
648 buffer[i + 3] = 0xff;
651 for (s = 0 ; s < 25 ; s++) {
652 int shape = random() % 3;
655 int r = (random() & 0xff);
656 int g = (random() & 0xff);
657 int b = (random() & 0xff);
662 x = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4); /* top left */
663 y = (random() % TEXTURE_SIZE) - (TEXTURE_SIZE / 4);
664 w = 10 + random() % (TEXTURE_SIZE / 4); /* size */
665 h = 10 + random() % (TEXTURE_SIZE / 4);
667 printf("Rectangle: (%d, %d)(%d, %d)\n", x, y, w, h);
675 for (i = x ; i < x + w && i < TEXTURE_SIZE; i++) {
676 for (j = y ; j < y + h && j < TEXTURE_SIZE; j++) {
677 plot(buffer, i, j, r, g, b, a);
684 x = random() % TEXTURE_SIZE; /* centre */
685 y = random() % TEXTURE_SIZE;
686 h = 10 + random() % (TEXTURE_SIZE / 8); /* radius */
688 printf("Circle: %d, %d, %d\n", x, y, h);
690 for (i = 0 ; i < h ; i++) {
692 for (j = 0 ; j < h ; j++) {
695 printf("xdist: %d\n", xdist);
696 printf("ydist: %d\n", ydist);
697 printf("radius: %d\n", h * h);
699 if ((xdist + ydist) < (h * h)) {
700 plot(buffer, x + i, y + j, r, b, g, a);
701 /* check we haven't already done these */
703 plot(buffer, x + i, y - j, r, b, g, a);
706 plot(buffer, x - i, y + j, r, b, g, a);
708 plot(buffer, x - i, y - j, r, b, g, a);
718 x = random() % TEXTURE_SIZE; /* top */
719 y = random() % TEXTURE_SIZE;
720 h = 10 + random() % (TEXTURE_SIZE / 4); /* height */
722 printf("Triangle: %d, %d, %d\n", x, y, h);
726 for (i = 0 ; i < h ; i++) {
727 for (j = left ; j < right ; j++) {
728 plot(buffer, j, y + i, r, g, b, a);
739 setup_random_texture (ModeInfo *mi, texture *texture)
741 int width = 0, height = 0;
743 unsigned char *my_data = NULL;
747 int r0, g0, b0, a0, r1, g1, b1, a1;
751 printf("RandomTexture\n");
754 /* use this texture */
755 glBindTexture(GL_TEXTURE_2D, texture->id);
760 * code for various generated patterns - noise, stripes, checks etc.
761 * random geometric shapes looked the best.
765 style = random() & 0x3;
766 r0 = random() & 0xff;
767 g0 = random() & 0xff;
768 b0 = random() & 0xff;
770 r1 = random() & 0xff;
771 g1 = random() & 0xff;
772 b1 = random() & 0xff;
778 height = width = TEXTURE_SIZE;
779 my_data = (void *)malloc(width * height * 4);
780 for (i = 0 ; i < width ; i += 2) {
781 for (j = 0 ; j < height ; j += 2) {
782 r0 = random() & 0xff;
783 g0 = random() & 0xff;
784 b0 = random() & 0xff;
786 plot2(my_data, i, j, r0, g0, b0, a0);
796 height = width = TEXTURE_SIZE;
797 my_data = (void *)malloc(width * height * 4);
798 draw_shapes(my_data);
804 height = width = TEXTURE_SIZE;
805 my_data = (void *)malloc(width * height * 4);
806 for (i = 0 ; i < height ; i += 2) {
807 for (j = 0 ; j < width ; j += 2) {
808 if (((i + j) & 0x3) == 0) {
809 plot2(my_data, i, j, r0, g0, b0, a0);
811 plot2(my_data, i, j, r1, g1, b1, a1);
817 case 3: /* random stripes */
818 printf("Stripes 2\n");
819 height = width = TEXTURE_SIZE;
820 my_data = (void *)malloc(width * height * 4);
821 for (i = 0 ; i < height ; i += 2) {
822 r0 = random() & 0xff;
823 g0 = random() & 0xff;
824 b0 = random() & 0xff;
826 for (j = 0 ; j < width ; j += 2) {
827 plot2(my_data, i, j, r0, g0, b0, a0);
834 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
836 GL_RGBA, GL_UNSIGNED_BYTE, my_data);
837 sprintf (buf, "random texture: (%dx%d)",
841 /* setup parameters for texturing */
842 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
843 glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
845 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
846 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
847 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
848 if (random() & 0x1) {
849 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
850 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
852 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
853 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
856 if (my_data != NULL) {
861 /* use full texture */
863 texture->min_tx = 0.0;
864 texture->max_tx = 2.0;
865 texture->min_ty = 0.0;
866 texture->max_ty = 2.0;
867 texture->start_time = time((time_t *)0);
871 setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
873 Display *dpy = mi->dpy;
874 Visual *visual = mi->xgwa.visual;
877 Colormap cmap = mi->xgwa.colormap;
878 XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
881 printf("FileTexture\n");
884 /* use this texture */
885 glBindTexture(GL_TEXTURE_2D, texture->id);
888 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
889 image->width, image->height, 0,
890 GL_RGBA, GL_UNSIGNED_BYTE, image->data);
891 sprintf (buf, "texture: %.100s (%dx%d)",
892 filename, image->width, image->height);
895 /* setup parameters for texturing */
896 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
897 glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
899 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
900 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
901 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
902 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
903 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
905 /* use full texture */
906 texture->min_tx = 0.0;
907 texture->max_tx = 1.0;
908 texture->min_ty = 0.0;
909 texture->max_ty = 1.0;
910 texture->start_time = time((time_t *)0);
914 setup_texture(ModeInfo * mi, texture *texture)
916 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
918 if (!image || !*image || !strcmp(image, "DEFAULT")) {
919 /* no image specified - use system settings */
921 printf("SetupTexture: get_snapshot\n");
923 getSnapshot(mi, texture);
925 if (strcmp(image, "GENERATE") == 0) {
927 printf("SetupTexture: random_texture\n");
929 setup_random_texture(mi, texture);
931 /* use supplied image file */
933 printf("SetupTexture: file_texture\n");
935 setup_file_texture(mi, image, texture);
938 /* copy start time from texture */
939 gp->start_time = texture->start_time;
941 check_gl_error("texture initialization");
944 * resultant loaded image is upside down BUT
945 * it's a kaledescope and half of the hexagon is backwards anyway...
948 /* TODO: values for lissajous movement */
949 texture->x_period = frandrange(-2.0, 2.0);
950 texture->y_period = frandrange(-2.0, 2.0);
951 texture->r_period = frandrange(-2.0, 2.0);
952 texture->x_phase = frand(M_PI * 2);
953 texture->y_phase = frand(M_PI * 2);
954 texture->r_phase = frand(M_PI * 2);
956 printf("XPeriod %f XPhase %f\n", texture->x_period, texture->x_phase);
957 printf("YPeriod %f YPhase %f\n", texture->y_period, texture->y_phase);
958 printf("RPeriod %f RPhase %f\n", texture->r_period, texture->r_phase);
962 #define VERTEX0 glVertex3f( 0.0000f, 0.000f, 0.0f);
963 #define VERTEX1 glVertex3f( 0.0000f, 1.000f, 0.0f);
964 #define VERTEX2 glVertex3f( XOFFSET, 0.500f, 0.0f);
965 #define VERTEX3 glVertex3f( XOFFSET, -0.500f, 0.0f);
966 #define VERTEX4 glVertex3f( 0.0000f, -1.000f, 0.0f);
967 #define VERTEX5 glVertex3f(-XOFFSET, -0.500f, 0.0f);
968 #define VERTEX6 glVertex3f(-XOFFSET, 0.500f, 0.0f);
971 ** Three different functions for calculating texture coordinates
972 ** which modify how the texture triangle moves over the source image.
977 /* the classic equilateral triangle rotating around centre */
979 calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
981 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
982 GLfloat centre_x = 0.5;
983 GLfloat centre_y = 0.5;
984 GLfloat radius_x = (texture->max_tx - texture->min_tx) / 2;
985 GLfloat radius_y = (texture->max_ty - texture->min_ty) / 2;
991 t[1].x = centre_x + .95 * radius_x * cos((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS));
992 t[1].y = centre_y + .95 * radius_y * sin((gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS));
994 /* t[2] is always 60' further around than t2 */
995 tangle2 = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS) + (M_PI * 2 / 6);
996 t[2].x = centre_x + .95 * radius_x * cos(tangle2);
997 t[2].y = centre_y + .95 * radius_y * sin(tangle2);
999 printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty);
1005 /* new lissajous movement pattern */
1007 calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
1009 /* equilateral triangle rotating around centre */
1010 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1011 GLfloat width = texture->max_tx - texture->min_tx;
1012 GLfloat height = texture->max_ty - texture->min_ty;
1014 GLfloat centre_x = texture->min_tx + (width * .5);
1015 GLfloat centre_y = texture->min_ty + (height * .5);
1016 /* m radius and t radius should be = .5 */
1017 /* triangle radius is 30% available space */
1018 GLfloat t_radius_x = width * .3;
1019 GLfloat t_radius_y = height * .3;
1020 /* movement radius is 30% available space */
1021 GLfloat m_radius_x = width * .2;
1022 GLfloat m_radius_y = height * .2;
1025 /* centre of triangle */
1026 GLfloat angle = (gp->ymouse * 2 * M_PI) + (gp->tangle * RADIANS); /* to radians */
1027 GLfloat t_centre_x = centre_x + m_radius_x * cos(texture->x_period * angle + texture->x_phase);
1028 GLfloat t_centre_y = centre_y + m_radius_y * sin(texture->y_period * angle + texture->y_phase);
1031 printf("WH: %f, %f - tWH: %f, %f\n", width, height, texture->width, texture->height);
1032 printf("size: (%f, %f)\n", width, height);
1033 printf("centre: (%f, %f)\n", centre_x, centre_y);
1036 angle2 = texture->r_period * angle + texture->r_phase;
1037 t[0].x = t_centre_x + t_radius_x * cos(angle2);
1038 t[0].y = t_centre_y + t_radius_y * sin(angle2);
1039 t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120);
1040 t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120);
1041 t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240);
1042 t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240);
1045 printf("texcoords:[%f,%f]->[%f,%f](%f,%f)\n", t[0].x, t[0].y, t[1].x, t[1].y, texture->max_tx, texture->max_ty);
1051 /* corners into corners - meant to maximise coverage */
1053 calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
1055 /* equilateral triangle rotating around centre */
1056 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1057 GLfloat width = texture->max_tx - texture->min_tx;
1058 GLfloat height = texture->max_ty - texture->min_ty;
1060 GLfloat centre_x = texture->min_tx + (width * .5);
1061 GLfloat centre_y = texture->min_ty + (height * .5);
1062 /* m radius and t radius should be = .5 */
1063 /* triangle radius calculated using maths 8) */
1064 #define TRADIUS (M_SQRT2 - 1.0)
1065 #define MRADIUS (1.0 - (M_SQRT2 / 2.0))
1066 GLfloat t_radius_x = width * TRADIUS * .95;
1067 GLfloat t_radius_y = height * TRADIUS * .95;
1068 /* movement radius also calculated using maths */
1069 GLfloat m_radius_x = width * MRADIUS * .95;
1070 GLfloat m_radius_y = height * MRADIUS * .95;
1071 GLfloat angle, angle2;
1072 GLfloat t_centre_x, t_centre_y;
1074 /* centre of triangle */
1075 angle = gp->tangle * RADIANS; /* to radians */
1076 t_centre_x = centre_x + m_radius_x * cos(angle);
1077 t_centre_y = centre_y + m_radius_y * sin(angle);
1079 printf("angle: %f, %f\n", angle, gp->tangle);
1080 printf("tcentre: %f,%f\n", t_centre_x, t_centre_y);
1081 printf("tradius: %f,%f\n", t_radius_x, t_radius_y);
1083 printf("size: (%f, %f)\n", width, height);
1084 printf("centre: (%f, %f)\n", centre_x, centre_y);
1085 printf("centre: (%f, %f)\n", centre_x, centre_y);
1086 printf("TRADIUS: %f\n", TRADIUS);
1087 printf("MRADIUS: %f\n", MRADIUS);
1090 /* angle2 is tied to tangle */
1091 angle2 = (180.0 - ((30.0 / 90.0) * gp->tangle)) * RADIANS;
1093 printf("Angle1: %f\tAngle2: %f\n", angle / RADIANS, angle2 / RADIANS);
1095 t[0].x = t_centre_x + t_radius_x * cos(angle2);
1096 t[0].y = t_centre_y + t_radius_y * sin(angle2);
1097 t[1].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_120);
1098 t[1].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_120);
1099 t[2].x = t_centre_x + t_radius_x * cos(angle2 + ANGLE_240);
1100 t[2].y = t_centre_y + t_radius_y * sin(angle2 + ANGLE_240);
1103 printf("texcoords:[%f,%f][%f,%f][%f,%f]\n", t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y);
1109 draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
1114 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1119 col[3] = (float)translucency / MAX_FADE;
1121 calculate_texture_coords(mi, texture, t);
1123 glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
1124 glEnable(GL_TEXTURE_2D);
1126 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1127 glDepthMask(GL_FALSE);
1128 glBindTexture(GL_TEXTURE_2D, texture->id);
1130 if (gp->list == -1) {
1131 gp->list = glGenLists(1);
1134 /* compile new list */
1135 glNewList(gp->list, GL_COMPILE);
1136 glBegin(GL_TRIANGLES);
1139 ** six triangles to each hexagon
1142 glTexCoord2f(t[0].x, t[0].y);
1144 glTexCoord2f(t[1].x, t[1].y);
1146 glTexCoord2f(t[2].x, t[2].y);
1149 glTexCoord2f(t[0].x, t[0].y);
1151 glTexCoord2f(t[2].x, t[2].y);
1153 glTexCoord2f(t[1].x, t[1].y);
1156 glTexCoord2f(t[0].x, t[0].y);
1158 glTexCoord2f(t[1].x, t[1].y);
1160 glTexCoord2f(t[2].x, t[2].y);
1163 glTexCoord2f(t[0].x, t[0].y);
1165 glTexCoord2f(t[2].x, t[2].y);
1167 glTexCoord2f(t[1].x, t[1].y);
1170 glTexCoord2f(t[0].x, t[0].y);
1172 glTexCoord2f(t[1].x, t[1].y);
1174 glTexCoord2f(t[2].x, t[2].y);
1177 glTexCoord2f(t[0].x, t[0].y);
1179 glTexCoord2f(t[2].x, t[2].y);
1181 glTexCoord2f(t[1].x, t[1].y);
1187 /* call the list n times */
1188 for (i = 0 ; i < sizeof(hex) / sizeof(hex[0]) ; i++) {
1192 glTranslatef(hex[i].x, hex[i].y, 0.0);
1193 glCallList(gp->list);
1198 #ifdef DISPLAY_TEXTURE
1200 /* acd debug - display (bigger, centred) texture */
1201 glScalef(2.0, 2.0, 2.0);
1202 glTranslatef(-0.5, -0.5, 0.0);
1204 glTexCoord2f(0.0, 0.0);
1205 glVertex3f(0.0, 0.0, -0.1);
1206 glTexCoord2f(1.0, 0.0);
1207 glVertex3f(1.0, 0.0, -0.1);
1208 glTexCoord2f(1.0, 1.0);
1209 glVertex3f(1.0, 1.0, -0.1);
1210 glTexCoord2f(0.0, 1.0);
1211 glVertex3f(0.0, 1.0, -0.1);
1213 /* acd debug - display texture triangle */
1214 glColor4f(1.0, 0.5, 1.0, 1.0);
1215 glBegin(GL_LINE_LOOP);
1216 glVertex3f(t[0].x, t[0].y, -0.11);
1217 glVertex3f(t[1].x, t[1].y, -0.11);
1218 glVertex3f(t[2].x, t[2].y, -0.11);
1223 glDisable(GL_TEXTURE_2D);
1224 glDepthMask(GL_TRUE);
1225 glDisable(GL_BLEND);
1229 * main rendering loop
1234 GLfloat x_angle, y_angle, z_angle;
1235 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1239 glClearColor(0.5, 0.5, 0.5, 1.0);
1240 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1245 x_angle = gp->cam_x_phase + gp->tic * gp->cam_x_speed;
1246 y_angle = gp->cam_y_phase + gp->tic * gp->cam_y_speed;
1247 z_angle = gp->cam_z_phase + gp->tic * gp->cam_z_speed;
1250 v1.x = 1 * sin(x_angle);
1251 v1.y = 1 * sin(y_angle);
1257 /* size is changed in pinit() to be distance from plane */
1258 gp->size = MI_SIZE(mi);
1259 if (gp->size > 10) {
1262 if (gp->size < -1) {
1265 if (gp->size != -1) {
1266 /* user defined size */
1269 /* max distance given by adding the constant and the multiplier */
1270 v1.z = 5.0 + 3.0 * sin(z_angle);
1276 /* update rotation angle (but not if mouse button down) */
1277 if (rotate && !gp->button_down_p)
1279 float new_rangle_vel = 0.0;
1281 /* update camera rotation angle and velocity */
1282 gp->rangle += gp->rangle_vel;
1283 new_rangle_vel = gp->rangle_vel + gp->rangle_acc;
1284 if (new_rangle_vel > -MAX_ANGLE_VEL && new_rangle_vel < MAX_ANGLE_VEL)
1286 /* new velocity is within limits */
1287 gp->rangle_vel = new_rangle_vel;
1290 /* randomly change twisting speed - 3ff = 1024 */
1291 if ((random() % TWISTING_PROBABILITY) < 1.0) {
1292 gp->rangle_acc = INITIAL_ANGLE_ACC * frand(1.0);
1293 if (gp->rangle_vel > 0.0) {
1294 gp->rangle_acc = -gp->rangle_acc;
1299 printf("Rangle: %f : %f : %f\n", gp->rangle, gp->rangle_vel, gp->rangle_acc);
1300 printf("Tangle: %f : %f : %f\n", gp->tangle, gp->tangle_vel, gp->tangle_acc);
1304 /* this makes the image wobble - requires -move and a larger grid */
1305 gluLookAt(0, 0, v1.z, v1.x, v1.y, 0.0, 0.0, 1.0, 0.0);
1307 /* no wobble - camera always perpendicular to grid */
1309 /* rotating camera rather than entire space - smoother */
1313 sin((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS),
1314 cos((gp->xmouse * M_PI * 2) + gp->rangle * RADIANS),
1318 /* light position same as camera */
1327 draw_hexagons(mi, MAX_FADE, &gp->textures[gp->visible]);
1331 /* fading - show both textures with alpha
1332 NB first is always max alpha */
1333 draw_hexagons(mi, MAX_FADE, &gp->textures[1 - gp->visible]);
1334 draw_hexagons(mi, MAX_FADE - gp->fade, &gp->textures[gp->visible]);
1336 /* fade some more */
1339 /* have we faded enough? */
1340 if (gp->fade > MAX_FADE)
1344 gp->visible = 1 - gp->visible;
1348 /* increment texture angle based on time, velocity etc */
1349 /* but only if button is not down */
1350 if (!gp->button_down_p)
1352 float new_tangle_vel = 0.0;
1354 gp->tangle += gp->tangle_vel;
1356 /* work out new texture angle velocity */
1357 new_tangle_vel = gp->tangle_vel + gp->tangle_acc;
1358 if (new_tangle_vel > -MAX_ANGLE_VEL && new_tangle_vel < MAX_ANGLE_VEL)
1360 /* new velocity is inside limits */
1361 gp->tangle_vel = new_tangle_vel;
1364 /* randomly change twisting speed - 3ff = 1024 */
1365 if ((random() % TWISTING_PROBABILITY) < 1.0) {
1366 gp->tangle_acc = INITIAL_ANGLE_ACC * frand(1.0);
1367 if (gp->tangle_vel > 0.0) {
1368 gp->tangle_acc = -gp->tangle_acc;
1377 * new window size or exposure
1379 ENTRYPOINT void reshape_gleidescope(ModeInfo *mi, int width, int height)
1381 GLfloat h = (GLfloat) height / (GLfloat) width;
1383 glViewport(0, 0, (GLint) width, (GLint) height);
1384 glMatrixMode(GL_PROJECTION);
1386 gluPerspective(50.0, 1/h, 0.1, 2000.0);
1387 glMatrixMode (GL_MODELVIEW);
1394 pinit(ModeInfo * mi)
1396 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1398 /* set start time - star_time = 0 implies non-dynamic texture */
1399 gp->start_time = (time_t)0;
1401 /* set the texture size to default */
1410 glShadeModel(GL_SMOOTH);
1411 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1412 glEnable(GL_DEPTH_TEST);
1413 glEnable(GL_CULL_FACE);
1414 glDisable(GL_LIGHTING);
1416 /* space for textures */
1417 glGenTextures(1, &gp->textures[0].id);
1418 glGenTextures(1, &gp->textures[1].id);
1421 setup_texture(mi, &gp->textures[gp->visible]);
1424 ** want to choose a value for arg randomly if neither -arg nor -no-arg
1425 ** is specified. xscreensaver libraries don't seem to let you do this -
1426 ** if something isn't true then it is false (pesky two-state boolean values).
1427 ** so, i've defined both -arg and -no-arg to arguments and added the
1429 ** (btw if both -arg and -no-arg are defined then arg is set to False)
1431 if (zoom == False && nozoom == False)
1433 /* no zoom preference - randomise */
1434 zoom = (((random() & 0x1) == 0x1) ? True : False);
1436 else if (nozoom == True)
1438 /* definately no zoom */
1442 if (move == False && nomove == False)
1444 /* no move preference - randomise */
1445 move = (((random() & 0x1) == 0x1) ? True : False);
1447 else if (nomove == True)
1449 /* definately no move */
1453 if (rotate == False && norotate == False)
1455 /* no rotate preference - randomise */
1456 rotate = (((random() & 0x1) == 0x1) ? True : False);
1458 else if (norotate == True)
1460 /* definately no rotate */
1464 /* define cam variables */
1465 gp->cam_x_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
1466 gp->cam_x_phase = random() % 360;
1467 gp->cam_y_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
1468 gp->cam_y_phase = random() % 360;
1469 gp->cam_z_speed = MAX_CAM_SPEED * frandrange(-.5, 0.5);
1470 gp->cam_z_phase = random() % 360;
1472 /* initial angular speeds */
1473 gp->rangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5);
1474 gp->tangle_vel = INITIAL_ANGLE_VEL * frandrange(-.5, 0.5);
1475 gp->rangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5);
1476 gp->tangle_acc = INITIAL_ANGLE_ACC * frandrange(-.5, 0.5);
1482 gp->rangle_vel *= speed;
1483 gp->tangle_vel *= speed;
1484 gp->rangle_acc *= speed;
1485 gp->tangle_acc *= speed;
1489 /* distance is 11 - size */
1490 if (gp->size != -1) {
1492 fprintf(stderr, "-size given. ignoring -zoom.\n");
1497 } else if (gp->size >= 10) {
1500 gp->size = 11 - gp->size;
1504 printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phase);
1509 init_gleidescope(ModeInfo * mi)
1512 int screen = MI_SCREEN(mi);
1514 if (gleidescope == NULL) {
1515 gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
1516 if (gleidescope == NULL) {
1520 gp = &gleidescope[screen];
1521 gp->window = MI_WINDOW(mi);
1525 if ((gp->glx_context = init_GL(mi)) != NULL) {
1527 reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1529 glDrawBuffer(GL_BACK);
1531 /* do initialisation */
1540 draw_gleidescope(ModeInfo * mi)
1542 gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
1543 Display *display = MI_DISPLAY(mi);
1544 Window window = MI_WINDOW(mi);
1547 if (!gp->glx_context)
1550 /* Just keep running before the texture has come in. */
1551 /* if (gp->waiting_for_image_p) return; */
1553 glDrawBuffer(GL_BACK);
1555 glXMakeCurrent(display, window, *(gp->glx_context));
1563 glXSwapBuffers(display, window);
1567 grab_frame(display, window);
1571 /* need to change texture? */
1572 if ((gp->start_time != 0) && (duration != -1) && gp->fade == 0) {
1573 if (gp->start_time + duration <= time((time_t *)0)) {
1575 printf("Start Time: %lu - Current Time: %lu\n", (unsigned long)gp->start_time, (unsigned long)time((time_t *)0));
1576 printf("Changing Texture\n");
1578 /* get new snapshot (into back buffer) and start fade count */
1579 setup_texture(mi, &gp->textures[1 - gp->visible]);
1580 /* restart fading */
1587 release_gleidescope(ModeInfo * mi)
1589 if (gleidescope != NULL) {
1592 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
1593 gleidestruct *gp = &gleidescope[screen];
1595 /* acd - is this needed? */
1596 if (gp->glx_context) {
1597 /* Display lists MUST be freed while their glXContext is current. */
1598 glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
1600 /* acd - was code here for freeing things that are no longer in struct */
1603 (void) free((void *) gleidescope);
1610 XSCREENSAVER_MODULE ("Gleidescope", gleidescope)