Copy of xlib driver. This will get trimmed down a lot for Gallium.
authorBrian <brian.paul@tungstengraphics.com>
Wed, 31 Oct 2007 20:19:09 +0000 (14:19 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Wed, 31 Oct 2007 20:19:09 +0000 (14:19 -0600)
19 files changed:
src/mesa/pipe/xlib/fakeglx.c [new file with mode: 0644]
src/mesa/pipe/xlib/glxapi.c [new file with mode: 0644]
src/mesa/pipe/xlib/glxapi.h [new file with mode: 0644]
src/mesa/pipe/xlib/glxheader.h [new file with mode: 0644]
src/mesa/pipe/xlib/realglx.c [new file with mode: 0644]
src/mesa/pipe/xlib/realglx.h [new file with mode: 0644]
src/mesa/pipe/xlib/xfonts.c [new file with mode: 0644]
src/mesa/pipe/xlib/xfonts.h [new file with mode: 0644]
src/mesa/pipe/xlib/xm_api.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_buffer.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_dd.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_image.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_image.h [new file with mode: 0644]
src/mesa/pipe/xlib/xm_line.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_span.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_surface.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_tri.c [new file with mode: 0644]
src/mesa/pipe/xlib/xm_winsys.c [new file with mode: 0644]
src/mesa/pipe/xlib/xmesaP.h [new file with mode: 0644]

diff --git a/src/mesa/pipe/xlib/fakeglx.c b/src/mesa/pipe/xlib/fakeglx.c
new file mode 100644 (file)
index 0000000..7a170b4
--- /dev/null
@@ -0,0 +1,3186 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * This is an emulation of the GLX API which allows Mesa/GLX-based programs
+ * to run on X servers which do not have the real GLX extension.
+ *
+ * Thanks to the contributors:
+ *
+ * Initial version:  Philip Brown (phil@bolthole.com)
+ * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
+ * Further visual-handling refinements: Wolfram Gloger
+ *    (wmglo@Dent.MED.Uni-Muenchen.DE).
+ *
+ * Notes:
+ *   Don't be fooled, stereo isn't supported yet.
+ */
+
+
+
+#include "glxheader.h"
+#include "glxapi.h"
+#include "GL/xmesa.h"
+#include "context.h"
+#include "config.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "version.h"
+#include "xfonts.h"
+#include "xmesaP.h"
+
+#ifdef __VMS
+#define _mesa_sprintf sprintf
+#endif
+
+/* This indicates the client-side GLX API and GLX encoder version. */
+#define CLIENT_MAJOR_VERSION 1
+#define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
+
+/* This indicates the server-side GLX decoder version.
+ * GLX 1.4 indicates OpenGL 1.3 support
+ */
+#define SERVER_MAJOR_VERSION 1
+#define SERVER_MINOR_VERSION 4
+
+/* This is appended onto the glXGetClient/ServerString version strings. */
+#define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING
+
+/* Who implemented this GLX? */
+#define VENDOR "Brian Paul"
+
+#define EXTENSIONS \
+   "GLX_MESA_set_3dfx_mode " \
+   "GLX_MESA_copy_sub_buffer " \
+   "GLX_MESA_pixmap_colormap " \
+   "GLX_MESA_release_buffers " \
+   "GLX_ARB_get_proc_address " \
+   "GLX_EXT_texture_from_pixmap " \
+   "GLX_EXT_visual_info " \
+   "GLX_EXT_visual_rating " \
+   /*"GLX_SGI_video_sync "*/ \
+   "GLX_SGIX_fbconfig " \
+   "GLX_SGIX_pbuffer "
+
+/*
+ * Our fake GLX context will contain a "real" GLX context and an XMesa context.
+ *
+ * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context,
+ * and vice versa.
+ *
+ * We really just need this structure in order to make the libGL functions
+ * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay()
+ * work correctly.
+ */
+struct fake_glx_context {
+   __GLXcontext glxContext;   /* this MUST be first! */
+   XMesaContext xmesaContext;
+};
+
+
+
+/**********************************************************************/
+/***                       GLX Visual Code                          ***/
+/**********************************************************************/
+
+#define DONT_CARE -1
+
+
+static XMesaVisual *VisualTable = NULL;
+static int NumVisuals = 0;
+
+
+/*
+ * This struct and some code fragments borrowed
+ * from Mark Kilgard's GLUT library.
+ */
+typedef struct _OverlayInfo {
+  /* Avoid 64-bit portability problems by being careful to use
+     longs due to the way XGetWindowProperty is specified. Note
+     that these parameters are passed as CARD32s over X
+     protocol. */
+  unsigned long overlay_visual;
+  long transparent_type;
+  long value;
+  long layer;
+} OverlayInfo;
+
+
+
+/* Macro to handle c_class vs class field name in XVisualInfo struct */
+#if defined(__cplusplus) || defined(c_plusplus)
+#define CLASS c_class
+#else
+#define CLASS class
+#endif
+
+
+
+/*
+ * Test if the given XVisualInfo is usable for Mesa rendering.
+ */
+static GLboolean
+is_usable_visual( XVisualInfo *vinfo )
+{
+   switch (vinfo->CLASS) {
+      case StaticGray:
+      case GrayScale:
+         /* Any StaticGray/GrayScale visual works in RGB or CI mode */
+         return GL_TRUE;
+      case StaticColor:
+      case PseudoColor:
+        /* Any StaticColor/PseudoColor visual of at least 4 bits */
+        if (vinfo->depth>=4) {
+           return GL_TRUE;
+        }
+        else {
+           return GL_FALSE;
+        }
+      case TrueColor:
+      case DirectColor:
+        /* Any depth of TrueColor or DirectColor works in RGB mode */
+        return GL_TRUE;
+      default:
+        /* This should never happen */
+        return GL_FALSE;
+   }
+}
+
+
+
+/**
+ * Get an array OverlayInfo records for specified screen.
+ * \param dpy  the display
+ * \param screen  screen number
+ * \param numOverlays  returns numver of OverlayInfo records
+ * \return  pointer to OverlayInfo array, free with XFree()
+ */
+static OverlayInfo *
+GetOverlayInfo(Display *dpy, int screen, int *numOverlays)
+{
+   Atom overlayVisualsAtom;
+   Atom actualType;
+   Status status;
+   unsigned char *ovInfo;
+   unsigned long sizeData, bytesLeft;
+   int actualFormat;
+
+   /*
+    * The SERVER_OVERLAY_VISUALS property on the root window contains
+    * a list of overlay visuals.  Get that list now.
+    */
+   overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+   if (overlayVisualsAtom == None) {
+      return 0;
+   }
+
+   status = XGetWindowProperty(dpy, RootWindow(dpy, screen),
+                               overlayVisualsAtom, 0L, (long) 10000, False,
+                               overlayVisualsAtom, &actualType, &actualFormat,
+                               &sizeData, &bytesLeft,
+                               &ovInfo);
+
+   if (status != Success || actualType != overlayVisualsAtom ||
+       actualFormat != 32 || sizeData < 4) {
+      /* something went wrong */
+      XFree((void *) ovInfo);
+      *numOverlays = 0;
+      return NULL;
+   }
+
+   *numOverlays = sizeData / 4;
+   return (OverlayInfo *) ovInfo;
+}
+
+
+
+/**
+ * Return the level (overlay, normal, underlay) of a given XVisualInfo.
+ * Input:  dpy - the X display
+ *         vinfo - the XVisualInfo to test
+ * Return:  level of the visual:
+ *             0 = normal planes
+ *            >0 = overlay planes
+ *            <0 = underlay planes
+ */
+static int
+level_of_visual( Display *dpy, XVisualInfo *vinfo )
+{
+   OverlayInfo *overlay_info;
+   int numOverlaysPerScreen, i;
+
+   overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen);
+   if (!overlay_info) {
+      return 0;
+   }
+
+   /* search the overlay visual list for the visual ID of interest */
+   for (i = 0; i < numOverlaysPerScreen; i++) {
+      const OverlayInfo *ov = overlay_info + i;
+      if (ov->overlay_visual == vinfo->visualid) {
+         /* found the visual */
+         if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
+            int level = ov->layer;
+            XFree((void *) overlay_info);
+            return level;
+         }
+         else {
+            XFree((void *) overlay_info);
+            return 0;
+         }
+      }
+   }
+
+   /* The visual ID was not found in the overlay list. */
+   XFree((void *) overlay_info);
+   return 0;
+}
+
+
+
+
+/*
+ * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
+ * configuration in our list of GLX visuals.
+ */
+static XMesaVisual
+save_glx_visual( Display *dpy, XVisualInfo *vinfo,
+                 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
+                 GLboolean stereoFlag,
+                 GLint depth_size, GLint stencil_size,
+                 GLint accumRedSize, GLint accumGreenSize,
+                 GLint accumBlueSize, GLint accumAlphaSize,
+                 GLint level, GLint numAuxBuffers )
+{
+   GLboolean ximageFlag = GL_TRUE;
+   XMesaVisual xmvis;
+   GLint i;
+   GLboolean comparePointers;
+
+   if (dbFlag) {
+      /* Check if the MESA_BACK_BUFFER env var is set */
+      char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
+      if (backbuffer) {
+         if (backbuffer[0]=='p' || backbuffer[0]=='P') {
+            ximageFlag = GL_FALSE;
+         }
+         else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
+            ximageFlag = GL_TRUE;
+         }
+         else {
+            _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
+         }
+      }
+   }
+
+   if (stereoFlag) {
+      /* stereo not supported */
+      return NULL;
+   }
+
+   /* Comparing IDs uses less memory but sometimes fails. */
+   /* XXX revisit this after 3.0 is finished. */
+   if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
+      comparePointers = GL_TRUE;
+   else
+      comparePointers = GL_FALSE;
+
+   /* Force the visual to have an alpha channel */
+   if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA"))
+      alphaFlag = GL_TRUE;
+
+   /* First check if a matching visual is already in the list */
+   for (i=0; i<NumVisuals; i++) {
+      XMesaVisual v = VisualTable[i];
+      if (v->display == dpy
+          && v->mesa_visual.level == level
+          && v->mesa_visual.numAuxBuffers == numAuxBuffers
+          && v->ximage_flag == ximageFlag
+          && v->mesa_visual.rgbMode == rgbFlag
+          && v->mesa_visual.doubleBufferMode == dbFlag
+          && v->mesa_visual.stereoMode == stereoFlag
+          && (v->mesa_visual.alphaBits > 0) == alphaFlag
+          && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
+          && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
+          && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
+          && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
+          && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
+          && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
+         /* now either compare XVisualInfo pointers or visual IDs */
+         if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
+             || (comparePointers && v->vishandle == vinfo)) {
+            return v;
+         }
+      }
+   }
+
+   /* Create a new visual and add it to the list. */
+
+   xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
+                              stereoFlag, ximageFlag,
+                              depth_size, stencil_size,
+                              accumRedSize, accumBlueSize,
+                              accumBlueSize, accumAlphaSize, 0, level,
+                              GLX_NONE_EXT );
+   if (xmvis) {
+      /* Save a copy of the pointer now so we can find this visual again
+       * if we need to search for it in find_glx_visual().
+       */
+      xmvis->vishandle = vinfo;
+      /* Allocate more space for additional visual */
+      VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, 
+                                   sizeof(XMesaVisual) * NumVisuals, 
+                                   sizeof(XMesaVisual) * (NumVisuals + 1));
+      /* add xmvis to the list */
+      VisualTable[NumVisuals] = xmvis;
+      NumVisuals++;
+      /* XXX minor hack, because XMesaCreateVisual doesn't support an
+       * aux buffers parameter.
+       */
+      xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
+   }
+   return xmvis;
+}
+
+
+/**
+ * Return the default number of bits for the Z buffer.
+ * If defined, use the MESA_GLX_DEPTH_BITS env var value.
+ * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
+ * XXX probably do the same thing for stencil, accum, etc.
+ */
+static GLint
+default_depth_bits(void)
+{
+   int zBits;
+   const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
+   if (zEnv)
+      zBits = _mesa_atoi(zEnv);
+   else
+      zBits = DEFAULT_SOFTWARE_DEPTH_BITS;
+   return zBits;
+}
+
+static GLint
+default_alpha_bits(void)
+{
+   int aBits;
+   const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
+   if (aEnv)
+      aBits = _mesa_atoi(aEnv);
+   else
+      aBits = 0;
+   return aBits;
+}
+
+static GLint
+default_accum_bits(void)
+{
+   return 16;
+}
+
+
+
+/*
+ * Create a GLX visual from a regular XVisualInfo.
+ * This is called when Fake GLX is given an XVisualInfo which wasn't
+ * returned by glXChooseVisual.  Since this is the first time we're
+ * considering this visual we'll take a guess at reasonable values
+ * for depth buffer size, stencil size, accum size, etc.
+ * This is the best we can do with a client-side emulation of GLX.
+ */
+static XMesaVisual
+create_glx_visual( Display *dpy, XVisualInfo *visinfo )
+{
+   int vislevel;
+   GLint zBits = default_depth_bits();
+   GLint accBits = default_accum_bits();
+   GLboolean alphaFlag = default_alpha_bits() > 0;
+
+   vislevel = level_of_visual( dpy, visinfo );
+   if (vislevel) {
+      /* Configure this visual as a CI, single-buffered overlay */
+      return save_glx_visual( dpy, visinfo,
+                              GL_FALSE,  /* rgb */
+                              GL_FALSE,  /* alpha */
+                              GL_FALSE,  /* double */
+                              GL_FALSE,  /* stereo */
+                              0,         /* depth bits */
+                              0,         /* stencil bits */
+                              0,0,0,0,   /* accum bits */
+                              vislevel,  /* level */
+                              0          /* numAux */
+                            );
+   }
+   else if (is_usable_visual( visinfo )) {
+      if (_mesa_getenv("MESA_GLX_FORCE_CI")) {
+         /* Configure this visual as a COLOR INDEX visual. */
+         return save_glx_visual( dpy, visinfo,
+                                 GL_FALSE,   /* rgb */
+                                 GL_FALSE,  /* alpha */
+                                 GL_TRUE,   /* double */
+                                 GL_FALSE,  /* stereo */
+                                 zBits,
+                                 STENCIL_BITS,
+                                 0, 0, 0, 0, /* accum bits */
+                                 0,         /* level */
+                                 0          /* numAux */
+                               );
+      }
+      else {
+         /* Configure this visual as RGB, double-buffered, depth-buffered. */
+         /* This is surely wrong for some people's needs but what else */
+         /* can be done?  They should use glXChooseVisual(). */
+         return save_glx_visual( dpy, visinfo,
+                                 GL_TRUE,   /* rgb */
+                                 alphaFlag, /* alpha */
+                                 GL_TRUE,   /* double */
+                                 GL_FALSE,  /* stereo */
+                                 zBits,
+                                 STENCIL_BITS,
+                                 accBits, /* r */
+                                 accBits, /* g */
+                                 accBits, /* b */
+                                 accBits, /* a */
+                                 0,         /* level */
+                                 0          /* numAux */
+                               );
+      }
+   }
+   else {
+      _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
+      return NULL;
+   }
+}
+
+
+
+/*
+ * Find the GLX visual associated with an XVisualInfo.
+ */
+static XMesaVisual
+find_glx_visual( Display *dpy, XVisualInfo *vinfo )
+{
+   int i;
+
+   /* try to match visual id */
+   for (i=0;i<NumVisuals;i++) {
+      if (VisualTable[i]->display==dpy
+          && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
+         return VisualTable[i];
+      }
+   }
+
+   /* if that fails, try to match pointers */
+   for (i=0;i<NumVisuals;i++) {
+      if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
+         return VisualTable[i];
+      }
+   }
+
+   return NULL;
+}
+
+
+
+/**
+ * Return the transparent pixel value for a GLX visual.
+ * Input:  glxvis - the glx_visual
+ * Return:  a pixel value or -1 if no transparent pixel
+ */
+static int
+transparent_pixel( XMesaVisual glxvis )
+{
+   Display *dpy = glxvis->display;
+   XVisualInfo *vinfo = glxvis->visinfo;
+   OverlayInfo *overlay_info;
+   int numOverlaysPerScreen, i;
+
+   overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen);
+   if (!overlay_info) {
+      return -1;
+   }
+
+   for (i = 0; i < numOverlaysPerScreen; i++) {
+      const OverlayInfo *ov = overlay_info + i;
+      if (ov->overlay_visual == vinfo->visualid) {
+         /* found it! */
+         if (ov->transparent_type == 0) {
+            /* type 0 indicates no transparency */
+            XFree((void *) overlay_info);
+            return -1;
+         }
+         else {
+            /* ov->value is the transparent pixel */
+            XFree((void *) overlay_info);
+            return ov->value;
+         }
+      }
+   }
+
+   /* The visual ID was not found in the overlay list. */
+   XFree((void *) overlay_info);
+   return -1;
+}
+
+
+
+/**
+ * Try to get an X visual which matches the given arguments.
+ */
+static XVisualInfo *
+get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
+{
+   XVisualInfo temp, *vis;
+   long mask;
+   int n;
+   unsigned int default_depth;
+   int default_class;
+
+   mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+   temp.screen = scr;
+   temp.depth = depth;
+   temp.CLASS = xclass;
+
+   default_depth = DefaultDepth(dpy,scr);
+   default_class = DefaultVisual(dpy,scr)->CLASS;
+
+   if (depth==default_depth && xclass==default_class) {
+      /* try to get root window's visual */
+      temp.visualid = DefaultVisual(dpy,scr)->visualid;
+      mask |= VisualIDMask;
+   }
+
+   vis = XGetVisualInfo( dpy, mask, &temp, &n );
+
+   /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
+    * An SGI Infinite Reality system, for example, can have 30bpp pixels:
+    * 10 bits per color channel.  Mesa's limited to a max of 8 bits/channel.
+    */
+   if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
+      if (_mesa_bitcount((GLuint) vis->red_mask  ) <= 8 &&
+          _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
+          _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
+         return vis;
+      }
+      else {
+         XFree((void *) vis);
+         return NULL;
+      }
+   }
+
+   return vis;
+}
+
+
+
+/*
+ * Retrieve the value of the given environment variable and find
+ * the X visual which matches it.
+ * Input:  dpy - the display
+ *         screen - the screen number
+ *         varname - the name of the environment variable
+ * Return:  an XVisualInfo pointer to NULL if error.
+ */
+static XVisualInfo *
+get_env_visual(Display *dpy, int scr, const char *varname)
+{
+   char value[100], type[100];
+   int depth, xclass = -1;
+   XVisualInfo *vis;
+
+   if (!_mesa_getenv( varname )) {
+      return NULL;
+   }
+
+   _mesa_strncpy( value, _mesa_getenv(varname), 100 );
+   value[99] = 0;
+
+   sscanf( value, "%s %d", type, &depth );
+
+   if (_mesa_strcmp(type,"TrueColor")==0)          xclass = TrueColor;
+   else if (_mesa_strcmp(type,"DirectColor")==0)   xclass = DirectColor;
+   else if (_mesa_strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
+   else if (_mesa_strcmp(type,"StaticColor")==0)   xclass = StaticColor;
+   else if (_mesa_strcmp(type,"GrayScale")==0)     xclass = GrayScale;
+   else if (_mesa_strcmp(type,"StaticGray")==0)    xclass = StaticGray;
+
+   if (xclass>-1 && depth>0) {
+      vis = get_visual( dpy, scr, depth, xclass );
+      if (vis) {
+        return vis;
+      }
+   }
+
+   _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
+                 type, depth);
+
+   return NULL;
+}
+
+
+
+/*
+ * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
+ * Input:  dpy, screen - X display and screen number
+ *         rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
+ *         min_depth - minimum visual depth
+ *         preferred_class - preferred GLX visual class or DONT_CARE
+ * Return:  pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *
+choose_x_visual( Display *dpy, int screen, GLboolean rgba, int min_depth,
+                 int preferred_class )
+{
+   XVisualInfo *vis;
+   int xclass, visclass = 0;
+   int depth;
+
+   if (rgba) {
+      Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
+      /* First see if the MESA_RGB_VISUAL env var is defined */
+      vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
+      if (vis) {
+        return vis;
+      }
+      /* Otherwise, search for a suitable visual */
+      if (preferred_class==DONT_CARE) {
+         for (xclass=0;xclass<6;xclass++) {
+            switch (xclass) {
+               case 0:  visclass = TrueColor;    break;
+               case 1:  visclass = DirectColor;  break;
+               case 2:  visclass = PseudoColor;  break;
+               case 3:  visclass = StaticColor;  break;
+               case 4:  visclass = GrayScale;    break;
+               case 5:  visclass = StaticGray;   break;
+            }
+            if (min_depth==0) {
+               /* start with shallowest */
+               for (depth=0;depth<=32;depth++) {
+                  if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+                     /* Special case:  try to get 8-bit PseudoColor before */
+                     /* 8-bit TrueColor */
+                     vis = get_visual( dpy, screen, 8, PseudoColor );
+                     if (vis) {
+                        return vis;
+                     }
+                  }
+                  vis = get_visual( dpy, screen, depth, visclass );
+                  if (vis) {
+                     return vis;
+                  }
+               }
+            }
+            else {
+               /* start with deepest */
+               for (depth=32;depth>=min_depth;depth--) {
+                  if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+                     /* Special case:  try to get 8-bit PseudoColor before */
+                     /* 8-bit TrueColor */
+                     vis = get_visual( dpy, screen, 8, PseudoColor );
+                     if (vis) {
+                        return vis;
+                     }
+                  }
+                  vis = get_visual( dpy, screen, depth, visclass );
+                  if (vis) {
+                     return vis;
+                  }
+               }
+            }
+         }
+      }
+      else {
+         /* search for a specific visual class */
+         switch (preferred_class) {
+            case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
+            case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
+            case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
+            case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
+            case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
+            case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
+            default:   return NULL;
+         }
+         if (min_depth==0) {
+            /* start with shallowest */
+            for (depth=0;depth<=32;depth++) {
+               vis = get_visual( dpy, screen, depth, visclass );
+               if (vis) {
+                  return vis;
+               }
+            }
+         }
+         else {
+            /* start with deepest */
+            for (depth=32;depth>=min_depth;depth--) {
+               vis = get_visual( dpy, screen, depth, visclass );
+               if (vis) {
+                  return vis;
+               }
+            }
+         }
+      }
+   }
+   else {
+      /* First see if the MESA_CI_VISUAL env var is defined */
+      vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
+      if (vis) {
+        return vis;
+      }
+      /* Otherwise, search for a suitable visual, starting with shallowest */
+      if (preferred_class==DONT_CARE) {
+         for (xclass=0;xclass<4;xclass++) {
+            switch (xclass) {
+               case 0:  visclass = PseudoColor;  break;
+               case 1:  visclass = StaticColor;  break;
+               case 2:  visclass = GrayScale;    break;
+               case 3:  visclass = StaticGray;   break;
+            }
+            /* try 8-bit up through 16-bit */
+            for (depth=8;depth<=16;depth++) {
+               vis = get_visual( dpy, screen, depth, visclass );
+               if (vis) {
+                  return vis;
+               }
+            }
+            /* try min_depth up to 8-bit */
+            for (depth=min_depth;depth<8;depth++) {
+               vis = get_visual( dpy, screen, depth, visclass );
+               if (vis) {
+                  return vis;
+               }
+            }
+         }
+      }
+      else {
+         /* search for a specific visual class */
+         switch (preferred_class) {
+            case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
+            case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
+            case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
+            case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
+            case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
+            case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
+            default:   return NULL;
+         }
+         /* try 8-bit up through 16-bit */
+         for (depth=8;depth<=16;depth++) {
+            vis = get_visual( dpy, screen, depth, visclass );
+            if (vis) {
+               return vis;
+            }
+         }
+         /* try min_depth up to 8-bit */
+         for (depth=min_depth;depth<8;depth++) {
+            vis = get_visual( dpy, screen, depth, visclass );
+            if (vis) {
+               return vis;
+            }
+         }
+      }
+   }
+
+   /* didn't find a visual */
+   return NULL;
+}
+
+
+
+/*
+ * Find the deepest X over/underlay visual of at least min_depth.
+ * Input:  dpy, screen - X display and screen number
+ *         level - the over/underlay level
+ *         trans_type - transparent pixel type: GLX_NONE_EXT,
+ *                      GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
+ *                      or DONT_CARE
+ *         trans_value - transparent pixel value or DONT_CARE
+ *         min_depth - minimum visual depth
+ *         preferred_class - preferred GLX visual class or DONT_CARE
+ * Return:  pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *
+choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
+                         int level, int trans_type, int trans_value,
+                         int min_depth, int preferred_class )
+{
+   OverlayInfo *overlay_info;
+   int numOverlaysPerScreen;
+   int i;
+   XVisualInfo *deepvis;
+   int deepest;
+
+   /*DEBUG int tt, tv; */
+
+   switch (preferred_class) {
+      case GLX_TRUE_COLOR_EXT:    preferred_class = TrueColor;    break;
+      case GLX_DIRECT_COLOR_EXT:  preferred_class = DirectColor;  break;
+      case GLX_PSEUDO_COLOR_EXT:  preferred_class = PseudoColor;  break;
+      case GLX_STATIC_COLOR_EXT:  preferred_class = StaticColor;  break;
+      case GLX_GRAY_SCALE_EXT:    preferred_class = GrayScale;    break;
+      case GLX_STATIC_GRAY_EXT:   preferred_class = StaticGray;   break;
+      default:                    preferred_class = DONT_CARE;
+   }
+
+   overlay_info = GetOverlayInfo(dpy, scr, &numOverlaysPerScreen);
+   if (!overlay_info) {
+      return NULL;
+   }
+
+   /* Search for the deepest overlay which satisifies all criteria. */
+   deepest = min_depth;
+   deepvis = NULL;
+
+   for (i = 0; i < numOverlaysPerScreen; i++) {
+      const OverlayInfo *ov = overlay_info + i;
+      XVisualInfo *vislist, vistemplate;
+      int count;
+
+      if (ov->layer!=level) {
+         /* failed overlay level criteria */
+         continue;
+      }
+      if (!(trans_type==DONT_CARE
+            || (trans_type==GLX_TRANSPARENT_INDEX_EXT
+                && ov->transparent_type>0)
+            || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
+         /* failed transparent pixel type criteria */
+         continue;
+      }
+      if (trans_value!=DONT_CARE && trans_value!=ov->value) {
+         /* failed transparent pixel value criteria */
+         continue;
+      }
+
+      /* get XVisualInfo and check the depth */
+      vistemplate.visualid = ov->overlay_visual;
+      vistemplate.screen = scr;
+      vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
+                                &vistemplate, &count );
+
+      if (count!=1) {
+         /* something went wrong */
+         continue;
+      }
+      if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
+         /* wrong visual class */
+         continue;
+      }
+
+      /* if RGB was requested, make sure we have True/DirectColor */
+      if (rgbFlag && vislist->CLASS != TrueColor
+          && vislist->CLASS != DirectColor)
+         continue;
+
+      /* if CI was requested, make sure we have a color indexed visual */
+      if (!rgbFlag
+          && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor))
+         continue;
+
+      if (deepvis==NULL || vislist->depth > deepest) {
+         /* YES!  found a satisfactory visual */
+         if (deepvis) {
+            XFree( deepvis );
+         }
+         deepest = vislist->depth;
+         deepvis = vislist;
+         /* DEBUG  tt = ov->transparent_type;*/
+         /* DEBUG  tv = ov->value; */
+      }
+   }
+
+/*DEBUG
+   if (deepvis) {
+      printf("chose 0x%x:  layer=%d depth=%d trans_type=%d trans_value=%d\n",
+             deepvis->visualid, level, deepvis->depth, tt, tv );
+   }
+*/
+   return deepvis;
+}
+
+
+/**********************************************************************/
+/***             Display-related functions                          ***/
+/**********************************************************************/
+
+
+/**
+ * Free all XMesaVisuals which are associated with the given display.
+ */
+static void
+destroy_visuals_on_display(Display *dpy)
+{
+   int i;
+   for (i = 0; i < NumVisuals; i++) {
+      if (VisualTable[i]->display == dpy) {
+         /* remove this visual */
+         int j;
+         free(VisualTable[i]);
+         for (j = i; j < NumVisuals - 1; j++)
+            VisualTable[j] = VisualTable[j + 1];
+         NumVisuals--;
+      }
+   }
+}
+
+
+/**
+ * Called from XCloseDisplay() to let us free our display-related data.
+ */
+static int
+close_display_callback(Display *dpy, XExtCodes *codes)
+{
+   destroy_visuals_on_display(dpy);
+   xmesa_destroy_buffers_on_display(dpy);
+   return 0;
+}
+
+
+/**
+ * Look for the named extension on given display and return a pointer
+ * to the _XExtension data, or NULL if extension not found.
+ */
+static _XExtension *
+lookup_extension(Display *dpy, const char *extName)
+{
+   _XExtension *ext;
+   for (ext = dpy->ext_procs; ext; ext = ext->next) {
+      if (ext->name && strcmp(ext->name, extName) == 0) {
+         return ext;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Whenever we're given a new Display pointer, call this function to
+ * register our close_display_callback function.
+ */
+static void
+register_with_display(Display *dpy)
+{
+   const char *extName = "MesaGLX";
+   _XExtension *ext;
+
+   ext = lookup_extension(dpy, extName);
+   if (!ext) {
+      XExtCodes *c = XAddExtension(dpy);
+      ext = dpy->ext_procs;  /* new extension is at head of list */
+      assert(c->extension == ext->codes.extension);
+      ext->name = _mesa_strdup(extName);
+      ext->close_display = close_display_callback;
+   }
+}
+
+
+/**********************************************************************/
+/***                  Begin Fake GLX API Functions                  ***/
+/**********************************************************************/
+
+
+/**
+ * Helper used by glXChooseVisual and glXChooseFBConfig.
+ * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for
+ * the later.
+ * In either case, the attribute list is terminated with the value 'None'.
+ */
+static XMesaVisual
+choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
+{
+   const GLboolean rgbModeDefault = fbConfig;
+   const int *parselist;
+   XVisualInfo *vis;
+   int min_ci = 0;
+   int min_red=0, min_green=0, min_blue=0;
+   GLboolean rgb_flag = rgbModeDefault;
+   GLboolean alpha_flag = GL_FALSE;
+   GLboolean double_flag = GL_FALSE;
+   GLboolean stereo_flag = GL_FALSE;
+   GLint depth_size = 0;
+   GLint stencil_size = 0;
+   GLint accumRedSize = 0;
+   GLint accumGreenSize = 0;
+   GLint accumBlueSize = 0;
+   GLint accumAlphaSize = 0;
+   int level = 0;
+   int visual_type = DONT_CARE;
+   int trans_type = DONT_CARE;
+   int trans_value = DONT_CARE;
+   GLint caveat = DONT_CARE;
+   XMesaVisual xmvis = NULL;
+   int desiredVisualID = -1;
+   int numAux = 0;
+
+   parselist = list;
+
+   while (*parselist) {
+
+      switch (*parselist) {
+        case GLX_USE_GL:
+            if (fbConfig) {
+               /* invalid token */
+               return NULL;
+            }
+            else {
+               /* skip */
+               parselist++;
+            }
+           break;
+        case GLX_BUFFER_SIZE:
+           parselist++;
+           min_ci = *parselist++;
+           break;
+        case GLX_LEVEL:
+           parselist++;
+            level = *parselist++;
+           break;
+        case GLX_RGBA:
+            if (fbConfig) {
+               /* invalid token */
+               return NULL;
+            }
+            else {
+               rgb_flag = GL_TRUE;
+               parselist++;
+            }
+           break;
+        case GLX_DOUBLEBUFFER:
+            parselist++;
+            if (fbConfig) {
+               double_flag = *parselist++;
+            }
+            else {
+               double_flag = GL_TRUE;
+            }
+           break;
+        case GLX_STEREO:
+            parselist++;
+            if (fbConfig) {
+               stereo_flag = *parselist++;
+            }
+            else {
+               stereo_flag = GL_TRUE;
+            }
+            break;
+        case GLX_AUX_BUFFERS:
+           parselist++;
+            numAux = *parselist++;
+            if (numAux > MAX_AUX_BUFFERS)
+               return NULL;
+           break;
+        case GLX_RED_SIZE:
+           parselist++;
+           min_red = *parselist++;
+           break;
+        case GLX_GREEN_SIZE:
+           parselist++;
+           min_green = *parselist++;
+           break;
+        case GLX_BLUE_SIZE:
+           parselist++;
+           min_blue = *parselist++;
+           break;
+        case GLX_ALPHA_SIZE:
+           parselist++;
+            {
+               GLint size = *parselist++;
+               alpha_flag = size ? GL_TRUE : GL_FALSE;
+            }
+           break;
+        case GLX_DEPTH_SIZE:
+           parselist++;
+           depth_size = *parselist++;
+           break;
+        case GLX_STENCIL_SIZE:
+           parselist++;
+           stencil_size = *parselist++;
+           break;
+        case GLX_ACCUM_RED_SIZE:
+           parselist++;
+            {
+               GLint size = *parselist++;
+               accumRedSize = MAX2( accumRedSize, size );
+            }
+            break;
+        case GLX_ACCUM_GREEN_SIZE:
+           parselist++;
+            {
+               GLint size = *parselist++;
+               accumGreenSize = MAX2( accumGreenSize, size );
+            }
+            break;
+        case GLX_ACCUM_BLUE_SIZE:
+           parselist++;
+            {
+               GLint size = *parselist++;
+               accumBlueSize = MAX2( accumBlueSize, size );
+            }
+            break;
+        case GLX_ACCUM_ALPHA_SIZE:
+           parselist++;
+            {
+               GLint size = *parselist++;
+               accumAlphaSize = MAX2( accumAlphaSize, size );
+            }
+           break;
+
+         /*
+          * GLX_EXT_visual_info extension
+          */
+         case GLX_X_VISUAL_TYPE_EXT:
+            parselist++;
+            visual_type = *parselist++;
+            break;
+         case GLX_TRANSPARENT_TYPE_EXT:
+            parselist++;
+            trans_type = *parselist++;
+            break;
+         case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+            parselist++;
+            trans_value = *parselist++;
+            break;
+         case GLX_TRANSPARENT_RED_VALUE_EXT:
+         case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+         case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+         case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+           /* ignore */
+           parselist++;
+           parselist++;
+           break;
+
+         /*
+          * GLX_EXT_visual_info extension
+          */
+         case GLX_VISUAL_CAVEAT_EXT:
+            parselist++;
+            caveat = *parselist++; /* ignored for now */
+            break;
+
+         /*
+          * GLX_ARB_multisample
+          */
+         case GLX_SAMPLE_BUFFERS_ARB:
+            /* ms not supported */
+            return NULL;
+         case GLX_SAMPLES_ARB:
+            /* ms not supported */
+            return NULL;
+
+         /*
+          * FBConfig attribs.
+          */
+         case GLX_RENDER_TYPE:
+            if (!fbConfig)
+               return NULL;
+            parselist++;
+            if (*parselist == GLX_RGBA_BIT) {
+               rgb_flag = GL_TRUE;
+            }
+            else if (*parselist == GLX_COLOR_INDEX_BIT) {
+               rgb_flag = GL_FALSE;
+            }
+            else if (*parselist == 0) {
+               rgb_flag = GL_TRUE;
+            }
+            parselist++;
+            break;
+         case GLX_DRAWABLE_TYPE:
+            if (!fbConfig)
+               return NULL;
+            parselist++;
+            if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
+               return NULL; /* bad bit */
+            }
+            parselist++;
+            break;
+         case GLX_FBCONFIG_ID:
+            if (!fbConfig)
+               return NULL;
+            parselist++;
+            desiredVisualID = *parselist++;
+            break;
+         case GLX_X_RENDERABLE:
+            if (!fbConfig)
+               return NULL;
+            parselist += 2;
+            /* ignore */
+            break;
+
+#ifdef GLX_EXT_texture_from_pixmap
+         case GLX_BIND_TO_TEXTURE_RGB_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+            parselist++;
+            if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
+                               GLX_TEXTURE_2D_BIT_EXT |
+                               GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
+               /* invalid bit */
+               return NULL;
+            }
+            break;
+         case GLX_Y_INVERTED_EXT:
+            parselist++; /*skip*/
+            break;
+#endif
+
+        case None:
+            /* end of list */
+           break;
+
+        default:
+           /* undefined attribute */
+            _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
+                          *parselist);
+           return NULL;
+      }
+   }
+
+   (void) caveat;
+
+   /*
+    * Since we're only simulating the GLX extension this function will never
+    * find any real GL visuals.  Instead, all we can do is try to find an RGB
+    * or CI visual of appropriate depth.  Other requested attributes such as
+    * double buffering, depth buffer, etc. will be associated with the X
+    * visual and stored in the VisualTable[].
+    */
+   if (desiredVisualID != -1) {
+      /* try to get a specific visual, by visualID */
+      XVisualInfo temp;
+      int n;
+      temp.visualid = desiredVisualID;
+      temp.screen = screen;
+      vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
+      if (vis) {
+         /* give the visual some useful GLX attributes */
+         double_flag = GL_TRUE;
+         if (vis->depth > 8)
+            rgb_flag = GL_TRUE;
+         depth_size = default_depth_bits();
+         stencil_size = STENCIL_BITS;
+         /* XXX accum??? */
+      }
+   }
+   else if (level==0) {
+      /* normal color planes */
+      if (rgb_flag) {
+         /* Get an RGB visual */
+         int min_rgb = min_red + min_green + min_blue;
+         if (min_rgb>1 && min_rgb<8) {
+            /* a special case to be sure we can get a monochrome visual */
+            min_rgb = 1;
+         }
+         vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
+      }
+      else {
+         /* Get a color index visual */
+         vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
+         accumRedSize = accumGreenSize = accumBlueSize = accumAlphaSize = 0;
+      }
+   }
+   else {
+      /* over/underlay planes */
+      if (rgb_flag) {
+         /* rgba overlay */
+         int min_rgb = min_red + min_green + min_blue;
+         if (min_rgb>1 && min_rgb<8) {
+            /* a special case to be sure we can get a monochrome visual */
+            min_rgb = 1;
+         }
+         vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
+                              trans_type, trans_value, min_rgb, visual_type );
+      }
+      else {
+         /* color index overlay */
+         vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
+                              trans_type, trans_value, min_ci, visual_type );
+      }
+   }
+
+   if (vis) {
+      /* Note: we're not exactly obeying the glXChooseVisual rules here.
+       * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
+       * largest depth buffer size, which is 32bits/value.  Instead, we
+       * return 16 to maintain performance with earlier versions of Mesa.
+       */
+      if (depth_size > 24)
+         depth_size = 32;
+      else if (depth_size > 16)
+         depth_size = 24;
+      else if (depth_size > 0) {
+         depth_size = default_depth_bits();
+      }
+
+      if (!alpha_flag) {
+         alpha_flag = default_alpha_bits() > 0;
+      }
+
+      /* we only support one size of stencil and accum buffers. */
+      if (stencil_size > 0)
+         stencil_size = STENCIL_BITS;
+      if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 ||
+          accumAlphaSize > 0) {
+         accumRedSize = 
+         accumGreenSize = 
+         accumBlueSize = default_accum_bits();
+         accumAlphaSize = alpha_flag ? accumRedSize : 0;
+      }
+
+      xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
+                               stereo_flag, depth_size, stencil_size,
+                               accumRedSize, accumGreenSize,
+                               accumBlueSize, accumAlphaSize, level, numAux );
+   }
+
+   return xmvis;
+}
+
+
+static XVisualInfo *
+Fake_glXChooseVisual( Display *dpy, int screen, int *list )
+{
+   XMesaVisual xmvis;
+
+   /* register ourselves as an extension on this display */
+   register_with_display(dpy);
+
+   xmvis = choose_visual(dpy, screen, list, GL_FALSE);
+   if (xmvis) {
+#if 0
+      return xmvis->vishandle;
+#else
+      /* create a new vishandle - the cached one may be stale */
+      xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+      if (xmvis->vishandle) {
+         _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+      }
+      return xmvis->vishandle;
+#endif
+   }
+   else
+      return NULL;
+}
+
+
+static GLXContext
+Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+                       GLXContext share_list, Bool direct )
+{
+   XMesaVisual xmvis;
+   struct fake_glx_context *glxCtx;
+   struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
+
+   if (!dpy || !visinfo)
+      return 0;
+
+   glxCtx = CALLOC_STRUCT(fake_glx_context);
+   if (!glxCtx)
+      return 0;
+
+   /* deallocate unused windows/buffers */
+#if 0
+   XMesaGarbageCollect();
+#endif
+
+   xmvis = find_glx_visual( dpy, visinfo );
+   if (!xmvis) {
+      /* This visual wasn't found with glXChooseVisual() */
+      xmvis = create_glx_visual( dpy, visinfo );
+      if (!xmvis) {
+         /* unusable visual */
+         _mesa_free(glxCtx);
+         return NULL;
+      }
+   }
+
+   glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+                                   shareCtx ? shareCtx->xmesaContext : NULL);
+   if (!glxCtx->xmesaContext) {
+      _mesa_free(glxCtx);
+      return NULL;
+   }
+
+   glxCtx->xmesaContext->direct = GL_FALSE;
+   glxCtx->glxContext.isDirect = GL_FALSE;
+   glxCtx->glxContext.currentDpy = dpy;
+   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
+
+   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+   return (GLXContext) glxCtx;
+}
+
+
+/* XXX these may have to be removed due to thread-safety issues. */
+static GLXContext MakeCurrent_PrevContext = 0;
+static GLXDrawable MakeCurrent_PrevDrawable = 0;
+static GLXDrawable MakeCurrent_PrevReadable = 0;
+static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
+static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
+
+
+/* GLX 1.3 and later */
+static Bool
+Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
+                            GLXDrawable read, GLXContext ctx )
+{
+   struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+
+   if (ctx && draw && read) {
+      XMesaBuffer drawBuffer, readBuffer;
+      XMesaContext xmctx = glxCtx->xmesaContext;
+
+      /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
+      if (ctx == MakeCurrent_PrevContext
+          && draw == MakeCurrent_PrevDrawable) {
+         drawBuffer = MakeCurrent_PrevDrawBuffer;
+      }
+      else {
+         drawBuffer = XMesaFindBuffer( dpy, draw );
+      }
+      if (!drawBuffer) {
+         /* drawable must be a new window! */
+         drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
+         if (!drawBuffer) {
+            /* Out of memory, or context/drawable depth mismatch */
+            return False;
+         }
+#ifdef FX
+         FXcreateContext( xmctx->xm_visual, draw, xmctx, drawBuffer );
+#endif
+      }
+
+      /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
+      if (ctx == MakeCurrent_PrevContext
+          && read == MakeCurrent_PrevReadable) {
+         readBuffer = MakeCurrent_PrevReadBuffer;
+      }
+      else {
+         readBuffer = XMesaFindBuffer( dpy, read );
+      }
+      if (!readBuffer) {
+         /* drawable must be a new window! */
+         readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
+         if (!readBuffer) {
+            /* Out of memory, or context/drawable depth mismatch */
+            return False;
+         }
+#ifdef FX
+         FXcreateContext( xmctx->xm_visual, read, xmctx, readBuffer );
+#endif
+      }
+
+      MakeCurrent_PrevContext = ctx;
+      MakeCurrent_PrevDrawable = draw;
+      MakeCurrent_PrevReadable = read;
+      MakeCurrent_PrevDrawBuffer = drawBuffer;
+      MakeCurrent_PrevReadBuffer = readBuffer;
+
+      /* Now make current! */
+      if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
+         ((__GLXcontext *) ctx)->currentDpy = dpy;
+         ((__GLXcontext *) ctx)->currentDrawable = draw;
+         ((__GLXcontext *) ctx)->currentReadable = read;
+         return True;
+      }
+      else {
+         return False;
+      }
+   }
+   else if (!ctx && !draw && !read) {
+      /* release current context w/out assigning new one. */
+      XMesaMakeCurrent( NULL, NULL );
+      MakeCurrent_PrevContext = 0;
+      MakeCurrent_PrevDrawable = 0;
+      MakeCurrent_PrevReadable = 0;
+      MakeCurrent_PrevDrawBuffer = 0;
+      MakeCurrent_PrevReadBuffer = 0;
+      return True;
+   }
+   else {
+      /* The args must either all be non-zero or all zero.
+       * This is an error.
+       */
+      return False;
+   }
+}
+
+
+static Bool
+Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+   return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx );
+}
+
+
+static GLXPixmap
+Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
+{
+   XMesaVisual v;
+   XMesaBuffer b;
+
+   v = find_glx_visual( dpy, visinfo );
+   if (!v) {
+      v = create_glx_visual( dpy, visinfo );
+      if (!v) {
+         /* unusable visual */
+         return 0;
+      }
+   }
+
+   b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+   if (!b) {
+      return 0;
+   }
+   return b->frontxrb->pixmap;
+}
+
+
+/*** GLX_MESA_pixmap_colormap ***/
+
+static GLXPixmap
+Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+                             Pixmap pixmap, Colormap cmap )
+{
+   XMesaVisual v;
+   XMesaBuffer b;
+
+   v = find_glx_visual( dpy, visinfo );
+   if (!v) {
+      v = create_glx_visual( dpy, visinfo );
+      if (!v) {
+         /* unusable visual */
+         return 0;
+      }
+   }
+
+   b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
+   if (!b) {
+      return 0;
+   }
+   return b->frontxrb->pixmap;
+}
+
+
+static void
+Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
+   if (b) {
+      XMesaDestroyBuffer(b);
+   }
+   else if (_mesa_getenv("MESA_DEBUG")) {
+      _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
+   }
+}
+
+
+static void
+Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+                     unsigned long mask )
+{
+   struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src;
+   struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst;
+   XMesaContext xm_src = fakeSrc->xmesaContext;
+   XMesaContext xm_dst = fakeDst->xmesaContext;
+   (void) dpy;
+   if (MakeCurrent_PrevContext == src) {
+      _mesa_Flush();
+   }
+   _mesa_copy_context( &(xm_src->mesa), &(xm_dst->mesa), (GLuint) mask );
+}
+
+
+static Bool
+Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+   /* Mesa's GLX isn't really an X extension but we try to act like one. */
+   (void) dpy;
+   (void) errorb;
+   (void) event;
+   return True;
+}
+
+
+extern void _kw_ungrab_all( Display *dpy );
+void _kw_ungrab_all( Display *dpy )
+{
+   XUngrabPointer( dpy, CurrentTime );
+   XUngrabKeyboard( dpy, CurrentTime );
+}
+
+
+static void
+Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+   struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+   (void) dpy;
+   MakeCurrent_PrevContext = 0;
+   MakeCurrent_PrevDrawable = 0;
+   MakeCurrent_PrevReadable = 0;
+   MakeCurrent_PrevDrawBuffer = 0;
+   MakeCurrent_PrevReadBuffer = 0;
+   XMesaDestroyContext( glxCtx->xmesaContext );
+   XMesaGarbageCollect();
+   _mesa_free(glxCtx);
+}
+
+
+static Bool
+Fake_glXIsDirect( Display *dpy, GLXContext ctx )
+{
+   struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+   (void) dpy;
+   return glxCtx->xmesaContext->direct;
+}
+
+
+
+static void
+Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+
+   if (buffer) {
+      XMesaSwapBuffers(buffer);
+   }
+   else if (_mesa_getenv("MESA_DEBUG")) {
+      _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
+                    (int) drawable);
+   }
+}
+
+
+
+/*** GLX_MESA_copy_sub_buffer ***/
+
+static void
+Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+                           int x, int y, int width, int height )
+{
+   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+   if (buffer) {
+      XMesaCopySubBuffer(buffer, x, y, width, height);
+   }
+   else if (_mesa_getenv("MESA_DEBUG")) {
+      _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
+   }
+}
+
+
+static Bool
+Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+   (void) dpy;
+   /* Return GLX version, not Mesa version */
+   assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
+   *maj = CLIENT_MAJOR_VERSION;
+   *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
+   return True;
+}
+
+
+/*
+ * Query the GLX attributes of the given XVisualInfo.
+ */
+static int
+get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
+{
+   ASSERT(xmvis);
+   switch(attrib) {
+      case GLX_USE_GL:
+         if (fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = (int) True;
+        return 0;
+      case GLX_BUFFER_SIZE:
+        *value = xmvis->visinfo->depth;
+        return 0;
+      case GLX_LEVEL:
+        *value = xmvis->mesa_visual.level;
+        return 0;
+      case GLX_RGBA:
+         if (fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+        if (xmvis->mesa_visual.rgbMode) {
+           *value = True;
+        }
+        else {
+           *value = False;
+        }
+        return 0;
+      case GLX_DOUBLEBUFFER:
+        *value = (int) xmvis->mesa_visual.doubleBufferMode;
+        return 0;
+      case GLX_STEREO:
+        *value = (int) xmvis->mesa_visual.stereoMode;
+        return 0;
+      case GLX_AUX_BUFFERS:
+        *value = xmvis->mesa_visual.numAuxBuffers;
+        return 0;
+      case GLX_RED_SIZE:
+         *value = xmvis->mesa_visual.redBits;
+        return 0;
+      case GLX_GREEN_SIZE:
+         *value = xmvis->mesa_visual.greenBits;
+        return 0;
+      case GLX_BLUE_SIZE:
+         *value = xmvis->mesa_visual.blueBits;
+        return 0;
+      case GLX_ALPHA_SIZE:
+         *value = xmvis->mesa_visual.alphaBits;
+        return 0;
+      case GLX_DEPTH_SIZE:
+         *value = xmvis->mesa_visual.depthBits;
+        return 0;
+      case GLX_STENCIL_SIZE:
+        *value = xmvis->mesa_visual.stencilBits;
+        return 0;
+      case GLX_ACCUM_RED_SIZE:
+        *value = xmvis->mesa_visual.accumRedBits;
+        return 0;
+      case GLX_ACCUM_GREEN_SIZE:
+        *value = xmvis->mesa_visual.accumGreenBits;
+        return 0;
+      case GLX_ACCUM_BLUE_SIZE:
+        *value = xmvis->mesa_visual.accumBlueBits;
+        return 0;
+      case GLX_ACCUM_ALPHA_SIZE:
+         *value = xmvis->mesa_visual.accumAlphaBits;
+        return 0;
+
+      /*
+       * GLX_EXT_visual_info extension
+       */
+      case GLX_X_VISUAL_TYPE_EXT:
+         switch (xmvis->visinfo->CLASS) {
+            case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
+            case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
+            case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
+            case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
+            case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
+            case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
+         }
+         return 0;
+      case GLX_TRANSPARENT_TYPE_EXT:
+         if (xmvis->mesa_visual.level==0) {
+            /* normal planes */
+            *value = GLX_NONE_EXT;
+         }
+         else if (xmvis->mesa_visual.level>0) {
+            /* overlay */
+            if (xmvis->mesa_visual.rgbMode) {
+               *value = GLX_TRANSPARENT_RGB_EXT;
+            }
+            else {
+               *value = GLX_TRANSPARENT_INDEX_EXT;
+            }
+         }
+         else if (xmvis->mesa_visual.level<0) {
+            /* underlay */
+            *value = GLX_NONE_EXT;
+         }
+         return 0;
+      case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+         {
+            int pixel = transparent_pixel( xmvis );
+            if (pixel>=0) {
+               *value = pixel;
+            }
+            /* else undefined */
+         }
+         return 0;
+      case GLX_TRANSPARENT_RED_VALUE_EXT:
+         /* undefined */
+         return 0;
+      case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+         /* undefined */
+         return 0;
+      case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+         /* undefined */
+         return 0;
+      case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+         /* undefined */
+         return 0;
+
+      /*
+       * GLX_EXT_visual_info extension
+       */
+      case GLX_VISUAL_CAVEAT_EXT:
+         /* test for zero, just in case */
+         if (xmvis->mesa_visual.visualRating > 0)
+            *value = xmvis->mesa_visual.visualRating;
+         else
+            *value = GLX_NONE_EXT;
+         return 0;
+
+      /*
+       * GLX_ARB_multisample
+       */
+      case GLX_SAMPLE_BUFFERS_ARB:
+         *value = 0;
+         return 0;
+      case GLX_SAMPLES_ARB:
+         *value = 0;
+         return 0;
+
+      /*
+       * For FBConfigs:
+       */
+      case GLX_SCREEN_EXT:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = xmvis->visinfo->screen;
+         break;
+      case GLX_DRAWABLE_TYPE: /*SGIX too */
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+         break;
+      case GLX_RENDER_TYPE_SGIX:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         if (xmvis->mesa_visual.rgbMode)
+            *value = GLX_RGBA_BIT;
+         else
+            *value = GLX_COLOR_INDEX_BIT;
+         break;
+      case GLX_X_RENDERABLE_SGIX:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = True; /* XXX really? */
+         break;
+      case GLX_FBCONFIG_ID_SGIX:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = xmvis->visinfo->visualid;
+         break;
+      case GLX_MAX_PBUFFER_WIDTH:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         /* XXX or MAX_WIDTH? */
+         *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
+         break;
+      case GLX_MAX_PBUFFER_HEIGHT:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+         break;
+      case GLX_MAX_PBUFFER_PIXELS:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
+                  DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+         break;
+      case GLX_VISUAL_ID:
+         if (!fbconfig)
+            return GLX_BAD_ATTRIBUTE;
+         *value = xmvis->visinfo->visualid;
+         break;
+
+#ifdef GLX_EXT_texture_from_pixmap
+      case GLX_BIND_TO_TEXTURE_RGB_EXT:
+         *value = True; /*XXX*/
+         break;
+      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+         /* XXX review */
+         *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
+         break;
+      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+         *value = True; /*XXX*/
+         break;
+      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+         *value = (GLX_TEXTURE_1D_BIT_EXT |
+                   GLX_TEXTURE_2D_BIT_EXT |
+                   GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
+         break;
+      case GLX_Y_INVERTED_EXT:
+         *value = True; /*XXX*/
+         break;
+#endif
+
+      default:
+        return GLX_BAD_ATTRIBUTE;
+   }
+   return Success;
+}
+
+
+static int
+Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+                   int attrib, int *value )
+{
+   XMesaVisual xmvis;
+   int k;
+   if (!dpy || !visinfo)
+      return GLX_BAD_ATTRIBUTE;
+
+   xmvis = find_glx_visual( dpy, visinfo );
+   if (!xmvis) {
+      /* this visual wasn't obtained with glXChooseVisual */
+      xmvis = create_glx_visual( dpy, visinfo );
+      if (!xmvis) {
+        /* this visual can't be used for GL rendering */
+        if (attrib==GLX_USE_GL) {
+           *value = (int) False;
+           return 0;
+        }
+        else {
+           return GLX_BAD_VISUAL;
+        }
+      }
+   }
+
+   k = get_config(xmvis, attrib, value, GL_FALSE);
+   return k;
+}
+
+
+static void
+Fake_glXWaitGL( void )
+{
+   XMesaContext xmesa = XMesaGetCurrentContext();
+   XMesaFlush( xmesa );
+}
+
+
+
+static void
+Fake_glXWaitX( void )
+{
+   XMesaContext xmesa = XMesaGetCurrentContext();
+   XMesaFlush( xmesa );
+}
+
+
+static const char *
+get_extensions( void )
+{
+#ifdef FX
+   const char *fx = _mesa_getenv("MESA_GLX_FX");
+   if (fx && fx[0] != 'd') {
+      return EXTENSIONS;
+   }
+#endif
+   return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXQueryExtensionsString( Display *dpy, int screen )
+{
+   (void) dpy;
+   (void) screen;
+   return get_extensions();
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXQueryServerString( Display *dpy, int screen, int name )
+{
+   static char version[1000];
+   _mesa_sprintf(version, "%d.%d %s",
+                 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION);
+
+   (void) dpy;
+   (void) screen;
+
+   switch (name) {
+      case GLX_EXTENSIONS:
+         return get_extensions();
+      case GLX_VENDOR:
+        return VENDOR;
+      case GLX_VERSION:
+        return version;
+      default:
+         return NULL;
+   }
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXGetClientString( Display *dpy, int name )
+{
+   static char version[1000];
+   _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
+                 CLIENT_MINOR_VERSION, MESA_GLX_VERSION);
+
+   (void) dpy;
+
+   switch (name) {
+      case GLX_EXTENSIONS:
+         return get_extensions();
+      case GLX_VENDOR:
+        return VENDOR;
+      case GLX_VERSION:
+        return version;
+      default:
+         return NULL;
+   }
+}
+
+
+
+/*
+ * GLX 1.3 and later
+ */
+
+
+static int
+Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
+                           int attribute, int *value )
+{
+   XMesaVisual v = (XMesaVisual) config;
+   (void) dpy;
+   (void) config;
+
+   if (!dpy || !config || !value)
+      return -1;
+
+   return get_config(v, attribute, value, GL_TRUE);
+}
+
+
+static GLXFBConfig *
+Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
+{
+   XVisualInfo *visuals, visTemplate;
+   const long visMask = VisualScreenMask;
+   int i;
+
+   /* Get list of all X visuals */
+   visTemplate.screen = screen;
+   visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
+   if (*nelements > 0) {
+      XMesaVisual *results;
+      results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual));
+      if (!results) {
+         *nelements = 0;
+         return NULL;
+      }
+      for (i = 0; i < *nelements; i++) {
+         results[i] = create_glx_visual(dpy, visuals + i);
+      }
+      return (GLXFBConfig *) results;
+   }
+   return NULL;
+}
+
+
+static GLXFBConfig *
+Fake_glXChooseFBConfig( Display *dpy, int screen,
+                        const int *attribList, int *nitems )
+{
+   XMesaVisual xmvis;
+
+   if (!attribList || !attribList[0]) {
+      /* return list of all configs (per GLX_SGIX_fbconfig spec) */
+      return Fake_glXGetFBConfigs(dpy, screen, nitems);
+   }
+
+   xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
+   if (xmvis) {
+      GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual));
+      if (!config) {
+         *nitems = 0;
+         return NULL;
+      }
+      *nitems = 1;
+      config[0] = (GLXFBConfig) xmvis;
+      return (GLXFBConfig *) config;
+   }
+   else {
+      *nitems = 0;
+      return NULL;
+   }
+}
+
+
+static XVisualInfo *
+Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
+{
+   if (dpy && config) {
+      XMesaVisual xmvis = (XMesaVisual) config;
+#if 0      
+      return xmvis->vishandle;
+#else
+      /* create a new vishandle - the cached one may be stale */
+      xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+      if (xmvis->vishandle) {
+         _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+      }
+      return xmvis->vishandle;
+#endif
+   }
+   else {
+      return NULL;
+   }
+}
+
+
+static GLXWindow
+Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
+                      const int *attribList )
+{
+   XMesaVisual xmvis = (XMesaVisual) config;
+   XMesaBuffer xmbuf;
+   if (!xmvis)
+      return 0;
+
+   xmbuf = XMesaCreateWindowBuffer(xmvis, win);
+   if (!xmbuf)
+      return 0;
+
+#ifdef FX
+   /* XXX this will segfault if actually called */
+   FXcreateContext(xmvis, win, NULL, xmbuf);
+#endif
+
+   (void) dpy;
+   (void) attribList;  /* Ignored in GLX 1.3 */
+
+   return win;  /* A hack for now */
+}
+
+
+static void
+Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window);
+   if (b)
+      XMesaDestroyBuffer(b);
+   /* don't destroy X window */
+}
+
+
+/* XXX untested */
+static GLXPixmap
+Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
+                      const int *attribList )
+{
+   XMesaVisual v = (XMesaVisual) config;
+   XMesaBuffer b;
+   const int *attr;
+   int target = 0, format = 0, mipmap = 0;
+   int value;
+
+   if (!dpy || !config || !pixmap)
+      return 0;
+
+   for (attr = attribList; *attr; attr++) {
+      switch (*attr) {
+      case GLX_TEXTURE_FORMAT_EXT:
+         attr++;
+         switch (*attr) {
+         case GLX_TEXTURE_FORMAT_NONE_EXT:
+         case GLX_TEXTURE_FORMAT_RGB_EXT:
+         case GLX_TEXTURE_FORMAT_RGBA_EXT:
+            format = *attr;
+            break;
+         default:
+            /* error */
+            return 0;
+         }
+         break;
+      case GLX_TEXTURE_TARGET_EXT:
+         attr++;
+         switch (*attr) {
+         case GLX_TEXTURE_1D_EXT:
+         case GLX_TEXTURE_2D_EXT:
+         case GLX_TEXTURE_RECTANGLE_EXT:
+            target = *attr;
+            break;
+         default:
+            /* error */
+            return 0;
+         }
+         break;
+      case GLX_MIPMAP_TEXTURE_EXT:
+         attr++;
+         if (*attr)
+            mipmap = 1;
+         break;
+      default:
+         /* error */
+         return 0;
+      }
+   }
+
+   if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   if (mipmap) {
+      if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   if (target == GLX_TEXTURE_1D_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+   else if (target == GLX_TEXTURE_2D_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+   if (target == GLX_TEXTURE_RECTANGLE_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+
+   if (format || target || mipmap) {
+      /* texture from pixmap */
+      b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
+   }
+   else {
+      b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+   }
+   if (!b) {
+      return 0;
+   }
+
+   return pixmap;
+}
+
+
+static void
+Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap);
+   if (b)
+      XMesaDestroyBuffer(b);
+   /* don't destroy X pixmap */
+}
+
+
+static GLXPbuffer
+Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+                       const int *attribList )
+{
+   XMesaVisual xmvis = (XMesaVisual) config;
+   XMesaBuffer xmbuf;
+   const int *attrib;
+   int width = 0, height = 0;
+   GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+   (void) dpy;
+
+   for (attrib = attribList; *attrib; attrib++) {
+      switch (*attrib) {
+         case GLX_PBUFFER_WIDTH:
+            attrib++;
+            width = *attrib;
+            break;
+         case GLX_PBUFFER_HEIGHT:
+            attrib++;
+            height = *attrib;
+            break;
+         case GLX_PRESERVED_CONTENTS:
+            attrib++;
+            preserveContents = *attrib; /* ignored */
+            break;
+         case GLX_LARGEST_PBUFFER:
+            attrib++;
+            useLargest = *attrib; /* ignored */
+            break;
+         default:
+            return 0;
+      }
+   }
+
+   /* not used at this time */
+   (void) useLargest;
+   (void) preserveContents;
+
+   if (width == 0 || height == 0)
+      return 0;
+
+   xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+   /* A GLXPbuffer handle must be an X Drawable because that's what
+    * glXMakeCurrent takes.
+    */
+   if (xmbuf)
+      return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+   else
+      return 0;
+}
+
+
+static void
+Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
+   if (b) {
+      XMesaDestroyBuffer(b);
+   }
+}
+
+
+static void
+Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
+                       unsigned int *value )
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
+   if (!xmbuf)
+      return;
+
+   switch (attribute) {
+      case GLX_WIDTH:
+         *value = xmbuf->mesa_buffer.Width;
+         break;
+      case GLX_HEIGHT:
+         *value = xmbuf->mesa_buffer.Height;
+         break;
+      case GLX_PRESERVED_CONTENTS:
+         *value = True;
+         break;
+      case GLX_LARGEST_PBUFFER:
+         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
+         break;
+      case GLX_FBCONFIG_ID:
+         *value = xmbuf->xm_visual->visinfo->visualid;
+         return;
+#ifdef GLX_EXT_texture_from_pixmap
+      case GLX_TEXTURE_FORMAT_EXT:
+         *value = xmbuf->TextureFormat;
+         break;
+      case GLX_TEXTURE_TARGET_EXT:
+         *value = xmbuf->TextureTarget;
+         break;
+      case GLX_MIPMAP_TEXTURE_EXT:
+         *value = xmbuf->TextureMipmap;
+         break;
+#endif
+
+      default:
+         return; /* raise BadValue error */
+   }
+}
+
+
+static GLXContext
+Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
+                          int renderType, GLXContext shareList, Bool direct )
+{
+   struct fake_glx_context *glxCtx;
+   struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList;
+   XMesaVisual xmvis = (XMesaVisual) config;
+
+   if (!dpy || !config ||
+       (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
+      return 0;
+
+   glxCtx = CALLOC_STRUCT(fake_glx_context);
+   if (!glxCtx)
+      return 0;
+
+   /* deallocate unused windows/buffers */
+   XMesaGarbageCollect();
+
+   glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+                                   shareCtx ? shareCtx->xmesaContext : NULL);
+   if (!glxCtx->xmesaContext) {
+      _mesa_free(glxCtx);
+      return NULL;
+   }
+
+   glxCtx->xmesaContext->direct = GL_FALSE;
+   glxCtx->glxContext.isDirect = GL_FALSE;
+   glxCtx->glxContext.currentDpy = dpy;
+   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
+
+   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+   return (GLXContext) glxCtx;
+}
+
+
+static int
+Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
+{
+   struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+   XMesaContext xmctx = glxCtx->xmesaContext;
+
+   (void) dpy;
+   (void) ctx;
+
+   switch (attribute) {
+   case GLX_FBCONFIG_ID:
+      *value = xmctx->xm_visual->visinfo->visualid;
+      break;
+   case GLX_RENDER_TYPE:
+      if (xmctx->xm_visual->mesa_visual.rgbMode)
+         *value = GLX_RGBA_BIT;
+      else
+         *value = GLX_COLOR_INDEX_BIT;
+      break;
+   case GLX_SCREEN:
+      *value = 0;
+      return Success;
+   default:
+      return GLX_BAD_ATTRIBUTE;
+   }
+   return 0;
+}
+
+
+static void
+Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+   if (xmbuf)
+      xmbuf->selectedEvents = mask;
+}
+
+
+static void
+Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
+                          unsigned long *mask )
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+   if (xmbuf)
+      *mask = xmbuf->selectedEvents;
+   else
+      *mask = 0;
+}
+
+
+
+/*** GLX_SGI_swap_control ***/
+
+static int
+Fake_glXSwapIntervalSGI(int interval)
+{
+   (void) interval;
+   return 0;
+}
+
+
+
+/*** GLX_SGI_video_sync ***/
+
+static unsigned int FrameCounter = 0;
+
+static int
+Fake_glXGetVideoSyncSGI(unsigned int *count)
+{
+   /* this is a bogus implementation */
+   *count = FrameCounter++;
+   return 0;
+}
+
+static int
+Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+   if (divisor <= 0 || remainder < 0)
+      return GLX_BAD_VALUE;
+   /* this is a bogus implementation */
+   FrameCounter++;
+   while (FrameCounter % divisor != remainder)
+      FrameCounter++;
+   *count = FrameCounter;
+   return 0;
+}
+
+
+
+/*** GLX_SGI_make_current_read ***/
+
+static Bool
+Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+   return Fake_glXMakeContextCurrent( dpy, draw, read, ctx );
+}
+
+/* not used
+static GLXDrawable
+Fake_glXGetCurrentReadDrawableSGI(void)
+{
+   return 0;
+}
+*/
+
+
+/*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+
+static GLXVideoSourceSGIX
+Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
+{
+   (void) dpy;
+   (void) screen;
+   (void) server;
+   (void) path;
+   (void) nodeClass;
+   (void) drainNode;
+   return 0;
+}
+
+static void
+Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
+{
+   (void) dpy;
+   (void) src;
+}
+
+#endif
+
+
+/*** GLX_EXT_import_context ***/
+
+static void
+Fake_glXFreeContextEXT(Display *dpy, GLXContext context)
+{
+   (void) dpy;
+   (void) context;
+}
+
+static GLXContextID
+Fake_glXGetContextIDEXT(const GLXContext context)
+{
+   (void) context;
+   return 0;
+}
+
+static GLXContext
+Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID)
+{
+   (void) dpy;
+   (void) contextID;
+   return 0;
+}
+
+static int
+Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value)
+{
+   (void) dpy;
+   (void) context;
+   (void) attribute;
+   (void) value;
+   return 0;
+}
+
+
+
+/*** GLX_SGIX_fbconfig ***/
+
+static int
+Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
+{
+   return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value);
+}
+
+static GLXFBConfigSGIX *
+Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
+{
+   return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements);
+}
+
+
+static GLXPixmap
+Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
+{
+   XMesaVisual xmvis = (XMesaVisual) config;
+   XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
+   return xmbuf->frontxrb->pixmap; /* need to return an X ID */
+}
+
+
+static GLXContext
+Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
+{
+   XMesaVisual xmvis = (XMesaVisual) config;
+   struct fake_glx_context *glxCtx;
+   struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
+
+   glxCtx = CALLOC_STRUCT(fake_glx_context);
+   if (!glxCtx)
+      return 0;
+
+   /* deallocate unused windows/buffers */
+   XMesaGarbageCollect();
+
+   glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+                                   shareCtx ? shareCtx->xmesaContext : NULL);
+   if (!glxCtx->xmesaContext) {
+      _mesa_free(glxCtx);
+      return NULL;
+   }
+
+   glxCtx->xmesaContext->direct = GL_FALSE;
+   glxCtx->glxContext.isDirect = GL_FALSE;
+   glxCtx->glxContext.currentDpy = dpy;
+   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
+
+   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+   return (GLXContext) glxCtx;
+}
+
+
+static XVisualInfo *
+Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
+{
+   return Fake_glXGetVisualFromFBConfig(dpy, config);
+}
+
+
+static GLXFBConfigSGIX
+Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
+{
+   XMesaVisual xmvis = find_glx_visual(dpy, vis);
+   if (!xmvis) {
+      /* This visual wasn't found with glXChooseVisual() */
+      xmvis = create_glx_visual(dpy, vis);
+   }
+
+   return (GLXFBConfigSGIX) xmvis;
+}
+
+
+
+/*** GLX_SGIX_pbuffer ***/
+
+static GLXPbufferSGIX
+Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
+                             unsigned int width, unsigned int height,
+                             int *attribList)
+{
+   XMesaVisual xmvis = (XMesaVisual) config;
+   XMesaBuffer xmbuf;
+   const int *attrib;
+   GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+   (void) dpy;
+
+   for (attrib = attribList; attrib && *attrib; attrib++) {
+      switch (*attrib) {
+         case GLX_PRESERVED_CONTENTS_SGIX:
+            attrib++;
+            preserveContents = *attrib; /* ignored */
+            break;
+         case GLX_LARGEST_PBUFFER_SGIX:
+            attrib++;
+            useLargest = *attrib; /* ignored */
+            break;
+         default:
+            return 0;
+      }
+   }
+
+   /* not used at this time */
+   (void) useLargest;
+   (void) preserveContents;
+
+   xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+   /* A GLXPbuffer handle must be an X Drawable because that's what
+    * glXMakeCurrent takes.
+    */
+   return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+}
+
+
+static void
+Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+   if (xmbuf) {
+      XMesaDestroyBuffer(xmbuf);
+   }
+}
+
+
+static int
+Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
+{
+   const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+
+   if (!xmbuf) {
+      /* Generate GLXBadPbufferSGIX for bad pbuffer */
+      return 0;
+   }
+
+   switch (attribute) {
+      case GLX_PRESERVED_CONTENTS_SGIX:
+         *value = True;
+         break;
+      case GLX_LARGEST_PBUFFER_SGIX:
+         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
+         break;
+      case GLX_WIDTH_SGIX:
+         *value = xmbuf->mesa_buffer.Width;
+         break;
+      case GLX_HEIGHT_SGIX:
+         *value = xmbuf->mesa_buffer.Height;
+         break;
+      case GLX_EVENT_MASK_SGIX:
+         *value = 0;  /* XXX might be wrong */
+         break;
+      default:
+         *value = 0;
+   }
+   return 0;
+}
+
+
+static void
+Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+   if (xmbuf) {
+      /* Note: we'll never generate clobber events */
+      xmbuf->selectedEvents = mask;
+   }
+}
+
+
+static void
+Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+   if (xmbuf) {
+      *mask = xmbuf->selectedEvents;
+   }
+   else {
+      *mask = 0;
+   }
+}
+
+
+
+/*** GLX_SGI_cushion ***/
+
+static void
+Fake_glXCushionSGI(Display *dpy, Window win, float cushion)
+{
+   (void) dpy;
+   (void) win;
+   (void) cushion;
+}
+
+
+
+/*** GLX_SGIX_video_resize ***/
+
+static int
+Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
+{
+   (void) dpy;
+   (void) screen;
+   (void) channel;
+   (void) window;
+   return 0;
+}
+
+static int
+Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
+{
+   (void) dpy;
+   (void) screen;
+   (void) channel;
+   (void) x;
+   (void) y;
+   (void) w;
+   (void) h;
+   return 0;
+}
+
+static int
+Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
+{
+   (void) dpy;
+   (void) screen;
+   (void) channel;
+   (void) x;
+   (void) y;
+   (void) w;
+   (void) h;
+   return 0;
+}
+
+static int
+Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
+{
+   (void) dpy;
+   (void) screen;
+   (void) channel;
+   (void) dx;
+   (void) dy;
+   (void) dw;
+   (void) dh;
+   return 0;
+}
+
+static int
+Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
+{
+   (void) dpy;
+   (void) screen;
+   (void) channel;
+   (void) synctype;
+   return 0;
+}
+
+
+
+/*** GLX_SGIX_dmbuffer **/
+
+#if defined(_DM_BUFFER_H_)
+static Bool
+Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
+{
+   (void) dpy;
+   (void) pbuffer;
+   (void) params;
+   (void) dmbuffer;
+   return False;
+}
+#endif
+
+
+/*** GLX_SGIX_swap_group ***/
+
+static void
+Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
+{
+   (void) dpy;
+   (void) drawable;
+   (void) member;
+}
+
+
+
+/*** GLX_SGIX_swap_barrier ***/
+
+static void
+Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
+{
+   (void) dpy;
+   (void) drawable;
+   (void) barrier;
+}
+
+static Bool
+Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+{
+   (void) dpy;
+   (void) screen;
+   (void) max;
+   return False;
+}
+
+
+
+/*** GLX_SUN_get_transparent_index ***/
+
+static Status
+Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
+{
+   (void) dpy;
+   (void) overlay;
+   (void) underlay;
+   (void) pTransparent;
+   return 0;
+}
+
+
+
+/*** GLX_MESA_release_buffers ***/
+
+/*
+ * Release the depth, stencil, accum buffers attached to a GLXDrawable
+ * (a window or pixmap) prior to destroying the GLXDrawable.
+ */
+static Bool
+Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, d);
+   if (b) {
+      XMesaDestroyBuffer(b);
+      return True;
+   }
+   return False;
+}
+
+
+
+/*** GLX_MESA_set_3dfx_mode ***/
+
+static Bool
+Fake_glXSet3DfxModeMESA( int mode )
+{
+   return XMesaSetFXmode( mode );
+}
+
+
+
+/*** GLX_NV_vertex_array range ***/
+static void *
+Fake_glXAllocateMemoryNV( GLsizei size,
+                          GLfloat readFrequency,
+                          GLfloat writeFrequency,
+                          GLfloat priority )
+{
+   (void) size;
+   (void) readFrequency;
+   (void) writeFrequency;
+   (void) priority;
+   return NULL;
+}
+
+
+static void 
+Fake_glXFreeMemoryNV( GLvoid *pointer )
+{
+   (void) pointer;
+}
+
+
+/*** GLX_MESA_agp_offset ***/
+
+static GLuint
+Fake_glXGetAGPOffsetMESA( const GLvoid *pointer )
+{
+   (void) pointer;
+   return ~0;
+}
+
+
+/*** GLX_EXT_texture_from_pixmap ***/
+
+static void
+Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
+                        const int *attrib_list)
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+   if (b)
+      XMesaBindTexImage(dpy, b, buffer, attrib_list);
+}
+
+static void
+Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+   if (b)
+      XMesaReleaseTexImage(dpy, b, buffer);
+}
+
+
+/* silence warning */
+extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
+
+
+/**
+ * Create a new GLX API dispatch table with its function pointers
+ * initialized to point to Mesa's "fake" GLX API functions.
+ * Note: there's a similar function (_real_GetGLXDispatchTable) that
+ * returns a new dispatch table with all pointers initalized to point
+ * to "real" GLX functions (which understand GLX wire protocol, etc).
+ */
+struct _glxapi_table *
+_mesa_GetGLXDispatchTable(void)
+{
+   static struct _glxapi_table glx;
+
+   /* be sure our dispatch table size <= libGL's table */
+   {
+      GLuint size = sizeof(struct _glxapi_table) / sizeof(void *);
+      (void) size;
+      assert(_glxapi_get_dispatch_table_size() >= size);
+   }
+
+   /* initialize the whole table to no-ops */
+   _glxapi_set_no_op_table(&glx);
+
+   /* now initialize the table with the functions I implement */
+   glx.ChooseVisual = Fake_glXChooseVisual;
+   glx.CopyContext = Fake_glXCopyContext;
+   glx.CreateContext = Fake_glXCreateContext;
+   glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap;
+   glx.DestroyContext = Fake_glXDestroyContext;
+   glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap;
+   glx.GetConfig = Fake_glXGetConfig;
+   /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
+   /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
+   glx.IsDirect = Fake_glXIsDirect;
+   glx.MakeCurrent = Fake_glXMakeCurrent;
+   glx.QueryExtension = Fake_glXQueryExtension;
+   glx.QueryVersion = Fake_glXQueryVersion;
+   glx.SwapBuffers = Fake_glXSwapBuffers;
+   glx.UseXFont = Fake_glXUseXFont;
+   glx.WaitGL = Fake_glXWaitGL;
+   glx.WaitX = Fake_glXWaitX;
+
+   /*** GLX_VERSION_1_1 ***/
+   glx.GetClientString = Fake_glXGetClientString;
+   glx.QueryExtensionsString = Fake_glXQueryExtensionsString;
+   glx.QueryServerString = Fake_glXQueryServerString;
+
+   /*** GLX_VERSION_1_2 ***/
+   /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
+
+   /*** GLX_VERSION_1_3 ***/
+   glx.ChooseFBConfig = Fake_glXChooseFBConfig;
+   glx.CreateNewContext = Fake_glXCreateNewContext;
+   glx.CreatePbuffer = Fake_glXCreatePbuffer;
+   glx.CreatePixmap = Fake_glXCreatePixmap;
+   glx.CreateWindow = Fake_glXCreateWindow;
+   glx.DestroyPbuffer = Fake_glXDestroyPbuffer;
+   glx.DestroyPixmap = Fake_glXDestroyPixmap;
+   glx.DestroyWindow = Fake_glXDestroyWindow;
+   /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
+   glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib;
+   glx.GetFBConfigs = Fake_glXGetFBConfigs;
+   glx.GetSelectedEvent = Fake_glXGetSelectedEvent;
+   glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig;
+   glx.MakeContextCurrent = Fake_glXMakeContextCurrent;
+   glx.QueryContext = Fake_glXQueryContext;
+   glx.QueryDrawable = Fake_glXQueryDrawable;
+   glx.SelectEvent = Fake_glXSelectEvent;
+
+   /*** GLX_SGI_swap_control ***/
+   glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI;
+
+   /*** GLX_SGI_video_sync ***/
+   glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI;
+   glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI;
+
+   /*** GLX_SGI_make_current_read ***/
+   glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI;
+   /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/
+
+/*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+   glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX;
+   glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX;
+#endif
+
+   /*** GLX_EXT_import_context ***/
+   glx.FreeContextEXT = Fake_glXFreeContextEXT;
+   glx.GetContextIDEXT = Fake_glXGetContextIDEXT;
+   /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/
+   glx.ImportContextEXT = Fake_glXImportContextEXT;
+   glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT;
+
+   /*** GLX_SGIX_fbconfig ***/
+   glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX;
+   glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX;
+   glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX;
+   glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX;
+   glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX;
+   glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX;
+
+   /*** GLX_SGIX_pbuffer ***/
+   glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX;
+   glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX;
+   glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX;
+   glx.SelectEventSGIX = Fake_glXSelectEventSGIX;
+   glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX;
+
+   /*** GLX_SGI_cushion ***/
+   glx.CushionSGI = Fake_glXCushionSGI;
+
+   /*** GLX_SGIX_video_resize ***/
+   glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX;
+   glx.ChannelRectSGIX = Fake_glXChannelRectSGIX;
+   glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX;
+   glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX;
+   glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX;
+
+   /*** GLX_SGIX_dmbuffer **/
+#if defined(_DM_BUFFER_H_)
+   glx.AssociateDMPbufferSGIX = NULL;
+#endif
+
+   /*** GLX_SGIX_swap_group ***/
+   glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX;
+
+   /*** GLX_SGIX_swap_barrier ***/
+   glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX;
+   glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX;
+
+   /*** GLX_SUN_get_transparent_index ***/
+   glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN;
+
+   /*** GLX_MESA_copy_sub_buffer ***/
+   glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA;
+
+   /*** GLX_MESA_release_buffers ***/
+   glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA;
+
+   /*** GLX_MESA_pixmap_colormap ***/
+   glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA;
+
+   /*** GLX_MESA_set_3dfx_mode ***/
+   glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA;
+
+   /*** GLX_NV_vertex_array_range ***/
+   glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV;
+   glx.FreeMemoryNV = Fake_glXFreeMemoryNV;
+
+   /*** GLX_MESA_agp_offset ***/
+   glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA;
+
+   /*** GLX_EXT_texture_from_pixmap ***/
+   glx.BindTexImageEXT = Fake_glXBindTexImageEXT;
+   glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT;
+
+   return &glx;
+}
diff --git a/src/mesa/pipe/xlib/glxapi.c b/src/mesa/pipe/xlib/glxapi.c
new file mode 100644 (file)
index 0000000..309a000
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * This is the GLX API dispatcher.  Calls to the glX* functions are
+ * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions.
+ * See the glxapi.h file for more details.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "glheader.h"
+#include "glapi.h"
+#include "glxapi.h"
+
+
+extern struct _glxapi_table *_real_GetGLXDispatchTable(void);
+extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
+
+
+struct display_dispatch {
+   Display *Dpy;
+   struct _glxapi_table *Table;
+   struct display_dispatch *Next;
+};
+
+static struct display_dispatch *DispatchList = NULL;
+
+
+/* Display -> Dispatch caching */
+static Display *prevDisplay = NULL;
+static struct _glxapi_table *prevTable = NULL;
+
+
+static struct _glxapi_table *
+get_dispatch(Display *dpy)
+{
+   if (!dpy)
+      return NULL;
+
+   /* search list of display/dispatch pairs for this display */
+   {
+      const struct display_dispatch *d = DispatchList;
+      while (d) {
+         if (d->Dpy == dpy) {
+            prevDisplay = dpy;
+            prevTable = d->Table;
+            return d->Table;  /* done! */
+         }
+         d = d->Next;
+      }
+   }
+
+   /* A new display, determine if we should use real GLX
+    * or Mesa's pseudo-GLX.
+    */
+   {
+      struct _glxapi_table *t = _mesa_GetGLXDispatchTable();
+
+      if (t) {
+         struct display_dispatch *d;
+         d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch));
+         if (d) {
+            d->Dpy = dpy;
+            d->Table = t;
+            /* insert at head of list */
+            d->Next = DispatchList;
+            DispatchList = d;
+            /* update cache */
+            prevDisplay = dpy;
+            prevTable = t;
+            return t;
+         }
+      }
+   }
+
+   /* If we get here that means we can't use real GLX on this display
+    * and the Mesa pseudo-GLX software renderer wasn't compiled in.
+    * Or, we ran out of memory!
+    */
+   return NULL;
+}
+
+
+/* Don't use the GET_DISPATCH defined in glthread.h */
+#undef GET_DISPATCH
+
+#define GET_DISPATCH(DPY, TABLE)       \
+   if (DPY == prevDisplay) {           \
+      TABLE = prevTable;               \
+   }                                   \
+   else if (!DPY) {                    \
+      TABLE = NULL;                    \
+   }                                   \
+   else {                              \
+      TABLE = get_dispatch(DPY);       \
+   }
+
+   
+
+
+/**
+ * GLX API current context.
+ */
+#if defined(GLX_USE_TLS)
+PUBLIC __thread void * CurrentContext
+    __attribute__((tls_model("initial-exec")));
+#elif defined(THREADS)
+static _glthread_TSD ContextTSD;         /**< Per-thread context pointer */
+#else
+static GLXContext CurrentContext = 0;
+#endif
+
+
+static void
+SetCurrentContext(GLXContext c)
+{
+#if defined(GLX_USE_TLS)
+   CurrentContext = c;
+#elif defined(THREADS)
+   _glthread_SetTSD(&ContextTSD, c);
+#else
+   CurrentContext = c;
+#endif
+}
+
+
+/*
+ * GLX API entrypoints
+ */
+
+/*** GLX_VERSION_1_0 ***/
+
+XVisualInfo PUBLIC *
+glXChooseVisual(Display *dpy, int screen, int *list)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->ChooseVisual)(dpy, screen, list);
+}
+
+
+void PUBLIC
+glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->CopyContext)(dpy, src, dst, mask);
+}
+
+
+GLXContext PUBLIC
+glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateContext)(dpy, visinfo, shareList, direct);
+}
+
+
+GLXPixmap PUBLIC
+glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateGLXPixmap)(dpy, visinfo, pixmap);
+}
+
+
+void PUBLIC
+glXDestroyContext(Display *dpy, GLXContext ctx)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   if (glXGetCurrentContext() == ctx)
+      SetCurrentContext(NULL);
+   (t->DestroyContext)(dpy, ctx);
+}
+
+
+void PUBLIC
+glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->DestroyGLXPixmap)(dpy, pixmap);
+}
+
+
+int PUBLIC
+glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return GLX_NO_EXTENSION;
+   return (t->GetConfig)(dpy, visinfo, attrib, value);
+}
+
+
+GLXContext PUBLIC
+glXGetCurrentContext(void)
+{
+#if defined(GLX_USE_TLS)
+   return CurrentContext;
+#elif defined(THREADS)
+   return (GLXContext) _glthread_GetTSD(&ContextTSD);
+#else
+   return CurrentContext;
+#endif
+}
+
+
+GLXDrawable PUBLIC
+glXGetCurrentDrawable(void)
+{
+   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+   return gc ? gc->currentDrawable : 0;
+}
+
+
+Bool PUBLIC
+glXIsDirect(Display *dpy, GLXContext ctx)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->IsDirect)(dpy, ctx);
+}
+
+
+Bool PUBLIC
+glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{
+   Bool b;
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t) {
+      return False;
+   }
+   b = (*t->MakeCurrent)(dpy, drawable, ctx);
+   if (b) {
+      SetCurrentContext(ctx);
+   }
+   return b;
+}
+
+
+Bool PUBLIC
+glXQueryExtension(Display *dpy, int *errorb, int *event)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->QueryExtension)(dpy, errorb, event);
+}
+
+
+Bool PUBLIC
+glXQueryVersion(Display *dpy, int *maj, int *min)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->QueryVersion)(dpy, maj, min);
+}
+
+
+void PUBLIC
+glXSwapBuffers(Display *dpy, GLXDrawable drawable)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->SwapBuffers)(dpy, drawable);
+}
+
+
+void PUBLIC
+glXUseXFont(Font font, int first, int count, int listBase)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->UseXFont)(font, first, count, listBase);
+}
+
+
+void PUBLIC
+glXWaitGL(void)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->WaitGL)();
+}
+
+
+void PUBLIC
+glXWaitX(void)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->WaitX)();
+}
+
+
+
+/*** GLX_VERSION_1_1 ***/
+
+const char PUBLIC *
+glXGetClientString(Display *dpy, int name)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->GetClientString)(dpy, name);
+}
+
+
+const char PUBLIC *
+glXQueryExtensionsString(Display *dpy, int screen)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->QueryExtensionsString)(dpy, screen);
+}
+
+
+const char PUBLIC *
+glXQueryServerString(Display *dpy, int screen, int name)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->QueryServerString)(dpy, screen, name);
+}
+
+
+/*** GLX_VERSION_1_2 ***/
+
+Display PUBLIC *
+glXGetCurrentDisplay(void)
+{
+   /* Same code as in libGL's glxext.c */
+   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+   if (NULL == gc) return NULL;
+   return gc->currentDpy;
+}
+
+
+
+/*** GLX_VERSION_1_3 ***/
+
+GLXFBConfig PUBLIC *
+glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->ChooseFBConfig)(dpy, screen, attribList, nitems);
+}
+
+
+GLXContext PUBLIC
+glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateNewContext)(dpy, config, renderType, shareList, direct);
+}
+
+
+GLXPbuffer PUBLIC
+glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreatePbuffer)(dpy, config, attribList);
+}
+
+
+GLXPixmap PUBLIC
+glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreatePixmap)(dpy, config, pixmap, attribList);
+}
+
+
+GLXWindow PUBLIC
+glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateWindow)(dpy, config, win, attribList);
+}
+
+
+void PUBLIC
+glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->DestroyPbuffer)(dpy, pbuf);
+}
+
+
+void PUBLIC
+glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->DestroyPixmap)(dpy, pixmap);
+}
+
+
+void PUBLIC
+glXDestroyWindow(Display *dpy, GLXWindow window)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->DestroyWindow)(dpy, window);
+}
+
+
+GLXDrawable PUBLIC
+glXGetCurrentReadDrawable(void)
+{
+   __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+   return gc ? gc->currentReadable : 0;
+}
+
+
+int PUBLIC
+glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return GLX_NO_EXTENSION;
+   return (t->GetFBConfigAttrib)(dpy, config, attribute, value);
+}
+
+
+GLXFBConfig PUBLIC *
+glXGetFBConfigs(Display *dpy, int screen, int *nelements)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->GetFBConfigs)(dpy, screen, nelements);
+}
+
+void PUBLIC
+glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->GetSelectedEvent)(dpy, drawable, mask);
+}
+
+
+XVisualInfo PUBLIC *
+glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->GetVisualFromFBConfig)(dpy, config);
+}
+
+
+Bool PUBLIC
+glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+   Bool b;
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   b = (t->MakeContextCurrent)(dpy, draw, read, ctx);
+   if (b) {
+      SetCurrentContext(ctx);
+   }
+   return b;
+}
+
+
+int PUBLIC
+glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   assert(t);
+   if (!t)
+      return 0; /* XXX correct? */
+   return (t->QueryContext)(dpy, ctx, attribute, value);
+}
+
+
+void PUBLIC
+glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->QueryDrawable)(dpy, draw, attribute, value);
+}
+
+
+void PUBLIC
+glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->SelectEvent)(dpy, drawable, mask);
+}
+
+
+
+/*** GLX_SGI_swap_control ***/
+
+int PUBLIC
+glXSwapIntervalSGI(int interval)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->SwapIntervalSGI)(interval);
+}
+
+
+
+/*** GLX_SGI_video_sync ***/
+
+int PUBLIC
+glXGetVideoSyncSGI(unsigned int *count)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t || !glXGetCurrentContext())
+      return GLX_BAD_CONTEXT;
+   return (t->GetVideoSyncSGI)(count);
+}
+
+int PUBLIC
+glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t || !glXGetCurrentContext())
+      return GLX_BAD_CONTEXT;
+   return (t->WaitVideoSyncSGI)(divisor, remainder, count);
+}
+
+
+
+/*** GLX_SGI_make_current_read ***/
+
+Bool PUBLIC
+glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx);
+}
+
+GLXDrawable PUBLIC
+glXGetCurrentReadDrawableSGI(void)
+{
+   return glXGetCurrentReadDrawable();
+}
+
+
+#if defined(_VL_H)
+
+GLXVideoSourceSGIX PUBLIC
+glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode);
+}
+
+void PUBLIC
+glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->DestroyGLXVideoSourceSGIX)(dpy, src);
+}
+
+#endif
+
+
+/*** GLX_EXT_import_context ***/
+
+void PUBLIC
+glXFreeContextEXT(Display *dpy, GLXContext context)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->FreeContextEXT)(dpy, context);
+}
+
+GLXContextID PUBLIC
+glXGetContextIDEXT(const GLXContext context)
+{
+   return ((__GLXcontext *) context)->xid;
+}
+
+Display PUBLIC *
+glXGetCurrentDisplayEXT(void)
+{
+   return glXGetCurrentDisplay();
+}
+
+GLXContext PUBLIC
+glXImportContextEXT(Display *dpy, GLXContextID contextID)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->ImportContextEXT)(dpy, contextID);
+}
+
+int PUBLIC
+glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;  /* XXX ok? */
+   return (t->QueryContextInfoEXT)(dpy, context, attribute, value);
+}
+
+
+
+/*** GLX_SGIX_fbconfig ***/
+
+int PUBLIC
+glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value);
+}
+
+GLXFBConfigSGIX PUBLIC *
+glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements);
+}
+
+GLXPixmap PUBLIC
+glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap);
+}
+
+GLXContext PUBLIC
+glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct);
+}
+
+XVisualInfo PUBLIC *
+glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->GetVisualFromFBConfigSGIX)(dpy, config);
+}
+
+GLXFBConfigSGIX PUBLIC
+glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->GetFBConfigFromVisualSGIX)(dpy, vis);
+}
+
+
+
+/*** GLX_SGIX_pbuffer ***/
+
+GLXPbufferSGIX PUBLIC
+glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list);
+}
+
+void PUBLIC
+glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->DestroyGLXPbufferSGIX)(dpy, pbuf);
+}
+
+int PUBLIC
+glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value);
+}
+
+void PUBLIC
+glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->SelectEventSGIX)(dpy, drawable, mask);
+}
+
+void PUBLIC
+glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->GetSelectedEventSGIX)(dpy, drawable, mask);
+}
+
+
+
+/*** GLX_SGI_cushion ***/
+
+void PUBLIC
+glXCushionSGI(Display *dpy, Window win, float cushion)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->CushionSGI)(dpy, win, cushion);
+}
+
+
+
+/*** GLX_SGIX_video_resize ***/
+
+int PUBLIC
+glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window);
+}
+
+int PUBLIC
+glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
+}
+
+int PUBLIC
+glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
+}
+
+int PUBLIC
+glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh);
+}
+
+int PUBLIC
+glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype);
+}
+
+
+
+#if defined(_DM_BUFFER_H_)
+
+Bool PUBLIC
+glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer);
+}
+
+#endif
+
+
+/*** GLX_SGIX_swap_group ***/
+
+void PUBLIC
+glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (*t->JoinSwapGroupSGIX)(dpy, drawable, member);
+}
+
+
+/*** GLX_SGIX_swap_barrier ***/
+
+void PUBLIC
+glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier);
+}
+
+Bool PUBLIC
+glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max);
+}
+
+
+
+/*** GLX_SUN_get_transparent_index ***/
+
+Status PUBLIC
+glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent);
+}
+
+
+
+/*** GLX_MESA_copy_sub_buffer ***/
+
+void PUBLIC
+glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height);
+}
+
+
+
+/*** GLX_MESA_release_buffers ***/
+
+Bool PUBLIC
+glXReleaseBuffersMESA(Display *dpy, Window w)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->ReleaseBuffersMESA)(dpy, w);
+}
+
+
+
+/*** GLX_MESA_pixmap_colormap ***/
+
+GLXPixmap PUBLIC
+glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return 0;
+   return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap);
+}
+
+
+
+/*** GLX_MESA_set_3dfx_mode ***/
+
+Bool PUBLIC
+glXSet3DfxModeMESA(int mode)
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return False;
+   return (t->Set3DfxModeMESA)(mode);
+}
+
+
+
+/*** GLX_NV_vertex_array_range ***/
+
+void PUBLIC *
+glXAllocateMemoryNV( GLsizei size,
+                     GLfloat readFrequency,
+                     GLfloat writeFrequency,
+                     GLfloat priority )
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return NULL;
+   return (t->AllocateMemoryNV)(size, readFrequency, writeFrequency, priority);
+}
+
+
+void PUBLIC
+glXFreeMemoryNV( GLvoid *pointer )
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return;
+   (t->FreeMemoryNV)(pointer);
+}
+
+
+
+
+/*** GLX_MESA_agp_offset */
+
+GLuint PUBLIC
+glXGetAGPOffsetMESA( const GLvoid *pointer )
+{
+   struct _glxapi_table *t;
+   Display *dpy = glXGetCurrentDisplay();
+   GET_DISPATCH(dpy, t);
+   if (!t)
+      return ~0;
+   return (t->GetAGPOffsetMESA)(pointer);
+}
+
+
+/*** GLX_MESA_allocate_memory */
+
+void *
+glXAllocateMemoryMESA(Display *dpy, int scrn, size_t size,
+                      float readfreq, float writefreq, float priority)
+{
+   /* dummy */
+   return NULL;
+}
+
+void
+glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
+{
+   /* dummy */
+}
+
+
+GLuint
+glXGetMemoryOffsetMESA(Display *dpy, int scrn, const void *pointer)
+{
+   /* dummy */
+   return 0;
+}
+
+
+/*** GLX_EXT_texture_from_pixmap */
+
+void
+glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
+                   const int *attrib_list)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (t)
+      t->BindTexImageEXT(dpy, drawable, buffer, attrib_list);
+}
+
+void
+glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
+{
+   struct _glxapi_table *t;
+   GET_DISPATCH(dpy, t);
+   if (t)
+      t->ReleaseTexImageEXT(dpy, drawable, buffer);
+}
+
+
+/**********************************************************************/
+/* GLX API management functions                                       */
+/**********************************************************************/
+
+
+const char *
+_glxapi_get_version(void)
+{
+   return "1.3";
+}
+
+
+/*
+ * Return array of extension strings.
+ */
+const char **
+_glxapi_get_extensions(void)
+{
+   static const char *extensions[] = {
+#ifdef GLX_EXT_import_context
+      "GLX_EXT_import_context",
+#endif
+#ifdef GLX_SGI_video_sync
+      "GLX_SGI_video_sync",
+#endif
+#ifdef GLX_MESA_copy_sub_buffer
+      "GLX_MESA_copy_sub_buffer",
+#endif
+#ifdef GLX_MESA_release_buffers
+      "GLX_MESA_release_buffers",
+#endif
+#ifdef GLX_MESA_pixmap_colormap
+      "GLX_MESA_pixmap_colormap",
+#endif
+#ifdef GLX_MESA_set_3dfx_mode
+      "GLX_MESA_set_3dfx_mode",
+#endif
+#ifdef GLX_SGIX_fbconfig
+      "GLX_SGIX_fbconfig",
+#endif
+#ifdef GLX_SGIX_pbuffer
+      "GLX_SGIX_pbuffer",
+#endif
+#ifdef GLX_EXT_texture_from_pixmap
+      "GLX_EXT_texture_from_pixmap",
+#endif
+      NULL
+   };
+   return extensions;
+}
+
+
+/*
+ * Return size of the GLX dispatch table, in entries, not bytes.
+ */
+GLuint
+_glxapi_get_dispatch_table_size(void)
+{
+   return sizeof(struct _glxapi_table) / sizeof(void *);
+}
+
+
+static int
+generic_no_op_func(void)
+{
+   return 0;
+}
+
+
+/*
+ * Initialize all functions in given dispatch table to be no-ops
+ */
+void
+_glxapi_set_no_op_table(struct _glxapi_table *t)
+{
+   typedef int (*nop_func)(void);
+   nop_func *dispatch = (nop_func *) t;
+   GLuint n = _glxapi_get_dispatch_table_size();
+   GLuint i;
+   for (i = 0; i < n; i++) {
+      dispatch[i] = generic_no_op_func;
+   }
+}
+
+
+struct name_address_pair {
+   const char *Name;
+   __GLXextFuncPtr Address;
+};
+
+static struct name_address_pair GLX_functions[] = {
+   /*** GLX_VERSION_1_0 ***/
+   { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual },
+   { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext },
+   { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext },
+   { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap },
+   { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext },
+   { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap },
+   { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig },
+   { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext },
+   { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable },
+   { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect },
+   { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent },
+   { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension },
+   { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion },
+   { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers },
+   { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont },
+   { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL },
+   { "glXWaitX", (__GLXextFuncPtr) glXWaitX },
+
+   /*** GLX_VERSION_1_1 ***/
+   { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString },
+   { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString },
+   { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString },
+
+   /*** GLX_VERSION_1_2 ***/
+   { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay },
+
+   /*** GLX_VERSION_1_3 ***/
+   { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig },
+   { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext },
+   { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer },
+   { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap },
+   { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow },
+   { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer },
+   { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap },
+   { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow },
+   { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable },
+   { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib },
+   { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs },
+   { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent },
+   { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig },
+   { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent },
+   { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext },
+   { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable },
+   { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent },
+
+   /*** GLX_VERSION_1_4 ***/
+   { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress },
+
+   /*** GLX_SGI_swap_control ***/
+   { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI },
+
+   /*** GLX_SGI_video_sync ***/
+   { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI },
+   { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI },
+
+   /*** GLX_SGI_make_current_read ***/
+   { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI },
+   { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI },
+
+   /*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+   { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX },
+   { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX },
+#endif
+
+   /*** GLX_EXT_import_context ***/
+   { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT },
+   { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT },
+   { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT },
+   { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT },
+   { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT },
+
+   /*** GLX_SGIX_fbconfig ***/
+   { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX },
+   { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX },
+   { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX },
+   { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX },
+   { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX },
+   { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX },
+
+   /*** GLX_SGIX_pbuffer ***/
+   { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX },
+   { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX },
+   { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX },
+   { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX },
+   { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX },
+
+   /*** GLX_SGI_cushion ***/
+   { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI },
+
+   /*** GLX_SGIX_video_resize ***/
+   { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX },
+   { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX },
+   { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX },
+   { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX },
+   { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX },
+
+   /*** GLX_SGIX_dmbuffer **/
+#if defined(_DM_BUFFER_H_)
+   { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX },
+#endif
+
+   /*** GLX_SGIX_swap_group ***/
+   { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX },
+
+   /*** GLX_SGIX_swap_barrier ***/
+   { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX },
+   { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX },
+
+   /*** GLX_SUN_get_transparent_index ***/
+   { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN },
+
+   /*** GLX_MESA_copy_sub_buffer ***/
+   { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA },
+
+   /*** GLX_MESA_pixmap_colormap ***/
+   { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA },
+
+   /*** GLX_MESA_release_buffers ***/
+   { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA },
+
+   /*** GLX_MESA_set_3dfx_mode ***/
+   { "glXSet3DfxModeMESA", (__GLXextFuncPtr) glXSet3DfxModeMESA },
+
+   /*** GLX_ARB_get_proc_address ***/
+   { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB },
+
+   /*** GLX_NV_vertex_array_range ***/
+   { "glXAllocateMemoryNV", (__GLXextFuncPtr) glXAllocateMemoryNV },
+   { "glXFreeMemoryNV", (__GLXextFuncPtr) glXFreeMemoryNV },
+
+   /*** GLX_MESA_agp_offset ***/
+   { "glXGetAGPOffsetMESA", (__GLXextFuncPtr) glXGetAGPOffsetMESA },
+
+   /*** GLX_MESA_allocate_memory ***/
+   { "glXAllocateMemoryMESA", (__GLXextFuncPtr) glXAllocateMemoryMESA },
+   { "glXFreeMemoryMESA", (__GLXextFuncPtr) glXFreeMemoryMESA },
+   { "glXGetMemoryOffsetMESA", (__GLXextFuncPtr) glXGetMemoryOffsetMESA },
+
+   /*** GLX_EXT_texture_from_pixmap ***/
+   { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT },
+   { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT },
+
+   { NULL, NULL }   /* end of list */
+};
+
+
+
+/*
+ * Return address of named glX function, or NULL if not found.
+ */
+__GLXextFuncPtr
+_glxapi_get_proc_address(const char *funcName)
+{
+   GLuint i;
+   for (i = 0; GLX_functions[i].Name; i++) {
+      if (strcmp(GLX_functions[i].Name, funcName) == 0)
+         return GLX_functions[i].Address;
+   }
+   return NULL;
+}
+
+
+
+/*
+ * This function does not get dispatched through the dispatch table
+ * since it's really a "meta" function.
+ */
+__GLXextFuncPtr
+glXGetProcAddressARB(const GLubyte *procName)
+{
+   __GLXextFuncPtr f;
+
+   f = _glxapi_get_proc_address((const char *) procName);
+   if (f) {
+      return f;
+   }
+
+   f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName);
+   return f;
+}
+
+
+/* GLX 1.4 */
+void (*glXGetProcAddress(const GLubyte *procName))()
+{
+   return glXGetProcAddressARB(procName);
+}
diff --git a/src/mesa/pipe/xlib/glxapi.h b/src/mesa/pipe/xlib/glxapi.h
new file mode 100644 (file)
index 0000000..37de81e
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.3
+ * 
+ * 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.
+ */
+
+
+#ifndef _glxapi_h_
+#define _glxapi_h_
+
+
+#define GLX_GLXEXT_PROTOTYPES
+#include "GL/glx.h"
+
+
+/* The GLX API dispatcher (i.e. this code) is being built into stand-alone
+ * Mesa.  We don't know anything about XFree86 or real GLX so we define a
+ * minimal __GLXContextRec here so some of the functions in this file can
+ * work properly.
+ */
+typedef struct __GLXcontextRec {
+   Display *currentDpy;
+   GLboolean isDirect;
+   GLXDrawable currentDrawable;
+   GLXDrawable currentReadable;
+   XID xid;
+} __GLXcontext;
+
+
+/*
+ * Almost all the GLX API functions get routed through this dispatch table.
+ * The exceptions are the glXGetCurrentXXX() functions.
+ *
+ * This dispatch table allows multiple GLX client-side modules to coexist.
+ * Specifically, a real GLX library (like SGI's or the Utah GLX) and Mesa's
+ * pseudo-GLX can be present at the same time.  The former being used on
+ * GLX-enabled X servers and the later on non-GLX X servers.
+ *
+ * Red Hat has been using this since Red Hat Linux 7.0 (I think).
+ * This'll be a standard feature in XFree86 4.3.  It basically allows one
+ * libGL to do both DRI-rendering and "fake GLX" rendering to X displays
+ * that lack the GLX extension.
+ */
+struct _glxapi_table {
+   /*** GLX_VERSION_1_0 ***/
+   XVisualInfo *(*ChooseVisual)(Display *dpy, int screen, int *list);
+   void (*CopyContext)(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
+   GLXContext (*CreateContext)(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct);
+   GLXPixmap (*CreateGLXPixmap)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap);
+   void (*DestroyContext)(Display *dpy, GLXContext ctx);
+   void (*DestroyGLXPixmap)(Display *dpy, GLXPixmap pixmap);
+   int (*GetConfig)(Display *dpy, XVisualInfo *visinfo, int attrib, int *value);
+   /*GLXContext (*GetCurrentContext)(void);*/
+   /*GLXDrawable (*GetCurrentDrawable)(void);*/
+   Bool (*IsDirect)(Display *dpy, GLXContext ctx);
+   Bool (*MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+   Bool (*QueryExtension)(Display *dpy, int *errorb, int *event);
+   Bool (*QueryVersion)(Display *dpy, int *maj, int *min);
+   void (*SwapBuffers)(Display *dpy, GLXDrawable drawable);
+   void (*UseXFont)(Font font, int first, int count, int listBase);
+   void (*WaitGL)(void);
+   void (*WaitX)(void);
+
+   /*** GLX_VERSION_1_1 ***/
+   const char *(*GetClientString)(Display *dpy, int name);
+   const char *(*QueryExtensionsString)(Display *dpy, int screen);
+   const char *(*QueryServerString)(Display *dpy, int screen, int name);
+
+   /*** GLX_VERSION_1_2 ***/
+   /*Display *(*GetCurrentDisplay)(void);*/
+
+   /*** GLX_VERSION_1_3 ***/
+   GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems);
+   GLXContext (*CreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct);
+   GLXPbuffer (*CreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attribList);
+   GLXPixmap (*CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList);
+   GLXWindow (*CreateWindow)(Display *dpy, GLXFBConfig config, Window win, const int *attribList);
+   void (*DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf);
+   void (*DestroyPixmap)(Display *dpy, GLXPixmap pixmap);
+   void (*DestroyWindow)(Display *dpy, GLXWindow window);
+   /*GLXDrawable (*GetCurrentReadDrawable)(void);*/
+   int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value);
+   GLXFBConfig *(*GetFBConfigs)(Display *dpy, int screen, int *nelements);
+   void (*GetSelectedEvent)(Display *dpy, GLXDrawable drawable, unsigned long *mask);
+   XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config);
+   Bool (*MakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+   int (*QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value);
+   void (*QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+   void (*SelectEvent)(Display *dpy, GLXDrawable drawable, unsigned long mask);
+
+   /*** GLX_SGI_swap_control ***/
+   int (*SwapIntervalSGI)(int);
+
+   /*** GLX_SGI_video_sync ***/
+   int (*GetVideoSyncSGI)(unsigned int *count);
+   int (*WaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count);
+
+   /*** GLX_SGI_make_current_read ***/
+   Bool (*MakeCurrentReadSGI)(Display *, GLXDrawable, GLXDrawable, GLXContext);
+   /*GLXDrawable (*GetCurrentReadDrawableSGI)(void);*/
+
+   /*** GLX_SGIX_video_source (needs video library) ***/
+#if defined(_VL_H_)
+   GLXVideoSourceSGIX (*CreateGLXVideoSourceSGIX)(Display *, int, VLServer, VLPath, int, VLNode);
+   void (*DestroyGLXVideoSourceSGIX)(Display *, GLXVideoSourceSGIX);
+#else
+   void *CreateGLXVideoSourceSGIX;
+   void *DestroyGLXVideoSourceSGIX;
+#endif
+
+   /*** GLX_EXT_import_context ***/
+   void (*FreeContextEXT)(Display *dpy, GLXContext context);
+   GLXContextID (*GetContextIDEXT)(const GLXContext context);
+   /*Display *(*GetCurrentDisplayEXT)(void);*/
+   GLXContext (*ImportContextEXT)(Display *dpy, GLXContextID contextID);
+   int (*QueryContextInfoEXT)(Display *dpy, GLXContext context, int attribute,int *value);
+
+   /*** GLX_SGIX_fbconfig ***/
+   int (*GetFBConfigAttribSGIX)(Display *, GLXFBConfigSGIX, int, int *);
+   GLXFBConfigSGIX * (*ChooseFBConfigSGIX)(Display *, int, int *, int *);
+   GLXPixmap (*CreateGLXPixmapWithConfigSGIX)(Display *, GLXFBConfigSGIX, Pixmap);
+   GLXContext (*CreateContextWithConfigSGIX)(Display *, GLXFBConfigSGIX, int, GLXContext, Bool);
+   XVisualInfo * (*GetVisualFromFBConfigSGIX)(Display *, GLXFBConfigSGIX);
+   GLXFBConfigSGIX (*GetFBConfigFromVisualSGIX)(Display *, XVisualInfo *);
+
+   /*** GLX_SGIX_pbuffer ***/
+   GLXPbufferSGIX (*CreateGLXPbufferSGIX)(Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *);
+   void (*DestroyGLXPbufferSGIX)(Display *, GLXPbufferSGIX);
+   int (*QueryGLXPbufferSGIX)(Display *, GLXPbufferSGIX, int, unsigned int *);
+   void (*SelectEventSGIX)(Display *, GLXDrawable, unsigned long);
+   void (*GetSelectedEventSGIX)(Display *, GLXDrawable, unsigned long *);
+
+   /*** GLX_SGI_cushion ***/
+   void (*CushionSGI)(Display *, Window, float);
+
+   /*** GLX_SGIX_video_resize ***/
+   int (*BindChannelToWindowSGIX)(Display *, int, int, Window);
+   int (*ChannelRectSGIX)(Display *, int, int, int, int, int, int);
+   int (*QueryChannelRectSGIX)(Display *, int, int, int *, int *, int *, int *);
+   int (*QueryChannelDeltasSGIX)(Display *, int, int, int *, int *, int *, int *);
+   int (*ChannelRectSyncSGIX)(Display *, int, int, GLenum);
+
+   /*** GLX_SGIX_dmbuffer (needs dmedia library) ***/
+#if defined (_DM_BUFFER_H_)
+   Bool (*AssociateDMPbufferSGIX)(Display *, GLXPbufferSGIX, DMparams *, DMbuffer);
+#else
+   void *AssociciateDMPbufferSGIX;
+#endif
+
+   /*** GLX_SGIX_swap_group ***/
+   void (*JoinSwapGroupSGIX)(Display *, GLXDrawable, GLXDrawable);
+
+   /*** GLX_SGIX_swap_barrier ***/
+   void (*BindSwapBarrierSGIX)(Display *, GLXDrawable, int);
+   Bool (*QueryMaxSwapBarriersSGIX)(Display *, int, int *);
+
+   /*** GLX_SUN_get_transparent_index ***/
+   Status (*GetTransparentIndexSUN)(Display *, Window, Window, long *);
+
+   /*** GLX_MESA_copy_sub_buffer ***/
+   void (*CopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
+   /*** GLX_MESA_release_buffers ***/
+   Bool (*ReleaseBuffersMESA)(Display *dpy, Window w);
+
+   /*** GLX_MESA_pixmap_colormap ***/
+   GLXPixmap (*CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap);
+
+   /*** GLX_MESA_set_3dfx_mode ***/
+   Bool (*Set3DfxModeMESA)(int mode);
+
+   /*** GLX_NV_vertex_array_range ***/
+   void * (*AllocateMemoryNV)( GLsizei size,
+                               GLfloat readFrequency,
+                               GLfloat writeFrequency,
+                               GLfloat priority );
+   void (*FreeMemoryNV)( GLvoid *pointer );
+
+   /*** GLX_MESA_agp_offset ***/
+   GLuint (*GetAGPOffsetMESA)( const GLvoid *pointer );
+
+   /*** GLX_EXT_texture_from_pixmap ***/
+   void (*BindTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer,
+                           const int *attrib_list);
+   void (*ReleaseTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer);
+};
+
+
+
+extern const char *
+_glxapi_get_version(void);
+
+
+extern const char **
+_glxapi_get_extensions(void);
+
+
+extern GLuint
+_glxapi_get_dispatch_table_size(void);
+
+
+extern void
+_glxapi_set_no_op_table(struct _glxapi_table *t);
+
+
+extern __GLXextFuncPtr
+_glxapi_get_proc_address(const char *funcName);
+
+
+#endif
diff --git a/src/mesa/pipe/xlib/glxheader.h b/src/mesa/pipe/xlib/glxheader.h
new file mode 100644 (file)
index 0000000..a402191
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.1
+ * 
+ * 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.
+ */
+
+
+#ifndef GLX_HEADER_H
+#define GLX_HEADER_H
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include "glheader.h"
+
+#ifdef XFree86Server
+
+# include "resource.h"
+# include "windowstr.h"
+
+#else
+
+# include <X11/Xlib.h>
+# include <X11/Xlibint.h>
+# include <X11/Xutil.h>
+# ifdef USE_XSHM  /* was SHM */
+#  include <sys/ipc.h>
+#  include <sys/shm.h>
+#  include <X11/extensions/XShm.h>
+# endif
+# include <GL/glx.h>
+# include <sys/time.h>
+
+#endif
+
+
+
+/* this silences a compiler warning on several systems */
+struct timespec;
+struct itimerspec;
+
+
+#endif /*GLX_HEADER*/
diff --git a/src/mesa/pipe/xlib/realglx.c b/src/mesa/pipe/xlib/realglx.c
new file mode 100644 (file)
index 0000000..30adb74
--- /dev/null
@@ -0,0 +1,180 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ * 
+ * Copyright (C) 1999-2002  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 <assert.h>
+#include <GL/glx.h>
+#include "realglx.h"
+#include "glxapi.h"
+
+
+struct _glxapi_table *
+_real_GetGLXDispatchTable(void)
+{
+   static struct _glxapi_table glx;
+
+   /* be sure our dispatch table size <= libGL's table */
+   {
+      GLuint size = sizeof(struct _glxapi_table) / sizeof(void *);
+      (void) size;
+      assert(_glxapi_get_dispatch_table_size() >= size);
+   }
+
+   /* initialize the whole table to no-ops */
+   _glxapi_set_no_op_table(&glx);
+
+   /* now initialize the table with the functions I implement */
+
+   /*** GLX_VERSION_1_0 ***/
+   glx.ChooseVisual = _real_glXChooseVisual;
+   glx.CopyContext = _real_glXCopyContext;
+   glx.CreateContext = _real_glXCreateContext;
+   glx.CreateGLXPixmap = _real_glXCreateGLXPixmap;
+   glx.DestroyContext = _real_glXDestroyContext;
+   glx.DestroyGLXPixmap = _real_glXDestroyGLXPixmap;
+   glx.GetConfig = _real_glXGetConfig;
+   /*glx.GetCurrentContext = _real_glXGetCurrentContext;*/
+   /*glx.GetCurrentDrawable = _real_glXGetCurrentDrawable;*/
+   glx.IsDirect = _real_glXIsDirect;
+   glx.MakeCurrent = _real_glXMakeCurrent;
+   glx.QueryExtension = _real_glXQueryExtension;
+   glx.QueryVersion = _real_glXQueryVersion;
+   glx.SwapBuffers = _real_glXSwapBuffers;
+   glx.UseXFont = _real_glXUseXFont;
+   glx.WaitGL = _real_glXWaitGL;
+   glx.WaitX = _real_glXWaitX;
+
+   /*** GLX_VERSION_1_1 ***/
+   glx.GetClientString = _real_glXGetClientString;
+   glx.QueryExtensionsString = _real_glXQueryExtensionsString;
+   glx.QueryServerString = _real_glXQueryServerString;
+
+   /*** GLX_VERSION_1_2 ***/
+   /*glx.GetCurrentDisplay = _real_glXGetCurrentDisplay;*/
+
+   /*** GLX_VERSION_1_3 ***/
+   glx.ChooseFBConfig = _real_glXChooseFBConfig;
+   glx.CreateNewContext = _real_glXCreateNewContext;
+   glx.CreatePbuffer = _real_glXCreatePbuffer;
+   glx.CreatePixmap = _real_glXCreatePixmap;
+   glx.CreateWindow = _real_glXCreateWindow;
+   glx.DestroyPbuffer = _real_glXDestroyPbuffer;
+   glx.DestroyPixmap = _real_glXDestroyPixmap;
+   glx.DestroyWindow = _real_glXDestroyWindow;
+   /*glx.GetCurrentReadDrawable = _real_glXGetCurrentReadDrawable;*/
+   glx.GetFBConfigAttrib = _real_glXGetFBConfigAttrib;
+   glx.GetFBConfigs = _real_glXGetFBConfigs;
+   glx.GetSelectedEvent = _real_glXGetSelectedEvent;
+   glx.GetVisualFromFBConfig = _real_glXGetVisualFromFBConfig;
+   glx.MakeContextCurrent = _real_glXMakeContextCurrent;
+   glx.QueryContext = _real_glXQueryContext;
+   glx.QueryDrawable = _real_glXQueryDrawable;
+   glx.SelectEvent = _real_glXSelectEvent;
+
+   /*** GLX_SGI_swap_control ***/
+   glx.SwapIntervalSGI = _real_glXSwapIntervalSGI;
+
+   /*** GLX_SGI_video_sync ***/
+   glx.GetVideoSyncSGI = _real_glXGetVideoSyncSGI;
+   glx.WaitVideoSyncSGI = _real_glXWaitVideoSyncSGI;
+
+   /*** GLX_SGI_make_current_read ***/
+   glx.MakeCurrentReadSGI = _real_glXMakeCurrentReadSGI;
+   /*glx.GetCurrentReadDrawableSGI = _real_glXGetCurrentReadDrawableSGI;*/
+
+#if defined(_VL_H)
+   /*** GLX_SGIX_video_source ***/
+   glx.CreateGLXVideoSourceSGIX = _real_glXCreateGLXVideoSourceSGIX;
+   glx.DestroyGLXVideoSourceSGIX = _real_glXDestroyGLXVideoSourceSGIX;
+#endif
+
+   /*** GLX_EXT_import_context ***/
+   glx.FreeContextEXT = _real_glXFreeContextEXT;
+   /*glx.GetContextIDEXT = _real_glXGetContextIDEXT;*/
+   /*glx.GetCurrentDisplayEXT = _real_glXGetCurrentDisplayEXT;*/
+   glx.ImportContextEXT = _real_glXImportContextEXT;
+   glx.QueryContextInfoEXT = _real_glXQueryContextInfoEXT;
+
+   /*** GLX_SGIX_fbconfig ***/
+   glx.GetFBConfigAttribSGIX = _real_glXGetFBConfigAttribSGIX;
+   glx.ChooseFBConfigSGIX = _real_glXChooseFBConfigSGIX;
+   glx.CreateGLXPixmapWithConfigSGIX = _real_glXCreateGLXPixmapWithConfigSGIX;
+   glx.CreateContextWithConfigSGIX = _real_glXCreateContextWithConfigSGIX;
+   glx.GetVisualFromFBConfigSGIX = _real_glXGetVisualFromFBConfigSGIX;
+   glx.GetFBConfigFromVisualSGIX = _real_glXGetFBConfigFromVisualSGIX;
+
+   /*** GLX_SGIX_pbuffer ***/
+   glx.CreateGLXPbufferSGIX = _real_glXCreateGLXPbufferSGIX;
+   glx.DestroyGLXPbufferSGIX = _real_glXDestroyGLXPbufferSGIX;
+   glx.QueryGLXPbufferSGIX = _real_glXQueryGLXPbufferSGIX;
+   glx.SelectEventSGIX = _real_glXSelectEventSGIX;
+   glx.GetSelectedEventSGIX = _real_glXGetSelectedEventSGIX;
+
+   /*** GLX_SGI_cushion ***/
+   glx.CushionSGI = _real_glXCushionSGI;
+
+   /*** GLX_SGIX_video_resize ***/
+   glx.BindChannelToWindowSGIX = _real_glXBindChannelToWindowSGIX;
+   glx.ChannelRectSGIX = _real_glXChannelRectSGIX;
+   glx.QueryChannelRectSGIX = _real_glXQueryChannelRectSGIX;
+   glx.QueryChannelDeltasSGIX = _real_glXQueryChannelDeltasSGIX;
+   glx.ChannelRectSyncSGIX = _real_glXChannelRectSyncSGIX;
+
+#if defined(_DM_BUFFER_H_)
+   /*** (GLX_SGIX_dmbuffer ***/
+   glx.AssociateDMPbufferSGIX = NULL;
+#endif
+
+   /*** GLX_SGIX_swap_group ***/
+   glx.JoinSwapGroupSGIX = _real_glXJoinSwapGroupSGIX;
+
+   /*** GLX_SGIX_swap_barrier ***/
+   glx.BindSwapBarrierSGIX = _real_glXBindSwapBarrierSGIX;
+   glx.QueryMaxSwapBarriersSGIX = _real_glXQueryMaxSwapBarriersSGIX;
+
+   /*** GLX_SUN_get_transparent_index ***/
+   glx.GetTransparentIndexSUN = _real_glXGetTransparentIndexSUN;
+
+   /*** GLX_MESA_copy_sub_buffer ***/
+   glx.CopySubBufferMESA = _real_glXCopySubBufferMESA;
+
+   /*** GLX_MESA_release_buffers ***/
+   glx.ReleaseBuffersMESA = _real_glXReleaseBuffersMESA;
+
+   /*** GLX_MESA_pixmap_colormap ***/
+   glx.CreateGLXPixmapMESA = _real_glXCreateGLXPixmapMESA;
+
+   /*** GLX_MESA_set_3dfx_mode ***/
+   glx.Set3DfxModeMESA = _real_glXSet3DfxModeMESA;
+
+   /*** GLX_NV_vertex_array_range ***/
+   glx.AllocateMemoryNV = _real_glXAllocateMemoryNV;
+   glx.FreeMemoryNV = _real_glXFreeMemoryNV;
+
+   /*** GLX_MESA_agp_offset ***/
+   glx.GetAGPOffsetMESA = _real_glXGetAGPOffsetMESA;
+
+   return &glx;
+}
diff --git a/src/mesa/pipe/xlib/realglx.h b/src/mesa/pipe/xlib/realglx.h
new file mode 100644 (file)
index 0000000..150129d
--- /dev/null
@@ -0,0 +1,326 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ * 
+ * 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.
+ */
+
+
+#ifndef REALGLX_H
+#define REALGLX_H
+
+
+extern struct _glxapi_table *
+_real_GetGLXDispatchTable(void);
+
+
+/*
+ * Basically just need these to prevent compiler warnings.
+ */
+
+
+extern XVisualInfo *
+_real_glXChooseVisual( Display *dpy, int screen, int *list );
+
+extern GLXContext
+_real_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+                        GLXContext share_list, Bool direct );
+
+extern GLXPixmap
+_real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap );
+
+extern GLXPixmap
+_real_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+                              Pixmap pixmap, Colormap cmap );
+
+extern void
+_real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap );
+
+extern void
+_real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+                      unsigned long mask );
+
+extern Bool
+_real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx );
+
+extern Bool
+_real_glXQueryExtension( Display *dpy, int *errorb, int *event );
+
+extern void
+_real_glXDestroyContext( Display *dpy, GLXContext ctx );
+
+extern Bool
+_real_glXIsDirect( Display *dpy, GLXContext ctx );
+
+extern void
+_real_glXSwapBuffers( Display *dpy, GLXDrawable drawable );
+
+extern void
+_real_glXUseXFont( Font font, int first, int count, int listbase );
+
+extern Bool
+_real_glXQueryVersion( Display *dpy, int *maj, int *min );
+
+extern int
+_real_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+                    int attrib, int *value );
+
+extern void
+_real_glXWaitGL( void );
+
+
+extern void
+_real_glXWaitX( void );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXQueryExtensionsString( Display *dpy, int screen );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXQueryServerString( Display *dpy, int screen, int name );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXGetClientString( Display *dpy, int name );
+
+
+/*
+ * GLX 1.3 and later
+ */
+
+extern GLXFBConfig *
+_real_glXChooseFBConfig( Display *dpy, int screen,
+                         const int *attribList, int *nitems );
+
+extern int
+_real_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
+                            int attribute, int *value );
+
+extern GLXFBConfig *
+_real_glXGetFBConfigs( Display *dpy, int screen, int *nelements );
+
+extern XVisualInfo *
+_real_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config );
+
+extern GLXWindow
+_real_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
+                       const int *attribList );
+
+extern void
+_real_glXDestroyWindow( Display *dpy, GLXWindow window );
+
+extern GLXPixmap
+_real_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
+                       const int *attribList );
+
+extern void
+_real_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap );
+
+extern GLXPbuffer
+_real_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+                        const int *attribList );
+
+extern void
+_real_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf );
+
+extern void
+_real_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
+                        unsigned int *value );
+
+extern GLXContext
+_real_glXCreateNewContext( Display *dpy, GLXFBConfig config,
+                           int renderType, GLXContext shareList, Bool direct );
+
+
+extern Bool
+_real_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
+                             GLXDrawable read, GLXContext ctx );
+
+extern int
+_real_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value );
+
+extern void
+_real_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask );
+
+extern void
+_real_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
+                           unsigned long *mask );
+
+#ifdef GLX_SGI_swap_control
+extern int
+_real_glXSwapIntervalSGI(int interval);
+#endif
+
+
+#ifdef GLX_SGI_video_sync
+extern int
+_real_glXGetVideoSyncSGI(unsigned int *count);
+
+extern int
+_real_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count);
+#endif
+
+
+#ifdef GLX_SGI_make_current_read
+extern Bool
+_real_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+
+extern GLXDrawable
+_real_glXGetCurrentReadDrawableSGI(void);
+#endif
+
+#if defined(_VL_H) && defined(GLX_SGIX_video_source)
+extern GLXVideoSourceSGIX
+_real_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
+
+extern void
+_real_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src);
+#endif
+
+#ifdef GLX_EXT_import_context
+extern void
+_real_glXFreeContextEXT(Display *dpy, GLXContext context);
+
+extern GLXContextID
+_real_glXGetContextIDEXT(const GLXContext context);
+
+extern Display *
+_real_glXGetCurrentDisplayEXT(void);
+
+extern GLXContext
+_real_glXImportContextEXT(Display *dpy, GLXContextID contextID);
+
+extern int
+_real_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value);
+#endif
+
+#ifdef GLX_SGIX_fbconfig
+extern int
+_real_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+
+extern GLXFBConfigSGIX *
+_real_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements);
+
+extern GLXPixmap
+_real_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
+
+extern GLXContext
+_real_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+
+extern XVisualInfo *
+_real_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config);
+
+extern GLXFBConfigSGIX
+_real_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis);
+#endif
+
+#ifdef GLX_SGIX_pbuffer
+extern GLXPbufferSGIX
+_real_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
+
+extern void
+_real_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf);
+
+extern int
+_real_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
+
+extern void
+_real_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask);
+
+extern void
+_real_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask);
+#endif
+
+#ifdef GLX_SGI_cushion
+extern void
+_real_glXCushionSGI(Display *dpy, Window win, float cushion);
+#endif
+
+#ifdef GLX_SGIX_video_resize
+extern int
+_real_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window);
+
+extern int
+_real_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h);
+
+extern int
+_real_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h);
+
+extern int
+_real_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+
+extern int
+_real_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype);
+#endif
+
+#if defined(_DM_BUFFER_H_) && defined(GLX_SGIX_dmbuffer)
+extern Bool
+_real_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
+#endif
+
+#ifdef GLX_SGIX_swap_group
+extern void
+_real_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member);
+#endif
+
+#ifdef GLX_SGIX_swap_barrier
+extern void
+_real_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier);
+
+extern Bool
+_real_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max);
+#endif
+
+#ifdef GLX_SUN_get_transparent_index
+extern Status
+_real_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent);
+#endif
+
+#ifdef GLX_MESA_release_buffers
+extern Bool
+_real_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d );
+#endif
+
+#ifdef GLX_MESA_set_3dfx_mode
+extern Bool
+_real_glXSet3DfxModeMESA( int mode );
+#endif
+
+#ifdef GLX_NV_vertex_array_range
+extern void *
+_real_glXAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+extern void
+_real_glXFreeMemoryNV(GLvoid *pointer);
+#endif
+
+#ifdef GLX_MESA_agp_offset
+extern GLuint
+_real_glXGetAGPOffsetMESA(const GLvoid *pointer);
+#endif
+
+#ifdef GLX_MESA_copy_sub_buffer
+extern void
+_real_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+                            int x, int y, int width, int height );
+#endif
+
+#endif /* REALGLX_H */
diff --git a/src/mesa/pipe/xlib/xfonts.c b/src/mesa/pipe/xlib/xfonts.c
new file mode 100644 (file)
index 0000000..d72c600
--- /dev/null
@@ -0,0 +1,377 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-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.
+ */
+
+
+/* xfonts.c -- glXUseXFont() for Mesa written by
+ * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
+ */
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include "glxheader.h"
+#include "context.h"
+#include "imports.h"
+#include "xfonts.h"
+
+
+/* Some debugging info.  */
+
+#ifdef DEBUG
+#undef _R
+#undef _G
+#undef _B
+#include <ctype.h>
+
+int debug_xfonts = 0;
+
+static void
+dump_char_struct(XCharStruct * ch, char *prefix)
+{
+   printf("%slbearing = %d, rbearing = %d, width = %d\n",
+         prefix, ch->lbearing, ch->rbearing, ch->width);
+   printf("%sascent = %d, descent = %d, attributes = %u\n",
+         prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
+}
+
+static void
+dump_font_struct(XFontStruct * font)
+{
+   printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
+   printf("char_or_byte2 = (%u,%u)\n",
+         font->min_char_or_byte2, font->max_char_or_byte2);
+   printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
+   printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
+   printf("default_char = %c (\\%03o)\n",
+         (char) (isprint(font->default_char) ? font->default_char : ' '),
+         font->default_char);
+   dump_char_struct(&font->min_bounds, "min> ");
+   dump_char_struct(&font->max_bounds, "max> ");
+#if 0
+   for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
+      char prefix[8];
+      sprintf(prefix, "%d> ", c);
+      dump_char_struct(&font->per_char[c], prefix);
+   }
+#endif
+}
+
+static void
+dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
+{
+   unsigned int x, y;
+
+   printf("    ");
+   for (x = 0; x < 8 * width; x++)
+      printf("%o", 7 - (x % 8));
+   putchar('\n');
+   for (y = 0; y < height; y++) {
+      printf("%3o:", y);
+      for (x = 0; x < 8 * width; x++)
+        putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
+                                                                        8))))
+                ? '*' : '.');
+      printf("   ");
+      for (x = 0; x < width; x++)
+        printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
+      putchar('\n');
+   }
+}
+#endif /* DEBUG */
+
+
+/* Implementation.  */
+
+/* Fill a BITMAP with a character C from thew current font
+   in the graphics context GC.  WIDTH is the width in bytes
+   and HEIGHT is the height in bits.
+
+   Note that the generated bitmaps must be used with
+
+        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);
+
+   Possible optimizations:
+
+     * use only one reusable pixmap with the maximum dimensions.
+     * draw the entire font into a single pixmap (careful with
+       proportional fonts!).
+*/
+
+
+/*
+ * Generate OpenGL-compatible bitmap.
+ */
+static void
+fill_bitmap(Display * dpy, Window win, GC gc,
+           unsigned int width, unsigned int height,
+           int x0, int y0, unsigned int c, GLubyte * bitmap)
+{
+   XImage *image;
+   unsigned int x, y;
+   Pixmap pixmap;
+   XChar2b char2b;
+
+   pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
+   XSetForeground(dpy, gc, 0);
+   XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
+   XSetForeground(dpy, gc, 1);
+
+   char2b.byte1 = (c >> 8) & 0xff;
+   char2b.byte2 = (c & 0xff);
+
+   XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
+
+   image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
+   if (image) {
+      /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
+      for (y = 0; y < height; y++)
+        for (x = 0; x < 8 * width; x++)
+           if (XGetPixel(image, x, y))
+              bitmap[width * (height - y - 1) + x / 8] |=
+                 (1 << (7 - (x % 8)));
+      XDestroyImage(image);
+   }
+
+   XFreePixmap(dpy, pixmap);
+}
+
+/*
+ * determine if a given glyph is valid and return the
+ * corresponding XCharStruct.
+ */
+static XCharStruct *
+isvalid(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
+Fake_glXUseXFont(Font font, int first, int count, int listbase)
+{
+   Display *dpy;
+   Window win;
+   Pixmap pixmap;
+   GC gc;
+   XGCValues values;
+   unsigned long valuemask;
+   XFontStruct *fs;
+   GLint swapbytes, lsbfirst, rowlength;
+   GLint skiprows, skippixels, alignment;
+   unsigned int max_width, max_height, max_bm_width, max_bm_height;
+   GLubyte *bm;
+   int i;
+
+   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 bitmap that can fit all characters.  */
+   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
+   max_bm_width = (max_width + 7) / 8;
+   max_bm_height = max_height;
+
+   bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte));
+   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);
+
+   pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
+   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);
+   XFreePixmap(dpy, pixmap);
+
+#ifdef DEBUG
+   if (debug_xfonts)
+      dump_font_struct(fs);
+#endif
+
+   for (i = 0; i < count; i++) {
+      unsigned int width, height, bm_width, bm_height;
+      GLfloat x0, y0, dx, dy;
+      XCharStruct *ch;
+      int x, y;
+      unsigned int c = first + i;
+      int list = listbase + i;
+      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
+      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.  */
+      width = ch->rbearing - ch->lbearing;
+      height = ch->ascent + ch->descent;
+      x0 = -ch->lbearing;
+      y0 = ch->descent - 0;    /* XXX used to subtract 1 here */
+      /* but that caused a conformace failure */
+      dx = ch->width;
+      dy = 0;
+
+      /* X11's starting point.  */
+      x = -ch->lbearing;
+      y = ch->ascent;
+
+      /* Round the width to a multiple of eight.  We will use this also
+         for the pixmap for capturing the X11 font.  This is slightly
+         inefficient, but it makes the OpenGL part real easy.  */
+      bm_width = (width + 7) / 8;
+      bm_height = height;
+
+      glNewList(list, GL_COMPILE);
+      if (valid && (bm_width > 0) && (bm_height > 0)) {
+
+        MEMSET(bm, '\0', bm_width * bm_height);
+        fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
+
+        glBitmap(width, height, x0, y0, dx, dy, bm);
+#ifdef DEBUG
+        if (debug_xfonts) {
+           printf("width/height = %u/%u\n", width, height);
+           printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
+           dump_bitmap(bm_width, bm_height, bm);
+        }
+#endif
+      }
+      else {
+        glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
+      }
+      glEndList();
+   }
+
+   FREE(bm);
+   XFreeFontInfo(NULL, fs, 1);
+   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 --git a/src/mesa/pipe/xlib/xfonts.h b/src/mesa/pipe/xlib/xfonts.h
new file mode 100644 (file)
index 0000000..e36f42f
--- /dev/null
@@ -0,0 +1,41 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-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.
+ */
+
+
+#ifndef XFONTS_H
+#define XFONTS_H
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include <X11/Xlib.h>
+
+
+extern void Fake_glXUseXFont( Font font, int first, int count, int listbase );
+
+
+#endif
+
diff --git a/src/mesa/pipe/xlib/xm_api.c b/src/mesa/pipe/xlib/xm_api.c
new file mode 100644 (file)
index 0000000..08c98ea
--- /dev/null
@@ -0,0 +1,2554 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file xm_api.c
+ *
+ * All the XMesa* API functions.
+ *
+ *
+ * NOTES:
+ *
+ * The window coordinate system origin (0,0) is in the lower-left corner
+ * of the window.  X11's window coordinate origin is in the upper-left
+ * corner of the window.  Therefore, most drawing functions in this
+ * file have to flip Y coordinates.
+ *
+ * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
+ * in support for the MIT Shared Memory extension.  If enabled, when you
+ * use an Ximage for the back buffer in double buffered mode, the "swap"
+ * operation will be faster.  You must also link with -lXext.
+ *
+ * Byte swapping:  If the Mesa host and the X display use a different
+ * byte order then there's some trickiness to be aware of when using
+ * XImages.  The byte ordering used for the XImage is that of the X
+ * display, not the Mesa host.
+ * The color-to-pixel encoding for True/DirectColor must be done
+ * according to the display's visual red_mask, green_mask, and blue_mask.
+ * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
+ * do byte swapping if needed.  If one wants to directly "poke" the pixel
+ * into the XImage's buffer then the pixel must be byte swapped first.  In
+ * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
+ * and use XPutPixel everywhere except in the implementation of
+ * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
+ * instead of using XPutPixel we "poke" our values after byte-swapping
+ * the clear pixel value if needed.
+ *
+ */
+
+#ifdef __CYGWIN__
+#undef WIN32
+#undef __WIN32__
+#endif
+
+#include "glxheader.h"
+#include "GL/xmesa.h"
+#include "xmesaP.h"
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "glthread.h"
+#include "imports.h"
+#include "macros.h"
+#include "renderbuffer.h"
+#include "teximage.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "vbo/vbo.h"
+#if 0
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#endif
+#include "drivers/common/driverfuncs.h"
+
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "pipe/softpipe/sp_context.h"
+#include "pipe/p_defines.h"
+
+/**
+ * Global X driver lock
+ */
+_glthread_Mutex _xmesa_lock;
+
+
+
+/**
+ * Lookup tables for HPCR pixel format:
+ */
+static short hpcr_rgbTbl[3][256] = {
+{
+ 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
+ 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
+ 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
+ 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
+ 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
+ 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
+ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
+ 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
+},
+{
+ 16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
+ 24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
+ 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
+ 32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
+ 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
+ 64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
+ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
+ 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
+},
+{
+ 32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
+ 40,  40,  41,  41,  42,  42,  43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
+ 48,  48,  49,  49,  50,  50,  51,  51,  52,  52,  53,  53,  54,  54,  55,  55,
+ 56,  56,  57,  57,  58,  58,  59,  59,  60,  60,  61,  61,  62,  62,  63,  63,
+ 64,  64,  65,  65,  66,  66,  67,  67,  68,  68,  69,  69,  70,  70,  71,  71,
+ 72,  72,  73,  73,  74,  74,  75,  75,  76,  76,  77,  77,  78,  78,  79,  79,
+ 80,  80,  81,  81,  82,  82,  83,  83,  84,  84,  85,  85,  86,  86,  87,  87,
+ 80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
+ 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
+}
+};
+
+
+
+/**********************************************************************/
+/*****                     X Utility Functions                    *****/
+/**********************************************************************/
+
+
+/**
+ * Return the host's byte order as LSBFirst or MSBFirst ala X.
+ */
+#ifndef XFree86Server
+static int host_byte_order( void )
+{
+   int i = 1;
+   char *cptr = (char *) &i;
+   return (*cptr==1) ? LSBFirst : MSBFirst;
+}
+#endif
+
+
+/**
+ * Check if the X Shared Memory extension is available.
+ * Return:  0 = not available
+ *          1 = shared XImage support available
+ *          2 = shared Pixmap support available also
+ */
+static int check_for_xshm( XMesaDisplay *display )
+{
+#if defined(USE_XSHM) && !defined(XFree86Server)
+   int major, minor, ignore;
+   Bool pixmaps;
+
+   if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
+      if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
+        return (pixmaps==True) ? 2 : 1;
+      }
+      else {
+        return 0;
+      }
+   }
+   else {
+      return 0;
+   }
+#else
+   /* No  XSHM support */
+   return 0;
+#endif
+}
+
+
+/**
+ * Apply gamma correction to an intensity value in [0..max].  Return the
+ * new intensity value.
+ */
+static GLint
+gamma_adjust( GLfloat gamma, GLint value, GLint max )
+{
+   if (gamma == 1.0) {
+      return value;
+   }
+   else {
+      double x = (double) value / (double) max;
+      return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma));
+   }
+}
+
+
+
+/**
+ * Return the true number of bits per pixel for XImages.
+ * For example, if we request a 24-bit deep visual we may actually need/get
+ * 32bpp XImages.  This function returns the appropriate bpp.
+ * Input:  dpy - the X display
+ *         visinfo - desribes the visual to be used for XImages
+ * Return:  true number of bits per pixel for XImages
+ */
+static int
+bits_per_pixel( XMesaVisual xmv )
+{
+#ifdef XFree86Server
+   const int depth = xmv->nplanes;
+   int i;
+   assert(depth > 0);
+   for (i = 0; i < screenInfo.numPixmapFormats; i++) {
+      if (screenInfo.formats[i].depth == depth)
+         return screenInfo.formats[i].bitsPerPixel;
+   }
+   return depth;  /* should never get here, but this should be safe */
+#else
+   XMesaDisplay *dpy = xmv->display;
+   XMesaVisualInfo visinfo = xmv->visinfo;
+   XMesaImage *img;
+   int bitsPerPixel;
+   /* Create a temporary XImage */
+   img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
+                      ZPixmap, 0,           /*format, offset*/
+                      (char*) MALLOC(8),    /*data*/
+                      1, 1,                 /*width, height*/
+                      32,                   /*bitmap_pad*/
+                      0                     /*bytes_per_line*/
+                     );
+   assert(img);
+   /* grab the bits/pixel value */
+   bitsPerPixel = img->bits_per_pixel;
+   /* free the XImage */
+   _mesa_free( img->data );
+   img->data = NULL;
+   XMesaDestroyImage( img );
+   return bitsPerPixel;
+#endif
+}
+
+
+
+/*
+ * Determine if a given X window ID is valid (window exists).
+ * Do this by calling XGetWindowAttributes() for the window and
+ * checking if we catch an X error.
+ * Input:  dpy - the display
+ *         win - the window to check for existance
+ * Return:  GL_TRUE - window exists
+ *          GL_FALSE - window doesn't exist
+ */
+#ifndef XFree86Server
+static GLboolean WindowExistsFlag;
+
+static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
+{
+   (void) dpy;
+   if (xerr->error_code == BadWindow) {
+      WindowExistsFlag = GL_FALSE;
+   }
+   return 0;
+}
+
+static GLboolean window_exists( XMesaDisplay *dpy, Window win )
+{
+   XWindowAttributes wa;
+   int (*old_handler)( XMesaDisplay*, XErrorEvent* );
+   WindowExistsFlag = GL_TRUE;
+   old_handler = XSetErrorHandler(window_exists_err_handler);
+   XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
+   XSetErrorHandler(old_handler);
+   return WindowExistsFlag;
+}
+
+static Status
+get_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height )
+{
+   Window root;
+   Status stat;
+   int xpos, ypos;
+   unsigned int w, h, bw, depth;
+   stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+   *width = w;
+   *height = h;
+   return stat;
+}
+#endif
+
+
+/**
+ * Return the size of the window (or pixmap) that corresponds to the
+ * given XMesaBuffer.
+ * \param width  returns width in pixels
+ * \param height  returns height in pixels
+ */
+void
+xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
+                      GLuint *width, GLuint *height)
+{
+#ifdef XFree86Server
+   *width = MIN2(b->frontxrb->drawable->width, MAX_WIDTH);
+   *height = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT);
+#else
+   Status stat;
+
+   _glthread_LOCK_MUTEX(_xmesa_lock);
+   XSync(b->xm_visual->display, 0); /* added for Chromium */
+   stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height);
+   _glthread_UNLOCK_MUTEX(_xmesa_lock);
+
+   if (!stat) {
+      /* probably querying a window that's recently been destroyed */
+      _mesa_warning(NULL, "XGetGeometry failed!\n");
+      *width = *height = 1;
+   }
+#endif
+}
+
+
+
+/**********************************************************************/
+/*****                Linked list of XMesaBuffers                 *****/
+/**********************************************************************/
+
+XMesaBuffer XMesaBufferList = NULL;
+
+
+/**
+ * Allocate a new XMesaBuffer object which corresponds to the given drawable.
+ * Note that XMesaBuffer is derived from GLframebuffer.
+ * The new XMesaBuffer will not have any size (Width=Height=0).
+ *
+ * \param d  the corresponding X drawable (window or pixmap)
+ * \param type  either WINDOW, PIXMAP or PBUFFER, describing d
+ * \param vis  the buffer's visual
+ * \param cmap  the window's colormap, if known.
+ * \return new XMesaBuffer or NULL if any problem
+ */
+static XMesaBuffer
+create_xmesa_buffer(XMesaDrawable d, BufferType type,
+                    XMesaVisual vis, XMesaColormap cmap)
+{
+   XMesaBuffer b;
+
+   ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
+
+   b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
+   if (!b)
+      return NULL;
+
+   b->display = vis->display;
+   b->xm_visual = vis;
+   b->type = type;
+   b->cmap = cmap;
+
+   _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
+   b->mesa_buffer.Delete = xmesa_delete_framebuffer;
+
+   /*
+    * Front renderbuffer
+    */
+   b->frontxrb = xmesa_create_renderbuffer(NULL, 0, &vis->mesa_visual, GL_FALSE);
+   if (!b->frontxrb) {
+      _mesa_free(b);
+      return NULL;
+   }
+   b->frontxrb->Parent = b;
+   b->frontxrb->drawable = d;
+   b->frontxrb->pixmap = (XMesaPixmap) d;
+   _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT,
+                          &b->frontxrb->St.Base);
+
+   /*
+    * Back renderbuffer
+    */
+   if (vis->mesa_visual.doubleBufferMode) {
+      b->backxrb = xmesa_create_renderbuffer(NULL, 0, &vis->mesa_visual, GL_TRUE);
+      if (!b->backxrb) {
+         /* XXX free front xrb too */
+         _mesa_free(b);
+         return NULL;
+      }
+      b->backxrb->Parent = b;
+      /* determine back buffer implementation */
+      b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP;
+      
+      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT,
+                             &b->backxrb->St.Base);
+   }
+
+   /*
+    * Software alpha planes
+    */
+   if (vis->mesa_visual.alphaBits > 0
+       && vis->undithered_pf != PF_8A8B8G8R
+       && vis->undithered_pf != PF_8A8R8G8B) {
+      /* Visual has alpha, but pixel format doesn't support it.
+       * We'll use an alpha renderbuffer wrapper.
+       */
+      b->swAlpha = GL_TRUE;
+   }
+   else {
+      b->swAlpha = GL_FALSE;
+   }
+
+   if (vis->mesa_visual.depthBits > 0 &&
+       vis->mesa_visual.stencilBits > 0) {
+      /* combined depth/stencil */
+      struct gl_renderbuffer *rb
+         = st_new_renderbuffer_fb(GL_DEPTH24_STENCIL8_EXT);
+      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_DEPTH, rb);
+      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_STENCIL, rb);
+   }
+   else {
+      if (vis->mesa_visual.depthBits > 0) {
+         struct gl_renderbuffer *rb
+         = st_new_renderbuffer_fb(GL_DEPTH_COMPONENT32);
+         _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_DEPTH, rb);
+      }
+
+      if (vis->mesa_visual.stencilBits > 0) {
+         struct gl_renderbuffer *rb
+            = st_new_renderbuffer_fb(GL_STENCIL_INDEX8_EXT);
+         _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_STENCIL, rb);
+      }
+   }
+
+   if (vis->mesa_visual.accumRedBits > 0) {
+      struct gl_renderbuffer *rb
+         = st_new_renderbuffer_fb(GL_RGBA16);
+      _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_ACCUM, rb);
+   }
+
+
+   /*
+    * Other renderbuffer (depth, stencil, etc)
+    */
+   _mesa_add_soft_renderbuffers(&b->mesa_buffer,
+                                GL_FALSE, /* color */
+                                GL_FALSE, /*vis->mesa_visual.haveDepthBuffer,*/
+                                GL_FALSE, /* stencil */
+                                GL_FALSE, /* accum */
+                                b->swAlpha,
+                                vis->mesa_visual.numAuxBuffers > 0 );
+
+   /* GLX_EXT_texture_from_pixmap */
+   b->TextureTarget = 0;
+   b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
+   b->TextureMipmap = 0;
+
+   /* insert buffer into linked list */
+   b->Next = XMesaBufferList;
+   XMesaBufferList = b;
+
+   return b;
+}
+
+
+/**
+ * Find an XMesaBuffer by matching X display and colormap but NOT matching
+ * the notThis buffer.
+ */
+XMesaBuffer
+xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
+{
+   XMesaBuffer b;
+   for (b=XMesaBufferList; b; b=b->Next) {
+      if (b->display==dpy && b->cmap==cmap && b!=notThis) {
+         return b;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Remove buffer from linked list, delete if no longer referenced.
+ */
+static void
+xmesa_free_buffer(XMesaBuffer buffer)
+{
+   XMesaBuffer prev = NULL, b;
+
+   for (b = XMesaBufferList; b; b = b->Next) {
+      if (b == buffer) {
+         struct gl_framebuffer *fb = &buffer->mesa_buffer;
+
+         /* unlink buffer from list */
+         if (prev)
+            prev->Next = buffer->Next;
+         else
+            XMesaBufferList = buffer->Next;
+
+         /* mark as delete pending */
+         fb->DeletePending = GL_TRUE;
+
+         /* Since the X window for the XMesaBuffer is going away, we don't
+          * want to dereference this pointer in the future.
+          */
+         b->frontxrb->drawable = 0;
+
+         /* Unreference.  If count = zero we'll really delete the buffer */
+         _mesa_unreference_framebuffer(&fb);
+
+         return;
+      }
+      /* continue search */
+      prev = b;
+   }
+   /* buffer not found in XMesaBufferList */
+   _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
+}
+
+
+/**
+ * Copy X color table stuff from one XMesaBuffer to another.
+ */
+static void
+copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
+{
+   MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
+   MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
+   MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
+   MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
+   dst->num_alloced = src->num_alloced;
+   MEMCPY(dst->alloced_colors, src->alloced_colors,
+          sizeof(src->alloced_colors));
+}
+
+
+
+/**********************************************************************/
+/*****                   Misc Private Functions                   *****/
+/**********************************************************************/
+
+
+/**
+ * A replacement for XAllocColor.  This function should never
+ * fail to allocate a color.  When XAllocColor fails, we return
+ * the nearest matching color.  If we have to allocate many colors
+ * this function isn't too efficient; the XQueryColors() could be
+ * done just once.
+ * Written by Michael Pichler, Brian Paul, Mark Kilgard
+ * Input:  dpy - X display
+ *         cmap - X colormap
+ *         cmapSize - size of colormap
+ * In/Out: color - the XColor struct
+ * Output:  exact - 1=exact color match, 0=closest match
+ *          alloced - 1=XAlloc worked, 0=XAlloc failed
+ */
+static void
+noFaultXAllocColor( int client,
+                    XMesaDisplay *dpy,
+                    XMesaColormap cmap,
+                    int cmapSize,
+                    XMesaColor *color,
+                    int *exact, int *alloced )
+{
+#ifdef XFree86Server
+   Pixel *ppixIn;
+   xrgb *ctable;
+#else
+   /* we'll try to cache ctable for better remote display performance */
+   static Display *prevDisplay = NULL;
+   static XMesaColormap prevCmap = 0;
+   static int prevCmapSize = 0;
+   static XMesaColor *ctable = NULL;
+#endif
+   XMesaColor subColor;
+   int i, bestmatch;
+   double mindist;       /* 3*2^16^2 exceeds long int precision. */
+
+   (void) client;
+
+   /* First try just using XAllocColor. */
+#ifdef XFree86Server
+   if (AllocColor(cmap,
+                 &color->red, &color->green, &color->blue,
+                 &color->pixel,
+                 client) == Success)
+#else
+   if (XAllocColor(dpy, cmap, color))
+#endif
+   {
+      *exact = 1;
+      *alloced = 1;
+      return;
+   }
+
+   /* Alloc failed, search for closest match */
+
+   /* Retrieve color table entries. */
+   /* XXX alloca candidate. */
+#ifdef XFree86Server
+   ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
+   ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
+   for (i = 0; i < cmapSize; i++) {
+      ppixIn[i] = i;
+   }
+   QueryColors(cmap, cmapSize, ppixIn, ctable);
+#else
+   if (prevDisplay != dpy || prevCmap != cmap
+       || prevCmapSize != cmapSize || !ctable) {
+      /* free previously cached color table */
+      if (ctable)
+         _mesa_free(ctable);
+      /* Get the color table from X */
+      ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
+      assert(ctable);
+      for (i = 0; i < cmapSize; i++) {
+         ctable[i].pixel = i;
+      }
+      XQueryColors(dpy, cmap, ctable, cmapSize);
+      prevDisplay = dpy;
+      prevCmap = cmap;
+      prevCmapSize = cmapSize;
+   }
+#endif
+
+   /* Find best match. */
+   bestmatch = -1;
+   mindist = 0.0;
+   for (i = 0; i < cmapSize; i++) {
+      double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
+      double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
+      double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
+      double dist = dr * dr + dg * dg + db * db;
+      if (bestmatch < 0 || dist < mindist) {
+         bestmatch = i;
+         mindist = dist;
+      }
+   }
+
+   /* Return result. */
+   subColor.red   = ctable[bestmatch].red;
+   subColor.green = ctable[bestmatch].green;
+   subColor.blue  = ctable[bestmatch].blue;
+   /* Try to allocate the closest match color.  This should only
+    * fail if the cell is read/write.  Otherwise, we're incrementing
+    * the cell's reference count.
+    */
+#ifdef XFree86Server
+   if (AllocColor(cmap,
+                 &subColor.red, &subColor.green, &subColor.blue,
+                 &subColor.pixel,
+                 client) == Success) {
+#else
+   if (XAllocColor(dpy, cmap, &subColor)) {
+#endif
+      *alloced = 1;
+   }
+   else {
+      /* do this to work around a problem reported by Frank Ortega */
+      subColor.pixel = (unsigned long) bestmatch;
+      subColor.red   = ctable[bestmatch].red;
+      subColor.green = ctable[bestmatch].green;
+      subColor.blue  = ctable[bestmatch].blue;
+      subColor.flags = DoRed | DoGreen | DoBlue;
+      *alloced = 0;
+   }
+#ifdef XFree86Server
+   _mesa_free(ppixIn);
+   _mesa_free(ctable);
+#else
+   /* don't free table, save it for next time */
+#endif
+
+   *color = subColor;
+   *exact = 0;
+}
+
+
+
+/**
+ * Do setup for PF_GRAYSCALE pixel format.
+ * Note that buffer may be NULL.
+ */
+static GLboolean
+setup_grayscale(int client, XMesaVisual v,
+                XMesaBuffer buffer, XMesaColormap cmap)
+{
+   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
+      return GL_FALSE;
+   }
+
+   if (buffer) {
+      XMesaBuffer prevBuffer;
+
+      if (!cmap) {
+         return GL_FALSE;
+      }
+
+      prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
+      if (prevBuffer &&
+          (buffer->xm_visual->mesa_visual.rgbMode ==
+           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
+         /* Copy colormap stuff from previous XMesaBuffer which uses same
+          * X colormap.  Do this to avoid time spent in noFaultXAllocColor.
+          */
+         copy_colortable_info(buffer, prevBuffer);
+      }
+      else {
+         /* Allocate 256 shades of gray */
+         int gray;
+         int colorsfailed = 0;
+         for (gray=0;gray<256;gray++) {
+            GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
+            GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
+            GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
+            int exact, alloced;
+            XMesaColor xcol;
+            xcol.red   = (r << 8) | r;
+            xcol.green = (g << 8) | g;
+            xcol.blue  = (b << 8) | b;
+            noFaultXAllocColor( client, v->display,
+                                cmap, GET_COLORMAP_SIZE(v),
+                                &xcol, &exact, &alloced );
+            if (!exact) {
+               colorsfailed++;
+            }
+            if (alloced) {
+               assert(buffer->num_alloced<256);
+               buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
+               buffer->num_alloced++;
+            }
+
+            /*OLD
+            assert(gray < 576);
+            buffer->color_table[gray*3+0] = xcol.pixel;
+            buffer->color_table[gray*3+1] = xcol.pixel;
+            buffer->color_table[gray*3+2] = xcol.pixel;
+            assert(xcol.pixel < 65536);
+            buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
+            buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
+            buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
+            */
+            buffer->color_table[gray] = xcol.pixel;
+            assert(xcol.pixel < 65536);
+            buffer->pixel_to_r[xcol.pixel] = gray;
+            buffer->pixel_to_g[xcol.pixel] = gray;
+            buffer->pixel_to_b[xcol.pixel] = gray;
+         }
+
+         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
+            _mesa_warning(NULL,
+                  "Note: %d out of 256 needed colors do not match exactly.\n",
+                  colorsfailed );
+         }
+      }
+   }
+
+   v->dithered_pf = PF_Grayscale;
+   v->undithered_pf = PF_Grayscale;
+   return GL_TRUE;
+}
+
+
+
+/**
+ * Setup RGB rendering for a window with a PseudoColor, StaticColor,
+ * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
+ * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
+ * color.  While this function was originally designed just for 8-bit
+ * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
+ * Dithering code contributed by Bob Mercier.
+ */
+static GLboolean
+setup_dithered_color(int client, XMesaVisual v,
+                     XMesaBuffer buffer, XMesaColormap cmap)
+{
+   if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
+      return GL_FALSE;
+   }
+
+   if (buffer) {
+      XMesaBuffer prevBuffer;
+
+      if (!cmap) {
+         return GL_FALSE;
+      }
+
+      prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
+      if (prevBuffer &&
+          (buffer->xm_visual->mesa_visual.rgbMode ==
+           prevBuffer->xm_visual->mesa_visual.rgbMode)) {
+         /* Copy colormap stuff from previous, matching XMesaBuffer.
+          * Do this to avoid time spent in noFaultXAllocColor.
+          */
+         copy_colortable_info(buffer, prevBuffer);
+      }
+      else {
+         /* Allocate X colors and initialize color_table[], red_table[], etc */
+         int r, g, b, i;
+         int colorsfailed = 0;
+         for (r = 0; r < DITH_R; r++) {
+            for (g = 0; g < DITH_G; g++) {
+               for (b = 0; b < DITH_B; b++) {
+                  XMesaColor xcol;
+                  int exact, alloced;
+                  xcol.red  =gamma_adjust(v->RedGamma,   r*65535/(DITH_R-1),65535);
+                  xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
+                  xcol.blue =gamma_adjust(v->BlueGamma,  b*65535/(DITH_B-1),65535);
+                  noFaultXAllocColor( client, v->display,
+                                      cmap, GET_COLORMAP_SIZE(v),
+                                      &xcol, &exact, &alloced );
+                  if (!exact) {
+                     colorsfailed++;
+                  }
+                  if (alloced) {
+                     assert(buffer->num_alloced<256);
+                     buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
+                     buffer->num_alloced++;
+                  }
+                  i = DITH_MIX( r, g, b );
+                  assert(i < 576);
+                  buffer->color_table[i] = xcol.pixel;
+                  assert(xcol.pixel < 65536);
+                  buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
+                  buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
+                  buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
+               }
+            }
+         }
+
+         if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
+            _mesa_warning(NULL,
+                  "Note: %d out of %d needed colors do not match exactly.\n",
+                  colorsfailed, DITH_R * DITH_G * DITH_B );
+         }
+      }
+   }
+
+   v->dithered_pf = PF_Dither;
+   v->undithered_pf = PF_Lookup;
+   return GL_TRUE;
+}
+
+
+/**
+ * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
+ * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
+ * Special dithering tables have to be initialized.
+ */
+static void
+setup_8bit_hpcr(XMesaVisual v)
+{
+   /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
+    * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
+    * on the root window AND the colormap obtainable by XGetRGBColormaps
+    * for that atom must be set on the window.  (see also tkInitWindow)
+    * If that colormap is not set, the output will look stripy.
+    */
+
+   /* Setup color tables with gamma correction */
+   int i;
+   double g;
+
+   g = 1.0 / v->RedGamma;
+   for (i=0; i<256; i++) {
+      GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g ));
+      v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
+   }
+
+   g = 1.0 / v->GreenGamma;
+   for (i=0; i<256; i++) {
+      GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g ));
+      v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
+   }
+
+   g = 1.0 / v->BlueGamma;
+   for (i=0; i<256; i++) {
+      GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g ));
+      v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
+   }
+   v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
+   v->dithered_pf = PF_HPCR;
+
+   /* which method should I use to clear */
+   /* GL_FALSE: keep the ordinary method  */
+   /* GL_TRUE : clear with dither pattern */
+   v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
+
+   if (v->hpcr_clear_flag) {
+      v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
+                                               DefaultRootWindow(v->display),
+                                               16, 2, 8);
+#ifndef XFree86Server
+      v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
+                                       0, 0, 16, 2, AllPlanes, ZPixmap);
+#endif
+   }
+}
+
+
+/**
+ * Setup RGB rendering for a window with a True/DirectColor visual.
+ */
+static void
+setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap)
+{
+   unsigned long rmask, gmask, bmask;
+   (void) buffer;
+   (void) cmap;
+
+   /* Compute red multiplier (mask) and bit shift */
+   v->rshift = 0;
+   rmask = GET_REDMASK(v);
+   while ((rmask & 1)==0) {
+      v->rshift++;
+      rmask = rmask >> 1;
+   }
+
+   /* Compute green multiplier (mask) and bit shift */
+   v->gshift = 0;
+   gmask = GET_GREENMASK(v);
+   while ((gmask & 1)==0) {
+      v->gshift++;
+      gmask = gmask >> 1;
+   }
+
+   /* Compute blue multiplier (mask) and bit shift */
+   v->bshift = 0;
+   bmask = GET_BLUEMASK(v);
+   while ((bmask & 1)==0) {
+      v->bshift++;
+      bmask = bmask >> 1;
+   }
+
+   /*
+    * Compute component-to-pixel lookup tables and dithering kernel
+    */
+   {
+      static GLubyte kernel[16] = {
+          0*16,  8*16,  2*16, 10*16,
+         12*16,  4*16, 14*16,  6*16,
+          3*16, 11*16,  1*16,  9*16,
+         15*16,  7*16, 13*16,  5*16,
+      };
+      GLint rBits = _mesa_bitcount(rmask);
+      GLint gBits = _mesa_bitcount(gmask);
+      GLint bBits = _mesa_bitcount(bmask);
+      GLint maxBits;
+      GLuint i;
+
+      /* convert pixel components in [0,_mask] to RGB values in [0,255] */
+      for (i=0; i<=rmask; i++)
+         v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
+      for (i=0; i<=gmask; i++)
+         v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
+      for (i=0; i<=bmask; i++)
+         v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
+
+      /* convert RGB values from [0,255] to pixel components */
+
+      for (i=0;i<256;i++) {
+         GLint r = gamma_adjust(v->RedGamma,   i, 255);
+         GLint g = gamma_adjust(v->GreenGamma, i, 255);
+         GLint b = gamma_adjust(v->BlueGamma,  i, 255);
+         v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
+         v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
+         v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
+      }
+      /* overflow protection */
+      for (i=256;i<512;i++) {
+         v->RtoPixel[i] = v->RtoPixel[255];
+         v->GtoPixel[i] = v->GtoPixel[255];
+         v->BtoPixel[i] = v->BtoPixel[255];
+      }
+
+      /* setup dithering kernel */
+      maxBits = rBits;
+      if (gBits > maxBits)  maxBits = gBits;
+      if (bBits > maxBits)  maxBits = bBits;
+      for (i=0;i<16;i++) {
+         v->Kernel[i] = kernel[i] >> maxBits;
+      }
+
+      v->undithered_pf = PF_Truecolor;
+      v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
+   }
+
+   /*
+    * Now check for TrueColor visuals which we can optimize.
+    */
+   if (   GET_REDMASK(v)  ==0x0000ff
+       && GET_GREENMASK(v)==0x00ff00
+       && GET_BLUEMASK(v) ==0xff0000
+       && CHECK_BYTE_ORDER(v)
+       && v->BitsPerPixel==32
+       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+      /* common 32 bpp config used on SGI, Sun */
+      v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */
+   }
+   else if (GET_REDMASK(v)  == 0xff0000
+         && GET_GREENMASK(v)== 0x00ff00
+         && GET_BLUEMASK(v) == 0x0000ff
+         && CHECK_BYTE_ORDER(v)
+         && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){
+      if (v->BitsPerPixel==32) {
+         /* if 32 bpp, and visual indicates 8 bpp alpha channel */
+         if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8)
+            v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */
+         else
+            v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */
+      }
+      else if (v->BitsPerPixel == 24) {
+         v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */
+      }
+   }
+   else if (GET_REDMASK(v)  ==0xf800
+       &&   GET_GREENMASK(v)==0x07e0
+       &&   GET_BLUEMASK(v) ==0x001f
+       && CHECK_BYTE_ORDER(v)
+       && v->BitsPerPixel==16
+       && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+      /* 5-6-5 RGB */
+      v->undithered_pf = PF_5R6G5B;
+      v->dithered_pf = PF_Dither_5R6G5B;
+   }
+   else if (GET_REDMASK(v)  ==0xe0
+       &&   GET_GREENMASK(v)==0x1c
+       &&   GET_BLUEMASK(v) ==0x03
+       && CHECK_FOR_HPCR(v)) {
+      /* 8-bit HP color recovery */
+      setup_8bit_hpcr( v );
+   }
+}
+
+
+
+/**
+ * Setup RGB rendering for a window with a monochrome visual.
+ */
+static void
+setup_monochrome( XMesaVisual v, XMesaBuffer b )
+{
+   (void) b;
+   v->dithered_pf = v->undithered_pf = PF_1Bit;
+   /* if black=1 then we must flip pixel values */
+   v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
+}
+
+
+
+/**
+ * When a context is bound for the first time, we can finally finish
+ * initializing the context's visual and buffer information.
+ * \param v  the XMesaVisual to initialize
+ * \param b  the XMesaBuffer to initialize (may be NULL)
+ * \param rgb_flag  TRUE = RGBA mode, FALSE = color index mode
+ * \param window  the window/pixmap we're rendering into
+ * \param cmap  the colormap associated with the window/pixmap
+ * \return GL_TRUE=success, GL_FALSE=failure
+ */
+static GLboolean
+initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
+                             GLboolean rgb_flag, XMesaDrawable window,
+                             XMesaColormap cmap)
+{
+   int client = 0;
+
+#ifdef XFree86Server
+   client = (window) ? CLIENT_ID(window->id) : 0;
+#endif
+
+   ASSERT(!b || b->xm_visual == v);
+
+   /* Save true bits/pixel */
+   v->BitsPerPixel = bits_per_pixel(v);
+   assert(v->BitsPerPixel > 0);
+
+   if (rgb_flag == GL_FALSE) {
+      /* COLOR-INDEXED WINDOW:
+       * Even if the visual is TrueColor or DirectColor we treat it as
+       * being color indexed.  This is weird but might be useful to someone.
+       */
+      v->dithered_pf = v->undithered_pf = PF_Index;
+      v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
+   }
+   else {
+      /* RGB WINDOW:
+       * We support RGB rendering into almost any kind of visual.
+       */
+      const int xclass = v->mesa_visual.visualType;
+      if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
+        setup_truecolor( v, b, cmap );
+      }
+      else if (xclass == GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v) == 1) {
+        setup_monochrome( v, b );
+      }
+      else if (xclass == GLX_GRAY_SCALE || xclass == GLX_STATIC_GRAY) {
+         if (!setup_grayscale( client, v, b, cmap )) {
+            return GL_FALSE;
+         }
+      }
+      else if ((xclass == GLX_PSEUDO_COLOR || xclass == GLX_STATIC_COLOR)
+               && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
+        if (!setup_dithered_color( client, v, b, cmap )) {
+            return GL_FALSE;
+         }
+      }
+      else {
+        _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n");
+        return GL_FALSE;
+      }
+      v->mesa_visual.indexBits = 0;
+
+      if (_mesa_getenv("MESA_NO_DITHER")) {
+        v->dithered_pf = v->undithered_pf;
+      }
+   }
+
+
+   /*
+    * If MESA_INFO env var is set print out some debugging info
+    * which can help Brian figure out what's going on when a user
+    * reports bugs.
+    */
+   if (_mesa_getenv("MESA_INFO")) {
+      _mesa_printf("X/Mesa visual = %p\n", (void *) v);
+      _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
+      _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
+      _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
+      _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
+      _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
+   }
+
+   if (b && window) {
+      char *data;
+
+      /* Do window-specific initializations */
+
+      /* these should have been set in create_xmesa_buffer */
+      ASSERT(b->frontxrb->drawable == window);
+      ASSERT(b->frontxrb->pixmap == (XMesaPixmap) window);
+
+      /* Setup for single/double buffering */
+      if (v->mesa_visual.doubleBufferMode) {
+         /* Double buffered */
+         b->shm = check_for_xshm( v->display );
+      }
+
+      /* X11 graphics contexts */
+#ifdef XFree86Server
+      b->gc = CreateScratchGC(v->display, window->depth);
+#else
+      b->gc = XCreateGC( v->display, window, 0, NULL );
+#endif
+      XMesaSetFunction( v->display, b->gc, GXcopy );
+
+      /* cleargc - for glClear() */
+#ifdef XFree86Server
+      b->cleargc = CreateScratchGC(v->display, window->depth);
+#else
+      b->cleargc = XCreateGC( v->display, window, 0, NULL );
+#endif
+      XMesaSetFunction( v->display, b->cleargc, GXcopy );
+
+      /*
+       * Don't generate Graphics Expose/NoExpose events in swapbuffers().
+       * Patch contributed by Michael Pichler May 15, 1995.
+       */
+#ifdef XFree86Server
+      b->swapgc = CreateScratchGC(v->display, window->depth);
+      {
+         CARD32 v[1];
+         v[0] = FALSE;
+         dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
+      }
+#else
+      {
+         XGCValues gcvalues;
+         gcvalues.graphics_exposures = False;
+         b->swapgc = XCreateGC(v->display, window,
+                               GCGraphicsExposures, &gcvalues);
+      }
+#endif
+      XMesaSetFunction( v->display, b->swapgc, GXcopy );
+      /*
+       * Set fill style and tile pixmap once for all for HPCR stuff
+       * (instead of doing it each time in clear_color_HPCR_pixmap())
+       * Initialize whole stuff
+       * Patch contributed by Jacques Leroy March 8, 1998.
+       */
+      if (v->hpcr_clear_flag && b->backxrb && b->backxrb->pixmap) {
+         int i;
+         for (i = 0; i < 16; i++) {
+            XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
+            XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
+         }
+         XMesaPutImage(b->display, (XMesaDrawable) v->hpcr_clear_pixmap,
+                       b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
+         XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
+         XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
+      }
+
+      /* Initialize the row buffer XImage for use in write_color_span() */
+      data = (char*) MALLOC(MAX_WIDTH*4);
+#ifdef XFree86Server
+      b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, data);
+#else
+      b->rowimage = XCreateImage( v->display,
+                                  v->visinfo->visual,
+                                  v->visinfo->depth,
+                                  ZPixmap, 0,           /*format, offset*/
+                                  data,                 /*data*/
+                                  MAX_WIDTH, 1,         /*width, height*/
+                                  32,                   /*bitmap_pad*/
+                                  0                     /*bytes_per_line*/ );
+#endif
+      if (!b->rowimage)
+         return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+
+/*
+ * Convert an RGBA color to a pixel value.
+ */
+unsigned long
+xmesa_color_to_pixel(GLcontext *ctx,
+                     GLubyte r, GLubyte g, GLubyte b, GLubyte a,
+                     GLuint pixelFormat)
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   switch (pixelFormat) {
+      case PF_Index:
+         return 0;
+      case PF_Truecolor:
+         {
+            unsigned long p;
+            PACK_TRUECOLOR( p, r, g, b );
+            return p;
+         }
+      case PF_8A8B8G8R:
+         return PACK_8A8B8G8R( r, g, b, a );
+      case PF_8A8R8G8B:
+         return PACK_8A8R8G8B( r, g, b, a );
+      case PF_8R8G8B:
+         /* fall through */
+      case PF_8R8G8B24:
+         return PACK_8R8G8B( r, g, b );
+      case PF_5R6G5B:
+         return PACK_5R6G5B( r, g, b );
+      case PF_Dither:
+         {
+            DITHER_SETUP;
+            return DITHER( 1, 0, r, g, b );
+         }
+      case PF_1Bit:
+         /* 382 = (3*255)/2 */
+         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
+      case PF_HPCR:
+         return DITHER_HPCR(1, 1, r, g, b);
+      case PF_Lookup:
+         {
+            LOOKUP_SETUP;
+            return LOOKUP( r, g, b );
+         }
+      case PF_Grayscale:
+         return GRAY_RGB( r, g, b );
+      case PF_Dither_True:
+         /* fall through */
+      case PF_Dither_5R6G5B:
+         {
+            unsigned long p;
+            PACK_TRUEDITHER(p, 1, 0, r, g, b);
+            return p;
+         }
+      default:
+         _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
+   }
+   return 0;
+}
+
+
+#define NUM_VISUAL_TYPES   6
+
+/**
+ * Convert an X visual type to a GLX visual type.
+ * 
+ * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
+ *        to be converted.
+ * \return If \c visualType is a valid X visual type, a GLX visual type will
+ *         be returned.  Otherwise \c GLX_NONE will be returned.
+ * 
+ * \note
+ * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
+ * DRI CVS tree.
+ */
+static GLint
+xmesa_convert_from_x_visual_type( int visualType )
+{
+    static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
+       GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
+       GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+       GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
+    };
+
+    return ( (unsigned) visualType < NUM_VISUAL_TYPES )
+       ? glx_visual_types[ visualType ] : GLX_NONE;
+}
+
+
+/**********************************************************************/
+/*****                       Public Functions                     *****/
+/**********************************************************************/
+
+
+/*
+ * Create a new X/Mesa visual.
+ * Input:  display - X11 display
+ *         visinfo - an XVisualInfo pointer
+ *         rgb_flag - GL_TRUE = RGB mode,
+ *                    GL_FALSE = color index mode
+ *         alpha_flag - alpha buffer requested?
+ *         db_flag - GL_TRUE = double-buffered,
+ *                   GL_FALSE = single buffered
+ *         stereo_flag - stereo visual?
+ *         ximage_flag - GL_TRUE = use an XImage for back buffer,
+ *                       GL_FALSE = use an off-screen pixmap for back buffer
+ *         depth_size - requested bits/depth values, or zero
+ *         stencil_size - requested bits/stencil values, or zero
+ *         accum_red_size - requested bits/red accum values, or zero
+ *         accum_green_size - requested bits/green accum values, or zero
+ *         accum_blue_size - requested bits/blue accum values, or zero
+ *         accum_alpha_size - requested bits/alpha accum values, or zero
+ *         num_samples - number of samples/pixel if multisampling, or zero
+ *         level - visual level, usually 0
+ *         visualCaveat - ala the GLX extension, usually GLX_NONE
+ * Return;  a new XMesaVisual or 0 if error.
+ */
+PUBLIC
+XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
+                               XMesaVisualInfo visinfo,
+                               GLboolean rgb_flag,
+                               GLboolean alpha_flag,
+                               GLboolean db_flag,
+                               GLboolean stereo_flag,
+                               GLboolean ximage_flag,
+                               GLint depth_size,
+                               GLint stencil_size,
+                               GLint accum_red_size,
+                               GLint accum_green_size,
+                               GLint accum_blue_size,
+                               GLint accum_alpha_size,
+                               GLint num_samples,
+                               GLint level,
+                               GLint visualCaveat )
+{
+   char *gamma;
+   XMesaVisual v;
+   GLint red_bits, green_bits, blue_bits, alpha_bits;
+
+#ifndef XFree86Server
+   /* For debugging only */
+   if (_mesa_getenv("MESA_XSYNC")) {
+      /* This makes debugging X easier.
+       * In your debugger, set a breakpoint on _XError to stop when an
+       * X protocol error is generated.
+       */
+      XSynchronize( display, 1 );
+   }
+#endif
+
+   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
+   if (!v) {
+      return NULL;
+   }
+
+   v->display = display;
+
+   /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
+    * the struct but we may need some of the information contained in it
+    * at a later time.
+    */
+#ifndef XFree86Server
+   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
+   if(!v->visinfo) {
+      _mesa_free(v);
+      return NULL;
+   }
+   MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
+#endif
+
+   /* check for MESA_GAMMA environment variable */
+   gamma = _mesa_getenv("MESA_GAMMA");
+   if (gamma) {
+      v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
+      sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
+      if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
+      if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
+      if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
+   }
+   else {
+      v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
+   }
+
+   v->ximage_flag = ximage_flag;
+
+#ifdef XFree86Server
+   /* We could calculate these values by ourselves.  nplanes is either the sum
+    * of the red, green, and blue bits or the number index bits.
+    * ColormapEntries is either (1U << index_bits) or
+    * (1U << max(redBits, greenBits, blueBits)).
+    */
+   assert(visinfo->nplanes > 0);
+   v->nplanes = visinfo->nplanes;
+   v->ColormapEntries = visinfo->ColormapEntries;
+
+   v->mesa_visual.redMask = visinfo->redMask;
+   v->mesa_visual.greenMask = visinfo->greenMask;
+   v->mesa_visual.blueMask = visinfo->blueMask;
+   v->mesa_visual.visualID = visinfo->vid;
+   v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
+#else
+   v->mesa_visual.redMask = visinfo->red_mask;
+   v->mesa_visual.greenMask = visinfo->green_mask;
+   v->mesa_visual.blueMask = visinfo->blue_mask;
+   v->mesa_visual.visualID = visinfo->visualid;
+   v->mesa_visual.screen = visinfo->screen;
+#endif
+
+#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
+   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
+#else
+   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
+#endif
+
+   v->mesa_visual.visualRating = visualCaveat;
+
+   if (alpha_flag)
+      v->mesa_visual.alphaBits = 8;
+
+   (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
+
+   {
+      const int xclass = v->mesa_visual.visualType;
+      if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
+         red_bits   = _mesa_bitcount(GET_REDMASK(v));
+         green_bits = _mesa_bitcount(GET_GREENMASK(v));
+         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
+      }
+      else {
+         /* this is an approximation */
+         int depth;
+         depth = GET_VISUAL_DEPTH(v);
+         red_bits = depth / 3;
+         depth -= red_bits;
+         green_bits = depth / 2;
+         depth -= green_bits;
+         blue_bits = depth;
+         alpha_bits = 0;
+         assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
+      }
+      alpha_bits = v->mesa_visual.alphaBits;
+   }
+
+   _mesa_initialize_visual( &v->mesa_visual,
+                            rgb_flag, db_flag, stereo_flag,
+                            red_bits, green_bits,
+                            blue_bits, alpha_bits,
+                            v->mesa_visual.indexBits,
+                            depth_size,
+                            stencil_size,
+                            accum_red_size, accum_green_size,
+                            accum_blue_size, accum_alpha_size,
+                            0 );
+
+   /* XXX minor hack */
+   v->mesa_visual.level = level;
+   return v;
+}
+
+
+PUBLIC
+void XMesaDestroyVisual( XMesaVisual v )
+{
+#ifndef XFree86Server
+   _mesa_free(v->visinfo);
+#endif
+   _mesa_free(v);
+}
+
+
+
+/**
+ * Create a new XMesaContext.
+ * \param v  the XMesaVisual
+ * \param share_list  another XMesaContext with which to share display
+ *                    lists or NULL if no sharing is wanted.
+ * \return an XMesaContext or NULL if error.
+ */
+PUBLIC
+XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
+{
+   static GLboolean firstTime = GL_TRUE;
+   XMesaContext c;
+   GLcontext *mesaCtx;
+   struct dd_function_table functions;
+#if 0
+   TNLcontext *tnl;
+#endif
+
+   if (firstTime) {
+      _glthread_INIT_MUTEX(_xmesa_lock);
+      firstTime = GL_FALSE;
+   }
+
+   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
+   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
+   if (!c)
+      return NULL;
+
+   mesaCtx = &(c->mesa);
+
+   /* initialize with default driver functions, then plug in XMesa funcs */
+   _mesa_init_driver_functions(&functions);
+   xmesa_init_driver_functions(v, &functions);
+   st_init_driver_functions(&functions);
+
+   /* override st's function */
+   functions.UpdateState = xmesa_update_state;
+
+   /*
+   functions.NewRenderbuffer = xmesa_new_renderbuffer;
+   */
+
+   if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
+                      share_list ? &(share_list->mesa) : (GLcontext *) NULL,
+                      &functions, (void *) c)) {
+      _mesa_free(c);
+      return NULL;
+   }
+
+   _mesa_enable_sw_extensions(mesaCtx);
+   _mesa_enable_1_3_extensions(mesaCtx);
+   _mesa_enable_1_4_extensions(mesaCtx);
+   _mesa_enable_1_5_extensions(mesaCtx);
+   _mesa_enable_2_0_extensions(mesaCtx);
+#if ENABLE_EXT_texure_compression_s3tc
+    if (c->Mesa_DXTn) {
+       _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc");
+       _mesa_enable_extension(mesaCtx, "GL_S3_s3tc");
+    }
+    _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1");
+#endif
+#if ENABLE_EXT_timer_query
+    _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query");
+#endif
+
+#ifdef XFree86Server
+   /* If we're running in the X server, do bounds checking to prevent
+    * segfaults and server crashes!
+    */
+   mesaCtx->Const.CheckArrayBounds = GL_TRUE;
+#endif
+
+   /* finish up xmesa context initializations */
+   c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
+   c->xm_visual = v;
+   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
+   c->display = v->display;
+   c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
+
+   /* Initialize the software rasterizer and helper modules.
+    */
+   if (!_swrast_CreateContext( mesaCtx )
+#if 0
+       || !_vbo_CreateContext( mesaCtx ) ||
+       !_tnl_CreateContext( mesaCtx ) ||
+       !_swsetup_CreateContext( mesaCtx )
+#endif
+       ) {
+      _mesa_free_context_data(&c->mesa);
+      _mesa_free(c);
+      return NULL;
+   }
+
+#if 0
+   /* tnl setup */
+   tnl = TNL_CONTEXT(mesaCtx);
+   tnl->Driver.RunPipeline = _tnl_run_pipeline;
+#endif
+
+   /* swrast setup */
+   xmesa_register_swrast_functions( mesaCtx );
+
+
+   st_create_context( mesaCtx,
+                      xmesa_create_softpipe( c ) );
+
+   _swsetup_CreateContext( mesaCtx );
+   _swsetup_Wakeup(mesaCtx);
+
+   /* override these functions, as if the xlib driver were derived from
+    * the softpipe driver.
+    */
+#if 0
+   mesaCtx->st->pipe->surface_alloc = xmesa_surface_alloc;
+#endif
+   mesaCtx->st->pipe->is_format_supported = xmesa_is_format_supported;
+   mesaCtx->st->pipe->get_tile_rgba = xmesa_get_tile_rgba;
+   mesaCtx->st->pipe->put_tile_rgba = xmesa_put_tile_rgba;
+
+   mesaCtx->st->haveFramebufferRegions = GL_FALSE;
+
+   /* special pipe->clear function */
+   mesaCtx->st->pipe->clear = xmesa_clear;
+
+   return c;
+}
+
+
+
+PUBLIC
+void XMesaDestroyContext( XMesaContext c )
+{
+   GLcontext *mesaCtx = &c->mesa;
+
+#ifdef FX
+   FXdestroyContext( XMESA_BUFFER(mesaCtx->DrawBuffer) );
+#endif
+
+   _swsetup_DestroyContext( mesaCtx );
+   _swrast_DestroyContext( mesaCtx );
+#if 0
+   _tnl_DestroyContext( mesaCtx );
+   _vbo_DestroyContext( mesaCtx );
+#endif
+   _mesa_free_context_data( mesaCtx );
+   _mesa_free( c );
+}
+
+
+
+/**
+ * Private function for creating an XMesaBuffer which corresponds to an
+ * X window or pixmap.
+ * \param v  the window's XMesaVisual
+ * \param w  the window we're wrapping
+ * \return  new XMesaBuffer or NULL if error
+ */
+PUBLIC XMesaBuffer
+XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
+{
+#ifndef XFree86Server
+   XWindowAttributes attr;
+#endif
+   XMesaBuffer b;
+   XMesaColormap cmap;
+   int depth;
+
+   assert(v);
+   assert(w);
+
+   /* Check that window depth matches visual depth */
+#ifdef XFree86Server
+   depth = ((XMesaDrawable)w)->depth;
+#else
+   XGetWindowAttributes( v->display, w, &attr );
+   depth = attr.depth;
+#endif
+   if (GET_VISUAL_DEPTH(v) != depth) {
+      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
+                    GET_VISUAL_DEPTH(v), depth);
+      return NULL;
+   }
+
+   /* Find colormap */
+#ifdef XFree86Server
+   cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
+#else
+   if (attr.colormap) {
+      cmap = attr.colormap;
+   }
+   else {
+      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
+      /* this is weird, a window w/out a colormap!? */
+      /* OK, let's just allocate a new one and hope for the best */
+      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
+   }
+#endif
+
+   b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
+   if (!b)
+      return NULL;
+
+   if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
+                                      (XMesaDrawable) w, cmap )) {
+      xmesa_free_buffer(b);
+      return NULL;
+   }
+
+   return b;
+}
+
+
+
+/**
+ * Create a new XMesaBuffer from an X pixmap.
+ *
+ * \param v    the XMesaVisual
+ * \param p    the pixmap
+ * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
+ *             \c GLX_DIRECT_COLOR visual for the pixmap
+ * \returns new XMesaBuffer or NULL if error
+ */
+PUBLIC XMesaBuffer
+XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
+{
+   XMesaBuffer b;
+
+   assert(v);
+
+   b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
+   if (!b)
+      return NULL;
+
+   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+                                    (XMesaDrawable) p, cmap)) {
+      xmesa_free_buffer(b);
+      return NULL;
+   }
+
+   return b;
+}
+
+
+/**
+ * For GLX_EXT_texture_from_pixmap
+ */
+XMesaBuffer
+XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
+                               XMesaColormap cmap,
+                               int format, int target, int mipmap)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   XMesaBuffer b;
+   GLuint width, height;
+
+   assert(v);
+
+   b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
+   if (!b)
+      return NULL;
+
+   /* get pixmap size, update framebuffer/renderbuffer dims */
+   xmesa_get_window_size(v->display, b, &width, &height);
+   _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height);
+
+   if (target == 0) {
+      /* examine dims */
+      if (ctx->Extensions.ARB_texture_non_power_of_two) {
+         target = GLX_TEXTURE_2D_EXT;
+      }
+      else if (   _mesa_bitcount(width)  == 1
+               && _mesa_bitcount(height) == 1) {
+         /* power of two size */
+         if (height == 1) {
+            target = GLX_TEXTURE_1D_EXT;
+         }
+         else {
+            target = GLX_TEXTURE_2D_EXT;
+         }
+      }
+      else if (ctx->Extensions.NV_texture_rectangle) {
+         target = GLX_TEXTURE_RECTANGLE_EXT;
+      }
+      else {
+         /* non power of two textures not supported */
+         XMesaDestroyBuffer(b);
+         return 0;
+      }
+   }
+
+   b->TextureTarget = target;
+   b->TextureFormat = format;
+   b->TextureMipmap = mipmap;
+
+   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+                                    (XMesaDrawable) p, cmap)) {
+      xmesa_free_buffer(b);
+      return NULL;
+   }
+
+   return b;
+}
+
+
+
+XMesaBuffer
+XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
+                   unsigned int width, unsigned int height)
+{
+#ifndef XFree86Server
+   XMesaWindow root;
+   XMesaDrawable drawable;  /* X Pixmap Drawable */
+   XMesaBuffer b;
+
+   /* allocate pixmap for front buffer */
+   root = RootWindow( v->display, v->visinfo->screen );
+   drawable = XCreatePixmap(v->display, root, width, height,
+                            v->visinfo->depth);
+   if (!drawable)
+      return NULL;
+
+   b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
+   if (!b)
+      return NULL;
+
+   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+                                    drawable, cmap)) {
+      xmesa_free_buffer(b);
+      return NULL;
+   }
+
+   return b;
+#else
+   return 0;
+#endif
+}
+
+
+
+/*
+ * Deallocate an XMesaBuffer structure and all related info.
+ */
+PUBLIC void
+XMesaDestroyBuffer(XMesaBuffer b)
+{
+   xmesa_free_buffer(b);
+}
+
+
+/**
+ * Query the current window size and update the corresponding GLframebuffer
+ * and all attached renderbuffers.
+ * Called when:
+ *  1. the first time a buffer is bound to a context.
+ *  2. from glViewport to poll for window size changes
+ *  3. from the XMesaResizeBuffers() API function.
+ * Note: it's possible (and legal) for xmctx to be NULL.  That can happen
+ * when resizing a buffer when no rendering context is bound.
+ */
+void
+xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
+{
+   GLuint width, height;
+   xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height);
+   if (drawBuffer->mesa_buffer.Width != width ||
+       drawBuffer->mesa_buffer.Height != height) {
+      GLcontext *ctx = xmctx ? &xmctx->mesa : NULL;
+      _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height);
+   }
+   drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */
+}
+
+
+/*
+ * Bind buffer b to context c and make c the current rendering context.
+ */
+GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
+{
+   return XMesaMakeCurrent2( c, b, b );
+}
+
+
+/*
+ * Bind buffer b to context c and make c the current rendering context.
+ */
+PUBLIC
+GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
+                             XMesaBuffer readBuffer )
+{
+   if (c) {
+      if (!drawBuffer || !readBuffer)
+         return GL_FALSE;  /* must specify buffers! */
+
+      if (&(c->mesa) == _mesa_get_current_context()
+          && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
+          && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
+          && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
+         /* same context and buffer, do nothing */
+         return GL_TRUE;
+      }
+
+      c->xm_buffer = drawBuffer;
+
+#ifdef FX
+      if (FXmakeCurrent( drawBuffer ))
+         return GL_TRUE;
+#endif
+
+      /* Call this periodically to detect when the user has begun using
+       * GL rendering from multiple threads.
+       */
+      _glapi_check_multithread();
+
+      xmesa_check_and_update_buffer_size(c, drawBuffer);
+      if (readBuffer != drawBuffer)
+         xmesa_check_and_update_buffer_size(c, readBuffer);
+
+      _mesa_make_current(&(c->mesa),
+                         &drawBuffer->mesa_buffer,
+                         &readBuffer->mesa_buffer);
+
+      if (c->xm_visual->mesa_visual.rgbMode) {
+         /*
+          * Must recompute and set these pixel values because colormap
+          * can be different for different windows.
+          */
+         c->clearpixel = xmesa_color_to_pixel( &c->mesa,
+                                               c->clearcolor[0],
+                                               c->clearcolor[1],
+                                               c->clearcolor[2],
+                                               c->clearcolor[3],
+                                               c->xm_visual->undithered_pf);
+         XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
+      }
+
+      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
+      drawBuffer->wasCurrent = GL_TRUE;
+   }
+   else {
+      /* Detach */
+      _mesa_make_current( NULL, NULL, NULL );
+   }
+   return GL_TRUE;
+}
+
+
+/*
+ * Unbind the context c from its buffer.
+ */
+GLboolean XMesaUnbindContext( XMesaContext c )
+{
+   /* A no-op for XFree86 integration purposes */
+   return GL_TRUE;
+}
+
+
+XMesaContext XMesaGetCurrentContext( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (ctx) {
+      XMesaContext xmesa = XMESA_CONTEXT(ctx);
+      return xmesa;
+   }
+   else {
+      return 0;
+   }
+}
+
+
+XMesaBuffer XMesaGetCurrentBuffer( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (ctx) {
+      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+      return xmbuf;
+   }
+   else {
+      return 0;
+   }
+}
+
+
+/* New in Mesa 3.1 */
+XMesaBuffer XMesaGetCurrentReadBuffer( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (ctx) {
+      return XMESA_BUFFER(ctx->ReadBuffer);
+   }
+   else {
+      return 0;
+   }
+}
+
+
+#ifdef XFree86Server
+PUBLIC
+GLboolean XMesaForceCurrent(XMesaContext c)
+{
+   if (c) {
+      _glapi_set_dispatch(c->mesa.CurrentDispatch);
+
+      if (&(c->mesa) != _mesa_get_current_context()) {
+        _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
+      }
+   }
+   else {
+      _mesa_make_current(NULL, NULL, NULL);
+   }
+   return GL_TRUE;
+}
+
+
+PUBLIC
+GLboolean XMesaLoseCurrent(XMesaContext c)
+{
+   (void) c;
+   _mesa_make_current(NULL, NULL, NULL);
+   return GL_TRUE;
+}
+
+
+PUBLIC
+GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask )
+{
+   _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
+   return GL_TRUE;
+}
+#endif /* XFree86Server */
+
+
+#ifndef FX
+GLboolean XMesaSetFXmode( GLint mode )
+{
+   (void) mode;
+   return GL_FALSE;
+}
+#endif
+
+
+
+/*
+ * Copy the back buffer to the front buffer.  If there's no back buffer
+ * this is a no-op.
+ */
+PUBLIC
+void XMesaSwapBuffers( XMesaBuffer b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!b->backxrb) {
+      /* single buffered */
+      return;
+   }
+
+   /* If we're swapping the buffer associated with the current context
+    * we have to flush any pending rendering commands first.
+    */
+   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
+      _mesa_notifySwapBuffers(ctx);
+
+   if (b->db_mode) {
+#ifdef FX
+      if (FXswapBuffers(b))
+         return;
+#endif
+      if (b->backxrb->ximage) {
+        /* Copy Ximage (back buf) from client memory to server window */
+#if defined(USE_XSHM) && !defined(XFree86Server)
+        if (b->shm) {
+            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+           XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
+                         b->swapgc,
+                         b->backxrb->ximage, 0, 0,
+                         0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
+                          False );
+            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+        }
+        else
+#endif
+         {
+            /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
+                          b->swapgc,
+                          b->backxrb->ximage, 0, 0,
+                          0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
+            /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+         }
+      }
+      else if (b->backxrb->pixmap) {
+        /* Copy pixmap (back buf) to window (front buf) on server */
+         /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+        XMesaCopyArea( b->xm_visual->display,
+                       b->backxrb->pixmap,   /* source drawable */
+                       b->frontxrb->drawable,  /* dest. drawable */
+                       b->swapgc,
+                       0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
+                       0, 0                 /* dest region */
+                     );
+         /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+      }
+
+      if (b->swAlpha)
+         _mesa_copy_soft_alpha_renderbuffers(ctx, &b->mesa_buffer);
+   }
+#if !defined(XFree86Server)
+   XSync( b->xm_visual->display, False );
+#endif
+}
+
+
+
+/*
+ * Copy sub-region of back buffer to front buffer
+ */
+void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* If we're swapping the buffer associated with the current context
+    * we have to flush any pending rendering commands first.
+    */
+   if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
+      _mesa_notifySwapBuffers(ctx);
+
+   if (!b->backxrb) {
+      /* single buffered */
+      return; 
+   }
+
+   if (b->db_mode) {
+      int yTop = b->mesa_buffer.Height - y - height;
+#ifdef FX
+      if (FXswapBuffers(b))
+         return;
+#endif
+      if (b->backxrb->ximage) {
+         /* Copy Ximage from host's memory to server's window */
+#if defined(USE_XSHM) && !defined(XFree86Server)
+         if (b->shm) {
+            /* XXX assuming width and height aren't too large! */
+            XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
+                          b->swapgc,
+                          b->backxrb->ximage, x, yTop,
+                          x, yTop, width, height, False );
+            /* wait for finished event??? */
+         }
+         else
+#endif
+         {
+            /* XXX assuming width and height aren't too large! */
+            XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
+                          b->swapgc,
+                          b->backxrb->ximage, x, yTop,
+                          x, yTop, width, height );
+         }
+      }
+      else {
+         /* Copy pixmap to window on server */
+         XMesaCopyArea( b->xm_visual->display,
+                       b->backxrb->pixmap,           /* source drawable */
+                       b->frontxrb->drawable,        /* dest. drawable */
+                       b->swapgc,
+                       x, yTop, width, height,  /* source region */
+                       x, yTop                  /* dest region */
+                      );
+      }
+   }
+}
+
+
+/*
+ * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
+ * is a way to get "under the hood" of X/Mesa so one can manipulate the
+ * back buffer directly.
+ * Output:  pixmap - pointer to back buffer's Pixmap, or 0
+ *          ximage - pointer to back buffer's XImage, or NULL
+ * Return:  GL_TRUE = context is double buffered
+ *          GL_FALSE = context is single buffered
+ */
+#ifndef XFree86Server
+GLboolean XMesaGetBackBuffer( XMesaBuffer b,
+                              XMesaPixmap *pixmap,
+                              XMesaImage **ximage )
+{
+   if (b->db_mode) {
+      if (pixmap)
+         *pixmap = b->backxrb->pixmap;
+      if (ximage)
+         *ximage = b->backxrb->ximage;
+      return GL_TRUE;
+   }
+   else {
+      *pixmap = 0;
+      *ximage = NULL;
+      return GL_FALSE;
+   }
+}
+#endif /* XFree86Server */
+
+
+/*
+ * Return the depth buffer associated with an XMesaBuffer.
+ * Input:  b - the XMesa buffer handle
+ * Output:  width, height - size of buffer in pixels
+ *          bytesPerValue - bytes per depth value (2 or 4)
+ *          buffer - pointer to depth buffer values
+ * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
+                               GLint *bytesPerValue, void **buffer )
+{
+   struct gl_renderbuffer *rb
+      = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
+   if (!rb || !rb->Data) {
+      *width = 0;
+      *height = 0;
+      *bytesPerValue = 0;
+      *buffer = 0;
+      return GL_FALSE;
+   }
+   else {
+      *width = b->mesa_buffer.Width;
+      *height = b->mesa_buffer.Height;
+      *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
+         ? sizeof(GLushort) : sizeof(GLuint);
+      *buffer = rb->Data;
+      return GL_TRUE;
+   }
+}
+
+
+void XMesaFlush( XMesaContext c )
+{
+   if (c && c->xm_visual) {
+#ifdef XFree86Server
+      /* NOT_NEEDED */
+#else
+      XSync( c->xm_visual->display, False );
+#endif
+   }
+}
+
+
+
+const char *XMesaGetString( XMesaContext c, int name )
+{
+   (void) c;
+   if (name==XMESA_VERSION) {
+      return "5.0";
+   }
+   else if (name==XMESA_EXTENSIONS) {
+      return "";
+   }
+   else {
+      return NULL;
+   }
+}
+
+
+
+XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
+{
+   XMesaBuffer b;
+   for (b=XMesaBufferList; b; b=b->Next) {
+      if (b->frontxrb->drawable == d && b->display == dpy) {
+         return b;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Free/destroy all XMesaBuffers associated with given display.
+ */
+void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
+{
+   XMesaBuffer b, next;
+   for (b = XMesaBufferList; b; b = next) {
+      next = b->Next;
+      if (b->display == dpy) {
+         xmesa_free_buffer(b);
+      }
+   }
+}
+
+
+/*
+ * Look for XMesaBuffers whose X window has been destroyed.
+ * Deallocate any such XMesaBuffers.
+ */
+void XMesaGarbageCollect( void )
+{
+   XMesaBuffer b, next;
+   for (b=XMesaBufferList; b; b=next) {
+      next = b->Next;
+      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
+#ifdef XFree86Server
+        /* NOT_NEEDED */
+#else
+         XSync(b->display, False);
+         if (!window_exists( b->display, b->frontxrb->drawable )) {
+            /* found a dead window, free the ancillary info */
+            XMesaDestroyBuffer( b );
+         }
+#endif
+      }
+   }
+}
+
+
+unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
+                                GLfloat red, GLfloat green,
+                                GLfloat blue, GLfloat alpha )
+{
+   GLcontext *ctx = &xmesa->mesa;
+   GLint r = (GLint) (red   * 255.0F);
+   GLint g = (GLint) (green * 255.0F);
+   GLint b = (GLint) (blue  * 255.0F);
+   GLint a = (GLint) (alpha * 255.0F);
+
+   switch (xmesa->pixelformat) {
+      case PF_Index:
+         return 0;
+      case PF_Truecolor:
+         {
+            unsigned long p;
+            PACK_TRUECOLOR( p, r, g, b );
+            return p;
+         }
+      case PF_8A8B8G8R:
+         return PACK_8A8B8G8R( r, g, b, a );
+      case PF_8A8R8G8B:
+         return PACK_8A8R8G8B( r, g, b, a );
+      case PF_8R8G8B:
+         return PACK_8R8G8B( r, g, b );
+      case PF_5R6G5B:
+         return PACK_5R6G5B( r, g, b );
+      case PF_Dither:
+         {
+            DITHER_SETUP;
+            return DITHER( x, y, r, g, b );
+         }
+      case PF_1Bit:
+         /* 382 = (3*255)/2 */
+         return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
+      case PF_HPCR:
+         return DITHER_HPCR(x, y, r, g, b);
+      case PF_Lookup:
+         {
+            LOOKUP_SETUP;
+            return LOOKUP( r, g, b );
+         }
+      case PF_Grayscale:
+         return GRAY_RGB( r, g, b );
+      case PF_Dither_5R6G5B:
+         /* fall through */
+      case PF_Dither_True:
+         {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, r, g, b);
+            return p;
+         }
+      default:
+         _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
+   }
+   return 0;
+}
+
+
+/*
+ * This is typically called when the window size changes and we need
+ * to reallocate the buffer's back/depth/stencil/accum buffers.
+ */
+PUBLIC void
+XMesaResizeBuffers( XMesaBuffer b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   XMesaContext xmctx = XMESA_CONTEXT(ctx);
+   if (!xmctx)
+      return;
+   xmesa_check_and_update_buffer_size(xmctx, b);
+}
+
+
+static GLint
+xbuffer_to_renderbuffer(int buffer)
+{
+   assert(MAX_AUX_BUFFERS <= 4);
+
+   switch (buffer) {
+   case GLX_FRONT_LEFT_EXT:
+      return BUFFER_FRONT_LEFT;
+   case GLX_FRONT_RIGHT_EXT:
+      return BUFFER_FRONT_RIGHT;
+   case GLX_BACK_LEFT_EXT:
+      return BUFFER_BACK_LEFT;
+   case GLX_BACK_RIGHT_EXT:
+      return BUFFER_BACK_RIGHT;
+   case GLX_AUX0_EXT:
+      return BUFFER_AUX0;
+   case GLX_AUX1_EXT:
+      return BUFFER_AUX1;
+   case GLX_AUX2_EXT:
+      return BUFFER_AUX2;
+   case GLX_AUX3_EXT:
+      return BUFFER_AUX3;
+   case GLX_AUX4_EXT:
+   case GLX_AUX5_EXT:
+   case GLX_AUX6_EXT:
+   case GLX_AUX7_EXT:
+   case GLX_AUX8_EXT:
+   case GLX_AUX9_EXT:
+   default:
+      /* BadValue error */
+      return -1;
+   }
+}
+
+
+PUBLIC void
+XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
+                  const int *attrib_list)
+{
+#if 0
+   GET_CURRENT_CONTEXT(ctx);
+   const GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *texObj;
+#endif
+   struct gl_renderbuffer *rb;
+   struct xmesa_renderbuffer *xrb;
+   GLint b;
+   XMesaImage *img = NULL;
+   GLboolean freeImg = GL_FALSE;
+
+   b = xbuffer_to_renderbuffer(buffer);
+   if (b < 0)
+      return;
+
+   if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT)
+      return; /* BadMatch error */
+
+   rb = drawable->mesa_buffer.Attachment[b].Renderbuffer;
+   if (!rb) {
+      /* invalid buffer */
+      return;
+   }
+   xrb = xmesa_renderbuffer(rb);
+
+#if 0
+   switch (drawable->TextureTarget) {
+   case GLX_TEXTURE_1D_EXT:
+      texObj = texUnit->Current1D;
+      break;
+   case GLX_TEXTURE_2D_EXT:
+      texObj = texUnit->Current2D;
+      break;
+   case GLX_TEXTURE_RECTANGLE_EXT:
+      texObj = texUnit->CurrentRect;
+      break;
+   default:
+      return; /* BadMatch error */
+   }
+#endif
+
+   /*
+    * The following is a quick and simple way to implement
+    * BindTexImage.  The better way is to write some new FetchTexel()
+    * functions which would extract texels from XImages.  We'd still
+    * need to use GetImage when texturing from a Pixmap (front buffer)
+    * but texturing from a back buffer (XImage) would avoid an image
+    * copy.
+    */
+
+   /* get XImage */
+   if (xrb->pixmap) {
+      img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L,
+                         ZPixmap);
+      freeImg = GL_TRUE;
+   }
+   else if (xrb->ximage) {
+      img = xrb->ximage;
+   }
+
+   /* store the XImage as a new texture image */
+   if (img) {
+      GLenum format, type, intFormat;
+      if (img->bits_per_pixel == 32) {
+         format = GL_BGRA;
+         type = GL_UNSIGNED_BYTE;
+         intFormat = GL_RGBA;
+      }
+      else if (img->bits_per_pixel == 24) {
+         format = GL_BGR;
+         type = GL_UNSIGNED_BYTE;
+         intFormat = GL_RGB;
+      }
+      else if (img->bits_per_pixel == 16) {
+         format = GL_BGR;
+         type = GL_UNSIGNED_SHORT_5_6_5;
+         intFormat = GL_RGB;
+      }
+      else {
+         _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage");
+         return;
+      }
+      if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) {
+         intFormat = GL_RGBA;
+      }
+      else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) {
+         intFormat = GL_RGB;
+      }
+
+      _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0,
+                       format, type, img->data);
+
+      if (freeImg) {
+        XMesaDestroyImage(img);
+      }
+   }
+}
+
+
+
+PUBLIC void
+XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
+{
+   const GLint b = xbuffer_to_renderbuffer(buffer);
+   if (b < 0)
+      return;
+
+   /* no-op for now */
+}
+
diff --git a/src/mesa/pipe/xlib/xm_buffer.c b/src/mesa/pipe/xlib/xm_buffer.c
new file mode 100644 (file)
index 0000000..09356c7
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * \file xm_buffer.h
+ * Framebuffer and renderbuffer-related functions.
+ */
+
+
+#include "glxheader.h"
+#include "GL/xmesa.h"
+#include "xmesaP.h"
+#include "imports.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "state_tracker/st_context.h"
+
+
+#if defined(USE_XSHM) && !defined(XFree86Server)
+static volatile int mesaXErrorFlag = 0;
+
+/**
+ * Catches potential Xlib errors.
+ */
+static int
+mesaHandleXError(XMesaDisplay *dpy, XErrorEvent *event)
+{
+   (void) dpy;
+   (void) event;
+   mesaXErrorFlag = 1;
+   return 0;
+}
+
+/**
+ * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
+ * Return:  GL_TRUE if success, GL_FALSE if error
+ */
+static GLboolean
+alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
+{
+   /*
+    * We have to do a _lot_ of error checking here to be sure we can
+    * really use the XSHM extension.  It seems different servers trigger
+    * errors at different points if the extension won't work.  Therefore
+    * we have to be very careful...
+    */
+   GC gc;
+   int (*old_handler)(XMesaDisplay *, XErrorEvent *);
+
+   if (width == 0 || height == 0) {
+      /* this will be true the first time we're called on 'b' */
+      return GL_FALSE;
+   }
+
+   b->backxrb->ximage = XShmCreateImage(b->xm_visual->display,
+                                        b->xm_visual->visinfo->visual,
+                                        b->xm_visual->visinfo->depth,
+                                        ZPixmap, NULL, &b->shminfo,
+                                        width, height);
+   if (b->backxrb->ximage == NULL) {
+      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n");
+      b->shm = 0;
+      return GL_FALSE;
+   }
+
+   b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
+                            * b->backxrb->ximage->height, IPC_CREAT|0777);
+   if (b->shminfo.shmid < 0) {
+      _mesa_warning(NULL, "shmget failed while allocating back buffer.\n");
+      XDestroyImage(b->backxrb->ximage);
+      b->backxrb->ximage = NULL;
+      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n");
+      b->shm = 0;
+      return GL_FALSE;
+   }
+
+   b->shminfo.shmaddr = b->backxrb->ximage->data
+                      = (char*)shmat(b->shminfo.shmid, 0, 0);
+   if (b->shminfo.shmaddr == (char *) -1) {
+      _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n");
+      XDestroyImage(b->backxrb->ximage);
+      shmctl(b->shminfo.shmid, IPC_RMID, 0);
+      b->backxrb->ximage = NULL;
+      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n");
+      b->shm = 0;
+      return GL_FALSE;
+   }
+
+   b->shminfo.readOnly = False;
+   mesaXErrorFlag = 0;
+   old_handler = XSetErrorHandler(mesaHandleXError);
+   /* This may trigger the X protocol error we're ready to catch: */
+   XShmAttach(b->xm_visual->display, &b->shminfo);
+   XSync(b->xm_visual->display, False);
+
+   if (mesaXErrorFlag) {
+      /* we are on a remote display, this error is normal, don't print it */
+      XFlush(b->xm_visual->display);
+      mesaXErrorFlag = 0;
+      XDestroyImage(b->backxrb->ximage);
+      shmdt(b->shminfo.shmaddr);
+      shmctl(b->shminfo.shmid, IPC_RMID, 0);
+      b->backxrb->ximage = NULL;
+      b->shm = 0;
+      (void) XSetErrorHandler(old_handler);
+      return GL_FALSE;
+   }
+
+   shmctl(b->shminfo.shmid, IPC_RMID, 0); /* nobody else needs it */
+
+   /* Finally, try an XShmPutImage to be really sure the extension works */
+   gc = XCreateGC(b->xm_visual->display, b->frontxrb->drawable, 0, NULL);
+   XShmPutImage(b->xm_visual->display, b->frontxrb->drawable, gc,
+                b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False);
+   XSync(b->xm_visual->display, False);
+   XFreeGC(b->xm_visual->display, gc);
+   (void) XSetErrorHandler(old_handler);
+   if (mesaXErrorFlag) {
+      XFlush(b->xm_visual->display);
+      mesaXErrorFlag = 0;
+      XDestroyImage(b->backxrb->ximage);
+      shmdt(b->shminfo.shmaddr);
+      shmctl(b->shminfo.shmid, IPC_RMID, 0);
+      b->backxrb->ximage = NULL;
+      b->shm = 0;
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+#else
+static GLboolean
+alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
+{
+   /* Can't compile XSHM support */
+   return GL_FALSE;
+}
+#endif
+
+
+
+/**
+ * Setup an off-screen pixmap or Ximage to use as the back buffer.
+ * Input:  b - the X/Mesa buffer
+ */
+static void
+alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
+{
+   if (b->db_mode == BACK_XIMAGE) {
+      /* Deallocate the old backxrb->ximage, if any */
+      if (b->backxrb->ximage) {
+#if defined(USE_XSHM) && !defined(XFree86Server)
+        if (b->shm) {
+           XShmDetach(b->xm_visual->display, &b->shminfo);
+           XDestroyImage(b->backxrb->ximage);
+           shmdt(b->shminfo.shmaddr);
+        }
+        else
+#endif
+          XMesaDestroyImage(b->backxrb->ximage);
+        b->backxrb->ximage = NULL;
+      }
+
+      if (width == 0 || height == 0)
+         return;
+
+      /* Allocate new back buffer */
+      if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) {
+        /* Allocate a regular XImage for the back buffer. */
+#ifdef XFree86Server
+        b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
+                                               width, height, NULL);
+#else
+        b->backxrb->ximage = XCreateImage(b->xm_visual->display,
+                                      b->xm_visual->visinfo->visual,
+                                      GET_VISUAL_DEPTH(b->xm_visual),
+                                     ZPixmap, 0,   /* format, offset */
+                                     NULL,
+                                      width, height,
+                                     8, 0);  /* pad, bytes_per_line */
+#endif
+        if (!b->backxrb->ximage) {
+           _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n");
+            return;
+        }
+         b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height
+                                        * b->backxrb->ximage->bytes_per_line);
+         if (!b->backxrb->ximage->data) {
+            _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n");
+            XMesaDestroyImage(b->backxrb->ximage);
+            b->backxrb->ximage = NULL;
+         }
+      }
+      b->backxrb->pixmap = None;
+   }
+   else if (b->db_mode == BACK_PIXMAP) {
+      /* Free the old back pixmap */
+      if (b->backxrb->pixmap) {
+         XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap);
+         b->backxrb->pixmap = 0;
+      }
+
+      if (width > 0 && height > 0) {
+         /* Allocate new back pixmap */
+         b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display,
+                                                b->frontxrb->drawable,
+                                                width, height,
+                                                GET_VISUAL_DEPTH(b->xm_visual));
+      }
+
+      b->backxrb->ximage = NULL;
+   }
+}
+
+
+static void
+xmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+   /* XXX Note: the ximage or Pixmap attached to this renderbuffer
+    * should probably get freed here, but that's currently done in
+    * XMesaDestroyBuffer().
+    */
+   _mesa_free(rb);
+}
+
+
+static void
+finish_surface_init(GLcontext *ctx, struct xmesa_renderbuffer *xrb)
+{
+   struct pipe_context *pipe = ctx->st->pipe;
+   if (!xrb->St.surface->region) {
+      int w = 1, h = 1;
+      xrb->St.surface->region = pipe->winsys->region_alloc(pipe->winsys,
+                                                           1, w, h, 0x0);
+   }
+}
+
+
+/**
+ * Reallocate renderbuffer storage for front color buffer.
+ * Called via gl_renderbuffer::AllocStorage()
+ */
+static GLboolean
+xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                          GLenum internalFormat, GLuint width, GLuint height)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+   /* just clear these to be sure we don't accidentally use them */
+   xrb->origin1 = NULL;
+   xrb->origin2 = NULL;
+   xrb->origin3 = NULL;
+   xrb->origin4 = NULL;
+
+   /* for the FLIP macro: */
+   xrb->bottom = height - 1;
+
+   rb->Width = width;
+   rb->Height = height;
+   rb->InternalFormat = internalFormat;
+
+   if (!xrb->St.surface || !xrb->St.surface->region)
+      finish_surface_init(ctx, xrb);
+
+   xrb->St.surface->width = width;
+   xrb->St.surface->height = height;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Reallocate renderbuffer storage for back color buffer.
+ * Called via gl_renderbuffer::AllocStorage()
+ */
+static GLboolean
+xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+                         GLenum internalFormat, GLuint width, GLuint height)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+   /* reallocate the back buffer XImage or Pixmap */
+   assert(xrb->Parent);
+   alloc_back_buffer(xrb->Parent, width, height);
+
+   /* same as front buffer */
+   /* XXX why is this here? */
+   (void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height);
+
+   /* plus... */
+   if (xrb->ximage) {
+      /* Needed by PIXELADDR1 macro */
+      xrb->width1 = xrb->ximage->bytes_per_line;
+      xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1);
+
+      /* Needed by PIXELADDR2 macro */
+      xrb->width2 = xrb->ximage->bytes_per_line / 2;
+      xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1);
+
+      /* Needed by PIXELADDR3 macro */
+      xrb->width3 = xrb->ximage->bytes_per_line;
+      xrb->origin3 = (GLubyte *) xrb->ximage->data + xrb->width3 * (height - 1);
+
+      /* Needed by PIXELADDR4 macro */
+      xrb->width4 = xrb->ximage->width;
+      xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1);
+   }
+   else {
+      /* out of memory or buffer size is 0 x 0 */
+      xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0;
+      xrb->origin1 = NULL;
+      xrb->origin2 = NULL;
+      xrb->origin3 = NULL;
+      xrb->origin4 = NULL;
+   }
+
+   if (!xrb->St.surface || !xrb->St.surface->region)
+      finish_surface_init(ctx, xrb);
+
+   xrb->St.surface->width = width;
+   xrb->St.surface->height = height;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Called to create the front/back color renderbuffers, not user-created
+ * renderbuffers.
+ */
+struct xmesa_renderbuffer *
+xmesa_create_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual,
+                          GLboolean backBuffer)
+{
+   struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
+   struct pipe_context *pipe = NULL;/*ctx->st->pipe;*/
+   if (xrb) {
+      GLuint name = 0;
+      GLuint pipeFormat = 0;
+      struct xmesa_surface *xms;
+
+      _mesa_init_renderbuffer(&xrb->St.Base, name);
+
+      xrb->St.Base.Delete = xmesa_delete_renderbuffer;
+      if (backBuffer)
+         xrb->St.Base.AllocStorage = xmesa_alloc_back_storage;
+      else
+         xrb->St.Base.AllocStorage = xmesa_alloc_front_storage;
+
+      if (visual->rgbMode) {
+         xrb->St.Base.InternalFormat = GL_RGBA;
+         xrb->St.Base._BaseFormat = GL_RGBA;
+         xrb->St.Base.DataType = GL_UNSIGNED_BYTE;
+         xrb->St.Base.RedBits = visual->redBits;
+         xrb->St.Base.GreenBits = visual->greenBits;
+         xrb->St.Base.BlueBits = visual->blueBits;
+         xrb->St.Base.AlphaBits = visual->alphaBits;
+         pipeFormat = PIPE_FORMAT_U_A8_R8_G8_B8;
+      }
+      else {
+         xrb->St.Base.InternalFormat = GL_COLOR_INDEX;
+         xrb->St.Base._BaseFormat = GL_COLOR_INDEX;
+         xrb->St.Base.DataType = GL_UNSIGNED_INT;
+         xrb->St.Base.IndexBits = visual->indexBits;
+      }
+      /* only need to set Red/Green/EtcBits fields for user-created RBs */
+
+      xrb->St.surface = xmesa_new_color_surface(pipe, pipeFormat);
+      xms = (struct xmesa_surface *) xrb->St.surface;
+      xms->xrb = xrb;
+   }
+   return xrb;
+}
+
+
+#if 0
+struct gl_renderbuffer *
+xmesa_new_renderbuffer(GLcontext *ctx, struct gl_renderbuffer *rb,
+                       GLenum internalFormat, GLuint width, GLuint height)
+{
+   struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
+   if (xrb) {
+      GLuint name = 0;
+      _mesa_init_renderbuffer(&xrb->St.Base, name);
+
+      xrb->St.Base.Delete = xmesa_delete_renderbuffer;
+      if (backBuffer)
+         xrb->St.Base.AllocStorage = xmesa_alloc_back_storage;
+      else
+         xrb->St.Base.AllocStorage = xmesa_alloc_front_storage;
+
+      if (visual->rgbMode) {
+         xrb->St.Base.InternalFormat = GL_RGBA;
+         xrb->St.Base._BaseFormat = GL_RGBA;
+         xrb->St.Base.DataType = GL_UNSIGNED_BYTE;
+         xrb->St.Base.RedBits = visual->redBits;
+         xrb->St.Base.GreenBits = visual->greenBits;
+         xrb->St.Base.BlueBits = visual->blueBits;
+         xrb->St.Base.AlphaBits = visual->alphaBits;
+      }
+      else {
+         xrb->St.Base.InternalFormat = GL_COLOR_INDEX;
+         xrb->St.Base._BaseFormat = GL_COLOR_INDEX;
+         xrb->St.Base.DataType = GL_UNSIGNED_INT;
+         xrb->St.Base.IndexBits = visual->indexBits;
+      }
+      /* only need to set Red/Green/EtcBits fields for user-created RBs */
+   }
+   return xrb;
+}
+#endif
+
+
+/**
+ * Called via gl_framebuffer::Delete() method when this buffer
+ * is _really_ being deleted.
+ */
+void
+xmesa_delete_framebuffer(struct gl_framebuffer *fb)
+{
+   XMesaBuffer b = XMESA_BUFFER(fb);
+
+   if (b->num_alloced > 0) {
+      /* If no other buffer uses this X colormap then free the colors. */
+      if (!xmesa_find_buffer(b->display, b->cmap, b)) {
+#ifdef XFree86Server
+         int client = 0;
+         if (b->frontxrb->drawable)
+            client = CLIENT_ID(b->frontxrb->drawable->id);
+         (void)FreeColors(b->cmap, client,
+                          b->num_alloced, b->alloced_colors, 0);
+#else
+         XFreeColors(b->display, b->cmap,
+                     b->alloced_colors, b->num_alloced, 0);
+#endif
+      }
+   }
+
+   if (b->gc)
+      XMesaFreeGC(b->display, b->gc);
+   if (b->cleargc)
+      XMesaFreeGC(b->display, b->cleargc);
+   if (b->swapgc)
+      XMesaFreeGC(b->display, b->swapgc);
+
+   if (fb->Visual.doubleBufferMode) {
+      /* free back ximage/pixmap/shmregion */
+      if (b->backxrb->ximage) {
+#if defined(USE_XSHM) && !defined(XFree86Server)
+         if (b->shm) {
+            XShmDetach( b->display, &b->shminfo );
+            XDestroyImage( b->backxrb->ximage );
+            shmdt( b->shminfo.shmaddr );
+         }
+         else
+#endif
+            XMesaDestroyImage( b->backxrb->ximage );
+         b->backxrb->ximage = NULL;
+      }
+      if (b->backxrb->pixmap) {
+         XMesaFreePixmap( b->display, b->backxrb->pixmap );
+         if (b->xm_visual->hpcr_clear_flag) {
+            XMesaFreePixmap( b->display,
+                             b->xm_visual->hpcr_clear_pixmap );
+            XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
+         }
+      }
+   }
+
+   if (b->rowimage) {
+      _mesa_free( b->rowimage->data );
+      b->rowimage->data = NULL;
+      XMesaDestroyImage( b->rowimage );
+   }
+
+   _mesa_free_framebuffer_data(fb);
+   _mesa_free(fb);
+}
diff --git a/src/mesa/pipe/xlib/xm_dd.c b/src/mesa/pipe/xlib/xm_dd.c
new file mode 100644 (file)
index 0000000..8ae243a
--- /dev/null
@@ -0,0 +1,1141 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * \file xm_dd.h
+ * General device driver functions for Xlib driver.
+ */
+
+#include "glxheader.h"
+#include "bufferobj.h"
+#include "buffers.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "drawpix.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "macros.h"
+#include "image.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "xmesaP.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#include "pipe/softpipe/sp_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_draw.h"
+
+
+/*
+ * Dithering kernels and lookup tables.
+ */
+
+const int xmesa_kernel8[DITH_DY * DITH_DX] = {
+    0 * MAXC,  8 * MAXC,  2 * MAXC, 10 * MAXC,
+   12 * MAXC,  4 * MAXC, 14 * MAXC,  6 * MAXC,
+    3 * MAXC, 11 * MAXC,  1 * MAXC,  9 * MAXC,
+   15 * MAXC,  7 * MAXC, 13 * MAXC,  5 * MAXC,
+};
+
+const short xmesa_HPCR_DRGB[3][2][16] = {
+   {
+      { 16, -4,  1,-11, 14, -6,  3, -9, 15, -5,  2,-10, 13, -7,  4, -8},
+      {-15,  5,  0, 12,-13,  7, -2, 10,-14,  6, -1, 11,-12,  8, -3,  9}
+   },
+   {
+      {-11, 15, -7,  3, -8, 14, -4,  2,-10, 16, -6,  4, -9, 13, -5,  1},
+      { 12,-14,  8, -2,  9,-13,  5, -1, 11,-15,  7, -3, 10,-12,  6,  0}
+   },
+   {
+      {  6,-18, 26,-14,  2,-22, 30,-10,  8,-16, 28,-12,  4,-20, 32, -8},
+      { -4, 20,-24, 16,  0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
+   }
+};
+
+const int xmesa_kernel1[16] = {
+   0*47,  9*47,  4*47, 12*47,     /* 47 = (255*3)/16 */
+   6*47,  2*47, 14*47,  8*47,
+  10*47,  1*47,  5*47, 11*47,
+   7*47, 13*47,  3*47, 15*47
+};
+
+
+static void
+finish_or_flush( GLcontext *ctx )
+{
+#ifdef XFree86Server
+      /* NOT_NEEDED */
+#else
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   if (xmesa) {
+      _glthread_LOCK_MUTEX(_xmesa_lock);
+      XSync( xmesa->display, False );
+      _glthread_UNLOCK_MUTEX(_xmesa_lock);
+   }
+#endif
+}
+
+
+static void
+clear_index( GLcontext *ctx, GLuint index )
+{
+   if (ctx->DrawBuffer->Name == 0) {
+      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+      xmesa->clearpixel = (unsigned long) index;
+      XMesaSetForeground( xmesa->display, xmbuf->cleargc, (unsigned long) index );
+   }
+}
+
+
+static void
+clear_color( GLcontext *ctx, const GLfloat color[4] )
+{
+   if (ctx->DrawBuffer->Name == 0) {
+      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+
+      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+      CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+      xmesa->clearpixel = xmesa_color_to_pixel( ctx,
+                                                xmesa->clearcolor[0],
+                                                xmesa->clearcolor[1],
+                                                xmesa->clearcolor[2],
+                                                xmesa->clearcolor[3],
+                                                xmesa->xm_visual->undithered_pf );
+      _glthread_LOCK_MUTEX(_xmesa_lock);
+      XMesaSetForeground( xmesa->display, xmbuf->cleargc,
+                          xmesa->clearpixel );
+      _glthread_UNLOCK_MUTEX(_xmesa_lock);
+   }
+}
+
+
+
+/* Set index mask ala glIndexMask */
+static void
+index_mask( GLcontext *ctx, GLuint mask )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+   /* not sure this conditional is really needed */
+   if (xmbuf->backxrb && xmbuf->backxrb->pixmap) {
+      unsigned long m;
+      if (mask==0xffffffff) {
+        m = ((unsigned long)~0L);
+      }
+      else {
+         m = (unsigned long) mask;
+      }
+      XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
+   }
+}
+
+
+/* Implements glColorMask() */
+static void
+color_mask(GLcontext *ctx,
+           GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf;
+   const int xclass = xmesa->xm_visual->mesa_visual.visualType;
+   (void) amask;
+
+   if (ctx->DrawBuffer->Name != 0)
+      return;
+
+   xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+
+   if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
+      unsigned long m;
+      if (rmask && gmask && bmask) {
+         m = ((unsigned long)~0L);
+      }
+      else {
+         m = 0;
+         if (rmask)   m |= GET_REDMASK(xmesa->xm_visual);
+         if (gmask)   m |= GET_GREENMASK(xmesa->xm_visual);
+         if (bmask)   m |= GET_BLUEMASK(xmesa->xm_visual);
+      }
+      XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
+   }
+}
+
+
+
+/**********************************************************************/
+/*** glClear implementations                                        ***/
+/**********************************************************************/
+
+
+/**
+ * Clear the front or back color buffer, if it's implemented with a pixmap.
+ */
+static void
+clear_pixmap(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+             GLint x, GLint y, GLint width, GLint height)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+
+   assert(xmbuf);
+   assert(xrb->pixmap);
+   assert(xmesa);
+   assert(xmesa->display);
+   assert(xrb->pixmap);
+   assert(xmbuf->cleargc);
+
+   XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
+                       x, xrb->St.Base.Height - y - height,
+                       width, height );
+}
+
+
+static void
+clear_8bit_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLint x, GLint y, GLint width, GLint height )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLint i;
+   for (i = 0; i < height; i++) {
+      GLubyte *ptr = PIXEL_ADDR1(xrb, x, y + i);
+      MEMSET( ptr, xmesa->clearpixel, width );
+   }
+}
+
+
+static void
+clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLint x, GLint y, GLint width, GLint height )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLint i;
+   for (i = y; i < y + height; i++) {
+      GLubyte *ptr = PIXEL_ADDR1( xrb, x, i );
+      int j;
+      const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+      if (i & 1) {
+         sptr += 16;
+      }
+      for (j = x; j < x + width; j++) {
+         *ptr = sptr[j&15];
+         ptr++;
+      }
+   }
+}
+
+
+static void
+clear_16bit_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                    GLint x, GLint y, GLint width, GLint height)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLuint pixel = (GLuint) xmesa->clearpixel;
+   GLint i, j;
+
+   if (xmesa->swapbytes) {
+      pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
+   }
+
+   for (j = 0; j < height; j++) {
+      GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y + j);
+      for (i = 0; i < width; i++) {
+         ptr2[i] = pixel;
+      }
+   }
+}
+
+
+/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
+static void
+clear_24bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLint x, GLint y, GLint width, GLint height)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const GLubyte r = xmesa->clearcolor[0];
+   const GLubyte g = xmesa->clearcolor[1];
+   const GLubyte b = xmesa->clearcolor[2];
+
+   if (r == g && g == b) {
+      /* same value for all three components (gray) */
+      GLint j;
+      for (j = 0; j < height; j++) {
+         bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
+         MEMSET(ptr3, r, 3 * width);
+      }
+   }
+   else {
+      /* non-gray clear color */
+      GLint i, j;
+      for (j = 0; j < height; j++) {
+         bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
+         for (i = 0; i < width; i++) {
+            ptr3->r = r;
+            ptr3->g = g;
+            ptr3->b = b;
+            ptr3++;
+         }
+      }
+   }
+}
+
+
+static void
+clear_32bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                   GLint x, GLint y, GLint width, GLint height)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint pixel = (GLuint) xmesa->clearpixel;
+
+   if (!xrb->ximage)
+      return;
+
+   if (xmesa->swapbytes) {
+      pixel = ((pixel >> 24) & 0x000000ff)
+            | ((pixel >> 8)  & 0x0000ff00)
+            | ((pixel << 8)  & 0x00ff0000)
+            | ((pixel << 24) & 0xff000000);
+   }
+
+   if (width == xrb->St.Base.Width && height == xrb->St.Base.Height) {
+      /* clearing whole buffer */
+      const GLuint n = xrb->St.Base.Width * xrb->St.Base.Height;
+      GLuint *ptr4 = (GLuint *) xrb->ximage->data;
+      if (pixel == 0) {
+         /* common case */
+         _mesa_memset(ptr4, pixel, 4 * n);
+      }
+      else {
+         GLuint i;
+         for (i = 0; i < n; i++)
+            ptr4[i] = pixel;
+      }
+   }
+   else {
+      /* clearing scissored region */
+      GLint i, j;
+      for (j = 0; j < height; j++) {
+         GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y + j);
+         for (i = 0; i < width; i++) {
+            ptr4[i] = pixel;
+         }
+      }
+   }
+}
+
+
+static void
+clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                  GLint x, GLint y, GLint width, GLint height)
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaImage *img = xrb->ximage;
+   GLint i, j;
+
+   /* TODO: optimize this */
+   y = YFLIP(xrb, y);
+   for (j = 0; j < height; j++) {
+      for (i = 0; i < width; i++) {
+         XMesaPutPixel(img, x+i, y-j, xmesa->clearpixel);
+      }
+   }
+}
+
+
+
+void
+xmesa_clear_buffers(GLcontext *ctx, GLbitfield buffers)
+{
+   if (ctx->DrawBuffer->Name == 0) {
+      /* this is a window system framebuffer */
+      const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+      XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
+      const GLint x = ctx->DrawBuffer->_Xmin;
+      const GLint y = ctx->DrawBuffer->_Ymin;
+      const GLint width = ctx->DrawBuffer->_Xmax - x;
+      const GLint height = ctx->DrawBuffer->_Ymax - y;
+
+      /* we can't handle color or index masking */
+      if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+         if (buffers & BUFFER_BIT_FRONT_LEFT) {
+            /* clear front color buffer */
+            struct gl_renderbuffer *frontRb
+               = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+            if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
+               /* renderbuffer is not wrapped - great! */
+               b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
+               buffers &= ~BUFFER_BIT_FRONT_LEFT;
+            }
+            else {
+               /* we can't directly clear an alpha-wrapped color buffer */
+            }
+         }
+         if (buffers & BUFFER_BIT_BACK_LEFT) {
+            /* clear back color buffer */
+            struct gl_renderbuffer *backRb
+               = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+            if (b->backxrb == xmesa_renderbuffer(backRb)) {
+               /* renderbuffer is not wrapped - great! */
+               b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
+               buffers &= ~BUFFER_BIT_BACK_LEFT;
+            }
+         }
+      }
+   }
+   if (buffers)
+      _swrast_Clear(ctx, buffers);
+}
+
+
+#ifndef XFree86Server
+/* XXX this was never tested in the Xserver environment */
+
+/**
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable).
+ * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
+ */
+static void
+xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels )
+{
+   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
+
+   if (swrast->NewState)
+      _swrast_validate_derived( ctx );
+
+   if (ctx->DrawBuffer->Name == 0 &&
+       format == GL_BGRA &&
+       type == GL_UNSIGNED_BYTE &&
+       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
+       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
+       ctx->Pixel.ZoomY == 1.0 &&
+       xrb->pixmap &&                    /* drawing to pixmap or window */
+       xrb->St.Base.AlphaBits == 0)
+   {
+      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+      XMesaDisplay *dpy = xmesa->xm_visual->display;
+      const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
+      int dstX = x;
+      int dstY = y;
+      int w = width;
+      int h = height;
+      struct gl_pixelstore_attrib clippedUnpack = *unpack;
+
+      ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
+      ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
+      ASSERT(dpy);
+      ASSERT(gc);
+
+      if (unpack->BufferObj->Name) {
+         /* unpack from PBO */
+         GLubyte *buf;
+         if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+                                        format, type, pixels)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(invalid PBO access)");
+            return;
+         }
+         buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
+                                                 GL_PIXEL_UNPACK_BUFFER_EXT,
+                                                 GL_READ_ONLY_ARB,
+                                                 unpack->BufferObj);
+         if (!buf) {
+            /* buffer is already mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(PBO is mapped)");
+            return;
+         }
+         pixels = ADD_POINTERS(buf, pixels);
+      }
+
+      if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
+         /* This is a little tricky since all coordinates up to now have
+          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
+          * so we have to carefully compute the Y coordinates/addresses here.
+          */
+         int srcX = clippedUnpack.SkipPixels;
+         int srcY = clippedUnpack.SkipRows;
+         int rowLength = clippedUnpack.RowLength;
+         XMesaImage ximage;
+         MEMSET(&ximage, 0, sizeof(XMesaImage));
+         ximage.width = width;
+         ximage.height = height;
+         ximage.format = ZPixmap;
+         ximage.data = (char *) pixels
+            + ((srcY + h - 1) * rowLength + srcX) * 4;
+         ximage.byte_order = LSBFirst;
+         ximage.bitmap_unit = 32;
+         ximage.bitmap_bit_order = LSBFirst;
+         ximage.bitmap_pad = 32;
+         ximage.depth = 24;
+         ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
+         ximage.bits_per_pixel = 32;
+         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
+         /* flip Y axis for dest position */
+         dstY = YFLIP(xrb, dstY) - h + 1;
+         XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
+      }
+
+      if (unpack->BufferObj->Name) {
+         ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                 unpack->BufferObj);
+      }
+   }
+   else {
+      /* software fallback */
+      _swrast_DrawPixels(ctx, x, y, width, height,
+                         format, type, unpack, pixels);
+   }
+}
+
+
+
+/**
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable).  The image format
+ * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
+ * match the PF_5R6G5B pixel format.
+ */
+static void
+xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels )
+{
+   struct xmesa_renderbuffer *xrb
+      = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+   const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
+
+   ASSERT(dpy);
+   ASSERT(gc);
+   ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
+
+   if (swrast->NewState)
+      _swrast_validate_derived( ctx );
+
+   if (xrb->pixmap &&       /* drawing to pixmap or window */
+       format == GL_RGB &&
+       type == GL_UNSIGNED_SHORT_5_6_5 &&
+       !ctx->Color.DitherFlag &&  /* no dithering */
+       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
+       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
+       ctx->Pixel.ZoomY == 1.0) {
+      int dstX = x;
+      int dstY = y;
+      int w = width;
+      int h = height;
+      struct gl_pixelstore_attrib clippedUnpack = *unpack;
+
+      if (unpack->BufferObj->Name) {
+         /* unpack from PBO */
+         GLubyte *buf;
+         if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+                                        format, type, pixels)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(invalid PBO access)");
+            return;
+         }
+         buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
+                                                 GL_PIXEL_UNPACK_BUFFER_EXT,
+                                                 GL_READ_ONLY_ARB,
+                                                 unpack->BufferObj);
+         if (!buf) {
+            /* buffer is already mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(PBO is mapped)");
+            return;
+         }
+         pixels = ADD_POINTERS(buf, pixels);
+      }
+
+      if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
+         /* This is a little tricky since all coordinates up to now have
+          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
+          * so we have to carefully compute the Y coordinates/addresses here.
+          */
+         int srcX = clippedUnpack.SkipPixels;
+         int srcY = clippedUnpack.SkipRows;
+         int rowLength = clippedUnpack.RowLength;
+         XMesaImage ximage;
+         MEMSET(&ximage, 0, sizeof(XMesaImage));
+         ximage.width = width;
+         ximage.height = height;
+         ximage.format = ZPixmap;
+         ximage.data = (char *) pixels
+            + ((srcY + h - 1) * rowLength + srcX) * 2;
+         ximage.byte_order = LSBFirst;
+         ximage.bitmap_unit = 16;
+         ximage.bitmap_bit_order = LSBFirst;
+         ximage.bitmap_pad = 16;
+         ximage.depth = 16;
+         ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
+         ximage.bits_per_pixel = 16;
+         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
+         /* flip Y axis for dest position */
+         dstY = YFLIP(xrb, dstY) - h + 1;
+         XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
+      }
+
+      if (unpack->BufferObj->Name) {
+         ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                 unpack->BufferObj);
+      }
+   }
+   else {
+      /* software fallback */
+      _swrast_DrawPixels(ctx, x, y, width, height,
+                         format, type, unpack, pixels);
+   }
+}
+
+
+
+/**
+ * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
+ * for the color buffer.  Don't support zooming, pixel transfer, etc.
+ * We do support copying from one window to another, ala glXMakeCurrentRead.
+ */
+static void
+xmesa_CopyPixels( GLcontext *ctx,
+                  GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+                  GLint destx, GLint desty, GLenum type )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+   const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
+   struct xmesa_renderbuffer *srcXrb
+      = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
+   struct xmesa_renderbuffer *dstXrb
+      = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
+
+   ASSERT(dpy);
+   ASSERT(gc);
+
+   if (swrast->NewState)
+      _swrast_validate_derived( ctx );
+
+   if (ctx->Color.DrawBuffer[0] == GL_FRONT &&
+       ctx->Pixel.ReadBuffer == GL_FRONT &&
+       srcXrb->pixmap &&
+       dstXrb->pixmap &&
+       type == GL_COLOR &&
+       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
+       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
+       ctx->Pixel.ZoomY == 1.0) {
+      /* Note: we don't do any special clipping work here.  We could,
+       * but X will do it for us.
+       */
+      srcy = YFLIP(srcXrb, srcy) - height + 1;
+      desty = YFLIP(dstXrb, desty) - height + 1;
+      XCopyArea(dpy, srcXrb->pixmap, dstXrb->pixmap, gc,
+                srcx, srcy, width, height, destx, desty);
+   }
+   else {
+      _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
+   }
+}
+#endif /* XFree86Server */
+
+
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *
+get_string( GLcontext *ctx, GLenum name )
+{
+   (void) ctx;
+   switch (name) {
+      case GL_RENDERER:
+#ifdef XFree86Server
+         return (const GLubyte *) "Mesa GLX Indirect";
+#else
+         return (const GLubyte *) "Mesa X11 (softpipe)";
+#endif
+      case GL_VENDOR:
+#ifdef XFree86Server
+         return (const GLubyte *) "Mesa project: www.mesa3d.org";
+#else
+         return NULL;
+#endif
+      default:
+         return NULL;
+   }
+}
+
+
+/*
+ * We implement the glEnable function only because we care about
+ * dither enable/disable.
+ */
+static void
+enable( GLcontext *ctx, GLenum pname, GLboolean state )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+   switch (pname) {
+      case GL_DITHER:
+         if (state)
+            xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
+         else
+            xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
+         break;
+      default:
+         ;  /* silence compiler warning */
+   }
+}
+
+
+static void
+clear_color_HPCR_ximage( GLcontext *ctx, const GLfloat color[4] )
+{
+   int i;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+
+   if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
+      /* black is black */
+      MEMSET( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
+              sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
+   }
+   else {
+      /* build clear pattern */
+      for (i=0; i<16; i++) {
+         xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
+            DITHER_HPCR(i, 0,
+                        xmesa->clearcolor[0],
+                        xmesa->clearcolor[1],
+                        xmesa->clearcolor[2]);
+         xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i]    =
+            DITHER_HPCR(i, 1,
+                        xmesa->clearcolor[0],
+                        xmesa->clearcolor[1],
+                        xmesa->clearcolor[2]);
+      }
+   }
+}
+
+
+static void
+clear_color_HPCR_pixmap( GLcontext *ctx, const GLfloat color[4] )
+{
+   int i;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+
+   if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
+      /* black is black */
+      for (i=0; i<16; i++) {
+         XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0);
+         XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0);
+      }
+   }
+   else {
+      for (i=0; i<16; i++) {
+         XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
+                       DITHER_HPCR(i, 0,
+                                   xmesa->clearcolor[0],
+                                   xmesa->clearcolor[1],
+                                   xmesa->clearcolor[2]));
+         XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
+                       DITHER_HPCR(i, 1,
+                                   xmesa->clearcolor[0],
+                                   xmesa->clearcolor[1],
+                                   xmesa->clearcolor[2]));
+      }
+   }
+   /* change tile pixmap content */
+   XMesaPutImage(xmesa->display,
+                (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap,
+                XMESA_BUFFER(ctx->DrawBuffer)->cleargc,
+                xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
+}
+
+
+/**
+ * Called when the driver should update its state, based on the new_state
+ * flags.
+ */
+void
+xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
+{
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+   /* Propagate statechange information to swrast and swrast_setup
+    * modules.  The X11 driver has no internal GL-dependent state.
+    */
+   _swrast_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+   _vbo_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
+
+   st_invalidate_state( ctx, new_state );
+
+
+   if (ctx->DrawBuffer->Name != 0)
+      return;
+
+   /*
+    * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
+    * renderbuffer span/clear funcs.
+    */
+   if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
+      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+      struct xmesa_renderbuffer *front_xrb, *back_xrb;
+
+      front_xrb = xmbuf->frontxrb;
+      if (front_xrb) {
+         xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
+                                      xmesa->xm_visual->BitsPerPixel);
+         front_xrb->clearFunc = clear_pixmap;
+      }
+
+      back_xrb = xmbuf->backxrb;
+      if (back_xrb) {
+         xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat,
+                                      xmesa->xm_visual->BitsPerPixel);
+         if (xmbuf->backxrb->pixmap) {
+            back_xrb->clearFunc = clear_pixmap;
+         }
+         else {
+            switch (xmesa->xm_visual->BitsPerPixel) {
+            case 8:
+               if (xmesa->xm_visual->hpcr_clear_flag) {
+                  back_xrb->clearFunc = clear_HPCR_ximage;
+               }
+               else {
+                  back_xrb->clearFunc = clear_8bit_ximage;
+               }
+               break;
+            case 16:
+               back_xrb->clearFunc = clear_16bit_ximage;
+               break;
+            case 24:
+               back_xrb->clearFunc = clear_24bit_ximage;
+               break;
+            case 32:
+               back_xrb->clearFunc = clear_32bit_ximage;
+               break;
+            default:
+               back_xrb->clearFunc = clear_nbit_ximage;
+               break;
+            }
+         }
+      }
+   }
+
+   if (xmesa->xm_visual->hpcr_clear_flag) {
+      /* this depends on whether we're drawing to the front or back buffer */
+      /* XXX FIX THIS! */
+#if 0
+      if (pixmap) {
+         ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
+      }
+      else {
+         ctx->Driver.ClearColor = clear_color_HPCR_ximage;
+      }
+#else
+      (void) clear_color_HPCR_pixmap;
+      (void) clear_color_HPCR_ximage;
+#endif
+   }
+}
+
+
+
+/**
+ * Called via ctx->Driver.TestProxyTeximage().  Normally, we'd just use
+ * the _mesa_test_proxy_teximage() fallback function, but we're going to
+ * special-case the 3D texture case to allow textures up to 512x512x32
+ * texels.
+ */
+static GLboolean
+test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+                    GLint internalFormat, GLenum format, GLenum type,
+                    GLint width, GLint height, GLint depth, GLint border)
+{
+   if (target == GL_PROXY_TEXTURE_3D) {
+      /* special case for 3D textures */
+      if (width * height * depth > 512 * 512 * 64 ||
+          width  < 2 * border ||
+          (!ctx->Extensions.ARB_texture_non_power_of_two &&
+           _mesa_bitcount(width  - 2 * border) != 1) ||
+          height < 2 * border ||
+          (!ctx->Extensions.ARB_texture_non_power_of_two &&
+           _mesa_bitcount(height - 2 * border) != 1) ||
+          depth  < 2 * border ||
+          (!ctx->Extensions.ARB_texture_non_power_of_two &&
+           _mesa_bitcount(depth  - 2 * border) != 1)) {
+         /* Bad size, or too many texels */
+         return GL_FALSE;
+      }
+      return GL_TRUE;
+   }
+   else {
+      /* use the fallback routine for 1D, 2D, cube and rect targets */
+      return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
+                                       format, type, width, height, depth,
+                                       border);
+   }
+}
+
+
+/**
+ * In SW, we don't really compress GL_COMPRESSED_RGB[A] textures!
+ */
+static const struct gl_texture_format *
+choose_tex_format( GLcontext *ctx, GLint internalFormat,
+                   GLenum format, GLenum type )
+{
+   switch (internalFormat) {
+      case GL_COMPRESSED_RGB_ARB:
+         return &_mesa_texformat_rgb;
+      case GL_COMPRESSED_RGBA_ARB:
+         return &_mesa_texformat_rgba;
+      default:
+         return _mesa_choose_tex_format(ctx, internalFormat, format, type);
+   }
+}
+
+
+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current X window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * X Resize/StructureNotify events since the X driver has no event loop.
+ * Thus, we poll.
+ * Note that this trick isn't fool-proof.  If the application never calls
+ * glViewport, our notion of the current window size may be incorrect.
+ * That problem led to the GLX_MESA_resize_buffers extension.
+ */
+static void
+xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+   XMesaContext xmctx = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
+   XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
+   xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
+   xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
+   (void) x;
+   (void) y;
+   (void) w;
+   (void) h;
+}
+
+
+#if ENABLE_EXT_timer_query
+
+/*
+ * The GL_EXT_timer_query extension is not enabled for the XServer
+ * indirect renderer.  Not sure about how/if wrapping of gettimeofday()
+ * is done, etc.
+ */
+
+struct xmesa_query_object
+{
+   struct gl_query_object Base;
+   struct timeval StartTime;
+};
+
+
+static struct gl_query_object *
+xmesa_new_query_object(GLcontext *ctx, GLuint id)
+{
+   struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
+   if (q) {
+      q->Base.Id = id;
+      q->Base.Ready = GL_TRUE;
+   }
+   return &q->Base;
+}
+
+
+static void
+xmesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
+{
+   if (q->Target == GL_TIME_ELAPSED_EXT) {
+      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+      (void) gettimeofday(&xq->StartTime, NULL);
+   }
+}
+
+
+/**
+ * Return the difference between the two given times in microseconds.
+ */
+#ifdef __VMS
+#define suseconds_t unsigned int
+#endif
+static GLuint64EXT
+time_diff(const struct timeval *t0, const struct timeval *t1)
+{
+   GLuint64EXT seconds0 = t0->tv_sec & 0xff;  /* 0 .. 255 seconds */
+   GLuint64EXT seconds1 = t1->tv_sec & 0xff;  /* 0 .. 255 seconds */
+   GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
+   GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
+   return nanosec1 - nanosec0;
+}
+
+
+static void
+xmesa_end_query(GLcontext *ctx, struct gl_query_object *q)
+{
+   if (q->Target == GL_TIME_ELAPSED_EXT) {
+      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+      struct timeval endTime;
+      (void) gettimeofday(&endTime, NULL);
+      /* result is in nanoseconds! */
+      q->Result = time_diff(&xq->StartTime, &endTime);
+   }
+   q->Ready = GL_TRUE;
+}
+
+#endif /* ENABLE_timer_query */
+
+
+/**
+ * Initialize the device driver function table with the functions
+ * we implement in this driver.
+ */
+void
+xmesa_init_driver_functions( XMesaVisual xmvisual,
+                             struct dd_function_table *driver )
+{
+   driver->GetString = get_string;
+   driver->UpdateState = xmesa_update_state;
+   driver->GetBufferSize = NULL; /* OBSOLETE */
+   driver->Flush = finish_or_flush;
+   driver->Finish = finish_or_flush;
+   driver->ClearIndex = clear_index;
+   driver->ClearColor = clear_color;
+   driver->IndexMask = index_mask;
+   driver->ColorMask = color_mask;
+   driver->Enable = enable;
+   driver->Clear = xmesa_clear_buffers;
+   driver->Viewport = xmesa_viewport;
+#ifndef XFree86Server
+   driver->CopyPixels = xmesa_CopyPixels;
+   if (xmvisual->undithered_pf == PF_8R8G8B &&
+       xmvisual->dithered_pf == PF_8R8G8B) {
+      driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
+   }
+   else if (xmvisual->undithered_pf == PF_5R6G5B) {
+      driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
+   }
+#endif
+   driver->TestProxyTexImage = test_proxy_teximage;
+#if ENABLE_EXT_texure_compression_s3tc
+   driver->ChooseTextureFormat = choose_tex_format;
+#else
+   (void) choose_tex_format;
+#endif
+
+#if ENABLE_EXT_timer_query
+   driver->NewQueryObject = xmesa_new_query_object;
+   driver->BeginQuery = xmesa_begin_query;
+   driver->EndQuery = xmesa_end_query;
+#endif
+
+}
+
+
+#define XMESA_NEW_POINT  (_NEW_POINT | \
+                          _NEW_RENDERMODE | \
+                          _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_LINE   (_NEW_LINE | \
+                          _NEW_TEXTURE | \
+                          _NEW_LIGHT | \
+                          _NEW_DEPTH | \
+                          _NEW_RENDERMODE | \
+                          _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
+                            _NEW_TEXTURE | \
+                            _NEW_LIGHT | \
+                            _NEW_DEPTH | \
+                            _NEW_RENDERMODE | \
+                            _SWRAST_NEW_RASTERMASK)
+
+
+/**
+ * Extend the software rasterizer with our line/point/triangle
+ * functions.
+ * Called during context creation only.
+ */
+void xmesa_register_swrast_functions( GLcontext *ctx )
+{
+   SWcontext *swrast = SWRAST_CONTEXT( ctx );
+
+   swrast->choose_point = xmesa_choose_point;
+   swrast->choose_line = xmesa_choose_line;
+   swrast->choose_triangle = xmesa_choose_triangle;
+
+   /* XXX these lines have no net effect.  Remove??? */
+   swrast->InvalidatePointMask |= XMESA_NEW_POINT;
+   swrast->InvalidateLineMask |= XMESA_NEW_LINE;
+   swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;
+}
diff --git a/src/mesa/pipe/xlib/xm_image.c b/src/mesa/pipe/xlib/xm_image.c
new file mode 100644 (file)
index 0000000..087b4e4
--- /dev/null
@@ -0,0 +1,133 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+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, sub license, 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 NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ */
+
+#include <stdlib.h>
+#include <X11/Xmd.h>
+
+#include "glxheader.h"
+#include "xmesaP.h"
+
+#ifdef XFree86Server
+
+#ifdef ROUNDUP
+#undef ROUNDUP
+#endif
+
+#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3))
+
+XMesaImage *XMesaCreateImage(int bitsPerPixel, int width, int height, char *data)
+{
+    XMesaImage *image;
+
+    image = (XMesaImage *)xalloc(sizeof(XMesaImage));
+
+    if (image) {
+       image->width = width;
+       image->height = height;
+       image->data = data;
+       /* Always pad to 32 bits */
+       image->bytes_per_line = ROUNDUP((bitsPerPixel * width), 32);
+       image->bits_per_pixel = bitsPerPixel;
+    }
+
+    return image;
+}
+
+void XMesaDestroyImage(XMesaImage *image)
+{
+    if (image->data)
+       free(image->data);
+    xfree(image);
+}
+
+unsigned long XMesaGetPixel(XMesaImage *image, int x, int y)
+{
+    CARD8  *row = (CARD8 *)(image->data + y*image->bytes_per_line);
+    CARD8  *i8;
+    CARD16 *i16;
+    CARD32 *i32;
+    switch (image->bits_per_pixel) {
+    case 8:
+       i8 = (CARD8 *)row;
+       return i8[x];
+       break;
+    case 15:
+    case 16:
+       i16 = (CARD16 *)row;
+       return i16[x];
+       break;
+    case 24: /* WARNING: architecture specific code */
+       i8 = (CARD8 *)row;
+       return (((CARD32)i8[x*3]) |
+               (((CARD32)i8[x*3+1])<<8) |
+               (((CARD32)i8[x*3+2])<<16));
+       break;
+    case 32:
+       i32 = (CARD32 *)row;
+       return i32[x];
+       break;
+    }
+    return 0;
+}
+
+#ifndef XMESA_USE_PUTPIXEL_MACRO
+void XMesaPutPixel(XMesaImage *image, int x, int y, unsigned long pixel)
+{
+    CARD8  *row = (CARD8 *)(image->data + y*image->bytes_per_line);
+    CARD8  *i8;
+    CARD16 *i16;
+    CARD32 *i32;
+    switch (image->bits_per_pixel) {
+    case 8:
+       i8 = (CARD8 *)row;
+       i8[x] = (CARD8)pixel;
+       break;
+    case 15:
+    case 16:
+       i16 = (CARD16 *)row;
+       i16[x] = (CARD16)pixel;
+       break;
+    case 24: /* WARNING: architecture specific code */
+       i8 = (CARD8 *)__row;
+       i8[x*3]   = (CARD8)(p);
+       i8[x*3+1] = (CARD8)(p>>8);
+       i8[x*3+2] = (CARD8)(p>>16);
+    case 32:
+       i32 = (CARD32 *)row;
+       i32[x] = (CARD32)pixel;
+       break;
+    }
+}
+#endif
+
+#endif /* XFree86Server */
diff --git a/src/mesa/pipe/xlib/xm_image.h b/src/mesa/pipe/xlib/xm_image.h
new file mode 100644 (file)
index 0000000..2a5e0f3
--- /dev/null
@@ -0,0 +1,77 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+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, sub license, 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 NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ */
+
+#ifndef _XM_IMAGE_H_
+#define _XM_IMAGE_H_
+
+#define XMESA_USE_PUTPIXEL_MACRO
+
+extern XMesaImage *XMesaCreateImage(int bitsPerPixel, int width, int height,
+                                   char *data);
+extern void XMesaDestroyImage(XMesaImage *image);
+extern unsigned long XMesaGetPixel(XMesaImage *image, int x, int y);
+#ifdef XMESA_USE_PUTPIXEL_MACRO
+#define XMesaPutPixel(__i,__x,__y,__p) \
+{ \
+    CARD8  *__row = (CARD8 *)(__i->data + __y*__i->bytes_per_line); \
+    CARD8  *__i8; \
+    CARD16 *__i16; \
+    CARD32 *__i32; \
+    switch (__i->bits_per_pixel) { \
+    case 8: \
+       __i8 = (CARD8 *)__row; \
+       __i8[__x] = (CARD8)__p; \
+       break; \
+    case 15: \
+    case 16: \
+       __i16 = (CARD16 *)__row; \
+       __i16[__x] = (CARD16)__p; \
+       break; \
+    case 24: /* WARNING: architecture specific code */ \
+       __i8 = (CARD8 *)__row; \
+       __i8[__x*3]   = (CARD8)(__p); \
+       __i8[__x*3+1] = (CARD8)(__p>>8); \
+       __i8[__x*3+2] = (CARD8)(__p>>16); \
+       break; \
+    case 32: \
+       __i32 = (CARD32 *)__row; \
+       __i32[__x] = (CARD32)__p; \
+       break; \
+    } \
+}
+#else
+extern void XMesaPutPixel(XMesaImage *image, int x, int y,
+                         unsigned long pixel);
+#endif
+
+#endif /* _XM_IMAGE_H_ */
diff --git a/src/mesa/pipe/xlib/xm_line.c b/src/mesa/pipe/xlib/xm_line.c
new file mode 100644 (file)
index 0000000..deeae50
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * 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 file contains "accelerated" point, line, and triangle functions.
+ * It should be fairly easy to write new special-purpose point, line or
+ * triangle functions and hook them into this module.
+ */
+
+
+#include "glxheader.h"
+#include "depth.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "xmesaP.h"
+
+/* Internal swrast includes:
+ */
+#include "swrast/s_depth.h"
+#include "swrast/s_points.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_context.h"
+
+
+/**********************************************************************/
+/***                    Point rendering                             ***/
+/**********************************************************************/
+
+
+/*
+ * Render an array of points into a pixmap, any pixel format.
+ */
+#if 000
+/* XXX don't use this, it doesn't dither correctly */
+static void draw_points_ANY_pixmap( GLcontext *ctx, const SWvertex *vert )
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+   XMesaGC gc = xmesa->xm_buffer->gc;
+
+   if (xmesa->xm_visual->mesa_visual.RGBAflag) {
+      register int x, y;
+      const GLubyte *color = vert->color;
+      unsigned long pixel = xmesa_color_to_pixel( xmesa,
+                                                 color[0], color[1],
+                                                 color[2], color[3],
+                                                 xmesa->pixelformat);
+      XMesaSetForeground( dpy, gc, pixel );
+      x = (GLint) vert->win[0];
+      y = YFLIP( xrb, (GLint) vert->win[1] );
+      XMesaDrawPoint( dpy, buffer, gc, x, y);
+   }
+   else {
+      /* Color index mode */
+      register int x, y;
+      XMesaSetForeground( dpy, gc, vert->index );
+      x =                         (GLint) vert->win[0];
+      y = YFLIP( xrb, (GLint) vert->win[1] );
+      XMesaDrawPoint( dpy, buffer, gc, x, y);
+   }
+}
+#endif
+
+
+/* Override the swrast point-selection function.  Try to use one of
+ * our internal point functions, otherwise fall back to the standard
+ * swrast functions.
+ */
+void xmesa_choose_point( GLcontext *ctx )
+{
+#if 0
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+   if (ctx->RenderMode == GL_RENDER
+       && ctx->Point.Size == 1.0F && !ctx->Point.SmoothFlag
+       && swrast->_RasterMask == 0
+       && !ctx->Texture._EnabledUnits
+       && xmesa->xm_buffer->buffer != XIMAGE) {
+      swrast->Point = draw_points_ANY_pixmap;
+   }
+   else {
+      _swrast_choose_point( ctx );
+   }
+#else
+   _swrast_choose_point( ctx );
+#endif
+}
+
+
+
+/**********************************************************************/
+/***                      Line rendering                            ***/
+/**********************************************************************/
+
+
+#if CHAN_BITS == 8
+
+
+#define GET_XRB(XRB)  struct xmesa_renderbuffer *XRB = \
+   xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped)
+
+
+/*
+ * Draw a flat-shaded, PF_TRUECOLOR line into an XImage.
+ */
+#define NAME flat_TRUECOLOR_line
+#define SETUP_CODE                                     \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);            \
+   GET_XRB(xrb);                                       \
+   const GLubyte *color = vert1->color;                        \
+   unsigned long pixel;                                        \
+   PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
+#define CLIP_HACK 1
+#define PLOT(X,Y) XMesaPutPixel(xrb->ximage, X, YFLIP(xrb, Y), pixel );
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8A8B8G8R line into an XImage.
+ */
+#define NAME flat_8A8B8G8R_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8A8B8G8R(color[0], color[1], color[2], color[3]);
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8A8R8G8B line into an XImage.
+ */
+#define NAME flat_8A8R8G8B_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8A8R8G8B(color[0], color[1], color[2], color[3]);
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8R8G8B line into an XImage.
+ */
+#define NAME flat_8R8G8B_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8R8G8B24 line into an XImage.
+ */
+#define NAME flat_8R8G8B24_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) {                    \
+      pixelPtr->r = color[RCOMP];      \
+      pixelPtr->g = color[GCOMP];      \
+      pixelPtr->b = color[BCOMP];      \
+}
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_5R6G5B line into an XImage.
+ */
+#define NAME flat_5R6G5B_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_DITHER_5R6G5B line into an XImage.
+ */
+#define NAME flat_DITHER_5R6G5B_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   const GLubyte *color = vert1->color;
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) PACK_TRUEDITHER( *pixelPtr, X, Y, color[0], color[1], color[2] );
+#include "swrast/s_linetemp.h"
+
+
+
+
+/*
+ * Draw a flat-shaded, PF_DITHER 8-bit line into an XImage.
+ */
+#define NAME flat_DITHER8_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLint r = color[0], g = color[1], b = color[2];             \
+   DITHER_SETUP;
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = DITHER(X,Y,r,g,b);
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_LOOKUP 8-bit line into an XImage.
+ */
+#define NAME flat_LOOKUP8_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLubyte pixel;                                              \
+   LOOKUP_SETUP;                                               \
+   pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_HPCR line into an XImage.
+ */
+#define NAME flat_HPCR_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   const GLubyte *color = vert1->color;                                \
+   GLint r = color[0], g = color[1], b = color[2];
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = (GLubyte) DITHER_HPCR(X,Y,r,g,b);
+#include "swrast/s_linetemp.h"
+
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_TRUECOLOR line into an XImage.
+ */
+#define NAME flat_TRUECOLOR_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   const GLubyte *color = vert1->color;                                \
+   unsigned long pixel;                                                \
+   PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define CLIP_HACK 1
+#define PLOT(X,Y)                                                      \
+       if (Z < *zPtr) {                                                \
+          *zPtr = Z;                                                   \
+           XMesaPutPixel(xrb->ximage, X, YFLIP(xrb, Y), pixel);                \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8A8B8G8R line into an XImage.
+ */
+#define NAME flat_8A8B8G8R_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8A8B8G8R(color[0], color[1], color[2], color[3]);
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          *pixelPtr = pixel;   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8A8R8G8B line into an XImage.
+ */
+#define NAME flat_8A8R8G8B_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8A8R8G8B(color[0], color[1], color[2], color[3]);
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          *pixelPtr = pixel;   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8R8G8B line into an XImage.
+ */
+#define NAME flat_8R8G8B_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          *pixelPtr = pixel;   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8R8G8B24 line into an XImage.
+ */
+#define NAME flat_8R8G8B24_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)                      \
+       if (Z < *zPtr) {                \
+          *zPtr = Z;                   \
+           pixelPtr->r = color[RCOMP]; \
+           pixelPtr->g = color[GCOMP]; \
+           pixelPtr->b = color[BCOMP]; \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_5R6G5B line into an XImage.
+ */
+#define NAME flat_5R6G5B_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          *pixelPtr = pixel;   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_DITHER_5R6G5B line into an XImage.
+ */
+#define NAME flat_DITHER_5R6G5B_z_line
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                               \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);            \
+   const GLubyte *color = vert1->color;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          PACK_TRUEDITHER(*pixelPtr, X, Y, color[0], color[1], color[2]); \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_DITHER 8-bit line into an XImage.
+ */
+#define NAME flat_DITHER8_z_line
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                        \
+   GLint r = color[0], g = color[1], b = color[2];     \
+   DITHER_SETUP;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)                                              \
+       if (Z < *zPtr) {                                        \
+          *zPtr = Z;                                           \
+          *pixelPtr = (GLubyte) DITHER( X, Y, r, g, b);        \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_LOOKUP 8-bit line into an XImage.
+ */
+#define NAME flat_LOOKUP8_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = vert1->color;                                \
+   GLubyte pixel;                                              \
+   LOOKUP_SETUP;                                               \
+   pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)              \
+       if (Z < *zPtr) {        \
+          *zPtr = Z;           \
+          *pixelPtr = pixel;   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_HPCR line into an XImage.
+ */
+#define NAME flat_HPCR_z_line
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   const GLubyte *color = vert1->color;                                \
+   GLint r = color[0], g = color[1], b = color[2];
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y)                                              \
+       if (Z < *zPtr) {                                        \
+          *zPtr = Z;                                           \
+          *pixelPtr = (GLubyte) DITHER_HPCR( X, Y, r, g, b);   \
+       }
+#include "swrast/s_linetemp.h"
+
+
+
+
+#ifndef XFree86Server
+/**
+ * Draw fast, XOR line with XDrawLine in front color buffer.
+ * WARNING: this isn't fully OpenGL conformant because different pixels
+ * will be hit versus using the other line functions.
+ * Don't use the code in X server GLcore module since we need a wrapper
+ * for the XSetLineAttributes() function call.
+ */
+static void
+xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaGC gc = xmesa->xm_buffer->gc;
+   GET_XRB(xrb);
+   unsigned long pixel = xmesa_color_to_pixel(ctx,
+                                              vert1->color[0], vert1->color[1],
+                                              vert1->color[2], vert1->color[3],
+                                              xmesa->pixelformat);
+   int x0 =            (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0];
+   int y0 = YFLIP(xrb, (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1]);
+   int x1 =            (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
+   int y1 = YFLIP(xrb, (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1]);
+   XMesaSetForeground(dpy, gc, pixel);
+   XMesaSetFunction(dpy, gc, GXxor);
+   XSetLineAttributes(dpy, gc, (int) ctx->Line.Width,
+                      LineSolid, CapButt, JoinMiter);
+   XDrawLine(dpy, xrb->pixmap, gc, x0, y0, x1, y1);
+   XMesaSetFunction(dpy, gc, GXcopy);  /* this gc is used elsewhere */
+}
+#endif /* XFree86Server */
+
+
+#endif /* CHAN_BITS == 8 */
+
+
+/**
+ * Return pointer to line drawing function, or NULL if we should use a
+ * swrast fallback.
+ */
+static swrast_line_func
+get_line_func(GLcontext *ctx)
+{
+#if CHAN_BITS == 8
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+   const int depth = GET_VISUAL_DEPTH(xmesa->xm_visual);
+   const struct xmesa_renderbuffer *xrb;
+
+   if ((ctx->DrawBuffer->_ColorDrawBufferMask[0]
+        & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0)
+      return (swrast_line_func) NULL;
+   if (ctx->RenderMode != GL_RENDER)      return (swrast_line_func) NULL;
+   if (ctx->Line.SmoothFlag)              return (swrast_line_func) NULL;
+   if (ctx->Texture._EnabledUnits)        return (swrast_line_func) NULL;
+   if (ctx->Light.ShadeModel != GL_FLAT)  return (swrast_line_func) NULL;
+   if (ctx->Line.StippleFlag)             return (swrast_line_func) NULL;
+   if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL;
+   if (xmbuf->swAlpha)                    return (swrast_line_func) NULL;
+
+   xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
+
+   if (xrb->ximage
+       && swrast->_RasterMask==DEPTH_BIT
+       && ctx->Depth.Func==GL_LESS
+       && ctx->Depth.Mask==GL_TRUE
+       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+       && ctx->Line.Width==1.0F) {
+      switch (xmesa->pixelformat) {
+         case PF_Truecolor:
+            return flat_TRUECOLOR_z_line;
+         case PF_8A8B8G8R:
+            return flat_8A8B8G8R_z_line;
+         case PF_8A8R8G8B:
+            return flat_8A8R8G8B_z_line;
+         case PF_8R8G8B:
+            return flat_8R8G8B_z_line;
+         case PF_8R8G8B24:
+            return flat_8R8G8B24_z_line;
+         case PF_5R6G5B:
+            return flat_5R6G5B_z_line;
+         case PF_Dither_5R6G5B:
+            return flat_DITHER_5R6G5B_z_line;
+         case PF_Dither:
+            return (depth==8) ? flat_DITHER8_z_line : (swrast_line_func) NULL;
+         case PF_Lookup:
+            return (depth==8) ? flat_LOOKUP8_z_line : (swrast_line_func) NULL;
+         case PF_HPCR:
+            return flat_HPCR_z_line;
+         default:
+            return (swrast_line_func)NULL;
+      }
+   }
+   if (xrb->ximage
+       && swrast->_RasterMask==0
+       && ctx->Line.Width==1.0F) {
+      switch (xmesa->pixelformat) {
+         case PF_Truecolor:
+            return flat_TRUECOLOR_line;
+         case PF_8A8B8G8R:
+            return flat_8A8B8G8R_line;
+         case PF_8A8R8G8B:
+            return flat_8A8R8G8B_line;
+         case PF_8R8G8B:
+            return flat_8R8G8B_line;
+         case PF_8R8G8B24:
+            return flat_8R8G8B24_line;
+         case PF_5R6G5B:
+            return flat_5R6G5B_line;
+         case PF_Dither_5R6G5B:
+            return flat_DITHER_5R6G5B_line;
+         case PF_Dither:
+            return (depth==8) ? flat_DITHER8_line : (swrast_line_func) NULL;
+         case PF_Lookup:
+            return (depth==8) ? flat_LOOKUP8_line : (swrast_line_func) NULL;
+         case PF_HPCR:
+            return flat_HPCR_line;
+        default:
+           return (swrast_line_func)NULL;
+      }
+   }
+
+#ifndef XFree86Server
+   if (ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1
+       && ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT
+       && swrast->_RasterMask == LOGIC_OP_BIT
+       && ctx->Color.LogicOp == GL_XOR
+       && !ctx->Line.StippleFlag
+       && !ctx->Line.SmoothFlag) {
+      return xor_line;
+   }
+#endif /* XFree86Server */
+
+#endif /* CHAN_BITS == 8 */
+   return (swrast_line_func) NULL;
+}
+
+
+/**
+ * Override for the swrast line-selection function.  Try to use one
+ * of our internal line functions, otherwise fall back to the
+ * standard swrast functions.
+ */
+void
+xmesa_choose_line(GLcontext *ctx)
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+   if (!(swrast->Line = get_line_func( ctx )))
+      _swrast_choose_line( ctx );
+}
diff --git a/src/mesa/pipe/xlib/xm_span.c b/src/mesa/pipe/xlib/xm_span.c
new file mode 100644 (file)
index 0000000..ce54a18
--- /dev/null
@@ -0,0 +1,4815 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.3
+ *
+ * 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.
+ */
+
+#include "glxheader.h"
+#include "colormac.h"
+#include "context.h"
+#include "depth.h"
+#include "drawpix.h"
+#include "extensions.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+#include "xmesaP.h"
+
+#include "swrast/swrast.h"
+
+
+/*
+ * The following functions are used to trap XGetImage() calls which
+ * generate BadMatch errors if the drawable isn't mapped.
+ */
+
+#ifndef XFree86Server
+static int caught_xgetimage_error = 0;
+static int (*old_xerror_handler)( XMesaDisplay *dpy, XErrorEvent *ev );
+static unsigned long xgetimage_serial;
+
+/*
+ * This is the error handler which will be called if XGetImage fails.
+ */
+static int xgetimage_error_handler( XMesaDisplay *dpy, XErrorEvent *ev )
+{
+   if (ev->serial==xgetimage_serial && ev->error_code==BadMatch) {
+      /* caught the expected error */
+      caught_xgetimage_error = 0;
+   }
+   else {
+      /* call the original X error handler, if any.  otherwise ignore */
+      if (old_xerror_handler) {
+         (*old_xerror_handler)( dpy, ev );
+      }
+   }
+   return 0;
+}
+
+
+/*
+ * Call this right before XGetImage to setup error trap.
+ */
+static void catch_xgetimage_errors( XMesaDisplay *dpy )
+{
+   xgetimage_serial = NextRequest( dpy );
+   old_xerror_handler = XSetErrorHandler( xgetimage_error_handler );
+   caught_xgetimage_error = 0;
+}
+
+
+/*
+ * Call this right after XGetImage to check if an error occured.
+ */
+static int check_xgetimage_errors( void )
+{
+   /* restore old handler */
+   (void) XSetErrorHandler( old_xerror_handler );
+   /* return 0=no error, 1=error caught */
+   return caught_xgetimage_error;
+}
+#endif
+
+
+/*
+ * Read a pixel from an X drawable.
+ */
+static unsigned long read_pixel( XMesaDisplay *dpy,
+                                 XMesaDrawable d, int x, int y )
+{
+   unsigned long p;
+#ifndef XFree86Server
+   XMesaImage *pixel = NULL;
+   int error;
+
+   catch_xgetimage_errors( dpy );
+   pixel = XGetImage( dpy, d, x, y, 1, 1, AllPlanes, ZPixmap );
+   error = check_xgetimage_errors();
+   if (pixel && !error) {
+      p = XMesaGetPixel( pixel, 0, 0 );
+   }
+   else {
+      p = 0;
+   }
+   if (pixel) {
+      XMesaDestroyImage( pixel );
+   }
+#else
+   (*dpy->GetImage)(d, x, y, 1, 1, ZPixmap, ~0L, (pointer)&p);
+#endif
+   return p;
+}
+
+
+
+/*
+ * The Mesa library needs to be able to draw pixels in a number of ways:
+ *   1. RGB vs Color Index
+ *   2. as horizontal spans (polygons, images) vs random locations (points,
+ *      lines)
+ *   3. different color per-pixel or same color for all pixels
+ *
+ * Furthermore, the X driver needs to support rendering to 3 possible
+ * "buffers", usually one, but sometimes two at a time:
+ *   1. The front buffer as an X window
+ *   2. The back buffer as a Pixmap
+ *   3. The back buffer as an XImage
+ *
+ * Finally, if the back buffer is an XImage, we can avoid using XPutPixel and
+ * optimize common cases such as 24-bit and 8-bit modes.
+ *
+ * By multiplication, there's at least 48 possible combinations of the above.
+ *
+ * Below are implementations of the most commonly used combinations.  They are
+ * accessed through function pointers which get initialized here and are used
+ * directly from the Mesa library.  The 8 function pointers directly correspond
+ * to the first 3 cases listed above.
+ *
+ *
+ * The function naming convention is:
+ *
+ *   [put|get]_[mono]_[row|values]_[format]_[pixmap|ximage]
+ *
+ * New functions optimized for specific cases can be added without too much
+ * trouble.  An example might be the 24-bit TrueColor mode 8A8R8G8B which is
+ * found on IBM RS/6000 X servers.
+ */
+
+
+
+
+/**********************************************************************/
+/*** Write COLOR SPAN functions                                     ***/
+/**********************************************************************/
+
+
+#define PUT_ROW_ARGS \
+       GLcontext *ctx,                                 \
+       struct gl_renderbuffer *rb,                     \
+       GLuint n, GLint x, GLint y,                     \
+       const void *values, const GLubyte mask[]
+
+#define RGB_SPAN_ARGS \
+       GLcontext *ctx,                                 \
+       struct gl_renderbuffer *rb,                     \
+       GLuint n, GLint x, GLint y,                     \
+       const void *values, const GLubyte mask[]
+
+
+#define GET_XRB(XRB) \
+   struct xmesa_renderbuffer *XRB = xmesa_renderbuffer(rb)
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void put_row_TRUECOLOR_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = XMESA_BUFFER(ctx->DrawBuffer)->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         XMesaPutPixel( rowimg, i, 0, p );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void put_row_rgb_TRUECOLOR_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         XMesaPutPixel( rowimg, i, 0, p );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void put_row_TRUEDITHER_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+         XMesaPutPixel( rowimg, i, 0, p );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_TRUEDITHER_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+         XMesaPutPixel( rowimg, i, 0, p );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R pixels to a pixmap.
+ */
+static void put_row_8A8B8G8R_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                         PACK_8A8B8G8R(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_8A8B8G8R_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                   PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_8A8R8G8B pixels to a pixmap.
+ */
+static void put_row_8A8R8G8B_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                         PACK_8A8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_8A8R8G8B pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_8A8R8G8B_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                   PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_8R8G8B pixels to a pixmap.
+ */
+static void put_row_8R8G8B_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24 pixels to a pixmap.
+ */
+static void put_row_8R8G8B24_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      register GLuint i;
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+               PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      register GLuint pixel;
+      static const GLuint shift[4] = {0, 8, 16, 24};
+      register GLuint i = 0;
+      int w = n;
+      while (w > 3) {
+         pixel  = rgba[i][BCOMP] /* << shift[0]*/;
+         pixel |= rgba[i][GCOMP]    << shift[1];
+         pixel |= rgba[i++][RCOMP]  << shift[2];
+         pixel |= rgba[i][BCOMP]    << shift[3];
+         *ptr4++ = pixel;
+
+         pixel  = rgba[i][GCOMP] /* << shift[0]*/;
+         pixel |= rgba[i++][RCOMP]  << shift[1];
+         pixel |= rgba[i][BCOMP]    << shift[2];
+         pixel |= rgba[i][GCOMP]    << shift[3];
+         *ptr4++ = pixel;
+
+         pixel  = rgba[i++][RCOMP]/* << shift[0]*/;
+         pixel |= rgba[i][BCOMP]     << shift[1];
+         pixel |= rgba[i][GCOMP]     << shift[2];
+         pixel |= rgba[i++][RCOMP]   << shift[3];
+         *ptr4++ = pixel;
+
+         w -= 4;
+      }
+      switch (w) {
+         case 3:
+            pixel = 0;
+            pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+            pixel |= rgba[i][GCOMP]   << shift[1];
+            pixel |= rgba[i++][RCOMP] << shift[2];
+            pixel |= rgba[i][BCOMP]   << shift[3];
+            *ptr4++ = pixel;
+            pixel = 0;
+            pixel |= rgba[i][GCOMP] /*<< shift[0]*/;
+            pixel |= rgba[i++][RCOMP] << shift[1];
+            pixel |= rgba[i][BCOMP]   << shift[2];
+            pixel |= rgba[i][GCOMP]   << shift[3];
+            *ptr4++ = pixel;
+            pixel = 0xffffff00 & *ptr4;
+            pixel |= rgba[i][RCOMP] /*<< shift[0]*/;
+            *ptr4 = pixel;
+            break;
+         case 2:
+            pixel = 0;
+            pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+            pixel |= rgba[i][GCOMP]   << shift[1];
+            pixel |= rgba[i++][RCOMP] << shift[2];
+            pixel |= rgba[i][BCOMP]   << shift[3];
+            *ptr4++ = pixel;
+            pixel = 0xffff0000 & *ptr4;
+            pixel |= rgba[i][GCOMP] /*<< shift[0]*/;
+            pixel |= rgba[i][RCOMP]   << shift[1];
+            *ptr4 = pixel;
+            break;
+         case 1:
+            pixel = 0xff000000 & *ptr4;
+            pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+            pixel |= rgba[i][GCOMP] << shift[1];
+            pixel |= rgba[i][RCOMP] << shift[2];
+            *ptr4 = pixel;
+            break;
+         case 0:
+            break;
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      for (i=0;i<n;i++) {
+         *ptr4++ = PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_8R8G8B24 pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_8R8G8B24_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      register GLuint i;
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                  PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLuint *ptr4 = (GLuint *) rowimg->data;
+      register GLuint pixel;
+      static const GLuint shift[4] = {0, 8, 16, 24};
+      unsigned w = n;
+      register GLuint i = 0;
+      while (w > 3) {
+         pixel = 0;
+         pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+         pixel |= rgb[i][GCOMP] << shift[1];
+         pixel |= rgb[i++][RCOMP] << shift[2];
+         pixel |= rgb[i][BCOMP] <<shift[3];
+         *ptr4++ = pixel;
+
+         pixel = 0;
+         pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+         pixel |= rgb[i++][RCOMP] << shift[1];
+         pixel |= rgb[i][BCOMP] << shift[2];
+         pixel |= rgb[i][GCOMP] << shift[3];
+         *ptr4++ = pixel;
+
+         pixel = 0;
+         pixel |= rgb[i++][RCOMP]/* << shift[0]*/;
+         pixel |= rgb[i][BCOMP] << shift[1];
+         pixel |= rgb[i][GCOMP] << shift[2];
+         pixel |= rgb[i++][RCOMP] << shift[3];
+         *ptr4++ = pixel;
+         w -= 4;
+      }
+      switch (w) {
+         case 3:
+            pixel = 0;
+            pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+            pixel |= rgb[i][GCOMP] << shift[1];
+            pixel |= rgb[i++][RCOMP] << shift[2];
+            pixel |= rgb[i][BCOMP] << shift[3];
+            *ptr4++ = pixel;
+            pixel = 0;
+            pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+            pixel |= rgb[i++][RCOMP] << shift[1];
+            pixel |= rgb[i][BCOMP] << shift[2];
+            pixel |= rgb[i][GCOMP] << shift[3];
+            *ptr4++ = pixel;
+            pixel = *ptr4;
+            pixel &= 0xffffff00;
+            pixel |= rgb[i++][RCOMP]/* << shift[0]*/;
+            *ptr4++ = pixel;
+            break;
+         case 2:
+            pixel = 0;
+            pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+            pixel |= rgb[i][GCOMP] << shift[1];
+            pixel |= rgb[i++][RCOMP] << shift[2];
+            pixel |= rgb[i][BCOMP]  << shift[3];
+            *ptr4++ = pixel;
+            pixel = *ptr4;
+            pixel &= 0xffff0000;
+            pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+            pixel |= rgb[i++][RCOMP] << shift[1];
+            *ptr4++ = pixel;
+            break;
+         case 1:
+            pixel = *ptr4;
+            pixel &= 0xff000000;
+            pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+            pixel |= rgb[i][GCOMP] << shift[1];
+            pixel |= rgb[i++][RCOMP] << shift[2];
+            *ptr4++ = pixel;
+            break;
+         case 0:
+            break;
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B pixels to a pixmap.
+ */
+static void put_row_5R6G5B_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLushort *ptr2 = (GLushort *) rowimg->data;
+      for (i=0;i<n;i++) {
+         ptr2[i] = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B pixels to a pixmap.
+ */
+static void put_row_DITHER_5R6G5B_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLushort *ptr2 = (GLushort *) rowimg->data;
+      for (i=0;i<n;i++) {
+         PACK_TRUEDITHER( ptr2[i], x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_5R6G5B_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLushort *ptr2 = (GLushort *) rowimg->data;
+      for (i=0;i<n;i++) {
+         ptr2[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_DITHER_5R6G5B_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+            XMesaSetForeground( dpy, gc, p );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLushort *ptr2 = (GLushort *) rowimg->data;
+      for (i=0;i<n;i++) {
+         PACK_TRUEDITHER( ptr2[i], x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap.
+ */
+static void put_row_DITHER_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   XDITHER_SETUP(y);
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, XDITHER(x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, XDITHER(x+i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_DITHER_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   XDITHER_SETUP(y);
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, XDITHER(x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, XDITHER(x+i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap.
+ */
+static void put_row_1BIT_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                            DITHER_1BIT( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0,
+                    DITHER_1BIT( x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_1BIT_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+              DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0,
+          DITHER_1BIT(x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to a pixmap.
+ */
+static void put_row_HPCR_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+                            DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLubyte *ptr = (GLubyte *) XMESA_BUFFER(ctx->DrawBuffer)->rowimage->data;
+      for (i=0;i<n;i++) {
+         ptr[i] = DITHER_HPCR( (x+i), y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_HPCR_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc,
+              DITHER_HPCR(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      register GLubyte *ptr = (GLubyte *) XMESA_BUFFER(ctx->DrawBuffer)->rowimage->data;
+      for (i=0;i<n;i++) {
+         ptr[i] = DITHER_HPCR( (x+i), y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_LOOKUP pixels to a pixmap.
+ */
+static void put_row_LOOKUP_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   LOOKUP_SETUP;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, LOOKUP(rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_LOOKUP_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   LOOKUP_SETUP;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, LOOKUP(rgb[i][RCOMP],rgb[i][GCOMP],rgb[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to a pixmap.
+ */
+static void put_row_GRAYSCALE_pixmap( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, GRAY_RGB(rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to a pixmap (no alpha).
+ */
+static void put_row_rgb_GRAYSCALE_pixmap( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+      for (i=0;i<n;i++) {
+         XMesaPutPixel( rowimg, i, 0, GRAY_RGB(rgb[i][RCOMP],rgb[i][GCOMP],rgb[i][BCOMP]) );
+      }
+      XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+   }
+}
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to an XImage.
+ */
+static void put_row_TRUECOLOR_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+            XMesaPutPixel( img, x, y, p );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         XMesaPutPixel( img, x, y, p );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_TRUECOLOR_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+            XMesaPutPixel( img, x, y, p );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         XMesaPutPixel( img, x, y, p );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to an XImage.
+ */
+static void put_row_TRUEDITHER_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+            XMesaPutPixel( img, x, y, p );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+         XMesaPutPixel( img, x, y, p );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            unsigned long p;
+            PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+            XMesaPutPixel( img, x, y, p );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+         XMesaPutPixel( img, x, y, p );
+      }
+   }
+}
+
+
+
+static void *get_pointer_4_ximage( GLcontext *ctx, 
+                                  struct gl_renderbuffer *rb, 
+                                  GLint x, GLint y )
+{
+   GET_XRB(xrb);
+   return PIXEL_ADDR4(xrb, x, y);
+}
+
+
+
+/*
+ * Write a span of PF_8A8B8G8R-format pixels to an ximage.
+ */
+static void put_row_8A8B8G8R_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   (void) ctx;
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8A8B8G8R( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8A8B8G8R( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+      }
+   }
+}
+
+/*
+ * Write a span of PF_8A8R8G8B-format pixels to an ximage.
+ */
+static void put_row_8A8R8G8B_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8A8R8G8B-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8A8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8A8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B-format pixels to an ximage.
+ */
+static void put_row_8R8G8B_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24-format pixels to an ximage.
+ */
+static void put_row_8R8G8B24_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y );
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            GLuint *ptr4 = (GLuint *) ptr;
+            register GLuint pixel = *ptr4;
+            switch (3 & (int)(ptr - (GLubyte*)ptr4)) {
+               case 0:
+                  pixel &= 0xff000000;
+                  pixel |= rgba[i][BCOMP];
+                  pixel |= rgba[i][GCOMP] << 8;
+                  pixel |= rgba[i][RCOMP] << 16;
+                  *ptr4 = pixel;
+                  break;
+               case 3:
+                  pixel &= 0x00ffffff;
+                  pixel |= rgba[i][BCOMP] << 24;
+                  *ptr4++ = pixel;
+                  pixel = *ptr4 & 0xffff0000;
+                  pixel |= rgba[i][GCOMP];
+                  pixel |= rgba[i][RCOMP] << 8;
+                  *ptr4 = pixel;
+                  break;
+               case 2:
+                  pixel &= 0x0000ffff;
+                  pixel |= rgba[i][BCOMP] << 16;
+                  pixel |= rgba[i][GCOMP] << 24;
+                  *ptr4++ = pixel;
+                  pixel = *ptr4 & 0xffffff00;
+                  pixel |= rgba[i][RCOMP];
+                  *ptr4 = pixel;
+                  break;
+               case 1:
+                  pixel &= 0x000000ff;
+                  pixel |= rgba[i][BCOMP] << 8;
+                  pixel |= rgba[i][GCOMP] << 16;
+                  pixel |= rgba[i][RCOMP] << 24;
+                  *ptr4 = pixel;
+                  break;
+            }
+         }
+        ptr += 3;
+      }
+   }
+   else {
+      /* write all pixels */
+      int w = n;
+      GLuint *ptr4 = (GLuint *) ptr;
+      register GLuint pixel = *ptr4;
+      int index = (int)(ptr - (GLubyte *)ptr4);
+      register GLuint i = 0;
+      switch (index) {
+         case 0:
+            break;
+         case 1:
+            pixel &= 0x00ffffff;
+            pixel |= rgba[i][BCOMP] << 24;
+            *ptr4++ = pixel;
+            pixel = *ptr4 & 0xffff0000;
+            pixel |= rgba[i][GCOMP];
+            pixel |= rgba[i++][RCOMP] << 8;
+            *ptr4 = pixel;
+            if (0 == --w)
+               break;
+         case 2:
+            pixel &= 0x0000ffff;
+            pixel |= rgba[i][BCOMP] << 16;
+            pixel |= rgba[i][GCOMP] << 24;
+            *ptr4++ = pixel;
+            pixel = *ptr4 & 0xffffff00;
+            pixel |= rgba[i++][RCOMP];
+            *ptr4 = pixel;
+            if (0 == --w)
+               break;
+         case 3:
+            pixel &= 0x000000ff;
+            pixel |= rgba[i][BCOMP] << 8;
+            pixel |= rgba[i][GCOMP] << 16;
+            pixel |= rgba[i++][RCOMP] << 24;
+            *ptr4++ = pixel;
+            if (0 == --w)
+               break;
+            break;
+      }
+      while (w > 3) {
+         pixel = rgba[i][BCOMP];
+         pixel |= rgba[i][GCOMP] << 8;
+         pixel |= rgba[i++][RCOMP] << 16;
+         pixel |= rgba[i][BCOMP] << 24;
+         *ptr4++ = pixel;
+         pixel = rgba[i][GCOMP];
+         pixel |= rgba[i++][RCOMP] << 8;
+         pixel |= rgba[i][BCOMP] << 16;
+         pixel |= rgba[i][GCOMP] << 24;
+         *ptr4++ = pixel;
+         pixel = rgba[i++][RCOMP];
+         pixel |= rgba[i][BCOMP] << 8;
+         pixel |= rgba[i][GCOMP] << 16;
+         pixel |= rgba[i++][RCOMP] << 24;
+         *ptr4++ = pixel;
+         w -= 4;
+      }
+      switch (w) {
+         case 0:
+            break;
+         case 1:
+            pixel = *ptr4 & 0xff000000;
+            pixel |= rgba[i][BCOMP];
+            pixel |= rgba[i][GCOMP] << 8;
+            pixel |= rgba[i][RCOMP] << 16;
+            *ptr4 = pixel;
+            break;
+         case 2:
+            pixel = rgba[i][BCOMP];
+            pixel |= rgba[i][GCOMP] << 8;
+            pixel |= rgba[i++][RCOMP] << 16;
+            pixel |= rgba[i][BCOMP] << 24;
+            *ptr4++ = pixel;
+            pixel = *ptr4 & 0xffff0000;
+            pixel |= rgba[i][GCOMP];
+            pixel |= rgba[i][RCOMP] << 8;
+            *ptr4 = pixel;
+            break;
+         case 3:
+            pixel = rgba[i][BCOMP];
+            pixel |= rgba[i][GCOMP] << 8;
+            pixel |= rgba[i++][RCOMP] << 16;
+            pixel |= rgba[i][BCOMP] << 24;
+            *ptr4++ = pixel;
+            pixel = rgba[i][GCOMP];
+            pixel |= rgba[i++][RCOMP] << 8;
+            pixel |= rgba[i][BCOMP] << 16;
+            pixel |= rgba[i][GCOMP] << 24;
+            *ptr4++ = pixel;
+            pixel = *ptr4 & 0xffffff00;
+            pixel |= rgba[i][RCOMP];
+            *ptr4 = pixel;
+            break;
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            *ptr++ = rgb[i][BCOMP];
+            *ptr++ = rgb[i][GCOMP];
+            *ptr++ = rgb[i][RCOMP];
+         }
+         else {
+            ptr += 3;
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         *ptr++ = rgb[i][BCOMP];
+         *ptr++ = rgb[i][GCOMP];
+         *ptr++ = rgb[i][RCOMP];
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B-format pixels to an ximage.
+ */
+static void put_row_5R6G5B_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+      GLuint *ptr32 = (GLuint *) ptr;
+      GLuint extraPixel = (n & 1);
+      n -= extraPixel;
+      for (i = 0; i < n; i += 2) {
+         GLuint p0, p1;
+         p0 = PACK_5R6G5B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+         p1 = PACK_5R6G5B(rgba[i+1][RCOMP], rgba[i+1][GCOMP], rgba[i+1][BCOMP]);
+         *ptr32++ = (p1 << 16) | p0;
+      }
+      if (extraPixel) {
+         ptr[n] = PACK_5R6G5B(rgba[n][RCOMP], rgba[n][GCOMP], rgba[n][BCOMP]);
+      }
+#else
+      for (i = 0; i < n; i++) {
+         ptr[i] = PACK_5R6G5B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+      }
+#endif
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B-format pixels to an ximage.
+ */
+static void put_row_DITHER_5R6G5B_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
+   const GLint y2 = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            PACK_TRUEDITHER( ptr[i], x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+      GLuint *ptr32 = (GLuint *) ptr;
+      GLuint extraPixel = (n & 1);
+      n -= extraPixel;
+      for (i = 0; i < n; i += 2, x += 2) {
+         GLuint p0, p1;
+         PACK_TRUEDITHER( p0, x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         PACK_TRUEDITHER( p1, x+1, y2, rgba[i+1][RCOMP], rgba[i+1][GCOMP], rgba[i+1][BCOMP] );
+         *ptr32++ = (p1 << 16) | p0;
+      }
+      if (extraPixel) {
+         PACK_TRUEDITHER( ptr[n], x+n, y2, rgba[n][RCOMP], rgba[n][GCOMP], rgba[n][BCOMP]);
+      }
+#else
+      for (i = 0; i < n; i++, x++) {
+         PACK_TRUEDITHER( ptr[i], x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+      }
+#endif
+   }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_5R6G5B_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+      GLuint *ptr32 = (GLuint *) ptr;
+      GLuint extraPixel = (n & 1);
+      n -= extraPixel;
+      for (i = 0; i < n; i += 2) {
+         GLuint p0, p1;
+         p0 = PACK_5R6G5B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+         p1 = PACK_5R6G5B(rgb[i+1][RCOMP], rgb[i+1][GCOMP], rgb[i+1][BCOMP]);
+         *ptr32++ = (p1 << 16) | p0;
+      }
+      if (extraPixel) {
+         ptr[n] = PACK_5R6G5B(rgb[n][RCOMP], rgb[n][GCOMP], rgb[n][BCOMP]);
+      }
+#else
+      for (i=0;i<n;i++) {
+         ptr[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+#endif
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B-format pixels to an ximage (no alpha).
+ */
+static void put_row_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   register GLushort *ptr = PIXEL_ADDR2(xrb, x, y );
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            PACK_TRUEDITHER( ptr[i], x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+      GLuint *ptr32 = (GLuint *) ptr;
+      GLuint extraPixel = (n & 1);
+      n -= extraPixel;
+      for (i = 0; i < n; i += 2, x += 2) {
+         GLuint p0, p1;
+         PACK_TRUEDITHER( p0, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         PACK_TRUEDITHER( p1, x+1, y, rgb[i+1][RCOMP], rgb[i+1][GCOMP], rgb[i+1][BCOMP] );
+         *ptr32++ = (p1 << 16) | p0;
+      }
+      if (extraPixel) {
+         PACK_TRUEDITHER( ptr[n], x+n, y, rgb[n][RCOMP], rgb[n][GCOMP], rgb[n][BCOMP]);
+      }
+#else
+      for (i=0;i<n;i++,x++) {
+         PACK_TRUEDITHER( ptr[i], x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+#endif
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to an XImage.
+ */
+static void put_row_DITHER_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   int yy = YFLIP(xrb, y);
+   XDITHER_SETUP(yy);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, yy, XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, yy, XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_DITHER_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   int yy = YFLIP(xrb, y);
+   XDITHER_SETUP(yy);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, yy, XDITHER( x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, yy, XDITHER( x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+      }
+   }
+}
+
+
+
+/*
+ * Write a span of 8-bit PF_DITHER pixels to an XImage.
+ */
+static void put_row_DITHER8_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   XDITHER_SETUP(y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++,x++) {
+         ptr[i] = (GLubyte) XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+static void put_row_rgb_DITHER8_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   XDITHER_SETUP(y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) XDITHER( x, rgb[i][0], rgb[i][1], rgb[i][2] );
+         }
+      }
+   }
+   else {
+      const GLubyte *data = (GLubyte *) rgb;
+      for (i=0;i<n;i++,x++) {
+         /*ptr[i] = XDITHER( x, rgb[i][0], rgb[i][1], rgb[i][2] );*/
+         ptr[i] = (GLubyte) XDITHER( x, data[i+i+i], data[i+i+i+1], data[i+i+i+2] );
+      }
+   }
+}
+
+
+
+/*
+ * Write a span of PF_1BIT pixels to an XImage.
+ */
+static void put_row_1BIT_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel(img, x, y, DITHER_1BIT(x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, DITHER_1BIT(x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_1BIT_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel(img, x, y, DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to an XImage.
+ */
+static void put_row_HPCR_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         ptr[i] = DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_HPCR_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = DITHER_HPCR( x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         ptr[i] = DITHER_HPCR( x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to an XImage.
+ */
+static void put_row_LOOKUP_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   LOOKUP_SETUP;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, y, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_LOOKUP_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   LOOKUP_SETUP;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, y, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void put_row_LOOKUP8_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   LOOKUP_SETUP;
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         ptr[i] = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+static void put_row_rgb_LOOKUP8_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   LOOKUP_SETUP;
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) LOOKUP( rgb[i][0], rgb[i][1], rgb[i][2] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      const GLubyte *data = (GLubyte *) rgb;
+      for (i=0;i<n;i++,x++) {
+         /*ptr[i] = LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );*/
+         ptr[i] = (GLubyte) LOOKUP( data[i+i+i], data[i+i+i+1], data[i+i+i+2] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to an XImage.
+ */
+static void put_row_GRAYSCALE_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, y, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, y, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void put_row_GRAYSCALE8_ximage( PUT_ROW_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write a span of 8-bit PF_GRAYSCALE pixels to an XImage (no alpha).
+ */
+static void put_row_rgb_GRAYSCALE8_ximage( RGB_SPAN_ARGS )
+{
+   const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   if (mask) {
+      for (i=0;i<n;i++) {
+         if (mask[i]) {
+            ptr[i] = (GLubyte) GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+         }
+      }
+   }
+   else {
+      /* draw all pixels */
+      for (i=0;i<n;i++) {
+         ptr[i] = (GLubyte) GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+      }
+   }
+}
+
+
+
+
+/**********************************************************************/
+/*** Write COLOR PIXEL functions                                    ***/
+/**********************************************************************/
+
+
+#define PUT_VALUES_ARGS \
+       GLcontext *ctx, struct gl_renderbuffer *rb,     \
+       GLuint n, const GLint x[], const GLint y[],     \
+       const void *values, const GLubyte mask[]
+
+
+/*
+ * Write an array of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void put_values_TRUECOLOR_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+        XMesaSetForeground( dpy, gc, p );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void put_values_TRUEDITHER_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+         XMesaSetForeground( dpy, gc, p );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_8A8B8G8R pixels to a pixmap.
+ */
+static void put_values_8A8B8G8R_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc,
+                         PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ));
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+/*
+ * Write an array of PF_8A8R8G8B pixels to a pixmap.
+ */
+static void put_values_8A8R8G8B_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc,
+                         PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ));
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+/*
+ * Write an array of PF_8R8G8B pixels to a pixmap.
+ */
+static void put_values_8R8G8B_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B24 pixels to a pixmap.
+ */
+static void put_values_8R8G8B24_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_5R6G5B pixels to a pixmap.
+ */
+static void put_values_5R6G5B_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_DITHER_5R6G5B pixels to a pixmap.
+ */
+static void put_values_DITHER_5R6G5B_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+        XMesaSetForeground( dpy, gc, p );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to a pixmap.
+ */
+static void put_values_DITHER_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc,
+                         DITHER(x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to a pixmap.
+ */
+static void put_values_1BIT_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   SETUP_1BIT;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc,
+                         DITHER_1BIT( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_HPCR pixels to a pixmap.
+ */
+static void put_values_HPCR_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         XMesaSetForeground( dpy, gc,
+                         DITHER_HPCR( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+         XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_LOOKUP pixels to a pixmap.
+ */
+static void put_values_LOOKUP_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   LOOKUP_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         XMesaSetForeground( dpy, gc, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_GRAYSCALE pixels to a pixmap.
+ */
+static void put_values_GRAYSCALE_pixmap( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         XMesaSetForeground( dpy, gc, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_TRUECOLOR pixels to an ximage.
+ */
+static void put_values_TRUECOLOR_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), p );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to an XImage.
+ */
+static void put_values_TRUEDITHER_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), p );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_8A8B8G8R pixels to an ximage.
+ */
+static void put_values_8A8B8G8R_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i] );
+         *ptr = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+   }
+}
+
+/*
+ * Write an array of PF_8A8R8G8B pixels to an ximage.
+ */
+static void put_values_8A8R8G8B_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i]);
+         *ptr = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B pixels to an ximage.
+ */
+static void put_values_8R8G8B_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i]);
+         *ptr = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B24 pixels to an ximage.
+ */
+static void put_values_8R8G8B24_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        bgr_t *ptr = PIXEL_ADDR3(xrb, x[i], y[i] );
+         ptr->r = rgba[i][RCOMP];
+         ptr->g = rgba[i][GCOMP];
+         ptr->b = rgba[i][BCOMP];
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_5R6G5B pixels to an ximage.
+ */
+static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLushort *ptr = PIXEL_ADDR2(xrb, x[i], y[i] );
+         *ptr = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_DITHER_5R6G5B pixels to an ximage.
+ */
+static void put_values_DITHER_5R6G5B_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLushort *ptr = PIXEL_ADDR2(xrb, x[i], y[i] );
+         PACK_TRUEDITHER( *ptr, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to an XImage.
+ */
+static void put_values_DITHER_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]),
+                    DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of 8-bit PF_DITHER pixels to an XImage.
+ */
+static void put_values_DITHER8_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+        *ptr = (GLubyte) DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to an XImage.
+ */
+static void put_values_1BIT_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   SETUP_1BIT;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]),
+                    DITHER_1BIT( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_HPCR pixels to an XImage.
+ */
+static void put_values_HPCR_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+         *ptr = (GLubyte) DITHER_HPCR( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_LOOKUP pixels to an XImage.
+ */
+static void put_values_LOOKUP_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   LOOKUP_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), LOOKUP(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void put_values_LOOKUP8_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   LOOKUP_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+        *ptr = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_GRAYSCALE pixels to an XImage.
+ */
+static void put_values_GRAYSCALE_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]),
+                    GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void put_values_GRAYSCALE8_ximage( PUT_VALUES_ARGS )
+{
+   const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i] );
+        *ptr = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+      }
+   }
+}
+
+
+
+
+/**********************************************************************/
+/*** Write MONO COLOR SPAN functions                                ***/
+/**********************************************************************/
+
+#define PUT_MONO_ROW_ARGS \
+       GLcontext *ctx, struct gl_renderbuffer *rb,     \
+       GLuint n, GLint x, GLint y, const void *value,  \
+       const GLubyte mask[]
+
+
+
+/*
+ * Write a span of identical pixels to a pixmap.
+ */
+static void put_mono_row_pixmap( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   register GLuint i;
+   XMesaSetForeground( xmesa->display, gc, pixel );
+   y = YFLIP(xrb, y);
+
+   /* New code contributed by Jeff Epler and cleaned up by Keith
+    * Whitwell.  
+    */
+   for (i = 0; i < n; ) {
+      GLuint start = i;
+
+      /* Identify and emit contiguous rendered pixels
+       */
+      while (i < n && (!mask || mask[i]))
+        i++;
+
+      if (start < i) 
+        XMesaFillRectangle( dpy, buffer, gc,
+                            (int)(x+start), (int) y,
+                            (int)(i-start), 1);
+
+      /* Eat up non-rendered pixels
+       */
+      while (i < n && !mask[i])
+        i++;
+   }
+}
+
+
+
+static void
+put_mono_row_ci_pixmap( PUT_MONO_ROW_ARGS )
+{
+   GLuint colorIndex = *((GLuint *) value);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   XMesaSetForeground( xmesa->display, gc, colorIndex );
+   y = YFLIP(xrb, y);
+
+   for (i = 0 ; i < n ;) {
+      GLuint start = i;
+      
+      /* Identify and emit contiguous rendered pixels 
+       */
+      while (i < n && (!mask || mask[i]))
+        i++;
+
+      if (start < i) 
+        XMesaFillRectangle( dpy, buffer, gc, 
+                            (int)(x+start), (int) y, 
+                            (int)(i-start), 1);
+
+      /* Eat up non-rendered pixels
+       */
+      while (i < n && !mask[i])
+        i++;
+   }
+}
+
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   int yy = YFLIP(xrb, y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x, yy, r, g, b);
+         XMesaSetForeground( dpy, gc, p );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) yy );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap.
+ */
+static void put_mono_row_DITHER_pixmap( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   int yy = YFLIP(xrb, y);
+   XDITHER_SETUP(yy);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+         XMesaSetForeground( dpy, gc, XDITHER( x, r, g, b ) );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) yy );
+      }
+   }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap.
+ */
+static void put_mono_row_1BIT_pixmap( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+         XMesaSetForeground( dpy, gc, DITHER_1BIT( x, y, r, g, b ) );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical pixels to an XImage.
+ */
+static void put_mono_row_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+        XMesaPutPixel( img, x, y, pixel );
+      }
+   }
+}
+
+
+static void
+put_mono_row_ci_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLuint colorIndex = *((GLuint *) value);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+        XMesaPutPixel( img, x, y, colorIndex );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical PF_TRUEDITHER pixels to an XImage.
+ */
+static void put_mono_row_TRUEDITHER_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaImage *img = xrb->ximage;
+   const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   GLuint i;
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER( p, x+i, y, r, g, b);
+        XMesaPutPixel( img, x+i, y, p );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8A8B8G8R pixels to an XImage.
+ */
+static void put_mono_row_8A8B8G8R_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GLuint i, *ptr;
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   ptr = PIXEL_ADDR4(xrb, x, y );
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+        ptr[i] = pixel;
+      }
+   }
+}
+
+/*
+ * Write a span of identical 8A8R8G8B pixels to an XImage.
+ */
+static void put_mono_row_8A8R8G8B_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   GLuint i, *ptr;
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   ptr = PIXEL_ADDR4(xrb, x, y );
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+        ptr[i] = pixel;
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8R8G8B pixels to an XImage.
+ */
+static void put_mono_row_8R8G8B_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLuint pixel = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
+   GLuint *ptr = PIXEL_ADDR4(xrb, x, y );
+   GLuint i;
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+        ptr[i] = pixel;
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8R8G8B pixels to an XImage.
+ */
+static void put_mono_row_8R8G8B24_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP];
+   const GLubyte g = color[GCOMP];
+   const GLubyte b = color[BCOMP];
+   GLuint i;
+   bgr_t *ptr = PIXEL_ADDR3(xrb, x, y );
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+         ptr[i].r = r;
+         ptr[i].g = g;
+         ptr[i].b = b;
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical DITHER pixels to an XImage.
+ */
+static void put_mono_row_DITHER_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   XMesaImage *img = xrb->ximage;
+   int yy = YFLIP(xrb, y);
+   register GLuint i;
+   XDITHER_SETUP(yy);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+        XMesaPutPixel( img, x, yy, XDITHER( x, r, g, b ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8-bit DITHER pixels to an XImage.
+ */
+static void put_mono_row_DITHER8_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   register GLuint i;
+   XDITHER_SETUP(y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+        ptr[i] = (GLubyte) XDITHER( x, r, g, b );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8-bit LOOKUP pixels to an XImage.
+ */
+static void put_mono_row_LOOKUP8_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   GLubyte pixel;
+   LOOKUP_SETUP;
+   pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]);
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+        ptr[i] = pixel;
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical PF_1BIT pixels to an XImage.
+ */
+static void put_mono_row_1BIT_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   SETUP_1BIT;
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+        XMesaPutPixel( img, x, y, DITHER_1BIT( x, y, r, g, b ) );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical HPCR pixels to an XImage.
+ */
+static void put_mono_row_HPCR_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
+   register GLuint i;
+   for (i=0;i<n;i++,x++) {
+      if (!mask || mask[i]) {
+         ptr[i] = DITHER_HPCR( x, y, r, g, b );
+      }
+   }
+}
+
+
+/*
+ * Write a span of identical 8-bit GRAYSCALE pixels to an XImage.
+ */
+static void put_mono_row_GRAYSCALE8_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+   GLubyte *ptr = (GLubyte *) PIXEL_ADDR1(xrb, x, y);
+   GLuint i;
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+        ptr[i] = p;
+      }
+   }
+}
+
+
+
+/*
+ * Write a span of identical PF_DITHER_5R6G5B pixels to an XImage.
+ */
+static void put_mono_row_DITHER_5R6G5B_ximage( PUT_MONO_ROW_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   register GLushort *ptr = PIXEL_ADDR2(xrb, x, y );
+   const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   GLuint i;
+   y = YFLIP(xrb, y);
+   for (i=0;i<n;i++) {
+      if (!mask || mask[i]) {
+         PACK_TRUEDITHER(ptr[i], x+i, y, r, g, b);
+      }
+   }
+}
+
+
+
+/**********************************************************************/
+/*** Write MONO COLOR PIXELS functions                              ***/
+/**********************************************************************/
+
+#define PUT_MONO_VALUES_ARGS \
+       GLcontext *ctx, struct gl_renderbuffer *rb,     \
+       GLuint n, const GLint x[], const GLint y[],     \
+       const void *value, const GLubyte mask[]
+
+
+
+/*
+ * Write an array of identical pixels to a pixmap.
+ */
+static void put_mono_values_pixmap( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   XMesaSetForeground( xmesa->display, gc, pixel );
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaDrawPoint( dpy, buffer, gc,
+                         (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+static void
+put_mono_values_ci_pixmap( PUT_MONO_VALUES_ARGS )
+{
+   const GLuint colorIndex = *((GLuint *) value);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   XMesaSetForeground( xmesa->display, gc, colorIndex );
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaDrawPoint( dpy, buffer, gc,
+                         (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void put_mono_values_TRUEDITHER_pixmap( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x[i], y[i], r, g, b);
+         XMesaSetForeground( dpy, gc, p );
+        XMesaDrawPoint( dpy, buffer, gc,
+                         (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to a pixmap.
+ */
+static void put_mono_values_DITHER_pixmap( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         XMesaSetForeground( dpy, gc, DITHER( x[i], y[i], r, g, b ) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to a pixmap.
+ */
+static void put_mono_values_1BIT_pixmap( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   SETUP_1BIT;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         XMesaSetForeground( dpy, gc, DITHER_1BIT( x[i], y[i], r, g, b ) );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical pixels to an XImage.
+ */
+static void put_mono_values_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
+               color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), pixel );
+      }
+   }
+}
+
+
+static void
+put_mono_values_ci_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLuint colorIndex = *((GLuint *) value);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), colorIndex );
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical TRUEDITHER pixels to an XImage.
+ */
+static void put_mono_values_TRUEDITHER_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         unsigned long p;
+         PACK_TRUEDITHER(p, x[i], YFLIP(xrb, y[i]), r, g, b);
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), p );
+      }
+   }
+}
+
+
+
+/*
+ * Write an array of identical 8A8B8G8R pixels to an XImage
+ */
+static void put_mono_values_8A8B8G8R_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLuint p = PACK_8A8B8G8R(color[RCOMP], color[GCOMP],
+                                  color[BCOMP], color[ACOMP]);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i] );
+        *ptr = p;
+      }
+   }
+}
+
+/*
+ * Write an array of identical 8A8R8G8B pixels to an XImage
+ */
+static void put_mono_values_8A8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLuint p = PACK_8A8R8G8B(color[RCOMP], color[GCOMP],
+                                  color[BCOMP], color[ACOMP]);
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i] );
+        *ptr = p;
+      }
+   }
+}
+
+/*
+ * Write an array of identical 8R8G8B pixels to an XImage.
+ */
+static void put_mono_values_8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   register GLuint i;
+   const GLuint p = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLuint *ptr = PIXEL_ADDR4(xrb, x[i], y[i] );
+        *ptr = p;
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical 8R8G8B pixels to an XImage.
+ */
+static void put_mono_values_8R8G8B24_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        bgr_t *ptr = PIXEL_ADDR3(xrb, x[i], y[i] );
+         ptr->r = r;
+         ptr->g = g;
+         ptr->b = b;
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical PF_DITHER pixels to an XImage.
+ */
+static void put_mono_values_DITHER_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]), DITHER( x[i], y[i], r, g, b ) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_DITHER pixels to an XImage.
+ */
+static void put_mono_values_DITHER8_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   DITHER_SETUP;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+        *ptr = (GLubyte) DITHER( x[i], y[i], r, g, b );
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void put_mono_values_LOOKUP8_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   register GLuint i;
+   GLubyte pixel;
+   LOOKUP_SETUP;
+   pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]);
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+        *ptr = pixel;
+      }
+   }
+}
+
+
+
+/*
+ * Write an array of identical PF_1BIT pixels to an XImage.
+ */
+static void put_mono_values_1BIT_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   SETUP_1BIT;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel( img, x[i], YFLIP(xrb, y[i]),
+                        DITHER_1BIT( x[i], y[i], r, g, b ));
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical PF_HPCR pixels to an XImage.
+ */
+static void put_mono_values_HPCR_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+         *ptr = DITHER_HPCR( x[i], y[i], r, g, b );
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void put_mono_values_GRAYSCALE8_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   register GLuint i;
+   register GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLubyte *ptr = PIXEL_ADDR1(xrb, x[i], y[i]);
+        *ptr = p;
+      }
+   }
+}
+
+
+/*
+ * Write an array of identical PF_DITHER_5R6G5B pixels to an XImage.
+ */
+static void put_mono_values_DITHER_5R6G5B_ximage( PUT_MONO_VALUES_ARGS )
+{
+   const GLubyte *color = (const GLubyte *) value;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        GLushort *ptr = PIXEL_ADDR2(xrb, x[i], y[i] );
+         PACK_TRUEDITHER(*ptr, x[i], y[i], r, g, b);
+      }
+   }
+}
+
+
+
+/**********************************************************************/
+/*** Write INDEX SPAN functions                                     ***/
+/**********************************************************************/
+
+/*
+ * Write a span of CI pixels to a Pixmap.
+ */
+static void put_row_ci_pixmap( PUT_ROW_ARGS )
+{
+   const GLuint *index = (GLuint *) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+            XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++,x++) {
+         XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+         XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+      }
+   }
+}
+
+
+/*
+ * Write a span of CI pixels to an XImage.
+ */
+static void put_row_ci_ximage( PUT_ROW_ARGS )
+{
+   const GLuint *index = (const GLuint *) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   y = YFLIP(xrb, y);
+   if (mask) {
+      for (i=0;i<n;i++,x++) {
+         if (mask[i]) {
+            XMesaPutPixel( img, x, y, (unsigned long) index[i] );
+         }
+      }
+   }
+   else {
+      for (i=0;i<n;i++,x++) {
+         XMesaPutPixel( img, x, y, (unsigned long) index[i] );
+      }
+   }
+}
+
+
+/**********************************************************************/
+/*** Write INDEX PIXELS functions                                   ***/
+/**********************************************************************/
+
+/*
+ * Write an array of CI pixels to a Pixmap.
+ */
+static void put_values_ci_pixmap( PUT_VALUES_ARGS )
+{
+   const GLuint *index = (const GLuint *) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaDrawable buffer = xrb->drawable;
+   XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+        XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+/*
+ * Write an array of CI pixels to an XImage.
+ */
+static void put_values_ci_ximage( PUT_VALUES_ARGS )
+{
+   const GLuint *index = (const GLuint *) values;
+   GET_XRB(xrb);
+   XMesaImage *img = xrb->ximage;
+   register GLuint i;
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+        XMesaPutPixel(img, x[i], YFLIP(xrb, y[i]), (unsigned long) index[i]);
+      }
+   }
+}
+
+
+
+
+/**********************************************************************/
+/*****                      Pixel reading                         *****/
+/**********************************************************************/
+
+#ifndef XFree86Server
+/**
+ * Do clip testing prior to calling XGetImage.  If any of the region lies
+ * outside the screen's bounds, XGetImage will return NULL.
+ * We use XTranslateCoordinates() to check if that's the case and
+ * adjust the x, y and length parameters accordingly.
+ * \return  -1 if span is totally clipped away,
+ *          else return number of pixels to skip in the destination array.
+ */
+static int
+clip_for_xgetimage(GLcontext *ctx, GLuint *n, GLint *x, GLint *y)
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer);
+   Window rootWin = RootWindow(xmesa->display, 0);
+   Window child;
+   GLint screenWidth = WidthOfScreen(DefaultScreenOfDisplay(xmesa->display));
+   GLint dx, dy;
+   if (source->type == PBUFFER || source->type == PIXMAP)
+      return 0;
+   XTranslateCoordinates(xmesa->display, source->frontxrb->pixmap, rootWin,
+                         *x, *y, &dx, &dy, &child);
+   if (dx >= screenWidth) {
+      /* totally clipped on right */
+      return -1;
+   }
+   if (dx < 0) {
+      /* clipped on left */
+      GLint clip = -dx;
+      if (clip >= (GLint) *n)
+         return -1;  /* totally clipped on left */
+      *x += clip;
+      *n -= clip;
+      dx = 0;
+      return clip;
+   }
+   if ((GLint) (dx + *n) > screenWidth) {
+      /* clipped on right */
+      GLint clip = dx + *n - screenWidth;
+      *n -= clip;
+   }
+   return 0;
+}
+#endif
+
+
+/*
+ * Read a horizontal span of color-index pixels.
+ */
+static void
+get_row_ci(GLcontext *ctx, struct gl_renderbuffer *rb,
+           GLuint n, GLint x, GLint y, void *values)
+{
+   GLuint *index = (GLuint *) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   GLuint i;
+
+   y = YFLIP(xrb, y);
+
+   if (xrb->pixmap) {
+#ifndef XFree86Server
+      XMesaImage *span = NULL;
+      int error;
+      int k = clip_for_xgetimage(ctx, &n, &x, &y);
+      if (k < 0)
+         return;
+      index += k;
+
+      catch_xgetimage_errors( xmesa->display );
+      span = XGetImage( xmesa->display, xrb->pixmap,
+                       x, y, n, 1, AllPlanes, ZPixmap );
+      error = check_xgetimage_errors();
+      if (span && !error) {
+        for (i=0;i<n;i++) {
+           index[i] = (GLuint) XMesaGetPixel( span, i, 0 );
+        }
+      }
+      else {
+        /* return 0 pixels */
+        for (i=0;i<n;i++) {
+           index[i] = 0;
+        }
+      }
+      if (span) {
+        XMesaDestroyImage( span );
+      }
+#else
+      (*xmesa->display->GetImage)(xrb->drawable,
+                                 x, y, n, 1, ZPixmap,
+                                 ~0L, (pointer)index);
+#endif
+   }
+   else if (xrb->ximage) {
+      XMesaImage *img = xrb->ximage;
+      for (i=0;i<n;i++,x++) {
+        index[i] = (GLuint) XMesaGetPixel( img, x, y );
+      }
+   }
+}
+
+
+
+/*
+ * Read a horizontal span of color pixels.
+ */
+static void
+get_row_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+             GLuint n, GLint x, GLint y, void *values)
+{
+   GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer);
+
+   if (xrb->pixmap) {
+      /* Read from Pixmap or Window */
+      XMesaImage *span = NULL;
+      int error;
+#ifdef XFree86Server
+      span = XMesaCreateImage(xmesa->xm_visual->BitsPerPixel, n, 1, NULL);
+      span->data = (char *)MALLOC(span->height * span->bytes_per_line);
+      error = (!span->data);
+      (*xmesa->display->GetImage)(xrb->drawable,
+                                 x, YFLIP(xrb, y), n, 1, ZPixmap,
+                                 ~0L, (pointer)span->data);
+#else
+      int k;
+      y = YFLIP(xrb, y);
+      k = clip_for_xgetimage(ctx, &n, &x, &y);
+      if (k < 0)
+         return;
+      rgba += k;
+      catch_xgetimage_errors( xmesa->display );
+      span = XGetImage( xmesa->display, xrb->pixmap,
+                       x, y, n, 1, AllPlanes, ZPixmap );
+      error = check_xgetimage_errors();
+#endif
+      if (span && !error) {
+        switch (xmesa->pixelformat) {
+           case PF_Truecolor:
+           case PF_Dither_True:
+               {
+                  const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+                  const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+                  const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+                  unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+                  unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+                  unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+                  GLint rShift = xmesa->xm_visual->rshift;
+                  GLint gShift = xmesa->xm_visual->gshift;
+                  GLint bShift = xmesa->xm_visual->bshift;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     unsigned long p;
+                     p = XMesaGetPixel( span, i, 0 );
+                     rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+                     rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+                     rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+              break;
+            case PF_5R6G5B:
+            case PF_Dither_5R6G5B:
+               {
+                  const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+                  const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+                  const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     unsigned long p = XMesaGetPixel( span, i, 0 );
+                     /* fast, but not quite accurate
+                     rgba[i][RCOMP] = ((p >> 8) & 0xf8);
+                     rgba[i][GCOMP] = ((p >> 3) & 0xfc);
+                     rgba[i][BCOMP] = ((p << 3) & 0xff);
+                     */
+                     rgba[i][RCOMP] = pixelToR[p >> 11];
+                     rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+                     rgba[i][BCOMP] = pixelToB[p & 0x1f];
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+              break;
+           case PF_8A8B8G8R:
+               {
+                  const GLuint *ptr4 = (GLuint *) span->data;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     GLuint p4 = *ptr4++;
+                     rgba[i][RCOMP] = (GLubyte) ( p4        & 0xff);
+                     rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                     rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                     rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+                  }
+              }
+              break;
+            case PF_8A8R8G8B:
+               {
+                  const GLuint *ptr4 = (GLuint *) span->data;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     GLuint p4 = *ptr4++;
+                     rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                     rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                     rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+                     rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+                  }
+              }
+              break;
+            case PF_8R8G8B:
+               {
+                  const GLuint *ptr4 = (GLuint *) span->data;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     GLuint p4 = *ptr4++;
+                     rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                     rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                     rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+                     rgba[i][ACOMP] = 255;
+                  }
+              }
+              break;
+            case PF_8R8G8B24:
+               {
+                  const bgr_t *ptr3 = (bgr_t *) span->data;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     rgba[i][RCOMP] = ptr3[i].r;
+                     rgba[i][GCOMP] = ptr3[i].g;
+                     rgba[i][BCOMP] = ptr3[i].b;
+                     rgba[i][ACOMP] = 255;
+                  }
+              }
+              break;
+            case PF_HPCR:
+               {
+                  GLubyte *ptr1 = (GLubyte *) span->data;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     GLubyte p = *ptr1++;
+                     rgba[i][RCOMP] =  p & 0xE0;
+                     rgba[i][GCOMP] = (p & 0x1C) << 3;
+                     rgba[i][BCOMP] = (p & 0x03) << 6;
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+               break;
+           case PF_Dither:
+           case PF_Lookup:
+           case PF_Grayscale:
+               {
+                  GLubyte *rTable = source->pixel_to_r;
+                  GLubyte *gTable = source->pixel_to_g;
+                  GLubyte *bTable = source->pixel_to_b;
+                  if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
+                     const GLubyte *ptr1 = (GLubyte *) span->data;
+                     GLuint i;
+                     for (i=0;i<n;i++) {
+                        unsigned long p = *ptr1++;
+                        rgba[i][RCOMP] = rTable[p];
+                        rgba[i][GCOMP] = gTable[p];
+                        rgba[i][BCOMP] = bTable[p];
+                        rgba[i][ACOMP] = 255;
+                     }
+                  }
+                  else {
+                     GLuint i;
+                     for (i=0;i<n;i++) {
+                        unsigned long p = XMesaGetPixel( span, i, 0 );
+                        rgba[i][RCOMP] = rTable[p];
+                        rgba[i][GCOMP] = gTable[p];
+                        rgba[i][BCOMP] = bTable[p];
+                        rgba[i][ACOMP] = 255;
+                     }
+                  }
+               }
+              break;
+           case PF_1Bit:
+               {
+                  int bitFlip = xmesa->xm_visual->bitFlip;
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     unsigned long p;
+                     p = XMesaGetPixel( span, i, 0 ) ^ bitFlip;
+                     rgba[i][RCOMP] = (GLubyte) (p * 255);
+                     rgba[i][GCOMP] = (GLubyte) (p * 255);
+                     rgba[i][BCOMP] = (GLubyte) (p * 255);
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+              break;
+           default:
+              _mesa_problem(NULL,"Problem in DD.read_color_span (1)");
+               return;
+        }
+      }
+      else {
+        /* return black pixels */
+         GLuint i;
+        for (i=0;i<n;i++) {
+           rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = rgba[i][ACOMP] = 0;
+        }
+      }
+      if (span) {
+        XMesaDestroyImage( span );
+      }
+   }
+   else if (xrb->ximage) {
+      /* Read from XImage back buffer */
+      switch (xmesa->pixelformat) {
+         case PF_Truecolor:
+         case PF_Dither_True:
+            {
+               const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+               const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+               const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+               unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+               unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+               unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+               GLint rShift = xmesa->xm_visual->rshift;
+               GLint gShift = xmesa->xm_visual->gshift;
+               GLint bShift = xmesa->xm_visual->bshift;
+               XMesaImage *img = xrb->ximage;
+               GLuint i;
+               y = YFLIP(xrb, y);
+               for (i=0;i<n;i++) {
+                  unsigned long p;
+                 p = XMesaGetPixel( img, x+i, y );
+                  rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+                  rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+                  rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+            break;
+         case PF_5R6G5B:
+         case PF_Dither_5R6G5B:
+            {
+               const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+               const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+               const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+               const GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y);
+               GLuint i;
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+               const GLuint *ptr4 = (const GLuint *) ptr2;
+               GLuint extraPixel = (n & 1);
+               n -= extraPixel;
+               for (i = 0; i < n; i += 2) {
+                  const GLuint p = *ptr4++;
+                  const GLuint p0 = p & 0xffff;
+                  const GLuint p1 = p >> 16;
+                  /* fast, but not quite accurate
+                  rgba[i][RCOMP] = ((p >> 8) & 0xf8);
+                  rgba[i][GCOMP] = ((p >> 3) & 0xfc);
+                  rgba[i][BCOMP] = ((p << 3) & 0xff);
+                  */
+                  rgba[i][RCOMP] = pixelToR[p0 >> 11];
+                  rgba[i][GCOMP] = pixelToG[(p0 >> 5) & 0x3f];
+                  rgba[i][BCOMP] = pixelToB[p0 & 0x1f];
+                  rgba[i][ACOMP] = 255;
+                  rgba[i+1][RCOMP] = pixelToR[p1 >> 11];
+                  rgba[i+1][GCOMP] = pixelToG[(p1 >> 5) & 0x3f];
+                  rgba[i+1][BCOMP] = pixelToB[p1 & 0x1f];
+                  rgba[i+1][ACOMP] = 255;
+               }
+               if (extraPixel) {
+                  GLushort p = ptr2[n];
+                  rgba[n][RCOMP] = pixelToR[p >> 11];
+                  rgba[n][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+                  rgba[n][BCOMP] = pixelToB[p & 0x1f];
+                  rgba[n][ACOMP] = 255;
+               }
+#else
+               for (i = 0; i < n; i++) {
+                  const GLushort p = ptr2[i];
+                  rgba[i][RCOMP] = pixelToR[p >> 11];
+                  rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+                  rgba[i][BCOMP] = pixelToB[p & 0x1f];
+                  rgba[i][ACOMP] = 255;
+               }
+#endif
+            }
+            break;
+        case PF_8A8B8G8R:
+            {
+               const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y);
+               GLuint i;
+               for (i=0;i<n;i++) {
+                  GLuint p4 = *ptr4++;
+                  rgba[i][RCOMP] = (GLubyte) ( p4        & 0xff);
+                  rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                  rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                  rgba[i][ACOMP] = (GLint)   ((p4 >> 24) & 0xff);
+               }
+            }
+           break;
+        case PF_8A8R8G8B:
+            {
+               const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y);
+               GLuint i;
+               for (i=0;i<n;i++) {
+                  GLuint p4 = *ptr4++;
+                  rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                  rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                  rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+                  rgba[i][ACOMP] = (GLint)   ((p4 >> 24) & 0xff);
+               }
+            }
+           break;
+        case PF_8R8G8B:
+            {
+               const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y);
+               GLuint i;
+               for (i=0;i<n;i++) {
+                  GLuint p4 = *ptr4++;
+                  rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+                  rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+                  rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+           break;
+        case PF_8R8G8B24:
+            {
+               const bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y);
+               GLuint i;
+               for (i=0;i<n;i++) {
+                  rgba[i][RCOMP] = ptr3[i].r;
+                  rgba[i][GCOMP] = ptr3[i].g;
+                  rgba[i][BCOMP] = ptr3[i].b;
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+           break;
+         case PF_HPCR:
+            {
+               const GLubyte *ptr1 = PIXEL_ADDR1(xrb, x, y);
+               GLuint i;
+               for (i=0;i<n;i++) {
+                  GLubyte p = *ptr1++;
+                  rgba[i][RCOMP] =  p & 0xE0;
+                  rgba[i][GCOMP] = (p & 0x1C) << 3;
+                  rgba[i][BCOMP] = (p & 0x03) << 6;
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+            break;
+        case PF_Dither:
+        case PF_Lookup:
+        case PF_Grayscale:
+            {
+               const GLubyte *rTable = source->pixel_to_r;
+               const GLubyte *gTable = source->pixel_to_g;
+               const GLubyte *bTable = source->pixel_to_b;
+               if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
+                  GLubyte *ptr1 = PIXEL_ADDR1(xrb, x, y);
+                  GLuint i;
+                  for (i=0;i<n;i++) {
+                     unsigned long p = *ptr1++;
+                     rgba[i][RCOMP] = rTable[p];
+                     rgba[i][GCOMP] = gTable[p];
+                     rgba[i][BCOMP] = bTable[p];
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+               else {
+                  XMesaImage *img = xrb->ximage;
+                  GLuint i;
+                  y = YFLIP(xrb, y);
+                  for (i=0;i<n;i++,x++) {
+                     unsigned long p = XMesaGetPixel( img, x, y );
+                     rgba[i][RCOMP] = rTable[p];
+                     rgba[i][GCOMP] = gTable[p];
+                     rgba[i][BCOMP] = bTable[p];
+                     rgba[i][ACOMP] = 255;
+                  }
+               }
+            }
+           break;
+        case PF_1Bit:
+            {
+               XMesaImage *img = xrb->ximage;
+               int bitFlip = xmesa->xm_visual->bitFlip;
+               GLuint i;
+               y = YFLIP(xrb, y);
+               for (i=0;i<n;i++,x++) {
+                  unsigned long p;
+                 p = XMesaGetPixel( img, x, y ) ^ bitFlip;
+                  rgba[i][RCOMP] = (GLubyte) (p * 255);
+                  rgba[i][GCOMP] = (GLubyte) (p * 255);
+                  rgba[i][BCOMP] = (GLubyte) (p * 255);
+                  rgba[i][ACOMP] = 255;
+               }
+           }
+           break;
+        default:
+           _mesa_problem(NULL,"Problem in DD.read_color_span (2)");
+            return;
+      }
+   }
+}
+
+
+
+/*
+ * Read an array of color index pixels.
+ */
+static void
+get_values_ci(GLcontext *ctx, struct gl_renderbuffer *rb,
+              GLuint n, const GLint x[], const GLint y[], void *values)
+{
+   GLuint *indx = (GLuint *) values;
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   GET_XRB(xrb);
+   GLuint i;
+   if (xrb->pixmap) {
+      for (i=0;i<n;i++) {
+         indx[i] = (GLuint) read_pixel( xmesa->display, xrb->drawable,
+                                        x[i], YFLIP(xrb, y[i]) );
+      }
+   }
+   else if (xrb->ximage) {
+      XMesaImage *img = xrb->ximage;
+      for (i=0;i<n;i++) {
+         indx[i] = (GLuint) XMesaGetPixel( img, x[i], YFLIP(xrb, y[i]) );
+      }
+   }
+}
+
+
+
+static void
+get_values_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+                GLuint n, const GLint x[], const GLint y[], void *values)
+{
+   GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+   GET_XRB(xrb);
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer);
+   register GLuint i;
+
+   if (xrb->pixmap) {
+      XMesaDrawable buffer = xrb->drawable;
+      switch (xmesa->pixelformat) {
+        case PF_Truecolor:
+         case PF_Dither_True:
+         case PF_5R6G5B:
+         case PF_Dither_5R6G5B:
+            {
+               unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+               unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+               unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+               GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+               GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+               GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+               GLint rShift = xmesa->xm_visual->rshift;
+               GLint gShift = xmesa->xm_visual->gshift;
+               GLint bShift = xmesa->xm_visual->bshift;
+               for (i=0;i<n;i++) {
+                  unsigned long p = read_pixel( dpy, buffer,
+                                                x[i], YFLIP(xrb, y[i]) );
+                  rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+                  rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+                  rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+            break;
+        case PF_8A8B8G8R:
+           for (i=0;i<n;i++) {
+               unsigned long p = read_pixel( dpy, buffer,
+                                             x[i], YFLIP(xrb, y[i]) );
+               rgba[i][RCOMP] = (GLubyte) ( p        & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ((p >> 16) & 0xff);
+               rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff);
+           }
+           break;
+        case PF_8A8R8G8B:
+           for (i=0;i<n;i++) {
+               unsigned long p = read_pixel( dpy, buffer,
+                                             x[i], YFLIP(xrb, y[i]) );
+               rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ( p        & 0xff);
+               rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff);
+           }
+           break;
+        case PF_8R8G8B:
+           for (i=0;i<n;i++) {
+               unsigned long p = read_pixel( dpy, buffer,
+                                             x[i], YFLIP(xrb, y[i]) );
+               rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ( p        & 0xff);
+               rgba[i][ACOMP] = 255;
+           }
+           break;
+        case PF_8R8G8B24:
+           for (i=0;i<n;i++) {
+               unsigned long p = read_pixel( dpy, buffer,
+                                             x[i], YFLIP(xrb, y[i]) );
+               rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ( p        & 0xff);
+               rgba[i][ACOMP] = 255;
+           }
+           break;
+         case PF_HPCR:
+            for (i=0;i<n;i++) {
+               unsigned long p = read_pixel( dpy, buffer,
+                                             x[i], YFLIP(xrb, y[i]) );
+               rgba[i][RCOMP] = (GLubyte) ( p & 0xE0      );
+               rgba[i][GCOMP] = (GLubyte) ((p & 0x1C) << 3);
+                  rgba[i][BCOMP] = (GLubyte) ((p & 0x03) << 6);
+                  rgba[i][ACOMP] = (GLubyte) 255;
+            }
+            break;
+        case PF_Dither:
+        case PF_Lookup:
+        case PF_Grayscale:
+            {
+               GLubyte *rTable = source->pixel_to_r;
+               GLubyte *gTable = source->pixel_to_g;
+               GLubyte *bTable = source->pixel_to_b;
+               for (i=0;i<n;i++) {
+                  unsigned long p = read_pixel( dpy, buffer,
+                                                x[i], YFLIP(xrb, y[i]) );
+                  rgba[i][RCOMP] = rTable[p];
+                  rgba[i][GCOMP] = gTable[p];
+                  rgba[i][BCOMP] = bTable[p];
+                  rgba[i][ACOMP] = 255;
+               }
+           }
+           break;
+        case PF_1Bit:
+            {
+               int bitFlip = xmesa->xm_visual->bitFlip;
+               for (i=0;i<n;i++) {
+                  unsigned long p = read_pixel( dpy, buffer,
+                                           x[i], YFLIP(xrb, y[i])) ^ bitFlip;
+                  rgba[i][RCOMP] = (GLubyte) (p * 255);
+                  rgba[i][GCOMP] = (GLubyte) (p * 255);
+                  rgba[i][BCOMP] = (GLubyte) (p * 255);
+                  rgba[i][ACOMP] = 255;
+               }
+           }
+           break;
+        default:
+           _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)");
+            return;
+      }
+   }
+   else if (xrb->ximage) {
+      /* Read from XImage back buffer */
+      switch (xmesa->pixelformat) {
+        case PF_Truecolor:
+         case PF_Dither_True:
+         case PF_5R6G5B:
+         case PF_Dither_5R6G5B:
+            {
+               unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+               unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+               unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+               GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+               GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+               GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+               GLint rShift = xmesa->xm_visual->rshift;
+               GLint gShift = xmesa->xm_visual->gshift;
+               GLint bShift = xmesa->xm_visual->bshift;
+               XMesaImage *img = xrb->ximage;
+               for (i=0;i<n;i++) {
+                  unsigned long p;
+                  p = XMesaGetPixel( img, x[i], YFLIP(xrb, y[i]) );
+                  rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+                  rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+                  rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+                  rgba[i][ACOMP] = 255;
+               }
+            }
+            break;
+        case PF_8A8B8G8R:
+           for (i=0;i<n;i++) {
+               GLuint *ptr4 = PIXEL_ADDR4(xrb, x[i], y[i]);
+               GLuint p4 = *ptr4;
+               rgba[i][RCOMP] = (GLubyte) ( p4        & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+               rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+           }
+           break;
+        case PF_8A8R8G8B:
+           for (i=0;i<n;i++) {
+               GLuint *ptr4 = PIXEL_ADDR4(xrb, x[i], y[i]);
+               GLuint p4 = *ptr4;
+               rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+               rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+           }
+           break;
+        case PF_8R8G8B:
+           for (i=0;i<n;i++) {
+               GLuint *ptr4 = PIXEL_ADDR4(xrb, x[i], y[i]);
+               GLuint p4 = *ptr4;
+               rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+               rgba[i][GCOMP] = (GLubyte) ((p4 >> 8)  & 0xff);
+               rgba[i][BCOMP] = (GLubyte) ( p4        & 0xff);
+               rgba[i][ACOMP] = 255;
+           }
+           break;
+        case PF_8R8G8B24:
+           for (i=0;i<n;i++) {
+               bgr_t *ptr3 = PIXEL_ADDR3(xrb, x[i], y[i]);
+               rgba[i][RCOMP] = ptr3->r;
+               rgba[i][GCOMP] = ptr3->g;
+               rgba[i][BCOMP] = ptr3->b;
+               rgba[i][ACOMP] = 255;
+           }
+           break;
+         case PF_HPCR:
+            for (i=0;i<n;i++) {
+               GLubyte *ptr1 = PIXEL_ADDR1(xrb, x[i], y[i]);
+               GLubyte p = *ptr1;
+               rgba[i][RCOMP] =  p & 0xE0;
+               rgba[i][GCOMP] = (p & 0x1C) << 3;
+               rgba[i][BCOMP] = (p & 0x03) << 6;
+               rgba[i][ACOMP] = 255;
+            }
+            break;
+        case PF_Dither:
+        case PF_Lookup:
+        case PF_Grayscale:
+            {
+               GLubyte *rTable = source->pixel_to_r;
+               GLubyte *gTable = source->pixel_to_g;
+               GLubyte *bTable = source->pixel_to_b;
+               XMesaImage *img = xrb->ximage;
+               for (i=0;i<n;i++) {
+                  unsigned long p;
+                  p = XMesaGetPixel( img, x[i], YFLIP(xrb, y[i]) );
+                  rgba[i][RCOMP] = rTable[p];
+                  rgba[i][GCOMP] = gTable[p];
+                  rgba[i][BCOMP] = bTable[p];
+                  rgba[i][ACOMP] = 255;
+               }
+           }
+           break;
+        case PF_1Bit:
+            {
+               XMesaImage *img = xrb->ximage;
+               int bitFlip = xmesa->xm_visual->bitFlip;
+               for (i=0;i<n;i++) {
+                  unsigned long p;
+                  p = XMesaGetPixel( img, x[i], YFLIP(xrb, y[i]) ) ^ bitFlip;
+                  rgba[i][RCOMP] = (GLubyte) (p * 255);
+                  rgba[i][GCOMP] = (GLubyte) (p * 255);
+                  rgba[i][BCOMP] = (GLubyte) (p * 255);
+                  rgba[i][ACOMP] = 255;
+               }
+           }
+           break;
+        default:
+           _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)");
+            return;
+      }
+   }
+}
+
+
+/**
+ * Initialize the renderbuffer's PutRow, GetRow, etc. functions.
+ * This would generally only need to be called once when the renderbuffer
+ * is created.  However, we can change pixel formats on the fly if dithering
+ * is enabled/disabled.  Therefore, we may call this more often than that.
+ */
+void
+xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb,
+                             enum pixel_format pixelformat, GLint depth)
+{
+   const GLboolean pixmap = xrb->pixmap ? GL_TRUE : GL_FALSE;
+   struct gl_renderbuffer *rb  = &xrb->St.Base;
+
+   switch (pixelformat) {
+   case PF_Index:
+      ASSERT(rb->DataType == GL_UNSIGNED_INT);
+      if (pixmap) {
+         rb->PutRow        = put_row_ci_pixmap;
+         rb->PutRowRGB     = NULL;
+         rb->PutMonoRow    = put_mono_row_ci_pixmap;
+         rb->PutValues     = put_values_ci_pixmap;
+         rb->PutMonoValues = put_mono_values_ci_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_ci_ximage;
+         rb->PutRowRGB     = NULL;
+         rb->PutMonoRow    = put_mono_row_ci_ximage;
+         rb->PutValues     = put_values_ci_ximage;
+         rb->PutMonoValues = put_mono_values_ci_ximage;
+      }
+      break;
+   case PF_Truecolor:
+      if (pixmap) {
+         rb->PutRow        = put_row_TRUECOLOR_pixmap;
+         rb->PutRowRGB     = put_row_rgb_TRUECOLOR_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_TRUECOLOR_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_TRUECOLOR_ximage;
+         rb->PutRowRGB     = put_row_rgb_TRUECOLOR_ximage;
+         rb->PutMonoRow    = put_mono_row_ximage;
+         rb->PutValues     = put_values_TRUECOLOR_ximage;
+         rb->PutMonoValues = put_mono_values_ximage;
+      }
+      break;
+   case PF_Dither_True:
+      if (pixmap) {
+         rb->PutRow        = put_row_TRUEDITHER_pixmap;
+         rb->PutRowRGB     = put_row_rgb_TRUEDITHER_pixmap;
+         rb->PutMonoRow    = put_mono_row_TRUEDITHER_pixmap;
+         rb->PutValues     = put_values_TRUEDITHER_pixmap;
+         rb->PutMonoValues = put_mono_values_TRUEDITHER_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_TRUEDITHER_ximage;
+         rb->PutRowRGB     = put_row_rgb_TRUEDITHER_ximage;
+         rb->PutMonoRow    = put_mono_row_TRUEDITHER_ximage;
+         rb->PutValues     = put_values_TRUEDITHER_ximage;
+         rb->PutMonoValues = put_mono_values_TRUEDITHER_ximage;
+      }
+      break;
+   case PF_8A8B8G8R:
+      if (pixmap) {
+         rb->PutRow        = put_row_8A8B8G8R_pixmap;
+         rb->PutRowRGB     = put_row_rgb_8A8B8G8R_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_8A8B8G8R_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_8A8B8G8R_ximage;
+         rb->PutRowRGB     = put_row_rgb_8A8B8G8R_ximage;
+         rb->PutMonoRow    = put_mono_row_8A8B8G8R_ximage;
+         rb->PutValues     = put_values_8A8B8G8R_ximage;
+         rb->PutMonoValues = put_mono_values_8A8B8G8R_ximage;
+        rb->GetPointer    = get_pointer_4_ximage;
+      }
+      break;
+   case PF_8A8R8G8B:
+      if (pixmap) {
+         rb->PutRow        = put_row_8A8R8G8B_pixmap;
+         rb->PutRowRGB     = put_row_rgb_8A8R8G8B_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_8A8R8G8B_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_8A8R8G8B_ximage;
+         rb->PutRowRGB     = put_row_rgb_8A8R8G8B_ximage;
+         rb->PutMonoRow    = put_mono_row_8A8R8G8B_ximage;
+         rb->PutValues     = put_values_8A8R8G8B_ximage;
+         rb->PutMonoValues = put_mono_values_8A8R8G8B_ximage;
+        rb->GetPointer    = get_pointer_4_ximage;
+      }
+      break;
+   case PF_8R8G8B:
+      if (pixmap) {
+         rb->PutRow        = put_row_8R8G8B_pixmap;
+         rb->PutRowRGB     = put_row_rgb_8R8G8B_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_8R8G8B_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_8R8G8B_ximage;
+         rb->PutRowRGB     = put_row_rgb_8R8G8B_ximage;
+         rb->PutMonoRow    = put_mono_row_8R8G8B_ximage;
+         rb->PutValues     = put_values_8R8G8B_ximage;
+         rb->PutMonoValues = put_mono_values_8R8G8B_ximage;
+      }
+      break;
+   case PF_8R8G8B24:
+      if (pixmap) {
+         rb->PutRow        = put_row_8R8G8B24_pixmap;
+         rb->PutRowRGB     = put_row_rgb_8R8G8B24_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_8R8G8B24_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_8R8G8B24_ximage;
+         rb->PutRowRGB     = put_row_rgb_8R8G8B24_ximage;
+         rb->PutMonoRow    = put_mono_row_8R8G8B24_ximage;
+         rb->PutValues     = put_values_8R8G8B24_ximage;
+         rb->PutMonoValues = put_mono_values_8R8G8B24_ximage;
+      }
+      break;
+   case PF_5R6G5B:
+      if (pixmap) {
+         rb->PutRow        = put_row_5R6G5B_pixmap;
+         rb->PutRowRGB     = put_row_rgb_5R6G5B_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_5R6G5B_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_5R6G5B_ximage;
+         rb->PutRowRGB     = put_row_rgb_5R6G5B_ximage;
+         rb->PutMonoRow    = put_mono_row_ximage;
+         rb->PutValues     = put_values_5R6G5B_ximage;
+         rb->PutMonoValues = put_mono_values_ximage;
+      }
+      break;
+   case PF_Dither_5R6G5B:
+      if (pixmap) {
+         rb->PutRow        = put_row_DITHER_5R6G5B_pixmap;
+         rb->PutRowRGB     = put_row_rgb_DITHER_5R6G5B_pixmap;
+         rb->PutMonoRow    = put_mono_row_TRUEDITHER_pixmap;
+         rb->PutValues     = put_values_DITHER_5R6G5B_pixmap;
+         rb->PutMonoValues = put_mono_values_TRUEDITHER_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_DITHER_5R6G5B_ximage;
+         rb->PutRowRGB     = put_row_rgb_DITHER_5R6G5B_ximage;
+         rb->PutMonoRow    = put_mono_row_DITHER_5R6G5B_ximage;
+         rb->PutValues     = put_values_DITHER_5R6G5B_ximage;
+         rb->PutMonoValues = put_mono_values_DITHER_5R6G5B_ximage;
+      }
+      break;
+   case PF_Dither:
+      if (pixmap) {
+         rb->PutRow        = put_row_DITHER_pixmap;
+         rb->PutRowRGB     = put_row_rgb_DITHER_pixmap;
+         rb->PutMonoRow    = put_mono_row_DITHER_pixmap;
+         rb->PutValues     = put_values_DITHER_pixmap;
+         rb->PutMonoValues = put_mono_values_DITHER_pixmap;
+      }
+      else {
+         if (depth == 8) {
+            rb->PutRow        = put_row_DITHER8_ximage;
+            rb->PutRowRGB     = put_row_rgb_DITHER8_ximage;
+            rb->PutMonoRow    = put_mono_row_DITHER8_ximage;
+            rb->PutValues     = put_values_DITHER8_ximage;
+            rb->PutMonoValues = put_mono_values_DITHER8_ximage;
+         }
+         else {
+            rb->PutRow        = put_row_DITHER_ximage;
+            rb->PutRowRGB     = put_row_rgb_DITHER_ximage;
+            rb->PutMonoRow    = put_mono_row_DITHER_ximage;
+            rb->PutValues     = put_values_DITHER_ximage;
+            rb->PutMonoValues = put_mono_values_DITHER_ximage;
+         }
+      }
+      break;
+   case PF_1Bit:
+      if (pixmap) {
+         rb->PutRow        = put_row_1BIT_pixmap;
+         rb->PutRowRGB     = put_row_rgb_1BIT_pixmap;
+         rb->PutMonoRow    = put_mono_row_1BIT_pixmap;
+         rb->PutValues     = put_values_1BIT_pixmap;
+         rb->PutMonoValues = put_mono_values_1BIT_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_1BIT_ximage;
+         rb->PutRowRGB     = put_row_rgb_1BIT_ximage;
+         rb->PutMonoRow    = put_mono_row_1BIT_ximage;
+         rb->PutValues     = put_values_1BIT_ximage;
+         rb->PutMonoValues = put_mono_values_1BIT_ximage;
+      }
+      break;
+   case PF_HPCR:
+      if (pixmap) {
+         rb->PutRow        = put_row_HPCR_pixmap;
+         rb->PutRowRGB     = put_row_rgb_HPCR_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_HPCR_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         rb->PutRow        = put_row_HPCR_ximage;
+         rb->PutRowRGB     = put_row_rgb_HPCR_ximage;
+         rb->PutMonoRow    = put_mono_row_HPCR_ximage;
+         rb->PutValues     = put_values_HPCR_ximage;
+         rb->PutMonoValues = put_mono_values_HPCR_ximage;
+      }
+      break;
+   case PF_Lookup:
+      if (pixmap) {
+         rb->PutRow        = put_row_LOOKUP_pixmap;
+         rb->PutRowRGB     = put_row_rgb_LOOKUP_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_LOOKUP_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         if (depth==8) {
+            rb->PutRow        = put_row_LOOKUP8_ximage;
+            rb->PutRowRGB     = put_row_rgb_LOOKUP8_ximage;
+            rb->PutMonoRow    = put_mono_row_LOOKUP8_ximage;
+            rb->PutValues     = put_values_LOOKUP8_ximage;
+            rb->PutMonoValues = put_mono_values_LOOKUP8_ximage;
+         }
+         else {
+            rb->PutRow        = put_row_LOOKUP_ximage;
+            rb->PutRowRGB     = put_row_rgb_LOOKUP_ximage;
+            rb->PutMonoRow    = put_mono_row_ximage;
+            rb->PutValues     = put_values_LOOKUP_ximage;
+            rb->PutMonoValues = put_mono_values_ximage;
+         }
+      }
+      break;
+   case PF_Grayscale:
+      if (pixmap) {
+         rb->PutRow        = put_row_GRAYSCALE_pixmap;
+         rb->PutRowRGB     = put_row_rgb_GRAYSCALE_pixmap;
+         rb->PutMonoRow    = put_mono_row_pixmap;
+         rb->PutValues     = put_values_GRAYSCALE_pixmap;
+         rb->PutMonoValues = put_mono_values_pixmap;
+      }
+      else {
+         if (depth == 8) {
+            rb->PutRow        = put_row_GRAYSCALE8_ximage;
+            rb->PutRowRGB     = put_row_rgb_GRAYSCALE8_ximage;
+            rb->PutMonoRow    = put_mono_row_GRAYSCALE8_ximage;
+            rb->PutValues     = put_values_GRAYSCALE8_ximage;
+            rb->PutMonoValues = put_mono_values_GRAYSCALE8_ximage;
+         }
+         else {
+            rb->PutRow        = put_row_GRAYSCALE_ximage;
+            rb->PutRowRGB     = put_row_rgb_GRAYSCALE_ximage;
+            rb->PutMonoRow    = put_mono_row_ximage;
+            rb->PutValues     = put_values_GRAYSCALE_ximage;
+            rb->PutMonoValues = put_mono_values_ximage;
+         }
+      }
+      break;
+   default:
+      _mesa_problem(NULL, "Bad pixel format in xmesa_update_state (1)");
+      return;
+   }
+
+
+   /* Get functions */
+   if (pixelformat == PF_Index) {
+      rb->GetRow = get_row_ci;
+      rb->GetValues = get_values_ci;
+   }
+   else {
+      rb->GetRow = get_row_rgba;
+      rb->GetValues = get_values_rgba;
+   }
+}
+
diff --git a/src/mesa/pipe/xlib/xm_surface.c b/src/mesa/pipe/xlib/xm_surface.c
new file mode 100644 (file)
index 0000000..5533158
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * \file xm_surface.c
+ * Code to allow the softpipe code to write to X windows/buffers.
+ * This is a bit of a hack for now.  We've basically got two different
+ * abstractions for color buffers: gl_renderbuffer and pipe_surface.
+ * They'll need to get merged someday...
+ * For now, they're separate things that point to each other.
+ */
+
+
+#include "glxheader.h"
+#include "GL/xmesa.h"
+#include "xmesaP.h"
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/softpipe/sp_context.h"
+#include "pipe/softpipe/sp_clear.h"
+#include "pipe/softpipe/sp_tile_cache.h"
+#include "pipe/softpipe/sp_surface.h"
+#include "state_tracker/st_context.h"
+
+
+#define CLIP_TILE \
+   do { \
+      if (x + w > ps->width) \
+         w = ps->width - x; \
+      if (y + h > ps->height) \
+         h = ps->height -y; \
+   } while(0)
+
+
+static INLINE struct xmesa_surface *
+xmesa_surface(struct pipe_surface *ps)
+{
+   return (struct xmesa_surface *) ps;
+}
+
+
+static INLINE struct xmesa_renderbuffer *
+xmesa_rb(struct pipe_surface *ps)
+{
+   struct xmesa_surface *xms = xmesa_surface(ps);
+   return xms->xrb;
+}
+
+
+#define FLIP(Y) Y = xrb->St.Base.Height - (Y) - 1;
+
+
+void
+xmesa_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+                    uint x, uint y, uint w, uint h, float *p)
+{
+   struct xmesa_surface *xms = xmesa_surface(ps);
+   struct xmesa_renderbuffer *xrb = xms->xrb;
+
+   if (xrb) {
+      /* this is a front/back color buffer */
+      GLubyte tmp[MAX_WIDTH * 4];
+      GLuint i, j;
+      uint w0 = w;
+      GET_CURRENT_CONTEXT(ctx);
+
+      CLIP_TILE;
+
+      FLIP(y);
+      for (i = 0; i < h; i++) {
+         xrb->St.Base.GetRow(ctx, &xrb->St.Base, w, x, y - i, tmp);
+         for (j = 0; j < w * 4; j++) {
+            p[j] = UBYTE_TO_FLOAT(tmp[j]);
+         }
+         p += w0 * 4;
+      }
+   }
+   else {
+      /* other softpipe surface */
+      softpipe_get_tile_rgba(pipe, ps, x, y, w, h, p);
+   }
+}
+
+
+void
+xmesa_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+                    uint x, uint y, uint w, uint h, const float *p)
+{
+   struct xmesa_surface *xms = xmesa_surface(ps);
+   struct xmesa_renderbuffer *xrb = xms->xrb;
+
+   if (xrb) {
+      /* this is a front/back color buffer */
+      GLubyte tmp[MAX_WIDTH * 4];
+      GLuint i, j;
+      uint w0 = w;
+      GET_CURRENT_CONTEXT(ctx);
+      CLIP_TILE;
+      FLIP(y);
+      for (i = 0; i < h; i++) {
+         for (j = 0; j < w * 4; j++) {
+            UNCLAMPED_FLOAT_TO_UBYTE(tmp[j], p[j]);
+         }
+         xrb->St.Base.PutRow(ctx, &xrb->St.Base, w, x, y - i, tmp, NULL);
+         p += w0 * 4;
+      }
+#if 0 /* debug: flush */
+      {
+         XMesaContext xm = XMESA_CONTEXT(ctx);
+         XSync(xm->display, 0);
+      }
+#endif
+   }
+   else {
+      /* other softpipe surface */
+      softpipe_put_tile_rgba(pipe, ps, x, y, w, h, p);
+   }
+}
+
+
+
+/**
+ * Called to create a pipe_surface for each X renderbuffer.
+ * Note: this is being used instead of pipe->surface_alloc() since we
+ * have special/unique quad read/write functions for X.
+ */
+struct pipe_surface *
+xmesa_new_color_surface(struct pipe_context *pipe, GLuint pipeFormat)
+{
+   struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
+
+   assert(pipeFormat);
+
+   xms->surface.format = pipeFormat;
+   xms->surface.refcount = 1;
+
+   /* Note, the region we allocate doesn't actually have any storage
+    * since we're drawing into an XImage or Pixmap.
+    * The region's size will get set in the xmesa_alloc_front/back_storage()
+    * functions.
+    */
+   if (pipe)
+      xms->surface.region = pipe->winsys->region_alloc(pipe->winsys,
+                                                       1, 0, 0, 0x0);
+
+   return &xms->surface;
+}
+
+
+/**
+ * Called via pipe->surface_alloc() to create new surfaces (textures,
+ * renderbuffers, etc.
+ */
+struct pipe_surface *
+xmesa_surface_alloc(struct pipe_context *pipe, GLuint pipeFormat)
+{
+   struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
+
+   assert(pipe);
+   assert(pipeFormat);
+
+   xms->surface.format = pipeFormat;
+   xms->surface.refcount = 1;
+
+   return &xms->surface;
+}
+
+
+boolean
+xmesa_is_format_supported(struct pipe_context *pipe, uint format)
+{
+   switch( format ) {
+   case PIPE_FORMAT_U_A8_R8_G8_B8:
+   case PIPE_FORMAT_S_R16_G16_B16_A16:
+   case PIPE_FORMAT_S8_Z24:
+      return TRUE;
+   };
+   return FALSE;
+}
+
+
+/**
+ * Called via pipe->clear()
+ */
+void
+xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, GLuint value)
+{
+   struct xmesa_renderbuffer *xrb = xmesa_rb(ps);
+
+   /* XXX actually, we should just discard any cached tiles from this
+    * surface since we don't want to accidentally re-use them after clearing.
+    */
+   pipe->flush(pipe, 0);
+
+   {
+      struct softpipe_context *sp = softpipe_context(pipe);
+      if (ps == sp_tile_cache_get_surface(sp->cbuf_cache[0])) {
+         float clear[4];
+         clear[0] = 0.2; /* XXX hack */
+         clear[1] = 0.2;
+         clear[2] = 0.2;
+         clear[3] = 0.2;
+         sp_tile_cache_clear(sp->cbuf_cache[0], clear);
+      }
+   }
+
+   if (xrb && xrb->ximage) {
+      /* clearing back color buffer */
+      GET_CURRENT_CONTEXT(ctx);
+      xmesa_clear_buffers(ctx, BUFFER_BIT_BACK_LEFT);
+   }
+   else if (xrb && xrb->pixmap) {
+      /* clearing front color buffer */
+      GET_CURRENT_CONTEXT(ctx);
+      xmesa_clear_buffers(ctx, BUFFER_BIT_FRONT_LEFT);
+   }
+   else {
+      /* clearing other buffer */
+      softpipe_clear(pipe, ps, value);
+   }
+}
+
diff --git a/src/mesa/pipe/xlib/xm_tri.c b/src/mesa/pipe/xlib/xm_tri.c
new file mode 100644 (file)
index 0000000..9f17083
--- /dev/null
@@ -0,0 +1,1694 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * 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 file contains "accelerated" triangle functions.  It should be
+ * fairly easy to write new special-purpose triangle functions and hook
+ * them into this module.
+ */
+
+
+#include "glxheader.h"
+#include "depth.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "xmesaP.h"
+
+/* Internal swrast includes:
+ */
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_triangle.h"
+
+
+#define GET_XRB(XRB)  struct xmesa_renderbuffer *XRB = \
+   xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped)
+
+
+/**********************************************************************/
+/***                   Triangle rendering                           ***/
+/**********************************************************************/
+
+
+#if CHAN_BITS == 8
+
+/*
+ * XImage, smooth, depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME smooth_TRUECOLOR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+
+#define RENDER_SPAN( span )                                    \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUECOLOR(p, FixedToInt(span.red),               \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         XMesaPutPixel(xrb->ximage, x, y, p);                  \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
+#include "swrast/s_tritemp.h"
+
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME smooth_8A8B8G8R_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_8A8B8G8R(FixedToInt(span.red),         \
+            FixedToInt(span.green), FixedToInt(span.blue),     \
+            FixedToInt(span.alpha));                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+      span.z += span.zStep;                                    \
+   }
+
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME smooth_8A8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_8A8R8G8B(FixedToInt(span.red),         \
+            FixedToInt(span.green), FixedToInt(span.blue),     \
+            FixedToInt(span.alpha));                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+      span.z += span.zStep;                                    \
+   }
+
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_8R8G8B(FixedToInt(span.red),           \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME smooth_8R8G8B24_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        PIXEL_TYPE *ptr = pRow + i;                            \
+         ptr->r = FixedToInt(span.red);                                \
+         ptr->g = FixedToInt(span.green);                      \
+         ptr->b = FixedToInt(span.blue);                       \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME smooth_TRUEDITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUEDITHER(p, x, y, FixedToInt(span.red),                \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         XMesaPutPixel(xrb->ximage, x, y, p);                  \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME smooth_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_5R6G5B(FixedToInt(span.red),           \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME smooth_DITHER_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red),  \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+ */
+#define NAME smooth_DITHER8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),\
+            FixedToInt(span.green), FixedToInt(span.blue) );   \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p = XDITHER(x, FixedToInt(span.red),    \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+        XMesaPutPixel(img, x, y, p);                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME smooth_LOOKUP8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   LOOKUP_SETUP;                                               \
+   for (i = 0; i < span.end; i++) {                            \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = LOOKUP(FixedToInt(span.red),                        \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME smooth_HPCR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red),     \
+            FixedToInt(span.green), FixedToInt(span.blue) );   \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME flat_TRUECOLOR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;                              \
+   unsigned long pixel;                                                \
+   PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         XMesaPutPixel(img, x, y, pixel);                      \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME flat_8A8B8G8R_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   GLuint p = PACK_8A8B8G8R( v2->color[0], v2->color[1],\
+                             v2->color[2], v2->color[3]);
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        pRow[i] = (PIXEL_TYPE) p;                      \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME flat_8A8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   GLuint p = PACK_8A8R8G8B(v2->color[0], v2->color[1],        \
+                            v2->color[2], v2->color[3]);
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        pRow[i] = (PIXEL_TYPE) p;                      \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME flat_8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   GLuint p = PACK_8R8G8B( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.end; i++) {            \
+      DEPTH_TYPE z = FixedToDepth(span.z);     \
+      if (z < zRow[i]) {                       \
+        pRow[i] = (PIXEL_TYPE) p;              \
+         zRow[i] = z;                          \
+      }                                                \
+      span.z += span.zStep;                    \
+   }
+
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME flat_8R8G8B24_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   const GLubyte *color = v2->color;
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        PIXEL_TYPE *ptr = pRow + i;                    \
+         ptr->r = color[RCOMP];                                \
+         ptr->g = color[GCOMP];                                \
+         ptr->b = color[BCOMP];                                \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME flat_TRUEDITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUEDITHER(p, x, y, v2->color[0],                        \
+            v2->color[1], v2->color[2]);                       \
+         XMesaPutPixel(img, x, y, p);                          \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME flat_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   GLushort p = PACK_5R6G5B( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        pRow[i] = (PIXEL_TYPE) p;                      \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME flat_DITHER_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = v2->color;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP],           \
+                        color[GCOMP], color[BCOMP]);           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME flat_DITHER8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);                   \
+   FLAT_DITHER_ROW_SETUP(YFLIP(xrb, y));                       \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x);                 \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_DITHER triangle.
+ */
+#define NAME flat_DITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                       \
+   XMesaImage *img = xrb->ximage;              \
+   FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   FLAT_DITHER_ROW_SETUP(y);                                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p = FLAT_DITHER(x);                     \
+        XMesaPutPixel(img, x, y, p);                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME flat_HPCR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   GLubyte r = v2->color[0];                                   \
+   GLubyte g = v2->color[1];                                   \
+   GLubyte b = v2->color[2];
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b);     \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME flat_LOOKUP8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   LOOKUP_SETUP;                                       \
+   GLubyte r = v2->color[0];                           \
+   GLubyte g = v2->color[1];                           \
+   GLubyte b = v2->color[2];                           \
+   GLubyte p = LOOKUP(r,g,b);
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        pRow[i] = p;                                   \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME smooth_TRUECOLOR_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      unsigned long p;                                         \
+      PACK_TRUECOLOR(p, FixedToInt(span.red),                  \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      XMesaPutPixel(img, x, y, p);                             \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME smooth_8A8B8G8R_triangle
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      pRow[i] = PACK_8A8B8G8R(FixedToInt(span.red),            \
+         FixedToInt(span.green), FixedToInt(span.blue),                \
+         FixedToInt(span.alpha));                              \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME smooth_8A8R8G8B_triangle
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      pRow[i] = PACK_8A8R8G8B(FixedToInt(span.red),            \
+         FixedToInt(span.green), FixedToInt(span.blue),                \
+         FixedToInt(span.alpha));                              \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      pRow[i] = PACK_8R8G8B(FixedToInt(span.red),              \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B24_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   PIXEL_TYPE *pixel = pRow;                           \
+   for (i = 0; i < span.end; i++, pixel++) {           \
+      pixel->r = FixedToInt(span.red);                 \
+      pixel->g = FixedToInt(span.green);               \
+      pixel->b = FixedToInt(span.blue);                        \
+      span.red += span.redStep;                                \
+      span.green += span.greenStep;                    \
+      span.blue += span.blueStep;                      \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME smooth_TRUEDITHER_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      unsigned long p;                                         \
+      PACK_TRUEDITHER(p, x, y, FixedToInt(span.red),           \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      XMesaPutPixel(img, x, y, p );                            \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME smooth_5R6G5B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.end; i++) {                            \
+      pRow[i] = (PIXEL_TYPE) PACK_5R6G5B(FixedToInt(span.red), \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME smooth_DITHER_5R6G5B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red),     \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER8_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),  \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      unsigned long p = XDITHER(x, FixedToInt(span.red),       \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      XMesaPutPixel(img, x, y, p);                             \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME smooth_LOOKUP8_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   LOOKUP_SETUP;                                               \
+   for (i = 0; i < span.end; i++) {                            \
+      pRow[i] = LOOKUP(FixedToInt(span.red),                   \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME smooth_HPCR_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red),                \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME flat_TRUECOLOR_triangle
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;                              \
+   unsigned long pixel;                                                \
+   PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      XMesaPutPixel(img, x, y, pixel);                         \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME flat_8A8B8G8R_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   unsigned long p = PACK_8B8G8R( v2->color[0],                \
+                v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      pRow[i] = (PIXEL_TYPE) p;                                \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME flat_8A8R8G8B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   unsigned long p = PACK_8R8G8B( v2->color[0],                \
+                v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      pRow[i] = (PIXEL_TYPE) p;                                \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME flat_8R8G8B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   unsigned long p = PACK_8R8G8B( v2->color[0],                \
+                v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      pRow[i] = (PIXEL_TYPE) p;                                \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME flat_8R8G8B24_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   const GLubyte *color = v2->color;
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   PIXEL_TYPE *pixel = pRow;                           \
+   for (i = 0; i < span.end; i++, pixel++) {           \
+      pixel->r = color[RCOMP];                         \
+      pixel->g = color[GCOMP];                         \
+      pixel->b = color[BCOMP];                         \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME flat_TRUEDITHER_triangle
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      unsigned long p;                                         \
+      PACK_TRUEDITHER(p, x, y, v2->color[0],                   \
+               v2->color[1], v2->color[2] );                   \
+      XMesaPutPixel(img, x, y, p);                             \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME flat_5R6G5B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   unsigned long p = PACK_5R6G5B( v2->color[0],                \
+                v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      pRow[i] = (PIXEL_TYPE) p;                                \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME flat_DITHER_5R6G5B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   const GLubyte *color = v2->color;
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP],             \
+         color[GCOMP], color[BCOMP]);                          \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME flat_DITHER8_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   FLAT_DITHER_ROW_SETUP(YFLIP(xrb, y));               \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x);                   \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_DITHER triangle.
+ */
+#define NAME flat_DITHER_triangle
+#define SETUP_CODE                                             \
+   GET_XRB(xrb);                                               \
+   XMesaImage *img = xrb->ximage;                              \
+   FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   FLAT_DITHER_ROW_SETUP(y);                                   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      unsigned long p = FLAT_DITHER(x);                                \
+      XMesaPutPixel(img, x, y, p );                            \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME flat_HPCR_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                             \
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);                    \
+   GET_XRB(xrb);                                               \
+   GLubyte r = v2->color[0];                                   \
+   GLubyte g = v2->color[1];                                   \
+   GLubyte b = v2->color[2];
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = YFLIP(xrb, span.y);   \
+   for (i = 0; i < span.end; i++, x++) {                       \
+      pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b);       \
+   }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME flat_LOOKUP8_triangle
+#define PIXEL_ADDRESS(X,Y) PIXEL_ADDR1(xrb, X, Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
+#define SETUP_CODE                                     \
+   GET_XRB(xrb);                                       \
+   LOOKUP_SETUP;                                       \
+   GLubyte r = v2->color[0];                           \
+   GLubyte g = v2->color[1];                           \
+   GLubyte b = v2->color[2];                           \
+   GLubyte p = LOOKUP(r,g,b);
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.end; i++) {                    \
+      pRow[i] = (PIXEL_TYPE) p;                                \
+   }
+#include "swrast/s_tritemp.h"
+
+
+#endif /* CHAN_BITS == 8 */
+
+
+#if defined(DEBUG) && CHAN_BITS == 8
+extern void _xmesa_print_triangle_func( swrast_tri_func triFunc );
+void _xmesa_print_triangle_func( swrast_tri_func triFunc )
+{
+   _mesa_printf("XMesa tri func = ");
+   if (triFunc ==smooth_TRUECOLOR_z_triangle)
+      _mesa_printf("smooth_TRUECOLOR_z_triangle\n");
+   else if (triFunc ==smooth_8A8B8G8R_z_triangle)
+      _mesa_printf("smooth_8A8B8G8R_z_triangle\n");
+   else if (triFunc ==smooth_8A8R8G8B_z_triangle)
+      _mesa_printf("smooth_8A8R8G8B_z_triangle\n");
+   else if (triFunc ==smooth_8R8G8B_z_triangle)
+      _mesa_printf("smooth_8R8G8B_z_triangle\n");
+   else if (triFunc ==smooth_8R8G8B24_z_triangle)
+      _mesa_printf("smooth_8R8G8B24_z_triangle\n");
+   else if (triFunc ==smooth_TRUEDITHER_z_triangle)
+      _mesa_printf("smooth_TRUEDITHER_z_triangle\n");
+   else if (triFunc ==smooth_5R6G5B_z_triangle)
+      _mesa_printf("smooth_5R6G5B_z_triangle\n");
+   else if (triFunc ==smooth_DITHER_5R6G5B_z_triangle)
+      _mesa_printf("smooth_DITHER_5R6G5B_z_triangle\n");
+   else if (triFunc ==smooth_HPCR_z_triangle)
+      _mesa_printf("smooth_HPCR_z_triangle\n");
+   else if (triFunc ==smooth_DITHER8_z_triangle)
+      _mesa_printf("smooth_DITHER8_z_triangle\n");
+   else if (triFunc ==smooth_LOOKUP8_z_triangle)
+      _mesa_printf("smooth_LOOKUP8_z_triangle\n");
+   else if (triFunc ==flat_TRUECOLOR_z_triangle)
+      _mesa_printf("flat_TRUECOLOR_z_triangle\n");
+   else if (triFunc ==flat_8A8B8G8R_z_triangle)
+      _mesa_printf("flat_8A8B8G8R_z_triangle\n");
+   else if (triFunc ==flat_8A8R8G8B_z_triangle)
+      _mesa_printf("flat_8A8R8G8B_z_triangle\n");
+   else if (triFunc ==flat_8R8G8B_z_triangle)
+      _mesa_printf("flat_8R8G8B_z_triangle\n");
+   else if (triFunc ==flat_8R8G8B24_z_triangle)
+      _mesa_printf("flat_8R8G8B24_z_triangle\n");
+   else if (triFunc ==flat_TRUEDITHER_z_triangle)
+      _mesa_printf("flat_TRUEDITHER_z_triangle\n");
+   else if (triFunc ==flat_5R6G5B_z_triangle)
+      _mesa_printf("flat_5R6G5B_z_triangle\n");
+   else if (triFunc ==flat_DITHER_5R6G5B_z_triangle)
+      _mesa_printf("flat_DITHER_5R6G5B_z_triangle\n");
+   else if (triFunc ==flat_HPCR_z_triangle)
+      _mesa_printf("flat_HPCR_z_triangle\n");
+   else if (triFunc ==flat_DITHER8_z_triangle)
+      _mesa_printf("flat_DITHER8_z_triangle\n");
+   else if (triFunc ==flat_LOOKUP8_z_triangle)
+      _mesa_printf("flat_LOOKUP8_z_triangle\n");
+   else if (triFunc ==smooth_TRUECOLOR_triangle)
+      _mesa_printf("smooth_TRUECOLOR_triangle\n");
+   else if (triFunc ==smooth_8A8B8G8R_triangle)
+      _mesa_printf("smooth_8A8B8G8R_triangle\n");
+   else if (triFunc ==smooth_8A8R8G8B_triangle)
+      _mesa_printf("smooth_8A8R8G8B_triangle\n");
+   else if (triFunc ==smooth_8R8G8B_triangle)
+      _mesa_printf("smooth_8R8G8B_triangle\n");
+   else if (triFunc ==smooth_8R8G8B24_triangle)
+      _mesa_printf("smooth_8R8G8B24_triangle\n");
+   else if (triFunc ==smooth_TRUEDITHER_triangle)
+      _mesa_printf("smooth_TRUEDITHER_triangle\n");
+   else if (triFunc ==smooth_5R6G5B_triangle)
+      _mesa_printf("smooth_5R6G5B_triangle\n");
+   else if (triFunc ==smooth_DITHER_5R6G5B_triangle)
+      _mesa_printf("smooth_DITHER_5R6G5B_triangle\n");
+   else if (triFunc ==smooth_HPCR_triangle)
+      _mesa_printf("smooth_HPCR_triangle\n");
+   else if (triFunc ==smooth_DITHER8_triangle)
+      _mesa_printf("smooth_DITHER8_triangle\n");
+   else if (triFunc ==smooth_LOOKUP8_triangle)
+      _mesa_printf("smooth_LOOKUP8_triangle\n");
+   else if (triFunc ==flat_TRUECOLOR_triangle)
+      _mesa_printf("flat_TRUECOLOR_triangle\n");
+   else if (triFunc ==flat_TRUEDITHER_triangle)
+      _mesa_printf("flat_TRUEDITHER_triangle\n");
+   else if (triFunc ==flat_8A8B8G8R_triangle)
+      _mesa_printf("flat_8A8B8G8R_triangle\n");
+   else if (triFunc ==flat_8A8R8G8B_triangle)
+      _mesa_printf("flat_8A8R8G8B_triangle\n");
+   else if (triFunc ==flat_8R8G8B_triangle)
+      _mesa_printf("flat_8R8G8B_triangle\n");
+   else if (triFunc ==flat_8R8G8B24_triangle)
+      _mesa_printf("flat_8R8G8B24_triangle\n");
+   else if (triFunc ==flat_5R6G5B_triangle)
+      _mesa_printf("flat_5R6G5B_triangle\n");
+   else if (triFunc ==flat_DITHER_5R6G5B_triangle)
+      _mesa_printf("flat_DITHER_5R6G5B_triangle\n");
+   else if (triFunc ==flat_HPCR_triangle)
+      _mesa_printf("flat_HPCR_triangle\n");
+   else if (triFunc ==flat_DITHER8_triangle)
+      _mesa_printf("flat_DITHER8_triangle\n");
+   else if (triFunc ==flat_LOOKUP8_triangle)
+      _mesa_printf("flat_LOOKUP8_triangle\n");
+   else
+      _mesa_printf("???\n");
+}
+#endif
+
+
+#ifdef DEBUG
+
+/* record the current triangle function name */
+static const char *triFuncName = NULL;
+
+#define USE(triFunc)                   \
+do {                                   \
+    triFuncName = #triFunc;            \
+    return triFunc;                    \
+} while (0)
+
+#else
+
+#define USE(triFunc)  return triFunc
+
+#endif
+
+
+#if 0
+GLboolean xmesa_get_cbuf_details( GLcontext *ctx,
+                                 void **ptr,
+                                 GLuint *cpp,
+                                 GLint *stride,
+                                 GLuint *format )
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   struct gl_renderbuffer *crb = fb->_ColorDrawBuffers[0][0];
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(crb->Wrapped);
+
+   *ptr = crb->GetPointer(ctx, crb, 0, 0);
+   *stride = ((GLubyte *)crb->GetPointer(ctx, crb, 0, 1) - 
+             (GLubyte *)crb->GetPointer(ctx, crb, 0, 0));
+
+   if (!ptr) 
+      goto bad;
+
+   switch (xmesa->pixelformat) {
+   case PF_8A8B8G8R:
+   case PF_8A8R8G8B:
+      *format = 1;             /* whatever */
+      *cpp = 4;
+      break;
+   default:
+      goto bad;
+   }
+
+   return GL_TRUE;
+
+ bad:
+   *ptr = NULL;
+   *stride = 0;
+   *format = 0;
+   return GL_FALSE;   
+}
+#endif
+
+
+/**
+ * Return pointer to line drawing function, or NULL if we should use a
+ * swrast fallback.
+ */
+static swrast_tri_func
+get_triangle_func(GLcontext *ctx)
+{
+#if CHAN_BITS == 8
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
+   const int depth = GET_VISUAL_DEPTH(xmesa->xm_visual);
+   const struct xmesa_renderbuffer *xrb;
+
+#ifdef DEBUG
+   triFuncName = NULL;
+#endif
+
+   /* trivial fallback tests */
+   if ((ctx->DrawBuffer->_ColorDrawBufferMask[0]
+        & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0)
+      return (swrast_tri_func) NULL;
+   if (ctx->RenderMode != GL_RENDER)
+      return (swrast_tri_func) NULL;
+   if (ctx->Polygon.SmoothFlag)
+      return (swrast_tri_func) NULL;
+   if (ctx->Texture._EnabledUnits)
+      return (swrast_tri_func) NULL;
+   if (swrast->_RasterMask & MULTI_DRAW_BIT)
+      return (swrast_tri_func) NULL;
+   if (ctx->Polygon.CullFlag && 
+       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+      return (swrast_tri_func) NULL;
+   if (xmbuf->swAlpha)
+      return (swrast_tri_func) NULL;
+
+   xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
+
+   if (xrb->ximage) {
+      if (   ctx->Light.ShadeModel==GL_SMOOTH
+          && swrast->_RasterMask==DEPTH_BIT
+          && ctx->Depth.Func==GL_LESS
+          && ctx->Depth.Mask==GL_TRUE
+          && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+          && ctx->Polygon.StippleFlag==GL_FALSE) {
+         switch (xmesa->pixelformat) {
+            case PF_Truecolor:
+              USE(smooth_TRUECOLOR_z_triangle);
+            case PF_8A8B8G8R:
+               USE(smooth_8A8B8G8R_z_triangle);
+            case PF_8A8R8G8B:
+               USE(smooth_8A8R8G8B_z_triangle);
+            case PF_8R8G8B:
+               USE(smooth_8R8G8B_z_triangle);
+            case PF_8R8G8B24:
+               USE(smooth_8R8G8B24_z_triangle);
+            case PF_Dither_True:
+               USE(smooth_TRUEDITHER_z_triangle);
+            case PF_5R6G5B:
+               USE(smooth_5R6G5B_z_triangle);
+            case PF_Dither_5R6G5B:
+               USE(smooth_DITHER_5R6G5B_z_triangle);
+            case PF_HPCR:
+              USE(smooth_HPCR_z_triangle);
+            case PF_Dither:
+               if (depth == 8)
+                  USE(smooth_DITHER8_z_triangle);
+               else
+                  USE(smooth_DITHER_z_triangle);
+            case PF_Lookup:
+               if (depth == 8)
+                  USE(smooth_LOOKUP8_z_triangle);
+               else
+                  return (swrast_tri_func) NULL;
+            default:
+               return (swrast_tri_func) NULL;
+         }
+      }
+      if (   ctx->Light.ShadeModel==GL_FLAT
+          && swrast->_RasterMask==DEPTH_BIT
+          && ctx->Depth.Func==GL_LESS
+          && ctx->Depth.Mask==GL_TRUE
+          && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+          && ctx->Polygon.StippleFlag==GL_FALSE) {
+         switch (xmesa->pixelformat) {
+            case PF_Truecolor:
+              USE(flat_TRUECOLOR_z_triangle);
+            case PF_8A8B8G8R:
+               USE(flat_8A8B8G8R_z_triangle);
+            case PF_8A8R8G8B:
+               USE(flat_8A8R8G8B_z_triangle);
+            case PF_8R8G8B:
+               USE(flat_8R8G8B_z_triangle);
+            case PF_8R8G8B24:
+               USE(flat_8R8G8B24_z_triangle);
+            case PF_Dither_True:
+               USE(flat_TRUEDITHER_z_triangle);
+            case PF_5R6G5B:
+               USE(flat_5R6G5B_z_triangle);
+            case PF_Dither_5R6G5B:
+               USE(flat_DITHER_5R6G5B_z_triangle);
+            case PF_HPCR:
+              USE(flat_HPCR_z_triangle);
+            case PF_Dither:
+               if (depth == 8)
+                  USE(flat_DITHER8_z_triangle);
+               else
+                  USE(flat_DITHER_z_triangle);
+            case PF_Lookup:
+               if (depth == 8)
+                  USE(flat_LOOKUP8_z_triangle);
+               else
+                  return (swrast_tri_func) NULL;
+            default:
+               return (swrast_tri_func) NULL;
+         }
+      }
+      if (   swrast->_RasterMask==0   /* no depth test */
+          && ctx->Light.ShadeModel==GL_SMOOTH
+          && ctx->Polygon.StippleFlag==GL_FALSE) {
+         switch (xmesa->pixelformat) {
+            case PF_Truecolor:
+              USE(smooth_TRUECOLOR_triangle);
+            case PF_8A8B8G8R:
+               USE(smooth_8A8B8G8R_triangle);
+            case PF_8A8R8G8B:
+               USE(smooth_8A8R8G8B_triangle);
+            case PF_8R8G8B:
+               USE(smooth_8R8G8B_triangle);
+            case PF_8R8G8B24:
+               USE(smooth_8R8G8B24_triangle);
+            case PF_Dither_True:
+               USE(smooth_TRUEDITHER_triangle);
+            case PF_5R6G5B:
+               USE(smooth_5R6G5B_triangle);
+            case PF_Dither_5R6G5B:
+               USE(smooth_DITHER_5R6G5B_triangle);
+            case PF_HPCR:
+              USE(smooth_HPCR_triangle);
+            case PF_Dither:
+               if (depth == 8)
+                  USE(smooth_DITHER8_triangle);
+               else
+                  USE(smooth_DITHER_triangle);
+            case PF_Lookup:
+               if (depth == 8)
+                  USE(smooth_LOOKUP8_triangle);
+               else
+                  return (swrast_tri_func) NULL;
+            default:
+               return (swrast_tri_func) NULL;
+         }
+      }
+
+      if (   swrast->_RasterMask==0   /* no depth test */
+          && ctx->Light.ShadeModel==GL_FLAT
+          && ctx->Polygon.StippleFlag==GL_FALSE) {
+         switch (xmesa->pixelformat) {
+            case PF_Truecolor:
+              USE(flat_TRUECOLOR_triangle);
+            case PF_Dither_True:
+              USE(flat_TRUEDITHER_triangle);
+            case PF_8A8B8G8R:
+               USE(flat_8A8B8G8R_triangle);
+            case PF_8A8R8G8B:
+               USE(flat_8A8R8G8B_triangle);
+            case PF_8R8G8B:
+               USE(flat_8R8G8B_triangle);
+            case PF_8R8G8B24:
+               USE(flat_8R8G8B24_triangle);
+            case PF_5R6G5B:
+               USE(flat_5R6G5B_triangle);
+            case PF_Dither_5R6G5B:
+               USE(flat_DITHER_5R6G5B_triangle);
+            case PF_HPCR:
+              USE(flat_HPCR_triangle);
+            case PF_Dither:
+               if (depth == 8)
+                  USE(flat_DITHER8_triangle);
+               else
+                  USE(flat_DITHER_triangle);
+            case PF_Lookup:
+               if (depth == 8)
+                  USE(flat_LOOKUP8_triangle);
+               else
+                  return (swrast_tri_func) NULL;
+            default:
+               return (swrast_tri_func) NULL;
+         }
+      }
+   }
+#endif /* CHAN_BITS == 8 */
+
+   return (swrast_tri_func) NULL;
+}
+
+
+/* Override for the swrast tri-selection function.  Try to use one
+ * of our internal tri functions, otherwise fall back to the
+ * standard swrast functions.
+ */
+void xmesa_choose_triangle( GLcontext *ctx )
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+   if (!(swrast->Triangle = get_triangle_func( ctx )))
+      _swrast_choose_triangle( ctx );
+}
+
diff --git a/src/mesa/pipe/xlib/xm_winsys.c b/src/mesa/pipe/xlib/xm_winsys.c
new file mode 100644 (file)
index 0000000..3680543
--- /dev/null
@@ -0,0 +1,368 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell
+ *   Brian Paul
+ */
+
+
+#include "glxheader.h"
+#include "xmesaP.h"
+#include "main/macros.h"
+
+#include "pipe/p_winsys.h"
+#include "pipe/softpipe/sp_winsys.h"
+
+
+/**
+ * XMesa winsys, derived from softpipe winsys.
+ * NOTE: there's nothing really X-specific in this winsys layer so
+ * we could probably lift it up somewhere.
+ */
+struct xm_winsys
+{
+   struct softpipe_winsys sws;
+   int foo; /* placeholder */
+};
+
+
+/**
+ * Low-level OS/window system memory buffer
+ */
+struct xm_buffer
+{
+   boolean userBuffer;  /** Is this a user-space buffer? */
+   int refcount;
+   unsigned size;
+   void *data;
+   void *mapped;
+};
+
+
+
+/* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
+ * buffer pointer...
+ */
+static inline struct xm_buffer *
+xm_bo( struct pipe_buffer_handle *bo )
+{
+   return (struct xm_buffer *) bo;
+}
+
+static inline struct pipe_buffer_handle *
+pipe_bo( struct xm_buffer *bo )
+{
+   return (struct pipe_buffer_handle *) bo;
+}
+
+/* Turn a softpipe winsys into an xm/softpipe winsys:
+ */
+static inline struct xm_winsys *
+xm_winsys(struct softpipe_winsys *sws)
+{
+   return (struct xm_winsys *) sws;
+}
+
+
+/* Most callbacks map direcly onto dri_bufmgr operations:
+ */
+static void *
+xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
+              unsigned flags)
+{
+   struct xm_buffer *xm_buf = xm_bo(buf);
+   xm_buf->mapped = xm_buf->data;
+   return xm_buf->mapped;
+}
+
+static void
+xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer_handle *buf)
+{
+   struct xm_buffer *xm_buf = xm_bo(buf);
+   xm_buf->mapped = NULL;
+}
+
+static void
+xm_buffer_reference(struct pipe_winsys *pws,
+                    struct pipe_buffer_handle **ptr,
+                    struct pipe_buffer_handle *buf)
+{
+   if (*ptr) {
+      struct xm_buffer *oldBuf = xm_bo(*ptr);
+      oldBuf->refcount--;
+      assert(oldBuf->refcount >= 0);
+      if (oldBuf->refcount == 0) {
+         if (oldBuf->data) {
+            if (!oldBuf->userBuffer)
+               free(oldBuf->data);
+            oldBuf->data = NULL;
+         }
+         free(oldBuf);
+      }
+      *ptr = NULL;
+   }
+
+   assert(!(*ptr));
+
+   if (buf) {
+      struct xm_buffer *newBuf = xm_bo(buf);
+      newBuf->refcount++;
+      *ptr = buf;
+   }
+}
+
+static void
+xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
+               unsigned size, const void *data )
+{
+   struct xm_buffer *xm_buf = xm_bo(buf);
+   assert(!xm_buf->userBuffer);
+   if (xm_buf->size != size) {
+      if (xm_buf->data)
+         free(xm_buf->data);
+      xm_buf->data = malloc(size);
+      xm_buf->size = size;
+   }
+   if (data)
+      memcpy(xm_buf->data, data, size);
+}
+
+static void
+xm_buffer_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
+                  unsigned long offset, unsigned long size, const void *data)
+{
+   struct xm_buffer *xm_buf = xm_bo(buf);
+   GLubyte *b = (GLubyte *) xm_buf->data;
+   assert(!xm_buf->userBuffer);
+   assert(b);
+   memcpy(b + offset, data, size);
+}
+
+static void
+xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
+                      unsigned long offset, unsigned long size, void *data)
+{
+   const struct xm_buffer *xm_buf = xm_bo(buf);
+   const GLubyte *b = (GLubyte *) xm_buf->data;
+   assert(!xm_buf->userBuffer);
+   assert(b);
+   memcpy(data, b + offset, size);
+}
+
+static void
+xm_flush_frontbuffer(struct pipe_winsys *pws)
+{
+   /*
+   struct intel_context *intel = intel_pipe_winsys(sws)->intel;
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   
+   intelCopyBuffer(dPriv, NULL);
+   */
+}
+
+static void
+xm_wait_idle(struct pipe_winsys *pws)
+{
+   /* no-op */
+}
+
+static void
+xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
+{
+   va_list args;
+   va_start( args, fmtString );  
+   vfprintf(stderr, fmtString, args);
+   va_end( args );
+}
+
+static const char *
+xm_get_name(struct pipe_winsys *pws)
+{
+   return "Xlib";
+}
+
+
+static struct pipe_buffer_handle *
+xm_buffer_create(struct pipe_winsys *pws, unsigned alignment)
+{
+   struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+   buffer->refcount = 1;
+   return pipe_bo(buffer);
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer_handle *
+xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+   struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+   buffer->userBuffer = TRUE;
+   buffer->refcount = 1;
+   buffer->data = ptr;
+   buffer->size = bytes;
+   return pipe_bo(buffer);
+}
+
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+   return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+static struct pipe_region *
+xm_region_alloc(struct pipe_winsys *winsys,
+                unsigned cpp, unsigned width, unsigned height, unsigned flags)
+{
+   struct pipe_region *region = CALLOC_STRUCT(pipe_region);
+   const unsigned alignment = 64;
+
+   region->cpp = cpp;
+   region->pitch = round_up(width, alignment / cpp);
+   region->height = height;
+   region->refcount = 1;
+
+   assert(region->pitch > 0);
+
+   region->buffer = winsys->buffer_create( winsys, alignment )
+;
+
+   /* NULL data --> just allocate the space */
+   winsys->buffer_data( winsys,
+                        region->buffer, 
+                        region->pitch * cpp * height, 
+                        NULL );
+   return region;
+}
+
+
+static void
+xm_region_release(struct pipe_winsys *winsys, struct pipe_region **region)
+{
+   if (!*region)
+      return;
+
+   assert((*region)->refcount > 0);
+   (*region)->refcount--;
+
+   if ((*region)->refcount == 0) {
+      assert((*region)->map_refcount == 0);
+
+      winsys->buffer_reference( winsys, &((*region)->buffer), NULL );
+      free(*region);
+   }
+   *region = NULL;
+}
+
+
+/**
+ * Called via pipe->surface_alloc() to create new surfaces (textures,
+ * renderbuffers, etc.
+ */
+static struct pipe_surface *
+xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
+{
+   struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
+
+   assert(ws);
+   assert(pipeFormat);
+
+   xms->surface.format = pipeFormat;
+   xms->surface.refcount = 1;
+#if 0
+   /*
+    * This is really just a softpipe surface, not an XImage/Pixmap surface.
+    */
+   softpipe_init_surface_funcs(&xms->surface);
+#endif
+   return &xms->surface;
+}
+
+
+
+
+struct xmesa_pipe_winsys
+{
+   struct pipe_winsys winsys;
+   XMesaContext xmesa;
+};
+
+static struct pipe_winsys *
+xmesa_create_pipe_winsys( XMesaContext xmesa )
+{
+   struct xmesa_pipe_winsys *xws = CALLOC_STRUCT(xmesa_pipe_winsys);
+   
+   /* Fill in this struct with callbacks that pipe will need to
+    * communicate with the window system, buffer manager, etc. 
+    *
+    * Pipe would be happy with a malloc based memory manager, but
+    * the SwapBuffers implementation in this winsys driver requires
+    * that rendering be done to an appropriate _DriBufferObject.  
+    */
+   xws->winsys.buffer_create = xm_buffer_create;
+   xws->winsys.user_buffer_create = xm_user_buffer_create;
+   xws->winsys.buffer_map = xm_buffer_map;
+   xws->winsys.buffer_unmap = xm_buffer_unmap;
+   xws->winsys.buffer_reference = xm_buffer_reference;
+   xws->winsys.buffer_data = xm_buffer_data;
+   xws->winsys.buffer_subdata = xm_buffer_subdata;
+   xws->winsys.buffer_get_subdata = xm_buffer_get_subdata;
+
+   xws->winsys.region_alloc = xm_region_alloc;
+   xws->winsys.region_release = xm_region_release;
+
+   xws->winsys.surface_alloc = xm_surface_alloc;
+
+   xws->winsys.flush_frontbuffer = xm_flush_frontbuffer;
+   xws->winsys.wait_idle = xm_wait_idle;
+   xws->winsys.printf = xm_printf;
+   xws->winsys.get_name = xm_get_name;
+   xws->xmesa = xmesa;
+
+   return &xws->winsys;
+}
+
+
+struct pipe_context *
+xmesa_create_softpipe(XMesaContext xmesa)
+{
+   struct xm_winsys *xm_ws = CALLOC_STRUCT( xm_winsys );
+   
+   /* Create the softpipe context:
+    */
+   return softpipe_create( xmesa_create_pipe_winsys(xmesa), &xm_ws->sws );
+}
diff --git a/src/mesa/pipe/xlib/xmesaP.h b/src/mesa/pipe/xlib/xmesaP.h
new file mode 100644 (file)
index 0000000..5796fdd
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+ * 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.
+ */
+
+
+#ifndef XMESAP_H
+#define XMESAP_H
+
+
+#include "GL/xmesa.h"
+#include "mtypes.h"
+#if defined(FX)
+#include "GL/fxmesa.h"
+#endif
+#ifdef XFree86Server
+#include "xm_image.h"
+#endif
+#include "state_tracker/st_cb_fbo.h"
+#include "pipe/softpipe/sp_context.h"
+#include "pipe/softpipe/sp_surface.h"
+
+
+extern _glthread_Mutex _xmesa_lock;
+
+extern XMesaBuffer XMesaBufferList;
+
+/* for PF_8R8G8B24 pixel format */
+typedef struct {
+   GLubyte b;
+   GLubyte g;
+   GLubyte r;
+} bgr_t;
+
+
+struct xmesa_renderbuffer;
+
+
+/* Function pointer for clearing color buffers */
+typedef void (*ClearFunc)( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
+                           GLint x, GLint y, GLint width, GLint height );
+
+
+
+
+/** Framebuffer pixel formats */
+enum pixel_format {
+   PF_Index,           /**< Color Index mode */
+   PF_Truecolor,       /**< TrueColor or DirectColor, any depth */
+   PF_Dither_True,     /**< TrueColor with dithering */
+   PF_8A8R8G8B,                /**< 32-bit TrueColor:  8-A, 8-R, 8-G, 8-B bits */
+   PF_8A8B8G8R,                /**< 32-bit TrueColor:  8-A, 8-B, 8-G, 8-R bits */
+   PF_8R8G8B,          /**< 32-bit TrueColor:  8-R, 8-G, 8-B bits */
+   PF_8R8G8B24,                /**< 24-bit TrueColor:  8-R, 8-G, 8-B bits */
+   PF_5R6G5B,          /**< 16-bit TrueColor:  5-R, 6-G, 5-B bits */
+   PF_Dither,          /**< Color-mapped RGB with dither */
+   PF_Lookup,          /**< Color-mapped RGB without dither */
+   PF_HPCR,            /**< HP Color Recovery (ad@lms.be 30/08/95) */
+   PF_1Bit,            /**< monochrome dithering of RGB */
+   PF_Grayscale,       /**< Grayscale or StaticGray */
+   PF_Dither_5R6G5B    /**< 16-bit dithered TrueColor: 5-R, 6-G, 5-B */
+};
+
+
+/**
+ * Visual inforation, derived from GLvisual.
+ * Basically corresponds to an XVisualInfo.
+ */
+struct xmesa_visual {
+   GLvisual mesa_visual;       /* Device independent visual parameters */
+   XMesaDisplay *display;      /* The X11 display */
+#ifdef XFree86Server
+   GLint ColormapEntries;
+   GLint nplanes;
+#else
+   XMesaVisualInfo visinfo;    /* X's visual info (pointer to private copy) */
+   XVisualInfo *vishandle;     /* Only used in fakeglx.c */
+#endif
+   GLint BitsPerPixel;         /* True bits per pixel for XImages */
+
+   GLboolean ximage_flag;      /* Use XImage for back buffer (not pixmap)? */
+
+   enum pixel_format dithered_pf;  /* Pixel format when dithering */
+   enum pixel_format undithered_pf;/* Pixel format when not dithering */
+
+   GLfloat RedGamma;           /* Gamma values, 1.0 is default */
+   GLfloat GreenGamma;
+   GLfloat BlueGamma;
+
+   /* For PF_TRUECOLOR */
+   GLint rshift, gshift, bshift;/* Pixel color component shifts */
+   GLubyte Kernel[16];         /* Dither kernel */
+   unsigned long RtoPixel[512];        /* RGB to pixel conversion */
+   unsigned long GtoPixel[512];
+   unsigned long BtoPixel[512];
+   GLubyte PixelToR[256];      /* Pixel to RGB conversion */
+   GLubyte PixelToG[256];
+   GLubyte PixelToB[256];
+
+   /* For PF_HPCR */
+   short       hpcr_rgbTbl[3][256];
+   GLboolean   hpcr_clear_flag;
+   GLubyte     hpcr_clear_ximage_pattern[2][16];
+   XMesaImage *hpcr_clear_ximage;
+   XMesaPixmap hpcr_clear_pixmap;
+
+   /* For PF_1BIT */
+   int bitFlip;
+};
+
+
+/**
+ * Context info, dDerived from GLcontext.
+ * Basically corresponds to a GLXContext.
+ */
+struct xmesa_context {
+   GLcontext mesa;             /* the core library context (containment) */
+   XMesaVisual xm_visual;      /* Describes the buffers */
+   XMesaBuffer xm_buffer;      /* current span/point/line/triangle buffer */
+
+   XMesaDisplay *display;      /* == xm_visual->display */
+   GLboolean swapbytes;                /* Host byte order != display byte order? */
+   GLboolean direct;           /* Direct rendering context? */
+
+   enum pixel_format pixelformat;
+
+   GLubyte clearcolor[4];              /* current clearing color */
+   unsigned long clearpixel;           /* current clearing pixel value */
+};
+
+
+/**
+ * Types of X/GLX drawables we might render into.
+ */
+typedef enum {
+   WINDOW,          /* An X window */
+   GLXWINDOW,       /* GLX window */
+   PIXMAP,          /* GLX pixmap */
+   PBUFFER          /* GLX Pbuffer */
+} BufferType;
+
+
+/** Values for db_mode: */
+/*@{*/
+#define BACK_PIXMAP    1
+#define BACK_XIMAGE    2
+/*@}*/
+
+
+/**
+ * An xmesa_renderbuffer represents the back or front color buffer.
+ * For the front color buffer:
+ *    <drawable> is the X window
+ * For the back color buffer:
+ *    Either <ximage> or <pixmap> will be used, never both.
+ * In any case, <drawable> always equals <pixmap>.
+ * For stand-alone Mesa, we could merge <drawable> and <pixmap> into one
+ * field.  We don't do that for the server-side GLcore module because
+ * pixmaps and drawables are different and we'd need a bunch of casts.
+ */
+struct xmesa_renderbuffer
+{
+#if 0
+   struct gl_renderbuffer Base;  /* Base class */
+#else
+   struct st_renderbuffer St; /**< Base class */
+#endif
+
+   XMesaBuffer Parent;  /**< The XMesaBuffer this renderbuffer belongs to */
+   XMesaDrawable drawable;     /* Usually the X window ID */
+   XMesaPixmap pixmap; /* Back color buffer */
+   XMesaImage *ximage; /* The back buffer, if not using a Pixmap */
+
+   GLubyte *origin1;   /* used for PIXEL_ADDR1 macro */
+   GLint width1;
+   GLushort *origin2;  /* used for PIXEL_ADDR2 macro */
+   GLint width2;
+   GLubyte *origin3;   /* used for PIXEL_ADDR3 macro */
+   GLint width3;
+   GLuint *origin4;    /* used for PIXEL_ADDR4 macro */
+   GLint width4;
+
+   GLint bottom;       /* used for FLIP macro, equals height - 1 */
+
+   ClearFunc clearFunc;
+
+   void *pSurface;      /** pipe surface */
+};
+
+
+/**
+ * Framebuffer information, derived from.
+ * Basically corresponds to a GLXDrawable.
+ */
+struct xmesa_buffer {
+   GLframebuffer mesa_buffer;  /* depth, stencil, accum, etc buffers */
+                               /* This MUST BE FIRST! */
+   GLboolean wasCurrent;       /* was ever the current buffer? */
+   XMesaVisual xm_visual;      /* the X/Mesa visual */
+
+   XMesaDisplay *display;
+   BufferType type;             /* window, pixmap, pbuffer or glxwindow */
+
+   struct xmesa_renderbuffer *frontxrb; /* front color renderbuffer */
+   struct xmesa_renderbuffer *backxrb;  /* back color renderbuffer */
+
+   XMesaColormap cmap;         /* the X colormap */
+
+   unsigned long selectedEvents;/* for pbuffers only */
+
+   GLint db_mode;              /* 0 = single buffered */
+                               /* BACK_PIXMAP = use Pixmap for back buffer */
+                               /* BACK_XIMAGE = use XImage for back buffer */
+   GLboolean swAlpha;
+
+   GLuint shm;                 /* X Shared Memory extension status:    */
+                               /*    0 = not available                 */
+                               /*    1 = XImage support available      */
+                               /*    2 = Pixmap support available too  */
+#if defined(USE_XSHM) && !defined(XFree86Server)
+   XShmSegmentInfo shminfo;
+#endif
+
+   XMesaImage *rowimage;       /* Used for optimized span writing */
+   XMesaPixmap stipple_pixmap; /* For polygon stippling */
+   XMesaGC stipple_gc;         /* For polygon stippling */
+
+   XMesaGC gc;                 /* scratch GC for span, line, tri drawing */
+   XMesaGC cleargc;            /* GC for clearing the color buffer */
+   XMesaGC swapgc;             /* GC for swapping the color buffers */
+
+   /* The following are here instead of in the XMesaVisual
+    * because they depend on the window's colormap.
+    */
+
+   /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+   unsigned long color_table[576];     /* RGB -> pixel value */
+
+   /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+   GLubyte pixel_to_r[65536];          /* pixel value -> red */
+   GLubyte pixel_to_g[65536];          /* pixel value -> green */
+   GLubyte pixel_to_b[65536];          /* pixel value -> blue */
+
+   /* Used to do XAllocColor/XFreeColors accounting: */
+   int num_alloced;
+#if defined(XFree86Server)
+   Pixel alloced_colors[256];
+#else
+   unsigned long alloced_colors[256];
+#endif
+
+#if defined( FX )
+   /* For 3Dfx Glide only */
+   GLboolean FXisHackUsable;   /* Can we render into window? */
+   GLboolean FXwindowHack;     /* Are we rendering into a window? */
+   fxMesaContext FXctx;
+#endif
+
+   /* GLX_EXT_texture_from_pixmap */
+   GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */
+   GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */
+   GLint TextureMipmap; /** 0 or 1 */
+
+   struct xmesa_buffer *Next;  /* Linked list pointer: */
+};
+
+
+/**
+ * If pixelformat==PF_TRUECOLOR:
+ */
+#define PACK_TRUECOLOR( PIXEL, R, G, B )       \
+   PIXEL = xmesa->xm_visual->RtoPixel[R]       \
+         | xmesa->xm_visual->GtoPixel[G]       \
+         | xmesa->xm_visual->BtoPixel[B];      \
+
+
+/**
+ * If pixelformat==PF_TRUEDITHER:
+ */
+#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B )                        \
+{                                                              \
+   int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)];   \
+   PIXEL = xmesa->xm_visual->RtoPixel[(R)+d]                   \
+         | xmesa->xm_visual->GtoPixel[(G)+d]                   \
+         | xmesa->xm_visual->BtoPixel[(B)+d];                  \
+}
+
+
+
+/**
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A )    \
+       ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/**
+ * Like PACK_8A8B8G8R() but don't use alpha.  This is usually an acceptable
+ * shortcut.
+ */
+#define PACK_8B8G8R( R, G, B )   ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+
+/**
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B)   ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/**
+ * If pixelformat==PF_5R6G5B:
+ */
+#define PACK_5R6G5B( R, G, B)   ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+
+
+/**
+ * If pixelformat==PF_8A8R8G8B:
+ */
+#define PACK_8A8R8G8B( R, G, B, A )    \
+       ( ((A) << 24) | ((R) << 16) | ((G) << 8) | (B) )
+
+
+
+/**
+ * If pixelformat==PF_DITHER:
+ *
+ * Improved 8-bit RGB dithering code contributed by Bob Mercier
+ * (mercier@hollywood.cinenet.net).  Thanks Bob!
+ */
+#ifdef DITHER666
+# define DITH_R   6
+# define DITH_G   6
+# define DITH_B   6
+# define DITH_MIX(r,g,b)  (((r) * DITH_G + (g)) * DITH_B + (b))
+#else
+# define DITH_R        5
+# define DITH_G        9
+# define DITH_B        5
+# define DITH_MIX(r,g,b)  (((g) << 6) | ((b) << 3) | (r))
+#endif
+#define DITH_DX        4
+#define DITH_DY        4
+#define DITH_N (DITH_DX * DITH_DY)
+
+#define _dither(C, c, d)   (((unsigned)((DITH_N * (C - 1) + 1) * c + d)) >> 12)
+
+#define MAXC   256
+extern const int xmesa_kernel8[DITH_DY * DITH_DX];
+
+/* Dither for random X,Y */
+#define DITHER_SETUP                                           \
+       int __d;                                                \
+       unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table;
+
+#define DITHER( X, Y, R, G, B )                                \
+       (__d = xmesa_kernel8[(((Y)&3)<<2) | ((X)&3)],   \
+        ctable[DITH_MIX(_dither(DITH_R, (R), __d),     \
+                        _dither(DITH_G, (G), __d),     \
+                        _dither(DITH_B, (B), __d))])
+
+/* Dither for random X, fixed Y */
+#define XDITHER_SETUP(Y)                                       \
+       int __d;                                                \
+       unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table;     \
+       const int *kernel = &xmesa_kernel8[ ((Y)&3) << 2 ];
+
+#define XDITHER( X, R, G, B )                          \
+       (__d = kernel[(X)&3],                           \
+       ctable[DITH_MIX(_dither(DITH_R, (R), __d),      \
+                       _dither(DITH_G, (G), __d),      \
+                       _dither(DITH_B, (B), __d))])
+
+
+
+/*
+ * Dithering for flat-shaded triangles.  Precompute all 16 possible
+ * pixel values given the triangle's RGB color.  Contributed by Martin Shenk.
+ */
+#define FLAT_DITHER_SETUP( R, G, B )                                   \
+       GLushort ditherValues[16];                                      \
+       {                                                               \
+          unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table;  \
+          int msdr = (DITH_N*((DITH_R)-1)+1) * (R);                    \
+          int msdg = (DITH_N*((DITH_G)-1)+1) * (G);                    \
+          int msdb = (DITH_N*((DITH_B)-1)+1) * (B);                    \
+          int i;                                                       \
+          for (i=0;i<16;i++) {                                         \
+             int k = xmesa_kernel8[i];                                 \
+             int j = DITH_MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 );\
+             ditherValues[i] = (GLushort) ctable[j];                   \
+          }                                                            \
+        }
+
+#define FLAT_DITHER_ROW_SETUP(Y)                                       \
+       GLushort *ditherRow = ditherValues + ( ((Y)&3) << 2);
+
+#define FLAT_DITHER(X)  ditherRow[(X)&3]
+
+
+
+/**
+ * If pixelformat==PF_LOOKUP:
+ */
+#define _dither_lookup(C, c)   (((unsigned)((DITH_N * (C - 1) + 1) * c)) >> 12)
+
+#define LOOKUP_SETUP                                           \
+       unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table
+
+#define LOOKUP( R, G, B )                              \
+       ctable[DITH_MIX(_dither_lookup(DITH_R, (R)),    \
+                       _dither_lookup(DITH_G, (G)),    \
+                       _dither_lookup(DITH_B, (B)))]
+
+
+/**
+ * If pixelformat==PF_HPCR:
+ *
+ *      HP Color Recovery dithering               (ad@lms.be 30/08/95)
+ *      HP has on it's 8-bit 700-series computers, a feature called
+ *      'Color Recovery'.  This allows near 24-bit output (so they say).
+ *      It is enabled by selecting the 8-bit  TrueColor  visual AND
+ *      corresponding  colormap (see tkInitWindow) AND doing some special
+ *      dither.
+ */
+extern const short xmesa_HPCR_DRGB[3][2][16];
+
+#define DITHER_HPCR( X, Y, R, G, B )                                      \
+  ( ((xmesa->xm_visual->hpcr_rgbTbl[0][R] + xmesa_HPCR_DRGB[0][(Y)&1][(X)&15]) & 0xE0)     \
+  |(((xmesa->xm_visual->hpcr_rgbTbl[1][G] + xmesa_HPCR_DRGB[1][(Y)&1][(X)&15]) & 0xE0)>>3) \
+  | ((xmesa->xm_visual->hpcr_rgbTbl[2][B] + xmesa_HPCR_DRGB[2][(Y)&1][(X)&15])>>6)        \
+  )
+
+
+
+/**
+ * If pixelformat==PF_1BIT:
+ */
+extern const int xmesa_kernel1[16];
+
+#define SETUP_1BIT  int bitFlip = xmesa->xm_visual->bitFlip
+#define DITHER_1BIT( X, Y, R, G, B )   \
+       (( ((int)(R)+(int)(G)+(int)(B)) > xmesa_kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip)
+
+
+
+/**
+ * If pixelformat==PF_GRAYSCALE:
+ */
+#define GRAY_RGB( R, G, B )   XMESA_BUFFER(ctx->DrawBuffer)->color_table[((R) + (G) + (B))/3]
+
+
+
+/**
+ * Converts a GL window Y coord to an X window Y coord:
+ */
+#define YFLIP(XRB, Y)  ((XRB)->bottom - (Y))
+
+
+/**
+ * Return the address of a 1, 2 or 4-byte pixel in the buffer's XImage:
+ * X==0 is left, Y==0 is bottom.
+ */
+#define PIXEL_ADDR1(XRB, X, Y)  \
+   ( (XRB)->origin1 - (Y) * (XRB)->width1 + (X) )
+
+#define PIXEL_ADDR2(XRB, X, Y)  \
+   ( (XRB)->origin2 - (Y) * (XRB)->width2 + (X) )
+
+#define PIXEL_ADDR3(XRB, X, Y)  \
+   ( (bgr_t *) ( (XRB)->origin3 - (Y) * (XRB)->width3 + 3 * (X) ))
+
+#define PIXEL_ADDR4(XRB, X, Y)  \
+   ( (XRB)->origin4 - (Y) * (XRB)->width4 + (X) )
+
+
+
+/*
+ * External functions:
+ */
+
+extern struct xmesa_renderbuffer *
+xmesa_create_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual,
+                          GLboolean backBuffer);
+
+extern void
+xmesa_delete_framebuffer(struct gl_framebuffer *fb);
+
+extern XMesaBuffer
+xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis);
+
+extern unsigned long
+xmesa_color_to_pixel( GLcontext *ctx,
+                      GLubyte r, GLubyte g, GLubyte b, GLubyte a,
+                      GLuint pixelFormat );
+
+extern void
+xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
+                      GLuint *width, GLuint *height);
+
+extern void
+xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
+
+extern void
+xmesa_init_driver_functions( XMesaVisual xmvisual,
+                             struct dd_function_table *driver );
+
+extern void
+xmesa_update_state( GLcontext *ctx, GLbitfield new_state );
+
+extern void
+xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb,
+                             enum pixel_format pixelformat, GLint depth);
+
+extern void
+xmesa_destroy_buffers_on_display(XMesaDisplay *dpy);
+
+
+/**
+ * Using a function instead of an ordinary cast is safer.
+ */
+static INLINE struct xmesa_renderbuffer *
+xmesa_renderbuffer(struct gl_renderbuffer *rb)
+{
+   return (struct xmesa_renderbuffer *) rb;
+}
+
+
+/**
+ * Return pointer to XMesaContext corresponding to a Mesa GLcontext.
+ * Since we're using structure containment, it's just a cast!.
+ * XXX should use inlined function for better type safety.
+ */
+static INLINE XMesaContext
+XMESA_CONTEXT(GLcontext *ctx)
+{
+   return (XMesaContext) ctx;
+}
+
+
+/**
+ * Return pointer to XMesaBuffer corresponding to a Mesa GLframebuffer.
+ * Since we're using structure containment, it's just a cast!.
+ * XXX should use inlined function for better type safety.
+ */
+static INLINE XMesaBuffer
+XMESA_BUFFER(GLframebuffer *b)
+{
+   return (XMesaBuffer) b;
+}
+
+
+/* Plugged into the software rasterizer.  Try to use internal
+ * swrast-style point, line and triangle functions.
+ */
+extern void xmesa_choose_point( GLcontext *ctx );
+extern void xmesa_choose_line( GLcontext *ctx );
+extern void xmesa_choose_triangle( GLcontext *ctx );
+
+
+extern void xmesa_register_swrast_functions( GLcontext *ctx );
+
+
+
+#define ENABLE_EXT_texure_compression_s3tc 0 /* SW texture compression */
+
+#ifdef XFree86Server
+#define ENABLE_EXT_timer_query 0
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ENABLE_EXT_timer_query 1 /* should have 64-bit GLuint64EXT */
+#else
+#define ENABLE_EXT_timer_query 0 /* may not have 64-bit GLuint64EXT */
+#endif
+
+
+struct pipe_surface;
+struct pipe_context;
+
+struct xmesa_surface
+{
+   struct pipe_surface surface;
+   struct xmesa_renderbuffer *xrb;
+};
+
+
+extern void
+xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, GLuint value);
+
+extern void
+xmesa_clear_buffers(GLcontext *ctx, GLbitfield buffers);
+
+extern struct pipe_context *
+xmesa_create_softpipe(XMesaContext xm);
+
+extern struct pipe_surface *
+xmesa_surface_alloc(struct pipe_context *pipe, GLuint format);
+
+extern struct pipe_surface *
+xmesa_new_color_surface(struct pipe_context *pipe, GLuint format);
+
+extern boolean
+xmesa_is_format_supported(struct pipe_context *pipe, uint format);
+
+extern void
+xmesa_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+                    uint x, uint y, uint w, uint h, float *p);
+
+extern void
+xmesa_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+                    uint x, uint y, uint w, uint h, const float *p);
+
+#endif