OSDN Git Service

miniglx test programs
authorKeith Whitwell <keith@tungstengraphics.com>
Wed, 6 Aug 2003 17:47:15 +0000 (17:47 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 6 Aug 2003 17:47:15 +0000 (17:47 +0000)
progs/miniglx/Makefile [new file with mode: 0644]
progs/miniglx/glfbdevtest.c [new file with mode: 0644]
progs/miniglx/manytex.c [new file with mode: 0644]
progs/miniglx/miniglxsample.c [new file with mode: 0644]
progs/miniglx/miniglxtest.c [new file with mode: 0644]
progs/miniglx/sample_server.c [new file with mode: 0644]
progs/miniglx/sample_server2.c [new file with mode: 0644]
progs/miniglx/texline.c [new file with mode: 0644]

diff --git a/progs/miniglx/Makefile b/progs/miniglx/Makefile
new file mode 100644 (file)
index 0000000..48923eb
--- /dev/null
@@ -0,0 +1,30 @@
+
+# Simple makefile for compiling test programs on Linux
+# These programs aren't intended to be included with the normal
+# distro.  They're not too interesting but they're good for testing.
+
+
+CC = gcc
+CFLAGS = -g -I../include
+LIBS = -L../lib -lGL -lGLU -lglut -lm -Wl,-rpath,../lib
+
+PROGS = miniglxtest miniglxsample sample_server sample_server2 manytex texline
+
+
+##### RULES #####
+
+.SUFFIXES:
+.SUFFIXES: .c
+
+.c:
+       $(CC) $(CFLAGS) $< $(LIBS) -o $@
+
+
+##### TARGETS #####
+
+default: $(PROGS)
+
+clean:
+       rm -f $(PROGS)
+       rm -f *.o
+
diff --git a/progs/miniglx/glfbdevtest.c b/progs/miniglx/glfbdevtest.c
new file mode 100644 (file)
index 0000000..c82ca6e
--- /dev/null
@@ -0,0 +1,478 @@
+/* $Id: glfbdevtest.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * Test the GLFBDev interface.   Only tested with radeonfb driver!!!!
+ */
+
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <linux/fb.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <GL/glut.h>
+#include "GL/glfbdev.h"
+
+#define DEFAULT_DEPTH 8
+
+static struct fb_fix_screeninfo FixedInfo;
+static struct fb_var_screeninfo VarInfo, OrigVarInfo;
+static int DesiredDepth = 0;
+static int OriginalVT = -1;
+static int ConsoleFD = -1;
+static int FrameBufferFD = -1;
+static caddr_t FrameBuffer = (caddr_t) -1;
+static caddr_t MMIOAddress = (caddr_t) -1;
+
+
+static void
+print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
+{
+   static const char *visuals[] = {
+      "MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
+      "DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
+   };
+
+   printf("%s info -----------------------\n", s);
+   printf("id = %16s\n", fixed->id);
+   printf("smem_start = 0x%x\n", fixed->smem_start);
+   printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len);
+   printf("type = 0x%x\n", fixed->type);
+   printf("type_aux = 0x%x\n", fixed->type_aux);
+   printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]);
+   printf("xpanstep = %d\n", fixed->xpanstep);
+   printf("ypanstep = %d\n", fixed->ypanstep);
+   printf("ywrapstep = %d\n", fixed->ywrapstep);
+   printf("line_length = %d\n", fixed->line_length);
+   printf("mmio_start = 0x%x\n", fixed->mmio_start);
+   printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len);
+   printf("accel = 0x%x\n", fixed->accel);
+}
+
+
+static void
+print_var_info(const struct fb_var_screeninfo *var, const char *s)
+{
+   printf("%s info -----------------------\n", s);
+   printf("xres = %d\n", var->xres);
+   printf("yres = %d\n", var->yres);
+   printf("xres_virtual = %d\n", var->xres_virtual);
+   printf("yres_virtual = %d\n", var->yres_virtual);
+   printf("xoffset = %d\n", var->xoffset);
+   printf("yoffset = %d\n", var->yoffset);
+   printf("bits_per_pixel = %d\n", var->bits_per_pixel);
+   printf("grayscale = %d\n", var->grayscale);
+
+   printf("red.offset = %d  length = %d  msb_right = %d\n",
+          var->red.offset, var->red.length, var->red.msb_right);
+   printf("green.offset = %d  length = %d  msb_right = %d\n",
+          var->green.offset, var->green.length, var->green.msb_right);
+   printf("blue.offset = %d  length = %d  msb_right = %d\n",
+          var->blue.offset, var->blue.length, var->blue.msb_right);
+   printf("transp.offset = %d  length = %d  msb_right = %d\n",
+          var->transp.offset, var->transp.length, var->transp.msb_right);
+
+   printf("nonstd = %d\n", var->nonstd);
+   printf("activate = %d\n", var->activate);
+   printf("height = %d mm\n", var->height);
+   printf("width = %d mm\n", var->width);
+   printf("accel_flags = 0x%x\n", var->accel_flags);
+   printf("pixclock = %d\n", var->pixclock);
+   printf("left_margin = %d\n", var->left_margin);
+   printf("right_margin = %d\n", var->right_margin);
+   printf("upper_margin = %d\n", var->upper_margin);
+   printf("lower_margin = %d\n", var->lower_margin);
+   printf("hsync_len = %d\n", var->hsync_len);
+   printf("vsync_len = %d\n", var->vsync_len);
+   printf("sync = %d\n", var->sync);
+   printf("vmode = %d\n", var->vmode);
+}
+
+
+static void
+signal_handler(int signumber)
+{
+   signal(signumber, SIG_IGN); /* prevent recursion! */
+   fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
+   exit(1);
+}
+
+
+static void
+initialize_fbdev( void )
+{
+   char ttystr[1000];
+   int fd, vtnumber, ttyfd;
+   int sz;
+
+   if (geteuid()) {
+      fprintf(stderr, "error: you need to be root\n");
+      exit(1);
+   }
+
+#if 1
+   /* open the framebuffer device */
+   FrameBufferFD = open("/dev/fb0", O_RDWR);
+   if (FrameBufferFD < 0) {
+      fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
+      exit(1);
+   }
+#endif
+
+   /* open /dev/tty0 and get the vt number */
+   if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
+      fprintf(stderr, "error opening /dev/tty0\n");
+      exit(1);
+   }
+   if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
+      fprintf(stderr, "error: couldn't get a free vt\n");
+      exit(1);
+   }
+   close(fd);
+
+   /* open the console tty */
+   sprintf(ttystr, "/dev/tty%d", vtnumber);  /* /dev/tty1-64 */
+   ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
+   if (ConsoleFD < 0) {
+      fprintf(stderr, "error couldn't open console fd\n");
+      exit(1);
+   }
+
+   /* save current vt number */
+   {
+      struct vt_stat vts;
+      if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
+         OriginalVT = vts.v_active;
+   }
+
+   /* disconnect from controlling tty */
+   ttyfd = open("/dev/tty", O_RDWR);
+   if (ttyfd >= 0) {
+      ioctl(ttyfd, TIOCNOTTY, 0);
+      close(ttyfd);
+   }
+
+   /* some magic to restore the vt when we exit */
+   {
+      struct vt_mode vt;
+      if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
+         printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
+      if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
+         printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
+
+      if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
+         fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
+         exit(1);
+      }
+
+      vt.mode = VT_PROCESS;
+      vt.relsig = SIGUSR1;
+      vt.acqsig = SIGUSR1;
+      if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
+         fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
+                 strerror(errno));
+         exit(1);
+      }
+   }
+
+   /* go into graphics mode */
+   if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
+      fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
+              strerror(errno));
+      exit(1);
+   }
+
+
+#if 0
+   /* open the framebuffer device */
+   FrameBufferFD = open("/dev/fb0", O_RDWR);
+   if (FrameBufferFD < 0) {
+      fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
+      exit(1);
+   }
+#endif
+
+   /* Get the fixed screen info */
+   if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
+              strerror(errno));
+      exit(1);
+   }
+
+   print_fixed_info(&FixedInfo, "Fixed");
+
+
+  /* get the variable screen info */
+   if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
+              strerror(errno));
+      exit(1);
+   }
+
+   print_var_info(&OrigVarInfo, "Orig Var");
+
+   /* operate on a copy */
+   VarInfo = OrigVarInfo;
+
+   /* set the depth, resolution, etc */
+   DesiredDepth = 32;
+   if (DesiredDepth)
+      VarInfo.bits_per_pixel = DesiredDepth;
+
+   if (VarInfo.bits_per_pixel == 16) {
+      VarInfo.red.offset = 11;
+      VarInfo.green.offset = 5;
+      VarInfo.blue.offset = 0;
+      VarInfo.red.length = 5;
+      VarInfo.green.length = 6;
+      VarInfo.blue.length = 5;
+      VarInfo.transp.offset = 0;
+      VarInfo.transp.length = 0;
+   }
+   else if (VarInfo.bits_per_pixel == 32) {
+      VarInfo.red.offset = 16;
+      VarInfo.green.offset = 8;
+      VarInfo.blue.offset = 0;
+      VarInfo.transp.offset = 24;
+      VarInfo.red.length = 8;
+      VarInfo.green.length = 8;
+      VarInfo.blue.length = 8;
+      VarInfo.transp.length = 8;
+   }
+   /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
+   VarInfo.xres_virtual = VarInfo.xres = 1280;
+   VarInfo.yres_virtual = VarInfo.yres = 1024;
+   VarInfo.pixclock = 7408;
+   VarInfo.left_margin = 248;
+   VarInfo.right_margin = 16;
+   VarInfo.upper_margin = 38;
+   VarInfo.lower_margin = 1;
+   VarInfo.hsync_len = 144;
+   VarInfo.vsync_len = 3;
+
+   VarInfo.xoffset = 0;
+   VarInfo.yoffset = 0;
+   VarInfo.nonstd = 0;
+   VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
+
+   /* set new variable screen info */
+   if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
+      fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
+              strerror(errno));
+      exit(1);
+   }
+
+   print_var_info(&VarInfo, "New Var");
+
+   if (FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
+       FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
+      fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
+      exit(1);
+   }
+
+   /* initialize colormap */
+   if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
+      struct fb_cmap cmap;
+      unsigned short red[256], green[256], blue[256];
+      int i;
+
+      /* we're assuming 256 entries here */
+      printf("initializing directcolor colormap\n");
+      cmap.start = 0;
+      cmap.len = 256;
+      cmap.red   = red;
+      cmap.green = green;
+      cmap.blue  = blue;
+      cmap.transp = NULL;
+      for (i = 0; i < cmap.len; i++) {
+         red[i] = green[i] = blue[i] = (i << 8) | i;
+      }
+      if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
+         fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
+      }
+   }
+
+   /*
+    * fbdev says the frame buffer is at offset zero, and the mmio region
+    * is immediately after.
+    */
+
+   /* mmap the framebuffer into our address space */
+   FrameBuffer = (caddr_t) mmap(0, /* start */
+                                FixedInfo.smem_len, /* bytes */
+                                PROT_READ | PROT_WRITE, /* prot */
+                                MAP_SHARED, /* flags */
+                                FrameBufferFD, /* fd */
+                                0 /* offset */);
+   if (FrameBuffer == (caddr_t) - 1) {
+      fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
+              strerror(errno));
+      exit(1);
+   }
+   printf("FrameBuffer = %p\n", FrameBuffer);
+
+#if 1
+   /* mmap the MMIO region into our address space */
+   MMIOAddress = (caddr_t) mmap(0, /* start */
+                                FixedInfo.mmio_len, /* bytes */
+                                PROT_READ | PROT_WRITE, /* prot */
+                                MAP_SHARED, /* flags */
+                                FrameBufferFD, /* fd */
+                                FixedInfo.smem_len /* offset */);
+   if (MMIOAddress == (caddr_t) - 1) {
+      fprintf(stderr, "error: unable to mmap mmio region: %s\n",
+              strerror(errno));
+   }
+   printf("MMIOAddress = %p\n", MMIOAddress);
+
+   /* try out some simple MMIO register reads */
+   if (1)
+   {
+      typedef unsigned int CARD32;
+      typedef unsigned char CARD8;
+#define RADEON_CONFIG_MEMSIZE               0x00f8
+#define RADEON_MEM_SDRAM_MODE_REG           0x0158
+#define MMIO_IN32(base, offset) \
+       *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
+#define INREG(addr)         MMIO_IN32(MMIOAddress, addr)
+      int sz, type;
+      const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"};
+      sz = INREG(RADEON_CONFIG_MEMSIZE);
+      type = INREG(RADEON_MEM_SDRAM_MODE_REG);
+      printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024);
+      printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
+             type >> 30, typeStr[type>>30]);
+   }
+#endif
+
+}
+
+
+static void
+shutdown_fbdev( void )
+{
+   struct vt_mode VT;
+
+   printf("cleaning up...\n");
+   /* restore original variable screen info */
+   if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
+      fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
+              strerror(errno));
+      exit(1);
+   }
+
+   munmap(MMIOAddress, FixedInfo.mmio_len);
+   munmap(FrameBuffer, FixedInfo.smem_len);
+   close(FrameBufferFD);
+
+   /* restore text mode */
+   ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
+
+   /* set vt */
+   if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
+      VT.mode = VT_AUTO;
+      ioctl(ConsoleFD, VT_SETMODE, &VT);
+   }
+
+   /* restore original vt */
+   if (OriginalVT >= 0) {
+      ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
+      OriginalVT = -1;
+   }
+
+   close(ConsoleFD);
+}
+
+
+static void
+gltest( void )
+{
+   static const int attribs[] = {
+      GLFBDEV_DOUBLE_BUFFER,
+      GLFBDEV_DEPTH_SIZE, 16,
+      GLFBDEV_NONE
+   };
+   GLFBDevContextPtr ctx;
+   GLFBDevBufferPtr buf;
+   GLFBDevVisualPtr vis;
+   int bytes, r, g, b, a;
+   float ang;
+
+   printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
+   printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
+
+   /* framebuffer size */
+   bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
+
+   vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
+   assert(vis);
+
+   buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
+   assert(buf);
+
+   ctx = glFBDevCreateContext( vis, NULL );
+   assert(buf);
+
+   b = glFBDevMakeCurrent( ctx, buf, buf );
+   assert(b);
+
+   /*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
+   glGetIntegerv(GL_RED_BITS, &r);
+   glGetIntegerv(GL_GREEN_BITS, &g);
+   glGetIntegerv(GL_BLUE_BITS, &b);
+   glGetIntegerv(GL_ALPHA_BITS, &a);
+   printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
+          r, g, b, a);
+
+   glClearColor(0.5, 0.5, 1.0, 0);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-1, 1, -1, 1, 2, 30);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0, 0, -15);
+   glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   for (ang = 0; ang <= 180; ang += 15) {
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glPushMatrix();
+      glRotatef(ang, 1, 0, 0);
+      glutSolidTorus(1, 3, 40, 20);
+      glPopMatrix();
+      glFBDevSwapBuffers(buf);
+   }
+
+   /* clean up */
+   b = glFBDevMakeCurrent( NULL, NULL, NULL);
+   assert(b);
+
+   glFBDevDestroyContext(ctx);
+   glFBDevDestroyBuffer(buf);
+   glFBDevDestroyVisual(vis);
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+   signal(SIGUSR1, signal_handler);  /* exit if someone tries a vt switch */
+   signal(SIGSEGV, signal_handler);  /* catch segfaults */
+
+   initialize_fbdev();
+   gltest();
+   shutdown_fbdev();
+
+   return 0;
+}
diff --git a/progs/miniglx/manytex.c b/progs/miniglx/manytex.c
new file mode 100644 (file)
index 0000000..3801963
--- /dev/null
@@ -0,0 +1,381 @@
+/* $Id: manytex.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * test handling of many texture maps
+ * Also tests texture priority and residency.
+ *
+ * Brian Paul
+ * August 2, 2000
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+
+
+static GLint NumTextures = 20;
+static GLuint *TextureID = NULL;
+static GLint *TextureWidth = NULL, *TextureHeight = NULL;
+static GLboolean *TextureResidency = NULL;
+static GLint TexWidth = 128, TexHeight = 128;
+static GLfloat Zrot = 0;
+static GLboolean Anim = GL_TRUE;
+static GLint WinWidth = 500, WinHeight = 400;
+static GLboolean MipMap = GL_FALSE;
+static GLboolean LinearFilter = GL_FALSE;
+static GLboolean RandomSize = GL_FALSE;
+static GLint Rows, Columns;
+static GLint LowPriorityCount = 0;
+
+
+static void Idle( void )
+{
+   Zrot += 1.0;
+   glutPostRedisplay();
+}
+
+
+static void Display( void )
+{
+   GLfloat spacing = WinWidth / Columns;
+   GLfloat size = spacing * 0.4;
+   GLint i;
+
+   /* test residency */
+   if (0)
+   {
+      GLboolean b;
+      GLint i, resident;
+      b = glAreTexturesResident(NumTextures, TextureID, TextureResidency);
+      if (b) {
+         printf("all resident\n");
+      }
+      else {
+         resident = 0;
+         for (i = 0; i < NumTextures; i++) {
+            if (TextureResidency[i]) {
+               resident++;
+            }
+         }
+         printf("%d of %d texture resident\n", resident, NumTextures);
+      }
+   }
+
+   /* render the textured quads */
+   glClear( GL_COLOR_BUFFER_BIT );
+   for (i = 0; i < NumTextures; i++) {
+      GLint row = i / Columns;
+      GLint col = i % Columns;
+      GLfloat x = col * spacing + spacing * 0.5;
+      GLfloat y = row * spacing + spacing * 0.5;
+
+      GLfloat maxDim = (TextureWidth[i] > TextureHeight[i])
+         ? TextureWidth[i] : TextureHeight[i];
+      GLfloat w = TextureWidth[i] / maxDim;
+      GLfloat h = TextureHeight[i] / maxDim;
+
+      glPushMatrix();
+         glTranslatef(x, y, 0.0);
+         glRotatef(Zrot, 0, 0, 1);
+         glScalef(size, size, 1);
+
+         glBindTexture(GL_TEXTURE_2D, TextureID[i]);
+         glBegin(GL_POLYGON);
+#if 0
+         glTexCoord2f(0, 0);  glVertex2f(-1, -1);
+         glTexCoord2f(1, 0);  glVertex2f( 1, -1);
+         glTexCoord2f(1, 1);  glVertex2f( 1,  1);
+         glTexCoord2f(0, 1);  glVertex2f(-1,  1);
+#else
+         glTexCoord2f(0, 0);  glVertex2f(-w, -h);
+         glTexCoord2f(1, 0);  glVertex2f( w, -h);
+         glTexCoord2f(1, 1);  glVertex2f( w,  h);
+         glTexCoord2f(0, 1);  glVertex2f(-w,  h);
+#endif
+         glEnd();
+      glPopMatrix();
+   }
+
+   glutSwapBuffers();
+}
+
+
+static void Reshape( int width, int height )
+{
+   WinWidth = width;
+   WinHeight = height;
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho(0, width, 0, height, -1, 1);
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+}
+
+
+/*
+ * Return a random int in [min, max].
+ */
+static int RandomInt(int min, int max)
+{
+   int i = rand();
+   int j = i % (max - min + 1);
+   return min + j;
+}
+
+
+
+static void Init( void )
+{
+   GLint i;
+
+   if (RandomSize) {
+      printf("Creating %d %s random-size textures, ", NumTextures,
+             MipMap ? "Mipmapped" : "non-Mipmapped");
+   }
+   else {
+      printf("Creating %d %s %d x %d textures, ", NumTextures,
+             MipMap ? "Mipmapped" : "non-Mipmapped",
+             TexWidth, TexHeight);
+   }
+
+   if (LinearFilter) {
+      printf("bilinear filtering\n");
+   }
+   else {
+      printf("nearest filtering\n");
+   }
+
+
+   /* compute number of rows and columns of rects */
+   {
+      GLfloat area = (GLfloat) (WinWidth * WinHeight) / (GLfloat) NumTextures;
+      GLfloat edgeLen = sqrt(area);
+
+      Columns = WinWidth / edgeLen;
+      Rows = (NumTextures + Columns - 1) / Columns;
+      printf("Rows: %d  Cols: %d\n", Rows, Columns);
+   }
+
+
+   if (!TextureID) {
+      TextureID = (GLuint *) malloc(sizeof(GLuint) * NumTextures);
+      assert(TextureID);
+      glGenTextures(NumTextures, TextureID);
+   }
+
+   if (!TextureResidency) {
+      TextureResidency = (GLboolean *) malloc(sizeof(GLboolean) * NumTextures);
+      assert(TextureResidency);
+   }
+
+   if (!TextureWidth) {
+      TextureWidth = (GLint *) malloc(sizeof(GLint) * NumTextures);
+      assert(TextureWidth);
+   }
+   if (!TextureHeight) {
+      TextureHeight = (GLint *) malloc(sizeof(GLint) * NumTextures);
+      assert(TextureHeight);
+   }
+
+   for (i = 0; i < NumTextures; i++) {
+      GLubyte color[4];
+      GLubyte *texImage;
+      GLint j, row, col;
+
+      row = i / Columns;
+      col = i % Columns;
+
+      glBindTexture(GL_TEXTURE_2D, TextureID[i]);
+
+      if (i < LowPriorityCount)
+         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F);
+
+      if (RandomSize) {
+#if 0
+         int k = (glutGet(GLUT_ELAPSED_TIME) % 7) + 2;
+         TexWidth  = 1 << k;
+         TexHeight = 1 << k;
+#else
+         TexWidth = 1 << RandomInt(2, 7);
+         TexHeight = 1 << RandomInt(2, 7);
+         printf("Random size of %3d: %d x %d\n", i, TexWidth, TexHeight);
+#endif
+      }
+
+      TextureWidth[i] = TexWidth;
+      TextureHeight[i] = TexHeight;
+
+      texImage = (GLubyte*) malloc(4 * TexWidth * TexHeight * sizeof(GLubyte));
+      assert(texImage);
+
+      /* determine texture color */
+      color[0] = (GLint) (255.0 * ((float) col / (Columns - 1)));
+      color[1] = 127;
+      color[2] = (GLint) (255.0 * ((float) row / (Rows - 1)));
+      color[3] = 255;
+
+      /* fill in solid-colored teximage */
+      for (j = 0; j < TexWidth * TexHeight; j++) {
+         texImage[j*4+0] = color[0];
+         texImage[j*4+1] = color[1];
+         texImage[j*4+2] = color[2];
+         texImage[j*4+3] = color[3];
+     }
+
+      if (MipMap) {
+         GLint level = 0;
+         GLint w = TexWidth, h = TexHeight;
+         while (1) {
+            glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0,
+                         GL_RGBA, GL_UNSIGNED_BYTE, texImage);
+            if (w == 1 && h == 1)
+               break;
+            if (w > 1)
+               w /= 2;
+            if (h > 1)
+               h /= 2;
+            level++;
+            /*printf("%d: %d x %d\n", level, w, h);*/
+         }
+         if (LinearFilter) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                            GL_LINEAR_MIPMAP_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+         }
+         else {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                            GL_NEAREST_MIPMAP_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+         }
+      }
+      else {
+         /* Set corners to white */
+         int k = 0;
+         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
+         k = (TexWidth - 1) * 4;
+         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
+         k = (TexWidth * TexHeight - TexWidth) * 4;
+         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
+         k = (TexWidth * TexHeight - 1) * 4;
+         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
+
+         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
+                      GL_RGBA, GL_UNSIGNED_BYTE, texImage);
+         if (LinearFilter) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+         }
+         else {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+         }
+      }
+
+      free(texImage);
+   }
+
+   glEnable(GL_TEXTURE_2D);
+}
+
+
+static void Key( unsigned char key, int x, int y )
+{
+   const GLfloat step = 3.0;
+   (void) x;
+   (void) y;
+   switch (key) {
+      case 'a':
+         Anim = !Anim;
+         if (Anim)
+            glutIdleFunc(Idle);
+         else
+            glutIdleFunc(NULL);
+         break;
+      case 's':
+         Idle();
+         break;
+      case 'z':
+         Zrot -= step;
+         break;
+      case 'Z':
+         Zrot += step;
+         break;
+      case ' ':
+         Init();
+         break;
+      case 27:
+         exit(0);
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+int main( int argc, char *argv[] )
+{
+   GLint i;
+
+   glutInit( &argc, argv );
+   glutInitWindowPosition( 0, 0 );
+   glutInitWindowSize( WinWidth, WinHeight );
+   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+   glutCreateWindow(argv[0]);
+   glutReshapeFunc( Reshape );
+   glutKeyboardFunc( Key );
+   glutDisplayFunc( Display );
+   if (Anim)
+      glutIdleFunc(Idle);
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-n") == 0) {
+         NumTextures = atoi(argv[i+1]);
+         if (NumTextures <= 0) {
+            printf("Error, bad number of textures\n");
+            return 1;
+         }
+         i++;
+      }
+      else if (strcmp(argv[i], "-mipmap") == 0) {
+         MipMap = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-linear") == 0) {
+         LinearFilter = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-size") == 0) {
+         TexWidth = atoi(argv[i+1]);
+         TexHeight = atoi(argv[i+2]);
+         assert(TexWidth >= 1);
+         assert(TexHeight >= 1);
+         i += 2;
+      }
+      else if (strcmp(argv[i], "-randomsize") == 0) {
+         RandomSize = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-lowpri") == 0) {
+         LowPriorityCount = atoi(argv[i+1]);
+         i++;
+      }
+      else {
+         printf("Usage:\n");
+         printf("  manytex [options]\n");
+         printf("Options:\n");
+         printf("  -n <number of texture objects>\n");
+         printf("  -size <width> <height>  - specify texture size\n");
+         printf("  -randomsize  - use random size textures\n");
+         printf("  -mipmap      - generate mipmaps\n");
+         printf("  -linear      - use linear filtering instead of nearest\n");
+         printf("  -lowpri <n>  - Set lower priority on <n> textures\n");
+         return 0;
+      }
+   }
+
+   Init();
+
+   glutMainLoop();
+
+   return 0;
+}
diff --git a/progs/miniglx/miniglxsample.c b/progs/miniglx/miniglxsample.c
new file mode 100644 (file)
index 0000000..bea845c
--- /dev/null
@@ -0,0 +1,127 @@
+
+#define USE_MINIGLX 1  /* 1 = use Mini GLX, 0 = use Xlib/GLX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/gl.h>
+
+#if USE_MINIGLX
+#include <GL/miniglx.h>
+#else
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#endif
+
+static void _subset_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+   glBegin( GL_QUADS );
+   glVertex2f( x1, y1 );
+   glVertex2f( x2, y1 );
+   glVertex2f( x2, y2 );
+   glVertex2f( x1, y2 );
+   glEnd();
+}
+
+
+/*
+ * Create a simple double-buffered RGBA window.
+ */
+static Window
+MakeWindow(Display * dpy, unsigned int width, unsigned int height)
+{
+   int visAttributes[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None
+   };
+   XSetWindowAttributes attr;
+   unsigned long attrMask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   root = RootWindow(dpy, 0);
+
+   /* Choose GLX visual / pixel format */
+   visinfo = glXChooseVisual(dpy, 0, visAttributes);
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\n");
+      exit(1);
+   }
+
+   /* Create the window */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attrMask = CWBackPixel | CWBorderPixel | CWColormap;
+   win = XCreateWindow(dpy, root, 0, 0, width, height,
+                      0, visinfo->depth, InputOutput,
+                      visinfo->visual, attrMask, &attr);
+   if (!win) {
+      printf("Error: XCreateWindow failed\n");
+      exit(1);
+   }
+
+   /* Display the window */
+   XMapWindow(dpy, win);
+
+   /* Create GLX rendering context */
+   ctx = glXCreateContext(dpy, visinfo, NULL, True);
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   /* Bind the rendering context and window */
+   glXMakeCurrent(dpy, win, ctx);
+
+   glViewport(0, 0, width, height);
+
+   return win;
+}
+
+
+/*
+ * Draw a few frames of a rotating square.
+ */
+static void
+DrawFrames(Display * dpy, Window win)
+{
+   int angle;
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   for (angle = 0; angle < 360; angle += 10) {
+      glClear(GL_COLOR_BUFFER_BIT);
+      glColor3f(1.0, 1.0, 0.0);
+      glPushMatrix();
+      glRotatef(angle, 0, 0, 1);
+      _subset_Rectf(-0.8, -0.8, 0.8, 0.8);
+      glPopMatrix();
+      glXSwapBuffers(dpy, win);
+      sleep(1);
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy) {
+      printf("Error: XOpenDisplay failed\n");
+      return 1;
+   }
+
+   win = MakeWindow(dpy, 300, 300);
+
+   DrawFrames(dpy, win);
+
+   return 0;
+}
diff --git a/progs/miniglx/miniglxtest.c b/progs/miniglx/miniglxtest.c
new file mode 100644 (file)
index 0000000..911bf4c
--- /dev/null
@@ -0,0 +1,194 @@
+/* $Id: miniglxtest.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * Test the mini GLX interface.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/gl.h>
+#define USE_MINI_GLX 1
+#if USE_MINI_GLX
+#include <GL/miniglx.h>
+#else
+#include <GL/glx.h>
+#endif
+
+#define FRONTBUFFER 1
+#define NR          6
+#define DO_SLEEPS   1
+#define NR_DISPLAYS 2
+
+GLXContext ctx;
+
+
+static void _subset_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+   glBegin( GL_QUADS );
+   glVertex2f( x1, y1 );
+   glVertex2f( x2, y1 );
+   glVertex2f( x2, y2 );
+   glVertex2f( x1, y2 );
+   glEnd();
+}
+
+
+
+static void redraw( Display *dpy, Window w, int rot )
+{
+   printf("Redraw event\n");
+
+#if FRONTBUFFER
+    glDrawBuffer( GL_FRONT ); 
+#else
+/*     glDrawBuffer( GL_BACK );    */
+#endif
+
+   glClearColor( rand()/(float)RAND_MAX, 
+                rand()/(float)RAND_MAX, 
+                rand()/(float)RAND_MAX,
+                1);
+
+   glClear( GL_COLOR_BUFFER_BIT ); 
+
+#if 1
+   glColor3f( rand()/(float)RAND_MAX, 
+             rand()/(float)RAND_MAX, 
+             rand()/(float)RAND_MAX );
+   glPushMatrix();
+   glRotatef(rot, 0, 0, 1);
+   glScalef(.5, .5, .5);
+   _subset_Rectf( -1, -1, 1, 1 );
+   glPopMatrix();
+#endif
+
+#if FRONTBUFFER
+   glFlush();
+#else
+   glXSwapBuffers( dpy, w ); 
+#endif
+   glFinish();
+}
+
+
+static Window make_rgb_db_window( Display *dpy,
+                                 unsigned int width, unsigned int height )
+{
+   int attrib[] = { GLX_RGBA,
+                   GLX_RED_SIZE, 1,
+                   GLX_GREEN_SIZE, 1,
+                   GLX_BLUE_SIZE, 1,
+#if !FRONT_BUFFER
+                   GLX_DOUBLEBUFFER, 
+#endif
+                   None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   XVisualInfo *visinfo;
+
+   scrnum = 0;
+   root = RootWindow( dpy, scrnum );
+
+   if (!(visinfo = glXChooseVisual( dpy, scrnum, attrib ))) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\n");
+      exit(1);
+   }
+
+   if(!(ctx = glXCreateContext( dpy, visinfo, NULL, True ))) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+                       0, visinfo->depth, InputOutput,
+                       visinfo->visual, mask, &attr );
+   if (!win) {
+      printf("Error: XCreateWindow failed\n");
+      exit(1);
+   }
+
+   glXMakeCurrent( dpy, win, ctx );
+
+   glViewport(0, 0, width, height);
+
+   return win;
+}
+
+
+static void event_loop( Display *dpy, Window win )
+{
+   int i;
+
+   printf("Hang on... drawing %d frames\n", NR);
+   for (i = 0; i < NR; i++) {
+      redraw( dpy, win, i*10 );
+      if (DO_SLEEPS) {
+        printf("sleep(1)\n");   
+        sleep(1);  
+      }
+   }
+}
+
+
+int foo( )
+{
+   Display *dpy;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy) {
+      printf("Error: XOpenDisplay failed\n");
+      return 1;
+   }
+
+   win = make_rgb_db_window( dpy, 800, 600);
+
+   srand(getpid());
+
+   glShadeModel( GL_FLAT );
+   glClearColor( 0.5, 0.5, 0.5, 1.0 );
+
+   XMapWindow( dpy, win );
+
+   {
+      XEvent e;
+      while (1) {
+        XNextEvent( dpy, &e );
+        if (e.type == MapNotify && e.xmap.window == win) {
+           break;
+        }
+      }
+   }
+
+   event_loop( dpy, win );
+
+   glXDestroyContext( dpy, ctx );
+   XDestroyWindow( dpy, win );
+
+   XCloseDisplay( dpy );
+
+   return 0;
+}
+
+
+int main()
+{
+   int i;
+   for (i = 0 ; i < NR_DISPLAYS ; i++) {
+      if (foo() != 0)
+        break;
+   }
+
+   return 0;
+}
diff --git a/progs/miniglx/sample_server.c b/progs/miniglx/sample_server.c
new file mode 100644 (file)
index 0000000..039c04f
--- /dev/null
@@ -0,0 +1,112 @@
+/* $Id: sample_server.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * Sample server that just keeps first available window mapped.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/gl.h>
+#include <GL/miniglx.h>
+
+struct client {
+   struct client *next;
+   Window windowid;
+   int mappable;
+};
+
+struct client *clients = 0, *mapped_client = 0;
+
+
+static struct client *find_client( Window id )
+{
+   struct client *c;
+
+   for (c = clients ; c ; c = c->next)
+      if (c->windowid == id)
+        return c;
+
+   return 0;
+}
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   XEvent ev;
+
+   dpy = __miniglx_StartServer(NULL);
+   if (!dpy) {
+      fprintf(stderr, "Error: __miniglx_StartServer failed\n");
+      return 1;
+   }
+
+   while (XNextEvent( dpy, &ev )) {
+      struct client *c;
+
+      switch (ev.type) {
+      case MapRequest:
+        fprintf(stderr, "MapRequest\n");
+        c = find_client(ev.xmaprequest.window);
+        if (!c) break;
+        c->mappable = True;
+        break;
+
+      case UnmapNotify:
+        fprintf(stderr, "UnmapNotify\n");
+        c = find_client(ev.xunmap.window);
+        if (!c) break;
+        c->mappable = False;
+        if (c == mapped_client)
+           mapped_client = 0;
+        break;
+
+      case CreateNotify: 
+        fprintf(stderr, "CreateNotify\n");
+        c = malloc(sizeof(*c));
+        c->next = clients;
+        c->windowid = ev.xcreatewindow.window;
+        c->mappable = False;
+        clients = c;
+        break;
+
+      case DestroyNotify:
+        fprintf(stderr, "DestroyNotify\n");
+        c = find_client(ev.xdestroywindow.window);
+        if (!c) break;
+        if (c == clients)
+           clients = c->next;
+        else {
+           struct client *t;
+           for (t = clients ; t->next != c ; t = t->next)
+              ;
+           t->next = c->next;
+        }
+
+        if (c == mapped_client) 
+           mapped_client = 0;
+
+        free(c);
+        break;
+
+      default:
+        break;
+      }
+
+      /* Search for first mappable client if none already mapped.
+       */
+      if (!mapped_client) {
+        for (c = clients ; c ; c = c->next) {
+           if (c->mappable) {
+              XMapWindow( dpy, c->windowid );
+              mapped_client = c;
+              break;
+           }
+        }
+      }
+   }
+
+   XCloseDisplay( dpy );
+
+   return 0;
+}
diff --git a/progs/miniglx/sample_server2.c b/progs/miniglx/sample_server2.c
new file mode 100644 (file)
index 0000000..3508a21
--- /dev/null
@@ -0,0 +1,227 @@
+/* $Id: sample_server2.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * Sample server that just keeps first available window mapped.
+ * 
+ * It also reads and echos anything that happens on stdin as an
+ * example of tracking events from sources other than miniglx clients.
+ * 
+ * It reads & writes without blocking, so that eg. piping a lot of
+ * text to stdin and then hitting 'ctrl-S' on the output stream won't
+ * cause it to stop handling miniglx events.
+ *
+ * See select_tut in the linux manual pages for a good overview of the 
+ * select(2) system call.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/gl.h>
+#include <GL/miniglx.h>
+#include <errno.h>
+#include <assert.h>
+
+struct client {
+   struct client *next;
+   Window windowid;
+   int mappable;
+};
+
+struct client *clients = 0, *mapped_client = 0;
+
+#define BUFSZ 4096
+char rbuf[BUFSZ];
+int rbuf_count;
+
+
+static struct client *find_client( Window id )
+{
+   struct client *c;
+
+   for (c = clients ; c ; c = c->next)
+      if (c->windowid == id)
+        return c;
+
+   return 0;
+}
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   XEvent ev;
+   int autostart = 0;
+
+   if (argc == 2 && strcmp(argv[1], "-autostart") == 0)
+      autostart = 1;
+
+   dpy = __miniglx_StartServer(NULL);
+   if (!dpy) {
+      fprintf(stderr, "Error: __miniglx_StartServer failed\n");
+      return 1;
+   }
+
+   /* How is vt switching communicated through the XNextEvent interface?
+    */
+   while (1) {
+      int r, n;
+      struct timeval tv;
+      fd_set rfds, wfds;
+      int bored = 0;
+
+      FD_ZERO(&rfds);
+      FD_ZERO(&wfds);
+      tv.tv_sec = 1;
+      tv.tv_usec = 0;
+
+      if (rbuf_count) {
+        FD_SET( 1, &wfds );    /* notify when we can write out buffer */
+        n = 1;
+      }
+      else {
+        FD_SET( 0, &rfds );    /* else notify when new data to read */
+        n = 0;
+      }
+
+      /* __miniglx_Select waits until any of these file groups becomes
+       * readable/writable/etc (like regular select), until timeout
+       * expires (like regular select), until a signal is received
+       * (like regular select) or until an event is available for
+       * XCheckMaskEvent().
+       */
+      r = __miniglx_Select( dpy, n+1, &rfds, &wfds, 0, &tv );
+
+      /* This can happen if select() is interrupted by a signal:
+       */
+      if (r < 0 && errno != EINTR && errno != EAGAIN) {
+        perror ("select()");
+        exit (1);
+      }
+
+      if (tv.tv_sec == 0 && tv.tv_usec == 0)
+        bored = 1;
+
+      /* Check and handle events on our local file descriptors
+       */
+      if (FD_ISSET( 0, &rfds )) {
+        /* Something on stdin */        
+        assert(rbuf_count == 0);
+        r = read(0, rbuf, BUFSZ);       
+        if (r < 1) {
+           perror("read");     
+           abort();
+        }
+        rbuf_count = r;
+      }
+
+      if (FD_ISSET( 1, &wfds )) {
+        /* Can write to stdout */
+        assert(rbuf_count > 0);
+        r = write(1, rbuf, rbuf_count);         
+        if (r < 1) {
+           perror("write");
+           abort();
+        }
+        rbuf_count -= r;
+        if (rbuf_count) 
+           memmove(rbuf + r, rbuf, rbuf_count);
+      }
+
+
+      /* Check and handle events generated by miniglx:
+       */
+      while (XCheckMaskEvent( dpy, ~0, &ev )) {
+        struct client *c;
+        bored = 0;
+
+        fprintf(stderr, "Received event %d\n", ev.type);
+
+        switch (ev.type) {
+        case CreateNotify: 
+           fprintf(stderr, "CreateNotify -- new client\n");
+           c = malloc(sizeof(*c));
+           c->next = clients;
+           c->windowid = ev.xcreatewindow.window;
+           c->mappable = False;
+           clients = c;
+           break;
+
+        case DestroyNotify:
+           fprintf(stderr, "DestroyNotify\n");
+           c = find_client(ev.xdestroywindow.window);
+           if (!c) break;
+           if (c == clients)
+              clients = c->next;
+           else {
+              struct client *t;
+              for (t = clients ; t->next != c ; t = t->next)
+                 ;
+              t->next = c->next;
+           }
+
+           if (c == mapped_client) 
+              mapped_client = 0;
+
+           free(c);
+           break;
+
+        case MapRequest:
+           fprintf(stderr, "MapRequest\n");
+           c = find_client(ev.xmaprequest.window);
+           if (!c) break;
+           c->mappable = True;
+           break;
+
+        case UnmapNotify:
+           fprintf(stderr, "UnmapNotify\n");
+           c = find_client(ev.xunmap.window);
+           if (!c) break;
+           c->mappable = False;
+           if (c == mapped_client)
+              mapped_client = 0;
+           break;
+
+        default:
+           break;
+        }
+      }
+
+
+      /* Search for first mappable client if none already mapped.
+       */
+      if (!mapped_client) {
+        struct client *c;
+        for (c = clients ; c ; c = c->next) {
+           if (c->mappable) {
+              XMapWindow( dpy, c->windowid );
+              mapped_client = c;
+              break;
+           }
+        }
+        if (!clients && autostart) {
+           system("nohup ./texline &");
+           system("nohup ./manytex &");
+        }
+      }
+      else if (bored) {
+        struct client *c;
+        /* bored of mapped client now, let's try & find another one */
+        for (c = mapped_client->next ; c && !c->mappable ; c = c->next)
+           ;
+        if (!c)
+           for (c = clients ; c && !c->mappable ; c = c->next)
+              ;
+        if (c && c != mapped_client) {
+           XUnmapWindow( dpy, mapped_client->windowid );
+           XMapWindow( dpy, c->windowid );
+           mapped_client = c;
+        }
+        else 
+           fprintf(stderr, "I'm bored!\n");
+      }
+   }
+
+   XCloseDisplay( dpy );
+
+   return 0;
+}
diff --git a/progs/miniglx/texline.c b/progs/miniglx/texline.c
new file mode 100644 (file)
index 0000000..d2a97d2
--- /dev/null
@@ -0,0 +1,268 @@
+/* $Id: texline.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
+
+/*
+ * Test textured lines.
+ *
+ * Brian Paul
+ * September 2000
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+#include "../util/readtex.c"   /* I know, this is a hack. */
+
+#define TEXTURE_FILE "../images/girl.rgb"
+
+static GLboolean Antialias = GL_FALSE;
+static GLboolean Animate = GL_FALSE;
+static GLint Texture = 1;
+static GLboolean Stipple = GL_FALSE;
+static GLfloat LineWidth = 1.0;
+
+static GLfloat Xrot = -60.0, Yrot = 0.0, Zrot = 0.0;
+static GLfloat DYrot = 1.0;
+static GLboolean Points = GL_FALSE;
+static GLfloat Scale = 1.0;
+
+static void Idle( void )
+{
+   if (Animate) {
+      Zrot += DYrot;
+      glutPostRedisplay();
+   }
+}
+
+
+static void Display( void )
+{
+   GLfloat x, y, s, t;
+
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   glPushMatrix();
+   glRotatef(Xrot, 1.0, 0.0, 0.0);
+   glRotatef(Yrot, 0.0, 1.0, 0.0);
+   glRotatef(Zrot, 0.0, 0.0, 1.0);
+   glScalef(Scale, Scale, Scale);
+
+   if (Texture)
+      glColor3f(1, 1, 1);
+
+   if (Points) {
+      glBegin(GL_POINTS);
+      for (t = 0.0; t <= 1.0; t += 0.025) {
+         for (s = 0.0; s <= 1.0; s += 0.025) {
+            x = s * 2.0 - 1.0;
+            y = t * 2.0 - 1.0;
+            if (!Texture)
+               glColor3f(1, 0, 1);
+            glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t, s);
+            glTexCoord2f(s, t);
+            glVertex2f(x, y);
+         }
+      }
+      glEnd();
+   }
+   else {
+      glBegin(GL_LINES);
+      for (t = 0.0; t <= 1.0; t += 0.025) {
+         x = t * 2.0 - 1.0;
+         if (!Texture)
+            glColor3f(1, 0, 1);
+         glTexCoord2f(t, 0.0);
+         glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, t);
+         glVertex2f(x, -1.0);
+         if (!Texture)
+            glColor3f(0, 1, 0);
+         glTexCoord2f(t, 1.0);
+         glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, t);
+         glVertex2f(x, 1.0);
+      }
+      glEnd();
+   }
+
+   glPopMatrix();
+
+   glutSwapBuffers();
+}
+
+
+static void Reshape( int width, int height )
+{
+   GLfloat ar = (float) width / height;
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -ar, ar, -1.0, 1.0, 10.0, 100.0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -12.0 );
+}
+
+
+static void Key( unsigned char key, int x, int y )
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+      case 'a':
+         Antialias = !Antialias;
+         if (Antialias) {
+            glEnable(GL_LINE_SMOOTH);
+            glEnable(GL_POINT_SMOOTH);
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+         }
+         else {
+            glDisable(GL_LINE_SMOOTH);
+            glDisable(GL_POINT_SMOOTH);
+            glDisable(GL_BLEND);
+         }
+         break;
+      case 't':
+         Texture++;
+         if (Texture > 2)
+            Texture = 0;
+         if (Texture == 0) {
+            glActiveTextureARB(GL_TEXTURE0_ARB);
+            glDisable(GL_TEXTURE_2D);
+            glActiveTextureARB(GL_TEXTURE1_ARB);
+            glDisable(GL_TEXTURE_2D);
+         }
+         else if (Texture == 1) {
+            glActiveTextureARB(GL_TEXTURE0_ARB);
+            glEnable(GL_TEXTURE_2D);
+            glActiveTextureARB(GL_TEXTURE1_ARB);
+            glDisable(GL_TEXTURE_2D);
+         }
+         else {
+            glActiveTextureARB(GL_TEXTURE0_ARB);
+            glEnable(GL_TEXTURE_2D);
+            glActiveTextureARB(GL_TEXTURE1_ARB);
+            glEnable(GL_TEXTURE_2D);
+         }
+         break;
+      case 'w':
+         LineWidth -= 0.25;
+         if (LineWidth < 0.25)
+            LineWidth = 0.25;
+         glLineWidth(LineWidth);
+         glPointSize(LineWidth);
+         break;
+      case 'W':
+         LineWidth += 0.25;
+         if (LineWidth > 8.0)
+            LineWidth = 8.0;
+         glLineWidth(LineWidth);
+         glPointSize(LineWidth);
+         break;
+      case 'p':
+         Points = !Points;
+         break;
+      case 's':
+         Stipple = !Stipple;
+         if (Stipple)
+            glEnable(GL_LINE_STIPPLE);
+         else
+            glDisable(GL_LINE_STIPPLE);
+         break;
+      case ' ':
+         Animate = !Animate;
+         if (Animate)
+            glutIdleFunc(Idle);
+         else
+            glutIdleFunc(NULL);
+         break;
+      case 27:
+         exit(0);
+         break;
+   }
+   printf("LineWidth, PointSize = %f\n", LineWidth);
+   glutPostRedisplay();
+}
+
+
+static void SpecialKey( int key, int x, int y )
+{
+   float step = 3.0;
+   (void) x;
+   (void) y;
+
+   switch (key) {
+      case GLUT_KEY_UP:
+         Xrot += step;
+         break;
+      case GLUT_KEY_DOWN:
+         Xrot -= step;
+         break;
+      case GLUT_KEY_LEFT:
+         Yrot += step;
+         break;
+      case GLUT_KEY_RIGHT:
+         Yrot -= step;
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void Init( int argc, char *argv[] )
+{
+   GLuint u;
+   for (u = 0; u < 2; u++) {
+      glActiveTextureARB(GL_TEXTURE0_ARB + u);
+      glBindTexture(GL_TEXTURE_2D, 10+u);
+      if (u == 0)
+         glEnable(GL_TEXTURE_2D);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+      if (u == 0)
+         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+      else
+         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
+
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
+         printf("Error: couldn't load texture image\n");
+         exit(1);
+      }
+   }
+
+   glLineStipple(1, 0xff);
+
+   if (argc > 1 && strcmp(argv[1], "-info")==0) {
+      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
+      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
+      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
+      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
+   }
+}
+
+
+int main( int argc, char *argv[] )
+{
+   glutInit( &argc, argv );
+   glutInitWindowSize( 400, 300 );
+
+   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+
+   glutCreateWindow(argv[0] );
+
+   Init(argc, argv);
+
+   glutReshapeFunc( Reshape );
+   glutKeyboardFunc( Key );
+   glutSpecialFunc( SpecialKey );
+   glutDisplayFunc( Display );
+   if (Animate)
+      glutIdleFunc( Idle );
+
+   glutMainLoop();
+   return 0;
+}