http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / glx / pulsar.c
index a6125c8154ed3a3e6b02feb0a01761ee19fbed3d..986f284634fbbc6119bec7eb4a870c53ed84a76b 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- Mode: C; tab-width: 4 -*- */
-/* pulsar --- pulsar module for xscreensaver */
+/* pulsar --- pulsar module for xpulsar */
 /*-
  * Permission to use, copy, modify, and distribute this software and its
  * documentation for any purpose and without fee is hereby granted,
@@ -20,7 +20,7 @@
  * 4-May-1999:  dek@cgl.ucsf.edu  Submitted module "pulsar" updates
  *
  * Notes:
- * The pulsar screensaver draws a number of rotating, pulsing rectangles
+ * The pulsar pulsar draws a number of rotating, pulsing rectangles
  * on your screen.  Depending on the options you choose, you can set a number
  * of interesting OpenGL parameters, including alpha blending, depth testing, fog,
  * lighting, texturing, mipmapping, bilinear filtering, and line antialiasing.  
 #include <stdio.h>
 #include <stdlib.h>
 
-/*-
- * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
- * otherwise caddr_t is not defined correctly
- */
-
-#include <X11/Intrinsic.h>
-
 #ifdef STANDALONE
-# define PROGCLASS                                             "Screensaver"
-# define HACK_INIT                                             init_screensaver
-# define HACK_DRAW                                             draw_screensaver
-# define screensaver_opts                              xlockmore_opts
-#define        DEFAULTS                        "*light:                        False   \n" \
-                                        "*wire:                                False   \n" \
-                                        "*quads:                       5       \n" \
-                                        "*blend:                       True    \n" \
-                                        "*fog:                         False   \n" \
-                                        "*antialias:           False   \n" \
-                                        "*texture:                     False   \n" \
-                                        "*texture_quality:     False   \n" \
-                                        "*mipmap:                      False   \n" \
-                                        "*fps:                         False   \n" \
-                                        "*doDepth:                     False   \n" \
-                                                                               "*image:                        BUILTIN \n"
-
-# include "xlockmore.h"                                /* from the xscreensaver distribution */
+#define        DEFAULTS                        "*delay:                        10000   \n" \
+                                                                               "*showFPS:          False   \n" \
+
+# define refresh_pulsar 0
+# define pulsar_handle_event 0
+# include "xlockmore.h"                                /* from the xpulsar distribution */
 #else /* !STANDALONE */
 # include "xlock.h"                                    /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL /* whole file */
 
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
-
 #ifdef HAVE_XMU
 # ifndef VMS
 #  include <X11/Xmu/Drawing.h>
 # endif /* VMS */
 #endif
 
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#include <string.h>
-#include <malloc.h>
-#include <stdio.h>
+#include "xpm-ximage.h"
 
 /* Functions for loading and storing textures */
 
 #define checkImageHeight 64
 
 /* Functions for handling the frames per second timer */
-#include "GL/glx.h"
-
-#ifndef SAMPLE_FRAMES
-#define SAMPLE_FRAMES 10
-#endif
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 #define DEF_TEXTURE    "False"
 #define DEF_TEXTURE_QUALITY   "False"
 #define DEF_MIPMAP     "False"
-#define DEF_FPS                "False"
 #define DEF_DO_DEPTH   "False"
 #define DEF_IMAGE      "BUILTIN"
 
@@ -136,50 +98,46 @@ static int do_antialias;
 static int do_texture;
 static int do_texture_quality;
 static int do_mipmap;
