Retire miniglx and move the actual glx code up to src/glx
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 9 Feb 2010 14:58:36 +0000 (09:58 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 9 Feb 2010 14:58:36 +0000 (09:58 -0500)
118 files changed:
Makefile
configs/darwin
configs/freebsd-dri
configs/linux-dri
configs/linux-dri-xcb
configs/linux-indirect
configure.ac
docs/egl.html
src/gallium/state_trackers/egl/Makefile
src/gallium/state_trackers/egl/x11/glxinit.c
src/glx/Makefile
src/glx/XF86dri.c [new file with mode: 0644]
src/glx/clientattrib.c [new file with mode: 0644]
src/glx/compsize.c [new file with mode: 0644]
src/glx/dri2.c [new file with mode: 0644]
src/glx/dri2.h [new file with mode: 0644]
src/glx/dri2_glx.c [new file with mode: 0644]
src/glx/dri_common.c [new file with mode: 0644]
src/glx/dri_common.h [new file with mode: 0644]
src/glx/dri_glx.c [new file with mode: 0644]
src/glx/drisw_glx.c [new file with mode: 0644]
src/glx/eval.c [new file with mode: 0644]
src/glx/glcontextmodes.c [new file with mode: 0644]
src/glx/glcontextmodes.h [new file with mode: 0644]
src/glx/glx_pbuffer.c [new file with mode: 0644]
src/glx/glx_query.c [new file with mode: 0644]
src/glx/glxclient.h [new file with mode: 0644]
src/glx/glxcmds.c [new file with mode: 0644]
src/glx/glxcurrent.c [new file with mode: 0644]
src/glx/glxext.c [new file with mode: 0644]
src/glx/glxextensions.c [new file with mode: 0644]
src/glx/glxextensions.h [new file with mode: 0644]
src/glx/glxhash.c [new file with mode: 0644]
src/glx/glxhash.h [new file with mode: 0644]
src/glx/indirect.c [new file with mode: 0644]
src/glx/indirect.h [new file with mode: 0644]
src/glx/indirect_init.c [new file with mode: 0644]
src/glx/indirect_init.h [new file with mode: 0644]
src/glx/indirect_size.c [new file with mode: 0644]
src/glx/indirect_size.h [new file with mode: 0644]
src/glx/indirect_texture_compression.c [new file with mode: 0644]
src/glx/indirect_transpose_matrix.c [new file with mode: 0644]
src/glx/indirect_vertex_array.c [new file with mode: 0644]
src/glx/indirect_vertex_array.h [new file with mode: 0644]
src/glx/indirect_vertex_array_priv.h [new file with mode: 0644]
src/glx/indirect_vertex_program.c [new file with mode: 0644]
src/glx/indirect_window_pos.c [new file with mode: 0644]
src/glx/mini/Makefile [deleted file]
src/glx/mini/NOTES [deleted file]
src/glx/mini/dispatch.c [deleted file]
src/glx/mini/driver.h [deleted file]
src/glx/mini/example.miniglx.conf [deleted file]
src/glx/mini/miniglx.c [deleted file]
src/glx/mini/miniglxP.h [deleted file]
src/glx/mini/miniglx_events.c [deleted file]
src/glx/packrender.h [new file with mode: 0644]
src/glx/packsingle.h [new file with mode: 0644]
src/glx/pixel.c [new file with mode: 0644]
src/glx/pixelstore.c [new file with mode: 0644]
src/glx/render2.c [new file with mode: 0644]
src/glx/renderpix.c [new file with mode: 0644]
src/glx/single2.c [new file with mode: 0644]
src/glx/singlepix.c [new file with mode: 0644]
src/glx/vertarr.c [new file with mode: 0644]
src/glx/x11/Makefile [deleted file]
src/glx/x11/XF86dri.c [deleted file]
src/glx/x11/clientattrib.c [deleted file]
src/glx/x11/compsize.c [deleted file]
src/glx/x11/dri2.c [deleted file]
src/glx/x11/dri2.h [deleted file]
src/glx/x11/dri2_glx.c [deleted file]
src/glx/x11/dri_common.c [deleted file]
src/glx/x11/dri_common.h [deleted file]
src/glx/x11/dri_glx.c [deleted file]
src/glx/x11/drisw_glx.c [deleted file]
src/glx/x11/eval.c [deleted file]
src/glx/x11/glcontextmodes.c [deleted file]
src/glx/x11/glcontextmodes.h [deleted file]
src/glx/x11/glx_pbuffer.c [deleted file]
src/glx/x11/glx_query.c [deleted file]
src/glx/x11/glxclient.h [deleted file]
src/glx/x11/glxcmds.c [deleted file]
src/glx/x11/glxcurrent.c [deleted file]
src/glx/x11/glxext.c [deleted file]
src/glx/x11/glxextensions.c [deleted file]
src/glx/x11/glxextensions.h [deleted file]
src/glx/x11/glxhash.c [deleted file]
src/glx/x11/glxhash.h [deleted file]
src/glx/x11/indirect.c [deleted file]
src/glx/x11/indirect.h [deleted file]
src/glx/x11/indirect_init.c [deleted file]
src/glx/x11/indirect_init.h [deleted file]
src/glx/x11/indirect_size.c [deleted file]
src/glx/x11/indirect_size.h [deleted file]
src/glx/x11/indirect_texture_compression.c [deleted file]
src/glx/x11/indirect_transpose_matrix.c [deleted file]
src/glx/x11/indirect_vertex_array.c [deleted file]
src/glx/x11/indirect_vertex_array.h [deleted file]
src/glx/x11/indirect_vertex_array_priv.h [deleted file]
src/glx/x11/indirect_vertex_program.c [deleted file]
src/glx/x11/indirect_window_pos.c [deleted file]
src/glx/x11/packrender.h [deleted file]
src/glx/x11/packsingle.h [deleted file]
src/glx/x11/pixel.c [deleted file]
src/glx/x11/pixelstore.c [deleted file]
src/glx/x11/render2.c [deleted file]
src/glx/x11/renderpix.c [deleted file]
src/glx/x11/single2.c [deleted file]
src/glx/x11/singlepix.c [deleted file]
src/glx/x11/vertarr.c [deleted file]
src/glx/x11/xf86dri.h [deleted file]
src/glx/x11/xf86dristr.h [deleted file]
src/glx/x11/xfont.c [deleted file]
src/glx/xf86dri.h [new file with mode: 0644]
src/glx/xf86dristr.h [new file with mode: 0644]
src/glx/xfont.c [new file with mode: 0644]
src/mesa/glapi/Makefile
src/mesa/main/dispatch.c

index bf8debfd5b37a8aa465ad2f88e4bdd813d8ef4cf..09a8ca29771a3813c7e55a470bbe99176b9a30b3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -361,8 +361,8 @@ DRI_FILES = \
        $(DIRECTORY)/include/GL/internal/glcore.h                       \
        $(DIRECTORY)/include/GL/internal/sarea.h                        \
        $(DIRECTORY)/src/glx/Makefile                                   \
-       $(DIRECTORY)/src/glx/x11/Makefile                               \
-       $(DIRECTORY)/src/glx/x11/*.[ch]                                 \
+       $(DIRECTORY)/src/glx/Makefile                                   \
+       $(DIRECTORY)/src/glx/*.[ch]                                     \
        $(DIRECTORY)/src/mesa/drivers/dri/Makefile                      \
        $(DIRECTORY)/src/mesa/drivers/dri/Makefile.template             \
        $(DIRECTORY)/src/mesa/drivers/dri/dri.pc.in                     \
@@ -488,7 +488,7 @@ GLUT_FILES = \
 
 DEPEND_FILES = \
        $(TOP)/src/mesa/depend          \
-       $(TOP)/src/glx/x11/depend       \
+       $(TOP)/src/glx/depend           \
        $(TOP)/src/glw/depend           \
        $(TOP)/src/glut/glx/depend      \
        $(TOP)/src/glu/sgi/depend
index 7556688fe6dd431c74a7f731b3d0402be4600db5..d28d5906ba14df5fe525ebc4e0a10e65c660450a 100644 (file)
@@ -16,7 +16,7 @@ DEFINES =  -D_DARWIN_C_SOURCE -DPTHREADS -D_GNU_SOURCE \
           -DGLX_ALIAS_UNSUPPORTED -DGLX_INDIRECT_RENDERING
 
 # -D_GNU_SOURCE          - for src/mesa/main ...
-# -DGLX_DIRECT_RENDERING - pulls in libdrm stuff in glx/x11
+# -DGLX_DIRECT_RENDERING - pulls in libdrm stuff in glx
 # -DGLX_USE_APPLEGL      - supposed to be used with GLX_DIRECT_RENDERING to use AGL rather than DRM, but doesn't compile
 # -DIN_DRI_DRIVER
 
@@ -49,7 +49,7 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X
 APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X11_DIR)/$(LIB_DIR) -lX11 -lXmu -lXt -lXi -lm
 
 # omit glw lib for now:
-SRC_DIRS = glsl glx/x11 mesa gallium glu glut/glx glew
+SRC_DIRS = glsl glx mesa gallium glu glut/glx glew
 GLU_DIRS = sgi
 DRIVER_DIRS = osmesa
 #DRIVER_DIRS = dri
index 0ec25f916ed24660e65509fc1b21bafae4e43ece..da63e3b78c5da749e7bb97c07a0ea545ba8ca31d 100644 (file)
@@ -41,7 +41,7 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/local/lib -lGL -lXt -lX11
 
 
 # Directories
-SRC_DIRS = glx/x11 gallium mesa glu glut/glx glew glw
+SRC_DIRS = glx gallium mesa glu glut/glx glew glw
 DRIVER_DIRS = dri
 PROGRAM_DIRS = 
 WINDOW_SYSTEM=dri
index 95f77ade1dd2301e60618dd19a910d3ec246fc2f..634546c64ca5e7429b9e5c80bbd94a2091d2984f 100644 (file)
@@ -51,7 +51,7 @@ GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
 
 
 # Directories
-SRC_DIRS := glx/x11 egl $(SRC_DIRS)
+SRC_DIRS := glx egl $(SRC_DIRS)
 PROGRAM_DIRS := egl $(PROGRAM_DIRS)
 
 # EGL directories
index 7b99dccdb88fa1fc6adfa29e0cb9dc02dcecdf54..691f8e4918c1f70bf26174a667601333cc5524d7 100644 (file)
@@ -47,7 +47,7 @@ DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl \
                 $(LIBDRM_LIB) $(shell pkg-config --libs xcb) $(shell pkg-config --libs x11-xcb) $(shell pkg-config --libs xcb-glx)
 
-SRC_DIRS = glx/x11 gallium mesa glu glut/glx glew glw
+SRC_DIRS = glx gallium mesa glu glut/glx glew glw
 PROGRAM_DIRS = xdemos
 
 DRIVER_DIRS = dri
index 4b81383c072235ab0c015321938a42a0646acd85..0914fba19bc16be53b7260f36c105c4643483099 100644 (file)
@@ -47,7 +47,7 @@ GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl
 
 
 # Directories
-SRC_DIRS = glx/x11 glu glut/glx glew glw
+SRC_DIRS = glx glu glut/glx glew glw
 DRIVER_DIRS =
 PROGRAM_DIRS = 
 WINDOW_SYSTEM=dri
index b6c6535fc6e547bcc3f7adbce9707247aa779529..a273a16c891870af86813f21f8f0ed2854850c9f 100644 (file)
@@ -445,7 +445,7 @@ xlib)
     GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS xlib"
     ;;
 dri)
-    SRC_DIRS="$SRC_DIRS glx/x11"
+    SRC_DIRS="$SRC_DIRS glx"
     DRIVER_DIRS="dri"
     WINDOW_SYSTEM="dri"
     GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS drm"
index 9eba402411d9f1a420173d96f9ada800e831d1f7..844cc32079e7dd978557df9c1cd5444dbd1f8c99 100644 (file)
@@ -309,7 +309,6 @@ surfaces.</p>
 <li>Pass the conformance tests</li>
 <li>Better automatic driver selection: <code>EGL_DISPLAY</code> loads all
 drivers and might eat too much memory.</li>
-<li>Stop using <code>glxinit.c</code> and sources from <code>src/glx/x11/</code></li>
 
 </ul>
 
index 2863320a480618dbff5971c5a67a61833762d9fd..794785006f5781f66c37c303e74d028556355f02 100644 (file)
@@ -14,12 +14,12 @@ common_OBJECTS = $(common_SOURCES:.c=.o)
 
 x11_INCLUDES = \
        -I$(TOP)/src/gallium/drivers \
-       -I$(TOP)/src/glx/x11 \
+       -I$(TOP)/src/glx \
        -I$(TOP)/src/mesa \
        $(shell pkg-config --cflags-only-I libdrm)
 
 x11_SOURCES = $(wildcard x11/*.c) \
-             $(TOP)/src/glx/x11/dri2.c
+             $(TOP)/src/glx/dri2.c
 x11_OBJECTS = $(x11_SOURCES:.c=.o)
 
 
index ba6132788a7fd9e58ba8ebc119a7f0b820280f83..1ed2afd3458cf2af274603e878089fc8ef3855f2 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * GLX initialization.  Code based on glxext.c, glx_query.c, and
- * glcontextmodes.c under src/glx/x11/.  The major difference is that DRI
+ * glcontextmodes.c under src/glx/.  The major difference is that DRI
  * related code is stripped out.
  *
  * If the maintenance of this file takes too much time, we should consider
index e0ab4a024016bac5a609ad6442792242c546a6ab..e681be834f058ee4dc321f27c7e4804306474875 100644 (file)
@@ -1,12 +1,97 @@
-
-TOP = ../..
+TOP = ../../..
 include $(TOP)/configs/current
 
+EXTRA_DEFINES = -DXF86VIDMODE -D_REENTRANT \
+                -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
+
+SOURCES = \
+         glcontextmodes.c \
+         clientattrib.c \
+         compsize.c \
+         eval.c \
+         glxcmds.c \
+         glxcurrent.c \
+         glxext.c \
+         glxextensions.c \
+         indirect.c \
+         indirect_init.c \
+         indirect_size.c \
+         indirect_window_pos.c \
+         indirect_texture_compression.c \
+         indirect_transpose_matrix.c \
+         indirect_vertex_array.c \
+         indirect_vertex_program.c \
+         pixel.c \
+         pixelstore.c \
+         render2.c \
+         renderpix.c \
+         single2.c \
+         singlepix.c \
+         vertarr.c \
+         xfont.c \
+         glx_pbuffer.c \
+         glx_query.c \
+         drisw_glx.c \
+         dri_common.c \
+         dri_glx.c \
+         XF86dri.c \
+         glxhash.c \
+         dri2_glx.c \
+         dri2.c
+
+GLAPI_LIB = $(TOP)/src/mesa/libglapi.a
+
+OBJECTS = $(SOURCES:.c=.o)
+
+INCLUDES = -I. \
+       -I$(TOP)/include \
+       -I$(TOP)/include/GL/internal \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/mesa/glapi \
+       $(LIBDRM_CFLAGS) \
+       $(DRI2PROTO_CFLAGS) \
+       $(X11_INCLUDES)
+
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_DEFINES)  $< -o $@
+
+##### TARGETS #####
+
+default: depend $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
+
+# Make libGL
+$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(GLAPI_LIB) Makefile
+       $(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+               -major 1 -minor 2 $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/lib$(GL_LIB).1.dylib \
+               $(GL_LIB_DEPS) $(OBJECTS) $(GLAPI_LIB)
+
+$(GLAPI_LIB):
+       @$(MAKE) -C $(TOP)/src/mesa libglapi.a
+
+depend: $(SOURCES) Makefile
+       rm -f depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES)
+
 
-default:
-       cd mini && $(MAKE)
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find $(TOP)/include`
 
+install: $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
+       $(MAKE) -C $(TOP)/src/mesa install-libgl
 
+# Remove .o and backup files
 clean:
-       -@cd mini && $(MAKE) clean
+       -rm -f $(TOP)/$(LIB_DIR)/libGL.so*
+       -rm -f *.o *~
+       -rm -f depend depend.bak
 
+-include depend
diff --git a/src/glx/XF86dri.c b/src/glx/XF86dri.c
new file mode 100644 (file)
index 0000000..248d96a
--- /dev/null
@@ -0,0 +1,637 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, 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 <martin@valinux.com>
+ *   Jens Owen <jens@tungstengraphics.com>
+ *   Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "xf86dristr.h"
+
+
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+#  define PUBLIC __attribute__((visibility("default")))
+#  define USED __attribute__((used))
+#else
+#  define PUBLIC
+#  define USED
+#endif
+
+
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define XF86DRICheckExtension(dpy,i,val) \
+  XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ *                                                                           *
+ *                        private utility routines                          *
+ *                                                                           *
+ *****************************************************************************/
+
+static int close_display(Display * dpy, XExtCodes * extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+   NULL,                        /* create_gc */
+   NULL,                        /* copy_gc */
+   NULL,                        /* flush_gc */
+   NULL,                        /* free_gc */
+   NULL,                        /* create_font */
+   NULL,                        /* free_font */
+   close_display,               /* close_display */
+   NULL,                        /* wire_to_event */
+   NULL,                        /* event_to_wire */
+   NULL,                        /* error */
+   NULL,                        /* error_string */
+};
+
+static
+XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info,
+                           xf86dri_extension_name,
+                           &xf86dri_extension_hooks, 0, NULL)
+
+static
+XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info)
+
+
+/*****************************************************************************
+ *                                                                           *
+ *                 public XFree86-DRI Extension routines                    *
+ *                                                                           *
+ *****************************************************************************/
+#if 0
+#include <stdio.h>
+#define TRACE(msg)  fprintf(stderr,"XF86DRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+Bool
+XF86DRIQueryExtension(Display * dpy, int *event_basep,
+                      int *error_basep)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+
+   TRACE("QueryExtension...");
+   if (XextHasExtension(info)) {
+      *event_basep = info->codes->first_event;
+      *error_basep = info->codes->first_error;
+      TRACE("QueryExtension... return True");
+      return True;
+   }
+   else {
+      TRACE("QueryExtension... return False");
+      return False;
+   }
+}
+
+Bool
+XF86DRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion,
+                    int *patchVersion)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIQueryVersionReply rep;
+   xXF86DRIQueryVersionReq *req;
+
+   TRACE("QueryVersion...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIQueryVersion, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIQueryVersion;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("QueryVersion... return False");
+      return False;
+   }
+   *majorVersion = rep.majorVersion;
+   *minorVersion = rep.minorVersion;
+   *patchVersion = rep.patchVersion;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("QueryVersion... return True");
+   return True;
+}
+
+Bool
+XF86DRIQueryDirectRenderingCapable(Display * dpy, int screen,
+                                   Bool * isCapable)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIQueryDirectRenderingCapableReply rep;
+   xXF86DRIQueryDirectRenderingCapableReq *req;
+
+   TRACE("QueryDirectRenderingCapable...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIQueryDirectRenderingCapable, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+   req->screen = screen;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("QueryDirectRenderingCapable... return False");
+      return False;
+   }
+   *isCapable = rep.isCapable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("QueryDirectRenderingCapable... return True");
+   return True;
+}
+
+Bool
+XF86DRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA,
+                      char **busIdString)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIOpenConnectionReply rep;
+   xXF86DRIOpenConnectionReq *req;
+
+   TRACE("OpenConnection...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIOpenConnection, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIOpenConnection;
+   req->screen = screen;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("OpenConnection... return False");
+      return False;
+   }
+
+   *hSAREA = rep.hSAREALow;
+   if (sizeof(drm_handle_t) == 8) {
+      int shift = 32;           /* var to prevent warning on next line */
+      *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
+   }
+
+   if (rep.length) {
+      if (!(*busIdString = (char *) Xcalloc(rep.busIdStringLength + 1, 1))) {
+         _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3));
+         UnlockDisplay(dpy);
+         SyncHandle();
+         TRACE("OpenConnection... return False");
+         return False;
+      }
+      _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+   }
+   else {
+      *busIdString = NULL;
+   }
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("OpenConnection... return True");
+   return True;
+}
+
+Bool
+XF86DRIAuthConnection(Display * dpy, int screen, drm_magic_t magic)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIAuthConnectionReq *req;
+   xXF86DRIAuthConnectionReply rep;
+
+   TRACE("AuthConnection...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIAuthConnection, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIAuthConnection;
+   req->screen = screen;
+   req->magic = magic;
+   rep.authenticated = 0;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("AuthConnection... return False");
+      return False;
+   }
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("AuthConnection... return True");
+   return True;
+}
+
+Bool
+XF86DRICloseConnection(Display * dpy, int screen)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRICloseConnectionReq *req;
+
+   TRACE("CloseConnection...");
+
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRICloseConnection, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRICloseConnection;
+   req->screen = screen;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("CloseConnection... return True");
+   return True;
+}
+
+Bool
+XF86DRIGetClientDriverName(Display * dpy, int screen,
+                           int *ddxDriverMajorVersion,
+                           int *ddxDriverMinorVersion,
+                           int *ddxDriverPatchVersion,
+                           char **clientDriverName)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIGetClientDriverNameReply rep;
+   xXF86DRIGetClientDriverNameReq *req;
+
+   TRACE("GetClientDriverName...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIGetClientDriverName, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIGetClientDriverName;
+   req->screen = screen;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("GetClientDriverName... return False");
+      return False;
+   }
+
+   *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+   *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+   *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+   if (rep.length) {
+      if (!
+          (*clientDriverName =
+           (char *) Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+         _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3));
+         UnlockDisplay(dpy);
+         SyncHandle();
+         TRACE("GetClientDriverName... return False");
+         return False;
+      }
+      _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+   }
+   else {
+      *clientDriverName = NULL;
+   }
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("GetClientDriverName... return True");
+   return True;
+}
+
+Bool
+XF86DRICreateContextWithConfig(Display * dpy, int screen, int configID,
+                               XID * context, drm_context_t * hHWContext)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRICreateContextReply rep;
+   xXF86DRICreateContextReq *req;
+
+   TRACE("CreateContext...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRICreateContext, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRICreateContext;
+   req->visual = configID;
+   req->screen = screen;
+   *context = XAllocID(dpy);
+   req->context = *context;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("CreateContext... return False");
+      return False;
+   }
+   *hHWContext = rep.hHWContext;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("CreateContext... return True");
+   return True;
+}
+
+Bool
+XF86DRICreateContext(Display * dpy, int screen, Visual * visual,
+                     XID * context, drm_context_t * hHWContext)
+{
+   return XF86DRICreateContextWithConfig(dpy, screen, visual->visualid,
+                                         context, hHWContext);
+}
+
+Bool
+XF86DRIDestroyContext(Display * dpy, int screen, XID context)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIDestroyContextReq *req;
+
+   TRACE("DestroyContext...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIDestroyContext, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIDestroyContext;
+   req->screen = screen;
+   req->context = context;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("DestroyContext... return True");
+   return True;
+}
+
+Bool
+XF86DRICreateDrawable(Display * dpy, int screen,
+                      XID drawable, drm_drawable_t * hHWDrawable)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRICreateDrawableReply rep;
+   xXF86DRICreateDrawableReq *req;
+
+   TRACE("CreateDrawable...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRICreateDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRICreateDrawable;
+   req->screen = screen;
+   req->drawable = drawable;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("CreateDrawable... return False");
+      return False;
+   }
+   *hHWDrawable = rep.hHWDrawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("CreateDrawable... return True");
+   return True;
+}
+
+static int
+noopErrorHandler(Display * dpy, XErrorEvent * xerr)
+{
+   return 0;
+}
+
+Bool
+XF86DRIDestroyDrawable(Display * dpy, int screen, XID drawable)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIDestroyDrawableReq *req;
+   int (*oldXErrorHandler) (Display *, XErrorEvent *);
+
+   TRACE("DestroyDrawable...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   /* This is called from the DRI driver, which used call it like this
+    *
+    *   if (windowExists(drawable))
+    *     destroyDrawable(drawable);
+    *
+    * which is a textbook race condition - the window may disappear
+    * from the server between checking for its existance and
+    * destroying it.  Instead we change the semantics of
+    * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
+    * the windows is gone, by wrapping the destroy call in an error
+    * handler. */
+
+   XSync(dpy, False);
+   oldXErrorHandler = XSetErrorHandler(noopErrorHandler);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIDestroyDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIDestroyDrawable;
+   req->screen = screen;
+   req->drawable = drawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   XSetErrorHandler(oldXErrorHandler);
+
+   TRACE("DestroyDrawable... return True");
+   return True;
+}
+
+Bool
+XF86DRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
+                       unsigned int *index, unsigned int *stamp,
+                       int *X, int *Y, int *W, int *H,
+                       int *numClipRects, drm_clip_rect_t ** pClipRects,
+                       int *backX, int *backY,
+                       int *numBackClipRects,
+                       drm_clip_rect_t ** pBackClipRects)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIGetDrawableInfoReply rep;
+   xXF86DRIGetDrawableInfoReq *req;
+   int total_rects;
+
+   TRACE("GetDrawableInfo...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIGetDrawableInfo, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIGetDrawableInfo;
+   req->screen = screen;
+   req->drawable = drawable;
+
+   if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("GetDrawableInfo... return False");
+      return False;
+   }
+   *index = rep.drawableTableIndex;
+   *stamp = rep.drawableTableStamp;
+   *X = (int) rep.drawableX;
+   *Y = (int) rep.drawableY;
+   *W = (int) rep.drawableWidth;
+   *H = (int) rep.drawableHeight;
+   *numClipRects = rep.numClipRects;
+   total_rects = *numClipRects;
+
+   *backX = rep.backX;
+   *backY = rep.backY;
+   *numBackClipRects = rep.numBackClipRects;
+   total_rects += *numBackClipRects;
+
+#if 0
+   /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+    * backwards compatibility (Because of the >> 2 shift) but the fix
+    * enables multi-threaded apps to work.
+    */
+   if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+                         SIZEOF(xGenericReply) +
+                         total_rects * sizeof(drm_clip_rect_t)) +
+                        3) & ~3) >> 2)) {
+      _XEatData(dpy, rep.length);
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("GetDrawableInfo... return False");
+      return False;
+   }
+#endif
+
+   if (*numClipRects) {
+      int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+      *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+      if (*pClipRects)
+         _XRead(dpy, (char *) *pClipRects, len);
+   }
+   else {
+      *pClipRects = NULL;
+   }
+
+   if (*numBackClipRects) {
+      int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+      *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+      if (*pBackClipRects)
+         _XRead(dpy, (char *) *pBackClipRects, len);
+   }
+   else {
+      *pBackClipRects = NULL;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("GetDrawableInfo... return True");
+   return True;
+}
+
+Bool
+XF86DRIGetDeviceInfo(Display * dpy, int screen, drm_handle_t * hFrameBuffer,
+                     int *fbOrigin, int *fbSize, int *fbStride,
+                     int *devPrivateSize, void **pDevPrivate)
+{
+   XExtDisplayInfo *info = find_display(dpy);
+   xXF86DRIGetDeviceInfoReply rep;
+   xXF86DRIGetDeviceInfoReq *req;
+
+   TRACE("GetDeviceInfo...");
+   XF86DRICheckExtension(dpy, info, False);
+
+   LockDisplay(dpy);
+   GetReq(XF86DRIGetDeviceInfo, req);
+   req->reqType = info->codes->major_opcode;
+   req->driReqType = X_XF86DRIGetDeviceInfo;
+   req->screen = screen;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      TRACE("GetDeviceInfo... return False");
+      return False;
+   }
+
+   *hFrameBuffer = rep.hFrameBufferLow;
+   if (sizeof(drm_handle_t) == 8) {
+      int shift = 32;           /* var to prevent warning on next line */
+      *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
+   }
+
+   *fbOrigin = rep.framebufferOrigin;
+   *fbSize = rep.framebufferSize;
+   *fbStride = rep.framebufferStride;
+   *devPrivateSize = rep.devPrivateSize;
+
+   if (rep.length) {
+      if (!(*pDevPrivate = (void *) Xcalloc(rep.devPrivateSize, 1))) {
+         _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3));
+         UnlockDisplay(dpy);
+         SyncHandle();
+         TRACE("GetDeviceInfo... return False");
+         return False;
+      }
+      _XRead(dpy, (char *) *pDevPrivate, rep.devPrivateSize);
+   }
+   else {
+      *pDevPrivate = NULL;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+   TRACE("GetDeviceInfo... return True");
+   return True;
+}
+
+Bool
+XF86DRIOpenFullScreen(Display * dpy, int screen, Drawable drawable)
+{
+   /* This function and the underlying X protocol are deprecated.
+    */
+   (void) dpy;
+   (void) screen;
+   (void) drawable;
+   return False;
+}
+
+Bool
+XF86DRICloseFullScreen(Display * dpy, int screen, Drawable drawable)
+{
+   /* This function and the underlying X protocol are deprecated.
+    */
+   (void) dpy;
+   (void) screen;
+   (void) drawable;
+   return True;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/clientattrib.c b/src/glx/clientattrib.c
new file mode 100644 (file)
index 0000000..a7dfb53
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include <assert.h>
+#include "glxclient.h"
+#include "indirect.h"
+#include "indirect_vertex_array.h"
+
+/*****************************************************************************/
+
+static void
+do_enable_disable(GLenum array, GLboolean val)
+{
+   __GLXcontext *gc = __glXGetCurrentContext();
+   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
+   unsigned index = 0;
+
+   if (array == GL_TEXTURE_COORD_ARRAY) {
+      index = __glXGetActiveTextureUnit(state);
+   }
+
+   if (!__glXSetArrayEnable(state, array, index, val)) {
+      __glXSetError(gc, GL_INVALID_ENUM);
+   }
+}
+
+void
+__indirect_glEnableClientState(GLenum array)
+{
+   do_enable_disable(array, GL_TRUE);
+}
+
+void
+__indirect_glDisableClientState(GLenum array)
+{
+   do_enable_disable(array, GL_FALSE);
+}
+
+/************************************************************************/
+
+void
+__indirect_glPushClientAttrib(GLuint mask)
+{
+   __GLXcontext *gc = __glXGetCurrentContext();
+   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
+   __GLXattribute **spp = gc->attributes.stackPointer, *sp;
+
+   if (spp < &gc->attributes.stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]) {
+      if (!(sp = *spp)) {
+         sp = (__GLXattribute *) Xmalloc(sizeof(__GLXattribute));
+         *spp = sp;
+      }
+      sp->mask = mask;
+      gc->attributes.stackPointer = spp + 1;
+      if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+         sp->storePack = state->storePack;
+         sp->storeUnpack = state->storeUnpack;
+      }
+      if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+         __glXPushArrayState(state);
+      }
+   }
+   else {
+      __glXSetError(gc, GL_STACK_OVERFLOW);
+      return;
+   }
+}
+
+void
+__indirect_glPopClientAttrib(void)
+{
+   __GLXcontext *gc = __glXGetCurrentContext();
+   __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
+   __GLXattribute **spp = gc->attributes.stackPointer, *sp;
+   GLuint mask;
+
+   if (spp > &gc->attributes.stack[0]) {
+      --spp;
+      sp = *spp;
+      assert(sp != 0);
+      mask = sp->mask;
+      gc->attributes.stackPointer = spp;
+
+      if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+         state->storePack = sp->storePack;
+         state->storeUnpack = sp->storeUnpack;
+      }
+      if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+         __glXPopArrayState(state);
+      }
+
+      sp->mask = 0;
+   }
+   else {
+      __glXSetError(gc, GL_STACK_UNDERFLOW);
+      return;
+   }
+}
+
+void
+__glFreeAttributeState(__GLXcontext * gc)
+{
+   __GLXattribute *sp, **spp;
+
+   for (spp = &gc->attributes.stack[0];
+        spp < &gc->attributes.stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]; spp++) {
+      sp = *spp;
+      if (sp) {
+         XFree((char *) sp);
+      }
+      else {
+         break;
+      }
+   }
+}
diff --git a/src/glx/compsize.c b/src/glx/compsize.c
new file mode 100644 (file)
index 0000000..5ba6dc9
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include <GL/gl.h>
+#include "glxclient.h"
+
+/*
+** Return the number of elements per group of a specified format
+*/
+GLint
+__glElementsPerGroup(GLenum format, GLenum type)
+{
+   /*
+    ** To make row length computation valid for image extraction,
+    ** packed pixel types assume elements per group equals one.
+    */
+   switch (type) {
+   case GL_UNSIGNED_BYTE_3_3_2:
+   case GL_UNSIGNED_BYTE_2_3_3_REV:
+   case GL_UNSIGNED_SHORT_5_6_5:
+   case GL_UNSIGNED_SHORT_5_6_5_REV:
+   case GL_UNSIGNED_SHORT_4_4_4_4:
+   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+   case GL_UNSIGNED_SHORT_5_5_5_1:
+   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+   case GL_UNSIGNED_SHORT_8_8_APPLE:
+   case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
+   case GL_UNSIGNED_SHORT_15_1_MESA:
+   case GL_UNSIGNED_SHORT_1_15_REV_MESA:
+   case GL_UNSIGNED_INT_8_8_8_8:
+   case GL_UNSIGNED_INT_8_8_8_8_REV:
+   case GL_UNSIGNED_INT_10_10_10_2:
+   case GL_UNSIGNED_INT_2_10_10_10_REV:
+   case GL_UNSIGNED_INT_24_8_NV:
+   case GL_UNSIGNED_INT_24_8_MESA:
+   case GL_UNSIGNED_INT_8_24_REV_MESA:
+      return 1;
+   default:
+      break;
+   }
+
+   switch (format) {
+   case GL_RGB:
+   case GL_BGR:
+      return 3;
+   case GL_422_EXT:
+   case GL_422_REV_EXT:
+   case GL_422_AVERAGE_EXT:
+   case GL_422_REV_AVERAGE_EXT:
+   case GL_YCBCR_422_APPLE:
+   case GL_LUMINANCE_ALPHA:
+      return 2;
+   case GL_RGBA:
+   case GL_BGRA:
+   case GL_ABGR_EXT:
+      return 4;
+   case GL_COLOR_INDEX:
+   case GL_STENCIL_INDEX:
+   case GL_DEPTH_COMPONENT:
+   case GL_RED:
+   case GL_GREEN:
+   case GL_BLUE:
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+   case GL_INTENSITY:
+      return 1;
+   default:
+      return 0;
+   }
+}
+
+/*
+** Return the number of bytes per element, based on the element type (other
+** than GL_BITMAP).
+*/
+GLint
+__glBytesPerElement(GLenum type)
+{
+   switch (type) {
+   case GL_UNSIGNED_SHORT:
+   case GL_SHORT:
+   case GL_UNSIGNED_SHORT_5_6_5:
+   case GL_UNSIGNED_SHORT_5_6_5_REV:
+   case GL_UNSIGNED_SHORT_4_4_4_4:
+   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+   case GL_UNSIGNED_SHORT_5_5_5_1:
+   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+   case GL_UNSIGNED_SHORT_8_8_APPLE:
+   case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
+   case GL_UNSIGNED_SHORT_15_1_MESA:
+   case GL_UNSIGNED_SHORT_1_15_REV_MESA:
+      return 2;
+   case GL_UNSIGNED_BYTE:
+   case GL_BYTE:
+   case GL_UNSIGNED_BYTE_3_3_2:
+   case GL_UNSIGNED_BYTE_2_3_3_REV:
+      return 1;
+   case GL_INT:
+   case GL_UNSIGNED_INT:
+   case GL_FLOAT:
+   case GL_UNSIGNED_INT_8_8_8_8:
+   case GL_UNSIGNED_INT_8_8_8_8_REV:
+   case GL_UNSIGNED_INT_10_10_10_2:
+   case GL_UNSIGNED_INT_2_10_10_10_REV:
+   case GL_UNSIGNED_INT_24_8_NV:
+   case GL_UNSIGNED_INT_24_8_MESA:
+   case GL_UNSIGNED_INT_8_24_REV_MESA:
+      return 4;
+   default:
+      return 0;
+   }
+}
+
+/*
+** Compute memory required for internal packed array of data of given type
+** and format.
+*/
+GLint
+__glImageSize(GLsizei width, GLsizei height, GLsizei depth,
+              GLenum format, GLenum type, GLenum target)
+{
+   int bytes_per_row;
+   int components;
+
+   switch (target) {
+   case GL_PROXY_TEXTURE_1D:
+   case GL_PROXY_TEXTURE_2D:
+   case GL_PROXY_TEXTURE_3D:
+   case GL_PROXY_TEXTURE_4D_SGIS:
+   case GL_PROXY_TEXTURE_CUBE_MAP:
+   case GL_PROXY_TEXTURE_RECTANGLE_ARB:
+   case GL_PROXY_HISTOGRAM:
+   case GL_PROXY_COLOR_TABLE:
+   case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
+   case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
+   case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
+   case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP:
+      return 0;
+   }
+
+   if (width < 0 || height < 0 || depth < 0) {
+      return 0;
+   }
+
+   /*
+    ** Zero is returned if either format or type are invalid.
+    */
+   components = __glElementsPerGroup(format, type);
+   if (type == GL_BITMAP) {
+      if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) {
+         bytes_per_row = (width + 7) >> 3;
+      }
+      else {
+         return 0;
+      }
+   }
+   else {
+      bytes_per_row = __glBytesPerElement(type) * width;
+   }
+
+   return bytes_per_row * height * depth * components;
+}
diff --git a/src/glx/dri2.c b/src/glx/dri2.c
new file mode 100644 (file)
index 0000000..91053d3
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define NEED_REPLIES
+#include <stdio.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/dri2proto.h>
+#include "xf86drm.h"
+#include "dri2.h"
+#include "glxclient.h"
+#include "GL/glxext.h"
+
+/* Allow the build to work with an older versions of dri2proto.h and
+ * dri2tokens.h.
+ */
+#if DRI2_MINOR < 1
+#undef DRI2_MINOR
+#define DRI2_MINOR 1
+#define X_DRI2GetBuffersWithFormat 7
+#endif
+
+
+static char dri2ExtensionName[] = DRI2_NAME;
+static XExtensionInfo *dri2Info;
+static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
+
+static Bool
+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
+static Status
+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
+
+static /* const */ XExtensionHooks dri2ExtensionHooks = {
+  NULL,                   /* create_gc */
+  NULL,                   /* copy_gc */
+  NULL,                   /* flush_gc */
+  NULL,                   /* free_gc */
+  NULL,                   /* create_font */
+  NULL,                   /* free_font */
+  DRI2CloseDisplay,       /* close_display */
+  DRI2WireToEvent,        /* wire_to_event */
+  DRI2EventToWire,        /* event_to_wire */
+  NULL,                   /* error */
+  NULL,                   /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
+                                   dri2Info,
+                                   dri2ExtensionName,
+                                   &dri2ExtensionHooks,
+                                   1, NULL)
+
+static Bool
+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   XExtDisplayInfo *glx_info = __glXFindDisplay(dpy);
+   static int glx_event_base;
+   static Bool found_glx_info = False;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
+
+#ifdef X_DRI2SwapBuffers
+   case DRI2_BufferSwapComplete:
+   {
+      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
+      xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
+      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
+      aevent->type =
+         (glx_info->codes->first_event + GLX_BufferSwapComplete) & 0x75;
+      aevent->send_event = (awire->type & 0x80) != 0;
+      aevent->display = dpy;
+      aevent->drawable = awire->drawable;
+      switch (awire->event_type) {
+      case DRI2_EXCHANGE_COMPLETE:
+        aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+        break;
+      case DRI2_BLIT_COMPLETE:
+        aevent->event_type = GLX_BLIT_COMPLETE_INTEL;
+        break;
+      case DRI2_FLIP_COMPLETE:
+        aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
+        break;
+      default:
+        /* unknown swap completion type */
+        return False;
+      }
+      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
+      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
+      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
+      return True;
+   }
+#endif
+
+   default:
+      /* client doesn't support server event */
+      break;
+   }
+
+   return False;
+}
+
+/* We don't actually support this.  It doesn't make sense for clients to
+ * send each other DRI2 events.
+ */
+static Status
+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   switch (event->type) {
+   default:
+      /* client doesn't support server event */
+      break;
+   }
+
+   return Success;
+}
+
+Bool
+DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+   if (XextHasExtension(info)) {
+      *eventBase = info->codes->first_event;
+      *errorBase = info->codes->first_error;
+      return True;
+   }
+
+   return False;
+}
+
+Bool
+DRI2QueryVersion(Display * dpy, int *major, int *minor)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2QueryVersionReply rep;
+   xDRI2QueryVersionReq *req;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2QueryVersion, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2QueryVersion;
+   req->majorVersion = DRI2_MAJOR;
+   req->minorVersion = DRI2_MINOR;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   *major = rep.majorVersion;
+   *minor = rep.minorVersion;
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return True;
+}
+
+Bool
+DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2ConnectReply rep;
+   xDRI2ConnectReq *req;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2Connect, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2Connect;
+   req->window = window;
+   req->driverType = DRI2DriverDRI;
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   *driverName = Xmalloc(rep.driverNameLength + 1);
+   if (*driverName == NULL) {
+      _XEatData(dpy,
+                ((rep.driverNameLength + 3) & ~3) +
+                ((rep.deviceNameLength + 3) & ~3));
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   _XReadPad(dpy, *driverName, rep.driverNameLength);
+   (*driverName)[rep.driverNameLength] = '\0';
+
+   *deviceName = Xmalloc(rep.deviceNameLength + 1);
+   if (*deviceName == NULL) {
+      Xfree(*driverName);
+      _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+   _XReadPad(dpy, *deviceName, rep.deviceNameLength);
+   (*deviceName)[rep.deviceNameLength] = '\0';
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return True;
+}
+
+Bool
+DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2AuthenticateReq *req;
+   xDRI2AuthenticateReply rep;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2Authenticate, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2Authenticate;
+   req->window = window;
+   req->magic = magic;
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return False;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return rep.authenticated;
+}
+
+void
+DRI2CreateDrawable(Display * dpy, XID drawable)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2CreateDrawableReq *req;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   LockDisplay(dpy);
+   GetReq(DRI2CreateDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2CreateDrawable;
+   req->drawable = drawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+void
+DRI2DestroyDrawable(Display * dpy, XID drawable)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2DestroyDrawableReq *req;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   XSync(dpy, False);
+
+   LockDisplay(dpy);
+   GetReq(DRI2DestroyDrawable, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2DestroyDrawable;
+   req->drawable = drawable;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+DRI2Buffer *
+DRI2GetBuffers(Display * dpy, XID drawable,
+               int *width, int *height,
+               unsigned int *attachments, int count, int *outCount)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2GetBuffersReply rep;
+   xDRI2GetBuffersReq *req;
+   DRI2Buffer *buffers;
+   xDRI2Buffer repBuffer;
+   CARD32 *p;
+   int i;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReqExtra(DRI2GetBuffers, count * 4, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2GetBuffers;
+   req->drawable = drawable;
+   req->count = count;
+   p = (CARD32 *) & req[1];
+   for (i = 0; i < count; i++)
+      p[i] = attachments[i];
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   *width = rep.width;
+   *height = rep.height;
+   *outCount = rep.count;
+
+   buffers = Xmalloc(rep.count * sizeof buffers[0]);
+   if (buffers == NULL) {
+      _XEatData(dpy, rep.count * sizeof repBuffer);
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   for (i = 0; i < rep.count; i++) {
+      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+      buffers[i].attachment = repBuffer.attachment;
+      buffers[i].name = repBuffer.name;
+      buffers[i].pitch = repBuffer.pitch;
+      buffers[i].cpp = repBuffer.cpp;
+      buffers[i].flags = repBuffer.flags;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return buffers;
+}
+
+
+DRI2Buffer *
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+                         int *width, int *height,
+                         unsigned int *attachments, int count, int *outCount)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2GetBuffersReply rep;
+   xDRI2GetBuffersReq *req;
+   DRI2Buffer *buffers;
+   xDRI2Buffer repBuffer;
+   CARD32 *p;
+   int i;
+
+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+   LockDisplay(dpy);
+   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
+   req->drawable = drawable;
+   req->count = count;
+   p = (CARD32 *) & req[1];
+   for (i = 0; i < (count * 2); i++)
+      p[i] = attachments[i];
+
+   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   *width = rep.width;
+   *height = rep.height;
+   *outCount = rep.count;
+
+   buffers = Xmalloc(rep.count * sizeof buffers[0]);
+   if (buffers == NULL) {
+      _XEatData(dpy, rep.count * sizeof repBuffer);
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return NULL;
+   }
+
+   for (i = 0; i < rep.count; i++) {
+      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+      buffers[i].attachment = repBuffer.attachment;
+      buffers[i].name = repBuffer.name;
+      buffers[i].pitch = repBuffer.pitch;
+      buffers[i].cpp = repBuffer.cpp;
+      buffers[i].flags = repBuffer.flags;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return buffers;
+}
+
+
+void
+DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
+               CARD32 dest, CARD32 src)
+{
+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   xDRI2CopyRegionReq *req;
+   xDRI2CopyRegionReply rep;
+
+   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+   LockDisplay(dpy);
+   GetReq(DRI2CopyRegion, req);
+   req->reqType = info->codes->major_opcode;
+   req->dri2ReqType = X_DRI2CopyRegion;
+   req->drawable = drawable;
+   req->region = region;
+   req->dest = dest;
+   req->src = src;
+
+   _XReply(dpy, (xReply *) & rep, 0, xFalse);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+#ifdef X_DRI2SwapBuffers
+static void
+load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
+            CARD64 remainder)
+{
+    req->target_msc_hi = target >> 32;
+    req->target_msc_lo = target & 0xffffffff;
+    req->divisor_hi = divisor >> 32;
+    req->divisor_lo = divisor & 0xffffffff;
+    req->remainder_hi = remainder >> 32;
+    req->remainder_lo = remainder & 0xffffffff;
+}
+
+static CARD64
+vals_to_card64(CARD32 lo, CARD32 hi)
+{
+    return (CARD64)hi << 32 | lo;
+}
+
+void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
+                    CARD64 divisor, CARD64 remainder, CARD64 *count)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2SwapBuffersReq *req;
+    xDRI2SwapBuffersReply rep;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapBuffers, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapBuffers;
+    req->drawable = drawable;
+    load_swap_req(req, target_msc, divisor, remainder);
+
+    _XReply(dpy, (xReply *)&rep, 0, xFalse);
+
+    *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
+
+#ifdef X_DRI2GetMSC
+Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
+               CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2GetMSCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2GetMSC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2GetMSC;
+    req->drawable = drawable;
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
+    *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
+    *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2WaitMSC
+static void
+load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
+            CARD64 remainder)
+{
+    req->target_msc_hi = target >> 32;
+    req->target_msc_lo = target & 0xffffffff;
+    req->divisor_hi = divisor >> 32;
+    req->divisor_lo = divisor & 0xffffffff;
+    req->remainder_hi = remainder >> 32;
+    req->remainder_lo = remainder & 0xffffffff;
+}
+
+Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+                CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2WaitMSCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2WaitMSC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2WaitMSC;
+    req->drawable = drawable;
+    load_msc_req(req, target_msc, divisor, remainder);
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
+    *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
+    *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2WaitSBC
+static void
+load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
+{
+    req->target_sbc_hi = target >> 32;
+    req->target_sbc_lo = target & 0xffffffff;
+}
+
+Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
+                CARD64 *msc, CARD64 *sbc)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2WaitSBCReq *req;
+    xDRI2MSCReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2WaitSBC, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2WaitSBC;
+    req->drawable = drawable;
+    load_sbc_req(req, target_sbc);
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
+    *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
+    *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2SwapInterval
+void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2SwapIntervalReq *req;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapInterval, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapInterval;
+    req->drawable = drawable;
+    req->interval = interval;
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/dri2.h b/src/glx/dri2.h
new file mode 100644 (file)
index 0000000..114e9f8
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2007,2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI2_H_
+#define _DRI2_H_
+
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/dri2tokens.h>
+
+typedef struct
+{
+   unsigned int attachment;
+   unsigned int name;
+   unsigned int pitch;
+   unsigned int cpp;
+   unsigned int flags;
+} DRI2Buffer;
+
+extern Bool
+DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
+
+extern Bool
+DRI2QueryVersion(Display * display, int *major, int *minor);
+
+extern Bool
+DRI2Connect(Display * display, XID window,
+            char **driverName, char **deviceName);
+
+extern Bool
+DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
+
+extern void
+DRI2CreateDrawable(Display * display, XID drawable);
+
+extern void
+DRI2DestroyDrawable(Display * display, XID handle);
+
+extern DRI2Buffer*
+DRI2GetBuffers(Display * dpy, XID drawable,
+               int *width, int *height,
+               unsigned int *attachments, int count,
+               int *outCount);
+
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.1 or later.
+ */
+extern DRI2Buffer*
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+                         int *width, int *height,
+                         unsigned int *attachments,
+                         int count, int *outCount);
+
+extern void
+DRI2CopyRegion(Display * dpy, XID drawable,
+               XserverRegion region,
+               CARD32 dest, CARD32 src);
+
+extern void
+DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+               CARD64 remainder, CARD64 *count);
+
+extern Bool
+DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
+
+extern Bool
+DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
+           CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
+
+extern Bool
+DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
+           CARD64 *msc, CARD64 *sbc);
+
+extern void
+DRI2SwapInterval(Display *dpy, XID drawable, int interval);
+
+#endif
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
new file mode 100644 (file)
index 0000000..15a3ea5
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
+#include "glapi.h"
+#include "glxclient.h"
+#include <X11/extensions/dri2proto.h>
+#include "xf86dri.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "xf86drm.h"
+#include "dri2.h"
+#include "dri_common.h"
+#include "../../mesa/drivers/dri/common/dri_util.h"
+
+#undef DRI2_MINOR
+#define DRI2_MINOR 1
+
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
+typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate;
+
+struct __GLXDRIdisplayPrivateRec
+{
+   __GLXDRIdisplay base;
+
+   /*
+    ** XFree86-DRI version information
+    */
+   int driMajor;
+   int driMinor;
+   int driPatch;
+   int swapAvailable;
+};
+
+struct __GLXDRIcontextPrivateRec
+{
+   __GLXDRIcontext base;
+   __DRIcontext *driContext;
+   __GLXscreenConfigs *psc;
+};
+
+struct __GLXDRIdrawablePrivateRec
+{
+   __GLXDRIdrawable base;
+   __DRIbuffer buffers[5];
+   int bufferCount;
+   int width, height;
+   int have_back;
+   int have_fake_front;
+   int swap_interval;
+};
+
+static void dri2WaitX(__GLXDRIdrawable * pdraw);
+
+static void
+dri2DestroyContext(__GLXDRIcontext * context,
+                   __GLXscreenConfigs * psc, Display * dpy)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   (*core->destroyContext) (pcp->driContext);
+
+   Xfree(pcp);
+}
+
+static Bool
+dri2BindContext(__GLXDRIcontext * context,
+                __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   return (*core->bindContext) (pcp->driContext,
+                                draw->driDrawable, read->driDrawable);
+}
+
+static void
+dri2UnbindContext(__GLXDRIcontext * context)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   (*core->unbindContext) (pcp->driContext);
+}
+
+static __GLXDRIcontext *
+dri2CreateContext(__GLXscreenConfigs * psc,
+                  const __GLcontextModes * mode,
+                  GLXContext gc, GLXContext shareList, int renderType)
+{
+   __GLXDRIcontextPrivate *pcp, *pcp_shared;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+   __DRIcontext *shared = NULL;
+
+   if (shareList) {
+      pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+      shared = pcp_shared->driContext;
+   }
+
+   pcp = Xmalloc(sizeof *pcp);
+   if (pcp == NULL)
+      return NULL;
+
+   pcp->psc = psc;
+   pcp->driContext =
+      (*psc->dri2->createNewContext) (psc->__driScreen,
+                                      config->driConfig, shared, pcp);
+   gc->__driContext = pcp->driContext;
+
+   if (pcp->driContext == NULL) {
+      Xfree(pcp);
+      return NULL;
+   }
+
+   pcp->base.destroyContext = dri2DestroyContext;
+   pcp->base.bindContext = dri2BindContext;
+   pcp->base.unbindContext = dri2UnbindContext;
+
+   return &pcp->base;
+}
+
+static void
+dri2DestroyDrawable(__GLXDRIdrawable * pdraw)
+{
+   const __DRIcoreExtension *core = pdraw->psc->core;
+
+   (*core->destroyDrawable) (pdraw->driDrawable);
+   DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable);
+   Xfree(pdraw);
+}
+
+static __GLXDRIdrawable *
+dri2CreateDrawable(__GLXscreenConfigs * psc,
+                   XID xDrawable,
+                   GLXDrawable drawable, const __GLcontextModes * modes)
+{
+   __GLXDRIdrawablePrivate *pdraw;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+
+   pdraw = Xmalloc(sizeof(*pdraw));
+   if (!pdraw)
+      return NULL;
+
+   pdraw->base.destroyDrawable = dri2DestroyDrawable;
+   pdraw->base.xDrawable = xDrawable;
+   pdraw->base.drawable = drawable;
+   pdraw->base.psc = psc;
+   pdraw->bufferCount = 0;
+
+   DRI2CreateDrawable(psc->dpy, xDrawable);
+
+   /* Create a new drawable */
+   pdraw->base.driDrawable =
+      (*psc->dri2->createNewDrawable) (psc->__driScreen,
+                                       config->driConfig, pdraw);
+
+   if (!pdraw->base.driDrawable) {
+      DRI2DestroyDrawable(psc->dpy, xDrawable);
+      Xfree(pdraw);
+      return NULL;
+   }
+
+   return &pdraw->base;
+}
+
+static int
+dri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw,
+                  int64_t *ust, int64_t *msc, int64_t *sbc)
+{
+   return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc);
+}
+
+static int
+dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
+              int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
+{
+   return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
+                     remainder, ust, msc, sbc);
+}
+
+static int
+dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
+              int64_t *msc, int64_t *sbc)
+{
+   return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc,
+                     sbc);
+}
+
+static void
+dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
+{
+   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+   XRectangle xrect;
+   XserverRegion region;
+
+   /* Check we have the right attachments */
+   if (!priv->have_back)
+      return;
+
+   xrect.x = x;
+   xrect.y = priv->height - y - height;
+   xrect.width = width;
+   xrect.height = height;
+
+#ifdef __DRI2_FLUSH
+   if (pdraw->psc->f)
+      (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+   /* should get a fence ID back from here at some point */
+   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+                  DRI2BufferFrontLeft, DRI2BufferBackLeft);
+   XFixesDestroyRegion(pdraw->psc->dpy, region);
+
+   /* Refresh the fake front (if present) after we just damaged the real
+    * front.
+    */
+   dri2WaitX(pdraw);
+}
+
+static void
+dri2WaitX(__GLXDRIdrawable *pdraw)
+{
+   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+   XRectangle xrect;
+   XserverRegion region;
+
+   /* Check we have the right attachments */
+   if (!priv->have_fake_front)
+      return;
+
+   xrect.x = 0;
+   xrect.y = 0;
+   xrect.width = priv->width;
+   xrect.height = priv->height;
+
+#ifdef __DRI2_FLUSH
+   if (pdraw->psc->f)
+      (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+                  DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+   XFixesDestroyRegion(pdraw->psc->dpy, region);
+}
+
+static void
+dri2WaitGL(__GLXDRIdrawable * pdraw)
+{
+   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+   XRectangle xrect;
+   XserverRegion region;
+
+   if (!priv->have_fake_front)
+      return;
+
+   xrect.x = 0;
+   xrect.y = 0;
+   xrect.width = priv->width;
+   xrect.height = priv->height;
+
+#ifdef __DRI2_FLUSH
+   if (pdraw->psc->f)
+      (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+                  DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+   XFixesDestroyRegion(pdraw->psc->dpy, region);
+}
+
+
+static void
+dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+   (void) driDrawable;
+   dri2WaitGL((__GLXDRIdrawable *) loaderPrivate);
+}
+
+
+static void
+dri2DestroyScreen(__GLXscreenConfigs * psc)
+{
+   /* Free the direct rendering per screen data */
+   (*psc->core->destroyScreen) (psc->__driScreen);
+   close(psc->fd);
+   psc->__driScreen = NULL;
+}
+
+/**
+ * Process list of buffer received from the server
+ *
+ * Processes the list of buffers received in a reply from the server to either
+ * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
+ */
+static void
+process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers,
+                unsigned count)
+{
+   int i;
+
+   pdraw->bufferCount = count;
+   pdraw->have_fake_front = 0;
+   pdraw->have_back = 0;
+
+   /* This assumes the DRI2 buffer attachment tokens matches the
+    * __DRIbuffer tokens. */
+   for (i = 0; i < count; i++) {
+      pdraw->buffers[i].attachment = buffers[i].attachment;
+      pdraw->buffers[i].name = buffers[i].name;
+      pdraw->buffers[i].pitch = buffers[i].pitch;
+      pdraw->buffers[i].cpp = buffers[i].cpp;
+      pdraw->buffers[i].flags = buffers[i].flags;
+      if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
+         pdraw->have_fake_front = 1;
+      if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
+         pdraw->have_back = 1;
+   }
+
+}
+
+static int64_t
+dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
+               int64_t remainder)
+{
+    __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+    __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy);
+    __GLXDRIdisplayPrivate *pdp =
+       (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;
+    int64_t ret;
+
+#ifdef __DRI2_FLUSH
+    if (pdraw->psc->f)
+       (*pdraw->psc->f->flush)(pdraw->driDrawable);
+#endif
+
+    /* Old servers can't handle swapbuffers */
+    if (!pdp->swapAvailable) {
+       dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+       return 0;
+    }
+
+#ifdef X_DRI2SwapBuffers
+    DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
+                   remainder, &ret);
+#endif
+
+#if __DRI2_FLUSH_VERSION >= 2
+    if (pdraw->psc->f)
+       (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
+#endif
+
+    return ret;
+}
+
+static __DRIbuffer *
+dri2GetBuffers(__DRIdrawable * driDrawable,
+               int *width, int *height,
+               unsigned int *attachments, int count,
+               int *out_count, void *loaderPrivate)
+{
+   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+   DRI2Buffer *buffers;
+
+   buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
+                            width, height, attachments, count, out_count);
+   if (buffers == NULL)
+      return NULL;
+
+   pdraw->width = *width;
+   pdraw->height = *height;
+   process_buffers(pdraw, buffers, *out_count);
+
+   Xfree(buffers);
+
+   return pdraw->buffers;
+}
+
+static __DRIbuffer *
+dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
+                         int *width, int *height,
+                         unsigned int *attachments, int count,
+                         int *out_count, void *loaderPrivate)
+{
+   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+   DRI2Buffer *buffers;
+
+   buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
+                                      pdraw->base.xDrawable,
+                                      width, height, attachments,
+                                      count, out_count);
+   if (buffers == NULL)
+      return NULL;
+
+   pdraw->width = *width;
+   pdraw->height = *height;
+   process_buffers(pdraw, buffers, *out_count);
+
+   Xfree(buffers);
+
+   return pdraw->buffers;
+}
+
+static void
+dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
+{
+   __GLXDRIdrawablePrivate *priv =  (__GLXDRIdrawablePrivate *) pdraw;
+
+   DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval);
+   priv->swap_interval = interval;
+}
+
+static unsigned int
+dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
+{
+   __GLXDRIdrawablePrivate *priv =  (__GLXDRIdrawablePrivate *) pdraw;
+
+  return priv->swap_interval;
+}
+
+static const __DRIdri2LoaderExtension dri2LoaderExtension = {
+   {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
+   dri2GetBuffers,
+   dri2FlushFrontBuffer,
+   dri2GetBuffersWithFormat,
+};
+
+static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
+   {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
+   dri2GetBuffers,
+   dri2FlushFrontBuffer,
+   NULL,
+};
+
+static const __DRIextension *loader_extensions[] = {
+   &dri2LoaderExtension.base,
+   &systemTimeExtension.base,
+   NULL
+};
+
+static const __DRIextension *loader_extensions_old[] = {
+   &dri2LoaderExtension_old.base,
+   &systemTimeExtension.base,
+   NULL
+};
+
+static __GLXDRIscreen *
+dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
+                 __GLXdisplayPrivate * priv)
+{
+   const __DRIconfig **driver_configs;
+   const __DRIextension **extensions;
+   const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
+      priv->dri2Display;
+   __GLXDRIscreen *psp;
+   char *driverName, *deviceName;
+   drm_magic_t magic;
+   int i;
+
+   psp = Xmalloc(sizeof *psp);
+   if (psp == NULL)
+      return NULL;
+
+   /* Initialize per screen dynamic client GLX extensions */
+   psc->ext_list_first_time = GL_TRUE;
+
+   if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
+                   &driverName, &deviceName)) {
+      XFree(psp);
+      return NULL;
+   }
+
+   psc->driver = driOpenDriver(driverName);
+   if (psc->driver == NULL) {
+      ErrorMessageF("driver pointer missing\n");
+      goto handle_error;
+   }
+
+   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+   if (extensions == NULL) {
+      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+      goto handle_error;
+   }
+
+   for (i = 0; extensions[i]; i++) {
+      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+        psc->core = (__DRIcoreExtension *) extensions[i];
+      if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
+        psc->dri2 = (__DRIdri2Extension *) extensions[i];
+   }
+
+   if (psc->core == NULL || psc->dri2 == NULL) {
+      ErrorMessageF("core dri or dri2 extension not found\n");
+      goto handle_error;
+   }
+
+   psc->fd = open(deviceName, O_RDWR);
+   if (psc->fd < 0) {
+      ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
+      goto handle_error;
+   }
+
+   if (drmGetMagic(psc->fd, &magic)) {
+      ErrorMessageF("failed to get magic\n");
+      goto handle_error;
+   }
+
+   if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
+      ErrorMessageF("failed to authenticate magic %d\n", magic);
+      goto handle_error;
+   }
+
+   /* If the server does not support the protocol for
+    * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
+    */
+   psc->__driScreen =
+      psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
+                                                  ? loader_extensions_old
+                                                  : loader_extensions),
+                                &driver_configs, psc);
+
+   if (psc->__driScreen == NULL) {
+      ErrorMessageF("failed to create dri screen\n");
+      goto handle_error;
+   }
+
+   driBindCommonExtensions(psc);
+   dri2BindExtensions(psc);
+
+   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+   psc->driver_configs = driver_configs;
+
+   psp->destroyScreen = dri2DestroyScreen;
+   psp->createContext = dri2CreateContext;
+   psp->createDrawable = dri2CreateDrawable;
+   psp->swapBuffers = dri2SwapBuffers;
+   psp->waitGL = dri2WaitGL;
+   psp->waitX = dri2WaitX;
+   psp->getDrawableMSC = NULL;
+   psp->waitForMSC = NULL;
+   psp->waitForSBC = NULL;
+   psp->setSwapInterval = NULL;
+   psp->getSwapInterval = NULL;
+
+   if (pdp->driMinor >= 2) {
+#ifdef X_DRI2GetMSC
+      psp->getDrawableMSC = dri2DrawableGetMSC;
+#endif
+#ifdef X_DRI2WaitMSC
+      psp->waitForMSC = dri2WaitForMSC;
+      psp->waitForSBC = dri2WaitForSBC;
+#endif
+#ifdef X_DRI2SwapInterval
+      psp->setSwapInterval = dri2SetSwapInterval;
+      psp->getSwapInterval = dri2GetSwapInterval;
+#endif
+   }
+
+   /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
+    * available.*/
+   psp->copySubBuffer = dri2CopySubBuffer;
+   __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
+
+   Xfree(driverName);
+   Xfree(deviceName);
+
+   return psp;
+
+handle_error:
+   Xfree(driverName);
+   Xfree(deviceName);
+   XFree(psp);
+
+   /* FIXME: clean up here */
+
+   return NULL;
+}
+
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void
+dri2DestroyDisplay(__GLXDRIdisplay * dpy)
+{
+   Xfree(dpy);
+}
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+_X_HIDDEN __GLXDRIdisplay *
+dri2CreateDisplay(Display * dpy)
+{
+   __GLXDRIdisplayPrivate *pdp;
+   int eventBase, errorBase;
+
+   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
+      return NULL;
+
+   pdp = Xmalloc(sizeof *pdp);
+   if (pdp == NULL)
+      return NULL;
+
+   if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
+      Xfree(pdp);
+      return NULL;
+   }
+
+   pdp->driPatch = 0;
+   pdp->swapAvailable = 0;
+#ifdef X_DRI2SwapBuffers
+   if (pdp->driMinor >= 2)
+      pdp->swapAvailable = 1;
+#endif
+
+   pdp->base.destroyDisplay = dri2DestroyDisplay;
+   pdp->base.createScreen = dri2CreateScreen;
+
+   return &pdp->base;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c
new file mode 100644 (file)
index 0000000..e403416
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <unistd.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include "glxclient.h"
+#include "glcontextmodes.h"
+#include "dri_common.h"
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+_X_HIDDEN void
+InfoMessageF(const char *f, ...)
+{
+   va_list args;
+   const char *env;
+
+   if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
+      fprintf(stderr, "libGL: ");
+      va_start(args, f);
+      vfprintf(stderr, f, args);
+      va_end(args);
+   }
+}
+
+/**
+ * Print error to stderr, unless LIBGL_DEBUG=="quiet".
+ */
+_X_HIDDEN void
+ErrorMessageF(const char *f, ...)
+{
+   va_list args;
+   const char *env;
+
+   if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
+      fprintf(stderr, "libGL error: ");
+      va_start(args, f);
+      vfprintf(stderr, f, args);
+      va_end(args);
+   }
+}
+
+#ifndef DEFAULT_DRIVER_DIR
+/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
+#define DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
+#endif
+
+/**
+ * Try to \c dlopen the named driver.
+ *
+ * This function adds the "_dri.so" suffix to the driver name and searches the
+ * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
+ * order to find the driver.
+ *
+ * \param driverName - a name like "tdfx", "i810", "mga", etc.
+ *
+ * \returns
+ * A handle from \c dlopen, or \c NULL if driver file not found.
+ */
+_X_HIDDEN void *
+driOpenDriver(const char *driverName)
+{
+   void *glhandle, *handle;
+   const char *libPaths, *p, *next;
+   char realDriverName[200];
+   int len;
+
+   /* Attempt to make sure libGL symbols will be visible to the driver */
+   glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
+
+   libPaths = NULL;
+   if (geteuid() == getuid()) {
+      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
+      libPaths = getenv("LIBGL_DRIVERS_PATH");
+      if (!libPaths)
+         libPaths = getenv("LIBGL_DRIVERS_DIR");        /* deprecated */
+   }
+   if (libPaths == NULL)
+      libPaths = DEFAULT_DRIVER_DIR;
+
+   handle = NULL;
+   for (p = libPaths; *p; p = next) {
+      next = strchr(p, ':');
+      if (next == NULL) {
+         len = strlen(p);
+         next = p + len;
+      }
+      else {
+         len = next - p;
+         next++;
+      }
+
+#ifdef GLX_USE_TLS
+      snprintf(realDriverName, sizeof realDriverName,
+               "%.*s/tls/%s_dri.so", len, p, driverName);
+      InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+      handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+#endif
+
+      if (handle == NULL) {
+         snprintf(realDriverName, sizeof realDriverName,
+                  "%.*s/%s_dri.so", len, p, driverName);
+         InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+         handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+      }
+
+      if (handle != NULL)
+         break;
+      else
+         ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
+   }
+
+   if (!handle)
+      ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);
+
+   if (glhandle)
+      dlclose(glhandle);
+
+   return handle;
+}
+
+_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = {
+   {__DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION},
+   __glXGetUST,
+   __driGetMscRateOML
+};
+
+#define __ATTRIB(attrib, field) \
+    { attrib, offsetof(__GLcontextModes, field) }
+
+static const struct
+{
+   unsigned int attrib, offset;
+} attribMap[] = {
+   __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
+      __ATTRIB(__DRI_ATTRIB_LEVEL, level),
+      __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
+      __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
+      __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
+      __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
+      __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
+      __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
+      __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
+      __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
+      __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
+      __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
+      __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
+      __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
+      __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
+      __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
+      __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
+#if 0
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex),
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
+      __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
+      __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
+      __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
+      __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
+      __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
+#endif
+      __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
+      __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
+      __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
+      __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
+      __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
+#if 0
+      __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
+#endif
+__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
+      __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
+      __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,
+                     bindToMipmapTexture),
+      __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+static int
+scalarEqual(__GLcontextModes * mode, unsigned int attrib, unsigned int value)
+{
+   unsigned int glxValue;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(attribMap); i++)
+      if (attribMap[i].attrib == attrib) {
+         glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
+         return glxValue == GLX_DONT_CARE || glxValue == value;
+      }
+
+   return GL_TRUE;              /* Is a non-existing attribute equal to value? */
+}
+
+static int
+driConfigEqual(const __DRIcoreExtension * core,
+               __GLcontextModes * modes, const __DRIconfig * driConfig)
+{
+   unsigned int attrib, value, glxValue;
+   int i;
+
+   i = 0;
+   while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
+      switch (attrib) {
+      case __DRI_ATTRIB_RENDER_TYPE:
+         glxValue = 0;
+         if (value & __DRI_ATTRIB_RGBA_BIT) {
+            glxValue |= GLX_RGBA_BIT;
+         }
+         else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
+            glxValue |= GLX_COLOR_INDEX_BIT;
+         }
+         if (glxValue != modes->renderType)
+            return GL_FALSE;
+         break;
+
+      case __DRI_ATTRIB_CONFIG_CAVEAT:
+         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+            glxValue = GLX_NON_CONFORMANT_CONFIG;
+         else if (value & __DRI_ATTRIB_SLOW_BIT)
+            glxValue = GLX_SLOW_CONFIG;
+         else
+            glxValue = GLX_NONE;
+         if (glxValue != modes->visualRating)
+            return GL_FALSE;
+         break;
+
+      case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
+         glxValue = 0;
+         if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
+            glxValue |= GLX_TEXTURE_1D_BIT_EXT;
+         if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
+            glxValue |= GLX_TEXTURE_2D_BIT_EXT;
+         if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
+            glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
+         if (modes->bindToTextureTargets != GLX_DONT_CARE &&
+             glxValue != modes->bindToTextureTargets)
+            return GL_FALSE;
+         break;
+
+      default:
+         if (!scalarEqual(modes, attrib, value))
+            return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+static __GLcontextModes *
+createDriMode(const __DRIcoreExtension * core,
+              __GLcontextModes * modes, const __DRIconfig ** driConfigs)
+{
+   __GLXDRIconfigPrivate *config;
+   int i;
+
+   for (i = 0; driConfigs[i]; i++) {
+      if (driConfigEqual(core, modes, driConfigs[i]))
+         break;
+   }
+
+   if (driConfigs[i] == NULL)
+      return NULL;
+
+   config = Xmalloc(sizeof *config);
+   if (config == NULL)
+      return NULL;
+
+   config->modes = *modes;
+   config->driConfig = driConfigs[i];
+
+   return &config->modes;
+}
+
+_X_HIDDEN __GLcontextModes *
+driConvertConfigs(const __DRIcoreExtension * core,
+                  __GLcontextModes * modes, const __DRIconfig ** configs)
+{
+   __GLcontextModes head, *tail, *m;
+
+   tail = &head;
+   head.next = NULL;
+   for (m = modes; m; m = m->next) {
+      tail->next = createDriMode(core, m, configs);
+      if (tail->next == NULL) {
+         /* no matching dri config for m */
+         continue;
+      }
+
+
+      tail = tail->next;
+   }
+
+   _gl_context_modes_destroy(modes);
+
+   return head.next;
+}
+
+/* Bind DRI1 specific extensions */
+_X_HIDDEN void
+driBindExtensions(__GLXscreenConfigs *psc)
+{
+   const __DRIextension **extensions;
+   int i;
+
+   extensions = psc->core->getExtensions(psc->__driScreen);
+
+   for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_SWAP_CONTROL
+      /* No DRI2 support for swap_control at the moment, since SwapBuffers
+       * is done by the X server */
+      if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
+        psc->swapControl = (__DRIswapControlExtension *) extensions[i];
+        __glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
+        __glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
+      }
+#endif
+
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+      if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
+         psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
+         __glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
+      }
+#endif
+
+#ifdef __DRI_SWAP_BUFFER_COUNTER
+      /* No driver supports this at this time and the extension is
+       * not defined in dri_interface.h.  Will enable
+       * GLX_OML_sync_control if implemented. */
+#endif
+
+      /* Ignore unknown extensions */
+   }
+}
+
+/* Bind DRI2 specific extensions */
+_X_HIDDEN void
+dri2BindExtensions(__GLXscreenConfigs *psc)
+{
+   const __DRIextension **extensions;
+   int i;
+
+   extensions = psc->core->getExtensions(psc->__driScreen);
+
+   for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_TEX_BUFFER
+      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
+        psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
+        __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap");
+      }
+#endif
+
+      __glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
+      __glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
+      __glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
+
+      /* FIXME: if DRI2 version supports it... */
+      __glXEnableDirectExtension(psc, "INTEL_swap_event");
+
+#ifdef __DRI2_FLUSH
+      if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
+        psc->f = (__DRI2flushExtension *) extensions[i];
+        /* internal driver extension, no GL extension exposed */
+      }
+#endif
+   }
+}
+
+/* Bind extensions common to DRI1 and DRI2 */
+_X_HIDDEN void
+driBindCommonExtensions(__GLXscreenConfigs *psc)
+{
+   const __DRIextension **extensions;
+   int i;
+
+   extensions = psc->core->getExtensions(psc->__driScreen);
+
+   for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_COPY_SUB_BUFFER
+      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
+        psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
+        __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
+      }
+#endif
+
+#ifdef __DRI_ALLOCATE
+      if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) {
+        psc->allocate = (__DRIallocateExtension *) extensions[i];
+        __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory");
+      }
+#endif
+
+#ifdef __DRI_FRAME_TRACKING
+      if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) {
+        psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i];
+        __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage");
+      }
+#endif
+
+#ifdef __DRI_READ_DRAWABLE
+      if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+        __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read");
+      }
+#endif
+
+      /* Ignore unknown extensions */
+   }
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/dri_common.h b/src/glx/dri_common.h
new file mode 100644 (file)
index 0000000..bb178db
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI_COMMON_H
+#define _DRI_COMMON_H
+
+typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate;
+
+struct __GLXDRIconfigPrivateRec
+{
+   __GLcontextModes modes;
+   const __DRIconfig *driConfig;
+};
+
+extern __GLcontextModes *driConvertConfigs(const __DRIcoreExtension * core,
+                                           __GLcontextModes * modes,
+                                           const __DRIconfig ** configs);
+
+extern const __DRIsystemTimeExtension systemTimeExtension;
+
+extern void InfoMessageF(const char *f, ...);
+
+extern void ErrorMessageF(const char *f, ...);
+
+extern void *driOpenDriver(const char *driverName);
+
+extern void driBindExtensions(__GLXscreenConfigs * psc);
+extern void dri2BindExtensions(__GLXscreenConfigs * psc);
+extern void driBindCommonExtensions(__GLXscreenConfigs * psc);
+
+#endif /* _DRI_COMMON_H */
diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c
new file mode 100644 (file)
index 0000000..0ff53c3
--- /dev/null
@@ -0,0 +1,751 @@
+/**************************************************************************
+
+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>
+ *
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
+#include "glxclient.h"
+#include "xf86dri.h"
+#include "dri2.h"
+#include "sarea.h"
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "xf86drm.h"
+#include "dri_common.h"
+
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
+
+struct __GLXDRIdisplayPrivateRec
+{
+   __GLXDRIdisplay base;
+
+   /*
+    ** XFree86-DRI version information
+    */
+   int driMajor;
+   int driMinor;
+   int driPatch;
+};
+
+struct __GLXDRIcontextPrivateRec
+{
+   __GLXDRIcontext base;
+   __DRIcontext *driContext;
+   XID hwContextID;
+   __GLXscreenConfigs *psc;
+};
+
+/*
+ * Given a display pointer and screen number, determine the name of
+ * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
+ * Return True for success, False for failure.
+ */
+static Bool
+driGetDriverName(Display * dpy, int scrNum, char **driverName)
+{
+   int directCapable;
+   Bool b;
+   int event, error;
+   int driverMajor, driverMinor, driverPatch;
+
+   *driverName = NULL;
+
+   if (XF86DRIQueryExtension(dpy, &event, &error)) {    /* DRI1 */
+      if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
+         ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
+         return False;
+      }
+      if (!directCapable) {
+         ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
+         return False;
+      }
+
+      b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
+                                     &driverPatch, driverName);
+      if (!b) {
+         ErrorMessageF("Cannot determine driver name for screen %d\n",
+                       scrNum);
+         return False;
+      }
+
+      InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
+                   driverMajor, driverMinor, driverPatch, *driverName,
+                   scrNum);
+
+      return True;
+   }
+   else if (DRI2QueryExtension(dpy, &event, &error)) {  /* DRI2 */
+      char *dev;
+      Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
+
+      if (ret)
+         Xfree(dev);
+
+      return ret;
+   }
+
+   return False;
+}
+
+/*
+ * Exported function for querying the DRI driver for a given screen.
+ *
+ * The returned char pointer points to a static array that will be
+ * overwritten by subsequent calls.
+ */
+PUBLIC const char *
+glXGetScreenDriver(Display * dpy, int scrNum)
+{
+   static char ret[32];
+   char *driverName;
+   if (driGetDriverName(dpy, scrNum, &driverName)) {
+      int len;
+      if (!driverName)
+         return NULL;
+      len = strlen(driverName);
+      if (len >= 31)
+         return NULL;
+      memcpy(ret, driverName, len + 1);
+      Xfree(driverName);
+      return ret;
+   }
+   return NULL;
+}
+
+/*
+ * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
+ *
+ * The returned char pointer points directly into the driver. Therefore
+ * it should be treated as a constant.
+ *
+ * If the driver was not found or does not support configuration NULL is
+ * returned.
+ *
+ * Note: The driver remains opened after this function returns.
+ */
+PUBLIC const char *
+glXGetDriverConfig(const char *driverName)
+{
+   void *handle = driOpenDriver(driverName);
+   if (handle)
+      return dlsym(handle, "__driConfigOptions");
+   else
+      return NULL;
+}
+
+#ifdef XDAMAGE_1_1_INTERFACE
+
+static GLboolean
+has_damage_post(Display * dpy)
+{
+   static GLboolean inited = GL_FALSE;
+   static GLboolean has_damage;
+
+   if (!inited) {
+      int major, minor;
+
+      if (XDamageQueryVersion(dpy, &major, &minor) &&
+          major == 1 && minor >= 1) {
+         has_damage = GL_TRUE;
+      }
+      else {
+         has_damage = GL_FALSE;
+      }
+      inited = GL_TRUE;
+   }
+
+   return has_damage;
+}
+
+static void
+__glXReportDamage(__DRIdrawable * driDraw,
+                  int x, int y,
+                  drm_clip_rect_t * rects, int num_rects,
+                  GLboolean front_buffer, void *loaderPrivate)
+{
+   XRectangle *xrects;
+   XserverRegion region;
+   int i;
+   int x_off, y_off;
+   __GLXDRIdrawable *glxDraw = loaderPrivate;
+   __GLXscreenConfigs *psc = glxDraw->psc;
+   Display *dpy = psc->dpy;
+   Drawable drawable;
+
+   if (!has_damage_post(dpy))
+      return;
+
+   if (front_buffer) {
+      x_off = x;
+      y_off = y;
+      drawable = RootWindow(dpy, psc->scr);
+   }
+   else {
+      x_off = 0;
+      y_off = 0;
+      drawable = glxDraw->xDrawable;
+   }
+
+   xrects = malloc(sizeof(XRectangle) * num_rects);
+   if (xrects == NULL)
+      return;
+
+   for (i = 0; i < num_rects; i++) {
+      xrects[i].x = rects[i].x1 + x_off;
+      xrects[i].y = rects[i].y1 + y_off;
+      xrects[i].width = rects[i].x2 - rects[i].x1;
+      xrects[i].height = rects[i].y2 - rects[i].y1;
+   }
+   region = XFixesCreateRegion(dpy, xrects, num_rects);
+   free(xrects);
+   XDamageAdd(dpy, drawable, region);
+   XFixesDestroyRegion(dpy, region);
+}
+
+static const __DRIdamageExtension damageExtension = {
+   {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
+   __glXReportDamage,
+};
+
+#endif
+
+static GLboolean
+__glXDRIGetDrawableInfo(__DRIdrawable * drawable,
+                        unsigned int *index, unsigned int *stamp,
+                        int *X, int *Y, int *W, int *H,
+                        int *numClipRects, drm_clip_rect_t ** pClipRects,
+                        int *backX, int *backY,
+                        int *numBackClipRects,
+                        drm_clip_rect_t ** pBackClipRects,
+                        void *loaderPrivate)
+{
+   __GLXDRIdrawable *glxDraw = loaderPrivate;
+   __GLXscreenConfigs *psc = glxDraw->psc;
+   Display *dpy = psc->dpy;
+
+   return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
+                                 index, stamp, X, Y, W, H,
+                                 numClipRects, pClipRects,
+                                 backX, backY,
+                                 numBackClipRects, pBackClipRects);
+}
+
+static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
+   {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
+   __glXDRIGetDrawableInfo
+};
+
+static const __DRIextension *loader_extensions[] = {
+   &systemTimeExtension.base,
+   &getDrawableInfoExtension.base,
+#ifdef XDAMAGE_1_1_INTERFACE
+   &damageExtension.base,
+#endif
+   NULL
+};
+
+/**
+ * Perform the required libGL-side initialization and call the client-side
+ * driver's \c __driCreateNewScreen function.
+ * 
+ * \param dpy    Display pointer.
+ * \param scrn   Screen number on the display.
+ * \param psc    DRI screen information.
+ * \param driDpy DRI display information.
+ * \param createNewScreen  Pointer to the client-side driver's
+ *               \c __driCreateNewScreen function.
+ * \returns A pointer to the \c __DRIscreen structure returned by
+ *          the client-side driver on success, or \c NULL on failure.
+ */
+static void *
+CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
+                    __GLXDRIdisplayPrivate * driDpy)
+{
+   void *psp = NULL;
+   drm_handle_t hSAREA;
+   drmAddress pSAREA = MAP_FAILED;
+   char *BusID;
+   __DRIversion ddx_version;
+   __DRIversion dri_version;
+   __DRIversion drm_version;
+   __DRIframebuffer framebuffer;
+   int fd = -1;
+   int status;
+
+   drm_magic_t magic;
+   drmVersionPtr version;
+   int newlyopened;
+   char *driverName;
+   drm_handle_t hFB;
+   int junk;
+   const __DRIconfig **driver_configs;
+   __GLcontextModes *visual;
+
+   /* DRI protocol version. */
+   dri_version.major = driDpy->driMajor;
+   dri_version.minor = driDpy->driMinor;
+   dri_version.patch = driDpy->driPatch;
+
+   framebuffer.base = MAP_FAILED;
+   framebuffer.dev_priv = NULL;
+
+   if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+      ErrorMessageF("XF86DRIOpenConnection failed\n");
+      goto handle_error;
+   }
+
+   fd = drmOpenOnce(NULL, BusID, &newlyopened);
+
+   Xfree(BusID);                /* No longer needed */
+
+   if (fd < 0) {
+      ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
+      goto handle_error;
+   }
+
+   if (drmGetMagic(fd, &magic)) {
+      ErrorMessageF("drmGetMagic failed\n");
+      goto handle_error;
+   }
+
+   version = drmGetVersion(fd);
+   if (version) {
+      drm_version.major = version->version_major;
+      drm_version.minor = version->version_minor;
+      drm_version.patch = version->version_patchlevel;
+      drmFreeVersion(version);
+   }
+   else {
+      drm_version.major = -1;
+      drm_version.minor = -1;
+      drm_version.patch = -1;
+   }
+
+   if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
+      ErrorMessageF("XF86DRIAuthConnection failed\n");
+      goto handle_error;
+   }
+
+   /* Get device name (like "tdfx") and the ddx version numbers.
+    * We'll check the version in each DRI driver's "createNewScreen"
+    * function. */
+   if (!XF86DRIGetClientDriverName(dpy, scrn,
+                                   &ddx_version.major,
+                                   &ddx_version.minor,
+                                   &ddx_version.patch, &driverName)) {
+      ErrorMessageF("XF86DRIGetClientDriverName failed\n");
+      goto handle_error;
+   }
+
+   Xfree(driverName);           /* No longer needed. */
+
+   /*
+    * Get device-specific info.  pDevPriv will point to a struct
+    * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
+    * has information about the screen size, depth, pitch, ancilliary
+    * buffers, DRM mmap handles, etc.
+    */
+   if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
+                             &framebuffer.size, &framebuffer.stride,
+                             &framebuffer.dev_priv_size,
+                             &framebuffer.dev_priv)) {
+      ErrorMessageF("XF86DRIGetDeviceInfo failed");
+      goto handle_error;
+   }
+
+   framebuffer.width = DisplayWidth(dpy, scrn);
+   framebuffer.height = DisplayHeight(dpy, scrn);
+
+   /* Map the framebuffer region. */
+   status = drmMap(fd, hFB, framebuffer.size,
+                   (drmAddressPtr) & framebuffer.base);
+   if (status != 0) {
+      ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
+      goto handle_error;
+   }
+
+   /* Map the SAREA region.  Further mmap regions may be setup in
+    * each DRI driver's "createNewScreen" function.
+    */
+   status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
+   if (status != 0) {
+      ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
+      goto handle_error;
+   }
+
+   psp = (*psc->legacy->createNewScreen) (scrn,
+                                          &ddx_version,
+                                          &dri_version,
+                                          &drm_version,
+                                          &framebuffer,
+                                          pSAREA,
+                                          fd,
+                                          loader_extensions,
+                                          &driver_configs, psc);
+
+   if (psp == NULL) {
+      ErrorMessageF("Calling driver entry point failed");
+      goto handle_error;
+   }
+
+   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+   psc->driver_configs = driver_configs;
+
+   /* Visuals with depth != screen depth are subject to automatic compositing
+    * in the X server, so DRI1 can't render to them properly. Mark them as
+    * non-conformant to prevent apps from picking them up accidentally.
+    */
+   for (visual = psc->visuals; visual; visual = visual->next) {
+      XVisualInfo template;
+      XVisualInfo *visuals;
+      int num_visuals;
+      long mask;
+
+      template.visualid = visual->visualID;
+      mask = VisualIDMask;
+      visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
+
+      if (visuals) {
+         if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
+            visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
+
+         XFree(visuals);
+      }
+   }
+
+   return psp;
+
+ handle_error:
+   if (pSAREA != MAP_FAILED)
+      drmUnmap(pSAREA, SAREA_MAX);
+
+   if (framebuffer.base != MAP_FAILED)
+      drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
+
+   if (framebuffer.dev_priv != NULL)
+      Xfree(framebuffer.dev_priv);
+
+   if (fd >= 0)
+      drmCloseOnce(fd);
+
+   XF86DRICloseConnection(dpy, scrn);
+
+   ErrorMessageF("reverting to software direct rendering\n");
+
+   return NULL;
+}
+
+static void
+driDestroyContext(__GLXDRIcontext * context,
+                  __GLXscreenConfigs * psc, Display * dpy)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+
+   (*psc->core->destroyContext) (pcp->driContext);
+
+   XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+   Xfree(pcp);
+}
+
+static Bool
+driBindContext(__GLXDRIcontext * context,
+               __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   return (*core->bindContext) (pcp->driContext,
+                                draw->driDrawable, read->driDrawable);
+}
+
+static void
+driUnbindContext(__GLXDRIcontext * context)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   (*core->unbindContext) (pcp->driContext);
+}
+
+static __GLXDRIcontext *
+driCreateContext(__GLXscreenConfigs * psc,
+                 const __GLcontextModes * mode,
+                 GLXContext gc, GLXContext shareList, int renderType)
+{
+   __GLXDRIcontextPrivate *pcp, *pcp_shared;
+   drm_context_t hwContext;
+   __DRIcontext *shared = NULL;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+
+   if (!psc || !psc->driScreen)
+      return NULL;
+
+   if (shareList) {
+      pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+      shared = pcp_shared->driContext;
+   }
+
+   pcp = Xmalloc(sizeof *pcp);
+   if (pcp == NULL)
+      return NULL;
+
+   pcp->psc = psc;
+   if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
+                                       mode->visualID,
+                                       &pcp->hwContextID, &hwContext)) {
+      Xfree(pcp);
+      return NULL;
+   }
+
+   pcp->driContext =
+      (*psc->legacy->createNewContext) (psc->__driScreen,
+                                        config->driConfig,
+                                        renderType, shared, hwContext, pcp);
+   if (pcp->driContext == NULL) {
+      XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+      Xfree(pcp);
+      return NULL;
+   }
+
+   pcp->base.destroyContext = driDestroyContext;
+   pcp->base.bindContext = driBindContext;
+   pcp->base.unbindContext = driUnbindContext;
+
+   return &pcp->base;
+}
+
+static void
+driDestroyDrawable(__GLXDRIdrawable * pdraw)
+{
+   __GLXscreenConfigs *psc = pdraw->psc;
+
+   (*psc->core->destroyDrawable) (pdraw->driDrawable);
+   XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
+   Xfree(pdraw);
+}
+
+static __GLXDRIdrawable *
+driCreateDrawable(__GLXscreenConfigs * psc,
+                  XID xDrawable,
+                  GLXDrawable drawable, const __GLcontextModes * modes)
+{
+   __GLXDRIdrawable *pdraw;
+   drm_drawable_t hwDrawable;
+   void *empty_attribute_list = NULL;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+
+   /* Old dri can't handle GLX 1.3+ drawable constructors. */
+   if (xDrawable != drawable)
+      return NULL;
+
+   pdraw = Xmalloc(sizeof(*pdraw));
+   if (!pdraw)
+      return NULL;
+
+   pdraw->drawable = drawable;
+   pdraw->psc = psc;
+
+   if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) {
+      Xfree(pdraw);
+      return NULL;
+   }
+
+   /* Create a new drawable */
+   pdraw->driDrawable =
+      (*psc->legacy->createNewDrawable) (psc->__driScreen,
+                                         config->driConfig,
+                                         hwDrawable,
+                                         GLX_WINDOW_BIT,
+                                         empty_attribute_list, pdraw);
+
+   if (!pdraw->driDrawable) {
+      XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
+      Xfree(pdraw);
+      return NULL;
+   }
+
+   pdraw->destroyDrawable = driDestroyDrawable;
+
+   return pdraw;
+}
+
+static int64_t
+driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
+              int64_t unused3)
+{
+   (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
+   return 0;
+}
+
+static void
+driCopySubBuffer(__GLXDRIdrawable * pdraw,
+                 int x, int y, int width, int height)
+{
+   (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable,
+                                                   x, y, width, height);
+}
+
+static void
+driDestroyScreen(__GLXscreenConfigs * psc)
+{
+   /* Free the direct rendering per screen data */
+   if (psc->__driScreen)
+      (*psc->core->destroyScreen) (psc->__driScreen);
+   psc->__driScreen = NULL;
+   if (psc->driver)
+      dlclose(psc->driver);
+}
+
+static __GLXDRIscreen *
+driCreateScreen(__GLXscreenConfigs * psc, int screen,
+                __GLXdisplayPrivate * priv)
+{
+   __GLXDRIdisplayPrivate *pdp;
+   __GLXDRIscreen *psp;
+   const __DRIextension **extensions;
+   char *driverName;
+   int i;
+
+   psp = Xcalloc(1, sizeof *psp);
+   if (psp == NULL)
+      return NULL;
+
+   /* Initialize per screen dynamic client GLX extensions */
+   psc->ext_list_first_time = GL_TRUE;
+
+   if (!driGetDriverName(priv->dpy, screen, &driverName)) {
+      Xfree(psp);
+      return NULL;
+   }
+
+   psc->driver = driOpenDriver(driverName);
+   Xfree(driverName);
+   if (psc->driver == NULL) {
+      Xfree(psp);
+      return NULL;
+   }
+
+   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+   if (extensions == NULL) {
+      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+      Xfree(psp);
+      return NULL;
+   }
+
+   for (i = 0; extensions[i]; i++) {
+      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+        psc->core = (__DRIcoreExtension *) extensions[i];
+      if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
+        psc->legacy = (__DRIlegacyExtension *) extensions[i];
+   }
+
+   if (psc->core == NULL || psc->legacy == NULL) {
+      Xfree(psp);
+      return NULL;
+   }
+
+   pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
+   psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp);
+   if (psc->__driScreen == NULL) {
+      dlclose(psc->driver);
+      Xfree(psp);
+      return NULL;
+   }
+
+   driBindExtensions(psc);
+   driBindCommonExtensions(psc);
+
+   if (psc->driCopySubBuffer)
+      psp->copySubBuffer = driCopySubBuffer;
+
+   psp->destroyScreen = driDestroyScreen;
+   psp->createContext = driCreateContext;
+   psp->createDrawable = driCreateDrawable;
+   psp->swapBuffers = driSwapBuffers;
+   psp->waitX = NULL;
+   psp->waitGL = NULL;
+
+   return psp;
+}
+
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void
+driDestroyDisplay(__GLXDRIdisplay * dpy)
+{
+   Xfree(dpy);
+}
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+_X_HIDDEN __GLXDRIdisplay *
+driCreateDisplay(Display * dpy)
+{
+   __GLXDRIdisplayPrivate *pdpyp;
+   int eventBase, errorBase;
+   int major, minor, patch;
+
+   if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
+      return NULL;
+   }
+
+   if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
+      return NULL;
+   }
+
+   pdpyp = Xmalloc(sizeof *pdpyp);
+   if (!pdpyp) {
+      return NULL;
+   }
+
+   pdpyp->driMajor = major;
+   pdpyp->driMinor = minor;
+   pdpyp->driPatch = patch;
+
+   pdpyp->base.destroyDisplay = driDestroyDisplay;
+   pdpyp->base.createScreen = driCreateScreen;
+
+   return &pdpyp->base;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c
new file mode 100644 (file)
index 0000000..eed9a8c
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2008 George Sapountzis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <X11/Xlib.h>
+#include "glxclient.h"
+#include <dlfcn.h>
+#include "dri_common.h"
+
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
+typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate;
+
+struct __GLXDRIdisplayPrivateRec
+{
+   __GLXDRIdisplay base;
+};
+
+struct __GLXDRIcontextPrivateRec
+{
+   __GLXDRIcontext base;
+   __DRIcontext *driContext;
+   __GLXscreenConfigs *psc;
+};
+
+struct __GLXDRIdrawablePrivateRec
+{
+   __GLXDRIdrawable base;
+
+   GC gc;
+   GC swapgc;
+
+   XVisualInfo *visinfo;
+   XImage *ximage;
+   int bpp;
+};
+
+/**
+ * swrast loader functions
+ */
+
+static Bool
+XCreateDrawable(__GLXDRIdrawablePrivate * pdp,
+                Display * dpy, XID drawable, int visualid)
+{
+   XGCValues gcvalues;
+   long visMask;
+   XVisualInfo visTemp;
+   int num_visuals;
+
+   /* create GC's */
+   pdp->gc = XCreateGC(dpy, drawable, 0, NULL);
+   pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL);
+
+   gcvalues.function = GXcopy;
+   gcvalues.graphics_exposures = False;
+   XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues);
+   XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues);
+   XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues);
+
+   /* create XImage  */
+   visTemp.screen = DefaultScreen(dpy);
+   visTemp.visualid = visualid;
+   visMask = (VisualScreenMask | VisualIDMask);
+   pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals);
+
+   pdp->ximage = XCreateImage(dpy, pdp->visinfo->visual, pdp->visinfo->depth, ZPixmap, 0,       /* format, offset */
+                              NULL,     /* data */
+                              0, 0,     /* size */
+                              32,       /* bitmap_pad */
+                              0);       /* bytes_per_line */
+
+   /* get the true number of bits per pixel */
+   pdp->bpp = pdp->ximage->bits_per_pixel;
+
+   return True;
+}
+
+static void
+XDestroyDrawable(__GLXDRIdrawablePrivate * pdp, Display * dpy, XID drawable)
+{
+   XDestroyImage(pdp->ximage);
+   XFree(pdp->visinfo);
+
+   XFreeGC(dpy, pdp->gc);
+   XFreeGC(dpy, pdp->swapgc);
+}
+
+static void
+swrastGetDrawableInfo(__DRIdrawable * draw,
+                      int *x, int *y, int *w, int *h, void *loaderPrivate)
+{
+   __GLXDRIdrawablePrivate *pdp = loaderPrivate;
+   __GLXDRIdrawable *pdraw = &(pdp->base);
+   Display *dpy = pdraw->psc->dpy;
+   Drawable drawable;
+
+   Window root;
+   Status stat;
+   unsigned int bw, depth;
+
+   drawable = pdraw->xDrawable;
+
+   stat = XGetGeometry(dpy, drawable, &root,
+                       x, y, (unsigned int *) w, (unsigned int *) h,
+                       &bw, &depth);
+}
+
+static inline int
+bytes_per_line(int w, int bpp, unsigned mul)
+{
+   unsigned mask = mul - 1;
+
+   return ((w * bpp + mask) & ~mask) / 8;
+}
+
+static void
+swrastPutImage(__DRIdrawable * draw, int op,
+               int x, int y, int w, int h, char *data, void *loaderPrivate)
+{
+   __GLXDRIdrawablePrivate *pdp = loaderPrivate;
+   __GLXDRIdrawable *pdraw = &(pdp->base);
+   Display *dpy = pdraw->psc->dpy;
+   Drawable drawable;
+   XImage *ximage;
+   GC gc;
+
+   switch (op) {
+   case __DRI_SWRAST_IMAGE_OP_DRAW:
+      gc = pdp->gc;
+      break;
+   case __DRI_SWRAST_IMAGE_OP_SWAP:
+      gc = pdp->swapgc;
+      break;
+   default:
+      return;
+   }
+
+   drawable = pdraw->xDrawable;
+
+   ximage = pdp->ximage;
+   ximage->data = data;
+   ximage->width = w;
+   ximage->height = h;
+   ximage->bytes_per_line = bytes_per_line(w, pdp->bpp, 32);
+
+   XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
+
+   ximage->data = NULL;
+}
+
+static void
+swrastGetImage(__DRIdrawable * draw,
+               int x, int y, int w, int h, char *data, void *loaderPrivate)
+{
+   __GLXDRIdrawablePrivate *pdp = loaderPrivate;
+   __GLXDRIdrawable *pdraw = &(pdp->base);
+   Display *dpy = pdraw->psc->dpy;
+   Drawable drawable;
+   XImage *ximage;
+
+   drawable = pdraw->xDrawable;
+
+   ximage = pdp->ximage;
+   ximage->data = data;
+   ximage->width = w;
+   ximage->height = h;
+   ximage->bytes_per_line = bytes_per_line(w, pdp->bpp, 32);
+
+   XGetSubImage(dpy, drawable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
+
+   ximage->data = NULL;
+}
+
+static const __DRIswrastLoaderExtension swrastLoaderExtension = {
+   {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
+   swrastGetDrawableInfo,
+   swrastPutImage,
+   swrastGetImage
+};
+
+static const __DRIextension *loader_extensions[] = {
+   &systemTimeExtension.base,
+   &swrastLoaderExtension.base,
+   NULL
+};
+
+/**
+ * GLXDRI functions
+ */
+
+static void
+driDestroyContext(__GLXDRIcontext * context,
+                  __GLXscreenConfigs * psc, Display * dpy)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   (*core->destroyContext) (pcp->driContext);
+
+   Xfree(pcp);
+}
+
+static Bool
+driBindContext(__GLXDRIcontext * context,
+               __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   return (*core->bindContext) (pcp->driContext,
+                                draw->driDrawable, read->driDrawable);
+}
+
+static void
+driUnbindContext(__GLXDRIcontext * context)
+{
+   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+   const __DRIcoreExtension *core = pcp->psc->core;
+
+   (*core->unbindContext) (pcp->driContext);
+}
+
+static __GLXDRIcontext *
+driCreateContext(__GLXscreenConfigs * psc,
+                 const __GLcontextModes * mode,
+                 GLXContext gc, GLXContext shareList, int renderType)
+{
+   __GLXDRIcontextPrivate *pcp, *pcp_shared;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+   const __DRIcoreExtension *core;
+   __DRIcontext *shared = NULL;
+
+   if (!psc || !psc->driScreen)
+      return NULL;
+
+   core = psc->core;
+
+   if (shareList) {
+      pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+      shared = pcp_shared->driContext;
+   }
+
+   pcp = Xmalloc(sizeof *pcp);
+   if (pcp == NULL)
+      return NULL;
+
+   pcp->psc = psc;
+   pcp->driContext =
+      (*core->createNewContext) (psc->__driScreen,
+                                 config->driConfig, shared, pcp);
+   if (pcp->driContext == NULL) {
+      Xfree(pcp);
+      return NULL;
+   }
+
+   pcp->base.destroyContext = driDestroyContext;
+   pcp->base.bindContext = driBindContext;
+   pcp->base.unbindContext = driUnbindContext;
+
+   return &pcp->base;
+}
+
+static void
+driDestroyDrawable(__GLXDRIdrawable * pdraw)
+{
+   __GLXDRIdrawablePrivate *pdp = (__GLXDRIdrawablePrivate *) pdraw;
+   const __DRIcoreExtension *core = pdraw->psc->core;
+
+   (*core->destroyDrawable) (pdraw->driDrawable);
+
+   XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
+   Xfree(pdp);
+}
+
+static __GLXDRIdrawable *
+driCreateDrawable(__GLXscreenConfigs * psc,
+                  XID xDrawable,
+                  GLXDrawable drawable, const __GLcontextModes * modes)
+{
+   __GLXDRIdrawable *pdraw;
+   __GLXDRIdrawablePrivate *pdp;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+   const __DRIswrastExtension *swrast = psc->swrast;
+
+   /* Old dri can't handle GLX 1.3+ drawable constructors. */
+   if (xDrawable != drawable)
+      return NULL;
+
+   pdp = Xmalloc(sizeof(*pdp));
+   if (!pdp)
+      return NULL;
+
+   pdraw = &(pdp->base);
+   pdraw->xDrawable = xDrawable;
+   pdraw->drawable = drawable;
+   pdraw->psc = psc;
+
+   XCreateDrawable(pdp, psc->dpy, xDrawable, modes->visualID);
+
+   /* Create a new drawable */
+   pdraw->driDrawable =
+      (*swrast->createNewDrawable) (psc->__driScreen, config->driConfig, pdp);
+
+   if (!pdraw->driDrawable) {
+      XDestroyDrawable(pdp, psc->dpy, xDrawable);
+      Xfree(pdp);
+      return NULL;
+   }
+
+   pdraw->destroyDrawable = driDestroyDrawable;
+
+   return pdraw;
+}
+
+static void
+driSwapBuffers(__GLXDRIdrawable * pdraw)
+{
+   (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
+}
+
+static void
+driDestroyScreen(__GLXscreenConfigs * psc)
+{
+   /* Free the direct rendering per screen data */
+   (*psc->core->destroyScreen) (psc->__driScreen);
+   psc->__driScreen = NULL;
+   if (psc->driver)
+      dlclose(psc->driver);
+}
+
+static __GLXDRIscreen *
+driCreateScreen(__GLXscreenConfigs * psc, int screen,
+                __GLXdisplayPrivate * priv)
+{
+   __GLXDRIscreen *psp;
+   const __DRIconfig **driver_configs;
+   const __DRIextension **extensions;
+   const char *driverName = "swrast";
+   int i;
+
+   psp = Xcalloc(1, sizeof *psp);
+   if (psp == NULL)
+      return NULL;
+
+   /* Initialize per screen dynamic client GLX extensions */
+   psc->ext_list_first_time = GL_TRUE;
+
+   psc->driver = driOpenDriver(driverName);
+   if (psc->driver == NULL)
+      goto handle_error;
+
+   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+   if (extensions == NULL) {
+      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+      goto handle_error;
+   }
+
+   for (i = 0; extensions[i]; i++) {
+      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+         psc->core = (__DRIcoreExtension *) extensions[i];
+      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
+         psc->swrast = (__DRIswrastExtension *) extensions[i];
+   }
+
+   if (psc->core == NULL || psc->swrast == NULL) {
+      ErrorMessageF("core dri extension not found\n");
+      goto handle_error;
+   }
+
+   psc->__driScreen =
+      psc->swrast->createNewScreen(screen,
+                                   loader_extensions, &driver_configs, psc);
+   if (psc->__driScreen == NULL) {
+      ErrorMessageF("failed to create dri screen\n");
+      goto handle_error;
+   }
+
+   driBindExtensions(psc);
+   driBindCommonExtensions(psc);
+
+   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+   psc->driver_configs = driver_configs;
+
+   psp->destroyScreen = driDestroyScreen;
+   psp->createContext = driCreateContext;
+   psp->createDrawable = driCreateDrawable;
+   psp->swapBuffers = driSwapBuffers;
+   psp->waitX = NULL;
+   psp->waitGL = NULL;
+
+   return psp;
+
+ handle_error:
+   Xfree(psp);
+
+   if (psc->driver)
+      dlclose(psc->driver);
+
+   ErrorMessageF("reverting to indirect rendering\n");
+
+   return NULL;
+}
+
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void
+driDestroyDisplay(__GLXDRIdisplay * dpy)
+{
+   Xfree(dpy);
+}
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+_X_HIDDEN __GLXDRIdisplay *
+driswCreateDisplay(Display * dpy)
+{
+   __GLXDRIdisplayPrivate *pdpyp;
+
+   pdpyp = Xmalloc(sizeof *pdpyp);
+   if (pdpyp == NULL)
+      return NULL;
+
+   pdpyp->base.destroyDisplay = driDestroyDisplay;
+   pdpyp->base.createScreen = driCreateScreen;
+
+   return &pdpyp->base;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/eval.c b/src/glx/eval.c
new file mode 100644 (file)
index 0000000..226fb7d
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "packrender.h"
+
+/*
+** Routines to pack evaluator maps into the transport buffer.  Maps are
+** allowed to have extra arbitrary data, so these routines extract just
+** the information that the GL needs.
+*/
+
+void
+__glFillMap1f(GLint k, GLint order, GLint stride,
+              const GLfloat * points, GLubyte * pc)
+{
+   if (stride == k) {
+      /* Just copy the data */
+      __GLX_PUT_FLOAT_ARRAY(0, points, order * k);
+   }
+   else {
+      GLint i;
+
+      for (i = 0; i < order; i++) {
+         __GLX_PUT_FLOAT_ARRAY(0, points, k);
+         points += stride;
+         pc += k * __GLX_SIZE_FLOAT32;
+      }
+   }
+}
+
+void
+__glFillMap1d(GLint k, GLint order, GLint stride,
+              const GLdouble * points, GLubyte * pc)
+{
+   if (stride == k) {
+      /* Just copy the data */
+      __GLX_PUT_DOUBLE_ARRAY(0, points, order * k);
+   }
+   else {
+      GLint i;
+      for (i = 0; i < order; i++) {
+         __GLX_PUT_DOUBLE_ARRAY(0, points, k);
+         points += stride;
+         pc += k * __GLX_SIZE_FLOAT64;
+      }
+   }
+}
+
+void
+__glFillMap2f(GLint k, GLint majorOrder, GLint minorOrder,
+              GLint majorStride, GLint minorStride,
+              const GLfloat * points, GLfloat * data)
+{
+   GLint i, j, x;
+
+   if ((minorStride == k) && (majorStride == minorOrder * k)) {
+      /* Just copy the data */
+      __GLX_MEM_COPY(data, points, majorOrder * majorStride *
+                     __GLX_SIZE_FLOAT32);
+      return;
+   }
+   for (i = 0; i < majorOrder; i++) {
+      for (j = 0; j < minorOrder; j++) {
+         for (x = 0; x < k; x++) {
+            data[x] = points[x];
+         }
+         points += minorStride;
+         data += k;
+      }
+      points += majorStride - minorStride * minorOrder;
+   }
+}
+
+void
+__glFillMap2d(GLint k, GLint majorOrder, GLint minorOrder,
+              GLint majorStride, GLint minorStride,
+              const GLdouble * points, GLdouble * data)
+{
+   int i, j, x;
+
+   if ((minorStride == k) && (majorStride == minorOrder * k)) {
+      /* Just copy the data */
+      __GLX_MEM_COPY(data, points, majorOrder * majorStride *
+                     __GLX_SIZE_FLOAT64);
+      return;
+   }
+
+#ifdef __GLX_ALIGN64
+   x = k * __GLX_SIZE_FLOAT64;
+#endif
+   for (i = 0; i < majorOrder; i++) {
+      for (j = 0; j < minorOrder; j++) {
+#ifdef __GLX_ALIGN64
+         __GLX_MEM_COPY(data, points, x);
+#else
+         for (x = 0; x < k; x++) {
+            data[x] = points[x];
+         }
+#endif
+         points += minorStride;
+         data += k;
+      }
+      points += majorStride - minorStride * minorOrder;
+   }
+}
diff --git a/src/glx/glcontextmodes.c b/src/glx/glcontextmodes.c
new file mode 100644 (file)
index 0000000..232031c
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * 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
+ * on 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
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glcontextmodes.c
+ * Utility routines for working with \c __GLcontextModes structures.  At
+ * some point most or all of these functions will be moved to the Mesa
+ * code base.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#if defined(IN_MINI_GLX)
+#include <GL/gl.h>
+#else
+#if defined(HAVE_DIX_CONFIG_H)
+# include <dix-config.h>
+#endif
+#include <X11/X.h>
+#include <GL/glx.h>
+#include "GL/glxint.h"
+#endif
+
+/* Memory macros */
+#if defined(IN_MINI_GLX)
+# include <stdlib.h>
+# include <string.h>
+# define _mesa_malloc(b) malloc(b)
+# define _mesa_free(m) free(m)
+# define _mesa_memset  memset
+#else
+# ifdef XFree86Server
+# include <os.h>
+# include <string.h>
+#  define _mesa_malloc(b) xalloc(b)
+#  define _mesa_free(m)   xfree(m)
+#  define _mesa_memset   memset
+# else
+#  include <X11/Xlibint.h>
+#  define _mesa_memset memset
+#  define _mesa_malloc(b) Xmalloc(b)
+#  define _mesa_free(m) Xfree(m)
+# endif /* XFree86Server */
+#endif /* !defined(IN_MINI_GLX) */
+
+#include "glcontextmodes.h"
+
+#if !defined(IN_MINI_GLX)
+#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.
+ */
+GLint
+_gl_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;
+}
+
+
+/**
+ * Convert a GLX visual type to an X visual type.
+ * 
+ * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR, 
+ *                   \c GLX_STATIC_GRAY, etc.) to be converted.
+ * \return If \c visualType is a valid GLX visual type, an X visual type will
+ *         be returned.  Otherwise -1 will be returned.
+ */
+GLint
+_gl_convert_to_x_visual_type(int visualType)
+{
+   static const int x_visual_types[NUM_VISUAL_TYPES] = {
+      TrueColor, DirectColor,
+      PseudoColor, StaticColor,
+      GrayScale, StaticGray
+   };
+
+   return ((unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES)
+      ? x_visual_types[visualType - GLX_TRUE_COLOR] : -1;
+}
+
+
+/**
+ * Copy a GLX visual config structure to a GL context mode structure.  All
+ * of the fields in \c config are copied to \c mode.  Additional fields in
+ * \c mode that can be derrived from the fields of \c config (i.e.,
+ * \c haveDepthBuffer) are also filled in.  The remaining fields in \c mode
+ * that cannot be derived are set to default values.
+ * 
+ * \param mode   Destination GL context mode.
+ * \param config Source GLX visual config.
+ * 
+ * \note
+ * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes
+ * structure will be set to the \c vid of the \c __GLXvisualConfig structure.
+ */
+void
+_gl_copy_visual_to_context_mode(__GLcontextModes * mode,
+                                const __GLXvisualConfig * config)
+{
+   __GLcontextModes *const next = mode->next;
+
+   (void) _mesa_memset(mode, 0, sizeof(__GLcontextModes));
+   mode->next = next;
+
+   mode->visualID = config->vid;
+   mode->visualType = _gl_convert_from_x_visual_type(config->class);
+   mode->xRenderable = GL_TRUE;
+   mode->fbconfigID = config->vid;
+   mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
+
+   mode->rgbMode = (config->rgba != 0);
+   mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+
+   mode->colorIndexMode = !(mode->rgbMode);
+   mode->doubleBufferMode = (config->doubleBuffer != 0);
+   mode->stereoMode = (config->stereo != 0);
+
+   mode->haveAccumBuffer = ((config->accumRedSize +
+                             config->accumGreenSize +
+                             config->accumBlueSize +
+                             config->accumAlphaSize) > 0);
+   mode->haveDepthBuffer = (config->depthSize > 0);
+   mode->haveStencilBuffer = (config->stencilSize > 0);
+
+   mode->redBits = config->redSize;
+   mode->greenBits = config->greenSize;
+   mode->blueBits = config->blueSize;
+   mode->alphaBits = config->alphaSize;
+   mode->redMask = config->redMask;
+   mode->greenMask = config->greenMask;
+   mode->blueMask = config->blueMask;
+   mode->alphaMask = config->alphaMask;
+   mode->rgbBits = mode->rgbMode ? config->bufferSize : 0;
+   mode->indexBits = mode->colorIndexMode ? config->bufferSize : 0;
+
+   mode->accumRedBits = config->accumRedSize;
+   mode->accumGreenBits = config->accumGreenSize;
+   mode->accumBlueBits = config->accumBlueSize;
+   mode->accumAlphaBits = config->accumAlphaSize;
+   mode->depthBits = config->depthSize;
+   mode->stencilBits = config->stencilSize;
+
+   mode->numAuxBuffers = config->auxBuffers;
+   mode->level = config->level;
+
+   mode->visualRating = config->visualRating;
+   mode->transparentPixel = config->transparentPixel;
+   mode->transparentRed = config->transparentRed;
+   mode->transparentGreen = config->transparentGreen;
+   mode->transparentBlue = config->transparentBlue;
+   mode->transparentAlpha = config->transparentAlpha;
+   mode->transparentIndex = config->transparentIndex;
+   mode->samples = config->multiSampleSize;
+   mode->sampleBuffers = config->nMultiSampleBuffers;
+   /* mode->visualSelectGroup = config->visualSelectGroup; ? */
+
+   mode->swapMethod = GLX_SWAP_UNDEFINED_OML;
+
+   mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE;
+   mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ?
+      GL_TRUE : GL_FALSE;
+   mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE;
+   mode->bindToTextureTargets = mode->rgbMode ?
+      GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT |
+      GLX_TEXTURE_RECTANGLE_BIT_EXT : 0;
+   mode->yInverted = GL_FALSE;
+}
+
+
+/**
+ * Get data from a GL context mode.
+ * 
+ * \param mode         GL context mode whose data is to be returned.
+ * \param attribute    Attribute of \c mode that is to be returned.
+ * \param value_return Location to store the data member of \c mode.
+ * \return  If \c attribute is a valid attribute of \c mode, zero is
+ *          returned.  Otherwise \c GLX_BAD_ATTRIBUTE is returned.
+ */
+int
+_gl_get_context_mode_data(const __GLcontextModes * mode, int attribute,
+                          int *value_return)
+{
+   switch (attribute) {
+   case GLX_USE_GL:
+      *value_return = GL_TRUE;
+      return 0;
+   case GLX_BUFFER_SIZE:
+      *value_return = mode->rgbBits;
+      return 0;
+   case GLX_RGBA:
+      *value_return = mode->rgbMode;
+      return 0;
+   case GLX_RED_SIZE:
+      *value_return = mode->redBits;
+      return 0;
+   case GLX_GREEN_SIZE:
+      *value_return = mode->greenBits;
+      return 0;
+   case GLX_BLUE_SIZE:
+      *value_return = mode->blueBits;
+      return 0;
+   case GLX_ALPHA_SIZE:
+      *value_return = mode->alphaBits;
+      return 0;
+   case GLX_DOUBLEBUFFER:
+      *value_return = mode->doubleBufferMode;
+      return 0;
+   case GLX_STEREO:
+      *value_return = mode->stereoMode;
+      return 0;
+   case GLX_AUX_BUFFERS:
+      *value_return = mode->numAuxBuffers;
+      return 0;
+   case GLX_DEPTH_SIZE:
+      *value_return = mode->depthBits;
+      return 0;
+   case GLX_STENCIL_SIZE:
+      *value_return = mode->stencilBits;
+      return 0;
+   case GLX_ACCUM_RED_SIZE:
+      *value_return = mode->accumRedBits;
+      return 0;
+   case GLX_ACCUM_GREEN_SIZE:
+      *value_return = mode->accumGreenBits;
+      return 0;
+   case GLX_ACCUM_BLUE_SIZE:
+      *value_return = mode->accumBlueBits;
+      return 0;
+   case GLX_ACCUM_ALPHA_SIZE:
+      *value_return = mode->accumAlphaBits;
+      return 0;
+   case GLX_LEVEL:
+      *value_return = mode->level;
+      return 0;
+   case GLX_TRANSPARENT_TYPE_EXT:
+      *value_return = mode->transparentPixel;
+      return 0;
+   case GLX_TRANSPARENT_RED_VALUE:
+      *value_return = mode->transparentRed;
+      return 0;
+   case GLX_TRANSPARENT_GREEN_VALUE:
+      *value_return = mode->transparentGreen;
+      return 0;
+   case GLX_TRANSPARENT_BLUE_VALUE:
+      *value_return = mode->transparentBlue;
+      return 0;
+   case GLX_TRANSPARENT_ALPHA_VALUE:
+      *value_return = mode->transparentAlpha;
+      return 0;
+   case GLX_TRANSPARENT_INDEX_VALUE:
+      *value_return = mode->transparentIndex;
+      return 0;
+   case GLX_X_VISUAL_TYPE:
+      *value_return = mode->visualType;
+      return 0;
+   case GLX_CONFIG_CAVEAT:
+      *value_return = mode->visualRating;
+      return 0;
+   case GLX_VISUAL_ID:
+      *value_return = mode->visualID;
+      return 0;
+   case GLX_DRAWABLE_TYPE:
+      *value_return = mode->drawableType;
+      return 0;
+   case GLX_RENDER_TYPE:
+      *value_return = mode->renderType;
+      return 0;
+   case GLX_X_RENDERABLE:
+      *value_return = mode->xRenderable;
+      return 0;
+   case GLX_FBCONFIG_ID:
+      *value_return = mode->fbconfigID;
+      return 0;
+   case GLX_MAX_PBUFFER_WIDTH:
+      *value_return = mode->maxPbufferWidth;
+      return 0;
+   case GLX_MAX_PBUFFER_HEIGHT:
+      *value_return = mode->maxPbufferHeight;
+      return 0;
+   case GLX_MAX_PBUFFER_PIXELS:
+      *value_return = mode->maxPbufferPixels;
+      return 0;
+   case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+      *value_return = mode->optimalPbufferWidth;
+      return 0;
+   case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+      *value_return = mode->optimalPbufferHeight;
+      return 0;
+   case GLX_SWAP_METHOD_OML:
+      *value_return = mode->swapMethod;
+      return 0;
+   case GLX_SAMPLE_BUFFERS_SGIS:
+      *value_return = mode->sampleBuffers;
+      return 0;
+   case GLX_SAMPLES_SGIS:
+      *value_return = mode->samples;
+      return 0;
+   case GLX_BIND_TO_TEXTURE_RGB_EXT:
+      *value_return = mode->bindToTextureRgb;
+      return 0;
+   case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+      *value_return = mode->bindToTextureRgba;
+      return 0;
+   case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+      *value_return = mode->bindToMipmapTexture == GL_TRUE ? GL_TRUE :
+         GL_FALSE;
+      return 0;
+   case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+      *value_return = mode->bindToTextureTargets;
+      return 0;
+   case GLX_Y_INVERTED_EXT:
+      *value_return = mode->yInverted;
+      return 0;
+
+      /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX.
+       * It is ONLY for communication between the GLX client and the GLX
+       * server.
+       */
+   case GLX_VISUAL_SELECT_GROUP_SGIX:
+   default:
+      return GLX_BAD_ATTRIBUTE;
+   }
+}
+#endif /* !defined(IN_MINI_GLX) */
+
+
+/**
+ * Allocate a linked list of \c __GLcontextModes structures.  The fields of
+ * each structure will be initialized to "reasonable" default values.  In
+ * most cases this is the default value defined by table 3.4 of the GLX
+ * 1.3 specification.  This means that most values are either initialized to
+ * zero or \c GLX_DONT_CARE (which is -1).  As support for additional
+ * extensions is added, the new values will be initialized to appropriate
+ * values from the extension specification.
+ * 
+ * \param count         Number of structures to allocate.
+ * \param minimum_size  Minimum size of a structure to allocate.  This allows
+ *                      for differences in the version of the
+ *                      \c __GLcontextModes stucture used in libGL and in a
+ *                      DRI-based driver.
+ * \returns A pointer to the first element in a linked list of \c count
+ *          stuctures on success, or \c NULL on failure.
+ * 
+ * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
+ *          The fundamental assumption is that if the \c minimum_size
+ *          specified by the driver and the size of the \c __GLcontextModes
+ *          structure in libGL is the same, then the meaning of each byte in
+ *          the structure is the same in both places.  \b Be \b careful!
+ *          Basically this means that fields have to be added in libGL and
+ *          then propagated to drivers.  Drivers should \b never arbitrarilly
+ *          extend the \c __GLcontextModes data-structure.
+ */
+__GLcontextModes *
+_gl_context_modes_create(unsigned count, size_t minimum_size)
+{
+   const size_t size = (minimum_size > sizeof(__GLcontextModes))
+      ? minimum_size : sizeof(__GLcontextModes);
+   __GLcontextModes *base = NULL;
+   __GLcontextModes **next;
+   unsigned i;
+
+   next = &base;
+   for (i = 0; i < count; i++) {
+      *next = (__GLcontextModes *) _mesa_malloc(size);
+      if (*next == NULL) {
+         _gl_context_modes_destroy(base);
+         base = NULL;
+         break;
+      }
+
+      (void) _mesa_memset(*next, 0, size);
+      (*next)->visualID = GLX_DONT_CARE;
+      (*next)->visualType = GLX_DONT_CARE;
+      (*next)->visualRating = GLX_NONE;
+      (*next)->transparentPixel = GLX_NONE;
+      (*next)->transparentRed = GLX_DONT_CARE;
+      (*next)->transparentGreen = GLX_DONT_CARE;
+      (*next)->transparentBlue = GLX_DONT_CARE;
+      (*next)->transparentAlpha = GLX_DONT_CARE;
+      (*next)->transparentIndex = GLX_DONT_CARE;
+      (*next)->xRenderable = GLX_DONT_CARE;
+      (*next)->fbconfigID = GLX_DONT_CARE;
+      (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+      (*next)->bindToTextureRgb = GLX_DONT_CARE;
+      (*next)->bindToTextureRgba = GLX_DONT_CARE;
+      (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+      (*next)->bindToTextureTargets = GLX_DONT_CARE;
+      (*next)->yInverted = GLX_DONT_CARE;
+
+      next = &((*next)->next);
+   }
+
+   return base;
+}
+
+
+/**
+ * Destroy a linked list of \c __GLcontextModes structures created by
+ * \c _gl_context_modes_create.
+ * 
+ * \param modes  Linked list of structures to be destroyed.  All structres
+ *               in the list will be freed.
+ */
+void
+_gl_context_modes_destroy(__GLcontextModes * modes)
+{
+   while (modes != NULL) {
+      __GLcontextModes *const next = modes->next;
+
+      _mesa_free(modes);
+      modes = next;
+   }
+}
+
+
+/**
+ * Find a context mode matching a Visual ID.
+ *
+ * \param modes  List list of context-mode structures to be searched.
+ * \param vid    Visual ID to be found.
+ * \returns A pointer to a context-mode in \c modes if \c vid was found in
+ *          the list, or \c NULL if it was not.
+ */
+
+__GLcontextModes *
+_gl_context_modes_find_visual(__GLcontextModes * modes, int vid)
+{
+   __GLcontextModes *m;
+
+   for (m = modes; m != NULL; m = m->next)
+      if (m->visualID == vid)
+         return m;
+
+   return NULL;
+}
+
+__GLcontextModes *
+_gl_context_modes_find_fbconfig(__GLcontextModes * modes, int fbid)
+{
+   __GLcontextModes *m;
+
+   for (m = modes; m != NULL; m = m->next)
+      if (m->fbconfigID == fbid)
+         return m;
+
+   return NULL;
+}
+
+/**
+ * Determine if two context-modes are the same.  This is intended to be used
+ * by libGL implementations to compare to sets of driver generated FBconfigs.
+ * 
+ * \param a  Context-mode to be compared.
+ * \param b  Context-mode to be compared.
+ * \returns \c GL_TRUE if the two context-modes are the same.  \c GL_FALSE is
+ *          returned otherwise.
+ */
+GLboolean
+_gl_context_modes_are_same(const __GLcontextModes * a,
+                           const __GLcontextModes * b)
+{
+   return ((a->rgbMode == b->rgbMode) &&
+           (a->floatMode == b->floatMode) &&
+           (a->colorIndexMode == b->colorIndexMode) &&
+           (a->doubleBufferMode == b->doubleBufferMode) &&
+           (a->stereoMode == b->stereoMode) &&
+           (a->redBits == b->redBits) &&
+           (a->greenBits == b->greenBits) &&
+           (a->blueBits == b->blueBits) && (a->alphaBits == b->alphaBits) &&
+#if 0                           /* For some reason these don't get set on the client-side in libGL. */
+           (a->redMask == b->redMask) &&
+           (a->greenMask == b->greenMask) &&
+           (a->blueMask == b->blueMask) && (a->alphaMask == b->alphaMask) &&
+#endif
+           (a->rgbBits == b->rgbBits) &&
+           (a->indexBits == b->indexBits) &&
+           (a->accumRedBits == b->accumRedBits) &&
+           (a->accumGreenBits == b->accumGreenBits) &&
+           (a->accumBlueBits == b->accumBlueBits) &&
+           (a->accumAlphaBits == b->accumAlphaBits) &&
+           (a->depthBits == b->depthBits) &&
+           (a->stencilBits == b->stencilBits) &&
+           (a->numAuxBuffers == b->numAuxBuffers) &&
+           (a->level == b->level) &&
+           (a->pixmapMode == b->pixmapMode) &&
+           (a->visualRating == b->visualRating) &&
+           (a->transparentPixel == b->transparentPixel) &&
+           ((a->transparentPixel != GLX_TRANSPARENT_RGB) ||
+            ((a->transparentRed == b->transparentRed) &&
+             (a->transparentGreen == b->transparentGreen) &&
+             (a->transparentBlue == b->transparentBlue) &&
+             (a->transparentAlpha == b->transparentAlpha))) &&
+           ((a->transparentPixel != GLX_TRANSPARENT_INDEX) ||
+            (a->transparentIndex == b->transparentIndex)) &&
+           (a->sampleBuffers == b->sampleBuffers) &&
+           (a->samples == b->samples) &&
+           ((a->drawableType & b->drawableType) != 0) &&
+           (a->renderType == b->renderType) &&
+           (a->maxPbufferWidth == b->maxPbufferWidth) &&
+           (a->maxPbufferHeight == b->maxPbufferHeight) &&
+           (a->maxPbufferPixels == b->maxPbufferPixels) &&
+           (a->optimalPbufferWidth == b->optimalPbufferWidth) &&
+           (a->optimalPbufferHeight == b->optimalPbufferHeight) &&
+           (a->swapMethod == b->swapMethod) &&
+           (a->bindToTextureRgb == b->bindToTextureRgb) &&
+           (a->bindToTextureRgba == b->bindToTextureRgba) &&
+           (a->bindToMipmapTexture == b->bindToMipmapTexture) &&
+           (a->bindToTextureTargets == b->bindToTextureTargets) &&
+           (a->yInverted == b->yInverted));
+}
diff --git a/src/glx/glcontextmodes.h b/src/glx/glcontextmodes.h
new file mode 100644 (file)
index 0000000..6676ae3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * 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
+ * on 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
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glcontextmodes.h
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef GLCONTEXTMODES_H
+#define GLCONTEXTMODES_H
+
+#include "GL/internal/glcore.h"
+
+#if !defined(IN_MINI_GLX)
+extern GLint _gl_convert_from_x_visual_type(int visualType);
+extern GLint _gl_convert_to_x_visual_type(int visualType);
+extern void _gl_copy_visual_to_context_mode(__GLcontextModes * mode,
+                                            const __GLXvisualConfig * config);
+extern int _gl_get_context_mode_data(const __GLcontextModes * mode,
+                                     int attribute, int *value_return);
+#endif /* !defined(IN_MINI_GLX) */
+
+extern __GLcontextModes *_gl_context_modes_create(unsigned count,
+                                                  size_t minimum_size);
+extern void _gl_context_modes_destroy(__GLcontextModes * modes);
+extern __GLcontextModes *_gl_context_modes_find_visual(__GLcontextModes *
+                                                       modes, int vid);
+extern __GLcontextModes *_gl_context_modes_find_fbconfig(__GLcontextModes *
+                                                         modes, int fbid);
+extern GLboolean _gl_context_modes_are_same(const __GLcontextModes * a,
+                                            const __GLcontextModes * b);
+
+#endif /* GLCONTEXTMODES_H */
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c
new file mode 100644 (file)
index 0000000..a0a0223
--- /dev/null
@@ -0,0 +1,724 @@
+/*
+ * (C) Copyright IBM Corporation 2004
+ * 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
+ * on 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
+ * IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glx_pbuffer.c
+ * Implementation of pbuffer related functions.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <inttypes.h>
+#include "glxclient.h"
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/Xext.h>
+#include <assert.h>
+#include <string.h>
+#include "glxextensions.h"
+
+#define WARN_ONCE_GLX_1_3(a, b) {              \
+               static int warned=1;            \
+               if(warned) {                    \
+                       warn_GLX_1_3((a), b );  \
+                       warned=0;               \
+               }                               \
+       }
+
+/**
+ * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems.
+ */
+static void
+warn_GLX_1_3(Display *dpy, const char *function_name)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+
+   if (priv->minorVersion < 3) {
+      fprintf(stderr, 
+             "WARNING: Application calling GLX 1.3 function \"%s\" "
+             "when GLX 1.3 is not supported!  This is an application bug!\n",
+             function_name);
+   }
+}
+
+
+/**
+ * Change a drawable's attribute.
+ *
+ * This function is used to implement \c glXSelectEvent and
+ * \c glXSelectEventSGIX.
+ *
+ * \note
+ * This function dynamically determines whether to use the SGIX_pbuffer
+ * version of the protocol or the GLX 1.3 version of the protocol.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static void
+ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
+                        const CARD32 * attribs, size_t num_attribs)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   CARD32 *output;
+   CARD8 opcode;
+
+   if ((dpy == NULL) || (drawable == 0)) {
+      return;
+   }
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   LockDisplay(dpy);
+
+   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+      xGLXChangeDrawableAttributesReq *req;
+
+      GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req);
+      output = (CARD32 *) (req + 1);
+
+      req->reqType = opcode;
+      req->glxCode = X_GLXChangeDrawableAttributes;
+      req->drawable = drawable;
+      req->numAttribs = (CARD32) num_attribs;
+   }
+   else {
+      xGLXVendorPrivateWithReplyReq *vpreq;
+
+      GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq);
+      output = (CARD32 *) (vpreq + 1);
+
+      vpreq->reqType = opcode;
+      vpreq->glxCode = X_GLXVendorPrivateWithReply;
+      vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
+
+      output[0] = (CARD32) drawable;
+      output++;
+   }
+
+   (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return;
+}
+
+
+/**
+ * Destroy a pbuffer.
+ *
+ * This function is used to implement \c glXDestroyPbuffer and
+ * \c glXDestroyGLXPbufferSGIX.
+ *
+ * \note
+ * This function dynamically determines whether to use the SGIX_pbuffer
+ * version of the protocol or the GLX 1.3 version of the protocol.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static void
+DestroyPbuffer(Display * dpy, GLXDrawable drawable)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   CARD8 opcode;
+
+   if ((dpy == NULL) || (drawable == 0)) {
+      return;
+   }
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   LockDisplay(dpy);
+
+   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+      xGLXDestroyPbufferReq *req;
+
+      GetReq(GLXDestroyPbuffer, req);
+      req->reqType = opcode;
+      req->glxCode = X_GLXDestroyPbuffer;
+      req->pbuffer = (GLXPbuffer) drawable;
+   }
+   else {
+      xGLXVendorPrivateWithReplyReq *vpreq;
+      CARD32 *data;
+
+      GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
+      data = (CARD32 *) (vpreq + 1);
+
+      data[0] = (CARD32) drawable;
+
+      vpreq->reqType = opcode;
+      vpreq->glxCode = X_GLXVendorPrivateWithReply;
+      vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return;
+}
+
+
+#ifdef GLX_DIRECT_RENDERING
+extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
+                                           GLXDrawable drawable,
+                                           int *const scrn_num);
+
+static GLenum
+determineTextureTarget(const int *attribs, int numAttribs)
+{
+   GLenum target = 0;
+   int i;
+
+   for (i = 0; i < numAttribs; i++) {
+      if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
+         switch (attribs[2 * i + 1]) {
+         case GLX_TEXTURE_2D_EXT:
+            target = GL_TEXTURE_2D;
+            break;
+         case GLX_TEXTURE_RECTANGLE_EXT:
+            target = GL_TEXTURE_RECTANGLE_ARB;
+            break;
+         }
+      }
+   }
+
+   return target;
+}
+
+
+static GLenum
+determineTextureFormat(const int *attribs, int numAttribs)
+{
+   int i;
+
+   for (i = 0; i < numAttribs; i++) {
+      if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
+         return attribs[2 * i + 1];
+   }
+
+   return 0;
+}
+#endif
+
+/**
+ * Get a drawable's attribute.
+ *
+ * This function is used to implement \c glXGetSelectedEvent and
+ * \c glXGetSelectedEventSGIX.
+ *
+ * \note
+ * This function dynamically determines whether to use the SGIX_pbuffer
+ * version of the protocol or the GLX 1.3 version of the protocol.
+ *
+ * \todo
+ * The number of attributes returned is likely to be small, probably less than
+ * 10.  Given that, this routine should try to use an array on the stack to
+ * capture the reply rather than always calling Xmalloc.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static int
+GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
+                     int attribute, unsigned int *value)
+{
+   __GLXdisplayPrivate *priv;
+   xGLXGetDrawableAttributesReply reply;
+   CARD32 *data;
+   CARD8 opcode;
+   unsigned int length;
+   unsigned int i;
+   unsigned int num_attributes;
+   GLboolean use_glx_1_3;
+
+   if ((dpy == NULL) || (drawable == 0)) {
+      return 0;
+   }
+
+   priv = __glXInitialize(dpy);
+   use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
+
+   *value = 0;
+
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return 0;
+
+   LockDisplay(dpy);
+
+   if (use_glx_1_3) {
+      xGLXGetDrawableAttributesReq *req;
+
+      GetReqExtra(GLXGetDrawableAttributes, 4, req);
+      req->reqType = opcode;
+      req->glxCode = X_GLXGetDrawableAttributes;
+      req->drawable = drawable;
+   }
+   else {
+      xGLXVendorPrivateWithReplyReq *vpreq;
+
+      GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
+      data = (CARD32 *) (vpreq + 1);
+      data[0] = (CARD32) drawable;
+
+      vpreq->reqType = opcode;
+      vpreq->glxCode = X_GLXVendorPrivateWithReply;
+      vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
+   }
+
+   _XReply(dpy, (xReply *) & reply, 0, False);
+
+   if (reply.type == X_Error) {
+      UnlockDisplay(dpy);
+      SyncHandle();
+      return 0;
+   }
+
+   length = reply.length;
+   if (length) {
+      num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
+      data = (CARD32 *) Xmalloc(length * sizeof(CARD32));
+      if (data == NULL) {
+         /* Throw data on the floor */
+         _XEatData(dpy, length);
+      }
+      else {
+         _XRead(dpy, (char *) data, length * sizeof(CARD32));
+
+         /* Search the set of returned attributes for the attribute requested by
+          * the caller.
+          */
+         for (i = 0; i < num_attributes; i++) {
+            if (data[i * 2] == attribute) {
+               *value = data[(i * 2) + 1];
+               break;
+            }
+         }
+
+#ifdef GLX_DIRECT_RENDERING
+         {
+            __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+            if (pdraw != NULL && !pdraw->textureTarget)
+               pdraw->textureTarget =
+                  determineTextureTarget((const int *) data, num_attributes);
+            if (pdraw != NULL && !pdraw->textureFormat)
+               pdraw->textureFormat =
+                  determineTextureFormat((const int *) data, num_attributes);
+         }
+#endif
+
+         Xfree(data);
+      }
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return 0;
+}
+
+/**
+ * Create a non-pbuffer GLX drawable.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static GLXDrawable
+CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig,
+               Drawable drawable, const int *attrib_list, CARD8 glxCode)
+{
+   xGLXCreateWindowReq *req;
+   CARD32 *data;
+   unsigned int i;
+   CARD8 opcode;
+
+   i = 0;
+   if (attrib_list) {
+      while (attrib_list[i * 2] != None)
+         i++;
+   }
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return None;
+
+   LockDisplay(dpy);
+   GetReqExtra(GLXCreateWindow, 8 * i, req);
+   data = (CARD32 *) (req + 1);
+
+   req->reqType = opcode;
+   req->glxCode = glxCode;
+   req->screen = (CARD32) fbconfig->screen;
+   req->fbconfig = fbconfig->fbconfigID;
+   req->window = (CARD32) drawable;
+   req->glxwindow = (GLXWindow) XAllocID(dpy);
+   req->numAttribs = (CARD32) i;
+
+   memcpy(data, attrib_list, 8 * i);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+#ifdef GLX_DIRECT_RENDERING
+   do {
+      /* FIXME: Maybe delay __DRIdrawable creation until the drawable
+       * is actually bound to a context... */
+
+      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+      __GLXDRIdrawable *pdraw;
+      __GLXscreenConfigs *psc;
+
+      psc = &priv->screenConfigs[fbconfig->screen];
+      if (psc->driScreen == NULL)
+         break;
+      pdraw = psc->driScreen->createDrawable(psc, drawable,
+                                             req->glxwindow, fbconfig);
+      if (pdraw == NULL) {
+         fprintf(stderr, "failed to create drawable\n");
+         break;
+      }
+
+      if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) {
+         (*pdraw->destroyDrawable) (pdraw);
+         return None;           /* FIXME: Check what we're supposed to do here... */
+      }
+
+      pdraw->textureTarget = determineTextureTarget(attrib_list, i);
+      pdraw->textureFormat = determineTextureFormat(attrib_list, i);
+   } while (0);
+#endif
+
+   return (GLXDrawable) req->glxwindow;
+}
+
+
+/**
+ * Destroy a non-pbuffer GLX drawable.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static void
+DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
+{
+   xGLXDestroyPbufferReq *req;
+   CARD8 opcode;
+
+   if ((dpy == NULL) || (drawable == 0)) {
+      return;
+   }
+
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   LockDisplay(dpy);
+
+   GetReqExtra(GLXDestroyPbuffer, 4, req);
+   req->reqType = opcode;
+   req->glxCode = glxCode;
+   req->pbuffer = (GLXPbuffer) drawable;
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+#ifdef GLX_DIRECT_RENDERING
+   {
+      int screen;
+      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+      __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
+
+      if (pdraw != NULL) {
+         (*pdraw->destroyDrawable) (pdraw);
+         __glxHashDelete(psc->drawHash, drawable);
+      }
+   }
+#endif
+
+   return;
+}
+
+
+/**
+ * Create a pbuffer.
+ *
+ * This function is used to implement \c glXCreatePbuffer and
+ * \c glXCreateGLXPbufferSGIX.
+ *
+ * \note
+ * This function dynamically determines whether to use the SGIX_pbuffer
+ * version of the protocol or the GLX 1.3 version of the protocol.
+ *
+ * \todo
+ * This function needs to be modified to work with direct-rendering drivers.
+ */
+static GLXDrawable
+CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig,
+              unsigned int width, unsigned int height,
+              const int *attrib_list, GLboolean size_in_attribs)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   GLXDrawable id = 0;
+   CARD32 *data;
+   CARD8 opcode;
+   unsigned int i;
+
+   i = 0;
+   if (attrib_list) {
+      while (attrib_list[i * 2])
+         i++;
+   }
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return None;
+
+   LockDisplay(dpy);
+   id = XAllocID(dpy);
+
+   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+      xGLXCreatePbufferReq *req;
+      unsigned int extra = (size_in_attribs) ? 0 : 2;
+
+      GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
+      data = (CARD32 *) (req + 1);
+
+      req->reqType = opcode;
+      req->glxCode = X_GLXCreatePbuffer;
+      req->screen = (CARD32) fbconfig->screen;
+      req->fbconfig = fbconfig->fbconfigID;
+      req->pbuffer = (GLXPbuffer) id;
+      req->numAttribs = (CARD32) (i + extra);
+
+      if (!size_in_attribs) {
+         data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
+         data[(2 * i) + 1] = width;
+         data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
+         data[(2 * i) + 3] = height;
+         data += 4;
+      }
+   }
+   else {
+      xGLXVendorPrivateReq *vpreq;
+
+      GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
+      data = (CARD32 *) (vpreq + 1);
+
+      vpreq->reqType = opcode;
+      vpreq->glxCode = X_GLXVendorPrivate;
+      vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
+
+      data[0] = (CARD32) fbconfig->screen;
+      data[1] = (CARD32) fbconfig->fbconfigID;
+      data[2] = (CARD32) id;
+      data[3] = (CARD32) width;
+      data[4] = (CARD32) height;
+      data += 5;
+   }
+
+   (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return id;
+}
+
+
+/**
+ * Create a new pbuffer.
+ */
+PUBLIC GLXPbufferSGIX
+glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
+                        unsigned int width, unsigned int height,
+                        int *attrib_list)
+{
+   return (GLXPbufferSGIX) CreatePbuffer(dpy, (__GLcontextModes *) config,
+                                         width, height,
+                                         attrib_list, GL_FALSE);
+}
+
+
+/**
+ * Create a new pbuffer.
+ */
+PUBLIC GLXPbuffer
+glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
+{
+   int i, width, height;
+
+   width = 0;
+   height = 0;
+
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+
+   for (i = 0; attrib_list[i * 2]; i++) {
+      switch (attrib_list[i * 2]) {
+      case GLX_PBUFFER_WIDTH:
+         width = attrib_list[i * 2 + 1];
+         break;
+      case GLX_PBUFFER_HEIGHT:
+         height = attrib_list[i * 2 + 1];
+         break;
+      }
+   }
+
+   return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config,
+                                     width, height, attrib_list, GL_TRUE);
+}
+
+
+/**
+ * Destroy an existing pbuffer.
+ */
+PUBLIC void
+glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
+{
+   DestroyPbuffer(dpy, pbuf);
+}
+
+
+/**
+ * Query an attribute of a drawable.
+ */
+PUBLIC void
+glXQueryDrawable(Display * dpy, GLXDrawable drawable,
+                 int attribute, unsigned int *value)
+{
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+   GetDrawableAttribute(dpy, drawable, attribute, value);
+}
+
+
+/**
+ * Query an attribute of a pbuffer.
+ */
+PUBLIC int
+glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
+                       int attribute, unsigned int *value)
+{
+   return GetDrawableAttribute(dpy, drawable, attribute, value);
+}
+
+
+/**
+ * Select the event mask for a drawable.
+ */
+PUBLIC void
+glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
+{
+   CARD32 attribs[2];
+
+   attribs[0] = (CARD32) GLX_EVENT_MASK;
+   attribs[1] = (CARD32) mask;
+
+   ChangeDrawableAttribute(dpy, drawable, attribs, 1);
+}
+
+
+/**
+ * Get the selected event mask for a drawable.
+ */
+PUBLIC void
+glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
+{
+   unsigned int value;
+
+
+   /* The non-sense with value is required because on LP64 platforms
+    * sizeof(unsigned int) != sizeof(unsigned long).  On little-endian
+    * we could just type-cast the pointer, but why?
+    */
+
+   GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
+   *mask = value;
+}
+
+
+PUBLIC GLXPixmap
+glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
+                const int *attrib_list)
+{
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+
+   return CreateDrawable(dpy, (__GLcontextModes *) config,
+                         (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
+}
+
+
+PUBLIC GLXWindow
+glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
+                const int *attrib_list)
+{
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+
+   return CreateDrawable(dpy, (__GLcontextModes *) config,
+                         (Drawable) win, attrib_list, X_GLXCreateWindow);
+}
+
+
+PUBLIC void
+glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
+{
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+
+   DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
+}
+
+
+PUBLIC void
+glXDestroyWindow(Display * dpy, GLXWindow win)
+{
+   WARN_ONCE_GLX_1_3(dpy, __func__);
+
+   DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
+}
+
+
+PUBLIC
+GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
+               (Display * dpy, GLXPbufferSGIX pbuf),
+               (dpy, pbuf), glXDestroyPbuffer)
+
+PUBLIC
+GLX_ALIAS_VOID(glXSelectEventSGIX,
+               (Display * dpy, GLXDrawable drawable,
+                unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
+
+PUBLIC
+GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
+               (Display * dpy, GLXDrawable drawable,
+                unsigned long *mask), (dpy, drawable, mask),
+               glXGetSelectedEvent)
+
diff --git a/src/glx/glx_query.c b/src/glx/glx_query.c
new file mode 100644 (file)
index 0000000..efad13d
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright IBM Corporation 2004
+ * 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
+ * on 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
+ * IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glx_query.c
+ * Generic utility functions to query internal data from the server.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "glxclient.h"
+
+#if defined(USE_XCB)
+# include <X11/Xlib-xcb.h>
+# include <xcb/xcb.h>
+# include <xcb/glx.h>
+#endif
+
+#ifdef USE_XCB
+
+/**
+ * Exchange a protocol request for glXQueryServerString.
+ */
+char *
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
+{
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_glx_query_server_string_reply_t *reply =
+      xcb_glx_query_server_string_reply(c,
+                                        xcb_glx_query_server_string(c,
+                                                                    screen,
+                                                                    name),
+                                        NULL);
+
+   /* The spec doesn't mention this, but the Xorg server replies with
+    * a string already terminated with '\0'. */
+   uint32_t len = xcb_glx_query_server_string_string_length(reply);
+   char *buf = Xmalloc(len);
+   memcpy(buf, xcb_glx_query_server_string_string(reply), len);
+   free(reply);
+
+   return buf;
+}
+
+/**
+ * Exchange a protocol request for glGetString.
+ */
+char *
+__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
+{
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_glx_get_string_reply_t *reply = xcb_glx_get_string_reply(c,
+                                                                xcb_glx_get_string
+                                                                (c,
+                                                                 contextTag,
+                                                                 name),
+                                                                NULL);
+
+   /* The spec doesn't mention this, but the Xorg server replies with
+    * a string already terminated with '\0'. */
+   uint32_t len = xcb_glx_get_string_string_length(reply);
+   char *buf = Xmalloc(len);
+   memcpy(buf, xcb_glx_get_string_string(reply), len);
+   free(reply);
+
+   return buf;
+}
+
+#else
+
+/**
+ * GLX protocol structure for the ficticious "GXLGenericGetString" request.
+ *
+ * This is a non-existant protocol packet.  It just so happens that all of
+ * the real protocol packets used to request a string from the server have
+ * an identical binary layout.  The only difference between them is the
+ * meaning of the \c for_whom field and the value of the \c glxCode.
+ */
+typedef struct GLXGenericGetString
+{
+   CARD8 reqType;
+   CARD8 glxCode;
+   CARD16 length B16;
+   CARD32 for_whom B32;
+   CARD32 name B32;
+} xGLXGenericGetStringReq;
+
+/* These defines are only needed to make the GetReq macro happy.
+ */
+#define sz_xGLXGenericGetStringReq 12
+#define X_GLXGenericGetString 0
+
+/**
+ * Query the Server GLX string.
+ * This routine will allocate the necessay space for the string.
+ */
+static char *
+__glXGetStringFromServer(Display * dpy, int opcode, CARD32 glxCode,
+                         CARD32 for_whom, CARD32 name)
+{
+   xGLXGenericGetStringReq *req;
+   xGLXSingleReply reply;
+   int length;
+   int numbytes;
+   char *buf;
+
+
+   LockDisplay(dpy);
+
+
+   /* All of the GLX protocol requests for getting a string from the server
+    * look the same.  The exact meaning of the for_whom field is usually
+    * either the screen number (for glXQueryServerString) or the context tag
+    * (for GLXSingle).
+    */
+
+   GetReq(GLXGenericGetString, req);
+   req->reqType = opcode;
+   req->glxCode = glxCode;
+   req->for_whom = for_whom;
+   req->name = name;
+
+   _XReply(dpy, (xReply *) & reply, 0, False);
+
+   length = reply.length * 4;
+   numbytes = reply.size;
+
+   buf = (char *) Xmalloc(numbytes);
+   if (buf != NULL) {
+      _XRead(dpy, buf, numbytes);
+      length -= numbytes;
+   }
+
+   _XEatData(dpy, length);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return buf;
+}
+
+char *
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
+{
+   return __glXGetStringFromServer(dpy, opcode,
+                                   X_GLXQueryServerString, screen, name);
+}
+
+char *
+__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
+{
+   return __glXGetStringFromServer(dpy, opcode, X_GLsop_GetString,
+                                   contextTag, name);
+}
+
+#endif /* USE_XCB */
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
new file mode 100644 (file)
index 0000000..e0b286b
--- /dev/null
@@ -0,0 +1,803 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/**
+ * \file glxclient.h
+ * Direct rendering support added by Precision Insight, Inc.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+#ifndef _GLX_client_h_
+#define _GLX_client_h_
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/extutil.h>
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef WIN32
+#include <stdint.h>
+#endif
+#include "GL/glxint.h"
+#include "GL/glxproto.h"
+#include "GL/internal/glcore.h"
+#include "glapi/glapitable.h"
+#include "glxhash.h"
+#if defined( PTHREADS )
+# include <pthread.h>
+#endif
+
+#include "glxextensions.h"
+
+
+/* If we build the library with gcc's -fvisibility=hidden flag, we'll
+ * use the PUBLIC macro to mark functions that are to be exported.
+ *
+ * We also need to define a USED attribute, so the optimizer doesn't
+ * inline a static function that we later use in an alias. - ajax
+ */
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+#  define PUBLIC __attribute__((visibility("default")))
+#  define USED __attribute__((used))
+#else
+#  define PUBLIC
+#  define USED
+#endif
+
+
+
+#define GLX_MAJOR_VERSION 1       /* current version numbers */
+#define GLX_MINOR_VERSION 4
+
+#define __GLX_MAX_TEXTURE_UNITS 32
+
+typedef struct __GLXscreenConfigsRec __GLXscreenConfigs;
+typedef struct __GLXcontextRec __GLXcontext;
+typedef struct __GLXdrawableRec __GLXdrawable;
+typedef struct __GLXdisplayPrivateRec __GLXdisplayPrivate;
+typedef struct _glapi_table __GLapi;
+
+/************************************************************************/
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define containerOf(ptr, type, member)              \
+    (type *)( (char *)ptr - offsetof(type,member) )
+
+#include <GL/internal/dri_interface.h>
+
+
+/**
+ * Display dependent methods.  This structure is initialized during the
+ * \c driCreateDisplay call.
+ */
+typedef struct __GLXDRIdisplayRec __GLXDRIdisplay;
+typedef struct __GLXDRIscreenRec __GLXDRIscreen;
+typedef struct __GLXDRIdrawableRec __GLXDRIdrawable;
+typedef struct __GLXDRIcontextRec __GLXDRIcontext;
+
+#include "glxextensions.h"
+
+struct __GLXDRIdisplayRec
+{
+    /**
+     * Method to destroy the private DRI display data.
+     */
+   void (*destroyDisplay) (__GLXDRIdisplay * display);
+
+   __GLXDRIscreen *(*createScreen) (__GLXscreenConfigs * psc, int screen,
+                                    __GLXdisplayPrivate * priv);
+};
+
+struct __GLXDRIscreenRec {
+
+   void (*destroyScreen)(__GLXscreenConfigs *psc);
+
+   __GLXDRIcontext *(*createContext)(__GLXscreenConfigs *psc,
+                                    const __GLcontextModes *mode,
+                                    GLXContext gc,
+                                    GLXContext shareList, int renderType);
+
+   __GLXDRIdrawable *(*createDrawable)(__GLXscreenConfigs *psc,
+                                      XID drawable,
+                                      GLXDrawable glxDrawable,
+                                      const __GLcontextModes *modes);
+
+   int64_t (*swapBuffers)(__GLXDRIdrawable *pdraw, int64_t target_msc,
+                         int64_t divisor, int64_t remainder);
+   void (*copySubBuffer)(__GLXDRIdrawable *pdraw,
+                        int x, int y, int width, int height);
+   void (*waitX)(__GLXDRIdrawable *pdraw);
+   void (*waitGL)(__GLXDRIdrawable *pdraw);
+   int (*getDrawableMSC)(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw,
+                        int64_t *ust, int64_t *msc, int64_t *sbc);
+   int (*waitForMSC)(__GLXDRIdrawable *pdraw, int64_t target_msc,
+                    int64_t divisor, int64_t remainder, int64_t *ust,
+                    int64_t *msc, int64_t *sbc);
+   int (*waitForSBC)(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
+                    int64_t *msc, int64_t *sbc);
+   void (*setSwapInterval)(__GLXDRIdrawable *pdraw, int interval);
+   int (*getSwapInterval)(__GLXDRIdrawable *pdraw);
+};
+
+struct __GLXDRIcontextRec
+{
+   void (*destroyContext) (__GLXDRIcontext * context,
+                           __GLXscreenConfigs * psc, Display * dpy);
+     Bool(*bindContext) (__GLXDRIcontext * context, __GLXDRIdrawable * pdraw,
+                         __GLXDRIdrawable * pread);
+
+   void (*unbindContext) (__GLXDRIcontext * context);
+};
+
+struct __GLXDRIdrawableRec
+{
+   void (*destroyDrawable) (__GLXDRIdrawable * drawable);
+
+   XID xDrawable;
+   XID drawable;
+   __GLXscreenConfigs *psc;
+   GLenum textureTarget;
+   __DRIdrawable *driDrawable;
+   GLenum textureFormat;        /* EXT_texture_from_pixmap support */
+};
+
+/*
+** Function to create and DRI display data and initialize the display
+** dependent methods.
+*/
+extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy);
+extern __GLXDRIdisplay *driCreateDisplay(Display * dpy);
+extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
+
+extern void DRI_glXUseXFont(Font font, int first, int count, int listbase);
+
+/*
+** Functions to obtain driver configuration information from a direct
+** rendering client application
+*/
+extern const char *glXGetScreenDriver(Display * dpy, int scrNum);
+
+extern const char *glXGetDriverConfig(const char *driverName);
+
+#endif
+
+/************************************************************************/
+
+#define __GL_CLIENT_ATTRIB_STACK_DEPTH 16
+
+typedef struct __GLXpixelStoreModeRec
+{
+   GLboolean swapEndian;
+   GLboolean lsbFirst;
+   GLuint rowLength;
+   GLuint imageHeight;
+   GLuint imageDepth;
+   GLuint skipRows;
+   GLuint skipPixels;
+   GLuint skipImages;
+   GLuint alignment;
+} __GLXpixelStoreMode;
+
+
+typedef struct __GLXattributeRec
+{
+   GLuint mask;
+
+    /**
+     * Pixel storage state.  Most of the pixel store mode state is kept
+     * here and used by the client code to manage the packing and
+     * unpacking of data sent to/received from the server.
+     */
+   __GLXpixelStoreMode storePack, storeUnpack;
+
+    /**
+     * Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
+     * disabled?
+     */
+   GLboolean NoDrawArraysProtocol;
+
+    /**
+     * Vertex Array storage state.  The vertex array component
+     * state is stored here and is used to manage the packing of
+     * DrawArrays data sent to the server.
+     */
+   struct array_state_vector *array_state;
+} __GLXattribute;
+
+typedef struct __GLXattributeMachineRec
+{
+   __GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];
+   __GLXattribute **stackPointer;
+} __GLXattributeMachine;
+
+/**
+ * GLX state that needs to be kept on the client.  One of these records
+ * exist for each context that has been made current by this client.
+ */
+struct __GLXcontextRec
+{
+    /**
+     * \name Drawing command buffer.
+     *
+     * Drawing commands are packed into this buffer before being sent as a
+     * single GLX protocol request.  The buffer is sent when it overflows or
+     * is flushed by \c __glXFlushRenderBuffer.  \c pc is the next location
+     * in the buffer to be filled.  \c limit is described above in the buffer
+     * slop discussion.
+     *
+     * Commands that require large amounts of data to be transfered will
+     * also use this buffer to hold a header that describes the large
+     * command.
+     *
+     * These must be the first 6 fields since they are static initialized
+     * in the dummy context in glxext.c
+     */
+   /*@{ */
+   GLubyte *buf;
+   GLubyte *pc;
+   GLubyte *limit;
+   GLubyte *bufEnd;
+   GLint bufSize;
+   /*@} */
+
+    /**
+     * The XID of this rendering context.  When the context is created a
+     * new XID is allocated.  This is set to None when the context is
+     * destroyed but is still current to some thread. In this case the
+     * context will be freed on next MakeCurrent.
+     */
+   XID xid;
+
+    /**
+     * The XID of the \c shareList context.
+     */
+   XID share_xid;
+
+    /**
+     * Screen number.
+     */
+   GLint screen;
+   __GLXscreenConfigs *psc;
+
+    /**
+     * \c GL_TRUE if the context was created with ImportContext, which
+     * means the server-side context was created by another X client.
+     */
+   GLboolean imported;
+
+    /**
+     * The context tag returned by MakeCurrent when this context is made
+     * current. This tag is used to identify the context that a thread has
+     * current so that proper server context management can be done.  It is
+     * used for all context specific commands (i.e., \c Render, \c RenderLarge,
+     * \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old
+     * context)).
+     */
+   GLXContextTag currentContextTag;
+
+    /**
+     * \name Rendering mode
+     *
+     * The rendering mode is kept on the client as well as the server.
+     * When \c glRenderMode is called, the buffer associated with the
+     * previous rendering mode (feedback or select) is filled.
+     */
+   /*@{ */
+   GLenum renderMode;
+   GLfloat *feedbackBuf;
+   GLuint *selectBuf;
+   /*@} */
+
+    /**
+     * This is \c GL_TRUE if the pixel unpack modes are such that an image
+     * can be unpacked from the clients memory by just copying.  It may
+     * still be true that the server will have to do some work.  This
+     * just promises that a straight copy will fetch the correct bytes.
+     */
+   GLboolean fastImageUnpack;
+
+    /**
+     * Fill newImage with the unpacked form of \c oldImage getting it
+     * ready for transport to the server.
+     */
+   void (*fillImage) (__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+                      GLenum, const GLvoid *, GLubyte *, GLubyte *);
+
+    /**
+     * Client side attribs.
+     */
+   __GLXattributeMachine attributes;
+
+    /**
+     * Client side error code.  This is set when client side gl API
+     * routines need to set an error because of a bad enumerant or
+     * running out of memory, etc.
+     */
+   GLenum error;
+
+    /**
+     * Whether this context does direct rendering.
+     */
+   Bool isDirect;
+
+    /**
+     * \c dpy of current display for this context.  Will be \c NULL if not
+     * current to any display, or if this is the "dummy context".
+     */
+   Display *currentDpy;
+
+    /**
+     * The current drawable for this context.  Will be None if this
+     * context is not current to any drawable.  currentReadable is below.
+     */
+   GLXDrawable currentDrawable;
+
+    /**
+     * \name GL Constant Strings
+     *
+     * Constant strings that describe the server implementation
+     * These pertain to GL attributes, not to be confused with
+     * GLX versioning attributes.
+     */
+   /*@{ */
+   GLubyte *vendor;
+   GLubyte *renderer;
+   GLubyte *version;
+   GLubyte *extensions;
+   /*@} */
+
+    /**
+     * Record the dpy this context was created on for later freeing
+     */
+   Display *createDpy;
+
+    /**
+     * Maximum small render command size.  This is the smaller of 64k and
+     * the size of the above buffer.
+     */
+   GLint maxSmallRenderCommandSize;
+
+    /**
+     * Major opcode for the extension.  Copied here so a lookup isn't
+     * needed.
+     */
+   GLint majorOpcode;
+
+    /**
+     * Pointer to the mode used to create this context.
+     */
+   const __GLcontextModes *mode;
+
+#ifdef GLX_DIRECT_RENDERING
+   __GLXDRIcontext *driContext;
+   __DRIcontext *__driContext;
+#endif
+
+    /**
+     * The current read-drawable for this context.  Will be None if this
+     * context is not current to any drawable.
+     *
+     * \since Internal API version 20030606.
+     */
+   GLXDrawable currentReadable;
+
+   /**
+    * Pointer to client-state data that is private to libGL.  This is only
+    * used for indirect rendering contexts.
+    *
+    * No internal API version change was made for this change.  Client-side
+    * drivers should NEVER use this data or even care that it exists.
+    */
+   void *client_state_private;
+
+   /**
+    * Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.
+    */
+   int renderType;
+
+   /**
+    * \name Raw server GL version
+    *
+    * True core GL version supported by the server.  This is the raw value
+    * returned by the server, and it may not reflect what is actually
+    * supported (or reported) by the client-side library.
+    */
+   /*@{ */
+   int server_major;        /**< Major version number. */
+   int server_minor;        /**< Minor version number. */
+   /*@} */
+
+   /**
+    * Thread ID we're currently current in. Zero if none.
+    */
+   unsigned long thread_id;
+
+   char gl_extension_bits[__GL_EXT_BYTES];
+};
+
+#define __glXSetError(gc,code)  \
+   if (!(gc)->error) {          \
+      (gc)->error = code;       \
+   }
+
+extern void __glFreeAttributeState(__GLXcontext *);
+
+/************************************************************************/
+
+/**
+ * The size of the largest drawing command known to the implementation
+ * that will use the GLXRender GLX command.  In this case it is
+ * \c glPolygonStipple.
+ */
+#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156
+
+/**
+ * To keep the implementation fast, the code uses a "limit" pointer
+ * to determine when the drawing command buffer is too full to hold
+ * another fixed size command.  This constant defines the amount of
+ * space that must always be available in the drawing command buffer
+ * at all times for the implementation to work.  It is important that
+ * the number be just large enough, but not so large as to reduce the
+ * efficacy of the buffer.  The "+32" is just to keep the code working
+ * in case somebody counts wrong.
+ */
+#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32)
+
+/**
+ * This implementation uses a smaller threshold for switching
+ * to the RenderLarge protocol than the protcol requires so that
+ * large copies don't occur.
+ */
+#define __GLX_RENDER_CMD_SIZE_LIMIT 4096
+
+/**
+ * One of these records exists per screen of the display.  It contains
+ * a pointer to the config data for that screen (if the screen supports GL).
+ */
+struct __GLXscreenConfigsRec
+{
+    /**
+     * GLX extension string reported by the X-server.
+     */
+   const char *serverGLXexts;
+
+    /**
+     * GLX extension string to be reported to applications.  This is the
+     * set of extensions that the application can actually use.
+     */
+   char *effectiveGLXexts;
+
+#ifdef GLX_DIRECT_RENDERING
+    /**
+     * Per screen direct rendering interface functions and data.
+     */
+   __DRIscreen *__driScreen;
+   const __DRIcoreExtension *core;
+   const __DRIlegacyExtension *legacy;
+   const __DRIswrastExtension *swrast;
+   const __DRIdri2Extension *dri2;
+   __glxHashTable *drawHash;
+   Display *dpy;
+   int scr, fd;
+   void *driver;
+
+   __GLXDRIscreen *driScreen;
+
+   const __DRIconfig **driver_configs;
+
+#ifdef __DRI_COPY_SUB_BUFFER
+   const __DRIcopySubBufferExtension *driCopySubBuffer;
+#endif
+
+#ifdef __DRI_SWAP_CONTROL
+   const __DRIswapControlExtension *swapControl;
+#endif
+
+#ifdef __DRI_ALLOCATE
+   const __DRIallocateExtension *allocate;
+#endif
+
+#ifdef __DRI_FRAME_TRACKING
+   const __DRIframeTrackingExtension *frameTracking;
+#endif
+
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+   const __DRImediaStreamCounterExtension *msc;
+#endif
+
+#ifdef __DRI_TEX_BUFFER
+   const __DRItexBufferExtension *texBuffer;
+#endif
+
+#ifdef __DRI2_FLUSH
+   const __DRI2flushExtension *f;
+#endif
+
+#endif
+
+    /**
+     * Linked list of glx visuals and  fbconfigs for this screen.
+     */
+   __GLcontextModes *visuals, *configs;
+
+    /**
+     * Per-screen dynamic GLX extension tracking.  The \c direct_support
+     * field only contains enough bits for 64 extensions.  Should libGL
+     * ever need to track more than 64 GLX extensions, we can safely grow
+     * this field.  The \c __GLXscreenConfigs structure is not used outside
+     * libGL.
+     */
+   /*@{ */
+   unsigned char direct_support[8];
+   GLboolean ext_list_first_time;
+   /*@} */
+
+};
+
+/**
+ * Per display private data.  One of these records exists for each display
+ * that is using the OpenGL (GLX) extension.
+ */
+struct __GLXdisplayPrivateRec
+{
+    /**
+     * Back pointer to the display
+     */
+   Display *dpy;
+
+    /**
+     * The \c majorOpcode is common to all connections to the same server.
+     * It is also copied into the context structure.
+     */
+   int majorOpcode;
+
+    /**
+     * \name Server Version
+     *
+     * Major and minor version returned by the server during initialization.
+     */
+   /*@{ */
+   int majorVersion, minorVersion;
+   /*@} */
+
+    /**
+     * \name Storage for the servers GLX vendor and versions strings.
+     *
+     * These are the same for all screens on this display. These fields will
+     * be filled in on demand.
+     */
+   /*@{ */
+   const char *serverGLXvendor;
+   const char *serverGLXversion;
+   /*@} */
+
+    /**
+     * Configurations of visuals for all screens on this display.
+     * Also, per screen data which now includes the server \c GLX_EXTENSION
+     * string.
+     */
+   __GLXscreenConfigs *screenConfigs;
+
+#ifdef GLX_DIRECT_RENDERING
+    /**
+     * Per display direct rendering interface functions and data.
+     */
+   __GLXDRIdisplay *driswDisplay;
+   __GLXDRIdisplay *driDisplay;
+   __GLXDRIdisplay *dri2Display;
+#endif
+};
+
+
+extern GLubyte *__glXFlushRenderBuffer(__GLXcontext *, GLubyte *);
+
+extern void __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
+                                GLint totalRequests,
+                                const GLvoid * data, GLint dataLen);
+
+extern void __glXSendLargeCommand(__GLXcontext *, const GLvoid *, GLint,
+                                  const GLvoid *, GLint);
+
+/* Initialize the GLX extension for dpy */
+extern __GLXdisplayPrivate *__glXInitialize(Display *);
+
+extern void __glXPreferEGL(int state);
+
+/************************************************************************/
+
+extern int __glXDebug;
+
+/* This is per-thread storage in an MT environment */
+#if defined( PTHREADS )
+
+extern void __glXSetCurrentContext(__GLXcontext * c);
+
+# if defined( GLX_USE_TLS )
+
+extern __thread void *__glX_tls_Context
+   __attribute__ ((tls_model("initial-exec")));
+
+#  define __glXGetCurrentContext() __glX_tls_Context
+
+# else
+
+extern __GLXcontext *__glXGetCurrentContext(void);
+
+# endif /* defined( GLX_USE_TLS ) */
+
+#else
+
+extern __GLXcontext *__glXcurrentContext;
+#define __glXGetCurrentContext() __glXcurrentContext
+#define __glXSetCurrentContext(gc) __glXcurrentContext = gc
+
+#endif /* defined( PTHREADS ) */
+
+extern void __glXSetCurrentContextNull(void);
+
+extern void __glXFreeContext(__GLXcontext *);
+
+
+/*
+** Global lock for all threads in this address space using the GLX
+** extension
+*/
+#if defined( PTHREADS )
+extern pthread_mutex_t __glXmutex;
+#define __glXLock()    pthread_mutex_lock(&__glXmutex)
+#define __glXUnlock()  pthread_mutex_unlock(&__glXmutex)
+#else
+#define __glXLock()
+#define __glXUnlock()
+#endif
+
+/*
+** Setup for a command.  Initialize the extension for dpy if necessary.
+*/
+extern CARD8 __glXSetupForCommand(Display * dpy);
+
+/************************************************************************/
+
+/*
+** Data conversion and packing support.
+*/
+
+extern const GLuint __glXDefaultPixelStore[9];
+
+/* Send an image to the server using RenderLarge. */
+extern void __glXSendLargeImage(__GLXcontext * gc, GLint compsize, GLint dim,
+                                GLint width, GLint height, GLint depth,
+                                GLenum format, GLenum type,
+                                const GLvoid * src, GLubyte * pc,
+                                GLubyte * modes);
+
+/* Return the size, in bytes, of some pixel data */
+extern GLint __glImageSize(GLint, GLint, GLint, GLenum, GLenum, GLenum);
+
+/* Return the number of elements per group of a specified format*/
+extern GLint __glElementsPerGroup(GLenum format, GLenum type);
+
+/* Return the number of bytes per element, based on the element type (other
+** than GL_BITMAP).
+*/
+extern GLint __glBytesPerElement(GLenum type);
+
+/*
+** Fill the transport buffer with the data from the users buffer,
+** applying some of the pixel store modes (unpack modes) to the data
+** first.  As a side effect of this call, the "modes" field is
+** updated to contain the modes needed by the server to decode the
+** sent data.
+*/
+extern void __glFillImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+                          GLenum, const GLvoid *, GLubyte *, GLubyte *);
+
+/* Copy map data with a stride into a packed buffer */
+extern void __glFillMap1f(GLint, GLint, GLint, const GLfloat *, GLubyte *);
+extern void __glFillMap1d(GLint, GLint, GLint, const GLdouble *, GLubyte *);
+extern void __glFillMap2f(GLint, GLint, GLint, GLint, GLint,
+                          const GLfloat *, GLfloat *);
+extern void __glFillMap2d(GLint, GLint, GLint, GLint, GLint,
+                          const GLdouble *, GLdouble *);
+
+/*
+** Empty an image out of the reply buffer into the clients memory applying
+** the pack modes to pack back into the clients requested format.
+*/
+extern void __glEmptyImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+                           GLenum, const GLubyte *, GLvoid *);
+
+
+/*
+** Allocate and Initialize Vertex Array client state, and free.
+*/
+extern void __glXInitVertexArrayState(__GLXcontext *);
+extern void __glXFreeVertexArrayState(__GLXcontext *);
+
+/*
+** Inform the Server of the major and minor numbers and of the client
+** libraries extension string.
+*/
+extern void __glXClientInfo(Display * dpy, int opcode);
+
+/************************************************************************/
+
+/*
+** Declarations that should be in Xlib
+*/
+#ifdef __GL_USE_OUR_PROTOTYPES
+extern void _XFlush(Display *);
+extern Status _XReply(Display *, xReply *, int, Bool);
+extern void _XRead(Display *, void *, long);
+extern void _XSend(Display *, const void *, long);
+#endif
+
+
+extern void __glXInitializeVisualConfigFromTags(__GLcontextModes * config,
+                                                int count, const INT32 * bp,
+                                                Bool tagged_only,
+                                                Bool fbconfig_style_tags);
+
+extern char *__glXQueryServerString(Display * dpy, int opcode,
+                                    CARD32 screen, CARD32 name);
+extern char *__glXGetString(Display * dpy, int opcode,
+                            CARD32 screen, CARD32 name);
+
+extern char *__glXstrdup(const char *str);
+
+
+extern const char __glXGLClientVersion[];
+extern const char __glXGLClientExtensions[];
+
+/* Get the unadjusted system time */
+extern int __glXGetUST(int64_t * ust);
+
+extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
+                                    int32_t * numerator,
+                                    int32_t * denominator);
+
+#ifdef GLX_DIRECT_RENDERING
+GLboolean
+__driGetMscRateOML(__DRIdrawable * draw,
+                   int32_t * numerator, int32_t * denominator, void *private);
+
+/* So that dri2.c:DRI2WireToEvent() can access
+ * glx_info->codes->first_event */
+XExtDisplayInfo *__glXFindDisplay (Display *dpy);
+#endif
+
+#endif /* !__GLX_client_h__ */
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
new file mode 100644 (file)
index 0000000..c3be974
--- /dev/null
@@ -0,0 +1,3173 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/**
+ * \file glxcmds.c
+ * Client-side GLX interface.
+ */
+
+#include "glxclient.h"
+#include "glapi.h"
+#include "glxextensions.h"
+#include "glcontextmodes.h"
+
+#ifdef GLX_DIRECT_RENDERING
+#include <sys/time.h>
+#include <X11/extensions/xf86vmode.h>
+#include "xf86dri.h"
+#endif
+
+#if defined(USE_XCB)
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb.h>
+#include <xcb/glx.h>
+#endif
+
+static const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
+static const char __glXGLXClientVersion[] = "1.4";
+
+
+/****************************************************************************/
+
+#ifdef GLX_DIRECT_RENDERING
+
+static Bool windowExistsFlag;
+static int
+windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
+{
+   if (xerr->error_code == BadWindow) {
+      windowExistsFlag = GL_FALSE;
+   }
+   return 0;
+}
+
+/**
+ * Find drawables in the local hash that have been destroyed on the
+ * server.
+ *
+ * \param dpy    Display to destroy drawables for
+ * \param screen Screen number to destroy drawables for
+ */
+static void
+GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
+{
+   XID draw;
+   __GLXDRIdrawable *pdraw;
+   XWindowAttributes xwa;
+   int (*oldXErrorHandler) (Display *, XErrorEvent *);
+
+   /* Set no-op error handler so Xlib doesn't bail out if the windows
+    * has alreay been destroyed on the server. */
+   XSync(dpy, GL_FALSE);
+   oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
+
+   if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
+      do {
+         windowExistsFlag = GL_TRUE;
+         XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
+         if (!windowExistsFlag) {
+            /* Destroy the local drawable data, if the drawable no
+               longer exists in the Xserver */
+            (*pdraw->destroyDrawable) (pdraw);
+            __glxHashDelete(sc->drawHash, draw);
+         }
+      } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
+   }
+
+   XSync(dpy, GL_FALSE);
+   XSetErrorHandler(oldXErrorHandler);
+}
+
+extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
+                                           GLXDrawable drawable,
+                                           int *const scrn_num);
+
+/**
+ * Get the __DRIdrawable for the drawable associated with a GLXContext
+ *
+ * \param dpy       The display associated with \c drawable.
+ * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved.
+ * \param scrn_num  If non-NULL, the drawables screen is stored there
+ * \returns  A pointer to the context's __DRIdrawable on success, or NULL if
+ *           the drawable is not associated with a direct-rendering context.
+ */
+_X_HIDDEN __GLXDRIdrawable *
+GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   __GLXDRIdrawable *pdraw;
+   const unsigned screen_count = ScreenCount(dpy);
+   unsigned i;
+   __GLXscreenConfigs *psc;
+
+   if (priv == NULL)
+      return NULL;
+
+   for (i = 0; i < screen_count; i++) {
+      psc = &priv->screenConfigs[i];
+      if (psc->drawHash == NULL)
+         continue;
+
+      if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
+         if (scrn_num != NULL)
+            *scrn_num = i;
+         return pdraw;
+      }
+   }
+
+   return NULL;
+}
+
+#endif
+
+
+/**
+ * Get the GLX per-screen data structure associated with a GLX context.
+ *
+ * \param dpy   Display for which the GLX per-screen information is to be
+ *              retrieved.
+ * \param scrn  Screen on \c dpy for which the GLX per-screen information is
+ *              to be retrieved.
+ * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
+ *          specify a valid GLX screen, or NULL otherwise.
+ *
+ * \todo Should this function validate that \c scrn is within the screen
+ *       number range for \c dpy?
+ */
+
+static __GLXscreenConfigs *
+GetGLXScreenConfigs(Display * dpy, int scrn)
+{
+   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+
+   return (priv
+           && priv->screenConfigs !=
+           NULL) ? &priv->screenConfigs[scrn] : NULL;
+}
+
+
+static int
+GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
+                       __GLXscreenConfigs ** ppsc)
+{
+   /* Initialize the extension, if needed .  This has the added value
+    * of initializing/allocating the display private
+    */
+
+   if (dpy == NULL) {
+      return GLX_NO_EXTENSION;
+   }
+
+   *ppriv = __glXInitialize(dpy);
+   if (*ppriv == NULL) {
+      return GLX_NO_EXTENSION;
+   }
+
+   /* Check screen number to see if its valid */
+   if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
+      return GLX_BAD_SCREEN;
+   }
+
+   /* Check to see if the GL is supported on this screen */
+   *ppsc = &((*ppriv)->screenConfigs[scrn]);
+   if ((*ppsc)->configs == NULL) {
+      /* No support for GL on this screen regardless of visual */
+      return GLX_BAD_VISUAL;
+   }
+
+   return Success;
+}
+
+
+/**
+ * Determine if a \c GLXFBConfig supplied by the application is valid.
+ *
+ * \param dpy     Application supplied \c Display pointer.
+ * \param config  Application supplied \c GLXFBConfig.
+ *
+ * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
+ *          \c __GLcontextModes structure is returned.  Otherwise, \c NULL
+ *          is returned.
+ */
+static __GLcontextModes *
+ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
+{
+   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+   const unsigned num_screens = ScreenCount(dpy);
+   unsigned i;
+   const __GLcontextModes *modes;
+
+
+   if (priv != NULL) {
+      for (i = 0; i < num_screens; i++) {
+         for (modes = priv->screenConfigs[i].configs; modes != NULL;
+              modes = modes->next) {
+            if (modes == (__GLcontextModes *) config) {
+               return (__GLcontextModes *) config;
+            }
+         }
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * \todo It should be possible to move the allocate of \c client_state_private
+ * later in the function for direct-rendering contexts.  Direct-rendering
+ * contexts don't need to track client state, so they don't need that memory
+ * at all.
+ *
+ * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
+ * function called \c __glXAllocateClientState that allocates the memory and
+ * does all the initialization (including the pixel pack / unpack).
+ */
+static GLXContext
+AllocateGLXContext(Display * dpy)
+{
+   GLXContext gc;
+   int bufSize;
+   CARD8 opcode;
+   __GLXattribute *state;
+
+   if (!dpy)
+      return NULL;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return NULL;
+   }
+
+   /* Allocate our context record */
+   gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
+   if (!gc) {
+      /* Out of memory */
+      return NULL;
+   }
+   memset(gc, 0, sizeof(struct __GLXcontextRec));
+
+   state = Xmalloc(sizeof(struct __GLXattributeRec));
+   if (state == NULL) {
+      /* Out of memory */
+      Xfree(gc);
+      return NULL;
+   }
+   gc->client_state_private = state;
+   memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
+   state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
+
+   /*
+    ** Create a temporary buffer to hold GLX rendering commands.  The size
+    ** of the buffer is selected so that the maximum number of GLX rendering
+    ** commands can fit in a single X packet and still have room in the X
+    ** packet for the GLXRenderReq header.
+    */
+
+   bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
+   gc->buf = (GLubyte *) Xmalloc(bufSize);
+   if (!gc->buf) {
+      Xfree(gc->client_state_private);
+      Xfree(gc);
+      return NULL;
+   }
+   gc->bufSize = bufSize;
+
+   /* Fill in the new context */
+   gc->renderMode = GL_RENDER;
+
+   state->storePack.alignment = 4;
+   state->storeUnpack.alignment = 4;
+
+   gc->attributes.stackPointer = &gc->attributes.stack[0];
+
+   /*
+    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
+    ** Other code uses the fastImageUnpack bit, but it is never set
+    ** to GL_TRUE.
+    */
+   gc->fastImageUnpack = GL_FALSE;
+   gc->fillImage = __glFillImage;
+   gc->pc = gc->buf;
+   gc->bufEnd = gc->buf + bufSize;
+   gc->isDirect = GL_FALSE;
+   if (__glXDebug) {
+      /*
+       ** Set limit register so that there will be one command per packet
+       */
+      gc->limit = gc->buf;
+   }
+   else {
+      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
+   }
+   gc->createDpy = dpy;
+   gc->majorOpcode = opcode;
+
+   /*
+    ** Constrain the maximum drawing command size allowed to be
+    ** transfered using the X_GLXRender protocol request.  First
+    ** constrain by a software limit, then constrain by the protocl
+    ** limit.
+    */
+   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
+      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
+   }
+   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
+      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
+   }
+   gc->maxSmallRenderCommandSize = bufSize;
+   return gc;
+}
+
+
+/**
+ * Create a new context.  Exactly one of \c vis and \c fbconfig should be
+ * non-NULL.
+ *
+ * \param use_glx_1_3  For FBConfigs, should GLX 1.3 protocol or
+ *                     SGIX_fbconfig protocol be used?
+ * \param renderType   For FBConfigs, what is the rendering type?
+ */
+
+static GLXContext
+CreateContext(Display * dpy, XVisualInfo * vis,
+              const __GLcontextModes * const fbconfig,
+              GLXContext shareList,
+              Bool allowDirect, GLXContextID contextID,
+              Bool use_glx_1_3, int renderType)
+{
+   GLXContext gc;
+#ifdef GLX_DIRECT_RENDERING
+   int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+#endif
+
+   if (dpy == NULL)
+      return NULL;
+
+   gc = AllocateGLXContext(dpy);
+   if (!gc)
+      return NULL;
+
+   if (None == contextID) {
+      if ((vis == NULL) && (fbconfig == NULL))
+         return NULL;
+
+#ifdef GLX_DIRECT_RENDERING
+      if (allowDirect && psc->driScreen) {
+         const __GLcontextModes *mode;
+
+         if (fbconfig == NULL) {
+            mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+            if (mode == NULL) {
+               xError error;
+
+               error.errorCode = BadValue;
+               error.resourceID = vis->visualid;
+               error.sequenceNumber = dpy->request;
+               error.type = X_Error;
+               error.majorCode = gc->majorOpcode;
+               error.minorCode = X_GLXCreateContext;
+               _XError(dpy, &error);
+               return None;
+            }
+            if (renderType == 0) {
+               /* Initialize renderType now */
+               renderType = mode->rgbMode ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE;
+            }
+         }
+         else {
+            mode = fbconfig;
+         }
+
+         gc->driContext = psc->driScreen->createContext(psc, mode, gc,
+                                                        shareList,
+                                                        renderType);
+         if (gc->driContext != NULL) {
+            gc->screen = mode->screen;
+            gc->psc = psc;
+            gc->mode = mode;
+            gc->isDirect = GL_TRUE;
+         }
+      }
+#endif
+
+      LockDisplay(dpy);
+      if (fbconfig == NULL) {
+         xGLXCreateContextReq *req;
+
+         /* Send the glXCreateContext request */
+         GetReq(GLXCreateContext, req);
+         req->reqType = gc->majorOpcode;
+         req->glxCode = X_GLXCreateContext;
+         req->context = gc->xid = XAllocID(dpy);
+         req->visual = vis->visualid;
+         req->screen = vis->screen;
+         req->shareList = shareList ? shareList->xid : None;
+#ifdef GLX_DIRECT_RENDERING
+         req->isDirect = gc->driContext != NULL;
+#else
+         req->isDirect = 0;
+#endif
+      }
+      else if (use_glx_1_3) {
+         xGLXCreateNewContextReq *req;
+
+         /* Send the glXCreateNewContext request */
+         GetReq(GLXCreateNewContext, req);
+         req->reqType = gc->majorOpcode;
+         req->glxCode = X_GLXCreateNewContext;
+         req->context = gc->xid = XAllocID(dpy);
+         req->fbconfig = fbconfig->fbconfigID;
+         req->screen = fbconfig->screen;
+         req->renderType = renderType;
+         req->shareList = shareList ? shareList->xid : None;
+#ifdef GLX_DIRECT_RENDERING
+         req->isDirect = gc->driContext != NULL;
+#else
+         req->isDirect = 0;
+#endif
+      }
+      else {
+         xGLXVendorPrivateWithReplyReq *vpreq;
+         xGLXCreateContextWithConfigSGIXReq *req;
+
+         /* Send the glXCreateNewContext request */
+         GetReqExtra(GLXVendorPrivateWithReply,
+                     sz_xGLXCreateContextWithConfigSGIXReq -
+                     sz_xGLXVendorPrivateWithReplyReq, vpreq);
+         req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
+         req->reqType = gc->majorOpcode;
+         req->glxCode = X_GLXVendorPrivateWithReply;
+         req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
+         req->context = gc->xid = XAllocID(dpy);
+         req->fbconfig = fbconfig->fbconfigID;
+         req->screen = fbconfig->screen;
+         req->renderType = renderType;
+         req->shareList = shareList ? shareList->xid : None;
+#ifdef GLX_DIRECT_RENDERING
+         req->isDirect = gc->driContext != NULL;
+#else
+         req->isDirect = 0;
+#endif
+      }
+
+      UnlockDisplay(dpy);
+      SyncHandle();
+      gc->imported = GL_FALSE;
+   }
+   else {
+      gc->xid = contextID;
+      gc->imported = GL_TRUE;
+   }
+
+   gc->renderType = renderType;
+
+   return gc;
+}
+
+PUBLIC GLXContext
+glXCreateContext(Display * dpy, XVisualInfo * vis,
+                 GLXContext shareList, Bool allowDirect)
+{
+   return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
+                        False, 0);
+}
+
+_X_HIDDEN void
+__glXFreeContext(__GLXcontext * gc)
+{
+   if (gc->vendor)
+      XFree((char *) gc->vendor);
+   if (gc->renderer)
+      XFree((char *) gc->renderer);
+   if (gc->version)
+      XFree((char *) gc->version);
+   if (gc->extensions)
+      XFree((char *) gc->extensions);
+   __glFreeAttributeState(gc);
+   XFree((char *) gc->buf);
+   Xfree((char *) gc->client_state_private);
+   XFree((char *) gc);
+
+}
+
+/*
+** Destroy the named context
+*/
+static void
+DestroyContext(Display * dpy, GLXContext gc)
+{
+   xGLXDestroyContextReq *req;
+   GLXContextID xid;
+   CARD8 opcode;
+   GLboolean imported;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode || !gc) {
+      return;
+   }
+
+   __glXLock();
+   xid = gc->xid;
+   imported = gc->imported;
+   gc->xid = None;
+
+   if (gc->currentDpy) {
+      /* This context is bound to some thread.  According to the man page,
+       * we should not actually delete the context until it's unbound.
+       * Note that we set gc->xid = None above.  In MakeContextCurrent()
+       * we check for that and delete the context there.
+       */
+      __glXUnlock();
+      return;
+   }
+
+#ifdef GLX_DIRECT_RENDERING
+   /* Destroy the direct rendering context */
+   if (gc->driContext) {
+      (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy);
+      gc->driContext = NULL;
+      GarbageCollectDRIDrawables(dpy, gc->psc);
+   }
+#endif
+
+   __glXFreeVertexArrayState(gc);
+
+   if (gc->currentDpy) {
+      /* Have to free later cuz it's in use now */
+      __glXUnlock();
+   }
+   else {
+      /* Destroy the handle if not current to anybody */
+      __glXUnlock();
+      __glXFreeContext(gc);
+   }
+
+   if (!imported) {
+      /*
+       ** This dpy also created the server side part of the context.
+       ** Send the glXDestroyContext request.
+       */
+      LockDisplay(dpy);
+      GetReq(GLXDestroyContext, req);
+      req->reqType = opcode;
+      req->glxCode = X_GLXDestroyContext;
+      req->context = xid;
+      UnlockDisplay(dpy);
+      SyncHandle();
+   }
+}
+
+PUBLIC void
+glXDestroyContext(Display * dpy, GLXContext gc)
+{
+   DestroyContext(dpy, gc);
+}
+
+/*
+** Return the major and minor version #s for the GLX extension
+*/
+PUBLIC Bool
+glXQueryVersion(Display * dpy, int *major, int *minor)
+{
+   __GLXdisplayPrivate *priv;
+
+   /* Init the extension.  This fetches the major and minor version. */
+   priv = __glXInitialize(dpy);
+   if (!priv)
+      return GL_FALSE;
+
+   if (major)
+      *major = priv->majorVersion;
+   if (minor)
+      *minor = priv->minorVersion;
+   return GL_TRUE;
+}
+
+/*
+** Query the existance of the GLX extension
+*/
+PUBLIC Bool
+glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
+{
+   int major_op, erb, evb;
+   Bool rv;
+
+   rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
+   if (rv) {
+      if (errorBase)
+         *errorBase = erb;
+      if (eventBase)
+         *eventBase = evb;
+   }
+   return rv;
+}
+
+/*
+** Put a barrier in the token stream that forces the GL to finish its
+** work before X can proceed.
+*/
+PUBLIC void
+glXWaitGL(void)
+{
+   xGLXWaitGLReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   Display *dpy = gc->currentDpy;
+
+   if (!dpy)
+      return;
+
+   /* Flush any pending commands out */
+   __glXFlushRenderBuffer(gc, gc->pc);
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext) {
+      int screen;
+      __GLXDRIdrawable *pdraw =
+         GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
+
+      if (pdraw != NULL) {
+         __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+         glFlush();
+         if (psc->driScreen->waitGL != NULL)
+            (*psc->driScreen->waitGL) (pdraw);
+      }
+      return;
+   }
+#endif
+
+   /* Send the glXWaitGL request */
+   LockDisplay(dpy);
+   GetReq(GLXWaitGL, req);
+   req->reqType = gc->majorOpcode;
+   req->glxCode = X_GLXWaitGL;
+   req->contextTag = gc->currentContextTag;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+/*
+** Put a barrier in the token stream that forces X to finish its
+** work before GL can proceed.
+*/
+PUBLIC void
+glXWaitX(void)
+{
+   xGLXWaitXReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   Display *dpy = gc->currentDpy;
+
+   if (!dpy)
+      return;
+
+   /* Flush any pending commands out */
+   __glXFlushRenderBuffer(gc, gc->pc);
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext) {
+      int screen;
+      __GLXDRIdrawable *pdraw =
+         GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
+
+      if (pdraw != NULL) {
+         __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+         if (psc->driScreen->waitX != NULL)
+            (*psc->driScreen->waitX) (pdraw);
+      }
+      else
+         XSync(dpy, False);
+      return;
+   }
+#endif
+
+   /*
+    ** Send the glXWaitX request.
+    */
+   LockDisplay(dpy);
+   GetReq(GLXWaitX, req);
+   req->reqType = gc->majorOpcode;
+   req->glxCode = X_GLXWaitX;
+   req->contextTag = gc->currentContextTag;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+PUBLIC void
+glXUseXFont(Font font, int first, int count, int listBase)
+{
+   xGLXUseXFontReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   Display *dpy = gc->currentDpy;
+
+   if (!dpy)
+      return;
+
+   /* Flush any pending commands out */
+   (void) __glXFlushRenderBuffer(gc, gc->pc);
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext) {
+      DRI_glXUseXFont(font, first, count, listBase);
+      return;
+   }
+#endif
+
+   /* Send the glXUseFont request */
+   LockDisplay(dpy);
+   GetReq(GLXUseXFont, req);
+   req->reqType = gc->majorOpcode;
+   req->glxCode = X_GLXUseXFont;
+   req->contextTag = gc->currentContextTag;
+   req->font = font;
+   req->first = first;
+   req->count = count;
+   req->listBase = listBase;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+/************************************************************************/
+
+/*
+** Copy the source context to the destination context using the
+** attribute "mask".
+*/
+PUBLIC void
+glXCopyContext(Display * dpy, GLXContext source,
+               GLXContext dest, unsigned long mask)
+{
+   xGLXCopyContextReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   GLXContextTag tag;
+   CARD8 opcode;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return;
+   }
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext) {
+      /* NOT_DONE: This does not work yet */
+   }
+#endif
+
+   /*
+    ** If the source is the current context, send its tag so that the context
+    ** can be flushed before the copy.
+    */
+   if (source == gc && dpy == gc->currentDpy) {
+      tag = gc->currentContextTag;
+   }
+   else {
+      tag = 0;
+   }
+
+   /* Send the glXCopyContext request */
+   LockDisplay(dpy);
+   GetReq(GLXCopyContext, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXCopyContext;
+   req->source = source ? source->xid : None;
+   req->dest = dest ? dest->xid : None;
+   req->mask = mask;
+   req->contextTag = tag;
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+
+/**
+ * Determine if a context uses direct rendering.
+ *
+ * \param dpy        Display where the context was created.
+ * \param contextID  ID of the context to be tested.
+ *
+ * \returns \c GL_TRUE if the context is direct rendering or not.
+ */
+static Bool
+__glXIsDirect(Display * dpy, GLXContextID contextID)
+{
+#if !defined(USE_XCB)
+   xGLXIsDirectReq *req;
+   xGLXIsDirectReply reply;
+#endif
+   CARD8 opcode;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return GL_FALSE;
+   }
+
+#ifdef USE_XCB
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c,
+                                                              xcb_glx_is_direct
+                                                              (c, contextID),
+                                                              NULL);
+
+   const Bool is_direct = reply->is_direct ? True : False;
+   free(reply);
+
+   return is_direct;
+#else
+   /* Send the glXIsDirect request */
+   LockDisplay(dpy);
+   GetReq(GLXIsDirect, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXIsDirect;
+   req->context = contextID;
+   _XReply(dpy, (xReply *) & reply, 0, False);
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return reply.isDirect;
+#endif /* USE_XCB */
+}
+
+/**
+ * \todo
+ * Shouldn't this function \b always return \c GL_FALSE when
+ * \c GLX_DIRECT_RENDERING is not defined?  Do we really need to bother with
+ * the GLX protocol here at all?
+ */
+PUBLIC Bool
+glXIsDirect(Display * dpy, GLXContext gc)
+{
+   if (!gc) {
+      return GL_FALSE;
+#ifdef GLX_DIRECT_RENDERING
+   }
+   else if (gc->driContext) {
+      return GL_TRUE;
+#endif
+   }
+   return __glXIsDirect(dpy, gc->xid);
+}
+
+PUBLIC GLXPixmap
+glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
+{
+   xGLXCreateGLXPixmapReq *req;
+   GLXPixmap xid;
+   CARD8 opcode;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return None;
+   }
+
+   /* Send the glXCreateGLXPixmap request */
+   LockDisplay(dpy);
+   GetReq(GLXCreateGLXPixmap, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXCreateGLXPixmap;
+   req->screen = vis->screen;
+   req->visual = vis->visualid;
+   req->pixmap = pixmap;
+   req->glxpixmap = xid = XAllocID(dpy);
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+#ifdef GLX_DIRECT_RENDERING
+   do {
+      /* FIXME: Maybe delay __DRIdrawable creation until the drawable
+       * is actually bound to a context... */
+
+      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+      __GLXDRIdrawable *pdraw;
+      __GLXscreenConfigs *psc;
+      __GLcontextModes *modes;
+
+      psc = &priv->screenConfigs[vis->screen];
+      if (psc->driScreen == NULL)
+         break;
+      modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+      pdraw = psc->driScreen->createDrawable(psc, pixmap, req->glxpixmap, modes);
+      if (pdraw == NULL) {
+         fprintf(stderr, "failed to create pixmap\n");
+         break;
+      }
+
+      if (__glxHashInsert(psc->drawHash, req->glxpixmap, pdraw)) {
+         (*pdraw->destroyDrawable) (pdraw);
+         return None;           /* FIXME: Check what we're supposed to do here... */
+      }
+   } while (0);
+#endif
+
+   return xid;
+}
+
+/*
+** Destroy the named pixmap
+*/
+PUBLIC void
+glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
+{
+   xGLXDestroyGLXPixmapReq *req;
+   CARD8 opcode;
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return;
+   }
+
+   /* Send the glXDestroyGLXPixmap request */
+   LockDisplay(dpy);
+   GetReq(GLXDestroyGLXPixmap, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXDestroyGLXPixmap;
+   req->glxpixmap = glxpixmap;
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+#ifdef GLX_DIRECT_RENDERING
+   {
+      int screen;
+      __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen);
+      __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
+
+      if (pdraw != NULL) {
+         (*pdraw->destroyDrawable) (pdraw);
+         __glxHashDelete(psc->drawHash, glxpixmap);
+      }
+   }
+#endif
+}
+
+PUBLIC void
+glXSwapBuffers(Display * dpy, GLXDrawable drawable)
+{
+   GLXContext gc;
+   GLXContextTag tag;
+   CARD8 opcode;
+#ifdef USE_XCB
+   xcb_connection_t *c;
+#else
+   xGLXSwapBuffersReq *req;
+#endif
+
+#ifdef GLX_DIRECT_RENDERING
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+   if (pdraw != NULL) {
+      glFlush();
+      (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0);
+      return;
+   }
+#endif
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return;
+   }
+
+   /*
+    ** The calling thread may or may not have a current context.  If it
+    ** does, send the context tag so the server can do a flush.
+    */
+   gc = __glXGetCurrentContext();
+   if ((gc != NULL) && (dpy == gc->currentDpy) &&
+       ((drawable == gc->currentDrawable)
+        || (drawable == gc->currentReadable))) {
+      tag = gc->currentContextTag;
+   }
+   else {
+      tag = 0;
+   }
+
+#ifdef USE_XCB
+   c = XGetXCBConnection(dpy);
+   xcb_glx_swap_buffers(c, tag, drawable);
+   xcb_flush(c);
+#else
+   /* Send the glXSwapBuffers request */
+   LockDisplay(dpy);
+   GetReq(GLXSwapBuffers, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXSwapBuffers;
+   req->drawable = drawable;
+   req->contextTag = tag;
+   UnlockDisplay(dpy);
+   SyncHandle();
+   XFlush(dpy);
+#endif /* USE_XCB */
+}
+
+
+/*
+** Return configuration information for the given display, screen and
+** visual combination.
+*/
+PUBLIC int
+glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
+             int *value_return)
+{
+   __GLXdisplayPrivate *priv;
+   __GLXscreenConfigs *psc;
+   __GLcontextModes *modes;
+   int status;
+
+   status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
+   if (status == Success) {
+      modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+
+      /* Lookup attribute after first finding a match on the visual */
+      if (modes != NULL) {
+         return _gl_get_context_mode_data(modes, attribute, value_return);
+      }
+
+      status = GLX_BAD_VISUAL;
+   }
+
+   /*
+    ** If we can't find the config for this visual, this visual is not
+    ** supported by the OpenGL implementation on the server.
+    */
+   if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
+      *value_return = GL_FALSE;
+      status = Success;
+   }
+
+   return status;
+}
+
+/************************************************************************/
+
+static void
+init_fbconfig_for_chooser(__GLcontextModes * config,
+                          GLboolean fbconfig_style_tags)
+{
+   memset(config, 0, sizeof(__GLcontextModes));
+   config->visualID = (XID) GLX_DONT_CARE;
+   config->visualType = GLX_DONT_CARE;
+
+   /* glXChooseFBConfig specifies different defaults for these two than
+    * glXChooseVisual.
+    */
+   if (fbconfig_style_tags) {
+      config->rgbMode = GL_TRUE;
+      config->doubleBufferMode = GLX_DONT_CARE;
+   }
+
+   config->visualRating = GLX_DONT_CARE;
+   config->transparentPixel = GLX_NONE;
+   config->transparentRed = GLX_DONT_CARE;
+   config->transparentGreen = GLX_DONT_CARE;
+   config->transparentBlue = GLX_DONT_CARE;
+   config->transparentAlpha = GLX_DONT_CARE;
+   config->transparentIndex = GLX_DONT_CARE;
+
+   config->drawableType = GLX_WINDOW_BIT;
+   config->renderType =
+      (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+   config->xRenderable = GLX_DONT_CARE;
+   config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
+
+   config->swapMethod = GLX_DONT_CARE;
+}
+
+#define MATCH_DONT_CARE( param )        \
+  do {                                  \
+    if ( (a-> param != GLX_DONT_CARE)   \
+         && (a-> param != b-> param) ) {        \
+      return False;                             \
+    }                                           \
+  } while ( 0 )
+
+#define MATCH_MINIMUM( param )                  \
+  do {                                          \
+    if ( (a-> param != GLX_DONT_CARE)           \
+         && (a-> param > b-> param) ) {         \
+      return False;                             \
+    }                                           \
+  } while ( 0 )
+
+#define MATCH_EXACT( param )                    \
+  do {                                          \
+    if ( a-> param != b-> param) {              \
+      return False;                             \
+    }                                           \
+  } while ( 0 )
+
+/**
+ * Determine if two GLXFBConfigs are compatible.
+ *
+ * \param a  Application specified config to test.
+ * \param b  Server specified config to test against \c a.
+ */
+static Bool
+fbconfigs_compatible(const __GLcontextModes * const a,
+                     const __GLcontextModes * const b)
+{
+   MATCH_DONT_CARE(doubleBufferMode);
+   MATCH_DONT_CARE(visualType);
+   MATCH_DONT_CARE(visualRating);
+   MATCH_DONT_CARE(xRenderable);
+   MATCH_DONT_CARE(fbconfigID);
+   MATCH_DONT_CARE(swapMethod);
+
+   MATCH_MINIMUM(rgbBits);
+   MATCH_MINIMUM(numAuxBuffers);
+   MATCH_MINIMUM(redBits);
+   MATCH_MINIMUM(greenBits);
+   MATCH_MINIMUM(blueBits);
+   MATCH_MINIMUM(alphaBits);
+   MATCH_MINIMUM(depthBits);
+   MATCH_MINIMUM(stencilBits);
+   MATCH_MINIMUM(accumRedBits);
+   MATCH_MINIMUM(accumGreenBits);
+   MATCH_MINIMUM(accumBlueBits);
+   MATCH_MINIMUM(accumAlphaBits);
+   MATCH_MINIMUM(sampleBuffers);
+   MATCH_MINIMUM(maxPbufferWidth);
+   MATCH_MINIMUM(maxPbufferHeight);
+   MATCH_MINIMUM(maxPbufferPixels);
+   MATCH_MINIMUM(samples);
+
+   MATCH_DONT_CARE(stereoMode);
+   MATCH_EXACT(level);
+
+   if (((a->drawableType & b->drawableType) == 0)
+       || ((a->renderType & b->renderType) == 0)) {
+      return False;
+   }
+
+
+   /* There is a bug in a few of the XFree86 DDX drivers.  They contain
+    * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
+    * Technically speaking, it is a bug in the DDX driver, but there is
+    * enough of an installed base to work around the problem here.  In any
+    * case, 0 is not a valid value of the transparent type, so we'll treat 0
+    * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
+    * 0 from the server to be a match to maintain backward compatibility with
+    * the (broken) drivers.
+    */
+
+   if (a->transparentPixel != GLX_DONT_CARE && a->transparentPixel != 0) {
+      if (a->transparentPixel == GLX_NONE) {
+         if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
+            return False;
+      }
+      else {
+         MATCH_EXACT(transparentPixel);
+      }
+
+      switch (a->transparentPixel) {
+      case GLX_TRANSPARENT_RGB:
+         MATCH_DONT_CARE(transparentRed);
+         MATCH_DONT_CARE(transparentGreen);
+         MATCH_DONT_CARE(transparentBlue);
+         MATCH_DONT_CARE(transparentAlpha);
+         break;
+
+      case GLX_TRANSPARENT_INDEX:
+         MATCH_DONT_CARE(transparentIndex);
+         break;
+
+      default:
+         break;
+      }
+   }
+
+   return True;
+}
+
+
+/* There's some trickly language in the GLX spec about how this is supposed
+ * to work.  Basically, if a given component size is either not specified
+ * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
+ * Well, that's really hard to do with the code as-is.  This behavior is
+ * closer to correct, but still not technically right.
+ */
+#define PREFER_LARGER_OR_ZERO(comp)             \
+  do {                                          \
+    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
+      if ( ((*a)-> comp) == 0 ) {               \
+        return -1;                              \
+      }                                         \
+      else if ( ((*b)-> comp) == 0 ) {          \
+        return 1;                               \
+      }                                         \
+      else {                                    \
+        return ((*b)-> comp) - ((*a)-> comp) ;  \
+      }                                         \
+    }                                           \
+  } while( 0 )
+
+#define PREFER_LARGER(comp)                     \
+  do {                                          \
+    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
+      return ((*b)-> comp) - ((*a)-> comp) ;    \
+    }                                           \
+  } while( 0 )
+
+#define PREFER_SMALLER(comp)                    \
+  do {                                          \
+    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
+      return ((*a)-> comp) - ((*b)-> comp) ;    \
+    }                                           \
+  } while( 0 )
+
+/**
+ * Compare two GLXFBConfigs.  This function is intended to be used as the
+ * compare function passed in to qsort.
+ *
+ * \returns If \c a is a "better" config, according to the specification of
+ *          SGIX_fbconfig, a number less than zero is returned.  If \c b is
+ *          better, then a number greater than zero is return.  If both are
+ *          equal, zero is returned.
+ * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
+ */
+static int
+fbconfig_compare(const __GLcontextModes * const *const a,
+                 const __GLcontextModes * const *const b)
+{
+   /* The order of these comparisons must NOT change.  It is defined by
+    * the GLX 1.3 spec and ARB_multisample.
+    */
+
+   PREFER_SMALLER(visualSelectGroup);
+
+   /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
+    * GLX_NON_CONFORMANT_CONFIG.  It just so happens that this is the
+    * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
+    */
+   PREFER_SMALLER(visualRating);
+
+   /* This isn't quite right.  It is supposed to compare the sum of the
+    * components the user specifically set minimums for.
+    */
+   PREFER_LARGER_OR_ZERO(redBits);
+   PREFER_LARGER_OR_ZERO(greenBits);
+   PREFER_LARGER_OR_ZERO(blueBits);
+   PREFER_LARGER_OR_ZERO(alphaBits);
+
+   PREFER_SMALLER(rgbBits);
+
+   if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
+      /* Prefer single-buffer.
+       */
+      return (!(*a)->doubleBufferMode) ? -1 : 1;
+   }
+
+   PREFER_SMALLER(numAuxBuffers);
+
+   PREFER_LARGER_OR_ZERO(depthBits);
+   PREFER_SMALLER(stencilBits);
+
+   /* This isn't quite right.  It is supposed to compare the sum of the
+    * components the user specifically set minimums for.
+    */
+   PREFER_LARGER_OR_ZERO(accumRedBits);
+   PREFER_LARGER_OR_ZERO(accumGreenBits);
+   PREFER_LARGER_OR_ZERO(accumBlueBits);
+   PREFER_LARGER_OR_ZERO(accumAlphaBits);
+
+   PREFER_SMALLER(visualType);
+
+   /* None of the multisample specs say where this comparison should happen,
+    * so I put it near the end.
+    */
+   PREFER_SMALLER(sampleBuffers);
+   PREFER_SMALLER(samples);
+
+   /* None of the pbuffer or fbconfig specs say that this comparison needs
+    * to happen at all, but it seems like it should.
+    */
+   PREFER_LARGER(maxPbufferWidth);
+   PREFER_LARGER(maxPbufferHeight);
+   PREFER_LARGER(maxPbufferPixels);
+
+   return 0;
+}
+
+
+/**
+ * Selects and sorts a subset of the supplied configs based on the attributes.
+ * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
+ * and \c glXChooseFBConfigSGIX.
+ *
+ * \param configs   Array of pointers to possible configs.  The elements of
+ *                  this array that do not meet the criteria will be set to
+ *                  NULL.  The remaining elements will be sorted according to
+ *                  the various visual / FBConfig selection rules.
+ * \param num_configs  Number of elements in the \c configs array.
+ * \param attribList   Attributes used select from \c configs.  This array is
+ *                     terminated by a \c None tag.  The array can either take
+ *                     the form expected by \c glXChooseVisual (where boolean
+ *                     tags do not have a value) or by \c glXChooseFBConfig
+ *                     (where every tag has a value).
+ * \param fbconfig_style_tags  Selects whether \c attribList is in
+ *                             \c glXChooseVisual style or
+ *                             \c glXChooseFBConfig style.
+ * \returns The number of valid elements left in \c configs.
+ *
+ * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
+ */
+static int
+choose_visual(__GLcontextModes ** configs, int num_configs,
+              const int *attribList, GLboolean fbconfig_style_tags)
+{
+   __GLcontextModes test_config;
+   int base;
+   int i;
+
+   /* This is a fairly direct implementation of the selection method
+    * described by GLX_SGIX_fbconfig.  Start by culling out all the
+    * configs that are not compatible with the selected parameter
+    * list.
+    */
+
+   init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
+   __glXInitializeVisualConfigFromTags(&test_config, 512,
+                                       (const INT32 *) attribList,
+                                       GL_TRUE, fbconfig_style_tags);
+
+   base = 0;
+   for (i = 0; i < num_configs; i++) {
+      if (fbconfigs_compatible(&test_config, configs[i])) {
+         configs[base] = configs[i];
+         base++;
+      }
+   }
+
+   if (base == 0) {
+      return 0;
+   }
+
+   if (base < num_configs) {
+      (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
+   }
+
+   /* After the incompatible configs are removed, the resulting
+    * list is sorted according to the rules set out in the various
+    * specifications.
+    */
+
+   qsort(configs, base, sizeof(__GLcontextModes *),
+         (int (*)(const void *, const void *)) fbconfig_compare);
+   return base;
+}
+
+
+
+
+/*
+** Return the visual that best matches the template.  Return None if no
+** visual matches the template.
+*/
+PUBLIC XVisualInfo *
+glXChooseVisual(Display * dpy, int screen, int *attribList)
+{
+   XVisualInfo *visualList = NULL;
+   __GLXdisplayPrivate *priv;
+   __GLXscreenConfigs *psc;
+   __GLcontextModes test_config;
+   __GLcontextModes *modes;
+   const __GLcontextModes *best_config = NULL;
+
+   /*
+    ** Get a list of all visuals, return if list is empty
+    */
+   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+      return None;
+   }
+
+
+   /*
+    ** Build a template from the defaults and the attribute list
+    ** Free visual list and return if an unexpected token is encountered
+    */
+   init_fbconfig_for_chooser(&test_config, GL_FALSE);
+   __glXInitializeVisualConfigFromTags(&test_config, 512,
+                                       (const INT32 *) attribList,
+                                       GL_TRUE, GL_FALSE);
+
+   /*
+    ** Eliminate visuals that don't meet minimum requirements
+    ** Compute a score for those that do
+    ** Remember which visual, if any, got the highest score
+    ** If no visual is acceptable, return None
+    ** Otherwise, create an XVisualInfo list with just the selected X visual
+    ** and return this.
+    */
+   for (modes = psc->visuals; modes != NULL; modes = modes->next) {
+      if (fbconfigs_compatible(&test_config, modes)
+          && ((best_config == NULL)
+              ||
+              (fbconfig_compare
+               ((const __GLcontextModes * const *const) &modes,
+                &best_config) < 0))) {
+         XVisualInfo visualTemplate;
+         XVisualInfo *newList;
+         int i;
+
+         visualTemplate.screen = screen;
+         visualTemplate.visualid = modes->visualID;
+         newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
+                                  &visualTemplate, &i);
+
+         if (newList) {
+            Xfree(visualList);
+            visualList = newList;
+            best_config = modes;
+         }
+      }
+   }
+
+   return visualList;
+}
+
+
+PUBLIC const char *
+glXQueryExtensionsString(Display * dpy, int screen)
+{
+   __GLXscreenConfigs *psc;
+   __GLXdisplayPrivate *priv;
+
+   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+      return NULL;
+   }
+
+   if (!psc->effectiveGLXexts) {
+      if (!psc->serverGLXexts) {
+         psc->serverGLXexts =
+            __glXQueryServerString(dpy, priv->majorOpcode, screen,
+                                   GLX_EXTENSIONS);
+      }
+
+      __glXCalculateUsableExtensions(psc,
+#ifdef GLX_DIRECT_RENDERING
+                                     (psc->driScreen != NULL),
+#else
+                                     GL_FALSE,
+#endif
+                                     priv->minorVersion);
+   }
+
+   return psc->effectiveGLXexts;
+}
+
+PUBLIC const char *
+glXGetClientString(Display * dpy, int name)
+{
+   switch (name) {
+   case GLX_VENDOR:
+      return (__glXGLXClientVendorName);
+   case GLX_VERSION:
+      return (__glXGLXClientVersion);
+   case GLX_EXTENSIONS:
+      return (__glXGetClientExtensions());
+   default:
+      return NULL;
+   }
+}
+
+PUBLIC const char *
+glXQueryServerString(Display * dpy, int screen, int name)
+{
+   __GLXscreenConfigs *psc;
+   __GLXdisplayPrivate *priv;
+   const char **str;
+
+
+   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+      return NULL;
+   }
+
+   switch (name) {
+   case GLX_VENDOR:
+      str = &priv->serverGLXvendor;
+      break;
+   case GLX_VERSION:
+      str = &priv->serverGLXversion;
+      break;
+   case GLX_EXTENSIONS:
+      str = &psc->serverGLXexts;
+      break;
+   default:
+      return NULL;
+   }
+
+   if (*str == NULL) {
+      *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
+   }
+
+   return *str;
+}
+
+void
+__glXClientInfo(Display * dpy, int opcode)
+{
+   char *ext_str = __glXGetClientGLExtensionString();
+   int size = strlen(ext_str) + 1;
+
+#ifdef USE_XCB
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_glx_client_info(c,
+                       GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str);
+#else
+   xGLXClientInfoReq *req;
+
+   /* Send the glXClientInfo request */
+   LockDisplay(dpy);
+   GetReq(GLXClientInfo, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXClientInfo;
+   req->major = GLX_MAJOR_VERSION;
+   req->minor = GLX_MINOR_VERSION;
+
+   req->length += (size + 3) >> 2;
+   req->numbytes = size;
+   Data(dpy, ext_str, size);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+#endif /* USE_XCB */
+
+   Xfree(ext_str);
+}
+
+
+/*
+** EXT_import_context
+*/
+
+PUBLIC Display *
+glXGetCurrentDisplay(void)
+{
+   GLXContext gc = __glXGetCurrentContext();
+   if (NULL == gc)
+      return NULL;
+   return gc->currentDpy;
+}
+
+PUBLIC
+GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
+          glXGetCurrentDisplay)
+
+/**
+ * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
+ * to the X-server.
+ *
+ * \param dpy  Display where \c ctx was created.
+ * \param ctx  Context to query.
+ * \returns  \c Success on success.  \c GLX_BAD_CONTEXT if \c ctx is invalid,
+ *           or zero if the request failed due to internal problems (i.e.,
+ *           unable to allocate temporary memory, etc.)
+ *
+ * \note
+ * This function dynamically determines whether to use the EXT_import_context
+ * version of the protocol or the GLX 1.3 version of the protocol.
+ */
+static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   xGLXQueryContextReply reply;
+   CARD8 opcode;
+   GLuint numValues;
+   int retval;
+
+   if (ctx == NULL) {
+      return GLX_BAD_CONTEXT;
+   }
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return 0;
+   }
+
+   /* Send the glXQueryContextInfoEXT request */
+   LockDisplay(dpy);
+
+   if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+      xGLXQueryContextReq *req;
+
+      GetReq(GLXQueryContext, req);
+
+      req->reqType = opcode;
+      req->glxCode = X_GLXQueryContext;
+      req->context = (unsigned int) (ctx->xid);
+   }
+   else {
+      xGLXVendorPrivateReq *vpreq;
+      xGLXQueryContextInfoEXTReq *req;
+
+      GetReqExtra(GLXVendorPrivate,
+                  sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
+                  vpreq);
+      req = (xGLXQueryContextInfoEXTReq *) vpreq;
+      req->reqType = opcode;
+      req->glxCode = X_GLXVendorPrivateWithReply;
+      req->vendorCode = X_GLXvop_QueryContextInfoEXT;
+      req->context = (unsigned int) (ctx->xid);
+   }
+
+   _XReply(dpy, (xReply *) & reply, 0, False);
+
+   numValues = reply.n;
+   if (numValues == 0)
+      retval = Success;
+   else if (numValues > __GLX_MAX_CONTEXT_PROPS)
+      retval = 0;
+   else {
+      int *propList, *pProp;
+      int nPropListBytes;
+      int i;
+
+      nPropListBytes = numValues << 3;
+      propList = (int *) Xmalloc(nPropListBytes);
+      if (NULL == propList) {
+         retval = 0;
+      }
+      else {
+         _XRead(dpy, (char *) propList, nPropListBytes);
+         pProp = propList;
+         for (i = 0; i < numValues; i++) {
+            switch (*pProp++) {
+            case GLX_SHARE_CONTEXT_EXT:
+               ctx->share_xid = *pProp++;
+               break;
+            case GLX_VISUAL_ID_EXT:
+               ctx->mode =
+                  _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
+               break;
+            case GLX_SCREEN:
+               ctx->screen = *pProp++;
+               break;
+            case GLX_FBCONFIG_ID:
+               ctx->mode =
+                  _gl_context_modes_find_fbconfig(ctx->psc->configs,
+                                                  *pProp++);
+               break;
+            case GLX_RENDER_TYPE:
+               ctx->renderType = *pProp++;
+               break;
+            default:
+               pProp++;
+               continue;
+            }
+         }
+         Xfree((char *) propList);
+         retval = Success;
+      }
+   }
+   UnlockDisplay(dpy);
+   SyncHandle();
+   return retval;
+}
+
+PUBLIC int
+glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
+{
+   int retVal;
+
+   /* get the information from the server if we don't have it already */
+#ifdef GLX_DIRECT_RENDERING
+   if (!ctx->driContext && (ctx->mode == NULL)) {
+#else
+   if (ctx->mode == NULL) {
+#endif
+      retVal = __glXQueryContextInfo(dpy, ctx);
+      if (Success != retVal)
+         return retVal;
+   }
+   switch (attribute) {
+   case GLX_SHARE_CONTEXT_EXT:
+      *value = (int) (ctx->share_xid);
+      break;
+   case GLX_VISUAL_ID_EXT:
+      *value = ctx->mode ? ctx->mode->visualID : None;
+      break;
+   case GLX_SCREEN:
+      *value = (int) (ctx->screen);
+      break;
+   case GLX_FBCONFIG_ID:
+      *value = ctx->mode ? ctx->mode->fbconfigID : None;
+      break;
+   case GLX_RENDER_TYPE:
+      *value = (int) (ctx->renderType);
+      break;
+   default:
+      return GLX_BAD_ATTRIBUTE;
+   }
+   return Success;
+}
+
+PUBLIC
+GLX_ALIAS(int, glXQueryContextInfoEXT,
+          (Display * dpy, GLXContext ctx, int attribute, int *value),
+          (dpy, ctx, attribute, value), glXQueryContext)
+
+PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
+{
+   return ctx->xid;
+}
+
+PUBLIC GLXContext
+glXImportContextEXT(Display * dpy, GLXContextID contextID)
+{
+   GLXContext ctx;
+
+   if (contextID == None) {
+      return NULL;
+   }
+   if (__glXIsDirect(dpy, contextID)) {
+      return NULL;
+   }
+
+   ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
+   if (NULL != ctx) {
+      if (Success != __glXQueryContextInfo(dpy, ctx)) {
+         return NULL;
+      }
+   }
+   return ctx;
+}
+
+PUBLIC void
+glXFreeContextEXT(Display * dpy, GLXContext ctx)
+{
+   DestroyContext(dpy, ctx);
+}
+
+
+
+/*
+ * GLX 1.3 functions - these are just stubs for now!
+ */
+
+PUBLIC GLXFBConfig *
+glXChooseFBConfig(Display * dpy, int screen,
+                  const int *attribList, int *nitems)
+{
+   __GLcontextModes **config_list;
+   int list_size;
+
+
+   config_list = (__GLcontextModes **)
+      glXGetFBConfigs(dpy, screen, &list_size);
+
+   if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
+      list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
+      if (list_size == 0) {
+         XFree(config_list);
+         config_list = NULL;
+      }
+   }
+
+   *nitems = list_size;
+   return (GLXFBConfig *) config_list;
+}
+
+
+PUBLIC GLXContext
+glXCreateNewContext(Display * dpy, GLXFBConfig config,
+                    int renderType, GLXContext shareList, Bool allowDirect)
+{
+   return CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
+                        allowDirect, None, True, renderType);
+}
+
+
+PUBLIC GLXDrawable
+glXGetCurrentReadDrawable(void)
+{
+   GLXContext gc = __glXGetCurrentContext();
+   return gc->currentReadable;
+}
+
+
+PUBLIC GLXFBConfig *
+glXGetFBConfigs(Display * dpy, int screen, int *nelements)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   __GLcontextModes **config = NULL;
+   int i;
+
+   *nelements = 0;
+   if (priv && (priv->screenConfigs != NULL)
+       && (screen >= 0) && (screen <= ScreenCount(dpy))
+       && (priv->screenConfigs[screen].configs != NULL)
+       && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE)) {
+      unsigned num_configs = 0;
+      __GLcontextModes *modes;
+
+
+      for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+           modes = modes->next) {
+         if (modes->fbconfigID != GLX_DONT_CARE) {
+            num_configs++;
+         }
+      }
+
+      config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
+                                             * num_configs);
+      if (config != NULL) {
+         *nelements = num_configs;
+         i = 0;
+         for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+              modes = modes->next) {
+            if (modes->fbconfigID != GLX_DONT_CARE) {
+               config[i] = modes;
+               i++;
+            }
+         }
+      }
+   }
+   return (GLXFBConfig *) config;
+}
+
+
+PUBLIC int
+glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
+                     int attribute, int *value)
+{
+   __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
+
+   return (modes != NULL)
+      ? _gl_get_context_mode_data(modes, attribute, value)
+      : GLXBadFBConfig;
+}
+
+
+PUBLIC XVisualInfo *
+glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
+{
+   XVisualInfo visualTemplate;
+   __GLcontextModes *fbconfig = (__GLcontextModes *) config;
+   int count;
+
+   /*
+    ** Get a list of all visuals, return if list is empty
+    */
+   visualTemplate.visualid = fbconfig->visualID;
+   return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
+}
+
+
+/*
+** GLX_SGI_swap_control
+*/
+static int
+__glXSwapIntervalSGI(int interval)
+{
+   xGLXVendorPrivateReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc;
+   Display *dpy;
+   CARD32 *interval_ptr;
+   CARD8 opcode;
+
+   if (gc == NULL) {
+      return GLX_BAD_CONTEXT;
+   }
+
+   if (interval <= 0) {
+      return GLX_BAD_VALUE;
+   }
+
+#ifdef __DRI_SWAP_CONTROL
+   if (gc->driContext) {
+      __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
+                                                           gc->screen );
+      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
+                                                 gc->currentDrawable,
+                                                 NULL);
+      if (psc->swapControl != NULL && pdraw != NULL) {
+        psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
+        return 0;
+      }
+      else if (pdraw == NULL) {
+        return GLX_BAD_CONTEXT;
+      }
+   }
+#endif
+   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
+
+   if (gc->driContext && psc->driScreen && psc->driScreen->setSwapInterval) {
+      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
+                                                 gc->currentDrawable,
+                                                 NULL);
+      psc->driScreen->setSwapInterval(pdraw, interval);
+      return 0;
+   }
+
+   dpy = gc->currentDpy;
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode) {
+      return 0;
+   }
+
+   /* Send the glXSwapIntervalSGI request */
+   LockDisplay(dpy);
+   GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXVendorPrivate;
+   req->vendorCode = X_GLXvop_SwapIntervalSGI;
+   req->contextTag = gc->currentContextTag;
+
+   interval_ptr = (CARD32 *) (req + 1);
+   *interval_ptr = interval;
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+   XFlush(dpy);
+
+   return 0;
+}
+
+
+/*
+** GLX_MESA_swap_control
+*/
+static int
+__glXSwapIntervalMESA(unsigned int interval)
+{
+   GLXContext gc = __glXGetCurrentContext();
+
+   if (interval < 0) {
+      return GLX_BAD_VALUE;
+   }
+
+#ifdef __DRI_SWAP_CONTROL
+   if (gc != NULL && gc->driContext) {
+      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+                                                          gc->screen);
+
+      if ((psc != NULL) && (psc->driScreen != NULL)) {
+         __GLXDRIdrawable *pdraw =
+            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+         if (psc->swapControl != NULL && pdraw != NULL) {
+            psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
+            return 0;
+         }
+      }
+   }
+#endif
+
+   if (gc != NULL && gc->driContext) {
+      __GLXscreenConfigs *psc;
+
+      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
+      if (psc->driScreen && psc->driScreen->setSwapInterval) {
+         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
+                                                    gc->currentDrawable, NULL);
+        psc->driScreen->setSwapInterval(pdraw, interval);
+        return 0;
+      }
+   }
+
+   return GLX_BAD_CONTEXT;
+}
+
+
+static int
+__glXGetSwapIntervalMESA(void)
+{
+#ifdef __DRI_SWAP_CONTROL
+   GLXContext gc = __glXGetCurrentContext();
+
+   if (gc != NULL && gc->driContext) {
+      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+                                                          gc->screen);
+
+      if ((psc != NULL) && (psc->driScreen != NULL)) {
+         __GLXDRIdrawable *pdraw =
+            GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+         if (psc->swapControl != NULL && pdraw != NULL) {
+            return psc->swapControl->getSwapInterval(pdraw->driDrawable);
+         }
+      }
+   }
+#endif
+   if (gc != NULL && gc->driContext) {
+      __GLXscreenConfigs *psc;
+
+      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
+      if (psc->driScreen && psc->driScreen->getSwapInterval) {
+         __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
+                                                    gc->currentDrawable, NULL);
+        return psc->driScreen->getSwapInterval(pdraw);
+      }
+   }
+
+   return 0;
+}
+
+
+/*
+** GLX_MESA_swap_frame_usage
+*/
+
+static GLint
+__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
+{
+   int status = GLX_BAD_CONTEXT;
+#ifdef __DRI_FRAME_TRACKING
+   int screen = 0;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+
+   if (pdraw != NULL && psc->frameTracking != NULL)
+      status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
+#else
+   (void) dpy;
+   (void) drawable;
+#endif
+   return status;
+}
+
+
+static GLint
+__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
+{
+   int status = GLX_BAD_CONTEXT;
+#ifdef __DRI_FRAME_TRACKING
+   int screen = 0;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
+
+   if (pdraw != NULL && psc->frameTracking != NULL)
+      status = psc->frameTracking->frameTracking(pdraw->driDrawable,
+                                                 GL_FALSE);
+#else
+   (void) dpy;
+   (void) drawable;
+#endif
+   return status;
+}
+
+
+static GLint
+__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
+{
+   int status = GLX_BAD_CONTEXT;
+#ifdef __DRI_FRAME_TRACKING
+   int screen = 0;
+   __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+
+   if (pdraw != NULL && psc->frameTracking != NULL) {
+      int64_t sbc, missedFrames;
+      float lastMissedUsage;
+
+      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
+                                                      &sbc,
+                                                      &missedFrames,
+                                                      &lastMissedUsage,
+                                                      usage);
+   }
+#else
+   (void) dpy;
+   (void) drawable;
+   (void) usage;
+#endif
+   return status;
+}
+
+
+static GLint
+__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
+                            int64_t * sbc, int64_t * missedFrames,
+                            GLfloat * lastMissedUsage)
+{
+   int status = GLX_BAD_CONTEXT;
+#ifdef __DRI_FRAME_TRACKING
+   int screen = 0;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+
+   if (pdraw != NULL && psc->frameTracking != NULL) {
+      float usage;
+
+      status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
+                                                      sbc, missedFrames,
+                                                      lastMissedUsage,
+                                                      &usage);
+   }
+#else
+   (void) dpy;
+   (void) drawable;
+   (void) sbc;
+   (void) missedFrames;
+   (void) lastMissedUsage;
+#endif
+   return status;
+}
+
+
+/*
+** GLX_SGI_video_sync
+*/
+static int
+__glXGetVideoSyncSGI(unsigned int *count)
+{
+   int64_t ust, msc, sbc;
+   int ret;
+   GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc;
+   __GLXDRIdrawable *pdraw;
+
+   if (!gc || !gc->driContext)
+      return GLX_BAD_CONTEXT;
+
+   psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen);
+   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+
+   /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
+    * FIXME: there should be a GLX encoding for this call.  I can find no
+    * FIXME: documentation for the GLX encoding.
+    */
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+   if ( psc->msc && psc->driScreen ) {
+      ret = (*psc->msc->getDrawableMSC)(psc->__driScreen,
+                                       pdraw->driDrawable, &msc);
+      *count = (unsigned) msc;
+
+      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+   }
+#endif
+   if (psc->driScreen && psc->driScreen->getDrawableMSC) {
+      ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
+      *count = (unsigned) msc;
+      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
+   }
+
+   return GLX_BAD_CONTEXT;
+}
+
+static int
+__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+   GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc;
+   __GLXDRIdrawable *pdraw;
+   int64_t ust, msc, sbc;
+   int ret;
+
+   if (divisor <= 0 || remainder < 0)
+      return GLX_BAD_VALUE;
+
+   if (!gc || !gc->driContext)
+      return GLX_BAD_CONTEXT;
+
+   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
+   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+   if (psc->msc != NULL && psc->driScreen ) {
+      ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0,
+                                   divisor, remainder, &msc, &sbc);
+      *count = (unsigned) msc;
+      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+   }
+#endif
+   if (psc->driScreen && psc->driScreen->waitForMSC) {
+      ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
+                                      &sbc);
+      *count = (unsigned) msc;
+      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
+   }
+
+   return GLX_BAD_CONTEXT;
+}
+
+
+/*
+** GLX_SGIX_fbconfig
+** Many of these functions are aliased to GLX 1.3 entry points in the 
+** GLX_functions table.
+*/
+
+PUBLIC
+GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
+          (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
+          (dpy, config, attribute, value), glXGetFBConfigAttrib)
+
+PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
+                 (Display * dpy, int screen, int *attrib_list,
+                  int *nelements), (dpy, screen, attrib_list, nelements),
+                 glXChooseFBConfig)
+
+PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
+                 (Display * dpy, GLXFBConfigSGIX config),
+                 (dpy, config), glXGetVisualFromFBConfig)
+
+PUBLIC GLXPixmap
+glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
+                                 GLXFBConfigSGIX config,
+                                 Pixmap pixmap)
+{
+   xGLXVendorPrivateWithReplyReq *vpreq;
+   xGLXCreateGLXPixmapWithConfigSGIXReq *req;
+   GLXPixmap xid = None;
+   CARD8 opcode;
+   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
+   __GLXscreenConfigs *psc;
+
+
+   if ((dpy == NULL) || (config == NULL)) {
+      return None;
+   }
+
+   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
+   if ((psc != NULL)
+       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
+      opcode = __glXSetupForCommand(dpy);
+      if (!opcode) {
+         return None;
+      }
+
+      /* Send the glXCreateGLXPixmapWithConfigSGIX request */
+      LockDisplay(dpy);
+      GetReqExtra(GLXVendorPrivateWithReply,
+                  sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
+                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
+      req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
+      req->reqType = opcode;
+      req->glxCode = X_GLXVendorPrivateWithReply;
+      req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
+      req->screen = fbconfig->screen;
+      req->fbconfig = fbconfig->fbconfigID;
+      req->pixmap = pixmap;
+      req->glxpixmap = xid = XAllocID(dpy);
+      UnlockDisplay(dpy);
+      SyncHandle();
+   }
+
+   return xid;
+}
+
+PUBLIC GLXContext
+glXCreateContextWithConfigSGIX(Display * dpy,
+                               GLXFBConfigSGIX config, int renderType,
+                               GLXContext shareList, Bool allowDirect)
+{
+   GLXContext gc = NULL;
+   const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
+   __GLXscreenConfigs *psc;
+
+
+   if ((dpy == NULL) || (config == NULL)) {
+      return None;
+   }
+
+   psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
+   if ((psc != NULL)
+       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
+      gc = CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
+                         allowDirect, None, False, renderType);
+   }
+
+   return gc;
+}
+
+
+PUBLIC GLXFBConfigSGIX
+glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
+{
+   __GLXdisplayPrivate *priv;
+   __GLXscreenConfigs *psc = NULL;
+
+   if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
+       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
+       && (psc->configs->fbconfigID != GLX_DONT_CARE)) {
+      return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
+                                                             vis->visualid);
+   }
+
+   return NULL;
+}
+
+
+/*
+** GLX_SGIX_swap_group
+*/
+static void
+__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
+                       GLXDrawable member)
+{
+   (void) dpy;
+   (void) drawable;
+   (void) member;
+}
+
+
+/*
+** GLX_SGIX_swap_barrier
+*/
+static void
+__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
+{
+   (void) dpy;
+   (void) drawable;
+   (void) barrier;
+}
+
+static Bool
+__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
+{
+   (void) dpy;
+   (void) screen;
+   (void) max;
+   return False;
+}
+
+
+/*
+** GLX_OML_sync_control
+*/
+static Bool
+__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
+                      int64_t * ust, int64_t * msc, int64_t * sbc)
+{
+   __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
+   int i, ret;
+   __GLXDRIdrawable *pdraw;
+   __GLXscreenConfigs *psc;
+
+   if (!priv)
+      return False;
+
+   pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
+   psc = &priv->screenConfigs[i];
+
+#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
+   if (pdraw && psc->sbc && psc->sbc)
+      return ( (pdraw && psc->sbc && psc->msc)
+              && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0)
+              && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0)
+              && (__glXGetUST(ust) == 0) );
+#endif
+   if (pdraw && psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
+      ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
+      return ret;
+   }
+
+   return False;
+}
+
+#ifdef GLX_DIRECT_RENDERING
+_X_HIDDEN GLboolean
+__driGetMscRateOML(__DRIdrawable * draw,
+                   int32_t * numerator, int32_t * denominator, void *private)
+{
+#ifdef XF86VIDMODE
+   __GLXscreenConfigs *psc;
+   XF86VidModeModeLine mode_line;
+   int dot_clock;
+   int i;
+   __GLXDRIdrawable *glxDraw = private;
+
+   psc = glxDraw->psc;
+   if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
+       XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
+      unsigned n = dot_clock * 1000;
+      unsigned d = mode_line.vtotal * mode_line.htotal;
+
+# define V_INTERLACE 0x010
+# define V_DBLSCAN   0x020
+
+      if (mode_line.flags & V_INTERLACE)
+         n *= 2;
+      else if (mode_line.flags & V_DBLSCAN)
+         d *= 2;
+
+      /* The OML_sync_control spec requires that if the refresh rate is a
+       * whole number, that the returned numerator be equal to the refresh
+       * rate and the denominator be 1.
+       */
+
+      if (n % d == 0) {
+         n /= d;
+         d = 1;
+      }
+      else {
+         static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
+
+         /* This is a poor man's way to reduce a fraction.  It's far from
+          * perfect, but it will work well enough for this situation.
+          */
+
+         for (i = 0; f[i] != 0; i++) {
+            while (n % f[i] == 0 && d % f[i] == 0) {
+               d /= f[i];
+               n /= f[i];
+            }
+         }
+      }
+
+      *numerator = n;
+      *denominator = d;
+
+      return True;
+   }
+   else
+      return False;
+#else
+   return False;
+#endif
+}
+#endif
+
+/**
+ * Determine the refresh rate of the specified drawable and display.
+ *
+ * \param dpy          Display whose refresh rate is to be determined.
+ * \param drawable     Drawable whose refresh rate is to be determined.
+ * \param numerator    Numerator of the refresh rate.
+ * \param demoninator  Denominator of the refresh rate.
+ * \return  If the refresh rate for the specified display and drawable could
+ *          be calculated, True is returned.  Otherwise False is returned.
+ *
+ * \note This function is implemented entirely client-side.  A lot of other
+ *       functionality is required to export GLX_OML_sync_control, so on
+ *       XFree86 this function can be called for direct-rendering contexts
+ *       when GLX_OML_sync_control appears in the client extension string.
+ */
+
+_X_HIDDEN GLboolean
+__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
+                   int32_t * numerator, int32_t * denominator)
+{
+#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
+   __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+   if (draw == NULL)
+      return False;
+
+   return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
+#else
+   (void) dpy;
+   (void) drawable;
+   (void) numerator;
+   (void) denominator;
+#endif
+   return False;
+}
+
+
+static int64_t
+__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
+                       int64_t target_msc, int64_t divisor, int64_t remainder)
+{
+   GLXContext gc = __glXGetCurrentContext();
+   int screen;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+
+   if (!pdraw || !gc->driContext) /* no GLX for this */
+      return -1;
+
+   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
+    * error", but it also says "It [glXSwapBuffersMscOML] will return a value
+    * of -1 if the function failed because of errors detected in the input
+    * parameters"
+    */
+   if (divisor < 0 || remainder < 0 || target_msc < 0)
+      return -1;
+   if (divisor > 0 && remainder >= divisor)
+      return -1;
+
+#ifdef __DRI_SWAP_BUFFER_COUNTER
+   if (psc->counters != NULL)
+      return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc,
+                                        divisor, remainder);
+#endif
+
+#ifdef GLX_DIRECT_RENDERING
+   if (psc->driScreen && psc->driScreen->swapBuffers)
+      return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
+                                           remainder);
+#endif
+
+   return -1;
+}
+
+
+static Bool
+__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
+                   int64_t target_msc, int64_t divisor,
+                   int64_t remainder, int64_t * ust,
+                   int64_t * msc, int64_t * sbc)
+{
+   int screen;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
+   int ret;
+
+   fprintf(stderr, "waitmsc: %lld, %lld, %lld\n", target_msc, divisor,
+          remainder);
+
+   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
+    * error", but the return type in the spec is Bool.
+    */
+   if (divisor < 0 || remainder < 0 || target_msc < 0)
+      return False;
+   if (divisor > 0 && remainder >= divisor)
+      return False;
+
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+   if (pdraw != NULL && psc->msc != NULL) {
+      fprintf(stderr, "dri1 msc\n");
+      ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
+                                     divisor, remainder, msc, sbc);
+
+      /* __glXGetUST returns zero on success and non-zero on failure.
+       * This function returns True on success and False on failure.
+       */
+      return ((ret == 0) && (__glXGetUST(ust) == 0));
+   }
+#endif
+   if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
+      ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder,
+                                      ust, msc, sbc);
+      return ret;
+   }
+
+   fprintf(stderr, "no drawable??\n");
+   return False;
+}
+
+
+static Bool
+__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
+                   int64_t target_sbc, int64_t * ust,
+                   int64_t * msc, int64_t * sbc)
+{
+   int screen;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+   int ret;
+
+   /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
+    * error", but the return type in the spec is Bool.
+    */
+   if (target_sbc < 0)
+      return False;
+#ifdef __DRI_SWAP_BUFFER_COUNTER
+   if (pdraw != NULL && psc->sbc != NULL) {
+      ret =
+         (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
+
+      /* __glXGetUST returns zero on success and non-zero on failure.
+       * This function returns True on success and False on failure.
+       */
+      return ((ret == 0) && (__glXGetUST(ust) == 0));
+   }
+#endif
+   if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
+      ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc);
+      return ret;
+   }
+   return False;
+}
+
+
+/**
+ * GLX_MESA_allocate_memory
+ */
+/*@{*/
+
+PUBLIC void *
+glXAllocateMemoryMESA(Display * dpy, int scrn,
+                      size_t size, float readFreq,
+                      float writeFreq, float priority)
+{
+#ifdef __DRI_ALLOCATE
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
+
+   if (psc && psc->allocate)
+      return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
+                                               readFreq, writeFreq, priority);
+
+#else
+   (void) dpy;
+   (void) scrn;
+   (void) size;
+   (void) readFreq;
+   (void) writeFreq;
+   (void) priority;
+#endif /* __DRI_ALLOCATE */
+
+   return NULL;
+}
+
+
+PUBLIC void
+glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
+{
+#ifdef __DRI_ALLOCATE
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
+
+   if (psc && psc->allocate)
+      (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
+
+#else
+   (void) dpy;
+   (void) scrn;
+   (void) pointer;
+#endif /* __DRI_ALLOCATE */
+}
+
+
+PUBLIC GLuint
+glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
+{
+#ifdef __DRI_ALLOCATE
+   __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
+
+   if (psc && psc->allocate)
+      return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
+
+#else
+   (void) dpy;
+   (void) scrn;
+   (void) pointer;
+#endif /* GLX_DIRECT_RENDERING */
+
+   return ~0L;
+}
+
+/*@}*/
+
+
+/**
+ * Mesa extension stubs.  These will help reduce portability problems.
+ */
+/*@{*/
+
+/**
+ * Release all buffers associated with the specified GLX drawable.
+ *
+ * \todo
+ * This function was intended for stand-alone Mesa.  The issue there is that
+ * the library doesn't get any notification when a window is closed.  In
+ * DRI there is a similar but slightly different issue.  When GLX 1.3 is
+ * supported, there are 3 different functions to destroy a drawable.  It
+ * should be possible to create GLX protocol (or have it determine which
+ * protocol to use based on the type of the drawable) to have one function
+ * do the work of 3.  For the direct-rendering case, this function could
+ * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
+ * This would reduce the frequency with which \c __driGarbageCollectDrawables
+ * would need to be used.  This really should be done as part of the new DRI
+ * interface work.
+ *
+ * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
+ *     __driGarbageCollectDrawables
+ *     glXDestroyGLXPixmap
+ *     glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
+ *     glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
+ */
+static Bool
+__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
+{
+   (void) dpy;
+   (void) d;
+   return False;
+}
+
+
+PUBLIC GLXPixmap
+glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
+                       Pixmap pixmap, Colormap cmap)
+{
+   (void) dpy;
+   (void) visual;
+   (void) pixmap;
+   (void) cmap;
+   return 0;
+}
+
+/*@}*/
+
+
+/**
+ * GLX_MESA_copy_sub_buffer
+ */
+#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
+static void
+__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
+                       int x, int y, int width, int height)
+{
+   xGLXVendorPrivateReq *req;
+   GLXContext gc;
+   GLXContextTag tag;
+   CARD32 *drawable_ptr;
+   INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
+   CARD8 opcode;
+
+#ifdef __DRI_COPY_SUB_BUFFER
+   int screen;
+   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+   if (pdraw != NULL) {
+      __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+      if (psc->driScreen->copySubBuffer != NULL) {
+         glFlush();
+         (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height);
+      }
+
+      return;
+   }
+#endif
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   /*
+    ** The calling thread may or may not have a current context.  If it
+    ** does, send the context tag so the server can do a flush.
+    */
+   gc = __glXGetCurrentContext();
+   if ((gc != NULL) && (dpy == gc->currentDpy) &&
+       ((drawable == gc->currentDrawable) ||
+        (drawable == gc->currentReadable))) {
+      tag = gc->currentContextTag;
+   }
+   else {
+      tag = 0;
+   }
+
+   LockDisplay(dpy);
+   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXVendorPrivate;
+   req->vendorCode = X_GLXvop_CopySubBufferMESA;
+   req->contextTag = tag;
+
+   drawable_ptr = (CARD32 *) (req + 1);
+   x_ptr = (INT32 *) (drawable_ptr + 1);
+   y_ptr = (INT32 *) (drawable_ptr + 2);
+   w_ptr = (INT32 *) (drawable_ptr + 3);
+   h_ptr = (INT32 *) (drawable_ptr + 4);
+
+   *drawable_ptr = drawable;
+   *x_ptr = x;
+   *y_ptr = y;
+   *w_ptr = width;
+   *h_ptr = height;
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+
+/**
+ * GLX_EXT_texture_from_pixmap
+ */
+/*@{*/
+static void
+__glXBindTexImageEXT(Display * dpy,
+                     GLXDrawable drawable, int buffer, const int *attrib_list)
+{
+   xGLXVendorPrivateReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   CARD32 *drawable_ptr;
+   INT32 *buffer_ptr;
+   CARD32 *num_attrib_ptr;
+   CARD32 *attrib_ptr;
+   CARD8 opcode;
+   unsigned int i;
+
+   if (gc == NULL)
+      return;
+
+   i = 0;
+   if (attrib_list) {
+      while (attrib_list[i * 2] != None)
+         i++;
+   }
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext) {
+      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+      if (pdraw != NULL) {
+         if (pdraw->psc->texBuffer->base.version >= 2 &&
+             pdraw->psc->texBuffer->setTexBuffer2 != NULL) {
+            (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext,
+                                                     pdraw->textureTarget,
+                                                     pdraw->textureFormat,
+                                                     pdraw->driDrawable);
+         }
+         else {
+            (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext,
+                                                    pdraw->textureTarget,
+                                                    pdraw->driDrawable);
+         }
+      }
+      return;
+   }
+#endif
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   LockDisplay(dpy);
+   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXVendorPrivate;
+   req->vendorCode = X_GLXvop_BindTexImageEXT;
+   req->contextTag = gc->currentContextTag;
+
+   drawable_ptr = (CARD32 *) (req + 1);
+   buffer_ptr = (INT32 *) (drawable_ptr + 1);
+   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
+   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
+
+   *drawable_ptr = drawable;
+   *buffer_ptr = buffer;
+   *num_attrib_ptr = (CARD32) i;
+
+   i = 0;
+   if (attrib_list) {
+      while (attrib_list[i * 2] != None) {
+         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
+         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
+         i++;
+      }
+   }
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+static void
+__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
+{
+   xGLXVendorPrivateReq *req;
+   GLXContext gc = __glXGetCurrentContext();
+   CARD32 *drawable_ptr;
+   INT32 *buffer_ptr;
+   CARD8 opcode;
+
+   if (gc == NULL)
+      return;
+
+#ifdef GLX_DIRECT_RENDERING
+   if (gc->driContext)
+      return;
+#endif
+
+   opcode = __glXSetupForCommand(dpy);
+   if (!opcode)
+      return;
+
+   LockDisplay(dpy);
+   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
+   req->reqType = opcode;
+   req->glxCode = X_GLXVendorPrivate;
+   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
+   req->contextTag = gc->currentContextTag;
+
+   drawable_ptr = (CARD32 *) (req + 1);
+   buffer_ptr = (INT32 *) (drawable_ptr + 1);
+
+   *drawable_ptr = drawable;
+   *buffer_ptr = buffer;
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+}
+
+/*@}*/
+
+/**
+ * \c strdup is actually not a standard ANSI C or POSIX routine.
+ * Irix will not define it if ANSI mode is in effect.
+ *
+ * \sa strdup
+ */
+_X_HIDDEN char *
+__glXstrdup(const char *str)
+{
+   char *copy;
+   copy = (char *) Xmalloc(strlen(str) + 1);
+   if (!copy)
+      return NULL;
+   strcpy(copy, str);
+   return copy;
+}
+
+/*
+** glXGetProcAddress support
+*/
+
+struct name_address_pair
+{
+   const char *Name;
+   GLvoid *Address;
+};
+
+#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
+#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
+
+static const struct name_address_pair GLX_functions[] = {
+   /*** GLX_VERSION_1_0 ***/
+   GLX_FUNCTION(glXChooseVisual),
+   GLX_FUNCTION(glXCopyContext),
+   GLX_FUNCTION(glXCreateContext),
+   GLX_FUNCTION(glXCreateGLXPixmap),
+   GLX_FUNCTION(glXDestroyContext),
+   GLX_FUNCTION(glXDestroyGLXPixmap),
+   GLX_FUNCTION(glXGetConfig),
+   GLX_FUNCTION(glXGetCurrentContext),
+   GLX_FUNCTION(glXGetCurrentDrawable),
+   GLX_FUNCTION(glXIsDirect),
+   GLX_FUNCTION(glXMakeCurrent),
+   GLX_FUNCTION(glXQueryExtension),
+   GLX_FUNCTION(glXQueryVersion),
+   GLX_FUNCTION(glXSwapBuffers),
+   GLX_FUNCTION(glXUseXFont),
+   GLX_FUNCTION(glXWaitGL),
+   GLX_FUNCTION(glXWaitX),
+
+   /*** GLX_VERSION_1_1 ***/
+   GLX_FUNCTION(glXGetClientString),
+   GLX_FUNCTION(glXQueryExtensionsString),
+   GLX_FUNCTION(glXQueryServerString),
+
+   /*** GLX_VERSION_1_2 ***/
+   GLX_FUNCTION(glXGetCurrentDisplay),
+
+   /*** GLX_VERSION_1_3 ***/
+   GLX_FUNCTION(glXChooseFBConfig),
+   GLX_FUNCTION(glXCreateNewContext),
+   GLX_FUNCTION(glXCreatePbuffer),
+   GLX_FUNCTION(glXCreatePixmap),
+   GLX_FUNCTION(glXCreateWindow),
+   GLX_FUNCTION(glXDestroyPbuffer),
+   GLX_FUNCTION(glXDestroyPixmap),
+   GLX_FUNCTION(glXDestroyWindow),
+   GLX_FUNCTION(glXGetCurrentReadDrawable),
+   GLX_FUNCTION(glXGetFBConfigAttrib),
+   GLX_FUNCTION(glXGetFBConfigs),
+   GLX_FUNCTION(glXGetSelectedEvent),
+   GLX_FUNCTION(glXGetVisualFromFBConfig),
+   GLX_FUNCTION(glXMakeContextCurrent),
+   GLX_FUNCTION(glXQueryContext),
+   GLX_FUNCTION(glXQueryDrawable),
+   GLX_FUNCTION(glXSelectEvent),
+
+   /*** GLX_SGI_swap_control ***/
+   GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
+
+   /*** GLX_SGI_video_sync ***/
+   GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
+   GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
+
+   /*** GLX_SGI_make_current_read ***/
+   GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
+   GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
+
+   /*** GLX_EXT_import_context ***/
+   GLX_FUNCTION(glXFreeContextEXT),
+   GLX_FUNCTION(glXGetContextIDEXT),
+   GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
+   GLX_FUNCTION(glXImportContextEXT),
+   GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
+
+   /*** GLX_SGIX_fbconfig ***/
+   GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
+   GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
+   GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
+   GLX_FUNCTION(glXCreateContextWithConfigSGIX),
+   GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
+   GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
+
+   /*** GLX_SGIX_pbuffer ***/
+   GLX_FUNCTION(glXCreateGLXPbufferSGIX),
+   GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
+   GLX_FUNCTION(glXQueryGLXPbufferSGIX),
+   GLX_FUNCTION(glXSelectEventSGIX),
+   GLX_FUNCTION(glXGetSelectedEventSGIX),
+
+   /*** GLX_SGIX_swap_group ***/
+   GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX),
+
+   /*** GLX_SGIX_swap_barrier ***/
+   GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX),
+   GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX),
+
+   /*** GLX_MESA_allocate_memory ***/
+   GLX_FUNCTION(glXAllocateMemoryMESA),
+   GLX_FUNCTION(glXFreeMemoryMESA),
+   GLX_FUNCTION(glXGetMemoryOffsetMESA),
+
+   /*** GLX_MESA_copy_sub_buffer ***/
+   GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
+
+   /*** GLX_MESA_pixmap_colormap ***/
+   GLX_FUNCTION(glXCreateGLXPixmapMESA),
+
+   /*** GLX_MESA_release_buffers ***/
+   GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
+
+   /*** GLX_MESA_swap_control ***/
+   GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
+   GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
+
+   /*** GLX_MESA_swap_frame_usage ***/
+   GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA),
+   GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA),
+   GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA),
+   GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA),
+
+   /*** GLX_ARB_get_proc_address ***/
+   GLX_FUNCTION(glXGetProcAddressARB),
+
+   /*** GLX 1.4 ***/
+   GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
+
+   /*** GLX_OML_sync_control ***/
+   GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
+   GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
+   GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
+   GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
+   GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
+
+   /*** GLX_EXT_texture_from_pixmap ***/
+   GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
+   GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
+
+#ifdef GLX_DIRECT_RENDERING
+   /*** DRI configuration ***/
+   GLX_FUNCTION(glXGetScreenDriver),
+   GLX_FUNCTION(glXGetDriverConfig),
+#endif
+
+   {NULL, NULL}                 /* end of list */
+};
+
+
+static const GLvoid *
+get_glx_proc_address(const char *funcName)
+{
+   GLuint i;
+
+   /* try static functions */
+   for (i = 0; GLX_functions[i].Name; i++) {
+      if (strcmp(GLX_functions[i].Name, funcName) == 0)
+         return GLX_functions[i].Address;
+   }
+
+   return NULL;
+}
+
+
+/**
+ * Get the address of a named GL function.  This is the pre-GLX 1.4 name for
+ * \c glXGetProcAddress.
+ *
+ * \param procName  Name of a GL or GLX function.
+ * \returns         A pointer to the named function
+ *
+ * \sa glXGetProcAddress
+ */
+PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
+{
+   typedef void (*gl_function) (void);
+   gl_function f;
+
+
+   /* Search the table of GLX and internal functions first.  If that
+    * fails and the supplied name could be a valid core GL name, try
+    * searching the core GL function table.  This check is done to prevent
+    * DRI based drivers from searching the core GL function table for
+    * internal API functions.
+    */
+
+   f = (gl_function) get_glx_proc_address((const char *) procName);
+   if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
+       && (procName[2] != 'X')) {
+      f = (gl_function) _glapi_get_proc_address((const char *) procName);
+   }
+
+   return f;
+}
+
+/**
+ * Get the address of a named GL function.  This is the GLX 1.4 name for
+ * \c glXGetProcAddressARB.
+ *
+ * \param procName  Name of a GL or GLX function.
+ * \returns         A pointer to the named function
+ *
+ * \sa glXGetProcAddressARB
+ */
+PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
+#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
+   __attribute__ ((alias("glXGetProcAddressARB")));
+#else
+{
+   return glXGetProcAddressARB(procName);
+}
+#endif /* __GNUC__ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+/**
+ * Get the unadjusted system time (UST).  Currently, the UST is measured in
+ * microseconds since Epoc.  The actual resolution of the UST may vary from
+ * system to system, and the units may vary from release to release.
+ * Drivers should not call this function directly.  They should instead use
+ * \c glXGetProcAddress to obtain a pointer to the function.
+ *
+ * \param ust Location to store the 64-bit UST
+ * \returns Zero on success or a negative errno value on failure.
+ *
+ * \sa glXGetProcAddress, PFNGLXGETUSTPROC
+ *
+ * \since Internal API version 20030317.
+ */
+_X_HIDDEN int
+__glXGetUST(int64_t * ust)
+{
+   struct timeval tv;
+
+   if (ust == NULL) {
+      return -EFAULT;
+   }
+
+   if (gettimeofday(&tv, NULL) == 0) {
+      ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
+      return 0;
+   }
+   else {
+      return -errno;
+   }
+}
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c
new file mode 100644 (file)
index 0000000..c28360b
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/**
+ * \file glxcurrent.c
+ * Client-side GLX interface for current context management.
+ */
+
+#include "glxclient.h"
+#include "glapi.h"
+#include "indirect_init.h"
+
+/*
+** We setup some dummy structures here so that the API can be used
+** even if no context is current.
+*/
+
+static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
+
+/*
+** Dummy context used by small commands when there is no current context.
+** All the
+** gl and glx entry points are designed to operate as nop's when using
+** the dummy context structure.
+*/
+static __GLXcontext dummyContext = {
+   &dummyBuffer[0],
+   &dummyBuffer[0],
+   &dummyBuffer[0],
+   &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
+   sizeof(dummyBuffer),
+};
+
+
+/*
+** All indirect rendering contexts will share the same indirect dispatch table.
+*/
+static __GLapi *IndirectAPI = NULL;
+
+
+/*
+ * Current context management and locking
+ */
+
+#if defined( PTHREADS )
+
+_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
+
+# if defined( GLX_USE_TLS )
+
+/**
+ * Per-thread GLX context pointer.
+ *
+ * \c __glXSetCurrentContext is written is such a way that this pointer can
+ * \b never be \c NULL.  This is important!  Because of this
+ * \c __glXGetCurrentContext can be implemented as trivial macro.
+ */
+__thread void *__glX_tls_Context __attribute__ ((tls_model("initial-exec")))
+   = &dummyContext;
+
+_X_HIDDEN void
+__glXSetCurrentContext(__GLXcontext * c)
+{
+   __glX_tls_Context = (c != NULL) ? c : &dummyContext;
+}
+
+# else
+
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+/**
+ * Per-thread data key.
+ *
+ * Once \c init_thread_data has been called, the per-thread data key will
+ * take a value of \c NULL.  As each new thread is created the default
+ * value, in that thread, will be \c NULL.
+ */
+static pthread_key_t ContextTSD;
+
+/**
+ * Initialize the per-thread data key.
+ *
+ * This function is called \b exactly once per-process (not per-thread!) to
+ * initialize the per-thread data key.  This is ideally done using the
+ * \c pthread_once mechanism.
+ */
+static void
+init_thread_data(void)
+{
+   if (pthread_key_create(&ContextTSD, NULL) != 0) {
+      perror("pthread_key_create");
+      exit(-1);
+   }
+}
+
+_X_HIDDEN void
+__glXSetCurrentContext(__GLXcontext * c)
+{
+   pthread_once(&once_control, init_thread_data);
+   pthread_setspecific(ContextTSD, c);
+}
+
+_X_HIDDEN __GLXcontext *
+__glXGetCurrentContext(void)
+{
+   void *v;
+
+   pthread_once(&once_control, init_thread_data);
+
+   v = pthread_getspecific(ContextTSD);
+   return (v == NULL) ? &dummyContext : (__GLXcontext *) v;
+}
+
+# endif /* defined( GLX_USE_TLS ) */
+
+#elif defined( THREADS )
+
+#error Unknown threading method specified.
+
+#else
+
+/* not thread safe */
+_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext;
+
+#endif
+
+
+_X_HIDDEN void
+__glXSetCurrentContextNull(void)
+{
+   __glXSetCurrentContext(&dummyContext);
+#ifdef GLX_DIRECT_RENDERING
+   _glapi_set_dispatch(NULL);   /* no-op functions */
+   _glapi_set_context(NULL);
+#endif
+}
+
+
+/************************************************************************/
+
+PUBLIC GLXContext
+glXGetCurrentContext(void)
+{
+   GLXContext cx = __glXGetCurrentContext();
+
+   if (cx == &dummyContext) {
+      return NULL;
+   }
+   else {
+      return cx;
+   }
+}
+
+PUBLIC GLXDrawable
+glXGetCurrentDrawable(void)
+{
+   GLXContext gc = __glXGetCurrentContext();
+   return gc->currentDrawable;
+}
+
+
+/************************************************************************/
+
+/**
+ * Sends a GLX protocol message to the specified display to make the context
+ * and the drawables current.
+ *
+ * \param dpy     Display to send the message to.
+ * \param opcode  Major opcode value for the display.
+ * \param gc_id   Context tag for the context to be made current.
+ * \param draw    Drawable ID for the "draw" drawable.
+ * \param read    Drawable ID for the "read" drawable.
+ * \param reply   Space to store the X-server's reply.
+ *
+ * \warning
+ * This function assumes that \c dpy is locked with \c LockDisplay on entry.
+ */
+static Bool
+SendMakeCurrentRequest(Display * dpy, CARD8 opcode,
+                       GLXContextID gc_id, GLXContextTag gc_tag,
+                       GLXDrawable draw, GLXDrawable read,
+                       xGLXMakeCurrentReply * reply)
+{
+   Bool ret;
+
+
+   LockDisplay(dpy);
+
+   if (draw == read) {
+      xGLXMakeCurrentReq *req;
+
+      GetReq(GLXMakeCurrent, req);
+      req->reqType = opcode;
+      req->glxCode = X_GLXMakeCurrent;
+      req->drawable = draw;
+      req->context = gc_id;
+      req->oldContextTag = gc_tag;
+   }
+   else {
+      __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+
+      /* If the server can support the GLX 1.3 version, we should
+       * perfer that.  Not only that, some servers support GLX 1.3 but
+       * not the SGI extension.
+       */
+
+      if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+         xGLXMakeContextCurrentReq *req;
+
+         GetReq(GLXMakeContextCurrent, req);
+         req->reqType = opcode;
+         req->glxCode = X_GLXMakeContextCurrent;
+         req->drawable = draw;
+         req->readdrawable = read;
+         req->context = gc_id;
+         req->oldContextTag = gc_tag;
+      }
+      else {
+         xGLXVendorPrivateWithReplyReq *vpreq;
+         xGLXMakeCurrentReadSGIReq *req;
+
+         GetReqExtra(GLXVendorPrivateWithReply,
+                     sz_xGLXMakeCurrentReadSGIReq -
+                     sz_xGLXVendorPrivateWithReplyReq, vpreq);
+         req = (xGLXMakeCurrentReadSGIReq *) vpreq;
+         req->reqType = opcode;
+         req->glxCode = X_GLXVendorPrivateWithReply;
+         req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
+         req->drawable = draw;
+         req->readable = read;
+         req->context = gc_id;
+         req->oldContextTag = gc_tag;
+      }
+   }
+
+   ret = _XReply(dpy, (xReply *) reply, 0, False);
+
+   UnlockDisplay(dpy);
+   SyncHandle();
+
+   return ret;
+}
+
+
+#ifdef GLX_DIRECT_RENDERING
+static __GLXDRIdrawable *
+FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc)
+{
+   __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+   __GLXDRIdrawable *pdraw;
+   __GLXscreenConfigs *psc;
+
+   if (priv == NULL)
+      return NULL;
+
+   psc = &priv->screenConfigs[gc->screen];
+   if (psc->drawHash == NULL)
+      return NULL;
+
+   if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0)
+      return pdraw;
+
+   pdraw = psc->driScreen->createDrawable(psc, glxDrawable,
+                                          glxDrawable, gc->mode);
+   if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) {
+      (*pdraw->destroyDrawable) (pdraw);
+      return NULL;
+   }
+
+   return pdraw;
+}
+#endif /* GLX_DIRECT_RENDERING */
+
+static void
+__glXGenerateError(Display * dpy, GLXContext gc, XID resource,
+                   BYTE errorCode, CARD16 minorCode)
+{
+   xError error;
+
+   error.errorCode = errorCode;
+   error.resourceID = resource;
+   error.sequenceNumber = dpy->request;
+   error.type = X_Error;
+   error.majorCode = gc->majorOpcode;
+   error.minorCode = minorCode;
+   _XError(dpy, &error);
+}
+
+/**
+ * Make a particular context current.
+ *
+ * \note This is in this file so that it can access dummyContext.
+ */
+static Bool
+MakeContextCurrent(Display * dpy, GLXDrawable draw,
+                   GLXDrawable read, GLXContext gc)
+{
+   xGLXMakeCurrentReply reply;
+   const GLXContext oldGC = __glXGetCurrentContext();
+   const CARD8 opcode = __glXSetupForCommand(dpy);
+   const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext))
+      ? opcode : __glXSetupForCommand(oldGC->currentDpy);
+   Bool bindReturnValue;
+   __GLXattribute *state;
+
+   if (!opcode || !oldOpcode) {
+      return GL_FALSE;
+   }
+
+   /* Make sure that the new context has a nonzero ID.  In the request,
+    * a zero context ID is used only to mean that we bind to no current
+    * context.
+    */
+   if ((gc != NULL) && (gc->xid == None)) {
+      return GL_FALSE;
+   }
+
+   if (gc == NULL && (draw != None || read != None)) {
+      __glXGenerateError(dpy, gc, (draw != None) ? draw : read,
+                         BadMatch, X_GLXMakeContextCurrent);
+      return False;
+   }
+   if (gc != NULL && (draw == None || read == None)) {
+      __glXGenerateError(dpy, gc, None, BadMatch, X_GLXMakeContextCurrent);
+      return False;
+   }
+
+   _glapi_check_multithread();
+
+   if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) {
+      __glXGenerateError(dpy, gc, gc->xid,
+                         BadAccess, X_GLXMakeContextCurrent);
+      return False;
+   }
+
+#ifdef GLX_DIRECT_RENDERING
+   /* Bind the direct rendering context to the drawable */
+   if (gc && gc->driContext) {
+      __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc);
+      __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc);
+
+      if ((pdraw == NULL) || (pread == NULL)) {
+         __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read,
+                            GLXBadDrawable, X_GLXMakeContextCurrent);
+         return False;
+      }
+
+      bindReturnValue =
+         (gc->driContext->bindContext) (gc->driContext, pdraw, pread);
+   }
+   else if (!gc && oldGC && oldGC->driContext) {
+      bindReturnValue = True;
+   }
+   else
+#endif
+   {
+      /* Send a glXMakeCurrent request to bind the new context. */
+      bindReturnValue =
+         SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None,
+                                ((dpy != oldGC->currentDpy)
+                                 || oldGC->isDirect)
+                                ? None : oldGC->currentContextTag, draw, read,
+                                &reply);
+   }
+
+
+   if (!bindReturnValue) {
+      return False;
+   }
+
+#ifdef GLX_DIRECT_RENDERING
+   if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) &&
+       !oldGC->isDirect && oldGC != &dummyContext) {
+#else
+   if ((dpy != oldGC->currentDpy) && oldGC != &dummyContext) {
+#endif
+      xGLXMakeCurrentReply dummy_reply;
+
+      /* We are either switching from one dpy to another and have to
+       * send a request to the previous dpy to unbind the previous
+       * context, or we are switching away from a indirect context to
+       * a direct context and have to send a request to the dpy to
+       * unbind the previous context.
+       */
+      (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None,
+                                    oldGC->currentContextTag, None, None,
+                                    &dummy_reply);
+   }
+#ifdef GLX_DIRECT_RENDERING
+   else if (oldGC->driContext && oldGC != gc) {
+      oldGC->driContext->unbindContext(oldGC->driContext);
+   }
+#endif
+
+
+   /* Update our notion of what is current */
+   __glXLock();
+   if (gc == oldGC) {
+      /* Even though the contexts are the same the drawable might have
+       * changed.  Note that gc cannot be the dummy, and that oldGC
+       * cannot be NULL, therefore if they are the same, gc is not
+       * NULL and not the dummy.
+       */
+      gc->currentDrawable = draw;
+      gc->currentReadable = read;
+   }
+   else {
+      if (oldGC != &dummyContext) {
+         /* Old current context is no longer current to anybody */
+         oldGC->currentDpy = 0;
+         oldGC->currentDrawable = None;
+         oldGC->currentReadable = None;
+         oldGC->currentContextTag = 0;
+         oldGC->thread_id = 0;
+
+         if (oldGC->xid == None) {
+            /* We are switching away from a context that was
+             * previously destroyed, so we need to free the memory
+             * for the old handle.
+             */
+#ifdef GLX_DIRECT_RENDERING
+            /* Destroy the old direct rendering context */
+            if (oldGC->driContext) {
+               oldGC->driContext->destroyContext(oldGC->driContext,
+                                                 oldGC->psc,
+                                                 oldGC->createDpy);
+               oldGC->driContext = NULL;
+            }
+#endif
+            __glXFreeContext(oldGC);
+         }
+      }
+      if (gc) {
+         __glXSetCurrentContext(gc);
+
+         gc->currentDpy = dpy;
+         gc->currentDrawable = draw;
+         gc->currentReadable = read;
+         gc->thread_id = _glthread_GetID();
+
+#ifdef GLX_DIRECT_RENDERING
+         if (!gc->driContext) {
+#endif
+            if (!IndirectAPI)
+               IndirectAPI = __glXNewIndirectAPI();
+            _glapi_set_dispatch(IndirectAPI);
+
+            state = (__GLXattribute *) (gc->client_state_private);
+
+            gc->currentContextTag = reply.contextTag;
+            if (state->array_state == NULL) {
+               (void) glGetString(GL_EXTENSIONS);
+               (void) glGetString(GL_VERSION);
+               __glXInitVertexArrayState(gc);
+            }
+#ifdef GLX_DIRECT_RENDERING
+         }
+         else {
+            gc->currentContextTag = -1;
+      &