From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / gleidescope.c
index 766e2396d914dac381a147ff38f5285ad4deffa9..dd6533a6779d227c3d38e1e5ebbb4bb696c27e57 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 4 -*- */
 /* vim: set ai ts=4 sw=4: */
 
-#if !defined( lint ) && !defined( SABER )
+#if 0
 /*static const char sccsid[] = "@(#)gleidescope.c      1.0 03/06/27 xlockmore";*/
 #endif
 
 # define DEFAULTS \
                "*delay:                20000           \n"     \
                "*showFPS:              False           \n"     \
-               "*size:                 -1                      \n"     \
-               "*useSHM:               True            \n"
+               "*size:                 0                       \n"     \
+               "*useSHM:               True            \n" \
+               "*suppressRotationAnimation: True\n" \
 
 # define refresh_gleidescope 0
+# define release_gleidescope 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"                                    /* from the xlockmore distribution */
@@ -104,7 +106,7 @@ static Bool         rotate;                 /* rotate in place */
 static Bool            norotate;               /* no rotate in place */
 static Bool            zoom;                   /* zooming camera */
 static Bool            nozoom;                 /* no zooming camera */
-static char            *image;                 /* name of texture to load */
+static char            *image_str;             /* name of texture to load */
 static int             duration;               /* length of time to display grabbed image */
 
 #define MAX_CAM_SPEED                  1.0
@@ -117,6 +119,17 @@ static int         duration;               /* length of time to display grabbed image */
 #define ANGLE_120      (M_PI * 2 / 3)
 #define ANGLE_240      (M_PI * 4 / 3)
 