-static int do_fps;
 static int do_depth;
 static char *which_image;
 
 
 static XrmOptionDescRec opts[] = {
-  {"-quads",   ".pulsar.quads",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-light",   ".pulsar.light",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+light",   ".pulsar.light",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-wire",   ".pulsar.wire",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+wire",   ".pulsar.wire",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-blend",   ".pulsar.blend",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+blend",   ".pulsar.blend",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-fog",   ".pulsar.fog",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+fog",   ".pulsar.fog",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-antialias",   ".pulsar.antialias",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+antialias",   ".pulsar.antialias",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-texture",   ".pulsar.texture",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+texture",   ".pulsar.texture",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-fps",   ".pulsar.fps",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+fps",   ".pulsar.fps",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-image",   ".pulsar.image",  XrmoptionSepArg, (caddr_t) NULL },
+  {"-quads",   ".pulsar.quads",   XrmoptionSepArg, 0 },
+  {"-light",   ".pulsar.light",   XrmoptionNoArg, "true" },
+  {"+light",   ".pulsar.light",   XrmoptionNoArg, "false" },
+  {"-wire",   ".pulsar.wire",   XrmoptionNoArg, "true" },
+  {"+wire",   ".pulsar.wire",   XrmoptionNoArg, "false" },
+  {"-blend",   ".pulsar.blend",   XrmoptionNoArg, "true" },
+  {"+blend",   ".pulsar.blend",   XrmoptionNoArg, "false" },
+  {"-fog",   ".pulsar.fog",   XrmoptionNoArg, "true" },
+  {"+fog",   ".pulsar.fog",   XrmoptionNoArg, "false" },
+  {"-antialias",   ".pulsar.antialias",   XrmoptionNoArg, "true" },
+  {"+antialias",   ".pulsar.antialias",   XrmoptionNoArg, "false" },
+  {"-texture",   ".pulsar.texture",   XrmoptionNoArg, "true" },
+  {"+texture",   ".pulsar.texture",   XrmoptionNoArg, "false" },
+  {"-texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, "true" },
+  {"+texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, "false" },
+  {"-mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, "true" },
+  {"+mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, "false" },
+  {"-do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, "true" },
+  {"+do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, "false" },
+  {"-image",   ".pulsar.image",  XrmoptionSepArg, 0 },
 };
 
 
 static argtype vars[] = {
-  {(caddr_t *) &num_quads, "quads", "Quads", DEF_NUM_QUADS, t_Int},
-  {(caddr_t *) &do_light,    "light",   "Light",   DEF_LIGHT,   t_Bool},
-  {(caddr_t *) &do_wire,    "wire",   "Wire",   DEF_WIRE,   t_Bool},
-  {(caddr_t *) &do_blend,    "blend",   "Blend",   DEF_BLEND,   t_Bool},
-  {(caddr_t *) &do_fog,    "fog",   "Fog",   DEF_FOG,   t_Bool},
-  {(caddr_t *) &do_antialias,    "antialias",   "Antialias",   DEF_ANTIALIAS,   t_Bool},
-  {(caddr_t *) &do_texture,    "texture",   "Texture",   DEF_TEXTURE,   t_Bool},
-  {(caddr_t *) &do_texture_quality,    "texture_quality",   "Texture_quality",   DEF_TEXTURE_QUALITY,   t_Bool},
-  {(caddr_t *) &do_mipmap,    "mipmap",   "Mipmap",   DEF_MIPMAP,   t_Bool},
-  {(caddr_t *) &do_fps,    "fps",   "fps",   DEF_FPS,   t_Bool},
-  {(caddr_t *) &do_depth,    "doDepth",   "DoDepth",   DEF_DO_DEPTH,   t_Bool},
-  {(caddr_t *) &which_image, "image",   "Image",   DEF_IMAGE,   t_String},
+  {&num_quads,    "quads",     "Quads",     DEF_NUM_QUADS, t_Int},
+  {&do_light,     "light",     "Light",     DEF_LIGHT,     t_Bool},
+  {&do_wire,      "wire",      "Wire",      DEF_WIRE,      t_Bool},
+  {&do_blend,     "blend",     "Blend",     DEF_BLEND,     t_Bool},
+  {&do_fog,       "fog",       "Fog",       DEF_FOG,       t_Bool},
+  {&do_antialias, "antialias", "Antialias", DEF_ANTIALIAS, t_Bool},
+  {&do_texture,   "texture",   "Texture",   DEF_TEXTURE,   t_Bool},
+  {&do_texture_quality, "texture_quality", "Texture_quality", DEF_TEXTURE_QUALITY,   t_Bool},
+  {&do_mipmap,    "mipmap",    "Mipmap",    DEF_MIPMAP,    t_Bool},
+  {&do_depth,    "doDepth",    "DoDepth",   DEF_DO_DEPTH,  t_Bool},
+  {&which_image, "image",      "Image",     DEF_IMAGE,     t_String},
 };
 
 
@@ -194,32 +152,20 @@ static OptionStruct desc[] =
        {"-/+ texture", "whether to do enable texturing (much slower)"},
        {"-/+ texture_quality", "whether to do enable linear/mipmap filtering (much much slower)"},
        {"-/+ mipmap", "whether to do enable mipmaps (much slower)"},
-       {"-/+ fps", "whether to do enable frames per second meter (?)"},
        {"-/+ depth", "whether to do enable depth buffer checking (slower)"},
-       {"-image <filename>", "texture image to load (PPM, PPM4, TIFF(?), XPM(?))"},
+       {"-image <filename>", "texture image to load"},
 };
 
-ModeSpecOpt screensaver_opts = {countof(opts), opts, countof(vars), vars, desc};
+ENTRYPOINT ModeSpecOpt pulsar_opts = {countof(opts), opts, countof(vars), vars, desc};
 
 #ifdef USE_MODULES
-ModStruct   screensaver_description =
-{"screensaver", "init_screensaver", "draw_screensaver", "release_screensaver",
- "draw_screensaver", "init_screensaver", NULL, &screensaver_opts,
+ModStruct   pulsar_description =
+{"pulsar", "init_pulsar", "draw_pulsar", "release_pulsar",
+ "draw_pulsar", "init_pulsar", NULL, &pulsar_opts,
  1000, 1, 2, 1, 4, 1.0, "",
- "OpenGL screensaver", 0, NULL};
+ "OpenGL pulsar", 0, NULL};
 #endif
 
-
-/* structure for holding the screensaver data */
-typedef struct {
-  int screen_width, screen_height;
-  GLXContext *glx_context;
-  Window window;
-  XColor fg, bg;
-} screensaverstruct;
-
-static screensaverstruct *Screensaver = NULL;
-
 struct quad
 {
   GLfloat tx, ty, tz;
@@ -230,129 +176,26 @@ struct quad
 
 };
 
-int global_width=WIDTH, global_height=HEIGHT;
-
-
-static GLint base;
-static int FrameCounter = 0;
-static double oldtime=-1., newtime=-1.;
-static char FPSstring[1024]="FPS: NONE"; 
-
-static float x_pos=0, y_pos=0;
-
-#define FONT "-*-courier-medium-r-normal-*-240-*"
-GLint quad_list;
-
-static float scale_x=1, scale_y=1, scale_z=1;
-static int frame = 0;
-
-static GLenum errCode;
-static const GLubyte *errString;
-
-struct quad *quads;
-
-int checkError(int line, char *file)
-{
-  if((errCode = glGetError()) != GL_NO_ERROR) {
-    errString = (GLubyte *)gluErrorString(errCode);
-    fprintf(stderr, "OpenGL error: %s detected at line %d in file %s\n", errString, line, file);
-    exit(1);
-  }
-  return 0;
-}
-
-
-void FPS_Setup(void)
-{
-  Display *Dpy;
-  XFontStruct *fontInfo;
-  Font id;
-  int first=0, last=255;
-
-  Dpy = XOpenDisplay(NULL);
-  fontInfo = XLoadQueryFont(Dpy, FONT);
-  if (fontInfo == NULL)
-    {
-      fprintf(stderr, "Failed to load font %s\n", FONT);
-      exit(1);
-    }
-
-  id = fontInfo->fid;
-  first = fontInfo->min_char_or_byte2;
-  last = fontInfo->max_char_or_byte2;
-  
-  base = glGenLists((GLuint) last+1);
-  if (base == 0) {
-    fprintf (stderr, "out of display lists\n");
-    exit(1);
-  }
-  glXUseXFont(id, first, last-first+1, base+first);
 
-}
+/* structure for holding the pulsar data */
+typedef struct {
+  int screen_width, screen_height;
+  GLXContext *glx_context;
+  Window window;
+  XColor fg, bg;
 
-void PrintString(float x, float y, char *string)
-{
-  int len, i;
+  GLint quad_list;
+  float scale_x, scale_y, scale_z;
+  int frame;
 
-  /* save the current state */
-  /* note: could be expensive! */
-  glPushAttrib(GL_ALL_ATTRIB_BITS);
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  gluOrtho2D(0, global_width, 0, global_height);
-  glMatrixMode(GL_MODELVIEW);
-  glLoadIdentity();
+  struct quad *quads;
 
-  /* disable lighting and texturing when drawing bitmaps! */
-  glDisable(GL_TEXTURE_2D);
-  glDisable(GL_LIGHTING);
-  glDisable(GL_BLEND);
-
-  /* draw a black background */
-
-  /* draw the text */
-  glColor3f(1,1,1);
-  glRasterPos2f( x, y);
-  len = (int) strlen(string);
-  for (i = 0; i < len; i++) {
-       if (glIsList(base+string[i]))
-         glCallList(base+string[i]);
-       else
-         fprintf(stderr, "%d+string[%d] is not a display list!\n", base, i);
-  }
+} pulsarstruct;
 
-  /* clean up after our state changes */
-  glPopAttrib();
-}
+static pulsarstruct *Pulsar = NULL;
 
-double gettime(void)
-{
-  struct timeval now;
-#ifdef GETTIMEOFDAY_TWO_ARGS
-  struct timezone tzp;
-  gettimeofday(&now, &tzp);
-#else
-  gettimeofday(&now);
-#endif
-  return (double) (now.tv_sec + (((double) now.tv_usec) * 0.000001));
-}
-
-void DoFPS(void)
-{
-  /* every SAMPLE_FRAMES frames, get the time and use it to get the 
-     frames per second */
-  if (!(FrameCounter % SAMPLE_FRAMES)) {
-    oldtime = newtime;
-    newtime = gettime();
-    sprintf(FPSstring, "FPS: %.02f", SAMPLE_FRAMES/(newtime-oldtime));
-  }
-
-  PrintString(x_pos,y_pos,FPSstring);
-
-  FrameCounter++;
-}
-
-GLubyte *Generate_Image(int *width, int *height, int *format)
+static GLubyte *
+Generate_Image(int *width, int *height, int *format)
 {
   GLubyte *result;
   int i, j, c;
@@ -360,7 +203,7 @@ GLubyte *Generate_Image(int *width, int *height, int *format)
 
   *width = checkImageWidth;
   *height = checkImageHeight;
-  result = (GLubyte *)malloc(4 * *width * *height);
+  result = (GLubyte *)malloc(4 * (*width) * (*height));
 
   counter = 0;
   for (i = 0; i < checkImageWidth; i++) {
@@ -378,210 +221,25 @@ GLubyte *Generate_Image(int *width, int *height, int *format)
 }
 
 
-
-#ifdef TIFF
-#include <tiffio>
-/* Load a TIFF texture: requires libtiff */
-uint32 *LoadTIFF(char *filename, int *width, int *height, int *format)
-{
-  TIFF *tif;
-  char emsg[1024];
-  uint32 *raster;
-  TIFFRGBAImage img;
-  tsize_t npixels;
-
-  tif = TIFFOpen(filename, "r");
-  if (tif == NULL) {
-    fprintf(stderr, "Problem showing %s\n", filename);
-    return Generate_Image(&width, &height, &format);
-  }
-  if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
-    npixels = (tsize_t) (img.width * img.height);
-    raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
-    if (raster != NULL) {
-      if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
-        TIFFError(filename, emsg);
-       return Generate_Image(&width, &height, &format);
-      }
-    }
-    TIFFRGBAImageEnd(&img);
-  } else {
-    TIFFError(filename, emsg);
-    return Generate_Image(&width, &height, &format);
-  }
-
-  *width = img.width;
-  *height = img.height;
-  *format = GL_RGBA;
-
-  TIFFClose(tif);
-  return raster;
-}
-#endif
-
-/* Load a modified version of PPM format with an extra byte for alpha */
-GLubyte *LoadPPM4(const char *filename, int *width, int *height, int *format)
-{
-  char buff[1024];
-  GLubyte *data;
-  int sizeX, sizeY;
-  FILE *fp;
-  int maxval;
-
-  fp = fopen(filename, "rb");
-  if (!fp)
-    {
-      fprintf(stderr, "Unable to open file '%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  if (!fgets(buff, sizeof(buff), fp))
-    {
-      perror("Unable to read header filename\n");
-      return  Generate_Image(width, height, format);
-    }
-
-  if (buff[0] != '6' || buff[1] != 'P')
-    {
-      fprintf(stderr, "Invalid image format (must be `6P')\n");
-      return  Generate_Image(width, height, format);
-    }
-
-  do
-    {
-      fgets(buff, sizeof(buff), fp);
-    }
-  while (buff[0] == '#');
-    
-  if (sscanf(buff, "%d %d", &sizeX, &sizeY) != 2)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  if (fscanf(fp, "%d", &maxval) != 1)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  while (fgetc(fp) != '\n')
-    ;
-
-  data = (GLubyte *)malloc(4 * sizeX * sizeY);
-  if (data == NULL)
-    {
-      fprintf(stderr, "Unable to allocate memory\n");
-         exit(1);
-    }
-
-  if (fread(data, 4 * sizeX, sizeY, fp) != sizeY)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  fclose(fp);
-
-  *width = sizeX;
-  *height = sizeY;
-  *format = GL_RGBA;
-  return data;
-}
-
-/* Load a plain PPM image */
-GLubyte *LoadPPM(const char *filename, int *width, int *height, int *format)
-{
-  char buff[1024];
-  GLubyte *data;
-  GLint sizeX, sizeY;
-  FILE *fp;
-  int maxval;
-
-  fp = fopen(filename, "rb");
-  if (!fp)
-    {
-      fprintf(stderr, "Unable to open file '%s'\n", filename);
-      return  Generate_Image(width, height, format);
-      exit(1);
-    }
-  if (!fgets(buff, sizeof(buff), fp))
-    {
-      perror(filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  if (buff[0] != 'P' || buff[1] != '6')
-    {
-      fprintf(stderr, "Invalid image format (must be `P6')\n");
-      return  Generate_Image(width, height, format);
-    }
-
-  do
-    {
-      fgets(buff, sizeof(buff), fp);
-    }
-  while (buff[0] == '#');
-    
-  if (sscanf(buff, "%d %d", &sizeX, &sizeY) != 2)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  if (fscanf(fp, "%d", &maxval) != 1)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  while (fgetc(fp) != '\n')
-    ;
-
-  data = (GLubyte *)malloc(3 * sizeX * sizeY);
-  if (data == NULL)
-    {
-      fprintf(stderr, "Unable to allocate memory\n");
-         exit(1);
-    }
-
-  if (fread(data, 3 * sizeX, sizeY, fp) != sizeY)
-    {
-      fprintf(stderr, "Error loading image `%s'\n", filename);
-      return  Generate_Image(width, height, format);
-    }
-
-  fclose(fp);
-
-  *width = sizeX;
-  *height = sizeY;
-  *format = GL_RGB;
-  return data;
-}
-
 /* Create a texture in OpenGL.  First an image is loaded 
    and stored in a raster buffer, then it's  */
-void Create_Texture(char *filename)
+static void Create_Texture(ModeInfo *mi, const char *filename)
 {
   int height, width;
   GLubyte *image;
-  GLint a;
   int format;
 
   if ( !strncmp(filename, "BUILTIN", 7))
     image = Generate_Image(&width, &height, &format);
-  else if ( !strncmp((filename+strlen(filename)-3), "ppm", 3))
-    image = LoadPPM(filename, &width, &height, &format);
-  else if ( !strncmp((filename+strlen(filename)-4), "ppm4", 4))
-    image = LoadPPM4(filename, &width, &height, &format);
-#ifdef TIFF
-  else if ( !strncmp((filename+strlen(filename)-4), "tiff", 4))
-    image = (GLubyte *)LoadTIFF(filename, &width, &height, &format);
-#endif
-  else {
-    fprintf(stderr, "Unknown file format extension: '%s'\n", filename);
-    image = Generate_Image(&width, &height, &format);
-  }
+  else
+    {
+      XImage *ximage = xpm_file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                           MI_COLORMAP (mi), filename);
+      image  = (GLubyte *) ximage->data;
+      width  = ximage->width;
+      height = ximage->height;
+      format = GL_RGBA;
+    }
 
   /* GL_MODULATE or GL_DECAL depending on what you want */
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@@ -605,7 +263,21 @@ void Create_Texture(char *filename)
 
   /* mipmaps make the image look much nicer */
   if (do_mipmap)
-       a=gluBuild2DMipmaps(GL_TEXTURE_2D, format, width, height, format, GL_UNSIGNED_BYTE, image);
+    {
+      int status;
+      clear_gl_error();
+      status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, format,
+                                 GL_UNSIGNED_BYTE, image);
+      if (status)
+        {
+          const char *s = (char *) gluErrorString (status);
+          fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
+                   progname, width, height,
+                   (s ? s : "(unknown)"));
+          exit (1);
+        }
+      check_gl_error("mipmapping");
+    }
   else
     {
       clear_gl_error();
@@ -613,11 +285,10 @@ void Create_Texture(char *filename)
                    format, GL_UNSIGNED_BYTE, image);
       check_gl_error("texture");
     }
-
-  free(image);
 }
 
-void resetProjection(void) {
+static void resetProjection(void) 
+{
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1, 1, -1, 1, 1, 100); 
@@ -626,12 +297,12 @@ void resetProjection(void) {
 }
 
 
-void GenerateQuad(void)
+static void GenerateQuad(pulsarstruct *gp)
 {
   int i;
 
-  quad_list = glGenLists(1);
-  glNewList(quad_list,GL_COMPILE);
+  gp->quad_list = glGenLists(1);
+  glNewList(gp->quad_list,GL_COMPILE);
 #if 1
   glBegin(GL_QUADS);
   glColor4f(1,0,0,.4); glNormal3f(0,0,1);  glTexCoord2f(0,0); glVertex2f(-1, -1);
@@ -648,38 +319,33 @@ void GenerateQuad(void)
   glEnd();
   glEndList();
 
-  quads = (struct quad *) malloc(sizeof(struct quad) * num_quads);
+  gp->quads = (struct quad *) malloc(sizeof(struct quad) * num_quads);
   for (i=0; i < num_quads; i++)
     {
-      quads[i].rx = 0.;
-      quads[i].ry = 0.;
-      quads[i].rz = 0.;
-      quads[i].tx = 0.;
-      quads[i].ty = 0.;
-      quads[i].tz = -10;
-
-      quads[i].drx = frand(5.0);
-      quads[i].dry = frand(5.0);
-      quads[i].drz = 0;
+      gp->quads[i].rx = 0.;
+      gp->quads[i].ry = 0.;
+      gp->quads[i].rz = 0.;
+      gp->quads[i].tx = 0.;
+      gp->quads[i].ty = 0.;
+      gp->quads[i].tz = -10;
+
+      gp->quads[i].drx = frand(5.0);
+      gp->quads[i].dry = frand(5.0);
+      gp->quads[i].drz = 0;
     }
 }
 
-void initializeGL(GLsizei width, GLsizei height) 
+static void initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) 
 {
+  pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)];
   GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 };
 
-  global_width=width;
-  global_height=height;
-
   glViewport( 0, 0, width, height ); 
   resetProjection();
 
   if (do_depth)
        glEnable(GL_DEPTH_TEST);
 
-  if (do_fps)
-       FPS_Setup();
-
   if (do_antialias) {
        do_blend = 1;
        glEnable(GL_LINE_SMOOTH);
@@ -714,35 +380,37 @@ void initializeGL(GLsizei width, GLsizei height)
        
 
   if (do_texture)
-         Create_Texture(which_image); 
+         Create_Texture(mi, which_image); 
 
-  GenerateQuad();
+  GenerateQuad(gp);
 }
-void drawQuads(void) {
+
+static void drawQuads(pulsarstruct *gp) 
+{
   int i;
   for (i=0; i < num_quads; i++)
     {
       glPushMatrix();
-      glTranslatef(quads[i].tx,0,0);
-      glTranslatef(0,quads[i].ty,0);
-      glTranslatef(0,0,quads[i].tz);
-      glRotatef(quads[i].rx, 1,0,0);
-      glRotatef(quads[i].ry, 0,1,0);
-      glRotatef(quads[i].rz, 0,0,1);
-      glCallList(quad_list);
+      glTranslatef(gp->quads[i].tx,0,0);
+      glTranslatef(0,gp->quads[i].ty,0);
+      glTranslatef(0,0,gp->quads[i].tz);
+      glRotatef(gp->quads[i].rx, 1,0,0);
+      glRotatef(gp->quads[i].ry, 0,1,0);
+      glRotatef(gp->quads[i].rz, 0,0,1);
+      glCallList(gp->quad_list);
       glPopMatrix();
 
-      quads[i].rx += quads[i].drx;
-      quads[i].ry += quads[i].dry;
-      quads[i].rz += quads[i].drz;
+      gp->quads[i].rx += gp->quads[i].drx;
+      gp->quads[i].ry += gp->quads[i].dry;
+      gp->quads[i].rz += gp->quads[i].drz;
 
     }
 }
 
-GLvoid drawScene(void
+static GLvoid drawScene(ModeInfo * mi
 {
-
-  checkError(__LINE__, __FILE__);
+  pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)];
+/*  check_gl_error ("drawScene"); */
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   /* we have to do this here because the FPS meter turns these 3 features off!! */
@@ -765,26 +433,24 @@ GLvoid drawScene(void)
   resetProjection();
 
   /* use XYZ scaling factors to change the size of the pulsar */
-  glScalef(scale_x, scale_y, scale_z);
-  drawQuads();
+  glScalef(gp->scale_x, gp->scale_y, gp->scale_z);
+  drawQuads(gp);
 
   /* update the scaling factors- cyclic */
-  scale_x = cos(frame/360.)*10.;
-  scale_y = sin(frame/360.)*10.;
-  scale_z = 1;
+  gp->scale_x = cos(gp->frame/360.)*10.;
+  gp->scale_y = sin(gp->frame/360.)*10.;
+  gp->scale_z = 1;
 
   /* increment frame-counter */
-  frame++;
+  gp->frame++;
 
-  if (do_fps)
-       DoFPS();
-  checkError(__LINE__, __FILE__);
+/*  check_gl_error ("drawScene"); */
 }
 
 
-void draw_screensaver(ModeInfo * mi)
+ENTRYPOINT void draw_pulsar(ModeInfo * mi)
 {
-  screensaverstruct *gp = &Screensaver[MI_SCREEN(mi)];
+  pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)];
   Display    *display = MI_DISPLAY(mi);
   Window      window = MI_WINDOW(mi);
 
@@ -792,35 +458,39 @@ void draw_screensaver(ModeInfo * mi)
        return;
 
   glXMakeCurrent(display, window, *(gp->glx_context));
-  drawScene();
+  drawScene(mi);
+  if (mi->fps_p) do_fps (mi);
   glXSwapBuffers(display, window);
 }
 
 /* Standard reshape function */
-static void
-reshape(int width, int height)
+ENTRYPOINT void
+reshape_pulsar(ModeInfo *mi, int width, int height)
 {
-  glViewport( 0, 0, global_width, global_height );
+  glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) );
   resetProjection();
 }
 
