From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / glmatrix.c
index 4d45e2e2b45b26e389820e9289663d33b4973000..4782c1cc7f65ce912822f00a26e8d9caa8ae1a4f 100644 (file)
  * movie did.
  */
 
  * movie did.
  */
 
-#include <X11/Intrinsic.h>
-
-extern XtAppContext app;
-
-#define PROGCLASS      "GLMatrix"
-#define HACK_INIT      init_matrix
-#define HACK_DRAW      draw_matrix
-#define HACK_RESHAPE   reshape_matrix
-#define HACK_HANDLE_EVENT matrix_handle_event
-#define EVENT_MASK      PointerMotionMask
-#define matrix_opts    xlockmore_opts
-
-#define DEF_SPEED       "1.0"
-#define DEF_DENSITY     "20"
-#define DEF_CLOCK       "False"
-#define DEF_FOG         "True"
-#define DEF_WAVES       "True"
-#define DEF_ROTATE      "True"
-#define DEF_TEXTURE     "True"
-#define DEF_MODE        "Matrix"
-#define DEF_TIMEFMT     " %l%M%p "
-
 #define DEFAULTS       "*delay:        30000         \n" \
                        "*showFPS:      False         \n" \
                        "*wireframe:    False         \n" \
 
 #define DEFAULTS       "*delay:        30000         \n" \
                        "*showFPS:      False         \n" \
                        "*wireframe:    False         \n" \
 
+# define refresh_matrix 0
+# define release_matrix 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -50,9 +30,6 @@ extern XtAppContext app;
 
 #include "xlockmore.h"
 #include "xpm-ximage.h"
 
 #include "xlockmore.h"
 #include "xpm-ximage.h"
-#include <ctype.h>
-#include <time.h>
-#include <stdio.h>
 
 #ifdef __GNUC__
   __extension__  /* don't warn about "string length is greater than the length
 
 #ifdef __GNUC__
   __extension__  /* don't warn about "string length is greater than the length
@@ -63,26 +40,39 @@ extern XtAppContext app;
 
 #ifdef USE_GL /* whole file */
 
 
 #ifdef USE_GL /* whole file */
 
-#include <GL/glu.h>
-
 
 
-#include "gllist.h"
+#define DEF_SPEED       "1.0"
+#define DEF_DENSITY     "20"
+#define DEF_CLOCK       "False"
+#define DEF_FOG         "True"
+#define DEF_WAVES       "True"
+#define DEF_ROTATE      "True"
+#define DEF_TEXTURE     "True"
+#define DEF_MODE        "Matrix"
+#define DEF_TIMEFMT     " %l%M%p "
 
 
 #define CHAR_COLS 16
 #define CHAR_ROWS 13
 
 
 #define CHAR_COLS 16
 #define CHAR_ROWS 13
