Merge branch 'origin'
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
index 440b43fe2f5fbc47d1e6951a4ba69449737c83c7..eecd52aa32b079fc82733abe2e18312263d7ef29 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * 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"),
@@ -52,6 +52,9 @@
 #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
@@ -77,7 +80,7 @@
    "GLX_ARB_get_proc_address " \
    "GLX_EXT_visual_info " \
    "GLX_EXT_visual_rating " \
-   "GLX_SGI_video_sync " \
+   /*"GLX_SGI_video_sync "*/ \
    "GLX_SGIX_fbconfig " \
    "GLX_SGIX_pbuffer "
 
@@ -105,8 +108,7 @@ struct fake_glx_context {
 #define DONT_CARE -1
 
 
-#define MAX_VISUALS 100
-static XMesaVisual VisualTable[MAX_VISUALS];
+static XMesaVisual *VisualTable = NULL;
 static int NumVisuals = 0;
 
 
@@ -136,7 +138,6 @@ typedef struct _OverlayInfo {
 
 
 
-
 /*
  * Test if the given XVisualInfo is usable for Mesa rendering.
  */
@@ -169,26 +170,22 @@ is_usable_visual( XVisualInfo *vinfo )
 
 
 
-/*
- * 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
+/**
+ * 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 int
-level_of_visual( Display *dpy, XVisualInfo *vinfo )
+static OverlayInfo *
+GetOverlayInfo(Display *dpy, int screen, int *numOverlays)
 {
    Atom overlayVisualsAtom;
-   OverlayInfo *overlay_info = NULL;
-   int numOverlaysPerScreen;
-   Status status;
    Atom actualType;
-   int actualFormat;
+   Status status;
+   unsigned char *ovInfo;
    unsigned long sizeData, bytesLeft;
-   int i;
+   int actualFormat;
 
    /*
     * The SERVER_OVERLAY_VISUALS property on the root window contains
@@ -199,25 +196,50 @@ level_of_visual( Display *dpy, XVisualInfo *vinfo )
       return 0;
    }
 
-   status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
+   status = XGetWindowProperty(dpy, RootWindow(dpy, screen),
                                overlayVisualsAtom, 0L, (long) 10000, False,
                                overlayVisualsAtom, &actualType, &actualFormat,
                                &sizeData, &bytesLeft,
-                               (unsigned char **) &overlay_info );
+                               &ovInfo);
 
    if (status != Success || actualType != overlayVisualsAtom ||
        actualFormat != 32 || sizeData < 4) {
       /* something went wrong */
-      XFree((void *) overlay_info);
+      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 */
-   numOverlaysPerScreen = (int) (sizeData / 4);
-   for (i=0;i<numOverlaysPerScreen;i++) {
-      OverlayInfo *ov;
-      ov = overlay_info + i;
-      if (ov->overlay_visual==vinfo->visualid) {
+   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;
@@ -311,11 +333,6 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
 
    /* Create a new visual and add it to the list. */
 
-   if (NumVisuals >= MAX_VISUALS) {
-      _mesa_problem(NULL, "GLX Error: maximum number of visuals exceeded");
-      return NULL;
-   }
-
    xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
                               stereoFlag, ximageFlag,
                               depth_size, stencil_size,
@@ -327,6 +344,10 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
        * 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++;
@@ -357,6 +378,24 @@ default_depth_bits(void)
    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;
+}
+
 
 
 /*
@@ -372,6 +411,8 @@ 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) {
@@ -397,11 +438,8 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
                                  GL_TRUE,   /* double */
                                  GL_FALSE,  /* stereo */
                                  zBits,
-                                 8 * sizeof(GLstencil),
-                                 0 * sizeof(GLaccum), /* r */
-                                 0 * sizeof(GLaccum), /* g */
-                                 0 * sizeof(GLaccum), /* b */
-                                 0 * sizeof(GLaccum), /* a */
+                                 STENCIL_BITS,
+                                 0, 0, 0, 0, /* accum bits */
                                  0,         /* level */
                                  0          /* numAux */
                                );
@@ -412,15 +450,15 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
          /* can be done?  They should use glXChooseVisual(). */
          return save_glx_visual( dpy, visinfo,
                                  GL_TRUE,   /* rgb */
-                                 GL_FALSE,  /* alpha */
+                                 alphaFlag, /* alpha */
                                  GL_TRUE,   /* double */
                                  GL_FALSE,  /* stereo */
                                  zBits,
-                                 8 * sizeof(GLstencil),
-                                 8 * sizeof(GLaccum), /* r */
-                                 8 * sizeof(GLaccum), /* g */
-                                 8 * sizeof(GLaccum), /* b */
-                                 8 * sizeof(GLaccum), /* a */
+                                 STENCIL_BITS,
+                                 accBits, /* r */
+                                 accBits, /* g */
+                                 accBits, /* b */
+                                 accBits, /* a */
                                  0,         /* level */
                                  0          /* numAux */
                                );
@@ -462,7 +500,7 @@ find_glx_visual( Display *dpy, XVisualInfo *vinfo )
 
 
 
-/*
+/**
  * Return the transparent pixel value for a GLX visual.
  * Input:  glxvis - the glx_visual
  * Return:  a pixel value or -1 if no transparent pixel
@@ -472,45 +510,19 @@ transparent_pixel( XMesaVisual glxvis )
 {
    Display *dpy = glxvis->display;
    XVisualInfo *vinfo = glxvis->visinfo;
-   Atom overlayVisualsAtom;
-   OverlayInfo *overlay_info = NULL;
-   int numOverlaysPerScreen;
-   Status status;
-   Atom actualType;
-   int actualFormat;
-   unsigned long sizeData, bytesLeft;
-   int i;
-
-   /*
-    * 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 -1;
-   }
-
-   status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
-                               overlayVisualsAtom, 0L, (long) 10000, False,
-                               overlayVisualsAtom, &actualType, &actualFormat,
-                               &sizeData, &bytesLeft,
-                               (unsigned char **) &overlay_info );
+   OverlayInfo *overlay_info;
+   int numOverlaysPerScreen, i;
 
-   if (status != Success || actualType != overlayVisualsAtom ||
-       actualFormat != 32 || sizeData < 4) {
-      /* something went wrong */
-      XFree((void *) overlay_info);
+   overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen);
+   if (!overlay_info) {
       return -1;
    }
 
-   /* search the overlay visual list for the visual ID of interest */
-   numOverlaysPerScreen = (int) (sizeData / 4);
-   for (i=0;i<numOverlaysPerScreen;i++) {
-      OverlayInfo *ov;
-      ov = overlay_info + i;
-      if (ov->overlay_visual==vinfo->visualid) {
+   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) {
+         if (ov->transparent_type == 0) {
             /* type 0 indicates no transparency */
             XFree((void *) overlay_info);
             return -1;
@@ -530,7 +542,7 @@ transparent_pixel( XMesaVisual glxvis )
 
 
 
-/*
+/**
  * Try to get an X visual which matches the given arguments.
  */
 static XVisualInfo *
@@ -808,13 +820,8 @@ choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
                          int level, int trans_type, int trans_value,
                          int min_depth, int preferred_class )
 {
-   Atom overlayVisualsAtom;
    OverlayInfo *overlay_info;
    int numOverlaysPerScreen;
-   Status status;
-   Atom actualType;
-   int actualFormat;
-   unsigned long sizeData, bytesLeft;
    int i;
    XVisualInfo *deepvis;
    int deepest;
@@ -831,24 +838,8 @@ choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
       default:                    preferred_class = DONT_CARE;
    }
 
-   /*
-    * 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 == (Atom) None) {
-      return NULL;
-   }
-
-   status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
-                               overlayVisualsAtom, 0L, (long) 10000, False,
-                               overlayVisualsAtom, &actualType, &actualFormat,
-                               &sizeData, &bytesLeft,
-                               (unsigned char **) &overlay_info );
-
-   if (status != Success || actualType != overlayVisualsAtom ||
-       actualFormat != 32 || sizeData < 4) {
-      /* something went wrong */
+   overlay_info = GetOverlayInfo(dpy, scr, &numOverlaysPerScreen);
+   if (!overlay_info) {
       return NULL;
    }
 
@@ -856,12 +847,10 @@ choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
    deepest = min_depth;
    deepvis = NULL;
 
-   numOverlaysPerScreen = (int) (sizeData / 4);
-   for (i=0;i<numOverlaysPerScreen;i++) {
+   for (i = 0; i < numOverlaysPerScreen; i++) {
+      const OverlayInfo *ov = overlay_info + i;
       XVisualInfo *vislist, vistemplate;
       int count;
-      OverlayInfo *ov;
-      ov = overlay_info + i;
 
       if (ov->layer!=level) {
          /* failed overlay level criteria */
@@ -926,15 +915,96 @@ choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
 }
 
 
+/**********************************************************************/
+/***             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 rgbModeDefault )
+choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
 {
+   const GLboolean rgbModeDefault = fbConfig;
    const int *parselist;
    XVisualInfo *vis;
    int min_ci = 0;
@@ -964,8 +1034,14 @@ choose_visual( Display *dpy, int screen, const int *list,
 
       switch (*parselist) {
         case GLX_USE_GL:
-           /* ignore */
-           parselist++;
+            if (fbConfig) {
+               /* invalid token */
+               return NULL;
+            }
+            else {
+               /* skip */
+               parselist++;
+            }
            break;
         case GLX_BUFFER_SIZE:
            parselist++;
@@ -976,18 +1052,34 @@ choose_visual( Display *dpy, int screen, const int *list,
             level = *parselist++;
            break;
         case GLX_RGBA:
-           rgb_flag = GL_TRUE;
-           parselist++;
+            if (fbConfig) {
+               /* invalid token */
+               return NULL;
+            }
+            else {
+               rgb_flag = GL_TRUE;
+               parselist++;
+            }
            break;
         case GLX_DOUBLEBUFFER:
-           double_flag = GL_TRUE;
-           parselist++;
+            parselist++;
+            if (fbConfig) {
+               double_flag = *parselist++;
+            }
+            else {
+               double_flag = GL_TRUE;
+            }
            break;
         case GLX_STEREO:
-            stereo_flag = GL_TRUE;
-            return NULL;
+            parselist++;
+            if (fbConfig) {
+               stereo_flag = *parselist++;
+            }
+            else {
+               stereo_flag = GL_TRUE;
+            }
+            return NULL; /* stereo not supported */
         case GLX_AUX_BUFFERS:
-           /* ignore */
            parselist++;
             numAux = *parselist++;
             if (numAux > MAX_AUX_BUFFERS)
@@ -1009,7 +1101,7 @@ choose_visual( Display *dpy, int screen, const int *list,
            parselist++;
             {
                GLint size = *parselist++;
-               alpha_flag = size>0 ? 1 : 0;
+               alpha_flag = size ? GL_TRUE : GL_FALSE;
             }
            break;
         case GLX_DEPTH_SIZE:
@@ -1095,6 +1187,8 @@ choose_visual( Display *dpy, int screen, const int *list,
           * FBConfig attribs.
           */
          case GLX_RENDER_TYPE:
+            if (!fbConfig)
+               return NULL;
             parselist++;
             if (*parselist == GLX_RGBA_BIT) {
                rgb_flag = GL_TRUE;
@@ -1108,6 +1202,8 @@ choose_visual( Display *dpy, int screen, const int *list,
             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 */
@@ -1115,8 +1211,16 @@ choose_visual( Display *dpy, int screen, const int *list,
             parselist++;
             break;
          case GLX_FBCONFIG_ID:
+            if (!fbConfig)
+               return NULL;
             parselist++;
-            desiredVisualID = *parselist;
+            desiredVisualID = *parselist++;
+            break;
+         case GLX_X_RENDERABLE:
+            if (!fbConfig)
+               return NULL;
+            parselist += 2;
+            /* ignore */
             break;
 
         case None:
@@ -1200,22 +1304,26 @@ choose_visual( Display *dpy, int screen, const int *list,
        * return 16 to maintain performance with earlier versions of Mesa.
        */
       if (depth_size > 24)
-         depth_size = 31;   /* 32 causes int overflow problems */
+         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 = ACCUM_BITS;
-         accumGreenSize = ACCUM_BITS;
-         accumBlueSize = ACCUM_BITS;
-         accumAlphaSize = alpha_flag ? ACCUM_BITS : 0;
+         accumRedSize = 
+         accumGreenSize = 
+         accumBlueSize = default_accum_bits();
+         accumAlphaSize = alpha_flag ? accumRedSize : 0;
       }
 
       xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
@@ -1231,7 +1339,12 @@ choose_visual( Display *dpy, int screen, const int *list,
 static XVisualInfo *
 Fake_glXChooseVisual( Display *dpy, int screen, int *list )
 {
-   XMesaVisual xmvis = choose_visual(dpy, screen, list, GL_FALSE);
+   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;
@@ -1265,7 +1378,9 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       return 0;
 
    /* deallocate unused windows/buffers */
+#if 0
    XMesaGarbageCollect();
+#endif
 
    xmvis = find_glx_visual( dpy, visinfo );
    if (!xmvis) {
@@ -1273,7 +1388,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       xmvis = create_glx_visual( dpy, visinfo );
       if (!xmvis) {
          /* unusable visual */
-         FREE(glxCtx);
+         _mesa_free(glxCtx);
          return NULL;
       }
    }
@@ -1281,7 +1396,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -1360,11 +1475,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
          ((__GLXcontext *) ctx)->currentDpy = dpy;
          ((__GLXcontext *) ctx)->currentDrawable = draw;
-#ifndef GLX_BUILT_IN_XMESA
          ((__GLXcontext *) ctx)->currentReadable = read;
-#else
-         __glXSetCurrentContext(ctx);
-#endif
          return True;
       }
       else {
@@ -1379,9 +1490,6 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       MakeCurrent_PrevReadable = 0;
       MakeCurrent_PrevDrawBuffer = 0;
       MakeCurrent_PrevReadBuffer = 0;
-#ifdef GLX_BUILT_IN_XMESA
-      /* XXX bind dummy context with __glXSetCurrentContext(ctx); */
-#endif
       return True;
    }
    else {
@@ -1419,7 +1527,7 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
    if (!b) {
       return 0;
    }
-   return b->frontbuffer;
+   return b->frontxrb->pixmap;
 }
 
 
@@ -1445,7 +1553,7 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
    if (!b) {
       return 0;
    }
-   return b->frontbuffer;
+   return b->frontxrb->pixmap;
 }
 
 
@@ -1471,6 +1579,9 @@ Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext 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 );
 }
 
@@ -1506,6 +1617,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
    MakeCurrent_PrevReadBuffer = 0;
    XMesaDestroyContext( glxCtx->xmesaContext );
    XMesaGarbageCollect();
+   _mesa_free(glxCtx);
 }
 
 
@@ -1528,7 +1640,8 @@ Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
       XMesaSwapBuffers(buffer);
    }
    else if (_mesa_getenv("MESA_DEBUG")) {
-      _mesa_warning(NULL, "Mesa: glXSwapBuffers: invalid drawable\n");
+      _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
+                    (int) drawable);
    }
 }
 
@@ -1571,6 +1684,8 @@ 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:
@@ -1580,6 +1695,8 @@ get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
         *value = xmvis->mesa_visual.level;
         return 0;
       case GLX_RGBA:
+         if (fbconfig)
+            return GLX_BAD_ATTRIBUTE;
         if (xmvis->mesa_visual.rgbMode) {
            *value = True;
         }
@@ -1768,7 +1885,7 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
                    int attrib, int *value )
 {
    XMesaVisual xmvis;
-
+   int k;
    if (!dpy || !visinfo)
       return GLX_BAD_ATTRIBUTE;
 
@@ -1788,7 +1905,8 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
       }
    }
 
-   return get_config(xmvis, attrib, value, GL_FALSE);
+   k = get_config(xmvis, attrib, value, GL_FALSE);
+   return k;
 }
 
 
@@ -1888,28 +2006,6 @@ Fake_glXGetClientString( Display *dpy, int name )
  */
 
 
-static GLXFBConfig *
-Fake_glXChooseFBConfig( Display *dpy, int screen,
-                        const int *attribList, int *nitems )
-{
-   XMesaVisual 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 int
 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
                            int attribute, int *value )
@@ -1951,6 +2047,35 @@ Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
 }
 
 
+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 )
 {
@@ -2084,7 +2209,10 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   return (GLXPbuffer) xmbuf->frontbuffer;
+   if (xmbuf)
+      return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+   else
+      return 0;
 }
 
 