-void
-init_screensaver(ModeInfo * mi)
+ENTRYPOINT void
+init_pulsar(ModeInfo * mi)
 {
   int screen = MI_SCREEN(mi);
 
-  screensaverstruct *gp;
+  pulsarstruct *gp;
 
-  if (Screensaver == NULL) {
-       if ((Screensaver = (screensaverstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (screensaverstruct))) == NULL)
+  if (Pulsar == NULL) {
+       if ((Pulsar = (pulsarstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (pulsarstruct))) == NULL)
          return;
   }
-  gp = &Screensaver[screen];
+  gp = &Pulsar[screen];
 
   gp->window = MI_WINDOW(mi);
+
+  gp->scale_x = gp->scale_y = gp->scale_z = 1;
+
   if ((gp->glx_context = init_GL(mi)) != NULL) {
-       reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
-       initializeGL(MI_WIDTH(mi), MI_HEIGHT(mi));
+       reshape_pulsar(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+       initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
   } else {
        MI_CLEARWINDOW(mi);
   }
@@ -828,18 +498,19 @@ init_screensaver(ModeInfo * mi)
 
 
 /* all sorts of nice cleanup code should go here! */
-void release_screensaver(ModeInfo * mi)
+ENTRYPOINT void release_pulsar(ModeInfo * mi)
 {
   int screen;
-  if (Screensaver != NULL) {
+  if (Pulsar != NULL) {
        for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-/*       screensaverstruct *gp = &Screensaver[screen];*/
+         pulsarstruct *gp = &Pulsar[screen];
+      free(gp->quads);
        }
-       (void) free((void *) Screensaver);
-       Screensaver = NULL;
+       (void) free((void *) Pulsar);
+       Pulsar = NULL;
   }
-  free(quads);
   FreeAllGL(mi);
 }
 #endif
 
+XSCREENSAVER_MODULE ("Pulsar", pulsar)