ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[xscreensaver] / hacks / glx / flipscreen3d.c
index c2bca2762f11c0e3e304c8b33785f41d61cbbd11..4cee56ee262011142accee066014dd53add1e138 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * screenflip - takes snapshots of the screen and flips it around
+ * flipscreen3d - takes snapshots of the screen and flips it around
  *
  * version 1.0 - Oct 24, 2001
  *
 
 
 #ifdef STANDALONE
-# define PROGCLASS                                      "Screenflip"
+# define PROGCLASS                                      "FlipScreen3D"
 # define HACK_INIT                                      init_screenflip
 # define HACK_DRAW                                      draw_screenflip
 # define HACK_RESHAPE                           reshape_screenflip
+# define HACK_HANDLE_EVENT                             screenflip_handle_event
+# define EVENT_MASK                                    PointerMotionMask
 # define screenflip_opts                                     xlockmore_opts
 /* insert defaults here */
 
 #define DEFAULTS       "*delay:       20000       \n" \
                         "*showFPS:       False       \n" \
                         "*rotate:       True       \n" \
+                       "*wireframe:    False   \n"     \
 
 # include "xlockmore.h"                         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -60,13 +63,13 @@ GLfloat qx = -6 , qy = 6;
 
 
 static XrmOptionDescRec opts[] = {
-  {"+rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "false" },
-  {"-rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "true" },
+  {"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" },
+  {"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" },
 };
 
 
 static argtype vars[] = {
-  {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool},
+  {&rotate, "rotate", "Rotate", "True", t_Bool},
 };
 
 
@@ -96,6 +99,7 @@ static Screenflip *screenflip = NULL;
 #include <stdio.h>
 #include <stdlib.h>
 #include "grab-ximage.h"
+#include "gltrackball.h"
 
 #ifndef M_PI
 #define M_PI 3.14159265
@@ -106,9 +110,43 @@ static GLfloat viewer[] = {0.0, 0.0, 15.0};
 int regrab = 0;
 int fadetime = 0; /* fade before regrab */
 
+static trackball_state *trackball;
+static Bool button_down_p = False;
+
+
+Bool
+screenflip_handle_event (ModeInfo *mi, XEvent *event)
+{
+  if (event->xany.type == ButtonPress &&
+      event->xbutton.button & Button1)
+    {
+      button_down_p = True;
+      gltrackball_start (trackball,
+                         event->xbutton.x, event->xbutton.y,
+                         MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button & Button1)
+    {
+      button_down_p = False;
+      return True;
+    }
+  else if (event->xany.type == MotionNotify &&
+           button_down_p)
+    {
+      gltrackball_track (trackball,
+                         event->xmotion.x, event->xmotion.y,
+                         MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
+    }
+
+  return False;
+}
+
 
 /* draw the texture mapped quad (actually two back to back)*/
-void showscreen(int frozen)
+void showscreen(int frozen, int wire)
 {
   static GLfloat r = 1, g = 1, b = 1, a = 1;
   GLfloat qxw, qyh;
@@ -142,29 +180,36 @@ void showscreen(int frozen)
   if (!frozen) {
      w *= sin (stretch_val_x) + 1;
      x *= sin (stretch_val_x) + 1;
+     if (!button_down_p) {
      if (!fadetime) stretch_val_x += stretch_val_dx;
      if (stretch_val_x > 2*M_PI && !(random() % 5))
        stretch_val_dx = (float)(random() % 100) / 5000;
      else
        stretch_val_x -= 2*M_PI;
+     }
 
-     if (!fadetime) stretch_val_y += stretch_val_dy;
+     if (!button_down_p && !fadetime) stretch_val_y += stretch_val_dy;
      h *= sin (stretch_val_y) / 2 + 1;
      y *= sin (stretch_val_y) / 2 + 1;
+     if (!button_down_p) {
      if (stretch_val_y > 2*M_PI && !(random() % 5))
        stretch_val_dy = (float)(random() % 100) / 5000;
      else
        stretch_val_y -= 2*M_PI;
+     }
   }
 
   glColor4f(r, g, b, a);
 
-  glEnable(GL_TEXTURE_2D);
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glDepthMask(GL_FALSE);
+  if (!wire)
+    {
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glDepthMask(GL_FALSE);
+    }
 
-  glBegin(GL_QUADS);
+  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
 
   glNormal3f(0, 0, 1);
 
@@ -275,7 +320,7 @@ void drawgrid(void)
   glEnd();
 }
 
-void display(void)
+void display(int wire)
 {
   static GLfloat rx=1, ry=1, rz=0;
   static GLfloat rot = 0;
@@ -295,7 +340,7 @@ void display(void)
     frozen = 0;
     glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10);
 /* randomly change the speed */
-    if (!(random() % 300)) {
+    if (!button_down_p && !(random() % 300)) {
       if (random() % 2)
         drho = 1/60 - (float)(random() % 100)/3000;
       if (random() % 2)
@@ -303,9 +348,10 @@ void display(void)
       if (random() % 2)
         dgamma = 1/60 - (float)(random() % 100)/3000;
     }
+    gltrackball_rotate (trackball);
     if (rotate) glRotatef(rot, rx, ry, rz);
 /* update variables with each frame */
-    if (!fadetime) {
+    if(!button_down_p && !fadetime) {
       theta += dtheta;
       rho += drho;
       gamma += dgamma;
@@ -323,7 +369,7 @@ void display(void)
     rot = 0;
     frozen = 1;
   }
-  if (!fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate  change */
+  if (!button_down_p && !fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate  change */
     rx = (GLfloat)(random() % 100) / 100;
     ry = (GLfloat)(random() % 100) / 100;
     rz = (GLfloat)(random() % 100) / 100;
@@ -335,7 +381,7 @@ void display(void)
   odrot = drot;
   if (rot > 360 || rot < -360) /* dont overflow rotation! */
     rot -= rot;
-  showscreen(frozen);
+  showscreen(frozen, wire);
   glPopMatrix();
   glFlush();
 }
@@ -354,15 +400,21 @@ void reshape_screenflip(ModeInfo *mi, int width, int height)
 void getSnapshot (ModeInfo *modeinfo)
 {
   XImage *ximage;
+  int status;
+
+  if (MI_IS_WIREFRAME(modeinfo))
+    return;
 
- ximage = screen_to_ximage (modeinfo->xgwa.screen, modeinfo->window);
+ ximage = screen_to_ximage (modeinfo->xgwa.screen, modeinfo->window, NULL);
 
   qw = QW; qh = QH;
   tw = modeinfo->xgwa.width;
   th = modeinfo->xgwa.height;
 
+#if 0  /* jwz: this makes the image start off the bottom right of the screen */
   qx += (qw*tw/winw);
   qy -= (qh*th/winh);
+#endif
 
   qw *= (GLfloat)tw/winw;
   qh *= (GLfloat)th/winh;
@@ -374,12 +426,30 @@ void getSnapshot (ModeInfo *modeinfo)
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                   GL_LINEAR_MIPMAP_LINEAR);
- if (gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
-                       ximage->width, ximage->height,
-                       GL_RGBA, GL_UNSIGNED_BYTE, ximage->data)) {
-    printf("Error!\n");
-    exit(1);
- }
+
+ clear_gl_error();
+ status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
+                            ximage->width, ximage->height,
+                            GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
+
+ if (!status && glGetError())
+   /* Some implementations of gluBuild2DMipmaps(), but set a GL error anyway.
+      We could just call check_gl_error(), but that would exit. */
+   status = -1;
+
+ if (status)
+   {
+     const char *s = (char *) gluErrorString (status);
+     fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
+              progname, ximage->width, ximage->height,
+              (s ? s : "(unknown)"));
+     fprintf (stderr, "%s: turning on -wireframe.\n", progname);
+     MI_IS_WIREFRAME(modeinfo) = 1;
+     clear_gl_error();
+   }
+ check_gl_error("mipmapping");  /* should get a return code instead of a
+                                   GL error, but just in case... */
+
  free(ximage->data);
  ximage->data = 0;
  XDestroyImage (ximage);
@@ -398,6 +468,8 @@ void init_screenflip(ModeInfo *mi)
  c = &screenflip[screen];
  c->window = MI_WINDOW(mi);
 
+ trackball = gltrackball_init ();
+
  if ((c->glx_context = init_GL(mi)) != NULL) {
       reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
  } else {
@@ -406,12 +478,16 @@ void init_screenflip(ModeInfo *mi)
  winh = MI_WIN_HEIGHT(mi);
  winw = MI_WIN_WIDTH(mi);
  glClearColor(0.0,0.0,0.0,0.0);
- glShadeModel(GL_SMOOTH);
- glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
- glDisable(GL_LIGHTING);
+
+ 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_FRONT);
+     glDisable(GL_LIGHTING);
+   }
 
  getSnapshot(mi);
 }
@@ -430,7 +506,7 @@ void draw_screenflip(ModeInfo *mi)
   if (regrab)
     getSnapshot(mi);
 
-  display();
+  display(MI_IS_WIREFRAME(mi));
 
   if(mi->fps_p) do_fps(mi);
   glFinish();