@@ -2108,16 +2236,16 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
 
    switch (attribute) {
       case GLX_WIDTH:
-         *value = xmbuf->width;
+         *value = xmbuf->mesa_buffer.Width;
          break;
       case GLX_HEIGHT:
-         *value = xmbuf->height;
+         *value = xmbuf->mesa_buffer.Height;
          break;
       case GLX_PRESERVED_CONTENTS:
          *value = True;
          break;
       case GLX_LARGEST_PBUFFER:
-         *value = xmbuf->width * xmbuf->height;
+         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
          break;
       case GLX_FBCONFIG_ID:
          *value = xmbuf->xm_visual->visinfo->visualid;
@@ -2150,7 +2278,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -2229,19 +2357,26 @@ Fake_glXSwapIntervalSGI(int interval)
 
 /*** GLX_SGI_video_sync ***/
 
+static unsigned int FrameCounter = 0;
+
 static int
 Fake_glXGetVideoSyncSGI(unsigned int *count)
 {
-   (void) count;
+   /* this is a bogus implementation */
+   *count = FrameCounter++;
    return 0;
 }
 
 static int
 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
 {
-   (void) divisor;
-   (void) remainder;
-   (void) 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;
 }
 
@@ -2345,7 +2480,7 @@ Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixm
 {
    XMesaVisual xmvis = (XMesaVisual) config;
    XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
-   return xmbuf->frontbuffer; /* need to return an X ID */
+   return xmbuf->frontxrb->pixmap; /* need to return an X ID */
 }
 
 
@@ -2366,7 +2501,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -2439,7 +2574,7 @@ Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   return (GLXPbuffer) xmbuf->frontbuffer;
+   return (GLXPbuffer) xmbuf->frontxrb->pixmap;
 }
 
 
@@ -2468,13 +2603,13 @@ Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, un
          *value = True;
          break;
       case GLX_LARGEST_PBUFFER_SGIX:
-         *value = xmbuf->width * xmbuf->height;
+         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
          break;
       case GLX_WIDTH_SGIX:
-         *value = xmbuf->width;
+         *value = xmbuf->mesa_buffer.Width;
          break;
       case GLX_HEIGHT_SGIX:
-         *value = xmbuf->height;
+         *value = xmbuf->mesa_buffer.Height;
          break;
       case GLX_EVENT_MASK_SGIX:
          *value = 0;  /* XXX might be wrong */