diff -Naurp Mesa-7.8.1/progs/xdemos/corender.c Mesa-7.8.1.patched/progs/xdemos/corender.c
--- Mesa-7.8.1/progs/xdemos/corender.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/corender.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,400 @@
+/**
+ * Example of cooperative rendering into one window by two processes.
+ * The first instance of the program creates the GLX window.
+ * The second instance of the program gets the window ID from the first
+ * and draws into it.
+ * Socket IPC is used for synchronization.
+ *
+ * Usage:
+ * 1. run 'corender &'
+ * 2. run 'corender 2'  (any arg will do)
+ *
+ * Brian Paul
+ * 11 Oct 2007
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+#include <unistd.h>
+#include "ipc.h"
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static int MyID = 0;  /* 0 or 1 */
+static int WindowID = 0;
+static GLXContext Context = 0;
+static int Width = 700, Height = 350;
+static int Rot = 0;
+static int Sock = 0;
+
+static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0};
+static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+static int Sync = 1;  /** synchronized rendering? */
+
+
+static void
+setup_ipc(void)
+{
+   int k, port = 10001;
+
+   if (MyID == 0) {
+      /* I'm the first one, wait for connection from second */
+      k = CreatePort(&port);
+      assert(k != -1);
+
+      printf("Waiting for connection from another 'corender'\n");
+      Sock = AcceptConnection(k);
+      assert(Sock != -1);
+
+      printf("Got connection, sending windowID\n");
+
+      /* send windowID */
+      SendData(Sock, &WindowID, sizeof(WindowID));
+   }
+   else {
+      /* I'm the second one, connect to first */
+      char hostname[1000];
+
+      MyHostName(hostname, 1000);
+      Sock = Connect(hostname, port);
+      assert(Sock != -1);
+
+      /* get windowID */
+      ReceiveData(Sock, &WindowID, sizeof(WindowID));
+      printf("Contacted first 'corender', getting WindowID\n");
+   }
+}
+
+
+
+/** from GLUT */
+static void
+doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
+{
+  int i, j;
+  GLfloat theta, phi, theta1;
+  GLfloat cosTheta, sinTheta;
+  GLfloat cosTheta1, sinTheta1;
+  GLfloat ringDelta, sideDelta;
+
+  ringDelta = 2.0 * M_PI / rings;
+  sideDelta = 2.0 * M_PI / nsides;
+
+  theta = 0.0;
+  cosTheta = 1.0;
+  sinTheta = 0.0;
+  for (i = rings - 1; i >= 0; i--) {
+    theta1 = theta + ringDelta;
+    cosTheta1 = cos(theta1);
+    sinTheta1 = sin(theta1);
+    glBegin(GL_QUAD_STRIP);
+    phi = 0.0;
+    for (j = nsides; j >= 0; j--) {
+      GLfloat cosPhi, sinPhi, dist;
+
+      phi += sideDelta;
+      cosPhi = cos(phi);
+      sinPhi = sin(phi);
+      dist = R + r * cosPhi;
+
+      glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
+      glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
+      glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
+      glVertex3f(cosTheta * dist, -sinTheta * dist,  r * sinPhi);
+    }
+    glEnd();
+    theta = theta1;
+    cosTheta = cosTheta1;
+    sinTheta = sinTheta1;
+  }
+}
+
+
+static void
+redraw(Display *dpy)
+{
+   int dbg = 0;
+
+   glXMakeCurrent(dpy, WindowID, Context);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+   glClearColor(0.5, 0.5, 0.5, 0.0);
+
+   if (MyID == 0) {
+      /* First process */
+
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+      glPushMatrix();
+      glTranslatef(-1, 0, 0);
+      glRotatef(Rot, 1, 0, 0);
+      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
+      doughnut(0.5, 2.0, 20, 30);
+      glPopMatrix();
+
+      glFinish();
+      if (!Sync) {
+         usleep(1000*10);
+      }
+
+      /* signal second process to render */
+      if (Sync) {
+         int code = 1;
+         if (dbg) printf("0: send signal\n");
+         SendData(Sock, &code, sizeof(code));
+         SendData(Sock, &Rot, sizeof(Rot));
+      }
+
+      /* wait for second process to finish rendering */
+      if (Sync) {
+         int code = 0;
+         if (dbg) printf("0: wait signal\n");
+         ReceiveData(Sock, &code, sizeof(code));
+         if (dbg) printf("0: got signal\n");
+         assert(code == 2);
+      }
+
+   }
+   else {
+      /* Second process */
+
+      /* wait for first process's signal for me to render */
+      if (Sync) {
+         int code = 0;
+         if (dbg) printf("1: wait signal\n");
+         ReceiveData(Sock, &code, sizeof(code));
+         ReceiveData(Sock, &Rot, sizeof(Rot));
+
+         if (dbg) printf("1: got signal\n");
+         assert(code == 1);
+      }
+
+      /* XXX this clear should not be here, but for some reason, it
+       * makes things _mostly_ work correctly w/ NVIDIA's driver.
+       * There's only occasional glitches.
+       * Without this glClear(), depth buffer for the second process
+       * is pretty much broken.
+       */
+      /* glClear(GL_DEPTH_BUFFER_BIT); */
+
+      glPushMatrix();
+      glTranslatef(1, 0, 0);
+      glRotatef(Rot + 90 , 1, 0, 0);
+      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
+      doughnut(0.5, 2.0, 20, 30);
+      glPopMatrix();
+      glFinish();
+
+      glXSwapBuffers(dpy, WindowID);
+      usleep(1000*10);
+
+      /* signal first process that I'm done rendering */
+      if (Sync) {
+         int code = 2;
+         if (dbg) printf("1: send signal\n");
+         SendData(Sock, &code, sizeof(code));
+      }
+   }
+}
+
+
+static void
+resize(Display *dpy, int width, int height)
+{
+   float ar = (float) width / height;
+
+   glXMakeCurrent(dpy, WindowID, Context);
+
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0, 0, -15);
+
+   Width = width;
+   Height = height;
+}
+
+
+
+static void
+set_window_title(Display *dpy, Window win, const char *title)
+{
+   XSizeHints sizehints;
+   sizehints.flags = 0;
+   XSetStandardProperties(dpy, win, title, title,
+                          None, (char **)NULL, 0, &sizehints);
+}
+
+
+static Window
+make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
+{
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   int x = 0, y = 0;
+   char *name = NULL;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, x, y, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   return win;
+}
+
+
+static void
+set_event_mask(Display *dpy, Window win)
+{
+   XSetWindowAttributes attr;
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
+}
+
+
+static void
+event_loop(Display *dpy)
+{
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+
+         switch (event.type) {
+         case Expose:
+            redraw(dpy);
+            break;
+         case ConfigureNotify:
+            resize(dpy, event.xconfigure.width, event.xconfigure.height);
+            break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                    NULL, NULL);
+                  if (buffer[0] == 27) {
+                     exit(0);
+                  }
+               }
+            }
+         default:
+            /* nothing */
+            ;
+         }
+      }
+
+      if (MyID == 0 || !Sync)
+         Rot += 1;
+      redraw(dpy);
+   }
+}
+
+
+static XVisualInfo *
+choose_visual(Display *dpy)
+{
+   int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+   int scrnum = DefaultScreen( dpy );
+   return glXChooseVisual(dpy, scrnum, attribs);
+}
+
+
+static void
+parse_opts(int argc, char *argv[])
+{
+   if (argc > 1) {
+      MyID = 1;
+   }
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+   Display *dpy;
+   XVisualInfo *visinfo;
+
+   parse_opts(argc, argv);
+
+   dpy = XOpenDisplay(NULL);
+
+   visinfo = choose_visual(dpy);
+
+   Context = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!Context) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   if (MyID == 0) {
+      WindowID = make_gl_window(dpy, visinfo, Width, Height);
+      set_window_title(dpy, WindowID, "corender");
+      XMapWindow(dpy, WindowID);
+      /*printf("WindowID 0x%x\n", (int) WindowID);*/
+   }
+
+   /* do ipc hand-shake here */
+   setup_ipc();
+   assert(Sock);
+   assert(WindowID);
+
+   if (MyID == 1) {
+      set_event_mask(dpy, WindowID);
+   }
+
+   resize(dpy, Width, Height);
+
+   event_loop(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glsync.c Mesa-7.8.1.patched/progs/xdemos/glsync.c
--- Mesa-7.8.1/progs/xdemos/glsync.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glsync.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,295 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jesse Barnes <jesse.barnes@intel.com>
+ *
+ */
+
+/** @file glsync.c
+ * The program is simple:  it paints a window alternating colors (red &
+ * white) either as fast as possible or synchronized to vblank events
+ *
+ * If run normally, the program should display a window that exhibits
+ * significant tearing between red and white colors (e.g. you might get
+ * a "waterfall" effect of red and white horizontal bars).
+ *
+ * If run with the '-s b' option, the program should synchronize the
+ * window color changes with the vertical blank period, resulting in a
+ * window that looks orangish with a high frequency flicker (which may
+ * be invisible).  If the window is moved to another screen, this
+ * property should be preserved.  If the window spans two screens, it
+ * shouldn't tear on whichever screen most of the window is on; the
+ * portion on the other screen may show some tearing (like the
+ * waterfall effect above).
+ *
+ * Other options include '-w <width>' and '-h <height' to set the
+ * window size.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+void (*video_sync_get)();
+void (*video_sync)();
+void (*swap_interval)();
+
+static int GLXExtensionSupported(Display *dpy, const char *extension)
+{
+	const char *extensionsString, *pos;
+
+	extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
+
+	pos = strstr(extensionsString, extension);
+
+	if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
+	    (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
+		return 1;
+
+	return 0;
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "w:h:s:vi:";
+
+enum sync_type {
+	none = 0,
+	sgi_video_sync,
+	buffer_swap
+};
+
+static void usage(char *name)
+{
+	printf("usage: %s [-w <width>] [-h <height>] [-s<sync method>] "
+	       "[-v]\n", name);
+	printf("\t-s<sync method>:\n");
+	printf("\t\tn: none\n");
+	printf("\t\ts: SGI video sync extension\n");
+	printf("\t\tb: buffer swap\n");
+	printf("\t-i<swap interval>\n");
+	printf("\t-v: verbose (print count)\n");
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	Display *disp;
+	XVisualInfo *pvi;
+	XSetWindowAttributes swa;
+	GLint last_val = -1, count = 0;
+	Window winGL;
+	GLXContext context;
+	int dummy;
+	Atom wmDelete;
+	enum sync_type waitforsync = none;
+	int width = 500, height = 500, verbose = 0, interval = 1;
+	int c, i = 1;
+	int ret;
+	int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     None };
+	int db_attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+	XSizeHints sizehints;
+
+	opterr = 0;
+	while ((c = getopt(argc, argv, optstr)) != -1) {
+		switch (c) {
+		case 'w':
+			width = atoi(optarg);
+			break;
+		case 'h':
+			height = atoi(optarg);
+			break;
+		case 's':
+			switch (optarg[0]) {
+			case 'n':
+				waitforsync = none;
+				break;
+			case 's':
+				waitforsync = sgi_video_sync;
+				break;
+			case 'b':
+				waitforsync = buffer_swap;
+				break;
+			default:
+				usage(argv[0]);
+				break;
+			}
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'i':
+			interval = atoi(optarg);
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	}
+
+	disp = XOpenDisplay(NULL);
+	if (!disp) {
+		fprintf(stderr, "failed to open display\n");
+		return -1;
+	}
+
+	if (!glXQueryExtension(disp, &dummy, &dummy)) {
+		fprintf(stderr, "glXQueryExtension failed\n");
+		return -1;
+	}
+
+	if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) {
+		fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n");
+		return -1;
+	}
+
+	if (waitforsync != buffer_swap) {
+		pvi = glXChooseVisual(disp, DefaultScreen(disp), attribs);
+	} else {
+		pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs);
+	}
+
+	if (!pvi) {
+		fprintf(stderr, "failed to choose visual, exiting\n");
+		return -1;
+	}
+
+	pvi->screen = DefaultScreen(disp);
+
+	swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
+				       pvi->visual, AllocNone);
+	swa.border_pixel = 0;
+	swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+		StructureNotifyMask;
+	winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
+			      0, 0,
+			      width, height,
+			      0, pvi->depth, InputOutput, pvi->visual,
+			      CWBorderPixel | CWColormap | CWEventMask, &swa);
+	if (!winGL) {
+		fprintf(stderr, "window creation failed\n");
+		return -1;
+	}
+        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
+        XSetWMProtocols(disp, winGL, &wmDelete, 1);
+
+	sizehints.x = 0;
+	sizehints.y = 0;
+	sizehints.width  = width;
+	sizehints.height = height;
+	sizehints.flags = USSize | USPosition;
+
+	XSetNormalHints(disp, winGL, &sizehints);
+	XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
+			       None, NULL, 0, &sizehints);
+
+	context = glXCreateContext(disp, pvi, NULL, GL_TRUE);
+	if (!context) {
+		fprintf(stderr, "failed to create glx context\n");
+		return -1;
+	}
+
+	XMapWindow(disp, winGL);
+	ret = glXMakeCurrent(disp, winGL, context);
+	if (!ret) {
+		fprintf(stderr, "failed to make context current: %d\n", ret);
+	}
+
+	video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI");
+	video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI");
+
+	swap_interval = glXGetProcAddress((unsigned char *)"glXSwapIntervalSGI");
+
+	if (!video_sync_get || !video_sync || !swap_interval) {
+		fprintf(stderr, "failed to get sync functions\n");
+		return -1;
+	}
+
+	if (waitforsync == buffer_swap) {
+		swap_interval(interval);
+		fprintf(stderr, "set swap interval to %d\n", interval);
+	}
+	video_sync_get(&count);
+	count++;
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	while (i++) {
+		/* Alternate colors to make tearing obvious */
+		if (i & 1) {
+			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+			glColor3f(1.0f, 1.0f, 1.0f);
+		} else {
+			glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+			glColor3f(1.0f, 0.0f, 0.0f);
+		}
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		glRectf(0, 0, width, height);
+
+		/* Wait for vsync */
+		if (waitforsync == sgi_video_sync) {
+			if (verbose)
+				fprintf(stderr, "waiting on count %d\n", count);
+			video_sync(2, (count + 1) % 2, &count);
+			if (count < last_val)
+				fprintf(stderr, "error:  vblank count went backwards: %d -> %d\n", last_val, count);
+			if (count == last_val)
+				fprintf(stderr, "error:  count didn't change: %d\n", count);
+			last_val = count;
+			glFlush();
+		} else if (waitforsync == buffer_swap) {
+			glXSwapBuffers(disp, winGL);
+		} else {
+			video_sync_get(&count);
+			sleep(1);
+			glFinish();
+		}
+
+		if (verbose) {
+			video_sync_get(&count);
+			fprintf(stderr, "current count: %d\n", count);
+		}
+	}
+
+	XDestroyWindow(disp, winGL);
+	glXDestroyContext(disp, context);
+	XCloseDisplay(disp);
+
+	return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glthreads.c Mesa-7.8.1.patched/progs/xdemos/glthreads.c
--- Mesa-7.8.1/progs/xdemos/glthreads.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glthreads.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2000  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * This program tests GLX thread safety.
+ * Command line options:
+ *  -p                       Open a display connection for each thread
+ *  -l                       Enable application-side locking
+ *  -n <num threads>         Number of threads to create (default is 2)
+ *  -display <display name>  Specify X display (default is $DISPLAY)
+ *  -t                       Use texture mapping
+ *
+ * Brian Paul  20 July 2000
+ */
+
+
+/*
+ * Notes:
+ * - Each thread gets its own GLX context.
+ *
+ * - The GLX contexts share texture objects.
+ *
+ * - When 't' is pressed to update the texture image, the window/thread which
+ *   has input focus is signalled to change the texture.  The other threads
+ *   should see the updated texture the next time they call glBindTexture.
+ */
+
+
+#if defined(PTHREADS)   /* defined by Mesa on Linux and other platforms */
+
+#include <assert.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+
+
+/*
+ * Each window/thread/context:
+ */
+struct winthread {
+   Display *Dpy;
+   int Index;
+   pthread_t Thread;
+   Window Win;
+   GLXContext Context;
+   float Angle;
+   int WinWidth, WinHeight;
+   GLboolean NewSize;
+   GLboolean Initialized;
+   GLboolean MakeNewTexture;
+};
+
+
+#define MAX_WINTHREADS 100
+static struct winthread WinThreads[MAX_WINTHREADS];
+static int NumWinThreads = 0;
+static volatile GLboolean ExitFlag = GL_FALSE;
+
+static GLboolean MultiDisplays = 0;
+static GLboolean Locking = 0;
+static GLboolean Texture = GL_FALSE;
+static GLuint TexObj = 12;
+static GLboolean Animate = GL_TRUE;
+
+static pthread_mutex_t Mutex;
+static pthread_cond_t CondVar;
+static pthread_mutex_t CondMutex;
+
+
+static void
+Error(const char *msg)
+{
+   fprintf(stderr, "Error: %s\n", msg);
+   exit(1);
+}
+
+
+static void
+signal_redraw(void)
+{
+   pthread_mutex_lock(&CondMutex);
+   pthread_cond_broadcast(&CondVar);
+   pthread_mutex_unlock(&CondMutex);
+}
+
+
+static void
+MakeNewTexture(struct winthread *wt)
+{
+#define TEX_SIZE 128
+   static float step = 0.0;
+   GLfloat image[TEX_SIZE][TEX_SIZE][4];
+   GLint width;
+   int i, j;
+
+   for (j = 0; j < TEX_SIZE; j++) {
+      for (i = 0; i < TEX_SIZE; i++) {
+         float dt = 5.0 * (j - 0.5 * TEX_SIZE) / TEX_SIZE;
+         float ds = 5.0 * (i - 0.5 * TEX_SIZE) / TEX_SIZE;
+         float r = dt * dt + ds * ds + step;
+         image[j][i][0] = 
+         image[j][i][1] = 
+         image[j][i][2] = 0.75 + 0.25 * cos(r);
+         image[j][i][3] = 1.0;
+      }
+   }
+
+   step += 0.5;
+
+   glBindTexture(GL_TEXTURE_2D, TexObj);
+
+   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+   if (width) {
+      assert(width == TEX_SIZE);
+      /* sub-tex replace */
+      glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEX_SIZE, TEX_SIZE,
+                   GL_RGBA, GL_FLOAT, image);
+   }
+   else {
+      /* create new */
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, 
+                   GL_RGBA, GL_FLOAT, image);
+   }
+}
+
+
+
+/* draw a colored cube */
+static void
+draw_object(void)
+{
+   glPushMatrix();
+   glScalef(0.75, 0.75, 0.75);
+
+   glColor3f(1, 0, 0);
+
+   if (Texture) {
+      glBindTexture(GL_TEXTURE_2D, TexObj);
+      glEnable(GL_TEXTURE_2D);
+   }
+   else {
+      glDisable(GL_TEXTURE_2D);
+   }
+
+   glBegin(GL_QUADS);
+
+   /* -X */
+   glColor3f(0, 1, 1);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f(-1,  1, -1);
+   glTexCoord2f(1, 1);  glVertex3f(-1,  1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
+
+   /* +X */
+   glColor3f(1, 0, 0);
+   glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f(1,  1, -1);
+   glTexCoord2f(1, 1);  glVertex3f(1,  1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(1, -1,  1);
+
+   /* -Y */
+   glColor3f(1, 0, 1);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1, -1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
+
+   /* +Y */
+   glColor3f(0, 1, 0);
+   glTexCoord2f(0, 0);  glVertex3f(-1, 1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, 1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1, 1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, 1,  1);
+
+   /* -Z */
+   glColor3f(1, 1, 0);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1,  1, -1);
+   glTexCoord2f(0, 1);  glVertex3f(-1,  1, -1);
+
+   /* +Y */
+   glColor3f(0, 0, 1);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, 1);
+   glTexCoord2f(1, 1);  glVertex3f( 1,  1, 1);
+   glTexCoord2f(0, 1);  glVertex3f(-1,  1, 1);
+
+   glEnd();
+
+   glPopMatrix();
+}
+
+
+/* signal resize of given window */
+static void
+resize(struct winthread *wt, int w, int h)
+{
+   wt->NewSize = GL_TRUE;
+   wt->WinWidth = w;
+   wt->WinHeight = h;
+   if (!Animate)
+      signal_redraw();
+}
+
+
+/*
+ * We have an instance of this for each thread.
+ */
+static void
+draw_loop(struct winthread *wt)
+{
+   while (!ExitFlag) {
+
+      if (Locking)
+         pthread_mutex_lock(&Mutex);
+
+      glXMakeCurrent(wt->Dpy, wt->Win, wt->Context);
+      if (!wt->Initialized) {
+         printf("glthreads: %d: GL_RENDERER = %s\n", wt->Index,
+                (char *) glGetString(GL_RENDERER));
+         if (Texture /*&& wt->Index == 0*/) {
+            MakeNewTexture(wt);
+         }
+         wt->Initialized = GL_TRUE;
+      }
+
+      if (Locking)
+         pthread_mutex_unlock(&Mutex);
+
+      glEnable(GL_DEPTH_TEST);
+
+      if (wt->NewSize) {
+         GLfloat w = (float) wt->WinWidth / (float) wt->WinHeight;
+         glViewport(0, 0, wt->WinWidth, wt->WinHeight);
+         glMatrixMode(GL_PROJECTION);
+         glLoadIdentity();
+         glFrustum(-w, w, -1.0, 1.0, 1.5, 10);
+         glMatrixMode(GL_MODELVIEW);
+         glLoadIdentity();
+         glTranslatef(0, 0, -2.5);
+         wt->NewSize = GL_FALSE;
+      }
+
+      if (wt->MakeNewTexture) {
+         MakeNewTexture(wt);
+         wt->MakeNewTexture = GL_FALSE;
+      }
+
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+      glPushMatrix();
+         glRotatef(wt->Angle, 0, 1, 0);
+         glRotatef(wt->Angle, 1, 0, 0);
+         glScalef(0.7, 0.7, 0.7);
+         draw_object();
+      glPopMatrix();
+
+      if (Locking)
+         pthread_mutex_lock(&Mutex);
+
+      glXSwapBuffers(wt->Dpy, wt->Win);
+
+      if (Locking)
+         pthread_mutex_unlock(&Mutex);
+
+      if (Animate) {
+         usleep(5000);
+      }
+      else {
+         /* wait for signal to draw */
+         pthread_mutex_lock(&CondMutex);
+         pthread_cond_wait(&CondVar, &CondMutex);
+         pthread_mutex_unlock(&CondMutex);
+      }
+      wt->Angle += 1.0;
+   }
+}
+
+
+static void
+keypress(XEvent *event, struct winthread *wt)
+{
+   char buf[100];
+   KeySym keySym;
+   XComposeStatus stat;
+
+   XLookupString(&event->xkey, buf, sizeof(buf), &keySym, &stat);
+
+   switch (keySym) {
+   case XK_Escape:
+      /* tell all threads to exit */
+      if (!Animate) {
+         signal_redraw();
+      }
+      ExitFlag = GL_TRUE;
+      /*printf("exit draw_loop %d\n", wt->Index);*/
+      return;
+   case XK_t:
+   case XK_T:
+      if (Texture) {
+         wt->MakeNewTexture = GL_TRUE;
+         if (!Animate)
+            signal_redraw();
+      }
+      break;
+   case XK_a:
+   case XK_A:
+      Animate = !Animate;
+      if (Animate)  /* yes, prev Animate state! */
+         signal_redraw();
+      break;
+   case XK_s:
+   case XK_S:
+      if (!Animate)
+         signal_redraw();
+      break;
+   default:
+      ; /* nop */
+   }
+}
+
+
+/*
+ * The main process thread runs this loop.
+ * Single display connection for all threads.
+ */
+static void
+event_loop(Display *dpy)
+{
+   XEvent event;
+   int i;
+
+   assert(!MultiDisplays);
+
+   while (!ExitFlag) {
+
+      if (Locking) {
+         while (1) {
+            int k;
+            pthread_mutex_lock(&Mutex);
+            k = XPending(dpy);
+            if (k) {
+               XNextEvent(dpy, &event);
+               pthread_mutex_unlock(&Mutex);
+               break;
+            }
+            pthread_mutex_unlock(&Mutex);
+            usleep(5000);
+         }
+      }
+      else {
+         XNextEvent(dpy, &event);
+      }
+
+      switch (event.type) {
+         case ConfigureNotify:
+            /* Find winthread for this event's window */
+            for (i = 0; i < NumWinThreads; i++) {
+               struct winthread *wt = &WinThreads[i];
+               if (event.xconfigure.window == wt->Win) {
+                  resize(wt, event.xconfigure.width,
+                         event.xconfigure.height);
+                  break;
+               }
+            }
+            break;
+         case KeyPress:
+            for (i = 0; i < NumWinThreads; i++) {
+               struct winthread *wt = &WinThreads[i];
+               if (event.xkey.window == wt->Win) {
+                  keypress(&event, wt);
+                  break;
+               }
+            }
+            break;
+         default:
+            /*no-op*/ ;
+      }
+   }
+}
+
+
+/*
+ * Separate display connection for each thread.
+ */
+static void
+event_loop_multi(void)
+{
+   XEvent event;
+   int w = 0;
+
+   assert(MultiDisplays);
+
+   while (!ExitFlag) {
+      struct winthread *wt = &WinThreads[w];
+      if (XPending(wt->Dpy)) {
+         XNextEvent(wt->Dpy, &event);
+         switch (event.type) {
+         case ConfigureNotify:
+            resize(wt, event.xconfigure.width, event.xconfigure.height);
+            break;
+         case KeyPress:
+            keypress(&event, wt);
+            break;
+         default:
+            ; /* nop */
+         }
+      }
+      w = (w + 1) % NumWinThreads;
+      usleep(5000);
+   }
+}
+
+
+
+/*
+ * we'll call this once for each thread, before the threads are created.
+ */
+static void
+create_window(struct winthread *wt, GLXContext shareCtx)
+{
+   Window win;
+   GLXContext ctx;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+                    GLX_DEPTH_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   XVisualInfo *visinfo;
+   int width = 160, height = 160;
+   int xpos = (wt->Index % 8) * (width + 10);
+   int ypos = (wt->Index / 8) * (width + 20);
+
+   scrnum = DefaultScreen(wt->Dpy);
+   root = RootWindow(wt->Dpy, scrnum);
+
+   visinfo = glXChooseVisual(wt->Dpy, scrnum, attrib);
+   if (!visinfo) {
+      Error("Unable to find RGB, Z, double-buffered visual");
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(wt->Dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(wt->Dpy, root, xpos, ypos, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   if (!win) {
+      Error("Couldn't create window");
+   }
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(wt->Dpy, win, &sizehints);
+      XSetStandardProperties(wt->Dpy, win, "glthreads", "glthreads",
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   ctx = glXCreateContext(wt->Dpy, visinfo, shareCtx, True);
+   if (!ctx) {
+      Error("Couldn't create GLX context");
+   }
+
+   XMapWindow(wt->Dpy, win);
+   XSync(wt->Dpy, 0);
+
+   /* save the info for this window/context */
+   wt->Win = win;
+   wt->Context = ctx;
+   wt->Angle = 0.0;
+   wt->WinWidth = width;
+   wt->WinHeight = height;
+   wt->NewSize = GL_TRUE;
+}
+
+
+/*
+ * Called by pthread_create()
+ */
+static void *
+thread_function(void *p)
+{
+   struct winthread *wt = (struct winthread *) p;
+   draw_loop(wt);
+   return NULL;
+}
+
+
+/*
+ * called before exit to wait for all threads to finish
+ */
+static void
+clean_up(void)
+{
+   int i;
+
+   /* wait for threads to finish */
+   for (i = 0; i < NumWinThreads; i++) {
+      pthread_join(WinThreads[i].Thread, NULL);
+   }
+
+   for (i = 0; i < NumWinThreads; i++) {
+      glXDestroyContext(WinThreads[i].Dpy, WinThreads[i].Context);
+      XDestroyWindow(WinThreads[i].Dpy, WinThreads[i].Win);
+   }
+}
+
+
+static void
+usage(void)
+{
+   printf("glthreads: test of GL thread safety (any key = exit)\n");
+   printf("Usage:\n");
+   printf("  glthreads [options]\n");
+   printf("Options:\n");
+   printf("   -display DISPLAYNAME  Specify display string\n");
+   printf("   -n NUMTHREADS  Number of threads to create\n");
+   printf("   -p  Use a separate display connection for each thread\n");
+   printf("   -l  Use application-side locking\n");
+   printf("   -t  Enable texturing\n");
+   printf("Keyboard:\n");
+   printf("   Esc  Exit\n");
+   printf("   t    Change texture image (requires -t option)\n");
+   printf("   a    Toggle animation\n");
+   printf("   s    Step rotation (when not animating)\n");
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   char *displayName = NULL;
+   int numThreads = 2;
+   Display *dpy = NULL;
+   int i;
+   Status threadStat;
+
+   if (argc == 1) {
+      usage();
+   }
+   else {
+      int i;
+      for (i = 1; i < argc; i++) {
+         if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
+            displayName = argv[i + 1];
+            i++;
+         }
+         else if (strcmp(argv[i], "-p") == 0) {
+            MultiDisplays = 1;
+         }
+         else if (strcmp(argv[i], "-l") == 0) {
+            Locking = 1;
+         }
+         else if (strcmp(argv[i], "-t") == 0) {
+            Texture = 1;
+         }
+         else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) {
+            numThreads = atoi(argv[i + 1]);
+            if (numThreads < 1)
+               numThreads = 1;
+            else if (numThreads > MAX_WINTHREADS)
+               numThreads = MAX_WINTHREADS;
+            i++;
+         }
+         else {
+            usage();
+            exit(1);
+         }
+      }
+   }
+   
+   if (Locking)
+      printf("glthreads: Using explicit locks around Xlib calls.\n");
+   else
+      printf("glthreads: No explict locking.\n");
+
+   if (MultiDisplays)
+      printf("glthreads: Per-thread display connections.\n");
+   else
+      printf("glthreads: Single display connection.\n");
+
+   /*
+    * VERY IMPORTANT: call XInitThreads() before any other Xlib functions.
+    */
+   if (!MultiDisplays) {
+      if (!Locking) {
+         threadStat = XInitThreads();
+      if (threadStat) {
+         printf("XInitThreads() returned %d (success)\n", (int) threadStat);
+      }
+      else {
+         printf("XInitThreads() returned 0 (failure- this program may fail)\n");
+      }
+      }
+
+      dpy = XOpenDisplay(displayName);
+      if (!dpy) {
+         fprintf(stderr, "Unable to open display %s\n", XDisplayName(displayName));
+         return -1;
+      }
+   }
+
+   pthread_mutex_init(&Mutex, NULL);
+   pthread_mutex_init(&CondMutex, NULL);
+   pthread_cond_init(&CondVar, NULL);
+
+   printf("glthreads: creating windows\n");
+
+   NumWinThreads = numThreads;
+
+   /* Create the GLX windows and contexts */
+   for (i = 0; i < numThreads; i++) {
+      GLXContext share;
+
+      if (MultiDisplays) {
+         WinThreads[i].Dpy = XOpenDisplay(displayName);
+         assert(WinThreads[i].Dpy);
+      }
+      else {
+         WinThreads[i].Dpy = dpy;
+      }
+      WinThreads[i].Index = i;
+      WinThreads[i].Initialized = GL_FALSE;
+
+      share = (Texture && i > 0) ? WinThreads[0].Context : 0;
+
+      create_window(&WinThreads[i], share);
+   }
+
+   printf("glthreads: creating threads\n");
+
+   /* Create the threads */
+   for (i = 0; i < numThreads; i++) {
+      pthread_create(&WinThreads[i].Thread, NULL, thread_function,
+                     (void*) &WinThreads[i]);
+      printf("glthreads: Created thread %p\n", (void *) WinThreads[i].Thread);
+   }
+
+   if (MultiDisplays)
+      event_loop_multi();
+   else
+      event_loop(dpy);
+
+   clean_up();
+
+   if (MultiDisplays) {
+      for (i = 0; i < numThreads; i++) {
+         XCloseDisplay(WinThreads[i].Dpy);
+      }
+   }
+   else {
+      XCloseDisplay(dpy);
+   }
+
+   return 0;
+}
+
+
+#else /* PTHREADS */
+
+
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+   printf("Sorry, this program wasn't compiled with PTHREADS defined.\n");
+   return 0;
+}
+
+
+#endif /* PTHREADS */
diff -Naurp Mesa-7.8.1/progs/xdemos/glxcontexts.c Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c
--- Mesa-7.8.1/progs/xdemos/glxcontexts.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Version of glxgears that creates/destroys the rendering context for each
+ * frame.  Also periodically destroy/recreate the window.
+ * Good for finding memory leaks, etc.
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *
+ */
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+
+#define BENCHMARK
+
+#ifdef BENCHMARK
+
+/* XXX this probably isn't very portable */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* return current time (in seconds) */
+static double
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+#else /*BENCHMARK*/
+
+/* dummy */
+static double
+current_time(void)
+{
+   /* update this function for other platforms! */
+   static double t = 0.0;
+   static int warn = 1;
+   if (warn) {
+      fprintf(stderr, "Warning: current_time() not implemented!!\n");
+      warn = 0;
+   }
+   return t += 1.0;
+}
+
+#endif /*BENCHMARK*/
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+static XVisualInfo *visinfo = NULL;
+static int WinWidth = 300, WinHeight = 300;
+
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+do_draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   glPushMatrix();
+   glTranslatef(-3.0, -2.0, 0.0);
+   glRotatef(angle, 0.0, 0.0, 1.0);
+   glCallList(gear1);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(3.1, -2.0, 0.0);
+   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+   glCallList(gear2);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(-3.1, 4.2, 0.0);
+   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+   glCallList(gear3);
+   glPopMatrix();
+
+   glPopMatrix();
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   glViewport(0, 0, (GLint) width, (GLint) height);
+
+   {
+      GLfloat h = (GLfloat) height / (GLfloat) width;
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+   }
+   
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -40.0);
+}
+
+
+static void
+init(void)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   /* make the gears */
+   gear1 = glGenLists(1);
+   glNewList(gear1, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   gear(1.0, 4.0, 1.0, 20, 0.7);
+   glEndList();
+
+   gear2 = glGenLists(1);
+   glNewList(gear2, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+   gear(0.5, 2.0, 2.0, 10, 0.7);
+   glEndList();
+
+   gear3 = glGenLists(1);
+   glNewList(gear3, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   gear(1.3, 2.0, 0.5, 10, 0.7);
+   glEndList();
+
+   glEnable(GL_NORMALIZE);
+}
+   
+
+static void
+draw( Display *dpy, Window win )
+{
+   GLXContext ctx;
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   glXMakeCurrent(dpy, win, ctx);
+
+   init();
+
+   reshape(WinWidth, WinHeight);
+
+   do_draw();
+
+   glDeleteLists(gear1, 1);
+   glDeleteLists(gear2, 1);
+   glDeleteLists(gear3, 1);
+
+   glXSwapBuffers(dpy, win);
+   glXDestroyContext(dpy, ctx);
+}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height,
+             Window *winRet)
+{
+   int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   if (visinfo)
+	   XFree(visinfo);
+
+   visinfo = glXChooseVisual( dpy, scrnum, attribs );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   attr.override_redirect = 0;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+   win = XCreateWindow( dpy, root, x, y, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   *winRet = win;
+}
+
+
+static void
+event_loop(Display *dpy)
+{
+   Window win;
+   make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win);
+   XMapWindow(dpy, win);
+
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+	 case Expose:
+            /* we'll redraw below */
+	    break;
+	 case ConfigureNotify:
+            WinWidth = event.xconfigure.width;
+            WinHeight = event.xconfigure.height;
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+                  view_roty += 5.0;
+               }
+               else if (code == XK_Right) {
+                  view_roty -= 5.0;
+               }
+               else if (code == XK_Up) {
+                  view_rotx += 5.0;
+               }
+               else if (code == XK_Down) {
+                  view_rotx -= 5.0;
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                    NULL, NULL);
+                  if (buffer[0] == 27) {
+                     /* escape */
+                     return;
+                  }
+               }
+            }
+         }
+      }
+
+      {
+         static int frames = 0;
+         static double tRot0 = -1.0, tRate0 = -1.0;
+         double dt, t = current_time();
+         if (tRot0 < 0.0)
+            tRot0 = t;
+         dt = t - tRot0;
+         tRot0 = t;
+
+         /* advance rotation for next frame */
+         angle += 70.0 * dt;  /* 70 degrees per second */
+         if (angle > 3600.0)
+	    angle -= 3600.0;
+
+         draw( dpy, win );
+
+         frames++;
+
+         if (tRate0 < 0.0)
+            tRate0 = t;
+
+         if (t - tRate0 >= 1.0) {
+            GLfloat seconds = t - tRate0;
+            GLfloat fps = frames / seconds;
+            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+                   fps);
+            tRate0 = t;
+
+            /* Destroy window and create new one */	    
+	    XDestroyWindow(dpy, win);
+	    make_window(dpy, "glxgears",
+                        (int)(fps * 100) % 100, (int)(fps * 100) % 100, /* x,y */
+                        WinWidth, WinHeight, &win);
+	    XMapWindow(dpy, win);
+
+            frames = 0;
+         }
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+      else
+	 printf("Warrning: unknown parameter: %s\n", argv[i]);
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      fprintf(stderr, "Error: couldn't open display %s\n",
+	      XDisplayName(dpyName));
+      return -1;
+   }
+
+   if (printInfo) {
+      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));
+   }
+
+   event_loop(dpy);
+
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxdemo.c Mesa-7.8.1.patched/progs/xdemos/glxdemo.c
--- Mesa-7.8.1/progs/xdemos/glxdemo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxdemo.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,127 @@
+
+
+/*
+ * A demonstration of using the GLX functions.  This program is in the
+ * public domain.
+ *
+ * Brian Paul
+ */
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+static void redraw( Display *dpy, Window w )
+{
+   printf("Redraw event\n");
+
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   glColor3f( 1.0, 1.0, 0.0 );
+   glRectf( -0.8, -0.8, 0.8, 0.8 );
+
+   glXSwapBuffers( dpy, w );
+}
+
+
+
+static void resize( unsigned int width, unsigned int height )
+{
+   printf("Resize event\n");
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
+}
+
+
+
+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,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, attrib );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 );
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   glXMakeCurrent( dpy, win, ctx );
+
+   return win;
+}
+
+
+static void event_loop( Display *dpy )
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent( dpy, &event );
+
+      switch (event.type) {
+	 case Expose:
+	    redraw( dpy, event.xany.window );
+	    break;
+	 case ConfigureNotify:
+	    resize( event.xconfigure.width, event.xconfigure.height );
+	    break;
+      }
+   }
+}
+
+
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+
+   win = make_rgb_db_window( dpy, 300, 300 );
+
+   glShadeModel( GL_FLAT );
+   glClearColor( 0.5, 0.5, 0.5, 1.0 );
+
+   XMapWindow( dpy, win );
+
+   event_loop( dpy );
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears.c Mesa-7.8.1.patched/progs/xdemos/glxgears.c
--- Mesa-7.8.1/progs/xdemos/glxgears.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxgears.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
+ * Port by Brian Paul  23 March 2001
+ *
+ * See usage() below for command line options.
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
+#ifndef GLX_MESA_swap_control
+#define GLX_MESA_swap_control 1
+typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
+#endif
+
+
+#define BENCHMARK
+
+#ifdef BENCHMARK
+
+/* XXX this probably isn't very portable */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* return current time (in seconds) */
+static double
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+#else /*BENCHMARK*/
+
+/* dummy */
+static double
+current_time(void)
+{
+   /* update this function for other platforms! */
+   static double t = 0.0;
+   static int warn = 1;
+   if (warn) {
+      fprintf(stderr, "Warning: current_time() not implemented!!\n");
+      warn = 0;
+   }
+   return t += 1.0;
+}
+
+#endif /*BENCHMARK*/
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+/** Event handler results: */
+#define NOP 0
+#define EXIT 1
+#define DRAW 2
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+static GLboolean fullscreen = GL_FALSE;	/* Create a single fullscreen window */
+static GLboolean stereo = GL_FALSE;	/* Enable stereo.  */
+static GLboolean animate = GL_TRUE;	/* Animation */
+static GLfloat eyesep = 5.0;		/* Eye separation. */
+static GLfloat fix_point = 40.0;	/* Fixation point distance.  */
+static GLfloat left, right, asp;	/* Stereo frustum params.  */
+
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   glPushMatrix();
+   glTranslatef(-3.0, -2.0, 0.0);
+   glRotatef(angle, 0.0, 0.0, 1.0);
+   glCallList(gear1);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(3.1, -2.0, 0.0);
+   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+   glCallList(gear2);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(-3.1, 4.2, 0.0);
+   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+   glCallList(gear3);
+   glPopMatrix();
+
+   glPopMatrix();
+}
+
+
+static void
+draw_gears(void)
+{
+   if (stereo) {
+      /* First left eye.  */
+      glDrawBuffer(GL_BACK_LEFT);
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(left, right, -asp, asp, 5.0, 60.0);
+
+      glMatrixMode(GL_MODELVIEW);
+
+      glPushMatrix();
+      glTranslated(+0.5 * eyesep, 0.0, 0.0);
+      draw();
+      glPopMatrix();
+
+      /* Then right eye.  */
+      glDrawBuffer(GL_BACK_RIGHT);
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(-right, -left, -asp, asp, 5.0, 60.0);
+
+      glMatrixMode(GL_MODELVIEW);
+
+      glPushMatrix();
+      glTranslated(-0.5 * eyesep, 0.0, 0.0);
+      draw();
+      glPopMatrix();
+   }
+   else {
+      draw();
+   }
+}
+
+
+/** Draw single frame, do SwapBuffers, compute FPS */
+static void
+draw_frame(Display *dpy, Window win)
+{
+   static int frames = 0;
+   static double tRot0 = -1.0, tRate0 = -1.0;
+   double dt, t = current_time();
+
+   if (tRot0 < 0.0)
+      tRot0 = t;
+   dt = t - tRot0;
+   tRot0 = t;
+
+   if (animate) {
+      /* advance rotation for next frame */
+      angle += 70.0 * dt;  /* 70 degrees per second */
+      if (angle > 3600.0)
+         angle -= 3600.0;
+   }
+
+   draw_gears();
+   glXSwapBuffers(dpy, win);
+
+   frames++;
+   
+   if (tRate0 < 0.0)
+      tRate0 = t;
+   if (t - tRate0 >= 5.0) {
+      GLfloat seconds = t - tRate0;
+      GLfloat fps = frames / seconds;
+      printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+             fps);
+      tRate0 = t;
+      frames = 0;
+   }
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   glViewport(0, 0, (GLint) width, (GLint) height);
+
+   if (stereo) {
+      GLfloat w;
+
+      asp = (GLfloat) height / (GLfloat) width;
+      w = fix_point * (1.0 / 5.0);
+
+      left = -5.0 * ((w - 0.5 * eyesep) / fix_point);
+      right = 5.0 * ((w + 0.5 * eyesep) / fix_point);
+   }
+   else {
+      GLfloat h = (GLfloat) height / (GLfloat) width;
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+   }
+   
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -40.0);
+}
+   
+
+
+static void
+init(void)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   /* make the gears */
+   gear1 = glGenLists(1);
+   glNewList(gear1, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   gear(1.0, 4.0, 1.0, 20, 0.7);
+   glEndList();
+
+   gear2 = glGenLists(1);
+   glNewList(gear2, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+   gear(0.5, 2.0, 2.0, 10, 0.7);
+   glEndList();
+
+   gear3 = glGenLists(1);
+   glNewList(gear3, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   gear(1.3, 2.0, 0.5, 10, 0.7);
+   glEndList();
+
+   glEnable(GL_NORMALIZE);
+}
+
+
+/**
+ * Remove window border/decorations.
+ */
+static void
+no_border( Display *dpy, Window w)
+{
+   static const unsigned MWM_HINTS_DECORATIONS = (1 << 1);
+   static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5;
+
+   typedef struct
+   {
+      unsigned long       flags;
+      unsigned long       functions;
+      unsigned long       decorations;
+      long                inputMode;
+      unsigned long       status;
+   } PropMotifWmHints;
+
+   PropMotifWmHints motif_hints;
+   Atom prop, proptype;
+   unsigned long flags = 0;
+
+   /* setup the property */
+   motif_hints.flags = MWM_HINTS_DECORATIONS;
+   motif_hints.decorations = flags;
+
+   /* get the atom for the property */
+   prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
+   if (!prop) {
+      /* something went wrong! */
+      return;
+   }
+
+   /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
+   proptype = prop;
+
+   XChangeProperty( dpy, w,                         /* display, window */
+                    prop, proptype,                 /* property, type */
+                    32,                             /* format: 32-bit datums */
+                    PropModeReplace,                /* mode */
+                    (unsigned char *) &motif_hints, /* data */
+                    PROP_MOTIF_WM_HINTS_ELEMENTS    /* nelements */
+                  );
+}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height,
+             Window *winRet, GLXContext *ctxRet)
+{
+   int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+   int stereoAttribs[] = { GLX_RGBA,
+                           GLX_RED_SIZE, 1,
+                           GLX_GREEN_SIZE, 1,
+                           GLX_BLUE_SIZE, 1,
+                           GLX_DOUBLEBUFFER,
+                           GLX_DEPTH_SIZE, 1,
+                           GLX_STEREO,
+                           None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   if (fullscreen) {
+      x = 0; y = 0;
+      width = DisplayWidth( dpy, scrnum );
+      height = DisplayHeight( dpy, scrnum );
+   }
+
+   if (stereo)
+      visinfo = glXChooseVisual( dpy, scrnum, stereoAttribs );
+   else
+      visinfo = glXChooseVisual( dpy, scrnum, attribs );
+   if (!visinfo) {
+      if (stereo) {
+         printf("Error: couldn't get an RGB, "
+                "Double-buffered, Stereo visual\n");
+      } else
+         printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   /* XXX this is a bad way to get a borderless window! */
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, x, y, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   if (fullscreen)
+      no_border(dpy, win);
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   XFree(visinfo);
+
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+/**
+ * Determine whether or not a GLX extension is supported.
+ */
+static int
+is_glx_extension_supported(Display *dpy, const char *query)
+{
+   const int scrnum = DefaultScreen(dpy);
+   const char *glx_extensions = NULL;
+   const size_t len = strlen(query);
+   const char *ptr;
+
+   if (glx_extensions == NULL) {
+      glx_extensions = glXQueryExtensionsString(dpy, scrnum);
+   }
+
+   ptr = strstr(glx_extensions, query);
+   return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0')));
+}
+
+
+/**
+ * Attempt to determine whether or not the display is synched to vblank.
+ */
+static void
+query_vsync(Display *dpy, GLXDrawable drawable)
+{
+   int interval = 0;
+
+#if defined(GLX_EXT_swap_control)
+   if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) {
+       unsigned int tmp = -1;
+       glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp);
+       interval = tmp;
+   } else
+#endif
+   if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
+      PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA =
+          (PFNGLXGETSWAPINTERVALMESAPROC)
+          glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
+
+      interval = (*pglXGetSwapIntervalMESA)();
+   } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) {
+      /* The default swap interval with this extension is 1.  Assume that it
+       * is set to the default.
+       *
+       * Many Mesa-based drivers default to 0, but all of these drivers also
+       * export GLX_MESA_swap_control.  In that case, this branch will never
+       * be taken, and the correct result should be reported.
+       */
+      interval = 1;
+   }
+
+
+   if (interval > 0) {
+      printf("Running synchronized to the vertical refresh.  The framerate should be\n");
+      if (interval == 1) {
+         printf("approximately the same as the monitor refresh rate.\n");
+      } else if (interval > 1) {
+         printf("approximately 1/%d the monitor refresh rate.\n",
+                interval);
+      }
+   }
+}
+
+/**
+ * Handle one X event.
+ * \return NOP, EXIT or DRAW
+ */
+static int
+handle_event(Display *dpy, Window win, XEvent *event)
+{
+   (void) dpy;
+   (void) win;
+
+   switch (event->type) {
+   case Expose:
+      return DRAW;
+   case ConfigureNotify:
+      reshape(event->xconfigure.width, event->xconfigure.height);
+      break;
+   case KeyPress:
+      {
+         char buffer[10];
+         int r, code;
+         code = XLookupKeysym(&event->xkey, 0);
+         if (code == XK_Left) {
+            view_roty += 5.0;
+         }
+         else if (code == XK_Right) {
+            view_roty -= 5.0;
+         }
+         else if (code == XK_Up) {
+            view_rotx += 5.0;
+         }
+         else if (code == XK_Down) {
+            view_rotx -= 5.0;
+         }
+         else {
+            r = XLookupString(&event->xkey, buffer, sizeof(buffer),
+                              NULL, NULL);
+            if (buffer[0] == 27) {
+               /* escape */
+               return EXIT;
+            }
+            else if (buffer[0] == 'a' || buffer[0] == 'A') {
+               animate = !animate;
+            }
+         }
+         return DRAW;
+      }
+   }
+   return NOP;
+}
+
+
+static void
+event_loop(Display *dpy, Window win)
+{
+   while (1) {
+      int op;
+      while (!animate || XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         op = handle_event(dpy, win, &event);
+         if (op == EXIT)
+            return;
+         else if (op == DRAW)
+            break;
+      }
+
+      draw_frame(dpy, win);
+   }
+}
+
+
+static void
+usage(void)
+{
+   printf("Usage:\n");
+   printf("  -display <displayname>  set the display to run on\n");
+   printf("  -stereo                 run in stereo mode\n");
+   printf("  -fullscreen             run in fullscreen mode\n");
+   printf("  -info                   display OpenGL renderer info\n");
+   printf("  -geometry WxH+X+Y       window geometry\n");
+}
+ 
+
+int
+main(int argc, char *argv[])
+{
+   unsigned int winWidth = 300, winHeight = 300;
+   int x = 0, y = 0;
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-stereo") == 0) {
+         stereo = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-fullscreen") == 0) {
+         fullscreen = GL_TRUE;
+      }
+      else if (i < argc-1 && strcmp(argv[i], "-geometry") == 0) {
+         XParseGeometry(argv[i+1], &x, &y, &winWidth, &winHeight);
+         i++;
+      }
+      else {
+         usage();
+         return -1;
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n",
+	     dpyName ? dpyName : getenv("DISPLAY"));
+      return -1;
+   }
+
+   make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, win, ctx);
+   query_vsync(dpy, win);
+
+   if (printInfo) {
+      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));
+   }
+
+   init();
+
+   /* Set initial projection/viewing transformation.
+    * We can't be sure we'll get a ConfigureNotify event when the window
+    * first appears.
+    */
+   reshape(winWidth, winHeight);
+
+   event_loop(dpy, win);
+
+   glDeleteLists(gear1, 1);
+   glDeleteLists(gear2, 1);
+   glDeleteLists(gear3, 1);
+   glXMakeCurrent(dpy, None, NULL);
+   glXDestroyContext(dpy, ctx);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c
--- Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glxgears_fbconfig.c
+ * Yet-another-version of gears.  Originally ported to GLX by Brian Paul on
+ * 23 March 2001.  Modified to use fbconfigs by Ian Romanick on 10 Feb 2004.
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *
+ * \author Brian Paul
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <assert.h>
+#include "pbutil.h"
+
+static PFNGLXCHOOSEFBCONFIGPROC choose_fbconfig = NULL;
+static PFNGLXGETVISUALFROMFBCONFIGPROC get_visual_from_fbconfig = NULL;
+static PFNGLXCREATENEWCONTEXTPROC create_new_context = NULL;
+static PFNGLXCREATEWINDOWPROC create_window = NULL;
+static PFNGLXDESTROYWINDOWPROC destroy_window = NULL;
+
+#define BENCHMARK
+
+#ifdef BENCHMARK
+
+/* XXX this probably isn't very portable */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* return current time (in seconds) */
+static int
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (int) tv.tv_sec;
+}
+
+#else /*BENCHMARK*/
+
+/* dummy */
+static int
+current_time(void)
+{
+   return 0;
+}
+
+#endif /*BENCHMARK*/
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   glPushMatrix();
+   glTranslatef(-3.0, -2.0, 0.0);
+   glRotatef(angle, 0.0, 0.0, 1.0);
+   glCallList(gear1);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(3.1, -2.0, 0.0);
+   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+   glCallList(gear2);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(-3.1, 4.2, 0.0);
+   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+   glCallList(gear3);
+   glPopMatrix();
+
+   glPopMatrix();
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   GLfloat h = (GLfloat) height / (GLfloat) width;
+
+   glViewport(0, 0, (GLint) width, (GLint) height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -40.0);
+}
+
+
+static void
+init(void)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   /* make the gears */
+   gear1 = glGenLists(1);
+   glNewList(gear1, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   gear(1.0, 4.0, 1.0, 20, 0.7);
+   glEndList();
+
+   gear2 = glGenLists(1);
+   glNewList(gear2, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+   gear(0.5, 2.0, 2.0, 10, 0.7);
+   glEndList();
+
+   gear3 = glGenLists(1);
+   glNewList(gear3, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   gear(1.3, 2.0, 0.5, 10, 0.7);
+   glEndList();
+
+   glEnable(GL_NORMALIZE);
+}
+
+
+static GLXWindow
+dummy_create_window(Display *dpy, GLXFBConfig config, Window win,
+                   const int *attrib_list)
+{
+   (void) dpy;
+   (void) config;
+   (void) attrib_list;
+
+   return (GLXWindow) win;
+}
+
+
+static void
+dummy_destroy_window(Display *dpy, GLXWindow win)
+{
+   (void) dpy;
+   (void) win;
+}
+
+
+/**
+ * Initialize fbconfig related function pointers.
+ */
+static void
+init_fbconfig_functions(Display *dpy, int scrnum)
+{
+   const char * glx_extensions;
+   const char * match;
+   static const char ext_name[] = "GLX_SGIX_fbconfig";
+   const size_t len = strlen( ext_name );
+   int major;
+   int minor;
+   GLboolean ext_version_supported;
+   GLboolean glx_1_3_supported;
+
+
+   /* Determine if GLX 1.3 or greater is supported.
+    */
+   glXQueryVersion(dpy, & major, & minor);
+   glx_1_3_supported = (major == 1) && (minor >= 3);
+
+   /* Determine if GLX_SGIX_fbconfig is supported.
+    */
+   glx_extensions = glXQueryExtensionsString(dpy, scrnum);
+   match = strstr( glx_extensions, ext_name );
+
+   ext_version_supported = (match != NULL)
+       && ((match[len] == '\0') || (match[len] == ' '));
+
+   printf( "GLX 1.3 is %ssupported.\n",
+	   (glx_1_3_supported) ? "" : "not " );
+   printf( "%s is %ssupported.\n",
+	   ext_name, (ext_version_supported) ? "" : "not " );
+
+   if ( glx_1_3_supported ) {
+      choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXChooseFBConfig");
+      get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfig");
+      create_new_context = (PFNGLXCREATENEWCONTEXTPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXCreateNewContext");
+      create_window = (PFNGLXCREATEWINDOWPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXCreateWindow");
+      destroy_window = (PFNGLXDESTROYWINDOWPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXDestroyWindow");
+   }
+   else if ( ext_version_supported ) {
+      choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXChooseFBConfigSGIX");
+      get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfigSGIX");
+      create_new_context = (PFNGLXCREATENEWCONTEXTPROC)
+	 glXGetProcAddressARB((GLubyte *) "glXCreateContextWithConfigSGIX");
+      create_window = dummy_create_window;
+      destroy_window = dummy_destroy_window;
+   }
+   else {
+      printf( "This demo requires either GLX 1.3 or %s be supported.\n",
+	      ext_name );
+      exit(1);
+   }
+
+   if ( choose_fbconfig == NULL ) {
+      printf( "glXChooseFBConfig not found!\n" );
+      exit(1);
+   }
+
+   if ( get_visual_from_fbconfig == NULL ) {
+      printf( "glXGetVisualFromFBConfig not found!\n" );
+      exit(1);
+   }
+
+   if ( create_new_context == NULL ) {
+      printf( "glXCreateNewContext not found!\n" );
+      exit(1);
+   }
+}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height,
+             Window *winRet, GLXWindow *glxWinRet, GLXContext *ctxRet)
+{
+   int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+		    GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+		    GLX_RED_SIZE,      1,
+		    GLX_GREEN_SIZE,    1,
+		    GLX_BLUE_SIZE,     1,
+		    GLX_DOUBLEBUFFER,  GL_TRUE,
+		    GLX_DEPTH_SIZE,    1,
+		    None };
+   GLXFBConfig * fbconfig;
+   int num_configs;
+   int scrnum;
+   int i;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXWindow glxWin;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   init_fbconfig_functions(dpy, scrnum);
+   fbconfig = (*choose_fbconfig)(dpy, scrnum, attrib, & num_configs);
+   if (fbconfig == NULL) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\n");
+      exit(1);
+   }
+
+   printf("\nThe following fbconfigs meet the requirements.  The first one "
+	  "will be used.\n\n");
+   for ( i = 0 ; i < num_configs ; i++ ) {
+      PrintFBConfigInfo(dpy, scrnum, fbconfig[i], GL_TRUE);
+   }
+
+   /* window attributes */
+   visinfo = (*get_visual_from_fbconfig)(dpy, fbconfig[0]);
+   assert(visinfo != NULL);
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   glxWin = (*create_window)(dpy, fbconfig[0], win, NULL);
+
+   ctx = (*create_new_context)(dpy, fbconfig[0], GLX_RGBA_TYPE, NULL, GL_TRUE);
+   if (!ctx) {
+      printf("Error: glXCreateNewContext failed\n");
+      exit(1);
+   }
+
+   XFree(fbconfig);
+
+   *glxWinRet = glxWin;
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+static void
+event_loop(Display *dpy, GLXWindow win)
+{
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+	 case Expose:
+            /* we'll redraw below */
+	    break;
+	 case ConfigureNotify:
+	    reshape(event.xconfigure.width, event.xconfigure.height);
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+                  view_roty += 5.0;
+               }
+               else if (code == XK_Right) {
+                  view_roty -= 5.0;
+               }
+               else if (code == XK_Up) {
+                  view_rotx += 5.0;
+               }
+               else if (code == XK_Down) {
+                  view_rotx -= 5.0;
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                    NULL, NULL);
+                  if (buffer[0] == 27) {
+                     /* escape */
+                     return;
+                  }
+               }
+            }
+         }
+      }
+
+      /* next frame */
+      angle += 2.0;
+
+      draw();
+      glXSwapBuffers(dpy, win);
+
+      /* calc framerate */
+      {
+         static int t0 = -1;
+         static int frames = 0;
+         int t = current_time();
+
+         if (t0 < 0)
+            t0 = t;
+
+         frames++;
+
+         if (t - t0 >= 5.0) {
+            GLfloat seconds = t - t0;
+            GLfloat fps = frames / seconds;
+            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+                   fps);
+            t0 = t;
+            frames = 0;
+         }
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   Window win;
+   GLXWindow glxWin;
+   GLXContext ctx;
+   const char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
+      return -1;
+   }
+
+   make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &glxWin, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, glxWin, ctx);
+
+   if (printInfo) {
+      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));
+   }
+
+   init();
+
+   event_loop(dpy, glxWin);
+
+   glXDestroyContext(dpy, ctx);
+   destroy_window(dpy, glxWin);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c
--- Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008  Red Hat, Inc   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glxgears_pixmap.c
+ * Yet-another-version of gears.  Originally ported to GLX by Brian Paul on
+ * 23 March 2001.  Modified to use fbconfigs by Ian Romanick on 10 Feb 2004.
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *
+ * \author Brian Paul
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Kristian Hoegsberg <krh@redhat.com>
+ */
+
+
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <assert.h>
+#include "pbutil.h"
+
+#define BENCHMARK
+
+#ifdef BENCHMARK
+
+/* XXX this probably isn't very portable */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* return current time (in seconds) */
+static int
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (int) tv.tv_sec;
+}
+
+#else /*BENCHMARK*/
+
+/* dummy */
+static int
+current_time(void)
+{
+   return 0;
+}
+
+#endif /*BENCHMARK*/
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   glPushMatrix();
+   glTranslatef(-3.0, -2.0, 0.0);
+   glRotatef(angle, 0.0, 0.0, 1.0);
+   glCallList(gear1);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(3.1, -2.0, 0.0);
+   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+   glCallList(gear2);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(-3.1, 4.2, 0.0);
+   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+   glCallList(gear3);
+   glPopMatrix();
+
+   glPopMatrix();
+}
+
+
+struct gears {
+   Window win;
+   GLXContext ctx;
+   Pixmap pixmap;
+   GLXPixmap glxpixmap;
+   GC gc;
+   int width, height;
+};
+
+
+/* new window size or exposure */
+static void
+reshape(struct gears *gears, int width, int height)
+{
+   gears->width = width;
+   gears->height = height;
+}
+
+
+static void
+init(int width, int height)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+   GLfloat h = (GLfloat) height / (GLfloat) width;
+
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   /* make the gears */
+   gear1 = glGenLists(1);
+   glNewList(gear1, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   gear(1.0, 4.0, 1.0, 20, 0.7);
+   glEndList();
+
+   gear2 = glGenLists(1);
+   glNewList(gear2, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+   gear(0.5, 2.0, 2.0, 10, 0.7);
+   glEndList();
+
+   gear3 = glGenLists(1);
+   glNewList(gear3, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   gear(1.3, 2.0, 0.5, 10, 0.7);
+   glEndList();
+
+   glEnable(GL_NORMALIZE);
+
+   glViewport(0, 0, (GLint) width, (GLint) height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -40.0);
+}
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height, struct gears *gears)
+{
+   int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+		    GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+		    GLX_RED_SIZE,      1,
+		    GLX_GREEN_SIZE,    1,
+		    GLX_BLUE_SIZE,     1,
+		    GLX_DOUBLEBUFFER,  GL_FALSE,
+		    GLX_DEPTH_SIZE,    1,
+		    None };
+   GLXFBConfig * fbconfig;
+   int num_configs;
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   XVisualInfo *visinfo;
+
+   gears->width = width;
+   gears->height = height;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   fbconfig = glXChooseFBConfig(dpy, scrnum, attrib, & num_configs);
+   if (fbconfig == NULL) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\n");
+      exit(1);
+   }
+
+   /* window attributes */
+   visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
+   assert(visinfo != NULL);
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   gears->win = XCreateWindow( dpy, root, 0, 0, width, height,
+			       0, visinfo->depth, InputOutput,
+			       visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, gears->win, &sizehints);
+      XSetStandardProperties(dpy, gears->win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   gears->gc = XCreateGC(dpy, gears->win, 0, NULL);
+
+   gears->pixmap = XCreatePixmap(dpy, gears->win,
+				 width, height, visinfo->depth);
+   if (!gears->pixmap) {
+      printf("Error: XCreatePixmap failed\n");
+      exit(-1);
+   }
+
+   gears->glxpixmap = glXCreatePixmap(dpy, fbconfig[0], gears->pixmap, NULL);
+   if (!gears->glxpixmap) {
+      printf("Error: glXCreatePixmap failed\n");
+      exit(-1);
+   }
+
+   gears->ctx = glXCreateNewContext(dpy, fbconfig[0],
+				    GLX_RGBA_TYPE, NULL, GL_TRUE);
+   if (!gears->ctx) {
+      printf("Error: glXCreateNewContext failed\n");
+      exit(1);
+   }
+
+   XFree(fbconfig);
+}
+
+
+static void
+event_loop(Display *dpy, struct gears *gears)
+{
+   int x, y;
+
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+	 case Expose:
+            /* we'll redraw below */
+	    break;
+	 case ConfigureNotify:
+	    reshape(gears, event.xconfigure.width, event.xconfigure.height);
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+                  view_roty += 5.0;
+               }
+               else if (code == XK_Right) {
+                  view_roty -= 5.0;
+               }
+               else if (code == XK_Up) {
+                  view_rotx += 5.0;
+               }
+               else if (code == XK_Down) {
+                  view_rotx -= 5.0;
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                    NULL, NULL);
+                  if (buffer[0] == 27) {
+                     /* escape */
+                     return;
+                  }
+               }
+            }
+         }
+      }
+
+      /* next frame */
+      angle += 2.0;
+
+      draw();
+      glFinish();
+
+      for (x = 0; x < gears->width; x += 100)
+         for (y = 0; y < gears->width; y += 100)
+            XCopyArea(dpy, gears->pixmap, gears->win, gears->gc,
+		      50, 50, 100, 100, x, y);
+
+      /* calc framerate */
+      {
+         static int t0 = -1;
+         static int frames = 0;
+         int t = current_time();
+
+         if (t0 < 0)
+            t0 = t;
+
+         frames++;
+
+         if (t - t0 >= 5.0) {
+            GLfloat seconds = t - t0;
+            GLfloat fps = frames / seconds;
+            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+                   fps);
+            t0 = t;
+            frames = 0;
+         }
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   const char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   struct gears gears;
+   int i, width = 200, height = 200;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
+      return -1;
+   }
+
+   make_window(dpy, "glxgears", 0, 0, width, height, &gears);
+   XMapWindow(dpy, gears.win);
+   glXMakeCurrent(dpy, gears.glxpixmap, gears.ctx);
+
+   if (printInfo) {
+      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));
+   }
+
+   init(width, height);
+
+   event_loop(dpy, &gears);
+
+   glXDestroyContext(dpy, gears.ctx);
+   XDestroyWindow(dpy, gears.win);
+   glXDestroyPixmap(dpy, gears.pixmap);
+   XFreePixmap(dpy, gears.pixmap);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxheads.c Mesa-7.8.1.patched/progs/xdemos/glxheads.c
--- Mesa-7.8.1/progs/xdemos/glxheads.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxheads.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,313 @@
+
+/*
+ * Exercise multiple GLX connections on multiple X displays.
+ * Direct GLX contexts are attempted first, then indirect.
+ * Each window will display a spinning green triangle.
+ *
+ * Copyright (C) 2000  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+
+/*
+ * Each display/window/context:
+ */
+struct head {
+   char DisplayName[1000];
+   Display *Dpy;
+   Window Win;
+   GLXContext Context;
+   float Angle;
+   char Renderer[1000];
+   char Vendor[1000];
+   char Version[1000];
+};
+
+
+#define MAX_HEADS 20
+static struct head Heads[MAX_HEADS];
+static int NumHeads = 0;
+
+
+static void
+Error(const char *display, const char *msg)
+{
+   fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg);
+   exit(1);
+}
+
+
+static struct head *
+AddHead(const char *displayName)
+{
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   XVisualInfo *visinfo;
+   int width = 300, height = 300;
+   int xpos = 10, ypos = 10;
+
+   if (NumHeads >= MAX_HEADS)
+      return NULL;
+
+   dpy = XOpenDisplay(displayName);
+   if (!dpy) {
+      Error(displayName, "Unable to open display");
+      return NULL;
+   }
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, attrib);
+   if (!visinfo) {
+      Error(displayName, "Unable to find RGB, double-buffered visual");
+      return NULL;
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   if (!win) {
+      Error(displayName, "Couldn't create window");
+      return NULL;
+   }
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, displayName, displayName,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   ctx = glXCreateContext(dpy, visinfo, NULL, True);
+   if (!ctx) {
+      Error(displayName, "Couldn't create GLX context");
+      return NULL;
+   }
+
+   XMapWindow(dpy, win);
+
+   if (!glXMakeCurrent(dpy, win, ctx)) {
+      Error(displayName, "glXMakeCurrent failed");
+      printf("glXMakeCurrent failed in Redraw()\n");
+      return NULL;
+   }
+
+   /* save the info for this head */
+   {
+      struct head *h = &Heads[NumHeads];
+      const char * tmp;
+
+      if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
+         Error(displayName, "displayName string length overflow");
+         return NULL;
+      }
+      strcpy(h->DisplayName, displayName);
+
+      h->Dpy = dpy;
+      h->Win = win;
+      h->Context = ctx;
+      h->Angle = 0.0;
+
+      tmp = (char *) glGetString(GL_VERSION);
+      if (strlen(tmp) + 1 > sizeof(h->Version)) {
+         Error(displayName, "GL_VERSION string length overflow");
+         return NULL;
+      }
+      strcpy(h->Version, tmp);
+
+      tmp = (char *) glGetString(GL_VENDOR);
+      if (strlen(tmp) + 1 > sizeof(h->Vendor)) {
+         Error(displayName, "GL_VENDOR string length overflow");
+         return NULL;
+      }
+      strcpy(h->Vendor, tmp);
+
+      tmp = (char *) glGetString(GL_RENDERER);
+      if (strlen(tmp) + 1 > sizeof(h->Renderer)) {
+         Error(displayName, "GL_RENDERER string length overflow");
+         return NULL;
+      }
+      strcpy(h->Renderer, tmp);
+
+      NumHeads++;
+      return &Heads[NumHeads-1];
+   }
+
+}
+
+
+static void
+Redraw(struct head *h)
+{
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed");
+      printf("glXMakeCurrent failed in Redraw()\n");
+      return;
+   }
+
+   h->Angle += 1.0;
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   /* draw green triangle */
+   glColor3f(0.0, 1.0, 0.0);
+   glPushMatrix();
+   glRotatef(h->Angle, 0, 0, 1);
+   glBegin(GL_TRIANGLES);
+   glVertex2f(0, 0.8);
+   glVertex2f(-0.8, -0.7);
+   glVertex2f(0.8, -0.7);
+   glEnd();
+   glPopMatrix();
+
+   glXSwapBuffers(h->Dpy, h->Win);
+}
+
+
+
+static void
+Resize(const struct head *h, unsigned int width, unsigned int height)
+{
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
+      return;
+   }
+   glFlush();
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+}
+
+
+
+static void
+EventLoop(void)
+{
+   while (1) {
+      int i;
+      for (i = 0; i < NumHeads; i++) {
+         struct head *h = &Heads[i];
+         while (XPending(h->Dpy) > 0) {
+            XEvent event;
+            XNextEvent(h->Dpy, &event);
+            if (event.xany.window == h->Win) {
+               switch (event.type) {
+                  case Expose:
+                     Redraw(h);
+                     break;
+                  case ConfigureNotify:
+                     Resize(h, event.xconfigure.width, event.xconfigure.height);
+                     break;
+                  case KeyPress:
+                     return;
+                  default:
+                     /*no-op*/ ;
+               }
+            }
+            else {
+               printf("window mismatch\n");
+            }
+         }
+         Redraw(h);
+      }
+      usleep(1);
+   }
+}
+
+
+
+static void
+PrintInfo(const struct head *h)
+{
+   printf("Name: %s\n", h->DisplayName);
+   printf("  Display:     %p\n", (void *) h->Dpy);
+   printf("  Window:      0x%x\n", (int) h->Win);
+   printf("  Context:     0x%lx\n", (long) h->Context);
+   printf("  GL_VERSION:  %s\n", h->Version);
+   printf("  GL_VENDOR:   %s\n", h->Vendor);
+   printf("  GL_RENDERER: %s\n", h->Renderer);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   int i;
+   if (argc == 1) {
+      struct head *h;
+      printf("glxheads: exercise multiple GLX connections (any key = exit)\n");
+      printf("Usage:\n");
+      printf("  glxheads xdisplayname ...\n");
+      printf("Example:\n");
+      printf("  glxheads :0 mars:0 venus:1\n");
+
+      h = AddHead(XDisplayName(NULL));
+      if (h)
+         PrintInfo(h);
+   }
+   else {
+      for (i = 1; i < argc; i++) {
+         const char *name = argv[i];
+         struct head *h = AddHead(name);
+         if (h) {
+            PrintInfo(h);
+         }
+      }
+   }
+
+   EventLoop();
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxinfo.c Mesa-7.8.1.patched/progs/xdemos/glxinfo.c
--- Mesa-7.8.1/progs/xdemos/glxinfo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxinfo.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,1195 @@
+/*
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * This program is a work-alike of the IRIX glxinfo program.
+ * Command line options:
+ *  -t                     print wide table
+ *  -v                     print verbose information
+ *  -display DisplayName   specify the X display to interogate
+ *  -b                     only print ID of "best" visual on screen 0
+ *  -i                     use indirect rendering connection only
+ *  -l                     print interesting OpenGL limits (added 5 Sep 2002)
+ *
+ * Brian Paul  26 January 2000
+ */
+
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#ifndef GLX_NONE_EXT
+#define GLX_NONE_EXT  0x8000
+#endif
+
+#ifndef GLX_TRANSPARENT_RGB
+#define GLX_TRANSPARENT_RGB 0x8008
+#endif
+
+#ifndef GLX_RGBA_BIT
+#define GLX_RGBA_BIT			0x00000001
+#endif
+
+#ifndef GLX_COLOR_INDEX_BIT
+#define GLX_COLOR_INDEX_BIT		0x00000002
+#endif
+
+typedef enum
+{
+   Normal,
+   Wide,
+   Verbose
+} InfoMode;
+
+
+struct visual_attribs
+{
+   /* X visual attribs */
+   int id;
+   int klass;
+   int depth;
+   int redMask, greenMask, blueMask;
+   int colormapSize;
+   int bitsPerRGB;
+
+   /* GL visual attribs */
+   int supportsGL;
+   int transparentType;
+   int transparentRedValue;
+   int transparentGreenValue;
+   int transparentBlueValue;
+   int transparentAlphaValue;
+   int transparentIndexValue;
+   int bufferSize;
+   int level;
+   int render_type;
+   int doubleBuffer;
+   int stereo;
+   int auxBuffers;
+   int redSize, greenSize, blueSize, alphaSize;
+   int depthSize;
+   int stencilSize;
+   int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
+   int numSamples, numMultisample;
+   int visualCaveat;
+};
+
+   
+/*
+ * Print a list of extensions, with word-wrapping.
+ */
+static void
+print_extension_list(const char *ext)
+{
+   const char *indentString = "    ";
+   const int indent = 4;
+   const int max = 79;
+   int width, i, j;
+
+   if (!ext || !ext[0])
+      return;
+
+   width = indent;
+   printf("%s", indentString);
+   i = j = 0;
+   while (1) {
+      if (ext[j] == ' ' || ext[j] == 0) {
+         /* found end of an extension name */
+         const int len = j - i;
+         if (width + len > max) {
+            /* start a new line */
+            printf("\n");
+            width = indent;
+            printf("%s", indentString);
+         }
+         /* print the extension name between ext[i] and ext[j] */
+         while (i < j) {
+            printf("%c", ext[i]);
+            i++;
+         }
+         /* either we're all done, or we'll continue with next extension */
+         width += len + 1;
+         if (ext[j] == 0) {
+            break;
+         }
+         else {
+            i++;
+            j++;
+            if (ext[j] == 0)
+               break;
+            printf(", ");
+            width += 2;
+         }
+      }
+      j++;
+   }
+   printf("\n");
+}
+
+
+static void
+print_display_info(Display *dpy)
+{
+   printf("name of display: %s\n", DisplayString(dpy));
+}
+
+
+/**
+ * Print interesting limits for vertex/fragment programs.
+ */
+static void
+print_program_limits(GLenum target)
+{
+#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
+   struct token_name {
+      GLenum token;
+      const char *name;
+   };
+   static const struct token_name common_limits[] = {
+      { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB" },
+      { GL_MAX_PROGRAM_PARAMETERS_ARB, "GL_MAX_PROGRAM_PARAMETERS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB" },
+      { GL_MAX_PROGRAM_ATTRIBS_ARB, "GL_MAX_PROGRAM_ATTRIBS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB" },
+      { GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" },
+      { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" },
+      { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" },
+      { (GLenum) 0, NULL }
+   };
+   static const struct token_name fragment_limits[] = {
+      { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB" },
+      { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" },
+      { (GLenum) 0, NULL }
+   };
+
+   PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC)
+      glXGetProcAddressARB((GLubyte *) "glGetProgramivARB");
+
+   GLint max[1];
+   int i;
+
+   if (target == GL_VERTEX_PROGRAM_ARB) {
+      printf("    GL_VERTEX_PROGRAM_ARB:\n");
+   }
+   else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      printf("    GL_FRAGMENT_PROGRAM_ARB:\n");
+   }
+   else {
+      return; /* something's wrong */
+   }
+
+   for (i = 0; common_limits[i].token; i++) {
+      GetProgramivARB_func(target, common_limits[i].token, max);
+      if (glGetError() == GL_NO_ERROR) {
+         printf("        %s = %d\n", common_limits[i].name, max[0]);
+      }
+   }
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      for (i = 0; fragment_limits[i].token; i++) {
+         GetProgramivARB_func(target, fragment_limits[i].token, max);
+         if (glGetError() == GL_NO_ERROR) {
+            printf("        %s = %d\n", fragment_limits[i].name, max[0]);
+         }
+      }
+   }
+#endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */
+}
+
+
+/**
+ * Print interesting limits for vertex/fragment shaders.
+ */
+static void
+print_shader_limits(GLenum target)
+{
+   struct token_name {
+      GLenum token;
+      const char *name;
+   };
+#if defined(GL_ARB_vertex_shader)
+   static const struct token_name vertex_limits[] = {
+      { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB" },
+      { GL_MAX_VARYING_FLOATS_ARB, "GL_MAX_VARYING_FLOATS_ARB" },
+      { GL_MAX_VERTEX_ATTRIBS_ARB, "GL_MAX_VERTEX_ATTRIBS_ARB" },
+      { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
+      { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB" },
+      { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB" },
+      { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
+      { (GLenum) 0, NULL }
+   };
+#endif
+#if defined(GL_ARB_fragment_shader)
+   static const struct token_name fragment_limits[] = {
+      { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB" },
+      { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
+      { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
+      { (GLenum) 0, NULL }
+   };
+#endif
+   GLint max[1];
+   int i;
+
+#if defined(GL_ARB_vertex_shader)
+   if (target == GL_VERTEX_SHADER_ARB) {
+      printf("    GL_VERTEX_SHADER_ARB:\n");
+      for (i = 0; vertex_limits[i].token; i++) {
+         glGetIntegerv(vertex_limits[i].token, max);
+         if (glGetError() == GL_NO_ERROR) {
+            printf("        %s = %d\n", vertex_limits[i].name, max[0]);
+         }
+      }
+   }
+#endif
+#if defined(GL_ARB_fragment_shader)
+   if (target == GL_FRAGMENT_SHADER_ARB) {
+      printf("    GL_FRAGMENT_SHADER_ARB:\n");
+      for (i = 0; fragment_limits[i].token; i++) {
+         glGetIntegerv(fragment_limits[i].token, max);
+         if (glGetError() == GL_NO_ERROR) {
+            printf("        %s = %d\n", fragment_limits[i].name, max[0]);
+         }
+      }
+   }
+#endif
+}
+
+
+/**
+ * Print interesting OpenGL implementation limits.
+ */
+static void
+print_limits(const char *extensions)
+{
+   struct token_name {
+      GLuint count;
+      GLenum token;
+      const char *name;
+   };
+   static const struct token_name limits[] = {
+      { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" },
+      { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" },
+      { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" },
+      { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" },
+      { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" },
+      { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" },
+      { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" },
+      { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" },
+      { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" },
+      { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" },
+      { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" },
+      { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" },
+      { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" },
+      { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" },
+      { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" },
+      { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" },
+      { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" },
+      { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" },
+      { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" },
+      { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" },
+      { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" },
+#if defined(GL_ARB_texture_cube_map)
+      { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" },
+#endif
+#if defined(GLX_NV_texture_rectangle)
+      { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" },
+#endif
+#if defined(GL_ARB_texture_compression)
+      { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" },
+#endif
+#if defined(GL_ARB_multitexture)
+      { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" },
+#endif
+#if defined(GL_EXT_texture_lod_bias)
+      { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" },
+#endif
+#if defined(GL_EXT_texture_filter_anisotropic)
+      { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" },
+#endif
+#if defined(GL_ARB_draw_buffers)
+      { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB" },
+#endif
+      { 0, (GLenum) 0, NULL }
+   };
+   GLint i, max[2];
+
+   printf("OpenGL limits:\n");
+   for (i = 0; limits[i].count; i++) {
+      glGetIntegerv(limits[i].token, max);
+      if (glGetError() == GL_NO_ERROR) {
+         if (limits[i].count == 1)
+            printf("    %s = %d\n", limits[i].name, max[0]);
+         else /* XXX fix if we ever query something with more than 2 values */
+            printf("    %s = %d, %d\n", limits[i].name, max[0], max[1]);
+      }
+   }
+
+   /* these don't fit into the above mechanism, unfortunately */
+   glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max);
+   glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1);
+   if (glGetError() == GL_NONE) {
+      printf("    GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]);
+   }
+
+#if defined(GL_ARB_vertex_program)
+   if (strstr(extensions, "GL_ARB_vertex_program")) {
+      print_program_limits(GL_VERTEX_PROGRAM_ARB);
+   }
+#endif
+#if defined(GL_ARB_fragment_program)
+   if (strstr(extensions, "GL_ARB_fragment_program")) {
+      print_program_limits(GL_FRAGMENT_PROGRAM_ARB);
+   }
+#endif
+#if defined(GL_ARB_vertex_shader)
+   if (strstr(extensions, "GL_ARB_vertex_shader")) {
+      print_shader_limits(GL_VERTEX_SHADER_ARB);
+   }
+#endif
+#if defined(GL_ARB_fragment_shader)
+   if (strstr(extensions, "GL_ARB_fragment_shader")) {
+      print_shader_limits(GL_FRAGMENT_SHADER_ARB);
+   }
+#endif
+}
+
+
+static void
+print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
+{
+   Window win;
+   int attribSingle[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      None };
+   int attribDouble[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None };
+
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   GLXContext ctx = NULL;
+   XVisualInfo *visinfo;
+   int width = 100, height = 100;
+
+   root = RootWindow(dpy, scrnum);
+
+   /*
+    * Find a basic GLX visual.  We'll then create a rendering context and
+    * query various info strings.
+    */
+   visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+   if (!visinfo)
+      visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+
+   if (visinfo)
+      ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
+
+#ifdef GLX_VERSION_1_3
+   /* Try glXChooseFBConfig() if glXChooseVisual didn't work.
+    * XXX when would that happen?
+    */
+   if (!visinfo) {
+      int fbAttribSingle[] = {
+	 GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+	 GLX_RED_SIZE,      1,
+	 GLX_GREEN_SIZE,    1,
+	 GLX_BLUE_SIZE,     1,
+	 GLX_DOUBLEBUFFER,  GL_FALSE,
+	 None };
+      int fbAttribDouble[] = {
+	 GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+	 GLX_RED_SIZE,      1,
+	 GLX_GREEN_SIZE,    1,
+	 GLX_BLUE_SIZE,     1,
+	 GLX_DOUBLEBUFFER,  GL_TRUE,
+	 None };
+      GLXFBConfig *configs = NULL;
+      int nConfigs;
+
+      configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
+      if (!configs)
+	 configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
+
+      if (configs) {
+	 visinfo = glXGetVisualFromFBConfig(dpy, configs[0]);
+	 ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect);
+	 XFree(configs);
+      }
+   }
+#endif
+
+   if (!visinfo) {
+      fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
+      return;
+   }
+
+   if (!ctx) {
+      fprintf(stderr, "Error: glXCreateContext failed\n");
+      XFree(visinfo);
+      return;
+   }
+
+   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 (glXMakeCurrent(dpy, win, ctx)) {
+      const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
+      const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
+      const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
+      const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
+      const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
+      const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
+      const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
+      const char *glVendor = (const char *) glGetString(GL_VENDOR);
+      const char *glRenderer = (const char *) glGetString(GL_RENDERER);
+      const char *glVersion = (const char *) glGetString(GL_VERSION);
+      const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
+      int glxVersionMajor;
+      int glxVersionMinor;
+      char *displayName = NULL;
+      char *colon = NULL, *period = NULL;
+      
+      if (! glXQueryVersion( dpy, & glxVersionMajor, & glxVersionMinor )) {
+         fprintf(stderr, "Error: glXQueryVersion failed\n");
+         exit(1);
+      }
+
+      /* Strip the screen number from the display name, if present. */
+      if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
+         fprintf(stderr, "Error: malloc() failed\n");
+         exit(1);
+      }
+      strcpy(displayName, DisplayString(dpy));
+      colon = strrchr(displayName, ':');
+      if (colon) {
+         period = strchr(colon, '.');
+         if (period)
+            *period = '\0';
+      }
+      printf("display: %s  screen: %d\n", displayName, scrnum);
+      free(displayName);
+      printf("direct rendering: ");
+      if (glXIsDirect(dpy, ctx)) {
+         printf("Yes\n");
+      } else {
+         if (!allowDirect) {
+            printf("No (-i specified)\n");
+         } else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
+            printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
+         } else {
+            printf("No (If you want to find out why, try setting "
+                   "LIBGL_DEBUG=verbose)\n");
+         }
+      }
+      printf("server glx vendor string: %s\n", serverVendor);
+      printf("server glx version string: %s\n", serverVersion);
+      printf("server glx extensions:\n");
+      print_extension_list(serverExtensions);
+      printf("client glx vendor string: %s\n", clientVendor);
+      printf("client glx version string: %s\n", clientVersion);
+      printf("client glx extensions:\n");
+      print_extension_list(clientExtensions);
+      printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor);
+      printf("GLX extensions:\n");
+      print_extension_list(glxExtensions);
+      printf("OpenGL vendor string: %s\n", glVendor);
+      printf("OpenGL renderer string: %s\n", glRenderer);
+      printf("OpenGL version string: %s\n", glVersion);
+#ifdef GL_VERSION_2_0
+      if (glVersion[0] >= '2' && glVersion[1] == '.') {
+         char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
+         printf("OpenGL shading language version string: %s\n", v);
+      }
+#endif
+
+      printf("OpenGL extensions:\n");
+      print_extension_list(glExtensions);
+      if (limits)
+         print_limits(glExtensions);
+   }
+   else {
+      fprintf(stderr, "Error: glXMakeCurrent failed\n");
+   }
+
+   glXDestroyContext(dpy, ctx);
+   XFree(visinfo);
+   XDestroyWindow(dpy, win);
+}
+
+
+static const char *
+visual_class_name(int cls)
+{
+   switch (cls) {
+      case StaticColor:
+         return "StaticColor";
+      case PseudoColor:
+         return "PseudoColor";
+      case StaticGray:
+         return "StaticGray";
+      case GrayScale:
+         return "GrayScale";
+      case TrueColor:
+         return "TrueColor";
+      case DirectColor:
+         return "DirectColor";
+      default:
+         return "";
+   }
+}
+
+
+static const char *
+visual_class_abbrev(int cls)
+{
+   switch (cls) {
+      case StaticColor:
+         return "sc";
+      case PseudoColor:
+         return "pc";
+      case StaticGray:
+         return "sg";
+      case GrayScale:
+         return "gs";
+      case TrueColor:
+         return "tc";
+      case DirectColor:
+         return "dc";
+      default:
+         return "";
+   }
+}
+
+static const char *
+visual_render_type_name(int type)
+{
+   switch (type) {
+      case GLX_RGBA_BIT:
+         return "rgba";
+      case GLX_COLOR_INDEX_BIT:
+         return "ci";
+      case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
+         return "rgba|ci";
+      default:
+         return "";
+      }
+}
+
+static GLboolean
+get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
+                   struct visual_attribs *attribs)
+{
+   const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
+   int rgba;
+
+   memset(attribs, 0, sizeof(struct visual_attribs));
+
+   attribs->id = vInfo->visualid;
+#if defined(__cplusplus) || defined(c_plusplus)
+   attribs->klass = vInfo->c_class;
+#else
+   attribs->klass = vInfo->class;
+#endif
+   attribs->depth = vInfo->depth;
+   attribs->redMask = vInfo->red_mask;
+   attribs->greenMask = vInfo->green_mask;
+   attribs->blueMask = vInfo->blue_mask;
+   attribs->colormapSize = vInfo->colormap_size;
+   attribs->bitsPerRGB = vInfo->bits_per_rgb;
+
+   if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
+       !attribs->supportsGL)
+      return GL_FALSE;
+   glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
+   glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
+   glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
+   if (rgba)
+      attribs->render_type = GLX_RGBA_BIT;
+   else
+      attribs->render_type = GLX_COLOR_INDEX_BIT;
+   
+   glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
+   glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
+   glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+   glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
+   glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
+   glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
+   glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
+   glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
+   glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
+   glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
+   glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
+   glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
+   glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+
+   /* get transparent pixel stuff */
+   glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
+   if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+     glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
+     glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
+     glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
+     glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
+   }
+   else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+     glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
+   }
+
+   /* multisample attribs */
+#ifdef GLX_ARB_multisample
+   if (ext && strstr(ext, "GLX_ARB_multisample")) {
+      glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
+      glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
+   }
+#endif
+   else {
+      attribs->numSamples = 0;
+      attribs->numMultisample = 0;
+   }
+
+#if defined(GLX_EXT_visual_rating)
+   if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
+      glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
+   }
+   else {
+      attribs->visualCaveat = GLX_NONE_EXT;
+   }
+#else
+   attribs->visualCaveat = 0;
+#endif
+
+   return GL_TRUE;
+}
+
+#ifdef GLX_VERSION_1_3
+
+static int
+glx_token_to_visual_class(int visual_type)
+{
+   switch (visual_type) {
+   case GLX_TRUE_COLOR:
+      return TrueColor;
+   case GLX_DIRECT_COLOR:
+      return DirectColor;
+   case GLX_PSEUDO_COLOR:
+      return PseudoColor;
+   case GLX_STATIC_COLOR:
+      return StaticColor;
+   case GLX_GRAY_SCALE:
+      return GrayScale;
+   case GLX_STATIC_GRAY:
+      return StaticGray;
+   case GLX_NONE:
+   default:
+      return None;
+   }
+}
+
+static GLboolean
+get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
+		     struct visual_attribs *attribs)
+{
+   int visual_type;
+
+   memset(attribs, 0, sizeof(struct visual_attribs));
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id);
+
+#if 0
+   attribs->depth = vInfo->depth;
+   attribs->redMask = vInfo->red_mask;
+   attribs->greenMask = vInfo->green_mask;
+   attribs->blueMask = vInfo->blue_mask;
+   attribs->colormapSize = vInfo->colormap_size;
+   attribs->bitsPerRGB = vInfo->bits_per_rgb;
+#endif
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
+   attribs->klass = glx_token_to_visual_class(visual_type);
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+
+   /* get transparent pixel stuff */
+   glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
+   if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
+     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
+     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
+     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
+   }
+   else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
+   }
+
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
+   glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+
+   return GL_TRUE;
+}
+
+#endif
+
+
+
+static void
+print_visual_attribs_verbose(const struct visual_attribs *attribs)
+{
+   printf("Visual ID: %x  depth=%d  class=%s\n",
+          attribs->id, attribs->depth, visual_class_name(attribs->klass));
+   printf("    bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
+          attribs->bufferSize, attribs->level,
+	  visual_render_type_name(attribs->render_type),
+          attribs->doubleBuffer, attribs->stereo);
+   printf("    rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
+          attribs->redSize, attribs->greenSize,
+          attribs->blueSize, attribs->alphaSize);
+   printf("    auxBuffers=%d depthSize=%d stencilSize=%d\n",
+          attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
+   printf("    accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
+          attribs->accumRedSize, attribs->accumGreenSize,
+          attribs->accumBlueSize, attribs->accumAlphaSize);
+   printf("    multiSample=%d  multiSampleBuffers=%d\n",
+          attribs->numSamples, attribs->numMultisample);
+#ifdef GLX_EXT_visual_rating
+   if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
+      printf("    visualCaveat=None\n");
+   else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
+      printf("    visualCaveat=Slow\n");
+   else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
+      printf("    visualCaveat=Nonconformant\n");
+#endif
+   if (attribs->transparentType == GLX_NONE) {
+     printf("    Opaque.\n");
+   }
+   else if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+     printf("    Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue);
+   }
+   else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+     printf("    Transparent index=%d\n",attribs->transparentIndexValue);
+   }
+}
+
+
+static void
+print_visual_attribs_short_header(void)
+{
+ printf("   visual  x  bf lv rg d st colorbuffer ax dp st accumbuffer  ms  cav\n");
+ printf(" id dep cl sp sz l  ci b ro  r  g  b  a bf th cl  r  g  b  a ns b eat\n");
+ printf("----------------------------------------------------------------------\n");
+}
+
+
+static void
+print_visual_attribs_short(const struct visual_attribs *attribs)
+{
+   char *caveat = NULL;
+#ifdef GLX_EXT_visual_rating
+   if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
+      caveat = "None";
+   else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
+      caveat = "Slow";
+   else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
+      caveat = "Ncon";
+   else
+      caveat = "None";
+#else
+   caveat = "None";
+#endif 
+
+   printf("0x%02x %2d %2s %2d %2d %2d %c%c %c  %c %2d %2d %2d %2d %2d %2d %2d",
+          attribs->id,
+          attribs->depth,
+          visual_class_abbrev(attribs->klass),
+          attribs->transparentType != GLX_NONE,
+          attribs->bufferSize,
+          attribs->level,
+          (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ',
+          (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ',
+          attribs->doubleBuffer ? 'y' : '.',
+          attribs->stereo ? 'y' : '.',
+          attribs->redSize, attribs->greenSize,
+          attribs->blueSize, attribs->alphaSize,
+          attribs->auxBuffers,
+          attribs->depthSize,
+          attribs->stencilSize
+          );
+
+   printf(" %2d %2d %2d %2d %2d %1d %s\n",
+          attribs->accumRedSize, attribs->accumGreenSize,
+          attribs->accumBlueSize, attribs->accumAlphaSize,
+          attribs->numSamples, attribs->numMultisample,
+          caveat
+          );
+}
+
+
+static void
+print_visual_attribs_long_header(void)
+{
+ printf("Vis  Vis   Visual Trans  buff lev render DB ste  r   g   b   a  aux dep ste  accum buffers  MS   MS\n");
+ printf(" ID Depth   Type  parent size el   type     reo sz  sz  sz  sz  buf th  ncl  r   g   b   a  num bufs\n");
+ printf("----------------------------------------------------------------------------------------------------\n");
+}
+
+
+static void
+print_visual_attribs_long(const struct visual_attribs *attribs)
+{
+   printf("0x%2x %2d %-11s %2d     %2d %2d  %4s %3d %3d %3d %3d %3d %3d",
+          attribs->id,
+          attribs->depth,
+          visual_class_name(attribs->klass),
+          attribs->transparentType != GLX_NONE,
+          attribs->bufferSize,
+          attribs->level,
+          visual_render_type_name(attribs->render_type),
+          attribs->doubleBuffer,
+          attribs->stereo,
+          attribs->redSize, attribs->greenSize,
+          attribs->blueSize, attribs->alphaSize
+          );
+
+   printf(" %3d %4d %2d %3d %3d %3d %3d  %2d  %2d\n",
+          attribs->auxBuffers,
+          attribs->depthSize,
+          attribs->stencilSize,
+          attribs->accumRedSize, attribs->accumGreenSize,
+          attribs->accumBlueSize, attribs->accumAlphaSize,
+          attribs->numSamples, attribs->numMultisample
+          );
+}
+
+
+static void
+print_visual_info(Display *dpy, int scrnum, InfoMode mode)
+{
+   XVisualInfo theTemplate;
+   XVisualInfo *visuals;
+   int numVisuals, numGlxVisuals;
+   long mask;
+   int i;
+   struct visual_attribs attribs;
+
+   /* get list of all visuals on this screen */
+   theTemplate.screen = scrnum;
+   mask = VisualScreenMask;
+   visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
+
+   numGlxVisuals = 0;
+   for (i = 0; i < numVisuals; i++) {
+      if (get_visual_attribs(dpy, &visuals[i], &attribs))
+	 numGlxVisuals++;
+   }
+
+   if (numGlxVisuals == 0)
+      return;
+
+   printf("%d GLX Visuals\n", numGlxVisuals);
+
+   if (mode == Normal)
+      print_visual_attribs_short_header();
+   else if (mode == Wide)
+      print_visual_attribs_long_header();
+
+   for (i = 0; i < numVisuals; i++) {
+      if (!get_visual_attribs(dpy, &visuals[i], &attribs))
+	 continue;
+
+      if (mode == Verbose)
+	 print_visual_attribs_verbose(&attribs);
+      else if (mode == Normal)
+         print_visual_attribs_short(&attribs);
+      else if (mode == Wide) 
+         print_visual_attribs_long(&attribs);
+   }
+   printf("\n");
+
+   XFree(visuals);
+}
+
+#ifdef GLX_VERSION_1_3
+
+static void
+print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode)
+{
+   int numFBConfigs = 0;
+   struct visual_attribs attribs;
+   GLXFBConfig *fbconfigs;
+   int i;
+
+   /* get list of all fbconfigs on this screen */
+   fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs);
+
+   if (numFBConfigs == 0) {
+      XFree(fbconfigs);
+      return;
+   }
+
+   printf("%d GLXFBConfigs:\n", numFBConfigs);
+   if (mode == Normal)
+      print_visual_attribs_short_header();
+   else if (mode == Wide)
+      print_visual_attribs_long_header();
+
+   for (i = 0; i < numFBConfigs; i++) {
+      get_fbconfig_attribs(dpy, fbconfigs[i], &attribs);
+
+      if (mode == Verbose) 
+         print_visual_attribs_verbose(&attribs);
+      else if (mode == Normal)
+	 print_visual_attribs_short(&attribs);
+      else if (mode == Wide)
+         print_visual_attribs_long(&attribs);
+   }
+   printf("\n");
+
+   XFree(fbconfigs);
+}
+
+#endif
+
+/*
+ * Stand-alone Mesa doesn't really implement the GLX protocol so it
+ * doesn't really know the GLX attributes associated with an X visual.
+ * The first time a visual is presented to Mesa's pseudo-GLX it
+ * attaches ancilliary buffers to it (like depth and stencil).
+ * But that usually only works if glXChooseVisual is used.
+ * This function calls glXChooseVisual() to sort of "prime the pump"
+ * for Mesa's GLX so that the visuals that get reported actually
+ * reflect what applications will see.
+ * This has no effect when using true GLX.
+ */
+static void
+mesa_hack(Display *dpy, int scrnum)
+{
+   static int attribs[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DEPTH_SIZE, 1,
+      GLX_STENCIL_SIZE, 1,
+      GLX_ACCUM_RED_SIZE, 1,
+      GLX_ACCUM_GREEN_SIZE, 1,
+      GLX_ACCUM_BLUE_SIZE, 1,
+      GLX_ACCUM_ALPHA_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None
+   };
+   XVisualInfo *visinfo;
+
+   visinfo = glXChooseVisual(dpy, scrnum, attribs);
+   if (visinfo)
+      XFree(visinfo);
+}
+
+
+/*
+ * Examine all visuals to find the so-called best one.
+ * We prefer deepest RGBA buffer with depth, stencil and accum
+ * that has no caveats.
+ */
+static int
+find_best_visual(Display *dpy, int scrnum)
+{
+   XVisualInfo theTemplate;
+   XVisualInfo *visuals;
+   int numVisuals;
+   long mask;
+   int i;
+   struct visual_attribs bestVis;
+
+   /* get list of all visuals on this screen */
+   theTemplate.screen = scrnum;
+   mask = VisualScreenMask;
+   visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
+
+   /* init bestVis with first visual info */
+   get_visual_attribs(dpy, &visuals[0], &bestVis);
+
+   /* try to find a "better" visual */
+   for (i = 1; i < numVisuals; i++) {
+      struct visual_attribs vis;
+
+      get_visual_attribs(dpy, &visuals[i], &vis);
+
+      /* always skip visuals with caveats */
+      if (vis.visualCaveat != GLX_NONE_EXT)
+         continue;
+
+      /* see if this vis is better than bestVis */
+      if ((!bestVis.supportsGL && vis.supportsGL) ||
+          (bestVis.visualCaveat != GLX_NONE_EXT) ||
+          (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) ||
+          (!bestVis.doubleBuffer && vis.doubleBuffer) ||
+          (bestVis.redSize < vis.redSize) ||
+          (bestVis.greenSize < vis.greenSize) ||
+          (bestVis.blueSize < vis.blueSize) ||
+          (bestVis.alphaSize < vis.alphaSize) ||
+          (bestVis.depthSize < vis.depthSize) ||
+          (bestVis.stencilSize < vis.stencilSize) ||
+          (bestVis.accumRedSize < vis.accumRedSize)) {
+         /* found a better visual */
+         bestVis = vis;
+      }
+   }
+
+   XFree(visuals);
+
+   return bestVis.id;
+}
+
+
+static void
+usage(void)
+{
+   printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
+   printf("\t-v: Print visuals info in verbose form.\n");
+   printf("\t-t: Print verbose table.\n");
+   printf("\t-display <dname>: Print GLX visuals on specified server.\n");
+   printf("\t-h: This information.\n");
+   printf("\t-i: Force an indirect rendering context.\n");
+   printf("\t-b: Find the 'best' visual and print its number.\n");
+   printf("\t-l: Print interesting OpenGL limits.\n");
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   char *displayName = NULL;
+   Display *dpy;
+   int numScreens, scrnum;
+   InfoMode mode = Normal;
+   GLboolean findBest = GL_FALSE;
+   GLboolean limits = GL_FALSE;
+   Bool allowDirect = True;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
+         displayName = argv[i + 1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-t") == 0) {
+         mode = Wide;
+      }
+      else if (strcmp(argv[i], "-v") == 0) {
+         mode = Verbose;
+      }
+      else if (strcmp(argv[i], "-b") == 0) {
+         findBest = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-i") == 0) {
+         allowDirect = False;
+      }
+      else if (strcmp(argv[i], "-l") == 0) {
+         limits = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-h") == 0) {
+         usage();
+         return 0;
+      }
+      else {
+         printf("Unknown option `%s'\n", argv[i]);
+         usage();
+         return 0;
+      }
+   }
+
+   dpy = XOpenDisplay(displayName);
+   if (!dpy) {
+      fprintf(stderr, "Error: unable to open display %s\n", XDisplayName(displayName));
+      return -1;
+   }
+
+   if (findBest) {
+      int b;
+      mesa_hack(dpy, 0);
+      b = find_best_visual(dpy, 0);
+      printf("%d\n", b);
+   }
+   else {
+      numScreens = ScreenCount(dpy);
+      print_display_info(dpy);
+      for (scrnum = 0; scrnum < numScreens; scrnum++) {
+         mesa_hack(dpy, scrnum);
+         print_screen_info(dpy, scrnum, allowDirect, limits);
+         printf("\n");
+         print_visual_info(dpy, scrnum, mode);
+#ifdef GLX_VERSION_1_3
+         print_fbconfig_info(dpy, scrnum, mode);
+#endif
+         if (scrnum + 1 < numScreens)
+            printf("\n\n");
+      }
+   }
+
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxpbdemo.c Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c
--- Mesa-7.8.1/progs/xdemos/glxpbdemo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,431 @@
+
+/*
+ * This program demonstrates how to do "off-screen" rendering using
+ * the GLX pixel buffer extension.
+ *
+ * Written by Brian Paul for the "OpenGL and Window System Integration"
+ * course presented at SIGGRAPH '97.  Updated on 5 October 2002.
+ *
+ * Updated on 31 January 2004 to use native GLX by
+ * Andrew P. Lentvorski, Jr. <bsder@allcaps.org>
+ *
+ * Usage:
+ *   glxpbdemo width height imgfile
+ * Where:
+ *   width is the width, in pixels, of the image to generate.
+ *   height is the height, in pixels, of the image to generate.
+ *   imgfile is the name of the PPM image file to write.
+ *
+ *
+ * This demo draws 3-D boxes with random orientation.
+ *
+ * On machines such as the SGI Indigo you may have to reconfigure your
+ * display/X server to enable pbuffers.  Look in the /usr/gfx/ucode/MGRAS/vof/
+ * directory for display configurations with the _pbuf suffix.  Use
+ * setmon -x <vof> to configure your X server and display for pbuffers.
+ *
+ * O2 systems seem to support pbuffers well.
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+/* Some ugly global vars */
+static GLXFBConfig gFBconfig = 0;
+static Display *gDpy = NULL;
+static int gScreen = 0;
+static GLXPbuffer gPBuffer = 0;
+static int gWidth, gHeight;
+
+
+/*
+ * Test for appropriate version of GLX to run this program
+ * Input:  dpy - the X display
+ *         screen - screen number
+ * Return:  0 = GLX not available.
+ *          1 = GLX available.
+ */
+static int
+RuntimeQueryGLXVersion(Display *dpy, int screen)
+{
+#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4)
+   char *glxversion;
+ 
+   glxversion = (char *) glXGetClientString(dpy, GLX_VERSION);
+   if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4")))
+      return 0;
+
+   glxversion = (char *) glXQueryServerString(dpy, screen, GLX_VERSION);
+   if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4")))
+      return 0;
+
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+
+
+/*
+ * Create the pbuffer and return a GLXPbuffer handle.
+ */
+static GLXPbuffer
+MakePbuffer( Display *dpy, int screen, int width, int height )
+{
+   GLXFBConfig *fbConfigs;
+   GLXFBConfig chosenFBConfig;
+   GLXPbuffer pBuffer = None;
+
+   int nConfigs;
+   int fbconfigid;
+
+   int fbAttribs[] = {
+      GLX_RENDER_TYPE, GLX_RGBA_BIT,
+      GLX_DEPTH_SIZE, 1,
+      GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_PBUFFER_BIT,
+      None
+   };
+
+   int pbAttribs[] = {
+      GLX_PBUFFER_WIDTH, 0,
+      GLX_PBUFFER_HEIGHT, 0,
+      GLX_LARGEST_PBUFFER, False,
+      GLX_PRESERVED_CONTENTS, False,
+      None
+   };
+
+   pbAttribs[1] = width;
+   pbAttribs[3] = height;
+
+   fbConfigs = glXChooseFBConfig(dpy, screen, fbAttribs, &nConfigs);
+
+   if (0 == nConfigs || !fbConfigs) {
+      printf("Error: glxChooseFBConfig failed\n");
+      XFree(fbConfigs);
+      XCloseDisplay(dpy);
+      return 0;
+   }
+
+   chosenFBConfig = fbConfigs[0];
+
+   glXGetFBConfigAttrib(dpy, chosenFBConfig, GLX_FBCONFIG_ID, &fbconfigid);
+   printf("Chose 0x%x as fbconfigid\n", fbconfigid);
+
+   /* Create the pbuffer using first fbConfig in the list that works. */
+   pBuffer = glXCreatePbuffer(dpy, chosenFBConfig, pbAttribs);
+
+   if (pBuffer) {
+      gFBconfig = chosenFBConfig;
+      gWidth = width;
+      gHeight = height;
+   }
+
+   XFree(fbConfigs);
+
+   return pBuffer;
+}
+
+
+
+/*
+ * Do all the X / GLX setup stuff.
+ */
+static int
+Setup(int width, int height)
+{
+#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4)
+   GLXContext glCtx;
+
+   /* Open the X display */
+   gDpy = XOpenDisplay(NULL);
+   if (!gDpy) {
+      printf("Error: couldn't open default X display.\n");
+      return 0;
+   }
+
+   /* Get default screen */
+   gScreen = DefaultScreen(gDpy);
+
+   /* Test that GLX is available */
+   if (!RuntimeQueryGLXVersion(gDpy, gScreen)) {
+     printf("Error: GLX 1.3 or 1.4 not available\n");
+     XCloseDisplay(gDpy);
+     return 0;
+   }
+
+   /* Create Pbuffer */
+   gPBuffer = MakePbuffer( gDpy, gScreen, width, height );
+   if (gPBuffer==None) {
+      printf("Error: couldn't create pbuffer\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   /* Create GLX context */
+   glCtx = glXCreateNewContext(gDpy, gFBconfig, GLX_RGBA_TYPE, NULL, True);
+   if (glCtx) {
+      if (!glXIsDirect(gDpy, glCtx)) {
+         printf("Warning: using indirect GLXContext\n");
+      }
+   }
+   else {
+      printf("Error: Couldn't create GLXContext\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   /* Bind context to pbuffer */
+   if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) {
+      printf("Error: glXMakeCurrent failed\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   return 1;  /* Success!! */
+#else
+   printf("Error: GLX version 1.3 or 1.4 not available at compile time\n");
+   return 0;
+#endif
+}
+
+
+
+/* One-time GL setup */
+static void
+InitGL(void)
+{
+   static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0};
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_NORMALIZE);
+   glEnable(GL_DEPTH_TEST);
+   glEnable(GL_CULL_FACE);
+
+   glViewport(0, 0, gWidth, gHeight);
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -15.0 );
+
+}
+
+
+/* Return random float in [0,1] */
+static float
+Random(void)
+{
+   int i = rand();
+   return (float) (i % 1000) / 1000.0;
+}
+
+
+static void
+RandomColor(void)
+{
+   GLfloat c[4];
+   c[0] = Random();
+   c[1] = Random();
+   c[2] = Random();
+   c[3] = 1.0;
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);
+}
+
+
+/* This function borrowed from Mark Kilgard's GLUT */
+static void
+drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1,
+        GLfloat z0, GLfloat z1, GLenum type)
+{
+  static GLfloat n[6][3] =
+  {
+    {-1.0, 0.0, 0.0},
+    {0.0, 1.0, 0.0},
+    {1.0, 0.0, 0.0},
+    {0.0, -1.0, 0.0},
+    {0.0, 0.0, 1.0},
+    {0.0, 0.0, -1.0}
+  };
+  static GLint faces[6][4] =
+  {
+    {0, 1, 2, 3},
+    {3, 2, 6, 7},
+    {7, 6, 5, 4},
+    {4, 5, 1, 0},
+    {5, 6, 2, 1},
+    {7, 4, 0, 3}
+  };
+  GLfloat v[8][3], tmp;
+  GLint i;
+
+  if (x0 > x1) {
+    tmp = x0;
+    x0 = x1;
+    x1 = tmp;
+  }
+  if (y0 > y1) {
+    tmp = y0;
+    y0 = y1;
+    y1 = tmp;
+  }
+  if (z0 > z1) {
+    tmp = z0;
+    z0 = z1;
+    z1 = tmp;
+  }
+  v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
+  v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
+  v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
+  v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
+  v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
+  v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
+
+  for (i = 0; i < 6; i++) {
+    glBegin(type);
+    glNormal3fv(&n[i][0]);
+    glVertex3fv(&v[faces[i][0]][0]);
+    glVertex3fv(&v[faces[i][1]][0]);
+    glVertex3fv(&v[faces[i][2]][0]);
+    glVertex3fv(&v[faces[i][3]][0]);
+    glEnd();
+  }
+}
+
+
+
+/* Render a scene */
+static void
+Render(void)
+{
+   int NumBoxes = 100;
+   int i;
+
+   InitGL();
+   glClearColor(0.2, 0.2, 0.9, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   for (i=0;i<NumBoxes;i++) {
+      float tx = -2.0 + 4.0 * Random();
+      float ty = -2.0 + 4.0 * Random();
+      float tz =  4.0 - 16.0 * Random();
+      float sx = 0.1 + Random() * 0.4;
+      float sy = 0.1 + Random() * 0.4;
+      float sz = 0.1 + Random() * 0.4;
+      float rx = Random();
+      float ry = Random();
+      float rz = Random();
+      float ra = Random() * 360.0;
+      glPushMatrix();
+      glTranslatef(tx, ty, tz);
+      glRotatef(ra, rx, ry, rz);
+      glScalef(sx, sy, sz);
+      RandomColor();
+      drawBox(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, GL_POLYGON);
+      glPopMatrix();
+   }
+
+   glFinish();
+}
+
+
+
+static void
+WriteFile(const char *filename)
+{
+   FILE *f;
+   GLubyte *image;
+   int i;
+
+   image = malloc(gWidth * gHeight * 3 * sizeof(GLubyte));
+   if (!image) {
+      printf("Error: couldn't allocate image buffer\n");
+      return;
+   }
+
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+   glReadPixels(0, 0, gWidth, gHeight, GL_RGB, GL_UNSIGNED_BYTE, image);
+
+   f = fopen(filename, "w");
+   if (!f) {
+      printf("Couldn't open image file: %s\n", filename);
+      return;
+   }
+   fprintf(f,"P6\n");
+   fprintf(f,"# ppm-file created by %s\n", "trdemo2");
+   fprintf(f,"%i %i\n", gWidth, gHeight);
+   fprintf(f,"255\n");
+   fclose(f);
+   f = fopen(filename, "ab");  /* now append binary data */
+   if (!f) {
+      printf("Couldn't append to image file: %s\n", filename);
+      return;
+   }
+
+   for (i=0;i<gHeight;i++) {
+      GLubyte *rowPtr;
+      /* Remember, OpenGL images are bottom to top.  Have to reverse. */
+      rowPtr = image + (gHeight-1-i) * gWidth*3;
+      fwrite(rowPtr, 1, gWidth*3, f);
+   }
+
+   fclose(f);
+   free(image);
+
+   printf("Wrote %d by %d image file: %s\n", gWidth, gHeight, filename);
+}
+
+
+
+/*
+ * Print message describing command line parameters.
+ */
+static void
+Usage(const char *appName)
+{
+   printf("Usage:\n");
+   printf("  %s width height imgfile\n", appName);
+   printf("Where imgfile is a ppm file\n");
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+   if (argc!=4) {
+      Usage(argv[0]);
+   }
+   else {
+      int width = atoi(argv[1]);
+      int height = atoi(argv[2]);
+      char *fileName = argv[3];
+      if (width<=0) {
+         printf("Error: width parameter must be at least 1.\n");
+         return 1;
+      }
+      if (height<=0) {
+         printf("Error: height parameter must be at least 1.\n");
+         return 1;
+      }
+      if (!Setup(width, height)) {
+         return 1;
+      }
+
+      printf("Setup completed\n");
+      Render();
+      printf("Render completed.\n");
+      WriteFile(fileName);
+      printf("File write completed.\n");
+
+      glXDestroyPbuffer( gDpy, gPBuffer );
+   }
+   return 0;
+}
+
diff -Naurp Mesa-7.8.1/progs/xdemos/glxpixmap.c Mesa-7.8.1.patched/progs/xdemos/glxpixmap.c
--- Mesa-7.8.1/progs/xdemos/glxpixmap.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxpixmap.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,187 @@
+
+
+/*
+ * A demonstration of using the GLXPixmap functions.  This program is in
+ * the public domain.
+ *
+ * Brian Paul
+ */
+
+
+#include <GL/gl.h>
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static GLXContext ctx;
+static XVisualInfo *visinfo;
+static GC gc;
+
+
+
+static Window make_rgb_window( Display *dpy,
+				  unsigned int width, unsigned int height )
+{
+   const int sbAttrib[] = { GLX_RGBA,
+                            GLX_RED_SIZE, 1,
+                            GLX_GREEN_SIZE, 1,
+                            GLX_BLUE_SIZE, 1,
+                            None };
+   const int dbAttrib[] = { GLX_RGBA,
+                            GLX_RED_SIZE, 1,
+                            GLX_GREEN_SIZE, 1,
+                            GLX_BLUE_SIZE, 1,
+                            GLX_DOUBLEBUFFER,
+                            None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, (int *) sbAttrib );
+   if (!visinfo) {
+      visinfo = glXChooseVisual( dpy, scrnum, (int *) dbAttrib );
+      if (!visinfo) {
+         printf("Error: couldn't get an RGB visual\n");
+         exit(1);
+      }
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   /* TODO: share root colormap if possible */
+   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 );
+
+   /* make an X GC so we can do XCopyArea later */
+   gc = XCreateGC( dpy, win, 0, NULL );
+
+   /* need indirect context */
+   ctx = glXCreateContext( dpy, visinfo, NULL, False );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(-1);
+   }
+
+   printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
+
+   return win;
+}
+
+
+static GLXPixmap make_pixmap( Display *dpy, Window win,
+			       unsigned int width, unsigned int height,
+                               Pixmap *pixmap)
+{
+   Pixmap pm;
+   GLXPixmap glxpm;
+   XWindowAttributes attr;
+
+   pm = XCreatePixmap( dpy, win, width, height, visinfo->depth );
+   if (!pm) {
+      printf("Error: XCreatePixmap failed\n");
+      exit(-1);
+   }
+
+   XGetWindowAttributes( dpy, win, &attr );
+
+   /*
+    * IMPORTANT:
+    *   Use the glXCreateGLXPixmapMESA funtion when using Mesa because
+    *   Mesa needs to know the colormap associated with a pixmap in order
+    *   to render correctly.  This is because Mesa allows RGB rendering
+    *   into any kind of visual, not just TrueColor or DirectColor.
+    */
+#ifdef GLX_MESA_pixmap_colormap
+   if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) {
+      /* stand-alone Mesa, specify the colormap */
+      glxpm = glXCreateGLXPixmapMESA( dpy, visinfo, pm, attr.colormap );
+   }
+   else {
+      glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
+   }
+#else
+   /* This will work with Mesa too if the visual is TrueColor or DirectColor */
+   glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
+#endif
+
+   if (!glxpm) {
+      printf("Error: GLXCreateGLXPixmap failed\n");
+      exit(-1);
+   }
+
+   *pixmap = pm;
+
+   return glxpm;
+}
+
+
+
+static void event_loop( Display *dpy, GLXPixmap pm )
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent( dpy, &event );
+
+      switch (event.type) {
+	 case Expose:
+	    printf("Redraw\n");
+	    /* copy the image from GLXPixmap to window */
+	    XCopyArea( dpy, pm, event.xany.window,  /* src, dest */
+		       gc, 0, 0, 300, 300,          /* gc, src pos, size */
+		       0, 0 );                      /* dest pos */
+	    break;
+	 case ConfigureNotify:
+	    /* nothing */
+	    break;
+      }
+   }
+}
+
+
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   Window win;
+   Pixmap pm;
+   GLXPixmap glxpm;
+
+   dpy = XOpenDisplay(NULL);
+
+   win = make_rgb_window( dpy, 300, 300 );
+   glxpm = make_pixmap( dpy, win, 300, 300, &pm );
+
+   glXMakeCurrent( dpy, glxpm, ctx );
+   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+
+   /* Render an image into the pixmap */
+   glShadeModel( GL_FLAT );
+   glClearColor( 0.5, 0.5, 0.5, 1.0 );
+   glClear( GL_COLOR_BUFFER_BIT );
+   glViewport( 0, 0, 300, 300 );
+   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
+   glColor3f( 0.0, 1.0, 1.0 );
+   glRectf( -0.75, -0.75, 0.75, 0.75 );
+   glFlush();
+   glXWaitGL();
+
+   XMapWindow( dpy, win );
+
+   event_loop( dpy, pm );
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxsnoop.c Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c
--- Mesa-7.8.1/progs/xdemos/glxsnoop.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,377 @@
+/**
+ * Display/snoop the z/stencil/back/front buffers of another app's window.
+ * Also, an example of the need for shared ancillary renderbuffers.
+ *
+ * Hint: use 'xwininfo' to get a window's ID.
+ *
+ * Brian Paul
+ * 11 Oct 2007
+ */
+
+#define GL_GLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/keysym.h>
+
+
+#define Z_BUFFER 1
+#define STENCIL_BUFFER 2
+#define BACK_BUFFER 3
+#define FRONT_BUFFER 4
+
+
+static int Buffer = BACK_BUFFER;
+static int WindowID = 0;
+static const char *DisplayName = NULL;
+static GLXContext Context = 0;
+static int Width, Height;
+
+
+/**
+ * Grab the z/stencil/back/front image from the srcWin and display it
+ * (possibly converted to grayscale) in the dstWin.
+ */
+static void
+redraw(Display *dpy, Window srcWin, Window dstWin )
+{
+   GLubyte *image = malloc(Width * Height * 4);
+
+   glXMakeCurrent(dpy, srcWin, Context);
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+   if (Buffer == BACK_BUFFER) {
+      glReadBuffer(GL_BACK);
+      glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+   }
+   else if (Buffer == FRONT_BUFFER) {
+      glReadBuffer(GL_FRONT);
+      glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+   }
+   else if (Buffer == Z_BUFFER) {
+      GLfloat *z = malloc(Width * Height * sizeof(GLfloat));
+      int i;
+      glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z);
+      for (i = 0; i < Width * Height; i++) {
+         image[i*4+0] =
+         image[i*4+1] =
+         image[i*4+2] = (GLint) (255.0 * z[i]);
+         image[i*4+3] = 255;
+      }
+      free(z);
+   }
+   else if (Buffer == STENCIL_BUFFER) {
+      GLubyte *sten = malloc(Width * Height * sizeof(GLubyte));
+      int i, min = 100, max = -1;
+      float step;
+      int sz;
+      glGetIntegerv(GL_STENCIL_BITS, &sz);
+      glReadPixels(0, 0, Width, Height,
+                   GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten);
+      /* find min/max for converting stencil to grayscale */
+      for (i = 0; i < Width * Height; i++) {
+         if (sten[i] < min)
+            min = sten[i];
+         if (sten[i] > max)
+            max = sten[i];
+      }
+      if (min == max)
+         step = 0;
+      else
+         step = 255.0 / (float) (max - min);
+      for (i = 0; i < Width * Height; i++) {
+         image[i*4+0] =
+         image[i*4+1] =
+         image[i*4+2] = (GLint) ((sten[i] - min) * step);
+         image[i*4+3] = 255;
+      }
+      free(sten);
+   }
+
+   glXMakeCurrent(dpy, dstWin, Context);
+   glWindowPos2iARB(0, 0);
+   glDrawBuffer(GL_FRONT);
+   glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+   glFlush();
+
+   free(image);
+}
+
+
+static void
+set_window_title(Display *dpy, Window win, const char *title)
+{
+   XSizeHints sizehints;
+   sizehints.flags = 0;
+   XSetStandardProperties(dpy, win, title, title,
+                          None, (char **)NULL, 0, &sizehints);
+}
+
+
+static Window
+make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
+{
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   int x = 0, y = 0;
+   char *name = NULL;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, x, y, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   return win;
+}
+
+
+static void
+update_window_title(Display *dpy, Window win)
+{
+   char title[1000], *buf;
+
+   switch (Buffer) {
+   case Z_BUFFER:
+      buf = "Z";
+      break;
+   case STENCIL_BUFFER:
+      buf = "Stencil";
+      break;
+   case BACK_BUFFER:
+      buf = "Back";
+      break;
+   case FRONT_BUFFER:
+      buf = "Front";
+      break;
+   default:
+      buf = "";
+   }
+
+   sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf);
+
+   set_window_title(dpy, win, title);
+}
+
+
+static void
+keypress(Display *dpy, Window win, char key)
+{
+   switch (key) {
+   case 27:
+      /* escape */
+      exit(0);
+      break;
+   case 's':
+      Buffer = STENCIL_BUFFER;
+      break;
+   case 'z':
+      Buffer = Z_BUFFER;
+      break;
+   case 'f':
+      Buffer = FRONT_BUFFER;
+      break;
+   case 'b':
+      Buffer = BACK_BUFFER;
+      break;
+   default:
+      return;
+   }
+
+   update_window_title(dpy, win);
+   redraw(dpy, WindowID, win);
+}
+
+
+static void
+event_loop(Display *dpy, Window win)
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent( dpy, &event );
+
+      switch (event.type) {
+      case Expose:
+         redraw(dpy, WindowID, win);
+         break;
+      case ConfigureNotify:
+         /*resize( event.xconfigure.width, event.xconfigure.height );*/
+         break;
+      case KeyPress:
+         {
+            char buffer[10];
+            int r, code;
+            code = XLookupKeysym(&event.xkey, 0);
+            if (code == XK_Left) {
+            }
+            else {
+               r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                 NULL, NULL);
+               keypress(dpy, win, buffer[0]);
+            }
+         }
+      default:
+         /* nothing */
+         ;
+      }
+   }
+}
+
+
+static VisualID
+get_window_visualid(Display *dpy, Window win)
+{
+   XWindowAttributes attr;
+
+   if (XGetWindowAttributes(dpy, win, &attr)) {
+      return attr.visual->visualid;
+   }
+   else {
+      return 0;
+   }
+}
+
+
+static void
+get_window_size(Display *dpy, Window win, int *w, int *h)
+{
+   XWindowAttributes attr;
+
+   if (XGetWindowAttributes(dpy, win, &attr)) {
+      *w = attr.width;
+      *h = attr.height;
+   }
+   else {
+      *w = *h = 0;
+   }
+}
+
+
+static XVisualInfo *
+visualid_to_visualinfo(Display *dpy, VisualID vid)
+{
+   XVisualInfo *vinfo, templ;
+   long mask;
+   int n;
+
+   templ.visualid = vid;
+   mask = VisualIDMask;
+
+   vinfo = XGetVisualInfo(dpy, mask, &templ, &n);
+   return vinfo;
+}
+
+
+static void
+key_usage(void)
+{
+   printf("Keyboard:\n");
+   printf("  z - display Z buffer\n");
+   printf("  s - display stencil buffer\n");
+   printf("  f - display front color buffer\n");
+   printf("  b - display back buffer\n");
+}
+
+
+static void
+usage(void)
+{
+   printf("Usage: glxsnoop [-display dpy] windowID\n");
+   key_usage();
+}
+
+
+static void
+parse_opts(int argc, char *argv[])
+{
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-h") == 0) {
+         usage();
+         exit(0);
+      }
+      else if (strcmp(argv[i], "-display") == 0) {
+         DisplayName = argv[i + 1];
+         i++;
+      }
+      else {
+         if (argv[i][0] == '0' && argv[i][1] == 'x') {
+            /* hex */
+            WindowID = strtol(argv[i], NULL, 16);
+         }
+         else {
+            WindowID = atoi(argv[i]);
+         }
+         break;
+      }
+   }
+
+   if (!WindowID) {
+      usage();
+      exit(0);
+   }
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+   Display *dpy;
+   VisualID vid;
+   XVisualInfo *visinfo;
+   Window win;
+
+   parse_opts(argc, argv);
+
+   key_usage();
+
+   dpy = XOpenDisplay(DisplayName);
+
+   /* find the VisualID for the named window */
+   vid = get_window_visualid(dpy, WindowID);
+   get_window_size(dpy, WindowID, &Width, &Height);
+
+   visinfo = visualid_to_visualinfo(dpy, vid);
+
+   Context = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!Context) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   win = make_gl_window(dpy, visinfo, Width, Height);
+   XMapWindow(dpy, win);
+   update_window_title(dpy, win);
+
+   event_loop( dpy, win );
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/glxswapcontrol.c Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c
--- Mesa-7.8.1/progs/xdemos/glxswapcontrol.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,893 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
+ * Port by Brian Paul  23 March 2001
+ *
+ * Modified by Ian Romanick <idr@us.ibm.com> 09 April 2003 to support
+ * GLX_{MESA,SGI}_swap_control and GLX_OML_sync_control.
+ *
+ * Command line options:
+ *    -display       Name of the display to use.
+ *    -info          print GL implementation information
+ *    -swap N        Attempt to set the swap interval to 1/N second
+ *    -forcegetrate  Get the display refresh rate even if the required GLX
+ *                   extension is not supported.
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#ifndef __VMS
+/*# include <stdint.h>*/
+#endif
+# define GLX_GLXEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#ifndef GLX_MESA_swap_control
+typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval);
+typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void );
+#endif
+
+#if !defined( GLX_OML_sync_control ) && defined( _STDINT_H )
+#define GLX_OML_sync_control 1
+typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
+#endif
+
+#ifndef GLX_MESA_swap_frame_usage
+#define GLX_MESA_swap_frame_usage 1
+typedef int ( * PFNGLXGETFRAMEUSAGEMESAPROC) (Display *dpy, GLXDrawable drawable, float * usage );
+#endif
+
+#define BENCHMARK
+
+PFNGLXGETFRAMEUSAGEMESAPROC get_frame_usage = NULL;
+
+#ifdef BENCHMARK
+
+/* XXX this probably isn't very portable */
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#define NUL '\0'
+
+/* return current time (in seconds) */
+static int
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (int) tv.tv_sec;
+}
+
+#else /*BENCHMARK*/
+
+/* dummy */
+static int
+current_time(void)
+{
+   return 0;
+}
+
+#endif /*BENCHMARK*/
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+static GLboolean has_OML_sync_control = GL_FALSE;
+static GLboolean has_SGI_swap_control = GL_FALSE;
+static GLboolean has_MESA_swap_control = GL_FALSE;
+static GLboolean has_MESA_swap_frame_usage = GL_FALSE;
+
+static char ** extension_table = NULL;
+static unsigned num_extensions;
+
+static GLboolean use_ztrick = GL_FALSE;
+static GLfloat aspectX = 1.0f, aspectY = 1.0f;
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+draw(void)
+{
+   if ( use_ztrick ) {
+      static GLboolean flip = GL_FALSE;
+      static const GLfloat vert[4][3] = {
+	 { -1, -1, -0.999 },
+	 {  1, -1, -0.999 },
+	 {  1,  1, -0.999 },
+	 { -1,  1, -0.999 }
+      };
+      static const GLfloat col[4][3] = {
+	 { 1.0, 0.6, 0.0 },
+	 { 1.0, 0.6, 0.0 },
+	 { 0.0, 0.0, 0.0 },
+	 { 0.0, 0.0, 0.0 },
+      };
+      
+      if ( flip ) {
+	 glDepthRange(0, 0.5);
+	 glDepthFunc(GL_LEQUAL);
+      }
+      else {
+	 glDepthRange(1.0, 0.4999);
+	 glDepthFunc(GL_GEQUAL);
+      }
+
+      flip = !flip;
+
+      /* The famous Quake "Z trick" only works when the whole screen is
+       * re-drawn each frame.
+       */
+
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glOrtho(-1, 1, -1, 1, -1, 1);
+      glDisable(GL_LIGHTING);
+      glShadeModel(GL_SMOOTH);
+
+      glEnableClientState( GL_VERTEX_ARRAY );
+      glEnableClientState( GL_COLOR_ARRAY );
+      glVertexPointer( 3, GL_FLOAT, 0, vert );
+      glColorPointer( 3, GL_FLOAT, 0, col );
+      glDrawArrays( GL_POLYGON, 0, 4 );
+      glDisableClientState( GL_COLOR_ARRAY );
+      glDisableClientState( GL_VERTEX_ARRAY );
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);
+
+      glEnable(GL_LIGHTING);
+
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      glTranslatef(0.0, 0.0, -45.0);
+   }
+   else {
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+   }
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   glPushMatrix();
+   glTranslatef(-3.0, -2.0, 0.0);
+   glRotatef(angle, 0.0, 0.0, 1.0);
+   glCallList(gear1);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(3.1, -2.0, 0.0);
+   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+   glCallList(gear2);
+   glPopMatrix();
+
+   glPushMatrix();
+   glTranslatef(-3.1, 4.2, 0.0);
+   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+   glCallList(gear3);
+   glPopMatrix();
+
+   glPopMatrix();
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   if (width > height) {
+      aspectX = (GLfloat) width / (GLfloat) height;
+      aspectY = 1.0;
+   }
+   else {
+      aspectX = 1.0;
+      aspectY = (GLfloat) height / (GLfloat) width;
+   }
+
+   glViewport(0, 0, (GLint) width, (GLint) height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+
+   glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -45.0);
+}
+
+
+static void
+init(void)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+
+   /* make the gears */
+   gear1 = glGenLists(1);
+   glNewList(gear1, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   gear(1.0, 4.0, 1.0, 20, 0.7);
+   glEndList();
+
+   gear2 = glGenLists(1);
+   glNewList(gear2, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+   gear(0.5, 2.0, 2.0, 10, 0.7);
+   glEndList();
+
+   gear3 = glGenLists(1);
+   glNewList(gear3, GL_COMPILE);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   gear(1.3, 2.0, 0.5, 10, 0.7);
+   glEndList();
+
+   glEnable(GL_NORMALIZE);
+}
+
+
+/**
+ * Remove window border/decorations.
+ */
+static void
+no_border( Display *dpy, Window w)
+{
+   static const unsigned MWM_HINTS_DECORATIONS = (1 << 1);
+   static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5;
+
+   typedef struct
+   {
+      unsigned long       flags;
+      unsigned long       functions;
+      unsigned long       decorations;
+      long                inputMode;
+      unsigned long       status;
+   } PropMotifWmHints;
+
+   PropMotifWmHints motif_hints;
+   Atom prop, proptype;
+   unsigned long flags = 0;
+
+   /* setup the property */
+   motif_hints.flags = MWM_HINTS_DECORATIONS;
+   motif_hints.decorations = flags;
+
+   /* get the atom for the property */
+   prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
+   if (!prop) {
+      /* something went wrong! */
+      return;
+   }
+
+   /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
+   proptype = prop;
+
+   XChangeProperty( dpy, w,                         /* display, window */
+                    prop, proptype,                 /* property, type */
+                    32,                             /* format: 32-bit datums */
+                    PropModeReplace,                /* mode */
+                    (unsigned char *) &motif_hints, /* data */
+                    PROP_MOTIF_WM_HINTS_ELEMENTS    /* nelements */
+                  );
+}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height, GLboolean fullscreen,
+             Window *winRet, GLXContext *ctxRet)
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    GLX_DEPTH_SIZE, 1,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   if (fullscreen) {
+      x = y = 0;
+      width = DisplayWidth( dpy, scrnum );
+      height = DisplayHeight( dpy, scrnum );
+   }
+
+   visinfo = glXChooseVisual( dpy, scrnum, attrib );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   if (fullscreen)
+      no_border(dpy, win);
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   XFree(visinfo);
+
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+static void
+event_loop(Display *dpy, Window win)
+{
+   float  frame_usage = 0.0;
+
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+	 case Expose:
+            /* we'll redraw below */
+	    break;
+	 case ConfigureNotify:
+	    reshape(event.xconfigure.width, event.xconfigure.height);
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+                  view_roty += 5.0;
+               }
+               else if (code == XK_Right) {
+                  view_roty -= 5.0;
+               }
+               else if (code == XK_Up) {
+                  view_rotx += 5.0;
+               }
+               else if (code == XK_Down) {
+                  view_rotx -= 5.0;
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                                    NULL, NULL);
+                  if (buffer[0] == 27) {
+                     /* escape */
+                     return;
+                  }
+               }
+            }
+         }
+      }
+
+      /* next frame */
+      angle += 2.0;
+
+      draw();
+
+      glXSwapBuffers(dpy, win);
+
+      if ( get_frame_usage != NULL ) {
+	 GLfloat   temp;
+	 
+	 (*get_frame_usage)( dpy, win, & temp );
+	 frame_usage += temp;
+      }
+
+      /* calc framerate */
+      {
+         static int t0 = -1;
+         static int frames = 0;
+         int t = current_time();
+
+         if (t0 < 0)
+            t0 = t;
+
+         frames++;
+
+         if (t - t0 >= 5.0) {
+            GLfloat seconds = t - t0;
+            GLfloat fps = frames / seconds;
+	    if ( get_frame_usage != NULL ) {
+	       printf("%d frames in %3.1f seconds = %6.3f FPS (%3.1f%% usage)\n",
+		      frames, seconds, fps,
+		      (frame_usage * 100.0) / (float) frames );
+	    }
+	    else {
+	       printf("%d frames in %3.1f seconds = %6.3f FPS\n",
+		      frames, seconds, fps);
+	    }
+
+            t0 = t;
+            frames = 0;
+	    frame_usage = 0.0;
+         }
+      }
+   }
+}
+
+
+/**
+ * Display the refresh rate of the display using the GLX_OML_sync_control
+ * extension.
+ */
+static void
+show_refresh_rate( Display * dpy )
+{
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+   PFNGLXGETMSCRATEOMLPROC  get_msc_rate;
+   int32_t  n;
+   int32_t  d;
+
+   get_msc_rate = (PFNGLXGETMSCRATEOMLPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetMscRateOML" );
+   if ( get_msc_rate != NULL ) {
+      (*get_msc_rate)( dpy, glXGetCurrentDrawable(), &n, &d );
+      printf( "refresh rate: %.1fHz\n", (float) n / d );
+      return;
+   }
+#endif
+   printf( "glXGetMscRateOML not supported.\n" );
+}
+
+
+/**
+ * Fill in the table of extension strings from a supplied extensions string
+ * (as returned by glXQueryExtensionsString).
+ *
+ * \param string   String of GLX extensions.
+ * \sa is_extension_supported
+ */
+static void
+make_extension_table( const char * string )
+{
+   char ** string_tab;
+   unsigned  num_strings;
+   unsigned  base;
+   unsigned  idx;
+   unsigned  i;
+      
+   /* Count the number of spaces in the string.  That gives a base-line
+    * figure for the number of extension in the string.
+    */
+   
+   num_strings = 1;
+   for ( i = 0 ; string[i] != NUL ; i++ ) {
+      if ( string[i] == ' ' ) {
+	 num_strings++;
+      }
+   }
+   
+   string_tab = (char **) malloc( sizeof( char * ) * num_strings );
+   if ( string_tab == NULL ) {
+      return;
+   }
+
+   base = 0;
+   idx = 0;
+
+   while ( string[ base ] != NUL ) {
+      /* Determine the length of the next extension string.
+       */
+
+      for ( i = 0 
+	    ; (string[ base + i ] != NUL) && (string[ base + i ] != ' ')
+	    ; i++ ) {
+	 /* empty */ ;
+      }
+
+      if ( i > 0 ) {
+	 /* If the string was non-zero length, add it to the table.  We
+	  * can get zero length strings if there is a space at the end of
+	  * the string or if there are two (or more) spaces next to each
+	  * other in the string.
+	  */
+
+	 string_tab[ idx ] = malloc( sizeof( char ) * (i + 1) );
+	 if ( string_tab[ idx ] == NULL ) {
+	    return;
+	 }
+
+	 (void) memcpy( string_tab[ idx ], & string[ base ], i );
+	 string_tab[ idx ][i] = NUL;
+	 idx++;
+      }
+
+
+      /* Skip to the start of the next extension string.
+       */
+
+      for ( base += i
+	    ; (string[ base ] == ' ') && (string[ base ] != NUL) 
+	    ; base++ ) {
+	 /* empty */ ;
+      }
+   }
+
+   extension_table = string_tab;
+   num_extensions = idx;
+}
+
+    
+/**
+ * Determine of an extension is supported.  The extension string table
+ * must have already be initialized by calling \c make_extension_table.
+ * 
+ * \praram ext  Extension to be tested.
+ * \return GL_TRUE of the extension is supported, GL_FALSE otherwise.
+ * \sa make_extension_table
+ */
+static GLboolean
+is_extension_supported( const char * ext )
+{
+   unsigned   i;
+   
+   for ( i = 0 ; i < num_extensions ; i++ ) {
+      if ( strcmp( ext, extension_table[i] ) == 0 ) {
+	 return GL_TRUE;
+      }
+   }
+   
+   return GL_FALSE;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   char *dpyName = NULL;
+   int swap_interval = 1;
+   GLboolean do_swap_interval = GL_FALSE;
+   GLboolean force_get_rate = GL_FALSE;
+   GLboolean fullscreen = GL_FALSE;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+   PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL;
+   PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL;
+   int width = 300, height = 300;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) {
+	 swap_interval = atoi( argv[i+1] );
+	 do_swap_interval = GL_TRUE;
+	 i++;
+      }
+      else if (strcmp(argv[i], "-forcegetrate") == 0) {
+	 /* This option was put in because some DRI drivers don't support the
+	  * full GLX_OML_sync_control extension, but they do support
+	  * glXGetMscRateOML.
+	  */
+	 force_get_rate = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-fullscreen") == 0) {
+         fullscreen = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-ztrick") == 0) {
+	 use_ztrick = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "-help") == 0) {
+         printf("Usage:\n");
+         printf("  gears [options]\n");
+         printf("Options:\n");
+         printf("  -help                   Print this information\n");
+         printf("  -display displayName    Specify X display\n");
+         printf("  -info                   Display GL information\n");
+         printf("  -swap N                 Swap no more than once per N vertical refreshes\n");
+         printf("  -forcegetrate           Try to use glXGetMscRateOML function\n");
+         printf("  -fullscreen             Full-screen window\n");
+         return 0;
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
+      return -1;
+   }
+
+   make_window(dpy, "glxgears", 0, 0, width, height, fullscreen, &win, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, win, ctx);
+
+   make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) );
+   has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" );
+   has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" );
+   has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" );
+   has_MESA_swap_frame_usage = is_extension_supported( "GLX_MESA_swap_frame_usage" );
+
+   if ( has_MESA_swap_control ) {
+      set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalMESA" );
+      get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetSwapIntervalMESA" );
+   }
+   else if ( has_SGI_swap_control ) {
+      set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" );
+   }
+
+
+   if ( has_MESA_swap_frame_usage ) {
+      get_frame_usage = (PFNGLXGETFRAMEUSAGEMESAPROC)  glXGetProcAddressARB( (const GLubyte *) "glXGetFrameUsageMESA" );
+   }
+      
+
+   if (printInfo) {
+      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));
+      if ( has_OML_sync_control || force_get_rate ) {
+	 show_refresh_rate( dpy );
+      }
+
+      if ( get_swap_interval != NULL ) {
+	 printf("Default swap interval = %d\n", (*get_swap_interval)() );
+      }
+   }
+
+   if ( do_swap_interval ) {
+      if ( set_swap_interval != NULL ) {
+	 if ( ((swap_interval == 0) && !has_MESA_swap_control)
+	      || (swap_interval < 0) ) {
+	    printf( "Swap interval must be non-negative or greater than zero "
+		    "if GLX_MESA_swap_control is not supported.\n" );
+	 }
+	 else {
+	    (*set_swap_interval)( swap_interval );
+	 }
+
+	 if ( printInfo && (get_swap_interval != NULL) ) {
+	    printf("Current swap interval = %d\n", (*get_swap_interval)() );
+	 }
+      }
+      else {
+	 printf("Unable to set swap-interval.  Neither GLX_SGI_swap_control "
+		"nor GLX_MESA_swap_control are supported.\n" );
+      }
+   }
+
+   init();
+
+   /* Set initial projection/viewing transformation.
+    * same as glxgears.c
+    */
+   reshape(width, height);
+
+   event_loop(dpy, win);
+
+   glXDestroyContext(dpy, ctx);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.c Mesa-7.8.1.patched/progs/xdemos/ipc.c
--- Mesa-7.8.1/progs/xdemos/ipc.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/ipc.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,264 @@
+/* Copyright (c) 2003 Tungsten Graphics, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files ("the
+ * Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:  The above copyright notice, the Tungsten
+ * Graphics splash screen, and this permission notice shall be included
+ * in all copies or substantial portions of the Software.  THE SOFTWARE
+ * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Simple IPC API
+ * Brian Paul
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include "ipc.h"
+
+#if defined(IRIX) || defined(irix)
+typedef int socklen_t;
+#endif
+
+#define NO_DELAY 1
+
+#define DEFAULT_MASTER_PORT 7011
+
+
+/*
+ * Return my hostname in <nameOut>.
+ * Return 1 for success, 0 for error.
+ */
+int
+MyHostName(char *nameOut, int maxNameLength)
+{
+    int k = gethostname(nameOut, maxNameLength);
+    return k==0;
+}
+
+
+/*
+ * Create a socket attached to a port.  Later, we can call AcceptConnection
+ * on the socket returned from this function.
+ * Return the new socket number or -1 if error.
+ */
+int
+CreatePort(int *port)
+{
+    char hostname[1000];
+    struct sockaddr_in servaddr;
+    struct hostent *hp;
+    int so_reuseaddr = 1;
+    int tcp_nodelay = 1;
+    int sock, k;
+
+    /* create socket */
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    assert(sock > 2);
+
+    /* get my host name */
+    k = gethostname(hostname, 1000);
+    assert(k == 0);
+
+    /* get hostent info */
+    hp = gethostbyname(hostname);
+    assert(hp);
+
+    /* initialize the servaddr struct */
+    memset(&servaddr, 0, sizeof(servaddr) );
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons((unsigned short) (*port));
+    memcpy((char *) &servaddr.sin_addr, hp->h_addr,
+	   sizeof(servaddr.sin_addr));
+
+    /* deallocate when we exit */
+    k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+		   (char *) &so_reuseaddr, sizeof(so_reuseaddr));
+    assert(k==0);
+
+    /* send packets immediately */
+#if NO_DELAY
+    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		   (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+    assert(k==0);
+#endif
+
+    if (*port == 0)
+        *port = DEFAULT_MASTER_PORT;
+
+    k = 1;
+    while (k && (*port < 65534)) {
+    	/* bind our address to the socket */
+    	servaddr.sin_port = htons((unsigned short) (*port));
+    	k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+        if (k)
+           *port = *port + 1;
+    }
+
+#if 0
+    printf("###### Real Port: %d\n", *port);
+#endif
+
+    /* listen for connections */
+    k = listen(sock, 100);
+    assert(k == 0);
+
+    return sock;
+}
+
+
+/*
+ * Accept a connection on the named socket.
+ * Return a new socket for the new connection, or -1 if error.
+ */
+int
+AcceptConnection(int socket)
+{
+    struct sockaddr addr;
+    socklen_t addrLen;
+    int newSock;
+
+    addrLen = sizeof(addr);
+    newSock = accept(socket, &addr, &addrLen);
+    if (newSock == 1)
+	return -1;
+    else
+	return newSock;
+}
+
+
+/*
+ * Contact the server running on the given host on the named port.
+ * Return socket number or -1 if error.
+ */
+int
+Connect(const char *hostname, int port)
+{
+    struct sockaddr_in servaddr;
+    struct hostent *hp;
+    int sock, k;
+    int tcp_nodelay = 1;
+
+    assert(port);
+
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    assert(sock >= 0);
+
+    hp = gethostbyname(hostname);
+    assert(hp);
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons((unsigned short) port);
+    memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
+
+    k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+    if (k != 0) {
+       perror("Connect:");
+       return -1;
+    }
+
+#if NO_DELAY
+    /* send packets immediately */
+    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		   (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+    assert(k==0);
+#endif
+
+    return sock;
+}
+
+
+void
+CloseSocket(int socket)
+{
+    close(socket);
+}
+
+
+int
+SendData(int socket, const void *data, int bytes)
+{
+    int sent = 0;
+    int b;
+
+    while (sent < bytes) {
+        b = write(socket, (char *) data + sent, bytes - sent);
+        if (b <= 0)
+            return -1; /* something broke */
+        sent += b;
+    }
+    return sent;
+}
+
+
+int
+ReceiveData(int socket, void *data, int bytes)
+{
+    int received = 0, b;
+
+    while (received < bytes) {
+        b = read(socket, (char *) data + received, bytes - received);
+        if (b <= 0)
+            return -1;
+        received += b;
+    }
+    return received;
+}
+
+
+int
+SendString(int socket, const char *str)
+{
+    const int len = strlen(str);
+    int sent, b;
+
+    /* first, send a 4-byte length indicator */
+    b = write(socket, &len, sizeof(len));
+    if (b <= 0)
+	return -1;
+
+    sent = SendData(socket, str, len);
+    assert(sent == len);
+    return sent;
+}
+
+
+int
+ReceiveString(int socket, char *str, int maxLen)
+{
+    int len, received, b;
+
+    /* first, read 4 bytes to see how long of string to receive */
+    b = read(socket, &len, sizeof(len));
+    if (b <= 0)
+	return -1;
+
+    assert(len <= maxLen);  /* XXX fix someday */
+    assert(len >= 0);
+    received = ReceiveData(socket, str, len);
+    assert(received != -1);
+    assert(received == len);
+    str[len] = 0;
+    return received;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.h Mesa-7.8.1.patched/progs/xdemos/ipc.h
--- Mesa-7.8.1/progs/xdemos/ipc.h	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/ipc.h	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,16 @@
+#ifndef IPC_H
+#define IPC_H
+
+
+extern int MyHostName(char *nameOut, int maxNameLength);
+extern int CreatePort(int *port);
+extern int AcceptConnection(int socket);
+extern int Connect(const char *hostname, int port);
+extern void CloseSocket(int socket);
+extern int SendData(int socket, const void *data, int bytes);
+extern int ReceiveData(int socket, void *data, int bytes);
+extern int SendString(int socket, const char *str);
+extern int ReceiveString(int socket, char *str, int maxLen);
+
+
+#endif /* IPC_H */
diff -Naurp Mesa-7.8.1/progs/xdemos/Makefile Mesa-7.8.1.patched/progs/xdemos/Makefile
--- Mesa-7.8.1/progs/xdemos/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/Makefile	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,103 @@
+# progs/xdemos/Makefile
+
+TOP = ../..
+include $(TOP)/configs/current
+
+
+INCDIR = $(TOP)/include
+
+LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
+
+# Add X11 and pthread libs to satisfy GNU gold.
+APP_LIB_DEPS += -lX11 -lpthread
+
+LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS)
+
+PROGS = \
+	corender \
+	glsync \
+	glthreads \
+	glxdemo \
+	glxgears \
+	glxgears_fbconfig \
+	glxgears_pixmap \
+	glxcontexts \
+	glxheads \
+	glxinfo \
+	glxpixmap \
+	glxpbdemo \
+	glxsnoop \
+	glxswapcontrol \
+	manywin \
+	msctest \
+	multictx \
+	offset \
+	omlsync \
+	overlay \
+	pbinfo \
+	pbdemo \
+	sharedtex \
+        sharedtex_mt \
+	texture_from_pixmap \
+	wincopy \
+	xfont \
+	xrotfontdemo
+
+# Don't build these by default because of extra library dependencies
+EXTRA_PROGS = \
+	shape \
+	yuvrect_client \
+	xdemo
+
+
+
+##### RULES #####
+
+.o: $(LIB_DEP)
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
+
+.c.o:
+	$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< -c -o $@
+
+
+##### TARGETS #####
+
+default: $(PROGS)
+
+$(PROGS): $(PROGS:%=%.o)
+
+extra: $(EXTRA_PROGS)
+
+
+clean:
+	-rm -f $(PROGS) $(EXTRA_PROGS)
+	-rm -f *.o *~
+
+
+# special cases
+pbutil.o: pbutil.h
+pbinfo.o: pbutil.h
+pbinfo: pbinfo.o pbutil.o
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@
+
+pbdemo.o: pbutil.h
+pbdemo: pbdemo.o pbutil.o
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@
+
+glxgears_fbconfig.o: pbutil.h
+glxgears_fbconfig: glxgears_fbconfig.o pbutil.o
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@
+
+xuserotfont.o: xuserotfont.h
+xrotfontdemo.o: xuserotfont.h
+xrotfontdemo: xrotfontdemo.o xuserotfont.o
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@
+
+ipc.o: ipc.h
+corender.o: ipc.h
+corender: corender.o ipc.o
+	$(APP_CC) $(CFLAGS) $(LDFLAGS) corender.o ipc.o $(LIBS) -o $@
+
+yuvrect_client: yuvrect_client.o
+	$(APP_CC) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@
+
diff -Naurp Mesa-7.8.1/progs/xdemos/manywin.c Mesa-7.8.1.patched/progs/xdemos/manywin.c
--- Mesa-7.8.1/progs/xdemos/manywin.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/manywin.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,421 @@
+/*
+ * Create N GLX windows/contexts and render to them in round-robin order.
+ * Also, have the contexts share all texture objects.
+ * Press 'd' to delete a texture, 'u' to unbind it.
+ *
+ * Copyright (C) 2000  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/keysym.h>
+
+
+/*
+ * Each display/window/context:
+ */
+struct head {
+   char DisplayName[1000];
+   Display *Dpy;
+   Window Win;
+   GLXContext Context;
+   float Angle;
+   char Renderer[1000];
+   char Vendor[1000];
+   char Version[1000];
+};
+
+
+#define MAX_HEADS 200
+static struct head Heads[MAX_HEADS];
+static int NumHeads = 0;
+static GLboolean SwapSeparate = GL_TRUE;
+static GLuint TexObj = 0;
+
+
+static void
+Error(const char *display, const char *msg)
+{
+   fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg);
+   exit(1);
+}
+
+
+static struct head *
+AddHead(const char *displayName, const char *name)
+{
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   XVisualInfo *visinfo;
+   int width = 90, height = 90;
+   int xpos = 0, ypos = 0;
+
+   if (NumHeads >= MAX_HEADS)
+      return NULL;
+
+   dpy = XOpenDisplay(displayName);
+   if (!dpy) {
+      Error(displayName, "Unable to open display");
+      return NULL;
+   }
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, attrib);
+   if (!visinfo) {
+      Error(displayName, "Unable to find RGB, double-buffered visual");
+      return NULL;
+   }
+
+   /* window attributes */
+   xpos = (NumHeads % 10) * 100;
+   ypos = (NumHeads / 10) * 100;
+   printf("%d, %d\n", xpos, ypos);
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   if (!win) {
+      Error(displayName, "Couldn't create window");
+      return NULL;
+   }
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   if (NumHeads == 0) {
+      ctx = glXCreateContext(dpy, visinfo, NULL, True);
+   }
+   else {
+      /* share textures & dlists with 0th context */
+      printf("sharing\n");
+      ctx = glXCreateContext(dpy, visinfo, Heads[0].Context, True);
+   }
+   if (!ctx) {
+      Error(displayName, "Couldn't create GLX context");
+      return NULL;
+   }
+
+   XMapWindow(dpy, win);
+
+   if (!glXMakeCurrent(dpy, win, ctx)) {
+      Error(displayName, "glXMakeCurrent failed");
+      printf("glXMakeCurrent failed in Redraw()\n");
+      return NULL;
+   }
+
+   if (NumHeads == 0) {
+      /* create texture object now */
+      static const GLubyte checker[2][2][4] = {
+         { {255, 255, 255, 255}, {  0,   0,   0, 255} },
+         { {  0,   0,   0,   0}, {255, 255, 255, 255} }
+      };
+      glGenTextures(1, &TexObj);
+      assert(TexObj);
+      glBindTexture(GL_TEXTURE_2D, TexObj);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGB,
+                   GL_UNSIGNED_BYTE, checker);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   }
+   else {
+      /* bind 0th context's texture in this context too */
+      assert(TexObj);
+      glBindTexture(GL_TEXTURE_2D, TexObj);
+   }
+   glEnable(GL_TEXTURE_2D);
+
+   /* save the info for this head */
+   {
+      struct head *h = &Heads[NumHeads];
+      const char * tmp;
+
+      if (strlen(name) + 1 > sizeof(h->DisplayName)) {
+         Error(displayName, "name string overflow");
+         return NULL;
+      }
+      strcpy(h->DisplayName, name);
+
+      h->Dpy = dpy;
+      h->Win = win;
+      h->Context = ctx;
+      h->Angle = 0.0;
+
+      tmp = (char *) glGetString(GL_VERSION);
+      if (strlen(tmp) + 1 > sizeof(h->Version)) {
+         Error(displayName, "GL_VERSION string overflow");
+         return NULL;
+      }
+      strcpy(h->Version, tmp);
+
+      tmp = (char *) glGetString(GL_VENDOR);
+      if (strlen(tmp) + 1 > sizeof(h->Vendor)) {
+         Error(displayName, "GL_VENDOR string overflow");
+         return NULL;
+      }
+      strcpy(h->Vendor, tmp);
+
+      tmp = (char *) glGetString(GL_RENDERER);
+      if (strlen(tmp) + 1 > sizeof(h->Renderer)) {
+         Error(displayName, "GL_RENDERER string overflow");
+         return NULL;
+      }
+      strcpy(h->Renderer, tmp);
+
+      NumHeads++;
+      return &Heads[NumHeads-1];
+   }
+
+}
+
+
+static void
+DestroyHeads(void)
+{
+   int i;
+   for (i = 0; i < NumHeads; i++) {
+      XDestroyWindow(Heads[i].Dpy, Heads[i].Win);
+      glXDestroyContext(Heads[i].Dpy, Heads[i].Context);
+      XCloseDisplay(Heads[i].Dpy);
+   }
+}
+
+
+static void
+Redraw(struct head *h)
+{
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed");
+      printf("glXMakeCurrent failed in Redraw()\n");
+      return;
+   }
+
+   h->Angle += 1.0;
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   /* draw green triangle */
+   glColor3f(0.0, 1.0, 0.0);
+   glPushMatrix();
+   glRotatef(h->Angle, 0, 0, 1);
+   glBegin(GL_TRIANGLES);
+   glTexCoord2f(0.5, 1.0);   glVertex2f(0, 0.8);
+   glTexCoord2f(0.0, 0.0);   glVertex2f(-0.8, -0.7);
+   glTexCoord2f(1.0, 0.0);   glVertex2f(0.8, -0.7);
+   glEnd();
+   glPopMatrix();
+
+   if (!SwapSeparate)
+      glXSwapBuffers(h->Dpy, h->Win);
+}
+
+
+static void
+Swap(struct head *h)
+{
+   glXSwapBuffers(h->Dpy, h->Win);
+}
+
+
+static void
+Resize(const struct head *h, unsigned int width, unsigned int height)
+{
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
+      return;
+   }
+   glFlush();
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+}
+
+
+
+static void
+EventLoop(void)
+{
+   while (1) {
+      int i;
+      for (i = 0; i < NumHeads; i++) {
+         struct head *h = &Heads[i];
+         while (XPending(h->Dpy) > 0) {
+            XEvent event;
+            XNextEvent(h->Dpy, &event);
+            if (event.xany.window == h->Win) {
+               switch (event.type) {
+                  case Expose:
+                     Redraw(h);
+                     if (SwapSeparate)
+                        Swap(h);
+                     break;
+                  case ConfigureNotify:
+                     Resize(h, event.xconfigure.width, event.xconfigure.height);
+                     break;
+                  case KeyPress:
+                     {
+                        char buf[100];
+                        KeySym keySym;
+                        XComposeStatus stat;
+                        XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+                        switch (keySym) {
+                           case XK_Escape:
+                              return;
+                              break;
+                           case XK_d:
+                           case XK_D:
+                              printf("Delete Texture in window %d\n", i);
+                              glXMakeCurrent(h->Dpy, h->Win, h->Context);
+                              glDeleteTextures(1, &TexObj);
+                              break;
+                           case XK_u:
+                           case XK_U:
+                              printf("Unbind Texture in window %d\n", i);
+                              glXMakeCurrent(h->Dpy, h->Win, h->Context);
+                              glBindTexture(GL_TEXTURE_2D, 0);
+                              break;
+                        }
+                     }
+                     break;
+                  default:
+                     /*no-op*/ ;
+               }
+            }
+            else {
+               printf("window mismatch\n");
+            }
+         }
+      }
+
+      /* redraw all windows */
+      for (i = 0; i < NumHeads; i++) {
+         Redraw(&Heads[i]);
+      }
+      /* swapbuffers on all windows, if not already done */
+      if (SwapSeparate) {
+         for (i = 0; i < NumHeads; i++) {
+            Swap(&Heads[i]);
+         }
+      }
+      usleep(1);
+   }
+}
+
+
+
+static void
+PrintInfo(const struct head *h)
+{
+   printf("Name: %s\n", h->DisplayName);
+   printf("  Display:     %p\n", (void *) h->Dpy);
+   printf("  Window:      0x%x\n", (int) h->Win);
+   printf("  Context:     0x%lx\n", (long) h->Context);
+   printf("  GL_VERSION:  %s\n", h->Version);
+   printf("  GL_VENDOR:   %s\n", h->Vendor);
+   printf("  GL_RENDERER: %s\n", h->Renderer);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   char *dpyName = NULL;
+   int i;
+
+   if (argc == 1) {
+      printf("manywin: open N simultaneous glx windows\n");
+      printf("Usage:\n");
+      printf("  manywin [-s] numWindows\n");
+      printf("Options:\n");
+      printf("  -s = swap immediately after drawing (see src code)\n");
+      printf("Example:\n");
+      printf("  manywin 10\n");
+      return 0;
+   }
+   else {
+      int n = 3;
+      for (i = 1; i < argc; i++) {
+         if (strcmp(argv[i], "-s") == 0) {
+            SwapSeparate = GL_FALSE;
+         }
+         else if (strcmp(argv[i], "-display") == 0 && i < argc) {
+            dpyName = argv[i+1];
+            i++;
+         }
+         else {
+            n = atoi(argv[i]);
+         }
+      }
+      if (n < 1)
+         n = 1;
+      if (n > MAX_HEADS)
+         n = MAX_HEADS;
+
+      printf("%d windows\n", n);
+      for (i = 0; i < n; i++) {
+         char name[100];
+         struct head *h;
+         sprintf(name, "%d", i);
+         h = AddHead(dpyName, name);
+         if (h) {
+            PrintInfo(h);
+         }
+      }
+   }
+
+   EventLoop();
+   DestroyHeads();
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/msctest.c Mesa-7.8.1.patched/progs/xdemos/msctest.c
--- Mesa-7.8.1/progs/xdemos/msctest.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/msctest.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jesse Barnes <jesse.barnes@intel.com>
+ *
+ */
+
+/** @file msctest.c
+ * Simple test for MSC functionality.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+void (*get_sync_values)(Display *dpy, Window winGL, int64_t *ust, int64_t *msc, int64_t *sbc);
+void (*wait_sync)(Display *dpy, Window winGL, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
+
+static int GLXExtensionSupported(Display *dpy, const char *extension)
+{
+	const char *extensionsString, *pos;
+
+	extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
+
+	pos = strstr(extensionsString, extension);
+
+	if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
+	    (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
+		return 1;
+
+	return 0;
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "v";
+
+static void usage(char *name)
+{
+	printf("usage: %s\n", name);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	Display *disp;
+	XVisualInfo *pvi;
+	XSetWindowAttributes swa;
+	int attrib[14];
+	Window winGL;
+	GLXContext context;
+	int dummy;
+	Atom wmDelete;
+	int verbose = 0, width = 200, height = 200;
+	int c, i = 1;
+	int64_t ust, msc, sbc;
+
+	opterr = 0;
+	while ((c = getopt(argc, argv, optstr)) != -1) {
+		switch (c) {
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	}
+
+	disp = XOpenDisplay(NULL);
+	if (!disp) {
+		fprintf(stderr, "failed to open display\n");
+		return -1;
+	}
+
+	if (!glXQueryExtension(disp, &dummy, &dummy)) {
+		fprintf(stderr, "glXQueryExtension failed\n");
+		return -1;
+	}
+
+	if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) {
+		fprintf(stderr, "GLX_OML_sync_control not supported, exiting\n");
+		return -1;
+	}
+
+	attrib[0] = GLX_RGBA;
+	attrib[1] = 1;
+	attrib[2] = GLX_RED_SIZE;
+	attrib[3] = 1;
+	attrib[4] = GLX_GREEN_SIZE;
+	attrib[5] = 1;
+	attrib[6] = GLX_BLUE_SIZE;
+	attrib[7] = 1;
+	attrib[8] = GLX_DOUBLEBUFFER;
+	attrib[9] = 1;
+	attrib[10] = None;
+
+	pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib);
+	if (!pvi) {
+		fprintf(stderr, "failed to choose visual, exiting\n");
+		return -1;
+	}
+
+	context = glXCreateContext(disp, pvi, None, GL_TRUE);
+	if (!context) {
+		fprintf(stderr, "failed to create glx context\n");
+		return -1;
+	}
+
+	pvi->screen = DefaultScreen(disp);
+
+	swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
+				       pvi->visual, AllocNone);
+	swa.border_pixel = 0;
+	swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+		StructureNotifyMask;
+	winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
+			      0, 0,
+			      width, height,
+			      0, pvi->depth, InputOutput, pvi->visual,
+			      CWBorderPixel | CWColormap | CWEventMask, &swa);
+	if (!winGL) {
+		fprintf(stderr, "window creation failed\n");
+		return -1;
+	}
+        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
+        XSetWMProtocols(disp, winGL, &wmDelete, 1);
+
+	XSetStandardProperties(disp, winGL, "msc test", "msc text",
+			       None, NULL, 0, NULL);
+
+	XMapRaised(disp, winGL);
+
+	glXMakeCurrent(disp, winGL, context);
+
+	get_sync_values = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
+	wait_sync = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
+
+	if (!get_sync_values || !wait_sync) {
+		fprintf(stderr, "failed to get sync values function\n");
+		return -1;
+	}
+
+	while (i++) {
+		get_sync_values(disp, winGL, &ust, &msc, &sbc);
+		fprintf(stderr, "ust: %llu, msc: %llu, sbc: %llu\n", ust, msc,
+			sbc);
+
+		/* Alternate colors to make tearing obvious */
+		if (i & 1)
+			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+		else
+			glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+		glClear(GL_COLOR_BUFFER_BIT);
+		glXSwapBuffers(disp, winGL);
+		wait_sync(disp, winGL, 0, 60, 0, &ust, &msc, &sbc);
+		fprintf(stderr,
+			"wait returned ust: %llu, msc: %llu, sbc: %llu\n",
+			ust, msc, sbc);
+		sleep(1);
+	}
+
+	XDestroyWindow(disp, winGL);
+	glXDestroyContext(disp, context);
+	XCloseDisplay(disp);
+
+	return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/multictx.c Mesa-7.8.1.patched/progs/xdemos/multictx.c
--- Mesa-7.8.1/progs/xdemos/multictx.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/multictx.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Test rendering with two contexts into one window.
+ * Setup different rendering state for each context to check that
+ * context switching is handled properly.
+ *
+ * Brian Paul
+ * 6 Aug 2009
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+/** Event handler results: */
+#define NOP 0
+#define EXIT 1
+#define DRAW 2
+
+static GLfloat view_rotx = 0.0, view_roty = 210.0, view_rotz = 0.0;
+static GLint gear1, gear2;
+static GLfloat angle = 0.0;
+
+static GLboolean animate = GL_TRUE;	/* Animation */
+
+
+static double
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+
+/*
+ *
+ *  Draw a gear wheel.  You'll probably want to call this function when
+ *  building a display list since we do a lot of trig here.
+ * 
+ *  Input:  inner_radius - radius of hole at center
+ *          outer_radius - radius at center of teeth
+ *          width - width of gear
+ *          teeth - number of teeth
+ *          tooth_depth - depth of tooth
+ */
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat angle, da;
+   GLfloat u, v, len;
+
+   r0 = inner_radius;
+   r1 = outer_radius - tooth_depth / 2.0;
+   r2 = outer_radius + tooth_depth / 2.0;
+
+   da = 2.0 * M_PI / teeth / 4.0;
+
+   glShadeModel(GL_FLAT);
+
+   glNormal3f(0.0, 0.0, 1.0);
+
+   /* draw front face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw front sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+   }
+   glEnd();
+
+   glNormal3f(0.0, 0.0, -1.0);
+
+   /* draw back face */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      if (i < teeth) {
+	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		    -width * 0.5);
+	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      }
+   }
+   glEnd();
+
+   /* draw back sides of teeth */
+   glBegin(GL_QUADS);
+   da = 2.0 * M_PI / teeth / 4.0;
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+   }
+   glEnd();
+
+   /* draw outward faces of teeth */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i < teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+      u = r2 * cos(angle + da) - r1 * cos(angle);
+      v = r2 * sin(angle + da) - r1 * sin(angle);
+      len = sqrt(u * u + v * v);
+      u /= len;
+      v /= len;
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 width * 0.5);
+      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+		 -width * 0.5);
+      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+      glNormal3f(v, -u, 0.0);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+		 -width * 0.5);
+      glNormal3f(cos(angle), sin(angle), 0.0);
+   }
+
+   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+   glEnd();
+
+   glShadeModel(GL_SMOOTH);
+
+   /* draw inside radius cylinder */
+   glBegin(GL_QUAD_STRIP);
+   for (i = 0; i <= teeth; i++) {
+      angle = i * 2.0 * M_PI / teeth;
+      glNormal3f(-cos(angle), -sin(angle), 0.0);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+   }
+   glEnd();
+}
+
+
+static void
+draw(int ctx)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1.0, 0.0, 0.0);
+   glRotatef(view_roty + angle, 0.0, 1.0, 0.0);
+   glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+   if (ctx == 0) {
+      glDisable(GL_CULL_FACE);
+      glPushMatrix();
+      glRotatef(angle, 0.0, 0.0, 1.0);
+      glCallList(gear1);
+      glPopMatrix();
+      /* This should not effect the other context's rendering */
+      glEnable(GL_CULL_FACE);
+      glCullFace(GL_FRONT_AND_BACK);
+   }
+   else {
+      glPushMatrix();
+      glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+      glCallList(gear2);
+      glPopMatrix();
+   }
+
+   glPopMatrix();
+
+   /* this flush is important since we'll be switching contexts next */
+   glFlush();
+}
+
+
+
+static void
+draw_frame(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
+{
+   static double tRot0 = -1.0;
+   double dt, t = current_time();
+
+   if (tRot0 < 0.0)
+      tRot0 = t;
+   dt = t - tRot0;
+   tRot0 = t;
+
+   if (animate) {
+      /* advance rotation for next frame */
+      angle += 70.0 * dt;  /* 70 degrees per second */
+      if (angle > 3600.0)
+         angle -= 3600.0;
+   }
+
+   glXMakeCurrent(dpy, (GLXDrawable) win, ctx1);
+   draw(0);
+
+   glXMakeCurrent(dpy, (GLXDrawable) win, ctx2);
+   draw(1);
+
+   glXSwapBuffers(dpy, win);
+}
+
+
+/* new window size or exposure */
+static void
+reshape(Display *dpy, Window win,
+        GLXContext ctx1, GLXContext ctx2, int width, int height)
+{
+   int i;
+
+   width /= 2;
+
+   /* loop: left half of window, right half of window */
+   for (i = 0; i < 2; i++) {
+      if (i == 0)
+         glXMakeCurrent(dpy, win, ctx1);
+      else
+         glXMakeCurrent(dpy, win, ctx2);
+
+      glViewport(width * i, 0, width, height);
+      glScissor(width * i, 0, width, height);
+
+      {
+         GLfloat h = (GLfloat) height / (GLfloat) width;
+
+         glMatrixMode(GL_PROJECTION);
+         glLoadIdentity();
+         glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+      }
+
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      glTranslatef(0.0, 0.0, -30.0);
+   }
+}
+   
+
+
+static void
+init(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
+{
+   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   static GLfloat green[4] = { 0.0, 0.8, 0.2, 0.5 };
+   /*static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };*/
+
+   /* first ctx */
+   {
+      static GLuint stipple[32] = {
+         0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
+         0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
+
+         0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+         0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+
+         0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
+         0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
+
+         0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
+         0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00
+      };
+
+      glXMakeCurrent(dpy, win, ctx1);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_DEPTH_TEST);
+
+      gear1 = glGenLists(1);
+      glNewList(gear1, GL_COMPILE);
+      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+      gear(1.0, 4.0, 1.0, 20, 0.7);
+      glEndList();
+
+      glEnable(GL_NORMALIZE);
+      glEnable(GL_SCISSOR_TEST);
+      glClearColor(0.4, 0.4, 0.4, 1.0);
+
+      glPolygonStipple((GLubyte *) stipple);
+      glEnable(GL_POLYGON_STIPPLE);
+   }
+
+   /* second ctx */
+   {
+      glXMakeCurrent(dpy, win, ctx2);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_DEPTH_TEST);
+
+      gear2 = glGenLists(1);
+      glNewList(gear2, GL_COMPILE);
+      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+      gear(1.5, 3.0, 1.5, 16, 0.7);
+      glEndList();
+
+      glEnable(GL_NORMALIZE);
+      glEnable(GL_SCISSOR_TEST);
+      glClearColor(0.6, 0.6, 0.6, 1.0);
+
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+   }
+}
+
+
+/**
+ * Create an RGB, double-buffered window.
+ * Return the window and two context handles.
+ */
+static void
+make_window_and_contexts( Display *dpy, const char *name,
+                          int x, int y, int width, int height,
+                          Window *winRet,
+                          GLXContext *ctxRet1,
+                          GLXContext *ctxRet2)
+{
+   int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, attribs );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, x, y, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   *winRet = win;
+   *ctxRet1 = glXCreateContext( dpy, visinfo, NULL, True );
+   *ctxRet2 = glXCreateContext( dpy, visinfo, NULL, True );
+
+   if (!*ctxRet1 || !*ctxRet2) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   XFree(visinfo);
+}
+
+
+/**
+ * Handle one X event.
+ * \return NOP, EXIT or DRAW
+ */
+static int
+handle_event(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2,
+             XEvent *event)
+{
+   (void) dpy;
+   (void) win;
+
+   switch (event->type) {
+   case Expose:
+      return DRAW;
+   case ConfigureNotify:
+      reshape(dpy, win, ctx1, ctx2,
+              event->xconfigure.width, event->xconfigure.height);
+      break;
+   case KeyPress:
+      {
+         char buffer[10];
+         int r, code;
+         code = XLookupKeysym(&event->xkey, 0);
+         if (code == XK_Left) {
+            view_roty += 5.0;
+         }
+         else if (code == XK_Right) {
+            view_roty -= 5.0;
+         }
+         else if (code == XK_Up) {
+            view_rotx += 5.0;
+         }
+         else if (code == XK_Down) {
+            view_rotx -= 5.0;
+         }
+         else {
+            r = XLookupString(&event->xkey, buffer, sizeof(buffer),
+                              NULL, NULL);
+            if (buffer[0] == 27) {
+               /* escape */
+               return EXIT;
+            }
+            else if (buffer[0] == 'a' || buffer[0] == 'A') {
+               animate = !animate;
+            }
+         }
+         return DRAW;
+      }
+   }
+   return NOP;
+}
+
+
+static void
+event_loop(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2)
+{
+   while (1) {
+      int op;
+      while (!animate || XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         op = handle_event(dpy, win, ctx1, ctx2, &event);
+         if (op == EXIT)
+            return;
+         else if (op == DRAW)
+            break;
+      }
+
+      draw_frame(dpy, win, ctx1, ctx2);
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   unsigned int winWidth = 800, winHeight = 400;
+   int x = 0, y = 0;
+   Display *dpy;
+   Window win;
+   GLXContext ctx1, ctx2;
+   char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else {
+         return 1;
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n",
+	     dpyName ? dpyName : getenv("DISPLAY"));
+      return -1;
+   }
+
+   make_window_and_contexts(dpy, "multictx", x, y, winWidth, winHeight,
+                            &win, &ctx1, &ctx2);
+   XMapWindow(dpy, win);
+
+   if (printInfo) {
+      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));
+   }
+
+   init(dpy, win, ctx1, ctx2);
+
+   /* Set initial projection/viewing transformation.
+    * We can't be sure we'll get a ConfigureNotify event when the window
+    * first appears.
+    */
+   reshape(dpy, win, ctx1, ctx2, winWidth, winHeight);
+
+   event_loop(dpy, win, ctx1, ctx2);
+
+   glDeleteLists(gear1, 1);
+   glDeleteLists(gear2, 1);
+   glXDestroyContext(dpy, ctx1);
+   glXDestroyContext(dpy, ctx2);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/offset.c Mesa-7.8.1.patched/progs/xdemos/offset.c
--- Mesa-7.8.1/progs/xdemos/offset.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/offset.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,343 @@
+/****************************************************************************
+Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+****************************************************************************/
+
+/*
+ * Derived from code written by Kurt Akeley, November 1992
+ *
+ *	Uses PolygonOffset to draw hidden-line images.  PolygonOffset
+ *	    shifts the z values of polygons an amount that is
+ *	    proportional to their slope in screen z.  This keeps
+ *	    the lines, which are drawn without displacement, from
+ *	    interacting with their respective polygons, and
+ *	    thus eliminates line dropouts.
+ *
+ *	The left image shows an ordinary antialiased wireframe image.
+ *	The center image shows an antialiased hidden-line image without
+ *	    PolygonOffset.
+ *	The right image shows an antialiased hidden-line image using
+ *	    PolygonOffset to reduce artifacts.
+ *
+ *	Drag with a mouse button pressed to rotate the models.
+ *	Press the escape key to exit.
+ */
+
+/*
+ * Modified for OpenGL 1.1 glPolygonOffset() conventions
+ */
+
+
+#include <GL/glx.h>
+#include <X11/keysym.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef GL_EXT_polygon_offset  /* use GL 1.1 version instead of extension */
+
+
+#ifndef EXIT_FAILURE
+#  define EXIT_FAILURE    1
+#endif
+#ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS    0
+#endif
+
+#define MAXQUAD 6
+
+typedef float Vertex[3];
+
+typedef Vertex Quad[4];
+
+/* data to define the six faces of a unit cube */
+Quad quads[MAXQUAD] = {
+   { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
+   { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
+   { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
+   { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
+   { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
+   { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} }  /* z = 1 */
+};
+
+#define WIREFRAME	0
+#define HIDDEN_LINE	1
+
+static void error(const char* prog, const char* msg);
+static void cubes(int mx, int my, int mode);
+static void fill(Quad quad);
+static void outline(Quad quad);
+static void draw_hidden(Quad quad, int mode, int face);
+static void process_input(Display *dpy, Window win);
+static int query_extension(char* extName);
+
+static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
+    GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None };
+
+static int dimension = 3;
+
+static float Scale = 1.0;
+
+
+int main(int argc, char** argv) {
+    Display *dpy;
+    XVisualInfo *vi;
+    XSetWindowAttributes swa;
+    Window win;
+    GLXContext cx;
+    GLint z;
+
+    dpy = XOpenDisplay(0);
+    if (!dpy) error(argv[0], "can't open display");
+
+    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
+    if (!vi) error(argv[0], "no suitable visual");
+
+    cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+
+    swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
+                                   vi->visual, AllocNone);
+
+    swa.border_pixel = 0;
+    swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
+	ButtonPressMask | ButtonMotionMask;
+    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
+			0, vi->depth, InputOutput, vi->visual,
+			CWBorderPixel|CWColormap|CWEventMask, &swa);
+    XStoreName(dpy, win, "hiddenline");
+    XMapWindow(dpy, win);
+
+    glXMakeCurrent(dpy, win, cx);
+
+    /* check for the polygon offset extension */
+#ifndef GL_VERSION_1_1
+    if (!query_extension("GL_EXT_polygon_offset"))
+        error(argv[0], "polygon_offset extension is not available");
+#else
+   (void) query_extension;
+#endif
+
+    /* set up viewing parameters */
+    glMatrixMode(GL_PROJECTION);
+    glFrustum(-1, 1, -1, 1, 6, 20);
+    glMatrixMode(GL_MODELVIEW);
+    glTranslatef(0, 0, -15);
+
+    /* set other relevant state information */
+    glEnable(GL_DEPTH_TEST);
+
+    glGetIntegerv(GL_DEPTH_BITS, &z);
+    printf("GL_DEPTH_BITS = %d\n", z);
+
+#ifdef GL_EXT_polygon_offset
+    printf("using 1.0 offset extension\n");
+    glPolygonOffsetEXT( 1.0, 0.00001 );
+#else
+    printf("using 1.1 offset\n");
+    glPolygonOffset( 1.0, 0.5 );
+#endif
+
+    glShadeModel( GL_FLAT );
+    glDisable( GL_DITHER );
+
+    /* process events until the user presses ESC */
+    while (1) process_input(dpy, win);
+
+    return 0;
+}
+
+static void
+draw_scene(int mx, int my) {
+   glClearColor(0.25, 0.25, 0.25, 0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glPushMatrix();
+    glTranslatef(-1.7, 0.0, 0.0);
+    cubes(mx, my, WIREFRAME);
+    glPopMatrix();
+
+    glPushMatrix();
+    cubes(mx, my, HIDDEN_LINE);
+    glPopMatrix();
+
+    glPushMatrix();
+    glTranslatef(1.7, 0.0, 0.0);
+#ifdef GL_EXT_polygon_offset
+    glEnable(GL_POLYGON_OFFSET_EXT);
+#else
+    glEnable(GL_POLYGON_OFFSET_FILL);
+#endif
+    glScalef(Scale, Scale, Scale);
+    cubes(mx, my, HIDDEN_LINE);
+#ifdef GL_EXT_polygon_offset
+    glDisable(GL_POLYGON_OFFSET_EXT);
+#else
+    glDisable(GL_POLYGON_OFFSET_FILL);
+#endif
+    glPopMatrix();
+}
+
+
+static void
+cubes(int mx, int my, int mode) {
+    int x, y, z, i;
+
+    /* track the mouse */
+    glRotatef(mx / 2.0, 0, 1, 0);
+    glRotatef(my / 2.0, 1, 0, 0);
+
+    /* draw the lines as hidden polygons */
+    glTranslatef(-0.5, -0.5, -0.5);
+    glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
+    for (z = 0; z < dimension; z++) {
+	for (y = 0; y < dimension; y++) {
+	    for (x = 0; x < dimension; x++) {
+		glPushMatrix();
+		glTranslatef(x, y, z);
+		glScalef(0.8, 0.8, 0.8);
+		for (i = 0; i < MAXQUAD; i++)
+                    draw_hidden(quads[i], mode, i);
+		glPopMatrix();
+	    }
+	}
+    }
+}
+
+static void
+fill(Quad quad) {
+    /* draw a filled polygon */
+    glBegin(GL_QUADS);
+    glVertex3fv(quad[0]);
+    glVertex3fv(quad[1]);
+    glVertex3fv(quad[2]);
+    glVertex3fv(quad[3]);
+    glEnd();
+}
+
+static void
+outline(Quad quad) {
+    /* draw an outlined polygon */
+    glBegin(GL_LINE_LOOP);
+    glVertex3fv(quad[0]);
+    glVertex3fv(quad[1]);
+    glVertex3fv(quad[2]);
+    glVertex3fv(quad[3]);
+    glEnd();
+}
+
+static void
+draw_hidden(Quad quad, int mode, int face) {
+    static const GLfloat colors[3][3] = {
+        {0.5, 0.5, 0.0},
+        {0.8, 0.5, 0.0},
+        {0.0, 0.5, 0.8}
+    };
+    if (mode == HIDDEN_LINE) {
+        glColor3fv(colors[face % 3]);
+	fill(quad);
+    }
+
+    /* draw the outline using white */
+    glColor3f(1, 1, 1);
+    outline(quad);
+}
+
+static void
+process_input(Display *dpy, Window win) {
+    XEvent event;
+    static int prevx, prevy;
+    static int deltax = 90, deltay = 40;
+
+    do {
+	char buf[31];
+	KeySym keysym;
+
+	XNextEvent(dpy, &event);
+	switch(event.type) {
+	case Expose:
+	    break;
+	case ConfigureNotify: {
+	    /* this approach preserves a 1:1 viewport aspect ratio */
+	    int vX, vY, vW, vH;
+	    int eW = event.xconfigure.width, eH = event.xconfigure.height;
+	    if (eW >= eH) {
+		vX = 0;
+		vY = (eH - eW) >> 1;
+		vW = vH = eW;
+	    } else {
+		vX = (eW - eH) >> 1;
+		vY = 0;
+		vW = vH = eH;
+	    }
+	    glViewport(vX, vY, vW, vH);
+	    }
+	    break;
+	case KeyPress:
+	    (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
+	    switch (keysym) {
+            case 'Z':
+               Scale *= 1.1;
+               break;
+            case 'z':
+               Scale *= 0.9;
+               break;
+	    case XK_Escape:
+		exit(EXIT_SUCCESS);
+	    default:
+		break;
+	    }
+	    break;
+	case ButtonPress:
+	    prevx = event.xbutton.x;
+	    prevy = event.xbutton.y;
+	    break;
+	case MotionNotify:
+	    deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
+	    deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
+	    break;
+	default:
+	    break;
+	}
+    } while (XPending(dpy));
+
+    draw_scene(deltax, deltay);
+    glXSwapBuffers(dpy, win);
+}
+
+static void
+error(const char *prog, const char *msg) {
+    fprintf(stderr, "%s: %s\n", prog, msg);
+    exit(EXIT_FAILURE);
+}
+
+static int
+query_extension(char* extName) {
+    char *p = (char *) glGetString(GL_EXTENSIONS);
+    char *end = p + strlen(p);
+    while (p < end) {
+        int n = strcspn(p, " ");
+        if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
+            return GL_TRUE;
+        p += (n + 1);
+    }
+    return GL_FALSE;
+}
+
diff -Naurp Mesa-7.8.1/progs/xdemos/omlsync.c Mesa-7.8.1.patched/progs/xdemos/omlsync.c
--- Mesa-7.8.1/progs/xdemos/omlsync.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/omlsync.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,265 @@
+/*
+ * Copyright © 2007-2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jesse Barnes <jesse.barnes@intel.com>
+ *
+ */
+
+/** @file omlsync.c
+ * The program is simple:  it paints a window alternating colors (red &
+ * white) either as fast as possible or synchronized to vblank events
+ *
+ * If run normally, the program should display a window that exhibits
+ * significant tearing between red and white colors (e.g. you might get
+ * a "waterfall" effect of red and white horizontal bars).
+ *
+ * If run with the '-s b' option, the program should synchronize the
+ * window color changes with the vertical blank period, resulting in a
+ * window that looks orangish with a high frequency flicker (which may
+ * be invisible).  If the window is moved to another screen, this
+ * property should be preserved.  If the window spans two screens, it
+ * shouldn't tear on whichever screen most of the window is on; the
+ * portion on the other screen may show some tearing (like the
+ * waterfall effect above).
+ *
+ * Other options include '-w <width>' and '-h <height>' to set the
+ * window size.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+Bool (*glXGetSyncValuesOML)(Display *dpy, GLXDrawable drawable,
+			    int64_t *ust, int64_t *msc, int64_t *sbc);
+Bool (*glXGetMscRateOML)(Display *dpy, GLXDrawable drawable, int32_t *numerator,
+			 int32_t *denominator);
+int64_t (*glXSwapBuffersMscOML)(Display *dpy, GLXDrawable drawable,
+				int64_t target_msc, int64_t divisor,
+				int64_t remainder);
+Bool (*glXWaitForMscOML)(Display *dpy, GLXDrawable drawable, int64_t target_msc,
+			 int64_t divisor, int64_t remainder, int64_t *ust,
+			 int64_t *msc, int64_t *sbc);
+Bool (*glXWaitForSbcOML)(Display *dpy, GLXDrawable drawable, int64_t target_sbc,
+			 int64_t *ust, int64_t *msc, int64_t *sbc);
+int (*glXSwapInterval)(int interval);
+
+static int GLXExtensionSupported(Display *dpy, const char *extension)
+{
+	const char *extensionsString, *pos;
+
+	extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
+
+	pos = strstr(extensionsString, extension);
+
+	if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
+	    (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
+		return 1;
+
+	return 0;
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "w:h:vd:r:n:i:";
+
+static void usage(char *name)
+{
+	printf("usage: %s [-w <width>] [-h <height>] ...\n", name);
+	printf("\t-d<divisor> - divisor for OML swap\n");
+	printf("\t-r<remainder> - remainder for OML swap\n");
+	printf("\t-n<interval> - wait interval for OML WaitMSC\n");
+	printf("\t-i<swap interval> - swap at most once every n frames\n");
+	printf("\t-v: verbose (print count)\n");
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	Display *disp;
+	XVisualInfo *pvi;
+	XSetWindowAttributes swa;
+	Window winGL;
+	GLXContext context;
+	int dummy;
+	Atom wmDelete;
+	int64_t ust, msc, sbc;
+	int width = 500, height = 500, verbose = 0, divisor = 0, remainder = 0,
+		wait_interval = 0, swap_interval = 1;
+	int c, i = 1;
+	int ret;
+	int db_attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+	XSizeHints sizehints;
+
+	opterr = 0;
+	while ((c = getopt(argc, argv, optstr)) != -1) {
+		switch (c) {
+		case 'w':
+			width = atoi(optarg);
+			break;
+		case 'h':
+			height = atoi(optarg);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'd':
+			divisor = atoi(optarg);
+			break;
+		case 'r':
+			remainder = atoi(optarg);
+			break;
+		case 'n':
+			wait_interval = atoi(optarg);
+			break;
+		case 'i':
+			swap_interval = atoi(optarg);
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	}
+
+	disp = XOpenDisplay(NULL);
+	if (!disp) {
+		fprintf(stderr, "failed to open display\n");
+		return -1;
+	}
+
+	if (!glXQueryExtension(disp, &dummy, &dummy)) {
+		fprintf(stderr, "glXQueryExtension failed\n");
+		return -1;
+	}
+
+	if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) {
+		fprintf(stderr, "GLX_OML_sync_control not supported\n");
+		return -1;
+	}
+
+	if (!GLXExtensionSupported(disp, "GLX_MESA_swap_control")) {
+		fprintf(stderr, "GLX_MESA_swap_control not supported\n");
+		return -1;
+	}
+
+	pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs);
+
+	if (!pvi) {
+		fprintf(stderr, "failed to choose visual, exiting\n");
+		return -1;
+	}
+
+	pvi->screen = DefaultScreen(disp);
+
+	swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
+				       pvi->visual, AllocNone);
+	swa.border_pixel = 0;
+	swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+		StructureNotifyMask;
+	winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
+			      0, 0,
+			      width, height,
+			      0, pvi->depth, InputOutput, pvi->visual,
+			      CWBorderPixel | CWColormap | CWEventMask, &swa);
+	if (!winGL) {
+		fprintf(stderr, "window creation failed\n");
+		return -1;
+	}
+        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
+        XSetWMProtocols(disp, winGL, &wmDelete, 1);
+
+	sizehints.x = 0;
+	sizehints.y = 0;
+	sizehints.width  = width;
+	sizehints.height = height;
+	sizehints.flags = USSize | USPosition;
+
+	XSetNormalHints(disp, winGL, &sizehints);
+	XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
+			       None, NULL, 0, &sizehints);
+
+	context = glXCreateContext(disp, pvi, NULL, GL_TRUE);
+	if (!context) {
+		fprintf(stderr, "failed to create glx context\n");
+		return -1;
+	}
+
+	XMapWindow(disp, winGL);
+	ret = glXMakeCurrent(disp, winGL, context);
+	if (!ret) {
+		fprintf(stderr, "failed to make context current: %d\n", ret);
+	}
+
+	glXGetSyncValuesOML = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
+	glXGetMscRateOML = (void *)glXGetProcAddress((unsigned char *)"glXGetMscRateOML");
+	glXSwapBuffersMscOML = (void *)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML");
+	glXWaitForMscOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
+	glXWaitForSbcOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML");
+	glXSwapInterval = (void *)glXGetProcAddress((unsigned char *)"glXSwapIntervalMESA");
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	glXSwapInterval(swap_interval);
+	fprintf(stderr, "set swap interval to %d\n", swap_interval);
+
+	glXGetSyncValuesOML(disp, winGL, &ust, &msc, &sbc);
+	while (i++) {
+		/* Alternate colors to make tearing obvious */
+		if (i & 1) {
+			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+			glColor3f(1.0f, 1.0f, 1.0f);
+		} else {
+			glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+			glColor3f(1.0f, 0.0f, 0.0f);
+		}
+
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		glRectf(0, 0, width, height);
+
+		glXSwapBuffersMscOML(disp, winGL, 0, divisor, remainder);
+
+		if (wait_interval) {
+			glXWaitForMscOML(disp, winGL, msc + wait_interval,
+					 0, 0, &ust, &msc, &sbc);
+		}
+	}
+
+	XDestroyWindow(disp, winGL);
+	glXDestroyContext(disp, context);
+	XCloseDisplay(disp);
+
+	return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/opencloseopen.c Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c
--- Mesa-7.8.1/progs/xdemos/opencloseopen.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * (C) Copyright IBM Corporation 2003
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+/** \file opencloseopen.c
+ * Simple test for Mesa bug #508473.  Create a window and rendering context.
+ * Draw a single frame.  Close the window, destroy the context, and close
+ * the display.  Re-open the display, create a new window and context.  This
+ * should work, but, at least as of Mesa 5.1, it segfaults.  See the bug
+ * report for more details.
+ * 
+ * Most of the code here was lifed from various other Mesa xdemos.
+ */
+
+static void
+draw(void)
+{
+   glViewport(0, 0, 300, 300);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   /* draw blue quad */
+   glLoadIdentity();
+   glColor3f(0.3, 0.3, 1.0);
+   glPushMatrix();
+   glRotatef(0, 0, 0, 1);
+   glBegin(GL_POLYGON);
+   glVertex2f(-0.5, -0.25);
+   glVertex2f( 0.5, -0.25);
+   glVertex2f( 0.5, 0.25);
+   glVertex2f(-0.5, 0.25);
+   glEnd();
+   glPopMatrix();}
+
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( const char * dpyName, const char *name,
+             int x, int y, int width, int height,
+	     Display **dpyRet, Window *winRet, GLXContext *ctxRet)
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+   Display *dpy;
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
+      exit(1);
+   }
+
+   *dpyRet = dpy;
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, attrib );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   XFree(visinfo);
+
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+static void
+destroy_window( Display *dpy, Window win, GLXContext ctx )
+{
+   glXMakeCurrent(dpy, None, NULL);
+   glXDestroyContext(dpy, ctx);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   char *dpyName = NULL;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+   }
+
+   printf("If this program segfaults, then Mesa bug #508473 is probably "
+	  "back.\n");
+   make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, win, ctx);
+
+   draw();
+   glXSwapBuffers(dpy, win);
+   sleep(2);
+
+   destroy_window(dpy, win, ctx);
+
+   make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, win, ctx);
+   destroy_window(dpy, win, ctx);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/overlay.c Mesa-7.8.1.patched/progs/xdemos/overlay.c
--- Mesa-7.8.1/progs/xdemos/overlay.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/overlay.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,246 @@
+/*
+ * GLX overlay test/demo.
+ *
+ * Brian Paul
+ * 18 July 2005
+ */
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <X11/keysym.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int WinWidth = 300, WinHeight = 300;
+static Window NormalWindow = 0;
+static Window OverlayWindow = 0;
+static GLXContext NormalContext = 0;
+static GLXContext OverlayContext = 0;
+static GLboolean RGBOverlay = GL_FALSE;
+static GLfloat Angle = 0.0;
+
+
+static void
+RedrawNormal(Display *dpy)
+{
+   glXMakeCurrent(dpy, NormalWindow, NormalContext);
+   glViewport(0, 0, WinWidth, WinHeight);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+   glColor3f(1.0, 1.0, 0.0);
+   glPushMatrix();
+   glRotatef(Angle, 0, 0, 1);
+   glRectf(-0.8, -0.8, 0.8, 0.8);
+   glPopMatrix();
+   glXSwapBuffers(dpy, NormalWindow);
+}
+
+
+static void
+RedrawOverlay(Display *dpy)
+{
+   glXMakeCurrent(dpy, OverlayWindow, OverlayContext);
+   glViewport(0, 0, WinWidth, WinHeight);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+   glClear(GL_COLOR_BUFFER_BIT);
+   if (RGBOverlay) {
+      glColor3f(0.0, 1.0, 1.0);
+   }
+   else {
+      glIndexi(2);
+   }
+   glBegin(GL_LINES);
+   glVertex2f(-1, -1);
+   glVertex2f(1, 1);
+   glVertex2f(1, -1);
+   glVertex2f(-1, 1);
+   glEnd();
+   glXSwapBuffers(dpy, OverlayWindow);
+}
+
+
+static Window
+MakeWindow(Display *dpy, XVisualInfo *visinfo, Window parent,
+             unsigned int width, unsigned int height)
+{
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, parent, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   return win;
+}
+
+
+static void
+MakeNormalWindow(Display *dpy)
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   Window root;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, attrib);
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\n");
+      exit(1);
+   }
+
+   NormalWindow = MakeWindow(dpy, visinfo, root, WinWidth, WinHeight);
+   assert(NormalWindow);
+
+   NormalContext = glXCreateContext(dpy, visinfo, NULL, True);
+   assert(NormalContext);
+}
+
+
+static void
+MakeOverlayWindow(Display *dpy)
+{
+   int rgbAttribs[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      GLX_LEVEL, 1,
+      None
+   };
+   int indexAttribs[] = {
+      /*GLX_RGBA, leave this out */
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      GLX_LEVEL, 1,
+      None
+   };
+   int scrnum;
+   Window root;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, rgbAttribs);
+   if (visinfo) {
+      printf("Found RGB overlay visual 0x%x\n", (int) visinfo->visualid);
+      RGBOverlay = GL_TRUE;
+   }
+   else {
+      visinfo = glXChooseVisual(dpy, scrnum, indexAttribs);
+      if (visinfo) {
+         printf("Found Color Index overlay visual 0x%x\n",
+                (int) visinfo->visualid);
+         /* XXX setup the colormap entries! */
+      }
+      else {
+         printf("Couldn't get an overlay visual.\n");
+         printf("Your hardware probably doesn't support framebuffer overlay planes.\n");
+         exit(1);
+      }
+   }
+
+   OverlayWindow = MakeWindow(dpy, visinfo, NormalWindow, WinWidth, WinHeight);
+   assert(OverlayWindow);
+
+   OverlayContext = glXCreateContext(dpy, visinfo, NULL, True);
+   assert(OverlayContext);
+}
+
+
+static void
+EventLoop(Display *dpy)
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent(dpy, &event);
+
+      switch (event.type) {
+	 case Expose:
+	    RedrawNormal(dpy);
+	    RedrawOverlay(dpy);
+	    break;
+	 case ConfigureNotify:
+            WinWidth = event.xconfigure.width;
+            WinHeight = event.xconfigure.height;
+            if (event.xconfigure.window == NormalWindow)
+               XResizeWindow(dpy, OverlayWindow, WinWidth, WinHeight);
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+	       r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+				 NULL, NULL);
+	       if (buffer[0] == 27) {
+                  /* escape */
+                  return;
+               }
+               else if (buffer[0] == ' ') {
+                  Angle += 5.0;
+                  RedrawNormal(dpy);
+               }
+            }
+            break;
+         default:
+            ; /* nothing */
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy = XOpenDisplay(NULL);
+
+   assert(dpy);
+
+   MakeNormalWindow(dpy);
+   MakeOverlayWindow(dpy);
+
+   XMapWindow(dpy, NormalWindow);
+   XMapWindow(dpy, OverlayWindow);
+
+   EventLoop(dpy);
+
+   glXDestroyContext(dpy, OverlayContext);
+   glXDestroyContext(dpy, NormalContext);
+   XDestroyWindow(dpy, OverlayWindow);
+   XDestroyWindow(dpy, NormalWindow);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/pbdemo.c Mesa-7.8.1.patched/progs/xdemos/pbdemo.c
--- Mesa-7.8.1/progs/xdemos/pbdemo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/pbdemo.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,493 @@
+
+/*
+ * This program demonstrates how to do "off-screen" rendering using
+ * the GLX pixel buffer extension.
+ *
+ * Written by Brian Paul for the "OpenGL and Window System Integration"
+ * course presented at SIGGRAPH '97.  Updated on 5 October 2002.
+ *
+ * Usage:
+ *   pbuffers width height imgfile
+ * Where:
+ *   width is the width, in pixels, of the image to generate.
+ *   height is the height, in pixels, of the image to generate.
+ *   imgfile is the name of the PPM image file to write.
+ *
+ *
+ * This demo draws 3-D boxes with random orientation.  A pbuffer with
+ * a depth (Z) buffer is prefered but if such a pbuffer can't be created
+ * we use a non-depth-buffered config.
+ *
+ * On machines such as the SGI Indigo you may have to reconfigure your
+ * display/X server to enable pbuffers.  Look in the /usr/gfx/ucode/MGRAS/vof/
+ * directory for display configurationswith the _pbuf suffix.  Use
+ * setmon -x <vof> to configure your X server and display for pbuffers.
+ *
+ * O2 systems seem to support pbuffers well.
+ *
+ * IR systems (at least 1RM systems) don't have single-buffered, RGBA,
+ * Z-buffered pbuffer configs.  BUT, they DO have DOUBLE-buffered, RGBA,
+ * Z-buffered pbuffers.  Note how we try four different fbconfig attribute
+ * lists below!
+ */
+
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include "pbutil.h"
+
+
+/* Some ugly global vars */
+static Display *gDpy = NULL;
+static int gScreen = 0;
+static FBCONFIG gFBconfig = 0;
+static PBUFFER gPBuffer = 0;
+static int gWidth, gHeight;
+static GLXContext glCtx;
+
+
+
+/*
+ * Create the pbuffer and return a GLXPbuffer handle.
+ *
+ * We loop over a list of fbconfigs trying to create
+ * a pixel buffer.  We return the first pixel buffer which we successfully
+ * create.
+ */
+static PBUFFER
+MakePbuffer( Display *dpy, int screen, int width, int height )
+{
+#define NUM_FB_CONFIGS 4
+   const char fbString[NUM_FB_CONFIGS][100] = {
+      "Single Buffered, depth buffer",
+      "Double Buffered, depth buffer",
+      "Single Buffered, no depth buffer",
+      "Double Buffered, no depth buffer"
+   };
+   int fbAttribs[NUM_FB_CONFIGS][100] = {
+      {
+         /* Single buffered, with depth buffer */
+         GLX_RENDER_TYPE, GLX_RGBA_BIT,
+         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+         GLX_RED_SIZE, 1,
+         GLX_GREEN_SIZE, 1,
+         GLX_BLUE_SIZE, 1,
+         GLX_DEPTH_SIZE, 1,
+         GLX_DOUBLEBUFFER, 0,
+         GLX_STENCIL_SIZE, 0,
+         None
+      },
+      {
+         /* Double buffered, with depth buffer */
+         GLX_RENDER_TYPE, GLX_RGBA_BIT,
+         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+         GLX_RED_SIZE, 1,
+         GLX_GREEN_SIZE, 1,
+         GLX_BLUE_SIZE, 1,
+         GLX_DEPTH_SIZE, 1,
+         GLX_DOUBLEBUFFER, 1,
+         GLX_STENCIL_SIZE, 0,
+         None
+      },
+      {
+         /* Single buffered, without depth buffer */
+         GLX_RENDER_TYPE, GLX_RGBA_BIT,
+         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+         GLX_RED_SIZE, 1,
+         GLX_GREEN_SIZE, 1,
+         GLX_BLUE_SIZE, 1,
+         GLX_DEPTH_SIZE, 0,
+         GLX_DOUBLEBUFFER, 0,
+         GLX_STENCIL_SIZE, 0,
+         None
+      },
+      {
+         /* Double buffered, without depth buffer */
+         GLX_RENDER_TYPE, GLX_RGBA_BIT,
+         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+         GLX_RED_SIZE, 1,
+         GLX_GREEN_SIZE, 1,
+         GLX_BLUE_SIZE, 1,
+         GLX_DEPTH_SIZE, 0,
+         GLX_DOUBLEBUFFER, 1,
+         GLX_STENCIL_SIZE, 0,
+         None
+      }
+   };
+   Bool largest = True;
+   Bool preserve = False;
+   FBCONFIG *fbConfigs;
+   PBUFFER pBuffer = None;
+   int nConfigs;
+   int i;
+   int attempt;
+
+   for (attempt=0; attempt<NUM_FB_CONFIGS; attempt++) {
+
+      /* Get list of possible frame buffer configurations */
+      fbConfigs = ChooseFBConfig(dpy, screen, fbAttribs[attempt], &nConfigs);
+      if (nConfigs==0 || !fbConfigs) {
+         printf("Note: glXChooseFBConfig(%s) failed\n", fbString[attempt]);
+         XFree(fbConfigs);
+         continue;
+      }
+
+#if 0 /*DEBUG*/
+      for (i=0;i<nConfigs;i++) {
+         printf("Config %d\n", i);
+         PrintFBConfigInfo(dpy, screen, fbConfigs[i], 0);
+      }
+#endif
+
+      /* Create the pbuffer using first fbConfig in the list that works. */
+      for (i=0;i<nConfigs;i++) {
+         pBuffer = CreatePbuffer(dpy, screen, fbConfigs[i], width, height, largest, preserve);
+         if (pBuffer) {
+            gFBconfig = fbConfigs[i];
+            gWidth = width;
+            gHeight = height;
+            break;
+         }
+      }
+
+      if (pBuffer!=None) {
+         break;
+      }
+   }
+
+   if (pBuffer) {
+      printf("Using: %s\n", fbString[attempt]);
+   }
+
+   XFree(fbConfigs);
+
+   return pBuffer;
+#undef NUM_FB_CONFIGS
+}
+
+
+
+/*
+ * Do all the X / GLX setup stuff.
+ */
+static int
+Setup(int width, int height)
+{
+   int pbSupport;
+   XVisualInfo *visInfo;
+
+   /* Open the X display */
+   gDpy = XOpenDisplay(NULL);
+   if (!gDpy) {
+      printf("Error: couldn't open default X display.\n");
+      return 0;
+   }
+
+   /* Get default screen */
+   gScreen = DefaultScreen(gDpy);
+
+   /* Test that pbuffers are available */
+   pbSupport = QueryPbuffers(gDpy, gScreen);
+   if (pbSupport == 1) {
+      printf("Using GLX 1.3 Pbuffers\n");
+   }
+   else if (pbSupport == 2) {
+      printf("Using SGIX Pbuffers\n");
+   }
+   else {
+      printf("Error: pbuffers not available on this screen\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   /* Create Pbuffer */
+   gPBuffer = MakePbuffer( gDpy, gScreen, width, height );
+   if (gPBuffer==None) {
+      printf("Error: couldn't create pbuffer\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   /* Test drawable queries */
+   {
+      unsigned int v;
+      glXQueryDrawable( gDpy, gPBuffer, GLX_WIDTH, &v);
+      printf("GLX_WIDTH = %u\n", v);
+      glXQueryDrawable( gDpy, gPBuffer, GLX_HEIGHT, &v);
+      printf("GLX_HEIGHT = %u\n", v);
+      glXQueryDrawable( gDpy, gPBuffer, GLX_PRESERVED_CONTENTS, &v);
+      printf("GLX_PRESERVED_CONTENTS = %u\n", v);
+      glXQueryDrawable( gDpy, gPBuffer, GLX_LARGEST_PBUFFER, &v);
+      printf("GLX_LARGEST_PBUFFER = %u\n", v);
+      glXQueryDrawable( gDpy, gPBuffer, GLX_FBCONFIG_ID, &v);
+      printf("GLX_FBCONFIG_ID = %u\n", v);
+   }
+
+   /* Get corresponding XVisualInfo */
+   visInfo = GetVisualFromFBConfig(gDpy, gScreen, gFBconfig);
+   if (!visInfo) {
+      printf("Error: can't get XVisualInfo from FBconfig\n");
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   /* Create GLX context */
+   glCtx = glXCreateContext(gDpy, visInfo, NULL, True);
+   if (!glCtx) {
+      /* try indirect */
+      glCtx = glXCreateContext(gDpy, visInfo, NULL, False);
+      if (!glCtx) {
+         printf("Error: Couldn't create GLXContext\n");
+         XFree(visInfo);
+         XCloseDisplay(gDpy);
+         return 0;
+      }
+      else {
+         printf("Warning: using indirect GLXContext\n");
+      }
+   }
+
+   /* Bind context to pbuffer */
+   if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) {
+      printf("Error: glXMakeCurrent failed\n");
+      XFree(visInfo);
+      XCloseDisplay(gDpy);
+      return 0;
+   }
+
+   return 1;  /* Success!! */
+}
+
+
+
+/* One-time GL setup */
+static void
+InitGL(void)
+{
+   static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0};
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glLightfv(GL_LIGHT0, GL_POSITION, pos);
+   glEnable(GL_NORMALIZE);
+   glEnable(GL_DEPTH_TEST);
+   glEnable(GL_CULL_FACE);
+
+   glViewport(0, 0, gWidth, gHeight);
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -15.0 );
+}
+
+
+/* Return random float in [0,1] */
+static float
+Random(void)
+{
+   int i = rand();
+   return (float) (i % 1000) / 1000.0;
+}
+
+
+static void
+RandomColor(void)
+{
+   GLfloat c[4];
+   c[0] = Random();
+   c[1] = Random();
+   c[2] = Random();
+   c[3] = 1.0;
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);
+}
+
+
+/* This function borrowed from Mark Kilgard's GLUT */
+static void
+drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1,
+  GLfloat z0, GLfloat z1, GLenum type)
+{
+  static GLfloat n[6][3] =
+  {
+    {-1.0, 0.0, 0.0},
+    {0.0, 1.0, 0.0},
+    {1.0, 0.0, 0.0},
+    {0.0, -1.0, 0.0},
+    {0.0, 0.0, 1.0},
+    {0.0, 0.0, -1.0}
+  };
+  static GLint faces[6][4] =
+  {
+    {0, 1, 2, 3},
+    {3, 2, 6, 7},
+    {7, 6, 5, 4},
+    {4, 5, 1, 0},
+    {5, 6, 2, 1},
+    {7, 4, 0, 3}
+  };
+  GLfloat v[8][3], tmp;
+  GLint i;
+
+  if (x0 > x1) {
+    tmp = x0;
+    x0 = x1;
+    x1 = tmp;
+  }
+  if (y0 > y1) {
+    tmp = y0;
+    y0 = y1;
+    y1 = tmp;
+  }
+  if (z0 > z1) {
+    tmp = z0;
+    z0 = z1;
+    z1 = tmp;
+  }
+  v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
+  v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
+  v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
+  v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
+  v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
+  v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
+
+  for (i = 0; i < 6; i++) {
+    glBegin(type);
+    glNormal3fv(&n[i][0]);
+    glVertex3fv(&v[faces[i][0]][0]);
+    glVertex3fv(&v[faces[i][1]][0]);
+    glVertex3fv(&v[faces[i][2]][0]);
+    glVertex3fv(&v[faces[i][3]][0]);
+    glEnd();
+  }
+}
+
+
+
+/* Render a scene */
+static void
+Render(void)
+{
+   int NumBoxes = 100;
+   int i;
+
+   glClearColor(0.2, 0.2, 0.9, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   for (i=0;i<NumBoxes;i++) {
+      float tx = -2.0 + 4.0 * Random();
+      float ty = -2.0 + 4.0 * Random();
+      float tz =  4.0 - 16.0 * Random();
+      float sx = 0.1 + Random() * 0.4;
+      float sy = 0.1 + Random() * 0.4;
+      float sz = 0.1 + Random() * 0.4;
+      float rx = Random();
+      float ry = Random();
+      float rz = Random();
+      float ra = Random() * 360.0;
+      glPushMatrix();
+      glTranslatef(tx, ty, tz);
+      glRotatef(ra, rx, ry, rz);
+      glScalef(sx, sy, sz);
+      RandomColor();
+      drawBox(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, GL_POLYGON);
+      glPopMatrix();
+   }
+
+   glFinish();
+}
+
+
+
+static void
+WriteFile(const char *filename)
+{
+   FILE *f;
+   GLubyte *image;
+   int i;
+
+   image = malloc(gWidth * gHeight * 3 * sizeof(GLubyte));
+   if (!image) {
+      printf("Error: couldn't allocate image buffer\n");
+      return;
+   }
+
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+   glReadPixels(0, 0, gWidth, gHeight, GL_RGB, GL_UNSIGNED_BYTE, image);
+
+   f = fopen(filename, "w");
+   if (!f) {
+      printf("Couldn't open image file: %s\n", filename);
+      return;
+   }
+   fprintf(f,"P6\n");
+   fprintf(f,"# ppm-file created by %s\n", "trdemo2");
+   fprintf(f,"%i %i\n", gWidth, gHeight);
+   fprintf(f,"255\n");
+   fclose(f);
+   f = fopen(filename, "ab");  /* now append binary data */
+   if (!f) {
+      printf("Couldn't append to image file: %s\n", filename);
+      return;
+   }
+
+   for (i=0;i<gHeight;i++) {
+      GLubyte *rowPtr;
+      /* Remember, OpenGL images are bottom to top.  Have to reverse. */
+      rowPtr = image + (gHeight-1-i) * gWidth*3;
+      fwrite(rowPtr, 1, gWidth*3, f);
+   }
+
+   fclose(f);
+   free(image);
+
+   printf("Wrote %d by %d image file: %s\n", gWidth, gHeight, filename);
+}
+
+
+
+/*
+ * Print message describing command line parameters.
+ */
+static void
+Usage(const char *appName)
+{
+   printf("Usage:\n");
+   printf("  %s width height imgfile\n", appName);
+   printf("Where imgfile is a ppm file\n");
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+   if (argc!=4) {
+      Usage(argv[0]);
+   }
+   else {
+      int width = atoi(argv[1]);
+      int height = atoi(argv[2]);
+      char *fileName = argv[3];
+      if (width<=0) {
+         printf("Error: width parameter must be at least 1.\n");
+         return 1;
+      }
+      if (height<=0) {
+         printf("Error: height parameter must be at least 1.\n");
+         return 1;
+      }
+      if (!Setup(width, height)) {
+         return 1;
+      }
+      InitGL();
+      Render();
+      WriteFile(fileName);
+      DestroyPbuffer(gDpy, gScreen, gPBuffer);
+   }
+   return 0;
+}
+
diff -Naurp Mesa-7.8.1/progs/xdemos/pbinfo.c Mesa-7.8.1.patched/progs/xdemos/pbinfo.c
--- Mesa-7.8.1/progs/xdemos/pbinfo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/pbinfo.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,107 @@
+
+/*
+ * Print list of fbconfigs and test each to see if a pbuffer can be created
+ * for that config.
+ *
+ * Brian Paul
+ * April 1997
+ * Updated on 5 October 2002.
+ */
+
+
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "pbutil.h"
+
+
+
+
+static void
+PrintConfigs(Display *dpy, int screen, Bool horizFormat)
+{
+   FBCONFIG *fbConfigs;
+   int nConfigs;
+   int i;
+
+   fbConfigs = GetAllFBConfigs(dpy, screen, &nConfigs);
+   if (!nConfigs || !fbConfigs) {
+      printf("Error: glxGetFBConfigs failed\n");
+      XFree(fbConfigs);
+      return;
+   }
+
+   printf("Number of fbconfigs: %d\n", nConfigs);
+
+   if (horizFormat) {
+      printf("  ID        VisualType  Depth Lvl RGB CI DB Stereo  R  G  B  A");
+      printf("   Z  S  AR AG AB AA  MSbufs MSnum  Pbuffer  Float\n");
+   }
+
+   /* Print config info */
+   for (i = 0; i < nConfigs; i++) {
+      PrintFBConfigInfo(dpy, screen, fbConfigs[i], horizFormat);
+   }
+
+   /* free the list */
+   XFree(fbConfigs);
+}
+
+
+
+static void
+PrintUsage(void)
+{
+   printf("Options:\n");
+   printf("  -display <display-name>  specify X display name\n");
+   printf("  -t                       print in tabular format\n");
+   printf("  -v                       print in verbose format\n");
+   printf("  -help                    print this information\n");
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   int scrn;
+   char *dpyName = NULL;
+   Bool horizFormat = True;
+   int i;
+
+   for (i=1; i<argc; i++) {
+      if (strcmp(argv[i],"-display")==0) {
+	 if (i+1<argc) {
+	    dpyName = argv[i+1];
+	    i++;
+	 }
+      }
+      else if (strcmp(argv[i],"-t")==0) {
+	 /* tabular format */
+	 horizFormat = True;
+      }
+      else if (strcmp(argv[i],"-v")==0) {
+	 /* verbose format */
+	 horizFormat = False;
+      }
+      else if (strcmp(argv[i],"-help")==0) {
+	 PrintUsage();
+	 return 0;
+      }
+      else {
+	 printf("Unknown option: %s\n", argv[i]);
+      }
+   }
+
+   dpy = XOpenDisplay(dpyName);
+
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
+      return 1;
+   }
+
+   scrn = DefaultScreen(dpy);
+   PrintConfigs(dpy, scrn, horizFormat);
+   XCloseDisplay(dpy);
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/pbutil.c Mesa-7.8.1.patched/progs/xdemos/pbutil.c
--- Mesa-7.8.1/progs/xdemos/pbutil.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/pbutil.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,446 @@
+
+/*
+ * OpenGL pbuffers utility functions.
+ *
+ * Brian Paul
+ * Original code: April 1997
+ * Updated on 5 October 2002
+ * Updated again on 3 January 2005 to use GLX 1.3 functions in preference
+ * to the GLX_SGIX_fbconfig/pbuffer extensions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "pbutil.h"
+
+
+/**
+ * Test if we pixel buffers are available for a particular X screen.
+ * Input:  dpy - the X display
+ *         screen - screen number
+ * Return:  0 = fbconfigs not available.
+ *          1 = fbconfigs are available via GLX 1.3.
+ *          2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig
+ */
+int
+QueryFBConfig(Display *dpy, int screen)
+{
+#if defined(GLX_VERSION_1_3)
+   {
+      /* GLX 1.3 supports pbuffers */
+      int glxVersionMajor, glxVersionMinor;
+      if (!glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)) {
+         /* GLX not available! */
+         return 0;
+      }
+      if (glxVersionMajor * 100 + glxVersionMinor >= 103) {
+         return 1;
+      }
+      /* fall-through */
+   }
+#endif
+
+   /* Try the SGIX extensions */
+   {
+      char *extensions;
+      extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
+      if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) {
+	 return 2;
+      }
+   }
+
+   return 0;
+}
+
+/**
+ * Test if we pixel buffers are available for a particular X screen.
+ * Input:  dpy - the X display
+ *         screen - screen number
+ * Return:  0 = pixel buffers not available.
+ *          1 = pixel buffers are available via GLX 1.3.
+ *          2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
+ */
+int
+QueryPbuffers(Display *dpy, int screen)
+{
+   int ret;
+
+   ret = QueryFBConfig(dpy, screen);
+   if (ret == 2) {
+      char *extensions;
+      extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
+      if (extensions && strstr(extensions, "GLX_SGIX_pbuffer"))
+	 return 2;
+      else
+	 return 0;
+   }
+   else
+      return ret;
+}
+
+FBCONFIG *
+ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
+{
+   int fbcSupport = QueryPbuffers(dpy, screen);
+#if defined(GLX_VERSION_1_3)
+   if (fbcSupport == 1) {
+      return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
+   }
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (fbcSupport == 2) {
+      return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
+   }
+#endif
+   return NULL;
+}
+
+
+FBCONFIG *
+GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
+{
+   int fbcSupport = QueryFBConfig(dpy, screen);
+#if defined(GLX_VERSION_1_3)
+   if (fbcSupport == 1) {
+      return glXGetFBConfigs(dpy, screen, nConfigs);
+   }
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (fbcSupport == 2) {
+      /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
+       * of all available configurations.
+       */
+      return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs);
+   }
+#endif
+   return NULL;
+}
+
+
+XVisualInfo *
+GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
+{
+   int fbcSupport = QueryFBConfig(dpy, screen);
+#if defined(GLX_VERSION_1_3)
+   if (fbcSupport == 1) {
+      return glXGetVisualFromFBConfig(dpy, config);
+   }
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (fbcSupport == 2) {
+      return glXGetVisualFromFBConfigSGIX(dpy, config);
+   }
+#endif
+   return NULL;
+}
+
+
+/**
+ * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
+ * to query an fbconfig attribute.
+ */
+static int
+GetFBConfigAttrib(Display *dpy, int screen,
+#if defined(GLX_VERSION_1_3)
+                  const GLXFBConfig config,
+#elif defined(GLX_SGIX_fbconfig)
+                  const GLXFBConfigSGIX config,
+#endif
+                  int attrib
+                  )
+{
+   int fbcSupport = QueryFBConfig(dpy, screen);
+   int value = 0;
+
+#if defined(GLX_VERSION_1_3)
+   if (fbcSupport == 1) {
+      /* ok */
+      if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
+         value = 0;
+      }
+      return value;
+   }
+   /* fall-through */
+#endif
+
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (fbcSupport == 2) {
+      if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
+         value = 0;
+      }
+      return value;
+   }
+#endif
+   
+   return value;
+}
+
+
+
+/**
+ * Print parameters for a GLXFBConfig to stdout.
+ * Input:  dpy - the X display
+ *         screen - the X screen number
+ *         fbConfig - the fbconfig handle
+ *         horizFormat - if true, print in horizontal format
+ */
+void
+PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
+{
+   PBUFFER pBuffer;
+   int width=2, height=2;
+   int bufferSize, level, doubleBuffer, stereo, auxBuffers;
+   int redSize, greenSize, blueSize, alphaSize;
+   int depthSize, stencilSize;
+   int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
+   int sampleBuffers, samples;
+   int drawableType, renderType, xRenderable, xVisual, id;
+   int maxWidth, maxHeight, maxPixels;
+   int optWidth, optHeight;
+   int floatComponents = 0;
+
+   /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
+   bufferSize     = GetFBConfigAttrib(dpy, screen, config, GLX_BUFFER_SIZE);
+   level          = GetFBConfigAttrib(dpy, screen, config, GLX_LEVEL);
+   doubleBuffer   = GetFBConfigAttrib(dpy, screen, config, GLX_DOUBLEBUFFER);
+   stereo         = GetFBConfigAttrib(dpy, screen, config, GLX_STEREO);
+   auxBuffers     = GetFBConfigAttrib(dpy, screen, config, GLX_AUX_BUFFERS);
+   redSize        = GetFBConfigAttrib(dpy, screen, config, GLX_RED_SIZE);
+   greenSize      = GetFBConfigAttrib(dpy, screen, config, GLX_GREEN_SIZE);
+   blueSize       = GetFBConfigAttrib(dpy, screen, config, GLX_BLUE_SIZE);
+   alphaSize      = GetFBConfigAttrib(dpy, screen, config, GLX_ALPHA_SIZE);
+   depthSize      = GetFBConfigAttrib(dpy, screen, config, GLX_DEPTH_SIZE);
+   stencilSize    = GetFBConfigAttrib(dpy, screen, config, GLX_STENCIL_SIZE);
+   accumRedSize   = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_RED_SIZE);
+   accumGreenSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_GREEN_SIZE);
+   accumBlueSize  = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_BLUE_SIZE);
+   accumAlphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_ALPHA_SIZE);
+   sampleBuffers  = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLE_BUFFERS);
+   samples        = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLES);
+   drawableType   = GetFBConfigAttrib(dpy, screen, config, GLX_DRAWABLE_TYPE);
+   renderType     = GetFBConfigAttrib(dpy, screen, config, GLX_RENDER_TYPE);
+   xRenderable    = GetFBConfigAttrib(dpy, screen, config, GLX_X_RENDERABLE);
+   xVisual        = GetFBConfigAttrib(dpy, screen, config, GLX_X_VISUAL_TYPE);
+   if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
+      xVisual = -1;
+
+   id        = GetFBConfigAttrib(dpy, screen, config, GLX_FBCONFIG_ID);
+   maxWidth  = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_WIDTH);
+   maxHeight = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_HEIGHT);
+   maxPixels = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_PIXELS);
+#if defined(GLX_SGIX_pbuffer)
+   optWidth  = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX);
+   optHeight = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX);
+#else
+   optWidth = optHeight = 0;
+#endif
+#if defined(GLX_NV_float_buffer)
+   floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV);
+#endif
+
+   /* See if we can create a pbuffer with this config */
+   pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
+
+   if (horizFormat) {
+      printf("0x%-9x ", id);
+      if (xVisual==GLX_STATIC_GRAY)        printf("StaticGray  ");
+      else if (xVisual==GLX_GRAY_SCALE)    printf("GrayScale   ");
+      else if (xVisual==GLX_STATIC_COLOR)  printf("StaticColor ");
+      else if (xVisual==GLX_PSEUDO_COLOR)  printf("PseudoColor ");
+      else if (xVisual==GLX_TRUE_COLOR)    printf("TrueColor   ");
+      else if (xVisual==GLX_DIRECT_COLOR)  printf("DirectColor ");
+      else                            printf("  -none-    ");
+      printf(" %3d %3d   %s   %s  %s   %2s   ", bufferSize, level,
+	     (renderType & GLX_RGBA_BIT_SGIX) ? "y" : ".",
+	     (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : ".",
+	     doubleBuffer ? "y" : ".",
+	     stereo ? "y" : ".");
+      printf("%2d %2d %2d %2d  ", redSize, greenSize, blueSize, alphaSize);
+      printf("%2d %2d  ", depthSize, stencilSize);
+      printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize,
+	     accumAlphaSize);
+      printf("    %2d    %2d", sampleBuffers, samples);
+      printf("       %s       %c", pBuffer ? "y" : ".",
+             ".y"[floatComponents]);
+      printf("\n");
+   }
+   else {
+      printf("Id 0x%x\n", id);
+      printf("  Buffer Size: %d\n", bufferSize);
+      printf("  Level: %d\n", level);
+      printf("  Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
+      printf("  Stereo: %s\n", stereo ? "yes" : "no");
+      printf("  Aux Buffers: %d\n", auxBuffers);
+      printf("  Red Size: %d\n", redSize);
+      printf("  Green Size: %d\n", greenSize);
+      printf("  Blue Size: %d\n", blueSize);
+      printf("  Alpha Size: %d\n", alphaSize);
+      printf("  Depth Size: %d\n", depthSize);
+      printf("  Stencil Size: %d\n", stencilSize);
+      printf("  Accum Red Size: %d\n", accumRedSize);
+      printf("  Accum Green Size: %d\n", accumGreenSize);
+      printf("  Accum Blue Size: %d\n", accumBlueSize);
+      printf("  Accum Alpha Size: %d\n", accumAlphaSize);
+      printf("  Sample Buffers: %d\n", sampleBuffers);
+      printf("  Samples/Pixel: %d\n", samples);
+      printf("  Drawable Types: ");
+      if (drawableType & GLX_WINDOW_BIT)  printf("Window ");
+      if (drawableType & GLX_PIXMAP_BIT)  printf("Pixmap ");
+      if (drawableType & GLX_PBUFFER_BIT)  printf("PBuffer");
+      printf("\n");
+      printf("  Render Types: ");
+      if (renderType & GLX_RGBA_BIT_SGIX)  printf("RGBA ");
+      if (renderType & GLX_COLOR_INDEX_BIT_SGIX)  printf("CI ");
+      printf("\n");
+      printf("  X Renderable: %s\n", xRenderable ? "yes" : "no");
+
+      printf("  Pbuffer: %s\n", pBuffer ? "yes" : "no");
+      printf("  Max Pbuffer width: %d\n", maxWidth);
+      printf("  Max Pbuffer height: %d\n", maxHeight);
+      printf("  Max Pbuffer pixels: %d\n", maxPixels);
+      printf("  Optimum Pbuffer width: %d\n", optWidth);
+      printf("  Optimum Pbuffer height: %d\n", optHeight);
+
+      printf("  Float Components: %s\n", floatComponents ? "yes" : "no");
+   }
+
+   if (pBuffer) {
+      DestroyPbuffer(dpy, screen, pBuffer);
+   }
+}
+
+
+
+GLXContext
+CreateContext(Display *dpy, int screen, FBCONFIG config)
+{
+   int fbcSupport = QueryFBConfig(dpy, screen);
+#if defined(GLX_VERSION_1_3)
+   if (fbcSupport == 1) {
+      /* GLX 1.3 */
+      GLXContext c;
+      c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True);
+      if (!c) {
+         /* try indirect */
+         c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, False);
+      }
+      return c;
+   }
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (fbcSupport == 2) {
+      GLXContext c;
+      c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);
+      if (!c) {
+         c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, False);
+      }
+      return c;
+   }
+#endif
+   return 0;
+}
+
+
+void
+DestroyContext(Display *dpy, GLXContext ctx)
+{
+   glXDestroyContext(dpy, ctx);
+}
+
+
+/* This is only used by CreatePbuffer() */
+static int XErrorFlag = 0;
+static int HandleXError(Display *dpy, XErrorEvent *event)
+{
+    XErrorFlag = 1;
+    return 0;
+}
+
+
+/**
+ * Create a Pbuffer.  Use an X error handler to deal with potential
+ * BadAlloc errors.
+ *
+ * Input:  dpy - the X display
+ *         fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
+ *         width, height - size of pixel buffer to request, in pixels.
+ *         pbAttribs - list of optional pixel buffer attributes
+ * Return:  a Pbuffer or None.
+ */
+PBUFFER
+CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
+              int width, int height, Bool largest, Bool preserve)
+{
+   int (*oldHandler)(Display *, XErrorEvent *);
+   PBUFFER pBuffer = None;
+   int pbSupport = QueryPbuffers(dpy, screen);
+
+   /* Catch X protocol errors with our own error handler */
+   oldHandler = XSetErrorHandler(HandleXError);
+   XErrorFlag = 0;
+
+#if defined(GLX_VERSION_1_3)
+   if (pbSupport == 1) {
+      /* GLX 1.3 */
+      int attribs[100], i = 0;
+      attribs[i++] = GLX_PBUFFER_WIDTH;
+      attribs[i++] = width;
+      attribs[i++] = GLX_PBUFFER_HEIGHT;
+      attribs[i++] = height;
+      attribs[i++] = GLX_PRESERVED_CONTENTS;
+      attribs[i++] = preserve;
+      attribs[i++] = GLX_LARGEST_PBUFFER;
+      attribs[i++] = largest;
+      attribs[i++] = 0;
+      pBuffer = glXCreatePbuffer(dpy, config, attribs);
+   }
+   else
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (pbSupport == 2) {
+      int attribs[100], i = 0;
+      attribs[i++] = GLX_PRESERVED_CONTENTS;
+      attribs[i++] = preserve;
+      attribs[i++] = GLX_LARGEST_PBUFFER;
+      attribs[i++] = largest;
+      attribs[i++] = 0;
+      pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
+   }
+   else
+#endif
+   {
+      pBuffer = None;
+   }
+
+   XSync(dpy, False);
+   /* Restore original X error handler */
+   (void) XSetErrorHandler(oldHandler);
+
+   /* Return pbuffer (may be None) */
+   if (!XErrorFlag && pBuffer != None) {
+      /*printf("config %d worked!\n", i);*/
+      return pBuffer;
+   }
+   else {
+      return None;
+   }
+}
+
+
+void
+DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
+{
+   int pbSupport = QueryPbuffers(dpy, screen);
+#if defined(GLX_VERSION_1_3)
+   if (pbSupport == 1) {
+      glXDestroyPbuffer(dpy, pbuffer);
+      return;
+   }
+#endif
+#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+   if (pbSupport == 2) {
+      glXDestroyGLXPbufferSGIX(dpy, pbuffer);
+      return;
+   }
+#endif
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/pbutil.h Mesa-7.8.1.patched/progs/xdemos/pbutil.h
--- Mesa-7.8.1/progs/xdemos/pbutil.h	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/pbutil.h	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,69 @@
+/*
+ * OpenGL pbuffers utility functions.
+ *
+ * Brian Paul
+ * April 1997
+ */
+
+
+#ifndef PBUTIL_H
+#define PBUTIL_H
+
+
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+
+
+#if defined(GLX_VERSION_1_3)
+#define PBUFFER GLXPbuffer
+#define FBCONFIG GLXFBConfig
+#elif defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
+#define PBUFFER GLXPbufferSGIX
+#define FBCONFIG GLXFBConfigSGIX
+#else
+#define PBUFFER int
+#define FBCONFIG int
+#endif
+
+
+extern int
+QueryFBConfig(Display *dpy, int screen);
+
+extern int
+QueryPbuffers(Display *dpy, int screen);
+
+
+extern void
+PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat);
+
+
+extern FBCONFIG *
+ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs);
+
+
+extern FBCONFIG *
+GetAllFBConfigs(Display *dpy, int screen, int *nConfigs);
+
+
+extern XVisualInfo *
+GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config);
+
+
+extern GLXContext
+CreateContext(Display *dpy, int screen, FBCONFIG config);
+
+
+extern void
+DestroyContext(Display *dpy, GLXContext ctx);
+
+
+extern PBUFFER
+CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
+	      int width, int height, Bool preserve, Bool largest);
+
+
+extern void
+DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer);
+
+
+#endif  /*PBUTIL_H*/
diff -Naurp Mesa-7.8.1/progs/xdemos/shape.c Mesa-7.8.1.patched/progs/xdemos/shape.c
--- Mesa-7.8.1/progs/xdemos/shape.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/shape.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,393 @@
+
+/*
+ * Example of using the X "shape" extension with OpenGL:  render a spinning
+ * cube inside of a non-rectangular window.
+ *
+ * Press ESC to exit.  Press up/down to change window shape.
+ *
+ * To compile add "shape" to the PROGS list in Makefile.
+ *
+ * Brian Paul
+ * June 16, 1997
+ *
+ * This program is in the public domain.
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/extensions/shape.h>
+#include <GL/glx.h>
+
+#ifndef PI
+#define PI 3.1415926
+#endif
+
+
+static int Width=500, Height=500;
+
+static float Xangle = 0.0, Yangle = 0.0;
+static int Sides = 5;
+static int MinSides = 3;
+static int MaxSides = 20;
+
+
+/* return current time (in seconds) */
+static double
+current_time(void)
+{
+   struct timeval tv;
+#ifdef __VMS
+   (void) gettimeofday(&tv, NULL );
+#else
+   struct timezone tz;
+   (void) gettimeofday(&tv, &tz);
+#endif
+   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+
+/*
+ * Draw the OpenGL stuff and do a SwapBuffers.
+ */
+static void display(Display *dpy, Window win)
+{
+   float scale = 1.7;
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+
+   glScalef(scale, scale, scale);
+   glRotatef(Xangle, 1.0, 0.0, 0.0);
+   glRotatef(Yangle, 0.0, 1.0, 0.0);
+
+   /*
+    * wireframe box
+    */
+   glColor3f(1.0, 1.0, 1.0);
+   glBegin(GL_LINE_LOOP);
+   glVertex3f(-1.0, -1.0, -1.0);
+   glVertex3f( 1.0, -1.0, -1.0);
+   glVertex3f( 1.0,  1.0, -1.0);
+   glVertex3f(-1.0,  1.0, -1.0);
+   glEnd();
+
+   glBegin(GL_LINE_LOOP);
+   glVertex3f(-1.0, -1.0, 1.0);
+   glVertex3f( 1.0, -1.0, 1.0);
+   glVertex3f( 1.0,  1.0, 1.0);
+   glVertex3f(-1.0,  1.0, 1.0);
+   glEnd();
+
+   glBegin(GL_LINES);
+   glVertex3f(-1.0, -1.0, -1.0);   glVertex3f(-1.0, -1.0, 1.0);
+   glVertex3f( 1.0, -1.0, -1.0);   glVertex3f( 1.0, -1.0, 1.0);
+   glVertex3f( 1.0,  1.0, -1.0);   glVertex3f( 1.0,  1.0, 1.0);
+   glVertex3f(-1.0,  1.0, -1.0);   glVertex3f(-1.0,  1.0, 1.0);
+   glEnd();
+
+   /*
+    * Solid box
+    */
+   glPushMatrix();
+   glScalef(0.75, 0.75, 0.75);
+
+   glColor3f(1, 0, 0);
+   glBegin(GL_POLYGON);
+   glVertex3f(1, -1, -1);
+   glVertex3f(1,  1, -1);
+   glVertex3f(1,  1,  1);
+   glVertex3f(1, -1,  1);
+   glEnd();
+
+   glColor3f(0, 1, 1);
+   glBegin(GL_POLYGON);
+   glVertex3f(-1, -1, -1);
+   glVertex3f(-1,  1, -1);
+   glVertex3f(-1,  1,  1);
+   glVertex3f(-1, -1,  1);
+   glEnd();
+
+   glColor3f(0, 1, 0);
+   glBegin(GL_POLYGON);
+   glVertex3f(-1, 1, -1);
+   glVertex3f( 1, 1, -1);
+   glVertex3f( 1, 1,  1);
+   glVertex3f(-1, 1,  1);
+   glEnd();
+
+   glColor3f(1, 0, 1);
+   glBegin(GL_POLYGON);
+   glVertex3f(-1, -1, -1);
+   glVertex3f( 1, -1, -1);
+   glVertex3f( 1, -1,  1);
+   glVertex3f(-1, -1,  1);
+   glEnd();
+
+   glColor3f(0, 0, 1);
+   glBegin(GL_POLYGON);
+   glVertex3f(-1, -1, 1);
+   glVertex3f( 1, -1, 1);
+   glVertex3f( 1,  1, 1);
+   glVertex3f(-1,  1, 1);
+   glEnd();
+
+   glColor3f(1, 1, 0);
+   glBegin(GL_POLYGON);
+   glVertex3f(-1, -1, -1);
+   glVertex3f( 1, -1, -1);
+   glVertex3f( 1,  1, -1);
+   glVertex3f(-1,  1, -1);
+   glEnd();
+   glPopMatrix();
+
+
+   glPopMatrix();
+
+   glXSwapBuffers(dpy, win);
+}
+
+
+/*
+ * This is called when we have to recompute the window shape bitmask.
+ * We just generate an n-sided regular polygon here but any other shape
+ * would be possible.
+ */
+static void make_shape_mask(Display *dpy, Window win, int width, int height,
+                            int sides)
+{
+   Pixmap shapeMask;
+   XGCValues xgcv;
+   GC gc;
+
+   /* allocate 1-bit deep pixmap and a GC */
+   shapeMask = XCreatePixmap(dpy, win, width, height, 1);
+   gc = XCreateGC(dpy, shapeMask, 0, &xgcv);
+
+   /* clear shapeMask to zeros */
+   XSetForeground(dpy, gc, 0);
+   XFillRectangle(dpy, shapeMask, gc, 0, 0, width, height);
+
+   /* draw mask */
+   XSetForeground(dpy, gc, 1);
+   {
+      int cx = width / 2;
+      int cy = height / 2;
+      float angle = 0.0;
+      float step = 2.0 * PI / sides;
+      float radius = width / 2;
+      int i;
+      XPoint points[100];
+      for (i=0;i<sides;i++) {
+         int x = cx + radius * sin(angle);
+         int y = cy - radius * cos(angle);
+         points[i].x = x;
+         points[i].y = y;
+         angle += step;
+      }
+      XFillPolygon(dpy, shapeMask, gc, points, sides, Convex, CoordModeOrigin);
+   }
+
+   /* This is the only SHAPE extension call- simple! */
+   XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shapeMask, ShapeSet);
+
+   XFreeGC(dpy, gc);
+   XFreePixmap(dpy, shapeMask);
+}
+
+
+/*
+ * Called when window is resized.  Do OpenGL viewport and projection stuff.
+ */
+static void reshape(int width, int height)
+{
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -10.0);
+
+   glEnable(GL_DEPTH_TEST);
+}
+
+
+/*
+ * Process X events.
+ */
+static void event_loop(Display *dpy, Window win)
+{
+   while (1) {
+      XEvent event;
+      if (XPending(dpy)) {
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+            case Expose:
+               display(dpy, event.xexpose.window);
+               break;
+            case ConfigureNotify:
+               Width = event.xconfigure.width;
+               Height = event.xconfigure.height,
+               make_shape_mask(dpy, win, Width, Height, Sides);
+               reshape(Width, Height);
+               break;
+            case KeyPress:
+               {
+                  char buf[100];
+                  KeySym keySym;
+                  XComposeStatus stat;
+                  XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+                  switch (keySym) {
+                     case XK_Escape:
+                        exit(0);
+                        break;
+                     case XK_Up:
+                        Sides++;
+                        if (Sides>MaxSides) Sides = MaxSides;
+                        make_shape_mask(dpy, win, Width, Height, Sides);
+                        break;
+                     case XK_Down:
+                        Sides--;
+                        if (Sides<MinSides) Sides = MinSides;
+                        make_shape_mask(dpy, win, Width, Height, Sides);
+                        break;
+                  }
+               }
+               break;
+            default:
+               ;;
+         }
+      }
+      else {
+         static double t0 = -1.0;
+         double dt, t = current_time();
+         if (t0 < 0.0)
+            t0 = t;
+         dt = t - t0;
+         Xangle += 90.0 * dt;  /* 90 degrees per second */
+         Yangle += 70.0 * dt;
+         t0 = t;
+         display(dpy, win);
+      }
+   }
+}
+
+
+/*
+ * Allocate a "nice" colormap.  This could be better (HP-CR support, etc).
+ */
+static Colormap alloc_colormap(Display *dpy, Window parent, Visual *vis)
+{
+   Screen *scr = DefaultScreenOfDisplay(dpy);
+   int scrnum = DefaultScreen(dpy);
+
+   if (MaxCmapsOfScreen(scr)==1 && vis==DefaultVisual(dpy, scrnum)) {
+      /* The window and root are of the same visual type so */
+      /* share the root colormap. */
+      return DefaultColormap(dpy, scrnum);
+   }
+   else {
+      return XCreateColormap(dpy, parent, vis, AllocNone);
+   }
+}
+
+
+int main(int argc, char *argv[])
+{
+   static int glAttribs[] = {
+      GLX_DOUBLEBUFFER,
+      GLX_RGBA,
+      GLX_DEPTH_SIZE, 1,
+      None
+   };
+   Display *dpy;
+   XVisualInfo *visInfo;
+   int scrn;
+   Window root;
+   Colormap cmap;
+   Window win;
+   XSetWindowAttributes winAttribs;
+   unsigned long winAttribsMask;
+   GLXContext glCtx;
+   int ignore;
+   const char *name = "OpenGL in a Shaped Window";
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy) {
+      fprintf(stderr, "Couldn't open default display\n");
+      return 1;
+   }
+
+   /* check that we can use the shape extension */
+   if (!XQueryExtension(dpy, "SHAPE", &ignore, &ignore, &ignore )) {
+      fprintf(stderr, "Display doesn't support shape extension\n");
+      return 1;
+   }
+
+   scrn = DefaultScreen(dpy);
+
+   root = RootWindow(dpy, scrn);
+
+   visInfo = glXChooseVisual(dpy, scrn, glAttribs);
+   if (!visInfo) {
+      fprintf(stderr, "Couldn't get RGB, DB, Z visual\n");
+      return 1;
+   }
+
+   glCtx = glXCreateContext(dpy, visInfo, 0, True);
+   if (!glCtx) {
+      fprintf(stderr, "Couldn't create GL context\n");
+      return 1;
+   }
+
+   cmap = alloc_colormap(dpy, root, visInfo->visual);
+   if (!cmap) {
+      fprintf(stderr, "Couln't create colormap\n");
+      return 1;
+   }
+
+   winAttribs.border_pixel = 0;
+   winAttribs.colormap = cmap;
+   winAttribs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   winAttribsMask = CWBorderPixel | CWColormap | CWEventMask;
+   win = XCreateWindow(dpy, root, 0, 0, Width, Height, 0,
+                       visInfo->depth, InputOutput,
+                       visInfo->visual,
+                       winAttribsMask, &winAttribs);
+
+   {
+      XSizeHints sizehints;
+      /*
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      */
+      sizehints.flags = 0;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   XMapWindow(dpy, win);
+
+   glXMakeCurrent(dpy, win, glCtx);
+
+   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+   printf("Press ESC to exit.\n");
+   printf("Press up/down to change window shape.\n");
+
+   event_loop(dpy, win);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex.c Mesa-7.8.1.patched/progs/xdemos/sharedtex.c
--- Mesa-7.8.1/progs/xdemos/sharedtex.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/sharedtex.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,324 @@
+/*
+ * Test sharing of texture objects by two rendering contexts.
+ * In particular, test that changing a texture object in one context
+ * effects the texture in the second context.
+ *
+ * Brian Paul
+ * 30 Apr 2008
+ *
+ * Copyright (C) 2008  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/keysym.h>
+
+
+#define MAX_CONTEXTS 2
+
+#define TEX_SIZE 32
+
+static const char *DisplayName = NULL;
+static Display *Dpy;
+static XVisualInfo *VisInfo;
+static Window Win;
+static GLXContext Contexts[MAX_CONTEXTS];
+static int WinWidth = 300, WinHeight = 300;
+
+static int DrawContext = 0, TexContext = 1;
+
+static GLuint TexObj = 0;
+static GLboolean NewTexture = GL_FALSE;
+
+
+static void
+Error(const char *msg)
+{
+   fprintf(stderr, "sharedtex error: %s\n", msg);
+   exit(1);
+}
+
+
+static void
+CreateWindow(const char *name)
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   int xpos = 0, ypos = 0;
+   static int n = 0;
+
+   scrnum = DefaultScreen(Dpy);
+   root = RootWindow(Dpy, scrnum);
+
+   VisInfo = glXChooseVisual(Dpy, scrnum, attrib);
+   if (!VisInfo) {
+      Error("Unable to find RGB, double-buffered visual");
+   }
+
+   /* window attributes */
+   xpos = (n % 10) * 100;
+   ypos = (n / 10) * 100;
+   n++;
+
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(Dpy, root, VisInfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   Win = XCreateWindow(Dpy, root, xpos, ypos, WinWidth, WinHeight,
+		        0, VisInfo->depth, InputOutput,
+		        VisInfo->visual, mask, &attr);
+   if (!Win) {
+      Error("Couldn't create window");
+   }
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = WinWidth;
+      sizehints.height = WinHeight;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(Dpy, Win, &sizehints);
+      XSetStandardProperties(Dpy, Win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   XMapWindow(Dpy, Win);
+}
+
+
+/**
+ * Change texture image, using TexContext
+ */
+static void
+ModifyTexture(void)
+{
+   GLuint tex[TEX_SIZE][TEX_SIZE];
+   GLuint c0, c1;
+   int i, j;
+
+   if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) {
+      Error("glXMakeCurrent failed");
+   }
+
+   /* choose two random colors */
+   c0 = rand() & 0xffffffff;
+   c1 = rand() & 0xffffffff;
+
+   for (i = 0; i < TEX_SIZE; i++) {
+      for (j = 0; j < TEX_SIZE; j++) {
+         if (((i / 4) ^ (j / 4)) & 1) {
+            tex[i][j] = c0;
+         }
+         else {
+            tex[i][j] = c1;
+         }
+      }
+   }
+
+   glBindTexture(GL_TEXTURE_2D, TexObj);
+   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, tex);
+
+   NewTexture = GL_TRUE;
+}
+
+
+static void
+InitContext(void)
+{
+   glGenTextures(1, &TexObj);
+   assert(TexObj);
+   glBindTexture(GL_TEXTURE_2D, TexObj);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+   glEnable(GL_TEXTURE_2D);
+
+   printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER));
+}
+
+
+static void
+Setup(void)
+{
+   int i;
+
+   Dpy = XOpenDisplay(DisplayName);
+   if (!Dpy) {
+      Error("Unable to open display");
+   }
+
+   CreateWindow("sharedtex");
+
+   for (i = 0; i < MAX_CONTEXTS; i++) {
+      GLXContext share = i > 0 ? Contexts[0] : 0;
+
+      Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True);
+      if (!Contexts[i]) {
+         Error("Unable to create GLX context");
+      }
+
+      if (!glXMakeCurrent(Dpy, Win, Contexts[i])) {
+         Error("glXMakeCurrent failed");
+      }
+
+      InitContext();
+   }
+
+   ModifyTexture();
+}
+
+
+/**
+ * Redraw window, using DrawContext
+ */
+static void
+Redraw(void)
+{
+   static float rot = 0.0;
+   float ar;
+
+   rot += 1.0;
+
+   if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) {
+      Error("glXMakeCurrent failed");
+   }
+
+   glViewport(0, 0, WinWidth, WinHeight);
+   ar = (float) WinWidth / (float) WinHeight;
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   glPushMatrix();
+   glRotatef(rot, 0, 0, 1);
+   glScalef(0.7, 0.7, 0.7);
+
+   if (NewTexture) {
+      /* rebind to get new contents */
+      glBindTexture(GL_TEXTURE_2D, TexObj);
+      NewTexture = GL_FALSE;
+   }
+
+   /* draw textured quad */
+   glBegin(GL_POLYGON);
+   glTexCoord2f( 0.0, 0.0 );   glVertex2f( -1.0, -1.0 );
+   glTexCoord2f( 1.0, 0.0 );   glVertex2f(  1.0, -1.0 );
+   glTexCoord2f( 1.0, 1.0 );   glVertex2f(  1.0,  1.0 );
+   glTexCoord2f( 0.0, 1.0 );   glVertex2f( -1.0,  1.0 );
+   glEnd();
+
+   glPopMatrix();
+
+   if (Win)
+      glXSwapBuffers(Dpy, Win);
+}
+
+
+static void
+EventLoop(void)
+{
+   while (1) {
+      while (XPending(Dpy) > 0) {
+         XEvent event;
+         XNextEvent(Dpy, &event);
+
+         switch (event.type) {
+         case Expose:
+            Redraw();
+            break;
+         case ConfigureNotify:
+            WinWidth = event.xconfigure.width;
+            WinHeight = event.xconfigure.height;
+            break;
+         case KeyPress:
+            {
+               char buf[100];
+               KeySym keySym;
+               XComposeStatus stat;
+               XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+               switch (keySym) {
+               case XK_Escape:
+                  exit(0);
+                  break;
+               case XK_t:
+               case XK_T:
+                  ModifyTexture();
+                  break;
+               default:
+                  ;
+               }
+            }
+            Redraw();
+            break;
+         default:
+            /*no-op*/ ;
+         }
+      }
+
+      Redraw();
+      usleep(10000);
+   }
+}
+
+
+
+
+int
+main(int argc, char *argv[])
+{
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0 && i < argc) {
+         DisplayName = argv[i+1];
+         i++;
+      }
+   }
+
+   Setup();
+
+   printf("Press 't' to change texture image/colors\n");
+
+   EventLoop();
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex_mt.c Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c
--- Mesa-7.8.1/progs/xdemos/sharedtex_mt.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,490 @@
+/* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */
+
+/*
+ * Test sharing of display lists and texture objects between GLX contests.
+ * Brian Paul
+ * Summer 2000
+ *
+ *
+ * Copyright (C) 2000  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Modified 2009 for multithreading by Thomas Hellstrom.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <X11/X.h>
+
+struct thread_init_arg {
+   int id;
+};
+
+struct window {
+   pthread_mutex_t drawMutex;
+   char DisplayName[1000];
+   Display *Dpy;
+   Window Win;
+   GLXContext Context;
+   float Angle;
+   int Id;
+   XVisualInfo *visInfo;
+};
+
+
+#define MAX_WINDOWS 20
+static struct window Windows[MAX_WINDOWS];
+static int NumWindows = 0;
+static int terminate = 0;
+static GLXContext gCtx;
+static Display *gDpy;
+static GLuint Textures[3];
+
+
+
+static void
+Error(const char *display, const char *msg)
+{
+   fprintf(stderr, "Error on display %s - %s\n", display, msg);
+   exit(1);
+}
+
+
+static int
+initMainthread(Display *dpy, const char *displayName)
+{
+   int scrnum;
+   XVisualInfo *visinfo;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+                    GLX_DEPTH_SIZE, 1,
+		    None };
+
+   scrnum = DefaultScreen(dpy);
+   visinfo = glXChooseVisual(dpy, scrnum, attrib);
+   if (!visinfo) {
+      Error(displayName, "Unable to find RGB, double-buffered visual");
+      return -1;
+   }
+   gCtx = glXCreateContext(dpy, visinfo, NULL, True);
+   if (!gCtx) {
+      Error(displayName, "Couldn't create GLX context");
+      return -1;
+   }
+   return 0;
+}
+
+static struct window *
+AddWindow(Display *dpy, const char *displayName, int xpos, int ypos,
+          GLXContext sCtx)
+{
+   Window win;
+   GLXContext ctx;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+                    GLX_DEPTH_SIZE, 1,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   XVisualInfo *visinfo;
+   int width = 300, height = 300;
+
+   if (NumWindows >= MAX_WINDOWS)
+      return NULL;
+
+   scrnum = DefaultScreen(dpy);
+   root = RootWindow(dpy, scrnum);
+
+   visinfo = glXChooseVisual(dpy, scrnum, attrib);
+   if (!visinfo) {
+      Error(displayName, "Unable to find RGB, double-buffered visual");
+      return NULL;
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
+		       0, visinfo->depth, InputOutput,
+		       visinfo->visual, mask, &attr);
+   if (!win) {
+      Error(displayName, "Couldn't create window");
+      return NULL;
+   }
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, displayName, displayName,
+			     None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   ctx = glXCreateContext(dpy, visinfo,
+                          sCtx ? sCtx : NULL, True);
+
+   if (!ctx) {
+      Error(displayName, "Couldn't create GLX context");
+      return NULL;
+   }
+
+   XMapWindow(dpy, win);
+
+   /* save the info for this window */
+   {
+      static int id = 0;
+      struct window *h = &Windows[NumWindows];
+      if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
+         Error(displayName, "string overflow");
+         return NULL;
+      }
+      strcpy(h->DisplayName, displayName);
+      h->Dpy = dpy;
+      h->Win = win;
+      h->Context = ctx;
+      h->Angle = 0.0;
+      h->Id = id++;
+      h->visInfo = visinfo;
+      pthread_mutex_init(&h->drawMutex, NULL);
+      NumWindows++;
+      return &Windows[NumWindows-1];
+   }
+}
+
+
+static void
+InitGLstuff(void)
+
+{
+   glGenTextures(3, Textures);
+
+   /* setup first texture object */
+   {
+      GLubyte image[16][16][4];
+      GLint i, j;
+      glBindTexture(GL_TEXTURE_2D, Textures[0]);
+
+      /* red/white checkerboard */
+      for (i = 0; i < 16; i++) {
+         for (j = 0; j < 16; j++) {
+            if ((i ^ j) & 1) {
+               image[i][j][0] = 255;
+               image[i][j][1] = 255;
+               image[i][j][2] = 255;
+               image[i][j][3] = 255;
+            }
+            else {
+               image[i][j][0] = 255;
+               image[i][j][1] = 0;
+               image[i][j][2] = 0;
+               image[i][j][3] = 255;
+            }
+         }
+      }
+
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
+                   GL_UNSIGNED_BYTE, image);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   }
+
+   /* setup second texture object */
+   {
+      GLubyte image[8][8][3];
+      GLint i, j;
+      glBindTexture(GL_TEXTURE_2D, Textures[1]);
+
+      /* green/yellow checkerboard */
+      for (i = 0; i < 8; i++) {
+         for (j = 0; j < 8; j++) {
+            if ((i ^ j) & 1) {
+               image[i][j][0] = 0;
+               image[i][j][1] = 255;
+               image[i][j][2] = 0;
+            }
+            else {
+               image[i][j][0] = 255;
+               image[i][j][1] = 255;
+               image[i][j][2] = 0;
+            }
+         }
+      }
+
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
+                   GL_UNSIGNED_BYTE, image);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   }
+
+   /* setup second texture object */
+   {
+      GLubyte image[4][4][3];
+      GLint i, j;
+      glBindTexture(GL_TEXTURE_2D, Textures[2]);
+
+      /* blue/gray checkerboard */
+      for (i = 0; i < 4; i++) {
+         for (j = 0; j < 4; j++) {
+            if ((i ^ j) & 1) {
+               image[i][j][0] = 0;
+               image[i][j][1] = 0;
+               image[i][j][2] = 255;
+            }
+            else {
+               image[i][j][0] = 200;
+               image[i][j][1] = 200;
+               image[i][j][2] = 200;
+            }
+         }
+      }
+
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
+                   GL_UNSIGNED_BYTE, image);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   }
+
+   /* Now make the cube object display list */
+
+   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));
+}
+
+static void
+Redraw(struct window *h)
+{
+   pthread_mutex_lock(&h->drawMutex);
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
+      pthread_mutex_unlock(&h->drawMutex);
+      return;
+   }
+
+   h->Angle += 1.0;
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.25, 0.25, 0.25, 1.0);
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glEnable(GL_TEXTURE_2D);
+   glEnable(GL_DEPTH_TEST);
+   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+   glColor3f(1, 1, 1);
+
+   glPushMatrix();
+   if (h->Id == 0)
+      glRotatef(h->Angle, 0, 1, -1);
+   else if (h->Id == 1)
+      glRotatef(-(h->Angle), 0, 1, -1);
+   else if (h->Id == 2)
+      glRotatef(h->Angle, 0, 1, 1);
+   else if (h->Id == 3)
+      glRotatef(-(h->Angle), 0, 1, 1);
+   glBindTexture(GL_TEXTURE_2D, Textures[0]);
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f(-1,  1, -1);
+   glTexCoord2f(1, 1);  glVertex3f(-1,  1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
+   glEnd();
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f(1,  1, -1);
+   glTexCoord2f(1, 1);  glVertex3f(1,  1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(1, -1,  1);
+   glEnd();
+
+   glBindTexture(GL_TEXTURE_2D, Textures[1]);
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1, -1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
+   glEnd();
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(-1, 1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, 1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1, 1,  1);
+   glTexCoord2f(0, 1);  glVertex3f(-1, 1,  1);
+   glEnd();
+
+   glBindTexture(GL_TEXTURE_2D, Textures[2]);
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
+   glTexCoord2f(1, 1);  glVertex3f( 1,  1, -1);
+   glTexCoord2f(0, 1);  glVertex3f(-1,  1, -1);
+   glEnd();
+   glBegin(GL_POLYGON);
+   glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
+   glTexCoord2f(1, 0);  glVertex3f( 1, -1, 1);
+   glTexCoord2f(1, 1);  glVertex3f( 1,  1, 1);
+   glTexCoord2f(0, 1);  glVertex3f(-1,  1, 1);
+   glEnd();
+
+   glPopMatrix();
+
+   glXSwapBuffers(h->Dpy, h->Win);
+
+   if (!glXMakeCurrent(h->Dpy, None, NULL)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Redraw");
+   }
+   pthread_mutex_unlock(&h->drawMutex);
+}
+
+static void *threadRunner (void *arg)
+{
+   struct thread_init_arg *tia = (struct thread_init_arg *) arg;
+   struct window *win;
+
+   win = &Windows[tia->id];
+
+   while(!terminate) {
+      usleep(1000);
+      Redraw(win);
+   }
+
+   return NULL;
+}
+
+static void
+Resize(struct window *h, unsigned int width, unsigned int height)
+{
+   pthread_mutex_lock(&h->drawMutex);
+
+   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
+      pthread_mutex_unlock(&h->drawMutex);
+      return;
+   }
+
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-1, 1, -1, 1, 2, 10);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0, 0, -4.5);
+   if (!glXMakeCurrent(h->Dpy, None, NULL)) {
+      Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
+   }
+   pthread_mutex_unlock(&h->drawMutex);
+}
+
+
+static void
+EventLoop(void)
+{
+   while (1) {
+      int i;
+      XEvent event;
+      XNextEvent(gDpy, &event);
+      for (i = 0; i < NumWindows; i++) {
+	 struct window *h = &Windows[i];
+	 if (event.xany.window == h->Win) {
+	    switch (event.type) {
+	    case Expose:
+	       Redraw(h);
+	       break;
+	    case ConfigureNotify:
+	       Resize(h, event.xconfigure.width, event.xconfigure.height);
+	       break;
+	    case KeyPress:
+	       terminate = 1;
+	       return;
+	    default:
+	       /*no-op*/ ;
+	    }
+	 }
+      }
+   }
+}
+
+int
+main(int argc, char *argv[])
+{
+   const char *dpyName = XDisplayName(NULL);
+   pthread_t t0, t1, t2, t3;
+   struct thread_init_arg tia0, tia1, tia2, tia3;
+   struct window *h0;
+
+   XInitThreads();
+
+   gDpy = XOpenDisplay(dpyName);
+   if (!gDpy) {
+      Error(dpyName, "Unable to open display");
+      return -1;
+   }
+
+   if (initMainthread(gDpy, dpyName))
+      return -1;
+
+   /* four windows and contexts sharing display lists and texture objects */
+   h0 = AddWindow(gDpy, dpyName,  10,  10, gCtx);
+   (void) AddWindow(gDpy, dpyName, 330,  10, gCtx);
+   (void) AddWindow(gDpy, dpyName,  10, 350, gCtx);
+   (void) AddWindow(gDpy, dpyName, 330, 350, gCtx);
+
+   if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) {
+      Error(dpyName, "glXMakeCurrent failed for init thread.");
+      return -1;
+   }
+
+   InitGLstuff();
+
+   tia0.id = 0;
+   pthread_create(&t0, NULL, threadRunner, &tia0);
+   tia1.id = 1;
+   pthread_create(&t1, NULL, threadRunner, &tia1);
+   tia2.id = 2;
+   pthread_create(&t2, NULL, threadRunner, &tia2);
+   tia3.id = 3;
+   pthread_create(&t3, NULL, threadRunner, &tia3);
+   EventLoop();
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c
--- Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,396 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ * 
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Test the GLX_EXT_texture_from_pixmap extension
+ * Brian Paul
+ * 19 May 2007
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <X11/keysym.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static float top, bottom;
+
+static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL;
+static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL;
+
+
+static Display *
+OpenDisplay(void)
+{
+   int screen;
+   Display *dpy;
+   const char *ext;
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy) {
+      printf("Couldn't open default display!\n");
+      exit(1);
+   }
+
+   screen = DefaultScreen(dpy);
+   ext = glXQueryExtensionsString(dpy, screen);
+   if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) {
+      fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n");
+      exit(1);
+   }
+
+   glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC)
+      glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
+   glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC)
+      glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT");
+
+   if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) {
+      fprintf(stderr, "glXGetProcAddress failed!\n");
+      exit(1);
+   }
+      
+   return dpy;
+}
+
+
+static GLXFBConfig
+ChoosePixmapFBConfig(Display *display)
+{
+   int screen = DefaultScreen(display);
+   GLXFBConfig *fbconfigs;
+   int i, nfbconfigs = 0, value;
+
+   fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs);
+   for (i = 0; i < nfbconfigs; i++) {
+
+      glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
+      if (!(value & GLX_PIXMAP_BIT))
+         continue;
+
+      glXGetFBConfigAttrib(display, fbconfigs[i],
+                           GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
+      if (!(value & GLX_TEXTURE_2D_BIT_EXT))
+         continue;
+
+      glXGetFBConfigAttrib(display, fbconfigs[i],
+                           GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
+      if (value == False) {
+         glXGetFBConfigAttrib(display, fbconfigs[i],
+                              GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
+         if (value == False)
+            continue;
+      }
+
+      glXGetFBConfigAttrib(display, fbconfigs[i],
+                           GLX_Y_INVERTED_EXT, &value);
+      if (value == True) {
+         top = 0.0f;
+         bottom = 1.0f;
+      }
+      else {
+         top = 1.0f;
+         bottom = 0.0f;
+      }
+
+      break;
+   }
+
+   if (i == nfbconfigs) {
+      printf("Unable to find FBconfig for texturing\n");
+      exit(1);
+   }
+
+   return fbconfigs[i];
+}
+
+
+static GLXPixmap
+CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p)
+{
+   GLXPixmap gp;
+   const int pixmapAttribs[] = {
+      GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+      GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+      None
+   };
+   Window root = RootWindow(dpy, 0);
+
+   *p = XCreatePixmap(dpy, root, w, h, 24);
+   XSync(dpy, 0);
+   gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs);
+   XSync(dpy, 0);
+
+   return gp;
+}
+
+
+static void
+DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h)
+{
+   XGCValues gcvals;
+   GC gc;
+
+   gcvals.background = 0;
+   gc = XCreateGC(dpy, pm, GCBackground, &gcvals);
+
+   XSetForeground(dpy, gc, 0x0);
+   XFillRectangle(dpy, pm, gc, 0, 0, w, h);
+
+   XSetForeground(dpy, gc, 0xff0000);
+   XFillRectangle(dpy, pm, gc, 0, 0, 50, 50);
+
+   XSetForeground(dpy, gc, 0x00ff00);
+   XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50);
+
+   XSetForeground(dpy, gc, 0x0000ff);
+   XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50);
+
+   XSetForeground(dpy, gc, 0xffffff);
+   XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50);
+
+   XSetForeground(dpy, gc, 0xffff00);
+   XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
+   XDrawLine(dpy, pm, gc, 0, 0, w, h);
+   XDrawLine(dpy, pm, gc, 0, h, w, 0);
+
+   XFreeGC(dpy, gc);
+}
+
+
+static XVisualInfo *
+ChooseWindowVisual(Display *dpy)
+{
+   int screen = DefaultScreen(dpy);
+   XVisualInfo *visinfo;
+   int attribs[] = {
+      GLX_RGBA,
+      GLX_RED_SIZE, 1,
+      GLX_GREEN_SIZE, 1,
+      GLX_BLUE_SIZE, 1,
+      GLX_DOUBLEBUFFER,
+      None
+   };
+
+   visinfo = glXChooseVisual(dpy, screen, attribs);
+   if (!visinfo) {
+      printf("Unable to find RGB, double-buffered visual\n");
+      exit(1);
+   }
+
+   return visinfo;
+}
+
+
+static Window
+CreateWindow(Display *dpy, XVisualInfo *visinfo,
+             int width, int height, const char *name)
+{
+   int screen = DefaultScreen(dpy);
+   Window win;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+
+   root = RootWindow(dpy, screen);
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   if (win) {
+      XSizeHints sizehints;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+
+      XMapWindow(dpy, win);
+   }
+   return win;
+}
+
+
+static void
+BindPixmapTexture(Display *dpy, GLXPixmap gp)
+{
+   GLuint texture;
+
+   glGenTextures(1, &texture);
+   glBindTexture(GL_TEXTURE_2D, texture);
+
+   glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL);
+
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+   glEnable(GL_TEXTURE_2D);
+   /*
+     glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT);
+   */
+}
+
+
+static void
+Resize(Window win, unsigned int width, unsigned int height)
+{
+   float sz = 1.5;
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-sz, sz, -sz, sz, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void
+Redraw(Display *dpy, Window win, float rot)
+{
+   glClearColor(0.25, 0.25, 0.25, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+   glPushMatrix();
+   glRotatef(rot, 0, 0, 1);
+   glRotatef(2.0 * rot, 1, 0, 0);
+
+   glBegin(GL_QUADS);
+   glTexCoord2d(0.0, bottom);
+   glVertex2f(-1, -1);
+   glTexCoord2d(1.0, bottom);
+   glVertex2f( 1, -1);
+   glTexCoord2d(1.0, top);
+   glVertex2d(1.0, 1.0);
+   glTexCoord2d(0.0, top);
+   glVertex2f(-1.0, 1.0);
+   glEnd();
+
+   glPopMatrix();
+
+   glXSwapBuffers(dpy, win);
+}
+
+
+static void
+EventLoop(Display *dpy, Window win)
+{
+   GLfloat rot = 0.0;
+   int anim = 0;
+ 
+   while (1) {
+      if (!anim || XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+
+         switch (event.type) {
+         case Expose:
+            Redraw(dpy, win, rot);
+            break;
+         case ConfigureNotify:
+            Resize(event.xany.window,
+                   event.xconfigure.width,
+                   event.xconfigure.height);
+            break;
+         case KeyPress:
+            {
+               char buf[100];
+               KeySym keySym;
+               XComposeStatus stat;
+               XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+               if (keySym == XK_Escape) {
+                  return; /* exit */
+               }
+               else if (keySym == XK_r) {
+                  rot += 1.0;
+                  Redraw(dpy, win, rot);
+               }
+               else if (keySym == XK_a) {
+                  anim = !anim;
+               }
+               else if (keySym == XK_R) {
+                  rot -= 1.0;
+                  Redraw(dpy, win, rot);
+               }
+            }
+            break;
+         default:
+            ; /*no-op*/
+         }
+      }
+      else {
+         /* animate */
+         rot += 1.0;
+         Redraw(dpy, win, rot);
+      }
+   }
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   GLXFBConfig pixmapConfig;
+   XVisualInfo *windowVis;
+   GLXPixmap gp;
+   Window win;
+   GLXContext ctx;
+   Pixmap p;
+
+   dpy = OpenDisplay();
+
+   pixmapConfig = ChoosePixmapFBConfig(dpy);
+   windowVis = ChooseWindowVisual(dpy);
+   win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap");
+
+   gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p);
+   DrawPixmapImage(dpy, p, 512, 512);
+
+   ctx = glXCreateContext(dpy, windowVis, NULL, True);
+   if (!ctx) {
+      printf("Couldn't create GLX context\n");
+      exit(1);
+   }
+
+   glXMakeCurrent(dpy, win, ctx);
+
+   BindPixmapTexture(dpy, gp);
+
+   EventLoop(dpy, win);
+
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/wincopy.c Mesa-7.8.1.patched/progs/xdemos/wincopy.c
--- Mesa-7.8.1/progs/xdemos/wincopy.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/wincopy.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,328 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.2
+ * 
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * This program opens two GLX windows, renders into one and uses
+ * glCopyPixels to copy the image from the first window into the
+ * second by means of the GLX 1.3 function glxMakeContextCurrent().
+ * This function works just like the glXMakeCurrentReadSGI() function
+ * in the GLX_SGI_make_current_read extension.
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <X11/keysym.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#ifdef GLX_VERSION_1_3
+
+
+static Display *Dpy;
+static int ScrNum;
+static GLXContext Context;
+static Window Win[2];  /* Win[0] = source,  Win[1] = dest */
+static GLint Width[2], Height[2];
+static GLboolean TestClipping = GL_FALSE;
+static GLfloat Angle = 0.0;
+
+static GLboolean DrawFront = GL_FALSE;
+
+PFNGLXMAKECURRENTREADSGIPROC make_context_current = NULL;
+
+static Window
+CreateWindow(Display *dpy, int scrnum, XVisualInfo *visinfo,
+             int xpos, int ypos, int width, int height,
+             const char *name)
+{
+   Window win;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+
+   root = RootWindow(dpy, scrnum);
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr);
+   if (win) {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+
+      XMapWindow(dpy, win);
+   }
+   return win;
+}
+
+
+static void
+Redraw(void)
+{
+   /* make the first window the current one */
+   if (! (*make_context_current)(Dpy, Win[0], Win[0], Context)) {
+      printf("glXMakeContextCurrent failed in Redraw()\n");
+      return;
+   }
+
+   Angle += 1.0;
+
+   if (DrawFront) {
+      glDrawBuffer(GL_FRONT);
+      glReadBuffer(GL_FRONT);
+   }
+   else {
+      glDrawBuffer(GL_BACK);
+      glReadBuffer(GL_BACK);
+   }
+
+   glViewport(0, 0, Width[0], Height[0]);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+   glMatrixMode(GL_MODELVIEW);
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.5, 0.5, 0.5, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   /* draw blue quad */
+   glColor3f(0.3, 0.3, 1.0);
+   glPushMatrix();
+   glRotatef(Angle, 0, 0, 1);
+   glBegin(GL_POLYGON);
+   glVertex2f(-0.5, -0.25);
+   glVertex2f( 0.5, -0.25);
+   glVertex2f( 0.5, 0.25);
+   glVertex2f(-0.5, 0.25);
+   glEnd();
+   glPopMatrix();
+
+   if (DrawFront)
+      glFinish();
+   else
+      glXSwapBuffers(Dpy, Win[0]);
+
+
+   /* copy image from window 0 to window 1 */
+   if (!(*make_context_current)(Dpy, Win[1], Win[0], Context)) {
+      printf("glXMakeContextCurrent failed in Redraw()\n");
+      return;
+   }
+
+   /* copy the image between windows */
+   glClearColor(0.0, 0.0, 0.0, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   if (TestClipping) {
+      glWindowPos2iARB(-2, -2);
+      glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR);
+   }
+   else {
+      glWindowPos2iARB(0, 0);
+      glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR);
+   }
+
+   if (DrawFront)
+      glFinish();
+   else
+      glXSwapBuffers(Dpy, Win[1]);
+}
+
+
+
+static void
+Resize(Window win, unsigned int width, unsigned int height)
+{
+   int i;
+   if (win == Win[0]) {
+      i = 0;
+   }
+   else {
+      i = 1;
+   }
+   Width[i] = width;
+   Height[i] = height;
+   if (!glXMakeCurrent(Dpy, Win[i], Context)) {
+      printf("glXMakeCurrent failed in Resize()\n");
+      return;
+   }
+}
+
+
+
+static void
+EventLoop(void)
+{
+   XEvent event;
+   while (1) {
+      if (XPending(Dpy) > 0) {
+         XNextEvent( Dpy, &event );
+         switch (event.type) {
+            case Expose:
+               Redraw();
+               break;
+            case ConfigureNotify:
+               Resize(event.xany.window, event.xconfigure.width, event.xconfigure.height);
+               break;
+            case KeyPress:
+               {
+                  char buf[100];
+                  KeySym keySym;
+                  XComposeStatus stat;
+                  XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+                  if (keySym == XK_Escape) {
+                        /* exit */
+                        return;
+                  }
+                  else if (buf[0] == 'f') {
+                     DrawFront = !DrawFront;
+                     printf("Drawing to %s buffer\n",
+                            DrawFront ? "GL_FRONT" : "GL_BACK");
+                  }
+               }
+               break;
+            default:
+               /*no-op*/ ;
+         }
+      }
+      else {
+         /* animate */
+         Redraw();
+      }
+   }
+}
+
+
+static void
+Init(void)
+{
+   XVisualInfo *visinfo;
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int major, minor;
+
+   Dpy = XOpenDisplay(NULL);
+   if (!Dpy) {
+      printf("Couldn't open default display!\n");
+      exit(1);
+   }
+
+   ScrNum = DefaultScreen(Dpy);
+
+   glXQueryVersion(Dpy, &major, &minor);
+
+   if (major * 100 + minor >= 103) {
+      make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
+	  glXGetProcAddressARB( (GLubyte *) "glXMakeContextCurrent" );
+   }
+   else {
+      const char * const glxExtensions = glXQueryExtensionsString(Dpy, ScrNum);
+      const char * ext = strstr( glxExtensions, "GLX_SGI_make_current_read" );
+      const size_t len = strlen( "GLX_SGI_make_current_read" );
+      
+      if ( (ext != NULL) 
+	   && ((ext[len] == ' ') || (ext[len] == '\0')) ) {
+	 make_context_current = (PFNGLXMAKECURRENTREADSGIPROC) 
+	     glXGetProcAddressARB( (GLubyte *) "glXMakeCurrentReadSGI" );
+      }
+   }
+
+   if (make_context_current == NULL) {
+      fprintf(stderr, "Sorry, this program requires either GLX 1.3 "
+	      "or GLX_SGI_make_current_read.\n");
+      exit(1);
+   }
+
+   visinfo = glXChooseVisual(Dpy, ScrNum, attrib);
+   if (!visinfo) {
+      printf("Unable to find RGB, double-buffered visual\n");
+      exit(1);
+   }
+
+   Context = glXCreateContext(Dpy, visinfo, NULL, True);
+   if (!Context) {
+      printf("Couldn't create GLX context\n");
+      exit(1);
+   }
+
+
+   Win[0] = CreateWindow(Dpy, ScrNum, visinfo,
+                         0, 0, 300, 300, "source window");
+
+   Win[1] = CreateWindow(Dpy, ScrNum, visinfo,
+                         350, 0, 300, 300, "dest window");
+
+   printf("Press Esc to exit\n");
+   printf("Press 'f' to toggle front/back buffer drawing\n");
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   if (argc > 1 && strcmp(argv[1], "-clip") == 0)
+      TestClipping = GL_TRUE;
+   Init();
+   EventLoop();
+   return 0;
+}
+
+
+#else
+
+
+int
+main(int argc, char *argv[])
+{
+   printf("This program requires GLX 1.3!\n");
+   return 0;
+}
+
+
+#endif /* GLX_VERSION_1_3 */
diff -Naurp Mesa-7.8.1/progs/xdemos/xdemo.c Mesa-7.8.1.patched/progs/xdemos/xdemo.c
--- Mesa-7.8.1/progs/xdemos/xdemo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/xdemo.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,334 @@
+
+/*
+ * Very simple demo of how to use the Mesa/X11 interface instead of the
+ * glx, tk or aux toolkits.  I highly recommend using the GLX interface
+ * instead of the X/Mesa interface, however.
+ *
+ * This program is in the public domain.
+ *
+ * Brian Paul
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "GL/xmesa.h"
+#include "GL/gl.h"
+
+
+
+static GLint Black, Red, Green, Blue;
+
+
+
+static void make_window( char *title, int color_flag )
+{
+   int x = 10, y = 10, width = 400, height = 300;
+   Display *dpy;
+   int scr;
+   Window root, win;
+   Colormap cmap;
+   XColor xcolor;
+   int attr_flags;
+   XVisualInfo *visinfo;
+   XSetWindowAttributes attr;
+   XTextProperty tp;
+   XSizeHints sh;
+   XEvent e;
+   XMesaContext context;
+   XMesaVisual visual;
+   XMesaBuffer buffer;
+
+
+   /*
+    * Do the usual X things to make a window.
+    */
+
+   dpy = XOpenDisplay(NULL);
+   if (!dpy) {
+      printf("Couldn't open default display!\n");
+      exit(1);
+   }
+
+   scr = DefaultScreen(dpy);
+   root = RootWindow(dpy, scr);
+
+   /* alloc visinfo struct */
+   visinfo = (XVisualInfo *) malloc( sizeof(XVisualInfo) );
+
+   /* Get a visual and colormap */
+   if (color_flag) {
+      /* Open TrueColor window */
+
+/*
+      if (!XMatchVisualInfo( dpy, scr, 24, TrueColor, visinfo )) {
+	 printf("Couldn't get 24-bit TrueColor visual!\n");
+	 exit(1);
+      }
+*/
+      if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) {
+	 printf("Couldn't get 8-bit PseudoColor visual!\n");
+	 exit(1);
+      }
+
+      cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone );
+      Black = Red = Green = Blue = 0;
+   }
+   else {
+      /* Open color index window */
+
+      if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) {
+	 printf("Couldn't get 8-bit PseudoColor visual\n");
+	 exit(1);
+      }
+
+      cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone );
+
+      /* Allocate colors */
+      xcolor.red   = 0x0;
+      xcolor.green = 0x0;
+      xcolor.blue  = 0x0;
+      xcolor.flags = DoRed | DoGreen | DoBlue;
+      if (!XAllocColor( dpy, cmap, &xcolor )) {
+	 printf("Couldn't allocate black!\n");
+	 exit(1);
+      }
+      Black = xcolor.pixel;
+
+      xcolor.red   = 0xffff;
+      xcolor.green = 0x0;
+      xcolor.blue  = 0x0;
+      xcolor.flags = DoRed | DoGreen | DoBlue;
+      if (!XAllocColor( dpy, cmap, &xcolor )) {
+	 printf("Couldn't allocate red!\n");
+	 exit(1);
+      }
+      Red = xcolor.pixel;
+
+      xcolor.red   = 0x0;
+      xcolor.green = 0xffff;
+      xcolor.blue  = 0x0;
+      xcolor.flags = DoRed | DoGreen | DoBlue;
+      if (!XAllocColor( dpy, cmap, &xcolor )) {
+	 printf("Couldn't allocate green!\n");
+	 exit(1);
+      }
+      Green = xcolor.pixel;
+
+      xcolor.red   = 0x0;
+      xcolor.green = 0x0;
+      xcolor.blue  = 0xffff;
+      xcolor.flags = DoRed | DoGreen | DoBlue;
+      if (!XAllocColor( dpy, cmap, &xcolor )) {
+	 printf("Couldn't allocate blue!\n");
+	 exit(1);
+      }
+      Blue = xcolor.pixel;
+   }
+
+   /* set window attributes */
+   attr.colormap = cmap;
+   attr.event_mask = ExposureMask | StructureNotifyMask;
+   attr.border_pixel = BlackPixel( dpy, scr );
+   attr.background_pixel = BlackPixel( dpy, scr );
+   attr_flags = CWColormap | CWEventMask | CWBorderPixel | CWBackPixel;
+
+   /* Create the window */
+   win = XCreateWindow( dpy, root, x,y, width, height, 0,
+			    visinfo->depth, InputOutput,
+			    visinfo->visual,
+			    attr_flags, &attr);
+   if (!win) {
+      printf("Couldn't open window!\n");
+      exit(1);
+   }
+
+   XStringListToTextProperty(&title, 1, &tp);
+   sh.flags = USPosition | USSize;
+   XSetWMProperties(dpy, win, &tp, &tp, 0, 0, &sh, 0, 0);
+   XMapWindow(dpy, win);
+   while (1) {
+      XNextEvent( dpy, &e );
+      if (e.type == MapNotify && e.xmap.window == win) {
+	 break;
+      }
+   }
+
+
+   /*
+    * Now do the special Mesa/Xlib stuff!
+    */
+
+   visual = XMesaCreateVisual( dpy, visinfo,
+                              (GLboolean) color_flag,
+                               GL_FALSE,  /* alpha_flag */
+                               GL_FALSE,  /* db_flag */
+                               GL_FALSE,  /* stereo flag */
+                               GL_FALSE,  /* ximage_flag */
+                               0,         /* depth size */
+                               0,         /* stencil size */
+                               0,0,0,0,   /* accum_size */
+                               0,         /* num samples */
+                               0,         /* level */
+                               0          /* caveat */
+                              );
+   if (!visual) {
+      printf("Couldn't create Mesa/X visual!\n");
+      exit(1);
+   }
+
+   /* Create a Mesa rendering context */
+   context = XMesaCreateContext( visual,
+                                 NULL       /* share_list */
+                               );
+   if (!context) {
+      printf("Couldn't create Mesa/X context!\n");
+      exit(1);
+   }
+
+   buffer = XMesaCreateWindowBuffer( visual, win );
+   if (!buffer) {
+      printf("Couldn't create Mesa/X buffer!\n");
+      exit(1);
+   }
+
+
+   XMesaMakeCurrent( context, buffer );
+
+   /* Ready to render! */
+}
+
+
+
+static void draw_cube( void )
+{
+   /* X faces */
+   glIndexi( Red );
+   glColor3f( 1.0, 0.0, 0.0 );
+   glBegin( GL_POLYGON );
+   glVertex3f( 1.0, 1.0, 1.0 );
+   glVertex3f( 1.0, -1.0, 1.0 );
+   glVertex3f( 1.0, -1.0, -1.0 );
+   glVertex3f( 1.0, 1.0, -1.0 );
+   glEnd();
+
+   glBegin( GL_POLYGON );
+   glVertex3f( -1.0, 1.0, 1.0 );
+   glVertex3f( -1.0, 1.0, -1.0 );
+   glVertex3f( -1.0, -1.0, -1.0 );
+   glVertex3f( -1.0, -1.0, 1.0 );
+   glEnd();
+
+   /* Y faces */
+   glIndexi( Green );
+   glColor3f( 0.0, 1.0, 0.0 );
+   glBegin( GL_POLYGON );
+   glVertex3f(  1.0, 1.0,  1.0 );
+   glVertex3f(  1.0, 1.0, -1.0 );
+   glVertex3f( -1.0, 1.0, -1.0 );
+   glVertex3f( -1.0, 1.0,  1.0 );
+   glEnd();
+
+   glBegin( GL_POLYGON );
+   glVertex3f(  1.0, -1.0,  1.0 );
+   glVertex3f( -1.0, -1.0,  1.0 );
+   glVertex3f( -1.0, -1.0, -1.0 );
+   glVertex3f(  1.0, -1.0, -1.0 );
+   glEnd();
+
+   /* Z faces */
+   glIndexi( Blue );
+   glColor3f( 0.0, 0.0, 1.0 );
+   glBegin( GL_POLYGON );
+   glVertex3f(  1.0,  1.0,  1.0 );
+   glVertex3f( -1.0,  1.0,  1.0 );
+   glVertex3f( -1.0, -1.0,  1.0 );
+   glVertex3f(  1.0, -1.0,  1.0 );
+   glEnd();
+
+   glBegin( GL_POLYGON );
+   glVertex3f(  1.0, 1.0, -1.0 );
+   glVertex3f(  1.0,-1.0, -1.0 );
+   glVertex3f( -1.0,-1.0, -1.0 );
+   glVertex3f( -1.0, 1.0, -1.0 );
+   glEnd();
+}
+
+
+
+
+static void display_loop( void )
+{
+   GLfloat xrot, yrot, zrot;
+
+   xrot = yrot = zrot = 0.0;
+
+   glClearColor( 0.0, 0.0, 0.0, 0.0 );
+   glClearIndex( Black );
+
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -1.0, 1.0,  -1.0, 1.0,  1.0, 10.0 );
+   glTranslatef( 0.0, 0.0, -5.0 );
+
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+
+   glCullFace( GL_BACK );
+   glEnable( GL_CULL_FACE );
+
+   glShadeModel( GL_FLAT );
+
+   while (1) {
+      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 );
+
+      draw_cube();
+
+      glPopMatrix();
+      glFinish();
+
+      xrot += 10.0;
+      yrot += 7.0;
+      zrot -= 3.0;
+   }
+
+}
+
+
+
+
+int main( int argc, char *argv[] )
+{
+   int mode = 0;
+
+   if (argc >= 2)
+   {
+        if (strcmp(argv[1],"-ci")==0)
+           mode = 0;
+        else if (strcmp(argv[1],"-rgb")==0)
+           mode = 1;
+        else
+        {
+           printf("Bad flag: %s\n", argv[1]);
+           printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n");
+           exit(1);
+        }
+   }
+   else
+   {
+        printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n");
+        printf("Defaulting to  8-bit color index\n");
+   }
+
+   make_window( argv[0], mode );
+
+   display_loop();
+   return 0;
+}
+
diff -Naurp Mesa-7.8.1/progs/xdemos/xfont.c Mesa-7.8.1.patched/progs/xdemos/xfont.c
--- Mesa-7.8.1/progs/xdemos/xfont.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/xfont.c	2010-06-13 13:45:06.788792936 +0200
@@ -0,0 +1,206 @@
+
+/*
+ * Mesa 3-D graphics library
+ * 
+ * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Example of using glXUseXFont().
+ * 5 November 1999
+ * Brian Paul
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static const char *ProgramName = "xfont";
+
+static const char *FontName = "fixed";
+
+static GLuint FontBase = 0;
+
+
+
+static void redraw( Display *dpy, Window w )
+{
+   static const char *text = "This is glXUseXFont()";
+
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   /* triangle */
+   glColor3f( 0.2, 0.2, 1.0 );
+   glBegin(GL_TRIANGLES);
+   glVertex2f( 0, 0.8 );
+   glVertex2f( -0.8, -0.7 );
+   glVertex2f( 0.8, -0.7 );
+   glEnd();
+
+   /* text */
+   glColor3f( 1, 1, 1 );
+   glRasterPos2f(-0.8, 0); 
+   glListBase(FontBase);
+   glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text);
+
+   glXSwapBuffers( dpy, w );
+}
+
+
+
+static void resize( unsigned int width, unsigned int height )
+{
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
+}
+
+
+
+static void setup_font( Display *dpy )
+{
+    XFontStruct *fontInfo;
+    Font id;
+    unsigned int first, last;
+
+    fontInfo = XLoadQueryFont(dpy, FontName);
+    if (!fontInfo) {
+        printf("Error: font %s not found\n", FontName);
+	exit(0);
+    }
+
+    id = fontInfo->fid;
+    first = fontInfo->min_char_or_byte2;
+    last = fontInfo->max_char_or_byte2;
+
+    FontBase = glGenLists((GLuint) last + 1);
+    if (!FontBase) {
+        printf("Error: unable to allocate display lists\n");
+	exit(0);
+    }
+    glXUseXFont(id, first, last - first + 1, FontBase + first);
+}
+
+static Window make_rgb_db_window( Display *dpy, int xpos, int ypos,
+				  unsigned int width, unsigned int height )
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, attrib );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, ProgramName, ProgramName,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+
+   glXMakeCurrent( dpy, win, ctx );
+
+   return win;
+}
+
+
+static void event_loop( Display *dpy )
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent( dpy, &event );
+
+      switch (event.type) {
+	 case Expose:
+	    redraw( dpy, event.xany.window );
+	    break;
+	 case ConfigureNotify:
+	    resize( event.xconfigure.width, event.xconfigure.height );
+	    break;
+         case KeyPress:
+            exit(0);
+         default:
+            ;  /* no-op */
+      }
+   }
+}
+
+
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+
+   win = make_rgb_db_window( dpy, 0, 0, 300, 300 );
+   setup_font( dpy );
+
+   glShadeModel( GL_FLAT );
+   glClearColor( 0.5, 0.5, 1.0, 1.0 );
+
+   XMapWindow( dpy, win );
+
+   event_loop( dpy );
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/xrotfontdemo.c Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c
--- Mesa-7.8.1/progs/xdemos/xrotfontdemo.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,220 @@
+/*
+ * Mesa 3-D graphics library
+ * 
+ * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Example of using glXUseRotatedXFontMESA().
+ * 24 Jan 2004
+ * Brian Paul
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xuserotfont.h"
+
+
+static const char *ProgramName = "xfont";
+
+static const char *FontName = "fixed";
+
+static GLuint FontBase[4];
+
+
+static void redraw( Display *dpy, Window w )
+{
+   static const char *text = "  Rotated bitmap text";
+   int i;
+
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   /* triangle */
+   glColor3f( 0.2, 0.2, 1.0 );
+   glBegin(GL_TRIANGLES);
+   glVertex2f( -0.8,  0.7 );
+   glVertex2f( -0.8, -0.7 );
+   glVertex2f(  0.8,  0.0 );
+   glEnd();
+
+   /* marker */
+   glColor3f( 0, 1, 0 );
+   glBegin(GL_POINTS);
+   glVertex2f(0, 0);
+   glEnd();
+
+   /* text */
+   glColor3f( 1, 1, 1 );
+
+   for (i = 0; i < 4; i++) {
+      glRasterPos2f(0, 0); 
+      glListBase(FontBase[i]);
+      glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text);
+   }
+
+   glXSwapBuffers( dpy, w );
+}
+
+
+
+static void resize( unsigned int width, unsigned int height )
+{
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
+}
+
+
+
+static void setup_font( Display *dpy )
+{
+    XFontStruct *fontInfo;
+    Font id;
+    unsigned int first, last;
+    int i;
+
+    fontInfo = XLoadQueryFont(dpy, FontName);
+    if (!fontInfo) {
+        printf("Error: font %s not found\n", FontName);
+	exit(0);
+    }
+
+    id = fontInfo->fid;
+    first = fontInfo->min_char_or_byte2;
+    last = fontInfo->max_char_or_byte2;
+
+    for (i = 0; i < 4; i++) {
+       FontBase[i] = glGenLists((GLuint) last + 1);
+       if (!FontBase[i]) {
+          printf("Error: unable to allocate display lists\n");
+          exit(0);
+       }
+       glXUseRotatedXFontMESA(id, first, last - first + 1, FontBase[i] + first,
+                              i * 90);
+    }
+}
+
+
+static Window make_rgb_db_window( Display *dpy, int xpos, int ypos,
+				  unsigned int width, unsigned int height )
+{
+   int attrib[] = { GLX_RGBA,
+		    GLX_RED_SIZE, 1,
+		    GLX_GREEN_SIZE, 1,
+		    GLX_BLUE_SIZE, 1,
+		    GLX_DOUBLEBUFFER,
+		    None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+
+   visinfo = glXChooseVisual( dpy, scrnum, attrib );
+   if (!visinfo) {
+      printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   {
+      XSizeHints sizehints;
+      sizehints.x = xpos;
+      sizehints.y = ypos;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, ProgramName, ProgramName,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+
+   glXMakeCurrent( dpy, win, ctx );
+
+   return win;
+}
+
+
+static void event_loop( Display *dpy )
+{
+   XEvent event;
+
+   while (1) {
+      XNextEvent( dpy, &event );
+
+      switch (event.type) {
+	 case Expose:
+	    redraw( dpy, event.xany.window );
+	    break;
+	 case ConfigureNotify:
+	    resize( event.xconfigure.width, event.xconfigure.height );
+	    break;
+         case KeyPress:
+            exit(0);
+         default:
+            ;  /* no-op */
+      }
+   }
+}
+
+
+
+int main( int argc, char *argv[] )
+{
+   Display *dpy;
+   Window win;
+
+   dpy = XOpenDisplay(NULL);
+
+   win = make_rgb_db_window( dpy, 0, 0, 300, 300 );
+   setup_font( dpy );
+
+   glShadeModel( GL_FLAT );
+   glClearColor( 0.5, 0.5, 1.0, 1.0 );
+
+   XMapWindow( dpy, win );
+
+   event_loop( dpy );
+   return 0;
+}
diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.c Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c
--- Mesa-7.8.1/progs/xdemos/xuserotfont.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,399 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/* \file xuserotfont.c
+ *
+ * A function like glXUseXFont() but takes a 0, 90, 180 or 270 degree
+ * rotation angle for rotated text display.
+ *
+ * Based on Mesa's glXUseXFont implementation written by Thorsten Ohl.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/glx.h>
+#include "xuserotfont.h"
+
+
+/**
+ * Generate OpenGL-compatible bitmap by drawing an X character glyph
+ * to an off-screen pixmap, then getting the image and testing pixels.
+ * \param width  bitmap width in pixels
+ * \param height  bitmap height in pixels
+ */
+static void
+fill_bitmap(Display *dpy, Pixmap pixmap, GC gc,
+	    unsigned int bitmapWidth, unsigned int bitmapHeight,
+            unsigned int charWidth, unsigned int charHeight,
+	    int xPos, int yPos, unsigned int c, GLubyte * bitmap,
+            int rotation)
+{
+   const int bytesPerRow = (bitmapWidth + 7) / 8;
+   XImage *image;
+   XChar2b char2b;
+
+   /* clear pixmap to 0 */
+   XSetForeground(dpy, gc, 0);
+   XFillRectangle(dpy, pixmap, gc, 0, 0, charWidth, charHeight);
+
+   /* The glyph is drawn snug up against the left/top edges of the pixmap */
+   XSetForeground(dpy, gc, 1);
+   char2b.byte1 = (c >> 8) & 0xff;
+   char2b.byte2 = (c & 0xff);
+   XDrawString16(dpy, pixmap, gc, xPos, yPos, &char2b, 1);
+
+   /* initialize GL bitmap */
+   memset(bitmap, 0, bytesPerRow * bitmapHeight);
+
+   image = XGetImage(dpy, pixmap, 0, 0, charWidth, charHeight, 1, XYPixmap);
+   if (image) {
+      /* Set appropriate bits in the GL bitmap.
+       * Note: X11 and OpenGL are upside down wrt each other).
+       */
+      unsigned int x, y;
+      if (rotation == 0) {
+         for (y = 0; y < charHeight; y++) {
+            for (x = 0; x < charWidth; x++) {
+               if (XGetPixel(image, x, y)) {
+                  int y2 = bitmapHeight - y - 1;
+                  bitmap[bytesPerRow * y2 + x / 8] |= (1 << (7 - (x % 8)));
+               }
+            }
+         }
+      }
+      else if (rotation == 90) {
+         for (y = 0; y < charHeight; y++) {
+            for (x = 0; x < charWidth; x++) {
+               if (XGetPixel(image, x, y)) {
+                  int x2 = y;
+                  int y2 = x;
+                  bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8)));
+               }
+            }
+         }
+      }
+      else if (rotation == 180) {
+         for (y = 0; y < charHeight; y++) {
+            for (x = 0; x < charWidth; x++) {
+               if (XGetPixel(image, x, y)) {
+                  int x2 = charWidth - x - 1;
+                  bitmap[bytesPerRow * y + x2 / 8] |= (1 << (7 - (x2 % 8)));
+               }
+            }
+         }
+      }
+      else {
+         assert(rotation == 270);
+         for (y = 0; y < charHeight; y++) {
+            for (x = 0; x < charWidth; x++) {
+               if (XGetPixel(image, x, y)) {
+                  int x2 = charHeight - y - 1;
+                  int y2 = charWidth - x - 1;
+                  bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8)));
+               }
+            }
+         }
+      }
+      XDestroyImage(image);
+   }
+}
+
+
+/*
+ * Determine if a given glyph is valid and return the
+ * corresponding XCharStruct.
+ */
+static const XCharStruct *
+isvalid(const XFontStruct * fs, unsigned int which)
+{
+   unsigned int rows, pages;
+   unsigned int byte1 = 0, byte2 = 0;
+   int i, valid = 1;
+
+   rows = fs->max_byte1 - fs->min_byte1 + 1;
+   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+
+   if (rows == 1) {
+      /* "linear" fonts */
+      if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
+	 valid = 0;
+   }
+   else {
+      /* "matrix" fonts */
+      byte2 = which & 0xff;
+      byte1 = which >> 8;
+      if ((fs->min_char_or_byte2 > byte2) ||
+	  (fs->max_char_or_byte2 < byte2) ||
+	  (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
+	 valid = 0;
+   }
+
+   if (valid) {
+      if (fs->per_char) {
+	 if (rows == 1) {
+	    /* "linear" fonts */
+	    return fs->per_char + (which - fs->min_char_or_byte2);
+	 }
+	 else {
+	    /* "matrix" fonts */
+	    i = ((byte1 - fs->min_byte1) * pages) +
+	       (byte2 - fs->min_char_or_byte2);
+	    return fs->per_char + i;
+	 }
+      }
+      else {
+	 return &fs->min_bounds;
+      }
+   }
+   return NULL;
+}
+
+
+void
+glXUseRotatedXFontMESA(Font font, int first, int count, int listbase,
+                       int rotation)
+{
+   Display *dpy;
+   Window win;
+   Pixmap pixmap;
+   GC gc;
+   XFontStruct *fs;
+   GLint swapbytes, lsbfirst, rowlength;
+   GLint skiprows, skippixels, alignment;
+   unsigned int maxCharWidth, maxCharHeight;
+   GLubyte *bm;
+   int i;
+
+   if (rotation != 0 &&
+       rotation != 90 &&
+       rotation != 180 &&
+       rotation != 270)
+      return;
+
+   dpy = glXGetCurrentDisplay();
+   if (!dpy)
+      return;			/* I guess glXMakeCurrent wasn't called */
+   win = RootWindow(dpy, DefaultScreen(dpy));
+
+   fs = XQueryFont(dpy, font);
+   if (!fs) {
+      /*
+      _mesa_error(NULL, GL_INVALID_VALUE,
+		  "Couldn't get font structure information");
+      */
+      return;
+   }
+
+   /* Allocate a GL bitmap that can fit any character */
+   maxCharWidth = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+   maxCharHeight = fs->max_bounds.ascent + fs->max_bounds.descent;
+   /* use max, in case we're rotating */
+   if (rotation == 90 || rotation == 270) {
+      /* swap width/height */
+      bm = (GLubyte *) malloc((maxCharHeight + 7) / 8 * maxCharWidth);
+   }
+   else {
+      /* normal or upside down */
+      bm = (GLubyte *) malloc((maxCharWidth + 7) / 8 * maxCharHeight);
+   }
+   if (!bm) {
+      XFreeFontInfo(NULL, fs, 1);
+      /*
+      _mesa_error(NULL, GL_OUT_OF_MEMORY,
+		  "Couldn't allocate bitmap in glXUseXFont()");
+      */
+      return;
+   }
+
+#if 0
+   /* get the page info */
+   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+   firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
+   lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
+   rows = fs->max_byte1 - fs->min_byte1 + 1;
+   unsigned int first_char, last_char, pages, rows;
+#endif
+
+   /* Save the current packing mode for bitmaps.  */
+   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
+   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
+   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
+   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
+   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
+   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
+   /* Enforce a standard packing mode which is compatible with
+      fill_bitmap() from above.  This is actually the default mode,
+      except for the (non)alignment.  */
+   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
+   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+   /* Create pixmap and GC */
+   pixmap = XCreatePixmap(dpy, win, maxCharWidth, maxCharHeight, 1);
+   {
+      XGCValues values;
+      unsigned long valuemask;
+      values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
+      values.background = WhitePixel(dpy, DefaultScreen(dpy));
+      values.font = fs->fid;
+      valuemask = GCForeground | GCBackground | GCFont;
+      gc = XCreateGC(dpy, pixmap, valuemask, &values);
+   }
+
+#ifdef DEBUG_XROT
+   if (debug_xfonts)
+      dump_font_struct(fs);
+#endif
+
+   for (i = 0; i < count; i++) {
+      const unsigned int c = first + i;
+      const int list = listbase + i;
+      unsigned int charWidth, charHeight;
+      unsigned int bitmapWidth = 0, bitmapHeight = 0;
+      GLfloat xOrig, yOrig, xStep, yStep, dtemp;
+      const XCharStruct *ch;
+      int xPos, yPos;
+      int valid;
+
+      /* check on index validity and get the bounds */
+      ch = isvalid(fs, c);
+      if (!ch) {
+	 ch = &fs->max_bounds;
+	 valid = 0;
+      }
+      else {
+	 valid = 1;
+      }
+
+#ifdef DEBUG_XROT
+      if (debug_xfonts) {
+	 char s[7];
+	 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
+	 dump_char_struct(ch, s);
+      }
+#endif
+
+      /* glBitmap()' parameters:
+         straight from the glXUseXFont(3) manpage.  */
+      charWidth = ch->rbearing - ch->lbearing;
+      charHeight = ch->ascent + ch->descent;
+      xOrig = -ch->lbearing;
+      yOrig = ch->descent;
+      xStep = ch->width;
+      yStep = 0;
+
+      /* X11's starting point.  */
+      xPos = -ch->lbearing;
+      yPos = ch->ascent;
+
+      /* Apply rotation */
+      switch (rotation) {
+      case 0:
+         /* nothing */
+         bitmapWidth = charWidth;
+         bitmapHeight = charHeight;
+         break;
+      case 90:
+         /* xStep, yStep */
+         dtemp = xStep;
+         xStep = -yStep;
+         yStep = dtemp;
+         /* xOrig, yOrig */
+         yOrig = xOrig;
+         xOrig = charHeight - (charHeight - yPos);
+         /* width, height */
+         bitmapWidth = charHeight;
+         bitmapHeight = charWidth;
+         break;
+      case 180:
+         /* xStep, yStep */
+         xStep = -xStep;
+         yStep = -yStep;
+         /* xOrig, yOrig */
+         xOrig = charWidth - xOrig - 1;
+         yOrig = charHeight - yOrig - 1;
+         bitmapWidth = charWidth;
+         bitmapHeight = charHeight;
+         break;
+      case 270:
+         /* xStep, yStep */
+         dtemp = xStep;
+         xStep = yStep;
+         yStep = -dtemp;
+         /* xOrig, yOrig */
+         dtemp = yOrig;
+         yOrig = charWidth - xOrig;
+         xOrig = dtemp;
+         /* width, height */
+         bitmapWidth = charHeight;
+         bitmapHeight = charWidth;
+         break;
+      default:
+         /* should never get here */
+         ;
+      }
+
+      glNewList(list, GL_COMPILE);
+      if (valid && bitmapWidth > 0 && bitmapHeight > 0) {
+
+	 fill_bitmap(dpy, pixmap, gc, bitmapWidth, bitmapHeight,
+                     charWidth, charHeight,
+                     xPos, yPos, c, bm, rotation);
+
+	 glBitmap(bitmapWidth, bitmapHeight, xOrig, yOrig, xStep, yStep, bm);
+
+#ifdef DEBUG_XROT
+	 if (debug_xfonts) {
+	    printf("width/height = %u/%u\n", bitmapWidth, bitmapHeight);
+	    dump_bitmap(bitmapWidth, bitmapHeight, bm);
+	 }
+#endif
+      }
+      else {
+	 glBitmap(0, 0, 0.0, 0.0, xStep, yStep, NULL);
+      }
+      glEndList();
+   }
+
+   free(bm);
+   XFreeFontInfo(NULL, fs, 1);
+   XFreePixmap(dpy, pixmap);
+   XFreeGC(dpy, gc);
+
+   /* Restore saved packing modes.  */
+   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
+   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
+   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
+   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
+   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
+
diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.h Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h
--- Mesa-7.8.1/progs/xdemos/xuserotfont.h	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,12 @@
+#ifndef XUSEROTFONT_H
+#define XUSEROTFONT_H
+
+#include <X11/Xlib.h>
+
+
+extern void
+glXUseRotatedXFontMESA(Font font, int first, int count, int listbase,
+                       int rotation);
+
+
+#endif
diff -Naurp Mesa-7.8.1/progs/xdemos/yuvrect_client.c Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c
--- Mesa-7.8.1/progs/xdemos/yuvrect_client.c	1970-01-01 01:00:00.000000000 +0100
+++ Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c	2010-06-13 13:45:06.789793146 +0200
@@ -0,0 +1,326 @@
+/*
+ * Test the GL_NV_texture_rectangle and GL_MESA_ycrcb_texture extensions and GLX_MESA_allocate-memory
+ *
+ * Dave Airlie - Feb 2005
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glx.h>
+
+#include "../util/readtex.c"   /* I know, this is a hack. */
+
+#define TEXTURE_FILE "../images/girl2.rgb"
+
+static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
+static GLint ImgWidth, ImgHeight;
+static GLushort *ImageYUV = NULL;
+static void *glx_memory;
+
+static void DrawObject(void)
+{
+   glBegin(GL_QUADS);
+
+   glTexCoord2f(0, 0);
+   glVertex2f(-1.0, -1.0);
+
+   glTexCoord2f(ImgWidth, 0);
+   glVertex2f(1.0, -1.0);
+
+   glTexCoord2f(ImgWidth, ImgHeight);
+   glVertex2f(1.0, 1.0);
+
+   glTexCoord2f(0, ImgHeight);
+   glVertex2f(-1.0, 1.0);
+
+   glEnd();
+}
+
+
+static void scr_Display( void )
+{
+   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);
+      DrawObject();
+   glPopMatrix();
+
+}
+
+
+static void Reshape( int width, int height )
+{
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -15.0 );
+}
+
+static int queryClient(Display *dpy, int screen)
+{
+#ifdef GLX_MESA_allocate_memory
+  char *extensions;
+
+  extensions = (char *)glXQueryExtensionsString(dpy, screen);
+  if (!extensions || !strstr(extensions,"GLX_MESA_allocate_memory")) {
+    return 0;
+  }
+
+  return 1;
+#else
+  return 0;
+#endif
+}
+
+static int
+query_extension(char* extName) {
+    char *p = (char *) glGetString(GL_EXTENSIONS);
+    char *end = p + strlen(p);
+    while (p < end) {
+        int n = strcspn(p, " ");
+        if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
+            return GL_TRUE;
+        p += (n + 1);
+    }
+    return GL_FALSE;
+}
+
+static void Init( int argc, char *argv[] , Display *dpy, int screen, Window win)
+{
+   GLuint texObj = 100;
+   const char *file;
+   void *glx_memory;
+
+   if (!query_extension("GL_NV_texture_rectangle")) {
+      printf("Sorry, GL_NV_texture_rectangle is required\n");
+      exit(0);
+   }
+
+   if (!query_extension("GL_MESA_ycbcr_texture")) {
+      printf("Sorry, GL_MESA_ycbcr_texture is required\n");
+      exit(0);
+   }
+
+   if (!queryClient(dpy, screen)) {
+     printf("Sorry, GLX_MESA_allocate_memory is required\n");
+     exit(0);
+   }
+
+   glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
+   glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj);
+#ifdef LINEAR_FILTER
+   /* linear filtering looks much nicer but is much slower for Mesa */
+   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#else
+   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+#endif
+
+   if (argc > 1)
+      file = argv[1];
+   else
+      file = TEXTURE_FILE;
+
+   ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight);
+   if (!ImageYUV) {
+      printf("Couldn't read %s\n", TEXTURE_FILE);
+      exit(0);
+   }
+   
+   glx_memory = glXAllocateMemoryMESA(dpy, screen, ImgWidth * ImgHeight * 2, 0, 0 ,0);
+   if (!glx_memory)
+   {
+     fprintf(stderr,"Failed to allocate MESA memory\n");
+     exit(-1);
+   }
+   
+   memcpy(glx_memory, ImageYUV, ImgWidth * ImgHeight * 2);
+   
+   printf("Image: %dx%d\n", ImgWidth, ImgHeight);
+
+   glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0,
+                GL_YCBCR_MESA, ImgWidth, ImgHeight, 0,
+                GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_APPLE, glx_memory);
+
+   assert(glGetError() == GL_NO_ERROR);
+
+   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+   glEnable(GL_TEXTURE_RECTANGLE_NV);
+
+   glShadeModel(GL_FLAT);
+   glClearColor(0.3, 0.3, 0.4, 1.0);
+
+}
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void
+make_window( Display *dpy, const char *name,
+             int x, int y, int width, int height,
+             Window *winRet, GLXContext *ctxRet)
+{
+   int attribs[] = { GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DOUBLEBUFFER,
+                     GLX_DEPTH_SIZE, 1,
+                     None };
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   GLXContext ctx;
+   XVisualInfo *visinfo;
+
+   scrnum = DefaultScreen( dpy );
+   root = RootWindow( dpy, scrnum );
+   
+   visinfo = glXChooseVisual( dpy, scrnum, attribs );
+   if (!visinfo) {
+     printf("Error: couldn't get an RGB, Double-buffered visual\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 | KeyPressMask;
+   attr.override_redirect = 0;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+   win = XCreateWindow( dpy, root, 0, 0, width, height,
+		        0, visinfo->depth, InputOutput,
+		        visinfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(dpy, win, &sizehints);
+      XSetStandardProperties(dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   XFree(visinfo);
+
+   *winRet = win;
+   *ctxRet = ctx;
+}
+
+
+static void
+event_loop(Display *dpy, Window win)
+{
+   while (1) {
+      while (XPending(dpy) > 0) {
+         XEvent event;
+         XNextEvent(dpy, &event);
+         switch (event.type) {
+	 case Expose:
+            /* we'll redraw below */
+	    break;
+	 case ConfigureNotify:
+	   Reshape(event.xconfigure.width, event.xconfigure.height);
+	    break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+	       r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+				 NULL, NULL);
+	       if (buffer[0] == 27) {
+		 /* escape */
+		 return;
+                 
+               }
+            }
+         }
+      }
+
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   Display *dpy;
+   Window win;
+   GLXContext ctx;
+   char *dpyName = NULL;
+   GLboolean printInfo = GL_FALSE;
+   int i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-display") == 0) {
+         dpyName = argv[i+1];
+         i++;
+      }
+      else if (strcmp(argv[i], "-info") == 0) {
+         printInfo = GL_TRUE;
+      }
+      else
+	 printf("Warrning: unknown parameter: %s\n", argv[i]);
+   }
+
+   dpy = XOpenDisplay(dpyName);
+   if (!dpy) {
+      printf("Error: couldn't open display %s\n",
+	     XDisplayName(dpyName));
+      return -1;
+   }
+
+   make_window(dpy, "yuvrect_client", 0, 0, 300, 300, &win, &ctx);
+   XMapWindow(dpy, win);
+   glXMakeCurrent(dpy, win, ctx);
+
+   if (printInfo) {
+      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));
+   }
+
+   Init(argc, argv, dpy, DefaultScreen(dpy), win);
+
+   scr_Display();			       
+   glXSwapBuffers(dpy, win);
+   event_loop(dpy, win);
+
+   glXFreeMemoryMESA(dpy, DefaultScreen(dpy), glx_memory);
+   glXDestroyContext(dpy, ctx);
+   XDestroyWindow(dpy, win);
+   XCloseDisplay(dpy);
+
+   return 0;
+}