+#define DEF_GRAB       "False"
+#define DEF_MOVE       "False"
+#define DEF_NOMOVE     "False"
+#define DEF_ROTATE     "False"
+#define DEF_NOROTATE   "False"
+#define DEF_ZOOM       "False"
+#define DEF_NOZOOM     "False"
+#define DEF_IMAGE      "DEFAULT"
+#define DEF_DURATION   "30"
+
+
 static XrmOptionDescRec opts[] =
 {
 #ifdef GRAB
@@ -126,7 +139,6 @@ static XrmOptionDescRec opts[] =
        {"-no-move",    ".gleidescope.nomove",          XrmoptionNoArg,         "true"},
        {"-rotate",             ".gleidescope.rotate",          XrmoptionNoArg,         "true"},
        {"-no-rotate",  ".gleidescope.norotate",        XrmoptionNoArg,         "true"},
-       /*{"-size",             ".gleidescope.size",            XrmoptionNoArg,         "-1"},*/
        {"-zoom",               ".gleidescope.zoom",            XrmoptionNoArg,         "true"},
        {"-no-zoom",    ".gleidescope.nozoom",          XrmoptionNoArg,         "true"},
        {"-image",              ".gleidescope.image",           XrmoptionSepArg,        "DEFAULT"},
@@ -136,17 +148,16 @@ static XrmOptionDescRec opts[] =
 
 static argtype vars[] = {
 #ifdef GRAB
-       {&grab,                 "grab",         "Grab",         "False",        t_Bool},
+       {&grab,                 "grab",         "Grab",         DEF_GRAB,       t_Bool},
 #endif
-       {&move,                 "move",         "Move",         "False",        t_Bool},
-       {&nomove,               "nomove",       "noMove",       "False",        t_Bool},
-       {&rotate,               "rotate",       "Rotate",       "False",        t_Bool},
-       {&norotate,             "norotate",     "noRotate",     "False",        t_Bool},
-       /*{&size,               "size",         "Size",         "-1",           t_Int},*/
-       {&zoom,                 "zoom",         "Zoom",         "False",        t_Bool},
-       {&nozoom,               "nozoom",       "noZoom",       "False",        t_Bool},
-       {&image,                "image",        "Image",        "DEFAULT",      t_String},
-       {&duration,             "duration",     "Duration",     "30",           t_Int},
+       {&move,                 "move",         "Move",         DEF_MOVE,       t_Bool},
+       {&nomove,               "nomove",       "noMove",       DEF_NOMOVE,     t_Bool},
+       {&rotate,               "rotate",       "Rotate",       DEF_ROTATE,     t_Bool},
+       {&norotate,             "norotate",     "noRotate",     DEF_NOROTATE,   t_Bool},
+       {&zoom,                 "zoom",         "Zoom",         DEF_ZOOM,       t_Bool},
+       {&nozoom,               "nozoom",       "noZoom",       DEF_NOZOOM,     t_Bool},
+       {&image_str,            "image",        "Image",        DEF_IMAGE,      t_String},
+       {&duration,             "duration",     "Duration",     DEF_DURATION,           t_Int},
 };
 
 static OptionStruct desc[] = {
@@ -157,7 +168,6 @@ static OptionStruct desc[] = {
        {"-no-move",    "camera won't move"},
        {"-rotate",             "camera will rotate"},
        {"-no-rotate",  "camera won't rotate"},
-       /*{"-size",             "size of the hexagons (1-10)"},*/
        {"-zoom",               "camera will zoom"},
        {"-no-zoom",    "camera won't zoom"},
        {"-image",              "xpm / xbm image file to use for texture"},
@@ -172,7 +182,7 @@ ENTRYPOINT ModeSpecOpt gleidescope_opts = {
 
 #ifdef USE_MODULES
 ModStruct   gleidescope_description = { 
-     "gleidescope", "init_gleidescope", "draw_gleidescope", "release_gleidescope",
+     "gleidescope", "init_gleidescope", "draw_gleidescope", NULL,
      "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts,
      1000, 1, 2, 1, 4, 1.0, "",
      "GL Kaleidescope", 0, NULL};
@@ -463,10 +473,8 @@ gleidescope_handle_event(ModeInfo *mi, XEvent *event)
        printf("event:%d\n", event->xany.type);
        printf("button:%d\n", event->xbutton.button);
        */
-       switch(event->xany.type)
-       {
-               case ButtonPress:
-
+       if (event->xany.type == ButtonPress)
+      {
                        if (event->xbutton.button == Button1 ||
                 event->xbutton.button == Button3)
                        {
@@ -490,10 +498,8 @@ gleidescope_handle_event(ModeInfo *mi, XEvent *event)
                                return True;
                        }
 #endif
-                       break;
-
-               case ButtonRelease:
-
+            } else if (event->xany.type == ButtonRelease)
+      {
                        if (event->xbutton.button == Button1 ||
                 event->xbutton.button == Button3)
                        {
@@ -501,10 +507,8 @@ gleidescope_handle_event(ModeInfo *mi, XEvent *event)
                                gp->button_down_p = False;
                                return True;
                        }
-                       break;
-
-               case MotionNotify:
-
+            } else if (event->xany.type == MotionNotify)
+      {
                        if (gp->button_down_p)
                        {
                                /* update mouse position */
@@ -515,8 +519,13 @@ gleidescope_handle_event(ModeInfo *mi, XEvent *event)
 
                                return True;
                        }
-                       break;
-       }
+      }
+  else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+    {
+      gp->start_time = -1;
+      gp->fade = 0;
+      return True;
+    }
 
        return False;
 }
@@ -867,7 +876,7 @@ setup_random_texture (ModeInfo *mi, texture *texture)
        texture->start_time = time((time_t *)0);
 }
 
-static void
+static Bool
 setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
 {
        Display *dpy = mi->dpy;
@@ -876,6 +885,7 @@ setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
 
        Colormap cmap = mi->xgwa.colormap;
        XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+    if (!image) return False;
 
 #ifdef DEBUG
        printf("FileTexture\n");
@@ -908,6 +918,7 @@ setup_file_texture (ModeInfo *mi, char *filename, texture *texture)
        texture->min_ty = 0.0;
        texture->max_ty = 1.0;
        texture->start_time = time((time_t *)0);
+    return True;
 }
 
 static void
@@ -915,14 +926,15 @@ setup_texture(ModeInfo * mi, texture *texture)
 {
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
-       if (!image || !*image || !strcmp(image, "DEFAULT")) {
+       if (!image_str || !*image_str || !strcmp(image_str, "DEFAULT")) {
+    BUILTIN:
                /* no image specified - use system settings */
 #ifdef DEBUG
                printf("SetupTexture: get_snapshot\n");
 #endif
                getSnapshot(mi, texture);
        } else {
-               if (strcmp(image, "GENERATE") == 0) {
+               if (strcmp(image_str, "GENERATE") == 0) {
 #ifdef DEBUG
                        printf("SetupTexture: random_texture\n");
 #endif
@@ -932,7 +944,8 @@ setup_texture(ModeInfo * mi, texture *texture)
 #ifdef DEBUG
                        printf("SetupTexture: file_texture\n");
 #endif
-                       setup_file_texture(mi, image, texture);
+                       if (! setup_file_texture(mi, image_str, texture))
+              goto BUILTIN;
                }
        }
        /* copy start time from texture */
@@ -1105,19 +1118,14 @@ calculate_texture_coords(ModeInfo *mi, texture *texture, vector2f t[3]) {
 }
 #endif
 
-static void
+static int
 draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
 {
+    int polys = 0;
        int             i;
-       GLfloat col[4];
        vector2f t[3];
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
-       col[0] = 1.0;
-       col[1] = 1.0;
-       col[2] = 1.0;
-       col[3] = (float)translucency / MAX_FADE;
-
        calculate_texture_coords(mi, texture, t);
 
        glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
@@ -1191,6 +1199,7 @@ draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
 
                glTranslatef(hex[i].x, hex[i].y, 0.0);
                glCallList(gp->list);
+        polys += 6;
 
                glPopMatrix();
        }
@@ -1209,6 +1218,7 @@ draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
        glVertex3f(1.0, 1.0, -0.1);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(0.0, 1.0, -0.1);
+    polys++;
        glEnd();
        /* acd debug - display texture triangle */
        glColor4f(1.0, 0.5, 1.0, 1.0);
@@ -1216,6 +1226,7 @@ draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
        glVertex3f(t[0].x, t[0].y, -0.11);
        glVertex3f(t[1].x, t[1].y, -0.11);
        glVertex3f(t[2].x, t[2].y, -0.11);
+    polys++;
        glEnd();
        glPopMatrix();
 #endif
@@ -1223,6 +1234,7 @@ draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
        glDisable(GL_TEXTURE_2D);
        glDepthMask(GL_TRUE);
        glDisable(GL_BLEND);
+    return polys;
 }
 
 /*
@@ -1234,9 +1246,9 @@ draw(ModeInfo * mi)
        GLfloat x_angle, y_angle, z_angle;
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
        vectorf v1;
-       GLfloat pos[4];
 
-       glClearColor(0.5, 0.5, 0.5, 1.0);
+    mi->polygon_count = 0;
+
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
 
@@ -1259,10 +1271,10 @@ draw(ModeInfo * mi)
        if (gp->size > 10) {
                gp->size = 10;
        }
-       if (gp->size < -1) {
-               gp->size = -1;
+       if (gp->size <= 0) {
+               gp->size = 0;
        }
-       if (gp->size != -1) {
+       if (gp->size > 0) {
                /* user defined size */
                v1.z = gp->size;
        } else if (zoom) {
@@ -1315,23 +1327,29 @@ draw(ModeInfo * mi)
                        0.0);
 #endif
 
-       /* light position same as camera */
-       pos[0] = v1.x;
-       pos[1] = v1.y;
-       pos[2] = v1.z;
-       pos[3] = 0;
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
 
        if (gp->fade == 0)
        {
                /* not fading */
-               draw_hexagons(mi, MAX_FADE, &gp->textures[gp->visible]);
+      mi->polygon_count += 
+        draw_hexagons(mi, MAX_FADE, &gp->textures[gp->visible]);
        }
        else
        {
                /* fading - show both textures with alpha
                NB first is always max alpha */
-               draw_hexagons(mi, MAX_FADE, &gp->textures[1 - gp->visible]);
-               draw_hexagons(mi, MAX_FADE - gp->fade, &gp->textures[gp->visible]);
+        mi->polygon_count += 
+          draw_hexagons(mi, MAX_FADE, &gp->textures[1 - gp->visible]);
+        mi->polygon_count += 
+                 draw_hexagons(mi, MAX_FADE - gp->fade, &gp->textures[gp->visible]);
 
                /* fade some more */
                gp->fade++;
@@ -1378,14 +1396,16 @@ draw(ModeInfo * mi)
  */
 ENTRYPOINT void reshape_gleidescope(ModeInfo *mi, int width, int height)
 {
+       gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
        GLfloat         h = (GLfloat) height / (GLfloat) width;
 
+       glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));
+
        glViewport(0, 0, (GLint) width, (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(50.0, 1/h, 0.1, 2000.0);
        glMatrixMode (GL_MODELVIEW);
-
        glLineWidth(1);
        glPointSize(1);   
 }
@@ -1505,18 +1525,15 @@ printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phas
 #endif
 }
 
+static void free_gleidescope(ModeInfo * mi);
+
 ENTRYPOINT void
 init_gleidescope(ModeInfo * mi)
 {
        gleidestruct *gp;
        int screen = MI_SCREEN(mi);
 
-       if (gleidescope == NULL) {
-               gleidescope = (gleidestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (gleidestruct));
-               if (gleidescope == NULL) {
-                       return;
-               }
-       }
+       MI_INIT(mi, gleidescope, free_gleidescope);
        gp = &gleidescope[screen];
        gp->window = MI_WINDOW(mi);
     gp->size = -1;
@@ -1525,6 +1542,7 @@ init_gleidescope(ModeInfo * mi)
        if ((gp->glx_context = init_GL(mi)) != NULL) {
 
                reshape_gleidescope(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+        clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
 
                glDrawBuffer(GL_BACK);
 
@@ -1583,28 +1601,18 @@ draw_gleidescope(ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-release_gleidescope(ModeInfo * mi)
+static void
+free_gleidescope(ModeInfo * mi)
 {
-       if (gleidescope != NULL) {
-               int screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       gleidestruct *gp = &gleidescope[screen];
+       gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
-                       /* acd -  is this needed? */
-                       if (gp->glx_context) {
-                               /* Display lists MUST be freed while their glXContext is current. */
-                               glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
+       /* acd -  is this needed? */
+       if (gp->glx_context) {
+               /* Display lists MUST be freed while their glXContext is current. */
+               glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
 
-                               /* acd - was code here for freeing things that are no longer in struct */
-                       }
-               }
-               (void) free((void *) gleidescope);
-               gleidescope = NULL;
+               /* acd - was code here for freeing things that are no longer in struct */
        }
-       
-       FreeAllGL(mi);
 }
 
 XSCREENSAVER_MODULE ("Gleidescope", gleidescope)