-static int real_char_rows;
-
-static int matrix_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-                                 192, 193, 194, 195, 196, 197, 198, 199,
-                                 200, 201, 202, 203, 204, 205, 206, 207 };
-static int decimal_encoding[]  = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
-static int hex_encoding[]      = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-                                   33, 34, 35, 36, 37, 38 };
-static int binary_encoding[] = { 16, 17 };
-static int dna_encoding[]    = { 33, 35, 39, 52 };
-
-static unsigned char char_map[256] = {
+
+static const int matrix_encoding[] = {
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+# if 0
+    192, 193, 194, 195, 196, 197, 198, 199,
+    200, 201, 202, 203, 204, 205, 206, 207
+# else
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175
+# endif
+  };
+static const int decimal_encoding[]  = {
+  16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
+static const int hex_encoding[] = {
+  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38 };
+static const int binary_encoding[] = { 16, 17 };
+static const int dna_encoding[]    = { 33, 35, 39, 52 };
+
+static const unsigned char char_map[256] = {
    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  /*   0 */
    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  /*  16 */
     0,  1,  2, 96,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  /*  32 */
    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  /*   0 */
    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  /*  16 */
     0,  1,  2, 96,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  /*  32 */
@@ -115,7 +105,7 @@ static unsigned char char_map[256] = {
 #define WAVE_SIZE  22     /* periodicity of color (brightness) waves */
 #define SPLASH_RATIO 0.7  /* ratio of GRID_DEPTH where chars hit the screen */
 
 #define WAVE_SIZE  22     /* periodicity of color (brightness) waves */
 #define SPLASH_RATIO 0.7  /* ratio of GRID_DEPTH where chars hit the screen */
 
-static struct { GLfloat x, y; } nice_views[] = {
+static const struct { GLfloat x, y; } nice_views[] = {
   {  0,     0 },
   {  0,   -20 },     /* this is a list of viewer rotations that look nice. */
   {  0,    20 },     /* every now and then we switch to a new one.         */
   {  0,     0 },
   {  0,   -20 },     /* this is a list of viewer rotations that look nice. */
   {  0,    20 },     /* every now and then we switch to a new one.         */
@@ -170,7 +160,7 @@ typedef struct {
   GLuint texture;
   int nstrips;
   strip *strips;
   GLuint texture;
   int nstrips;
   strip *strips;
-  int *glyph_map;
+  const int *glyph_map;
   int nglyphs;
   GLfloat tex_char_width, tex_char_height;
 
   int nglyphs;
   GLfloat tex_char_width, tex_char_height;
 
@@ -179,13 +169,15 @@ typedef struct {
   GLfloat view_x, view_y;
   int view_steps, view_tick;
   Bool auto_tracking_p;
   GLfloat view_x, view_y;
   int view_steps, view_tick;
   Bool auto_tracking_p;
+  int track_tick;
+
+  int real_char_rows;
+  GLfloat brightness_ramp[WAVE_SIZE];
 
 } matrix_configuration;
 
 static matrix_configuration *mps = NULL;
 
 
 } matrix_configuration;
 
 static matrix_configuration *mps = NULL;
 
-static GLfloat brightness_ramp[WAVE_SIZE];
-
 static GLfloat speed;
 static GLfloat density;
 static Bool do_clock;
 static GLfloat speed;
 static GLfloat density;
 static Bool do_clock;
@@ -229,7 +221,7 @@ static argtype vars[] = {
   {&do_texture, "texture",    "Texture", DEF_TEXTURE,   t_Bool},
 };
 
   {&do_texture, "texture",    "Texture", DEF_TEXTURE,   t_Bool},
 };
 
-ModeSpecOpt matrix_opts = {countof(opts), opts, countof(vars), vars, NULL};
+ENTRYPOINT ModeSpecOpt matrix_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
 
 /* Re-randomize the state of one strip.
 
 
 /* Re-randomize the state of one strip.
@@ -395,7 +387,7 @@ draw_glyph (ModeInfo *mi, int glyph, Bool highlight,
       int ccy = ((glyph - 1) / CHAR_COLS);
 
       cx = ccx * w;
       int ccy = ((glyph - 1) / CHAR_COLS);
 
       cx = ccx * w;
-      cy = (real_char_rows - ccy - 1) * h;
+      cy = (mp->real_char_rows - ccy - 1) * h;
 
       if (do_fog)
         {
 
       if (do_fog)
         {
@@ -407,15 +399,17 @@ draw_glyph (ModeInfo *mi, int glyph, Bool highlight,
     }
 
   {
     }
 
   {
-    GLfloat r, g, b, a = 1;
+    GLfloat r, g, b, a;
 
     if (highlight)
       brightness *= 2;
 
     if (!do_texture && !spinner_p)
 
     if (highlight)
       brightness *= 2;
 
     if (!do_texture && !spinner_p)
-      r = b = 0, g = brightness;
+      r = b = 0, g = 1;
     else
     else
-      r = g = b = brightness;
+      r = g = b = 1;
+
+    a = brightness;
 
     /* If the glyph is very close to the screen (meaning it is very large,
        and is about to splash into the screen and vanish) then start fading
 
     /* If the glyph is very close to the screen (meaning it is very large,
        and is about to splash into the screen and vanish) then start fading
@@ -430,23 +424,7 @@ draw_glyph (ModeInfo *mi, int glyph, Bool highlight,
         if (i < 0) i = 0;
         else if (i >= WAVE_SIZE) i = WAVE_SIZE-1; 
 
         if (i < 0) i = 0;
         else if (i >= WAVE_SIZE) i = WAVE_SIZE-1; 
 
-        a = brightness_ramp[i];
-#if 1
-        /* I don't understand this -- if I change the alpha on the color of
-           the quad, I'd expect that to make the quad more transparent.
-           But instead, it seems to be making the transparent parts of the
-           texture on the quad be *less* transparent!  So as we fade out,
-           we fade towards a completely solid rectangle.  WTF?
-
-           So, for now, instead of changing the alpha, just make the colors
-           be darker.  This works out ok so long as we use GL_ONE in
-           glBlendFunc, so that stacked glyph colors are added together.
-         */
-        r *= a;
-        g *= a;
-        b *= a;
-        a = 1;
-#endif
+        a *= mp->brightness_ramp[i];
       }
 
     glColor4f (r,g,b,a);
       }
 
     glColor4f (r,g,b,a);
@@ -479,6 +457,7 @@ draw_glyph (ModeInfo *mi, int glyph, Bool highlight,
 static void
 draw_strip (ModeInfo *mi, strip *s)
 {
 static void
 draw_strip (ModeInfo *mi, strip *s)
 {
+  matrix_configuration *mp = &mps[MI_SCREEN(mi)];
   int i;
   for (i = 0; i < GRID_SIZE; i++)
     {
   int i;
   for (i = 0; i < GRID_SIZE; i++)
     {
@@ -497,7 +476,7 @@ draw_strip (ModeInfo *mi, strip *s)
             {
               int j = WAVE_SIZE - ((i + (GRID_SIZE - s->wave_position))
                                    % WAVE_SIZE);
             {
               int j = WAVE_SIZE - ((i + (GRID_SIZE - s->wave_position))
                                    % WAVE_SIZE);
-              brightness = brightness_ramp[j];
+              brightness = mp->brightness_ramp[j];
             }
 
           draw_glyph (mi, g, s->highlight[i],
             }
 
           draw_glyph (mi, g, s->highlight[i],
@@ -552,9 +531,8 @@ auto_track (ModeInfo *mi)
   /* if we're not moving, maybe start moving.  Otherwise, do nothing. */
   if (! mp->auto_tracking_p)
     {
   /* if we're not moving, maybe start moving.  Otherwise, do nothing. */
   if (! mp->auto_tracking_p)
     {
-      static int tick = 0;
-      if (++tick < 20/speed) return;
-      tick = 0;
+      if (++mp->track_tick < 20/speed) return;
+      mp->track_tick = 0;
       if (! (random() % 20))
         mp->auto_tracking_p = True;
       else
       if (! (random() % 20))
         mp->auto_tracking_p = True;
       else
@@ -590,7 +568,7 @@ auto_track (ModeInfo *mi)
 
 /* Window management, etc
  */
 
 /* Window management, etc
  */
-void
+ENTRYPOINT void
 reshape_matrix (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
 reshape_matrix (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
@@ -611,7 +589,7 @@ reshape_matrix (ModeInfo *mi, int width, int height)
 }
 
 
 }
 
 
-Bool
+ENTRYPOINT Bool
 matrix_handle_event (ModeInfo *mi, XEvent *event)
 {
   matrix_configuration *mp = &mps[MI_SCREEN(mi)];
 matrix_handle_event (ModeInfo *mi, XEvent *event)
 {
   matrix_configuration *mp = &mps[MI_SCREEN(mi)];
@@ -654,16 +632,20 @@ bigendian (void)
 
    If this hack ever grows into something that displays full Latin1 text,
    well then, Something Else Will Need To Be Done.
 
    If this hack ever grows into something that displays full Latin1 text,
    well then, Something Else Will Need To Be Done.
+
+   Since currently GLMatrix does not run textclient / xscreensaver-text,
+   it's not an issue.  (XMatrix does that.)
+
  */
 static void
  */
 static void
-spank_image (XImage *xi)
+spank_image (matrix_configuration *mp, XImage *xi)
 {
   int ch = xi->height / CHAR_ROWS;
   int cut = 2;
   unsigned char *bits = (unsigned char *) xi->data;
   unsigned char *from, *to, *s, *end;
   int L = xi->bytes_per_line * ch;
 {
   int ch = xi->height / CHAR_ROWS;
   int cut = 2;
   unsigned char *bits = (unsigned char *) xi->data;
   unsigned char *from, *to, *s, *end;
   int L = xi->bytes_per_line * ch;
-  int i;
+/*  int i;*/
 
   /* Copy row 12 into 10 (which really means, copy 2 into 0,
      since texture data is upside down.).
 
   /* Copy row 12 into 10 (which really means, copy 2 into 0,
      since texture data is upside down.).
@@ -693,13 +675,15 @@ spank_image (XImage *xi)
     *s++ = 0;
 
   xi->height -= (cut * ch);
     *s++ = 0;
 
   xi->height -= (cut * ch);
-  real_char_rows -= cut;
+  mp->real_char_rows -= cut;
 
 
+# if 0
   /* Finally, pull the map indexes back to match the new bits.
    */
   for (i = 0; i < countof(matrix_encoding); i++)
     if (matrix_encoding[i] > (CHAR_COLS * (CHAR_ROWS - cut)))
       matrix_encoding[i] -= (cut * CHAR_COLS);
   /* Finally, pull the map indexes back to match the new bits.
    */
   for (i = 0; i < countof(matrix_encoding); i++)
     if (matrix_encoding[i] > (CHAR_COLS * (CHAR_ROWS - cut)))
       matrix_encoding[i] -= (cut * CHAR_COLS);
+# endif
 }
 
 
 }
 
 
@@ -719,8 +703,8 @@ load_textures (ModeInfo *mi, Bool flip_p)
                       matrix3_xpm);
   orig_w = xi->width;
   orig_h = xi->height;
                       matrix3_xpm);
   orig_w = xi->width;
   orig_h = xi->height;
-  real_char_rows = CHAR_ROWS;
-  spank_image (xi);
+  mp->real_char_rows = CHAR_ROWS;
+  spank_image (mp, xi);
 
   if (xi->height != 512 && xi->height != 1024)
     {
 
   if (xi->height != 512 && xi->height != 1024)
     {
@@ -785,7 +769,7 @@ load_textures (ModeInfo *mi, Bool flip_p)
           unsigned char r = (p >> rpos) & 0xFF;
           unsigned char g = (p >> gpos) & 0xFF;
           unsigned char b = (p >> bpos) & 0xFF;
           unsigned char r = (p >> rpos) & 0xFF;
           unsigned char g = (p >> gpos) & 0xFF;
           unsigned char b = (p >> bpos) & 0xFF;
-          unsigned char a = ~g;
+          unsigned char a = g;
           g = 0xFF;
           p = (r << rpos) | (g << gpos) | (b << bpos) | (a << apos);
           XPutPixel (xi, x, y, p);
           g = 0xFF;
           p = (r << rpos) | (g << gpos) | (b << bpos) | (a << apos);
           XPutPixel (xi, x, y, p);
@@ -798,7 +782,8 @@ load_textures (ModeInfo *mi, Bool flip_p)
   glGenTextures (1, &mp->texture);
 
   glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
   glGenTextures (1, &mp->texture);
 
   glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
-  glPixelStorei (GL_UNPACK_ROW_LENGTH, xi->width);
+  /* messes up -fps */
+  /* glPixelStorei (GL_UNPACK_ROW_LENGTH, xi->width);*/
   glBindTexture (GL_TEXTURE_2D, mp->texture);
   check_gl_error ("texture init");
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, xi->width, xi->height, 0, GL_RGBA,
   glBindTexture (GL_TEXTURE_2D, mp->texture);
   check_gl_error ("texture init");
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, xi->width, xi->height, 0, GL_RGBA,
@@ -826,7 +811,7 @@ load_textures (ModeInfo *mi, Bool flip_p)
 }
 
 
 }
 
 
-void 
+ENTRYPOINT void 
 init_matrix (ModeInfo *mi)
 {
   matrix_configuration *mp;
 init_matrix (ModeInfo *mi)
 {
   matrix_configuration *mp;
@@ -837,14 +822,7 @@ init_matrix (ModeInfo *mi)
   if (wire)
     do_texture = False;
 
   if (wire)
     do_texture = False;
 
-  if (!mps) {
-    mps = (matrix_configuration *)
-      calloc (MI_NUM_SCREENS(mi), sizeof (matrix_configuration));
-    if (!mps) {
-      fprintf(stderr, "%s: out of memory\n", progname);
-      exit(1);
-    }
-  }
+  MI_INIT (mi, mps, NULL);
 
   mp = &mps[MI_SCREEN(mi)];
   mp->glx_context = init_GL(mi);
 
   mp = &mps[MI_SCREEN(mi)];
   mp->glx_context = init_GL(mi);
@@ -899,18 +877,7 @@ init_matrix (ModeInfo *mi)
   glEnable(GL_NORMALIZE);
 
   if (do_texture)
   glEnable(GL_NORMALIZE);
 
   if (do_texture)
-    {
-      load_textures (mi, flip_p);
-      glEnable(GL_TEXTURE_2D);
-      glEnable(GL_BLEND);
-
-      /* Jeff Epler points out:
-         By using GL_ONE instead of GL_SRC_ALPHA, glyphs are added to
-         each other, so that a bright glyph with a darker one in front
-         is a little brighter than the bright glyph alone.
-       */
-      glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, /* GL_SRC_ALPHA */ GL_ONE);
-    }
+    load_textures (mi, flip_p);
 
   /* to scale coverage-percent to strips, this number looks about right... */
   mp->nstrips = (int) (density * 2.2);
 
   /* to scale coverage-percent to strips, this number looks about right... */
   mp->nstrips = (int) (density * 2.2);
@@ -942,7 +909,7 @@ init_matrix (ModeInfo *mi)
       j *= (M_PI / 2);       /* j ranges from 0.0 - PI/2  */
       j = sin (j);           /* j ranges from 0.0 - 1.0   */
       j = 0.2 + (j * 0.8);   /* j ranges from 0.2 - 1.0   */
       j *= (M_PI / 2);       /* j ranges from 0.0 - PI/2  */
       j = sin (j);           /* j ranges from 0.0 - 1.0   */
       j = 0.2 + (j * 0.8);   /* j ranges from 0.2 - 1.0   */
-      brightness_ramp[i] = j;
+      mp->brightness_ramp[i] = j;
       /* printf("%2d %8.2f\n", i, j); */
     }
 
       /* printf("%2d %8.2f\n", i, j); */
     }
 
@@ -962,6 +929,7 @@ draw_grid (ModeInfo *mi)
       glDisable(GL_BLEND);
     }
   glPushMatrix();
       glDisable(GL_BLEND);
     }
   glPushMatrix();
+
   glColor3f(1, 1, 1);
   glBegin(GL_LINES);
   glVertex3f(-GRID_SIZE, 0, 0); glVertex3f(GRID_SIZE, 0, 0);
   glColor3f(1, 1, 1);
   glBegin(GL_LINES);
   glVertex3f(-GRID_SIZE, 0, 0); glVertex3f(GRID_SIZE, 0, 0);
@@ -1005,7 +973,7 @@ draw_grid (ModeInfo *mi)
 #endif /* DEBUG */
 
 
 #endif /* DEBUG */
 
 
-void
+ENTRYPOINT void
 draw_matrix (ModeInfo *mi)
 {
   matrix_configuration *mp = &mps[MI_SCREEN(mi)];
 draw_matrix (ModeInfo *mi)
 {
   matrix_configuration *mp = &mps[MI_SCREEN(mi)];
@@ -1016,9 +984,25 @@ draw_matrix (ModeInfo *mi)
   if (!mp->glx_context)
     return;
 
   if (!mp->glx_context)
     return;
 
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
+
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
+  glRotatef(current_device_rotation(), 0, 0, 1);
+
+  if (do_texture)
+    {
+      glEnable(GL_TEXTURE_2D);
+      glEnable(GL_BLEND);
+
+      /* Jeff Epler points out:
+         By using GL_ONE instead of GL_SRC_ONE_MINUS_ALPHA, glyphs are
+         added to each other, so that a bright glyph with a darker one
+         in front is a little brighter than the bright glyph alone.
+       */
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+    }
 
   if (do_rotate)
     {
 
   if (do_rotate)
     {
@@ -1077,4 +1061,6 @@ draw_matrix (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
   glXSwapBuffers(dpy, window);
 }
 
+XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix)
+
 #endif /* USE_GL */
 #endif /* USE_GL */