First pass at support for building DRI drivers in mesa tree.
authorKeith Whitwell <keith@tungstengraphics.com>
Wed, 14 Apr 2004 12:39:58 +0000 (12:39 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 14 Apr 2004 12:39:58 +0000 (12:39 +0000)
18 files changed:
src/mesa/drivers/dri/dri_client/Makefile [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/XF86dri.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/dri_glx.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/dri_glx.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/dri_util.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/dri_util.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/drm.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/glcontextmodes.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/glcontextmodes.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/imports/glxclient.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/imports/sarea.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/imports/xf86drm.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86dri.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86dristr.h [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86drm.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86drmHash.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86drmRandom.c [new file with mode: 0644]
src/mesa/drivers/dri/dri_client/xf86drmSL.c [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/dri_client/Makefile b/src/mesa/drivers/dri/dri_client/Makefile
new file mode 100644 (file)
index 0000000..14ba194
--- /dev/null
@@ -0,0 +1,60 @@
+# src/mesa/drivers/dri/gamma/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+# Get rid of this:
+#
+DEFINES += -DGLX_DIRECT_RENDERING 
+
+C_SOURCES = \
+       dri_glx.c \
+       dri_util.c \
+       glcontextmodes.c \
+       XF86dri.c \
+       xf86drm.c \
+       xf86drmHash.c \
+       xf86drmRandom.c \
+       xf86drmSL.c \
+
+
+
+OBJECTS = $(C_SOURCES:.c=.o)  
+
+INCLUDES = \
+       -I$(TOP)/include \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/mesa/main \
+       -I$(TOP)/src/mesa/glapi \
+       -Iimports
+
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend dri.a
+
+
+# Run 'make dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(C_SOURCES) $(ASM_SOURCES)
+       touch depend
+       makedepend -fdepend -Y $(INCLUDES) \
+               $(C_SOURCES) $(ASM_SOURCES) >& /dev/null
+
+
+dri.a: $(OBJECTS)
+       rm -f $@
+       ar rcv $@ $(OBJECTS)
+       ranlib $@
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o */*.o *~ *.so *.a
+
+include depend
diff --git a/src/mesa/drivers/dri/dri_client/XF86dri.c b/src/mesa/drivers/dri/dri_client/XF86dri.c
new file mode 100644 (file)
index 0000000..ea14b7a
--- /dev/null
@@ -0,0 +1,636 @@
+/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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 */
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include "xf86dristr.h"
+#include <X11/extensions/Xext.h>
+#include "extutil.h"
+
+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 (dpy, event_basep, error_basep)
+    Display *dpy;
+    int *event_basep, *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(dpy, majorVersion, minorVersion, patchVersion)
+    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(dpy, screen, isCapable)
+    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(dpy, screen, hSAREA, busIdString)
+    Display* dpy;
+    int screen;
+    drmHandlePtr 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;
+#ifdef LONG64
+    *hSAREA |= ((drmHandle)rep.hSAREAHigh) << 32;
+#endif
+
+    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(dpy, screen, magic)
+    Display* dpy;
+    int screen;
+    drmMagic 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(dpy, screen)
+    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(dpy, screen, ddxDriverMajorVersion, 
+       ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+    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(dpy, screen, configID, context, hHWContext)
+    Display* dpy;
+    int screen;
+    int configID;
+    XID* context;
+    drmContextPtr 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(dpy, screen, visual, context, hHWContext)
+    Display* dpy;
+    int screen;
+    Visual* visual;
+    XID* context;
+    drmContextPtr hHWContext;
+{
+    return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
+                                          context, hHWContext );
+}
+
+Bool XF86DRIDestroyContext(dpy, screen, context)
+    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(dpy, screen, drawable, hHWDrawable)
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+    drmDrawablePtr 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;
+}
+
+Bool XF86DRIDestroyDrawable(dpy, screen, drawable)
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+{
+    XExtDisplayInfo *info = find_display (dpy);
+    xXF86DRIDestroyDrawableReq *req;
+
+    TRACE("DestroyDrawable...");
+    XF86DRICheckExtension (dpy, info, False);
+
+    LockDisplay(dpy);
+    GetReq(XF86DRIDestroyDrawable, req);
+    req->reqType = info->codes->major_opcode;
+    req->driReqType = X_XF86DRIDestroyDrawable;
+    req->screen = screen;
+    req->drawable = drawable;
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("DestroyDrawable... return True");
+    return True;
+}
+
+Bool XF86DRIGetDrawableInfo(dpy, screen, drawable, 
+                           index, stamp, X, Y, W, H, 
+                           numClipRects, pClipRects,
+                           backX, backY, 
+                           numBackClipRects, pBackClipRects
+                           )
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+    unsigned int* index;
+    unsigned int* stamp;
+    int* X;
+    int* Y;
+    int* W;
+    int* H;
+    int* numClipRects;
+    XF86DRIClipRectPtr* pClipRects;
+    int* backX;
+    int* backY;
+    int* numBackClipRects;
+    XF86DRIClipRectPtr*        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(XF86DRIClipRectRec)) + 3) & ~3) >> 2)) {
+        _XEatData(dpy, rep.length);
+       UnlockDisplay(dpy);
+       SyncHandle();
+        TRACE("GetDrawableInfo... return False");
+        return False;
+    }
+#endif
+
+    if (*numClipRects) {
+       int len = sizeof(XF86DRIClipRectRec) * (*numClipRects);
+
+       *pClipRects = (XF86DRIClipRectPtr)Xcalloc(len, 1);
+       if (*pClipRects) 
+         _XRead(dpy, (char*)*pClipRects, len);
+    } else {
+        *pClipRects = NULL;
+    }
+
+    if (*numBackClipRects) {
+       int len = sizeof(XF86DRIClipRectRec) * (*numBackClipRects);
+
+       *pBackClipRects = (XF86DRIClipRectPtr)Xcalloc(len, 1);
+       if (*pBackClipRects) 
+         _XRead(dpy, (char*)*pBackClipRects, len);
+    } else {
+        *pBackClipRects = NULL;
+    }
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    TRACE("GetDrawableInfo... return True");
+    return True;
+}
+
+Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer, 
+       fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+    Display* dpy;
+    int screen;
+    drmHandlePtr 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;
+#ifdef LONG64
+    *hFrameBuffer |= ((drmHandle)rep.hFrameBufferHigh) << 32;
+#endif
+
+    *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;
+}
+
+#if 0
+Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
+    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(dpy, screen, drawable)
+    Display* dpy;
+    int screen;
+    Drawable drawable;
+{
+    /* This function and the underlying X protocol are deprecated.
+     */
+    (void) dpy;
+    (void) screen;
+    (void) drawable;
+    return True;
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/dri_glx.c b/src/mesa/drivers/dri/dri_client/dri_glx.c
new file mode 100644 (file)
index 0000000..f0b5f19
--- /dev/null
@@ -0,0 +1,475 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+/* $XFree86: xc/lib/GL/dri/dri_glx.c,v 1.14 2003/07/16 00:54:00 dawes Exp $ */
+
+/*
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <unistd.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include "extutil.h"
+#include "glxclient.h"
+#include "xf86dri.h"
+#include "sarea.h"
+#include <stdio.h>
+#include <dlfcn.h>
+#include "dri_glx.h"
+#include <sys/types.h>
+#include <stdarg.h>
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+#ifdef BUILT_IN_DRI_DRIVER
+
+extern void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                               int numConfigs, __GLXvisualConfig *config);
+
+
+#else /* BUILT_IN_DRI_DRIVER */
+
+
+#ifndef DEFAULT_DRIVER_DIR
+/* this is normally defined in the Imakefile */
+#define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
+#endif
+
+static __DRIdriver *Drivers = NULL;
+
+
+/*
+ * printf wrappers
+ */
+
+static 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);
+    }
+}
+
+static void ErrorMessageF(const char *f, ...)
+{
+    va_list args;
+
+    if (getenv("LIBGL_DEBUG")) {
+       fprintf(stderr, "libGL error: ");
+       va_start(args, f);
+       vfprintf(stderr, f, args);
+       va_end(args);
+    }
+}
+
+
+/*
+ * We'll save a pointer to this function when we couldn't find a
+ * direct rendering driver for a given screen.
+ */
+static void *DummyCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                               int numConfigs, __GLXvisualConfig *config)
+{
+    (void) dpy;
+    (void) scrn;
+    (void) psc;
+    (void) numConfigs;
+    (void) config;
+    return NULL;
+}
+
+
+
+/*
+ * Extract the ith directory path out of a colon-separated list of
+ * paths.
+ * Input:
+ *   index - index of path to extract (starting at zero)
+ *   paths - the colon-separated list of paths
+ *   dirLen - max length of result to store in <dir>
+ * Output:
+ *   dir - the extracted directory path, dir[0] will be zero when
+ *         extraction fails.
+ */
+static void ExtractDir(int index, const char *paths, int dirLen, char *dir)
+{
+   int i, len;
+   const char *start, *end;
+
+   /* find ith colon */
+   start = paths;
+   i = 0;
+   while (i < index) {
+      if (*start == ':') {
+         i++;
+         start++;
+      }
+      else if (*start == 0) {
+         /* end of string and couldn't find ith colon */
+         dir[0] = 0;
+         return;
+      }
+      else {
+         start++;
+      }
+   }
+
+   while (*start == ':')
+      start++;
+
+   /* find next colon, or end of string */
+   end = start + 1;
+   while (*end != ':' && *end != 0) {
+      end++;
+   }
+
+   /* copy string between <start> and <end> into result string */
+   len = end - start;
+   if (len > dirLen - 1)
+      len = dirLen - 1;
+   strncpy(dir, start, len);
+   dir[len] = 0;
+}
+
+
+/*
+ * Try to dlopen() the named driver.  This function adds the
+ * "_dri.so" suffix to the driver name and searches the
+ * directories specified by the LIBGL_DRIVERS_PATH env var
+ * in order to find the driver.
+ * Input:
+ *   driverName - a name like "tdfx", "i810", "mga", etc.
+ * Return:
+ *   handle from dlopen, or NULL if driver file not found.
+ */
+static __DRIdriver *OpenDriver(const char *driverName)
+{
+   char *libPaths = NULL;
+   int i;
+   __DRIdriver *driver;
+
+   /* First, search Drivers list to see if we've already opened this driver */
+   for (driver = Drivers; driver; driver = driver->next) {
+      if (strcmp(driver->name, driverName) == 0) {
+         /* found it */
+         return driver;
+      }
+   }
+
+   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)
+      libPaths = DEFAULT_DRIVER_DIR;
+
+   for (i = 0; ; i++) {
+      char libDir[1000], realDriverName[200];
+      void *handle;
+      ExtractDir(i, libPaths, 1000, libDir);
+      if (!libDir[0])
+         break; /* ran out of paths to search */
+      snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
+      InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+      handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+      if (handle) {
+         /* allocate __DRIdriver struct */
+         driver = (__DRIdriver *) Xmalloc(sizeof(__DRIdriver));
+         if (!driver)
+            return NULL; /* out of memory! */
+         /* init the struct */
+         driver->name = __glXstrdup(driverName);
+         if (!driver->name) {
+            Xfree(driver);
+            return NULL; /* out of memory! */
+         }
+
+         driver->createScreenFunc = (CreateScreenFunc)
+            dlsym(handle, "__driCreateScreen");
+         driver->createNewScreenFunc = (CreateNewScreenFunc)
+            dlsym(handle, "__driCreateNewScreen");
+
+         if ( (driver->createScreenFunc == NULL) 
+             && (driver->createNewScreenFunc == NULL) ) {
+            /* If the driver doesn't have this symbol then something's
+             * really, really wrong.
+             */
+            ErrorMessageF("Neither __driCreateScreen or __driCreateNewScreen "
+                         "are defined in %s_dri.so!\n", driverName);
+            Xfree(driver);
+            dlclose(handle);
+            continue;
+         }
+         driver->handle = handle;
+         /* put at head of linked list */
+         driver->next = Drivers;
+         Drivers = driver;
+         return driver;
+      }
+      else {
+        ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
+      }
+   }
+
+   ErrorMessageF("unable to find driver: %s_dri.so\n", driverName);
+   return NULL;
+}
+
+
+/*
+ * 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 GetDriverName(Display *dpy, int scrNum, char **driverName)
+{
+   int directCapable;
+   Bool b;
+   int driverMajor, driverMinor, driverPatch;
+
+   *driverName = NULL;
+
+   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;
+}
+
+
+/*
+ * Given a display pointer and screen number, return a __DRIdriver handle.
+ * Return NULL if anything goes wrong.
+ */
+__DRIdriver *driGetDriver(Display *dpy, int scrNum)
+{
+   char *driverName;
+   if (GetDriverName(dpy, scrNum, &driverName)) {
+      __DRIdriver *ret;
+      ret = OpenDriver(driverName);
+      if (driverName)
+        Xfree(driverName);
+      return ret;
+   }
+   return NULL;
+}
+
+
+/*
+ * 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.
+ */
+const char *glXGetScreenDriver (Display *dpy, int scrNum) {
+   static char ret[32];
+   char *driverName;
+   if (GetDriverName(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.
+ */
+const char *glXGetDriverConfig (const char *driverName) {
+   __DRIdriver *driver = OpenDriver (driverName);
+   if (driver)
+      return dlsym (driver->handle, "__driConfigOptions");
+   else
+      return NULL;
+}
+
+
+#endif /* BUILT_IN_DRI_DRIVER */
+
+
+/* This function isn't currently used.
+ */
+static void driDestroyDisplay(Display *dpy, void *private)
+{
+    __DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
+
+    if (pdpyp) {
+        const int numScreens = ScreenCount(dpy);
+        int i;
+        for (i = 0; i < numScreens; i++) {
+            if (pdpyp->libraryHandles[i])
+                dlclose(pdpyp->libraryHandles[i]);
+        }
+        Xfree(pdpyp->libraryHandles);
+       Xfree(pdpyp);
+    }
+}
+
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
+{
+    const int numScreens = ScreenCount(dpy);
+    __DRIdisplayPrivate *pdpyp;
+    int eventBase, errorBase;
+    int major, minor, patch;
+    int scrn;
+
+    /* Initialize these fields to NULL in case we fail.
+     * If we don't do this we may later get segfaults trying to free random
+     * addresses when the display is closed.
+     */
+    pdisp->private = NULL;
+    pdisp->destroyDisplay = NULL;
+    pdisp->createScreen = NULL;
+
+    if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
+       return NULL;
+    }
+
+    if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
+       return NULL;
+    }
+
+    pdpyp = (__DRIdisplayPrivate *)Xmalloc(sizeof(__DRIdisplayPrivate));
+    if (!pdpyp) {
+       return NULL;
+    }
+
+    pdpyp->driMajor = major;
+    pdpyp->driMinor = minor;
+    pdpyp->driPatch = patch;
+
+    pdisp->destroyDisplay = driDestroyDisplay;
+
+    /* allocate array of pointers to createScreen funcs */
+    pdisp->createScreen = (CreateScreenFunc *) Xmalloc(numScreens * sizeof(void *));
+    if (!pdisp->createScreen) {
+       Xfree(pdpyp);
+       return NULL;
+    }
+
+    /* allocate array of pointers to createScreen funcs */
+    pdisp->createNewScreen = (CreateNewScreenFunc *) Xmalloc(numScreens * sizeof(void *));
+    if (!pdisp->createNewScreen) {
+       Xfree(pdisp->createScreen);
+       Xfree(pdpyp);
+       return NULL;
+    }
+
+    /* allocate array of library handles */
+    pdpyp->libraryHandles = (void **) Xmalloc(numScreens * sizeof(void*));
+    if (!pdpyp->libraryHandles) {
+       Xfree(pdisp->createNewScreen);
+       Xfree(pdisp->createScreen);
+       Xfree(pdpyp);
+       return NULL;
+    }
+
+#ifdef BUILT_IN_DRI_DRIVER
+    /* we'll statically bind to the built-in __driCreateScreen function */
+    for (scrn = 0; scrn < numScreens; scrn++) {
+       pdisp->createScreen[scrn] = __driCreateScreen;
+       pdisp->createNewScreen[scrn] = NULL;
+       pdpyp->libraryHandles[scrn] = NULL;
+    }
+
+#else
+    /* dynamically discover DRI drivers for all screens, saving each
+     * driver's "__driCreateScreen" function pointer.  That's the bootstrap
+     * entrypoint for all DRI drivers.
+     */
+    for (scrn = 0; scrn < numScreens; scrn++) {
+        __DRIdriver *driver = driGetDriver(dpy, scrn);
+        if (driver) {
+           pdisp->createScreen[scrn] = driver->createScreenFunc;
+           pdisp->createNewScreen[scrn] = driver->createNewScreenFunc;
+           pdpyp->libraryHandles[scrn] = driver->handle;
+        }
+        else {
+           pdisp->createScreen[scrn] = DummyCreateScreen;
+           pdisp->createNewScreen[scrn] = NULL;
+           pdpyp->libraryHandles[scrn] = NULL;
+        }
+    }
+#endif
+
+    return (void *)pdpyp;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/mesa/drivers/dri/dri_client/dri_glx.h b/src/mesa/drivers/dri/dri_client/dri_glx.h
new file mode 100644 (file)
index 0000000..7556168
--- /dev/null
@@ -0,0 +1,61 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *
+ */
+
+#ifndef _DRI_GLX_H_
+#define _DRI_GLX_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+struct __DRIdisplayPrivateRec {
+    /*
+    ** XFree86-DRI version information
+    */
+    int driMajor;
+    int driMinor;
+    int driPatch;
+
+    /*
+    ** Array of library handles [indexed by screen number]
+    */
+    void **libraryHandles;
+};
+
+typedef struct __DRIdisplayPrivateRec  __DRIdisplayPrivate;
+typedef struct __DRIscreenPrivateRec   __DRIscreenPrivate;
+typedef struct __DRIvisualPrivateRec   __DRIvisualPrivate;
+typedef struct __DRIcontextPrivateRec  __DRIcontextPrivate;
+typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate;
+
+#endif
+#endif /* _DRI_GLX_H_ */
diff --git a/src/mesa/drivers/dri/dri_client/dri_util.c b/src/mesa/drivers/dri/dri_client/dri_util.c
new file mode 100644 (file)
index 0000000..4284728
--- /dev/null
@@ -0,0 +1,1578 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \note
+ * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
+ * that only the "new" libGL-to-driver interfaces are supported.  This breaks
+ * backwards compatability.  However, this may be necessary when DRI drivers
+ * are built to be used in non-XFree86 environments.
+ *
+ * \todo There are still some places in the code that need to be wrapped with
+ *       \c DRI_NEW_INTERFACE_ONLY.
+ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <inttypes.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <X11/Xlibint.h>
+#include <Xext.h>
+#include <extutil.h>
+#include <stdio.h>
+#include "xf86dri.h"
+#include "sarea.h"
+#include "dri_util.h"
+#include "glcontextmodes.h"
+
+/*#define DRI_NEW_INTERFACE_ONLY*/
+
+/**
+ * This is used in a couple of places that call \c driCreateNewDrawable.
+ */
+static const int empty_attribute_list[1] = { None };
+
+/**
+ * Function used to determine if a drawable (window) still exists.  Ideally
+ * this function comes from libGL.  With older versions of libGL from XFree86
+ * we can fall-back to an internal version.
+ * 
+ * \sa __driWindowExists __glXWindowExists
+ */
+static PFNGLXWINDOWEXISTSPROC window_exists;
+
+typedef Bool (*PFNGLXCREATECONTEXTWITHCONFIGPROC)( Display*, int, int, void *,
+    drmContextPtr );
+
+static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config;
+
+/**
+ * Cached copy of the internal API version used by libGL and the client-side
+ * DRI driver.
+ */
+static int api_ver = 0;
+
+/* forward declarations */
+static int driQueryFrameTracking( Display * dpy, void * priv,
+    int64_t * sbc, int64_t * missedFrames, float * lastMissedUsage,
+    float * usage );
+
+static void *driCreateNewDrawable(Display *dpy, const __GLcontextModes *modes,
+    GLXDrawable draw, __DRIdrawable *pdraw, int renderType, const int *attrs);
+
+static void driDestroyDrawable(Display *dpy, void *drawablePrivate);
+
+
+
+
+#ifdef not_defined
+static Bool driFeatureOn(const char *name)
+{
+    char *env = getenv(name);
+
+    if (!env) return GL_FALSE;
+    if (!strcasecmp(env, "enable")) return GL_TRUE;
+    if (!strcasecmp(env, "1"))      return GL_TRUE;
+    if (!strcasecmp(env, "on"))     return GL_TRUE;
+    if (!strcasecmp(env, "true"))   return GL_TRUE;
+    if (!strcasecmp(env, "t"))      return GL_TRUE;
+    if (!strcasecmp(env, "yes"))    return GL_TRUE;
+    if (!strcasecmp(env, "y"))      return GL_TRUE;
+
+    return GL_FALSE;
+}
+#endif /* not_defined */
+
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set. 
+ * 
+ * Is called from the drivers.
+ * 
+ * \param f \c printf like format string.
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+    va_list args;
+
+    if (getenv("LIBGL_DEBUG")) {
+        fprintf(stderr, "libGL error: \n");
+        va_start(args, f);
+        vfprintf(stderr, f, args);
+        va_end(args);
+        fprintf(stderr, "\n");
+    }
+}
+
+
+/*****************************************************************/
+/** \name Visual utility functions                               */
+/*****************************************************************/
+/*@{*/
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Find a \c __GLcontextModes structure matching the given visual ID.
+ * 
+ * \param dpy   Display to search for a matching configuration.
+ * \param scrn  Screen number on \c dpy to be searched.
+ * \param vid   Desired \c VisualID to find.
+ *
+ * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
+ *          if found, or \c NULL if no match is found.
+ */
+static const __GLcontextModes *
+findConfigMode(Display *dpy, int scrn, VisualID vid, 
+              const __DRIscreen * pDRIScreen)
+{
+    if ( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) ) {
+       const __DRIscreenPrivate * const psp =
+           (const __DRIscreenPrivate *) pDRIScreen->private;
+
+       return _gl_context_modes_find_visual( psp->modes, vid );
+    }
+
+    return NULL;
+}
+
+
+/**
+ * This function is a hack to work-around old versions of libGL.so that
+ * do not export \c XF86DRICreateContextWithConfig.  I would modify the
+ * code to just use this function, but the stand-alone driver (i.e., DRI
+ * drivers that are built to work without XFree86) shouldn't have to know
+ * about X structures like a \c Visual.
+ */
+static Bool
+fake_XF86DRICreateContextWithConfig( Display* dpy, int screen, int configID,
+                                    XID* context, drmContextPtr hHWContext )
+{
+    Visual  vis;
+    
+    vis.visualid = configID;
+    return XF86DRICreateContext( dpy, screen, & vis, context, hHWContext );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable list management */
+/*****************************************************************/
+/*@{*/
+
+static Bool __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
+{
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+    if (drmHashInsert(drawHash, pdp->draw, pdraw))
+       return GL_FALSE;
+
+    return GL_TRUE;
+}
+
+static __DRIdrawable *__driFindDrawable(void *drawHash, GLXDrawable draw)
+{
+    int retcode;
+    __DRIdrawable *pdraw;
+
+    retcode = drmHashLookup(drawHash, draw, (void **)&pdraw);
+    if (retcode)
+       return NULL;
+
+    return pdraw;
+}
+
+static void __driRemoveDrawable(void *drawHash, __DRIdrawable *pdraw)
+{
+    int retcode;
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+    retcode = drmHashLookup(drawHash, pdp->draw, (void **)&pdraw);
+    if (!retcode) { /* Found */
+       drmHashDelete(drawHash, pdp->draw);
+    }
+}
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+static Bool __driWindowExistsFlag;
+
+static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
+{
+    if (xerr->error_code == BadWindow) {
+       __driWindowExistsFlag = GL_FALSE;
+    }
+    return 0;
+}
+
+/**
+ * Determine if a window associated with a \c GLXDrawable exists on the
+ * X-server.
+ *
+ * \param dpy  Display associated with the drawable to be queried.
+ * \param draw \c GLXDrawable to test.
+ * 
+ * \returns \c GL_TRUE if a window exists that is associated with \c draw,
+ *          otherwise \c GL_FALSE is returned.
+ * 
+ * \warning This function is not currently thread-safe.
+ *
+ * \deprecated
+ * \c __glXWindowExists (from libGL) is prefered over this function.  Starting
+ * with the next major release of XFree86, this function will be removed.
+ * Even now this function is no longer directly called.  Instead it is called
+ * via a function pointer if and only if \c __glXWindowExists does not exist.
+ * 
+ * \sa __glXWindowExists glXGetProcAddress window_exists
+ */
+static Bool __driWindowExists(Display *dpy, GLXDrawable draw)
+{
+    XWindowAttributes xwa;
+    int (*oldXErrorHandler)(Display *, XErrorEvent *);
+
+    XSync(dpy, GL_FALSE);
+    __driWindowExistsFlag = GL_TRUE;
+    oldXErrorHandler = XSetErrorHandler(__driWindowExistsErrorHandler);
+    XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
+    XSetErrorHandler(oldXErrorHandler);
+    return __driWindowExistsFlag;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/**
+ * Find drawables in the local hash that have been destroyed on the
+ * server.
+ * 
+ * \param drawHash  Hash-table containing all know drawables.
+ */
+static void __driGarbageCollectDrawables(void *drawHash)
+{
+    GLXDrawable draw;
+    __DRIdrawable *pdraw;
+    Display *dpy;
+
+    if (drmHashFirst(drawHash, &draw, (void **)&pdraw)) {
+       do {
+           __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+           dpy = pdp->driScreenPriv->display;
+           if (! (*window_exists)(dpy, draw)) {
+               /* Destroy the local drawable data in the hash table, if the
+                  drawable no longer exists in the Xserver */
+               __driRemoveDrawable(drawHash, pdraw);
+               (*pdraw->destroyDrawable)(dpy, pdraw->private);
+               Xfree(pdraw);
+           }
+       } while (drmHashNext(drawHash, &draw, (void **)&pdraw));
+    }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context (un)binding functions                          */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param draw drawable.
+ * \param read Current reading drawable.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ * 
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
+ * return.
+ * 
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL. 
+ */
+static Bool driUnbindContext2(Display *dpy, int scrn,
+                             GLXDrawable draw, GLXDrawable read,
+                             GLXContext gc)
+{
+    __DRIscreen *pDRIScreen;
+    __DRIdrawable *pdraw;
+    __DRIdrawable *pread;
+    __DRIcontextPrivate *pcp;
+    __DRIscreenPrivate *psp;
+    __DRIdrawablePrivate *pdp;
+    __DRIdrawablePrivate *prp;
+
+    /*
+    ** Assume error checking is done properly in glXMakeCurrent before
+    ** calling driUnbindContext2.
+    */
+
+    if (gc == NULL || draw == None || read == None) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+
+    pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+
+    psp = (__DRIscreenPrivate *)pDRIScreen->private;
+    pcp = (__DRIcontextPrivate *)gc->driContext.private;
+
+    pdraw = __driFindDrawable(psp->drawHash, draw);
+    if (!pdraw) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+    pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+    pread = __driFindDrawable(psp->drawHash, read);
+    if (!pread) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+    prp = (__DRIdrawablePrivate *)pread->private;
+
+
+    /* Let driver unbind drawable from context */
+    (*psp->DriverAPI.UnbindContext)(pcp);
+
+
+    if (pdp->refcount == 0) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+
+    pdp->refcount--;
+
+    if (prp != pdp) {
+        if (prp->refcount == 0) {
+           /* ERROR!!! */
+           return GL_FALSE;
+       }
+
+       prp->refcount--;
+    }
+
+
+    /* XXX this is disabled so that if we call SwapBuffers on an unbound
+     * window we can determine the last context bound to the window and
+     * use that context's lock. (BrianP, 2-Dec-2000)
+     */
+#if 0
+    /* Unbind the drawable */
+    pcp->driDrawablePriv = NULL;
+    pdp->driContextPriv = &psp->dummyContextPriv;
+#endif
+
+    return GL_TRUE;
+}
+
+
+/**
+ * This function takes both a read buffer and a draw buffer.  This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ * 
+ * \bug This function calls \c driCreateNewDrawable in two places with the
+ *      \c renderType hard-coded to \c GLX_WINDOW_BIT.  Some checking might
+ *      be needed in those places when support for pbuffers and / or pixmaps
+ *      is added.  Is it safe to assume that the drawable is a window?
+ */
+static Bool driBindContext2(Display *dpy, int scrn,
+                            GLXDrawable draw, GLXDrawable read,
+                            GLXContext gc)
+{
+    __DRIscreen *pDRIScreen;
+    __DRIdrawable *pdraw;
+    __DRIdrawablePrivate *pdp;
+    __DRIdrawable *pread;
+    __DRIdrawablePrivate *prp;
+    __DRIscreenPrivate *psp;
+    __DRIcontextPrivate *pcp;
+    const __GLcontextModes *modes;
+
+    /*
+    ** Assume error checking is done properly in glXMakeCurrent before
+    ** calling driBindContext.
+    */
+
+    if (gc == NULL || draw == None || read == None) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+
+    pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+#ifdef DRI_NEW_INTERFACE_ONLY
+    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       /* ERROR!!! */
+       return GL_FALSE;
+    }
+#else
+    if ( driCompareGLXAPIVersion( 20031201 ) >= 0 ) {
+#endif /* DRI_NEW_INTERFACE_ONLY */
+       modes = gc->mode;
+#ifndef DRI_NEW_INTERFACE_ONLY
+    }
+    else {
+       modes = findConfigMode( dpy, scrn, gc->vid, pDRIScreen );
+       if ( modes == NULL ) {
+           /* ERROR!!! */
+           return GL_FALSE;
+       }
+    }
+
+
+    /* findConfigMode will return NULL if the DRI screen or screen private
+     * are NULL.
+     */
+    assert( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) );
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+    /* Find the _DRIdrawable which corresponds to the writing GLXDrawable */
+    psp = (__DRIscreenPrivate *)pDRIScreen->private;
+    pdraw = __driFindDrawable(psp->drawHash, draw);
+    if (!pdraw) {
+       /* Allocate a new drawable */
+       pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
+       if (!pdraw) {
+           /* ERROR!!! */
+           return GL_FALSE;
+       }
+
+       /* Create a new drawable */
+       driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
+                            empty_attribute_list);
+       if (!pdraw->private) {
+           /* ERROR!!! */
+           Xfree(pdraw);
+           return GL_FALSE;
+       }
+
+    }
+    pdp = (__DRIdrawablePrivate *) pdraw->private;
+
+    /* Find the _DRIdrawable which corresponds to the reading GLXDrawable */
+    if (read == draw) {
+        /* read buffer == draw buffer */
+        prp = pdp;
+    }
+    else {
+        pread = __driFindDrawable(psp->drawHash, read);
+        if (!pread) {
+            /* Allocate a new drawable */
+            pread = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
+            if (!pread) {
+                /* ERROR!!! */
+                return GL_FALSE;
+            }
+
+            /* Create a new drawable */
+           driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
+                                empty_attribute_list);
+            if (!pread->private) {
+                /* ERROR!!! */
+                Xfree(pread);
+                return GL_FALSE;
+            }
+        }
+        prp = (__DRIdrawablePrivate *) pread->private;
+    }
+
+    /* Bind the drawable to the context */
+    pcp = (__DRIcontextPrivate *)gc->driContext.private;
+    pcp->driDrawablePriv = pdp;
+    pdp->driContextPriv = pcp;
+    pdp->refcount++;
+    if ( pdp != prp ) {
+       prp->refcount++;
+    }
+
+    /*
+    ** Now that we have a context associated with this drawable, we can
+    ** initialize the drawable information if has not been done before.
+    */
+    if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
+       DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+       __driUtilUpdateDrawableInfo(pdp);
+       DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+    }
+
+    /* Call device-specific MakeCurrent */
+    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+
+    return GL_TRUE;
+}
+
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static Bool driBindContext(Display *dpy, int scrn,
+                           GLXDrawable draw, GLXContext gc)
+{
+    return driBindContext2(dpy, scrn, draw, draw, gc);
+}
+
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static Bool driUnbindContext(Display *dpy, int scrn,
+                             GLXDrawable draw, GLXContext gc,
+                             int will_rebind)
+{
+   (void) will_rebind;
+   return driUnbindContext2( dpy, scrn, draw, draw, gc );
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions                            */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ * 
+ * This function basically updates the __DRIdrawablePrivate struct's
+ * cliprect information by calling \c __DRIDrawablePrivate::getInfo.  This is
+ * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
+{
+    __DRIscreenPrivate *psp;
+    __DRIcontextPrivate *pcp = pdp->driContextPriv;
+    
+    if (!pcp || (pdp != pcp->driDrawablePriv)) {
+       /* ERROR!!! */
+       return;
+    }
+
+    psp = pdp->driScreenPriv;
+    if (!psp) {
+       /* ERROR!!! */
+       return;
+    }
+
+    if (pdp->pClipRects) {
+       Xfree(pdp->pClipRects); 
+    }
+
+    if (pdp->pBackClipRects) {
+       Xfree(pdp->pBackClipRects); 
+    }
+
+    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+    if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
+       ! (*pdp->getInfo)(pdp->display, pdp->screen, pdp->draw,
+                         &pdp->index, &pdp->lastStamp,
+                         &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+                         &pdp->numClipRects, &pdp->pClipRects,
+                         &pdp->backX,
+                         &pdp->backY,
+                         &pdp->numBackClipRects,
+                         &pdp->pBackClipRects )) {
+       /* Error -- eg the window may have been destroyed.  Keep going
+        * with no cliprects.
+        */
+        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+       pdp->numClipRects = 0;
+       pdp->pClipRects = NULL;
+       pdp->numBackClipRects = 0;
+       pdp->pBackClipRects = NULL;
+    }
+    else
+       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks                                          */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Swap buffers.
+ *
+ * \param dpy the display handle.
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ * 
+ * \internal
+ * This function calls __DRIdrawablePrivate::swapBuffers.
+ * 
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers( Display *dpy, void *drawablePrivate )
+{
+    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+    dPriv->swapBuffers(dPriv);
+    (void) dpy;
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetMSC( void *screenPrivate, int64_t *msc )
+{
+    __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
+
+    return sPriv->DriverAPI.GetMSC( sPriv, msc );
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetSBC( Display *dpy, void *drawablePrivate, int64_t *sbc )
+{
+   __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+   __DRIswapInfo  sInfo;
+   int  status;
+
+
+   status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+   *sbc = sInfo.swap_count;
+
+   return status;
+}
+
+static int driWaitForSBC( Display * dpy, void *drawablePriv,
+                         int64_t target_sbc,
+                         int64_t * msc, int64_t * sbc )
+{
+    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+    return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
+                                                       msc, sbc );
+}
+
+static int driWaitForMSC( Display * dpy, void *drawablePriv,
+                         int64_t target_msc,
+                         int64_t divisor, int64_t remainder,
+                         int64_t * msc, int64_t * sbc )
+{
+    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+    __DRIswapInfo  sInfo;
+    int  status;
+
+
+    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+                                                         divisor, remainder,
+                                                         msc );
+
+    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
+     * an error value if GetSwapInfo() is not implemented.
+    */
+    if ( status == 0
+         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+        *sbc = sInfo.swap_count;
+    }
+
+    return status;
+}
+
+static int64_t driSwapBuffersMSC( Display * dpy, void *drawablePriv,
+                                 int64_t target_msc,
+                                 int64_t divisor, int64_t remainder )
+{
+    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+    return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
+                                                           divisor, 
+                                                           remainder );
+}
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static void *driCreateNewDrawable(Display *dpy,
+                                 const __GLcontextModes *modes,
+                                 GLXDrawable draw,
+                                 __DRIdrawable *pdraw,
+                                 int renderType,
+                                 const int *attrs)
+{
+    __DRIscreen * const pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
+    __DRIscreenPrivate *psp;
+    __DRIdrawablePrivate *pdp;
+
+
+    /* Since pbuffers are not yet supported, no drawable attributes are
+     * supported either.
+     */
+    (void) attrs;
+
+    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       return NULL;
+    }
+
+    pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
+    if (!pdp) {
+       return NULL;
+    }
+
+    if (!XF86DRICreateDrawable(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
+       Xfree(pdp);
+       return NULL;
+    }
+
+    pdp->draw = draw;
+    pdp->pdraw = pdraw;
+    pdp->refcount = 0;
+    pdp->pStamp = NULL;
+    pdp->lastStamp = 0;
+    pdp->index = 0;
+    pdp->x = 0;
+    pdp->y = 0;
+    pdp->w = 0;
+    pdp->h = 0;
+    pdp->numClipRects = 0;
+    pdp->numBackClipRects = 0;
+    pdp->pClipRects = NULL;
+    pdp->pBackClipRects = NULL;
+    pdp->display = dpy;
+    pdp->screen = modes->screen;
+
+    psp = (__DRIscreenPrivate *)pDRIScreen->private;
+    pdp->driScreenPriv = psp;
+    pdp->driContextPriv = &psp->dummyContextPriv;
+
+    pdp->getInfo = (GetDrawableInfo *)
+       glXGetProcAddress( (const GLubyte *) "__glXGetDrawableInfo" );
+    if ( pdp->getInfo == NULL ) {
+       pdp->getInfo = XF86DRIGetDrawableInfo;
+    }
+
+    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
+                                       renderType == GLX_PIXMAP_BIT)) {
+       (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
+       Xfree(pdp);
+       return NULL;
+    }
+
+    pdraw->private = pdp;
+    pdraw->destroyDrawable = driDestroyDrawable;
+    pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
+
+    if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+        pdraw->getSBC = driGetSBC;
+        pdraw->waitForSBC = driWaitForSBC;
+        pdraw->waitForMSC = driWaitForMSC;
+        pdraw->swapBuffersMSC = driSwapBuffersMSC;
+        pdraw->frameTracking = NULL;
+        pdraw->queryFrameTracking = driQueryFrameTracking;
+
+        /* This special default value is replaced with the configured
+        * default value when the drawable is first bound to a direct
+        * rendering context. */
+        pdraw->swap_interval = (unsigned)-1;
+    }
+
+    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
+
+    /* Add pdraw to drawable list */
+    if (!__driAddDrawable(psp->drawHash, pdraw)) {
+       /* ERROR!!! */
+       (*pdraw->destroyDrawable)(dpy, pdp);
+       Xfree(pdp);
+       pdp = NULL;
+       pdraw->private = NULL;
+    }
+
+   return (void *) pdp;
+}
+
+static __DRIdrawable *driGetDrawable(Display *dpy, GLXDrawable draw,
+                                        void *screenPrivate)
+{
+    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+    /*
+    ** Make sure this routine returns NULL if the drawable is not bound
+    ** to a direct rendering context!
+    */
+    return __driFindDrawable(psp->drawHash, draw);
+}
+
+static void driDestroyDrawable(Display *dpy, void *drawablePrivate)
+{
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
+    __DRIscreenPrivate *psp = pdp->driScreenPriv;
+    int scrn = psp->myNum;
+
+    if (pdp) {
+        (*psp->DriverAPI.DestroyBuffer)(pdp);
+       if ((*window_exists)(dpy, pdp->draw))
+           (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+       if (pdp->pClipRects) {
+           Xfree(pdp->pClipRects);
+           pdp->pClipRects = NULL;
+       }
+       if (pdp->pBackClipRects) {
+           Xfree(pdp->pBackClipRects);
+           pdp->pBackClipRects = NULL;
+       }
+       Xfree(pdp);
+    }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions                             */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param contextPrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate)
+{
+    __DRIcontextPrivate  *pcp   = (__DRIcontextPrivate *) contextPrivate;
+
+    if (pcp) {
+       (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+       __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+       (void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
+       Xfree(pcp);
+    }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ * 
+ * \param dpy           The display handle.
+ * \param modes         Mode used to create the new context.
+ * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
+ *                      type likely to ever be supported for direct-rendering.
+ * \param sharedPrivate The shared context dependent methods or \c NULL if
+ *                      non-existent.
+ * \param pctx          DRI context to receive the context dependent methods.
+ *
+ * \returns An opaque pointer to the per-context private information on
+ *          success, or \c NULL on failure.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure.  It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static void *
+driCreateNewContext(Display *dpy, const __GLcontextModes *modes,
+                   int render_type, void *sharedPrivate, __DRIcontext *pctx)
+{
+    __DRIscreen *pDRIScreen;
+    __DRIcontextPrivate *pcp;
+    __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
+    __DRIscreenPrivate *psp;
+    void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
+
+    pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
+    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       /* ERROR!!! */
+       return NULL;
+    } 
+
+    psp = (__DRIscreenPrivate *)pDRIScreen->private;
+
+    pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
+    if (!pcp) {
+       return NULL;
+    }
+
+    if (! (*create_context_with_config)(dpy, modes->screen, modes->fbconfigID,
+                                       &pcp->contextID, &pcp->hHWContext)) {
+       Xfree(pcp);
+       return NULL;
+    }
+
+    pcp->display = dpy;
+    pcp->driScreenPriv = psp;
+    pcp->driDrawablePriv = NULL;
+
+    /* When the first context is created for a screen, initialize a "dummy"
+     * context.
+     */
+
+    if (!psp->dummyContextPriv.driScreenPriv) {
+        psp->dummyContextPriv.contextID = 0;
+        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
+        psp->dummyContextPriv.driScreenPriv = psp;
+        psp->dummyContextPriv.driDrawablePriv = NULL;
+        psp->dummyContextPriv.driverPrivate = NULL;
+       /* No other fields should be used! */
+    }
+
+    pctx->destroyContext = driDestroyContext;
+    pctx->bindContext    = driBindContext;
+    pctx->unbindContext  = driUnbindContext;
+    if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
+        pctx->bindContext2   = driBindContext2;
+        pctx->unbindContext2 = driUnbindContext2;
+    }
+
+    if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
+        (void)XF86DRIDestroyContext(dpy, modes->screen, pcp->contextID);
+        Xfree(pcp);
+        return NULL;
+    }
+
+    __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+
+    return pcp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Create the per-drawable private driver information.
+ * 
+ * \param dpy the display handle.
+ * \param vis the visual information.
+ * \param sharedPrivate the shared context dependent methods or \c NULL if
+ *                      non-existent.
+ * \param pctx will receive the context dependent methods.
+ *
+ * \returns a opaque pointer to the per-context private information on success, or \c NULL
+ * on failure.
+ * 
+ * \deprecated
+ * This function has been replaced by \c driCreateNewContext.  In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL.  Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure.  It
+ * gets the visual, converts it into a __GLcontextModesRec and passes it
+ * to __DriverAPIRec::CreateContext to create the context.
+ */
+static void *driCreateContext(Display *dpy, XVisualInfo *vis,
+                              void *sharedPrivate, __DRIcontext *pctx)
+{
+    __DRIscreen *pDRIScreen;
+    const __GLcontextModes *modes;
+
+    pDRIScreen = __glXFindDRIScreen(dpy, vis->screen);
+    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       /* ERROR!!! */
+       return NULL;
+    } 
+
+
+    /* Setup a __GLcontextModes struct corresponding to vis->visualid
+     * and create the rendering context.
+     */
+
+    modes = findConfigMode(dpy, vis->screen, vis->visualid, pDRIScreen);
+    return (modes == NULL) 
+       ? NULL
+       : driCreateNewContext( dpy, modes, GLX_RGBA_TYPE,
+                              sharedPrivate, pctx );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions                              */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param screenPrivate opaque pointer to the per-screen private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
+{
+    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+    if (psp) {
+       /* No interaction with the X-server is possible at this point.  This
+        * routine is called after XCloseDisplay, so there is no protocol
+        * stream open to the X-server anymore.
+        */
+
+       if (psp->DriverAPI.DestroyScreen)
+           (*psp->DriverAPI.DestroyScreen)(psp);
+
+       (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+       (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+       Xfree(psp->pDevPriv);
+       (void)drmClose(psp->fd);
+       if ( psp->modes != NULL ) {
+           _gl_context_modes_destroy( psp->modes );
+       }
+       Xfree(psp);
+    }
+}
+
+
+/**
+ * Utility function used to create a new driver-private screen structure.
+ * 
+ * \param dpy   Display pointer
+ * \param scrn  Index of the screen
+ * \param psc   DRI screen data (not driver private)
+ * \param modes Linked list of known display modes.  This list is, at a
+ *              minimum, a list of modes based on the current display mode.
+ *              These roughly match the set of available X11 visuals, but it
+ *              need not be limited to X11!  The calling libGL should create
+ *              a list that will inform the driver of the current display
+ *              mode (i.e., color buffer depth, depth buffer depth, etc.).
+ * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
+ *                    all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ *                     framebuffer.
+ * \param pSAREA       Pointer the the SAREA.
+ * \param fd           Device handle for the DRM.
+ * \param internal_api_version  Version of the internal interface between the
+ *                              driver and libGL.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ */
+__DRIscreenPrivate *
+__driUtilCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                        __GLcontextModes * modes,
+                        const __DRIversion * ddx_version,
+                        const __DRIversion * dri_version,
+                        const __DRIversion * drm_version,
+                        const __DRIframebuffer * frame_buffer,
+                        drmAddress pSAREA,
+                        int fd,
+                        int internal_api_version,
+                        const struct __DriverAPIRec *driverAPI)
+{
+    __DRIscreenPrivate *psp;
+
+
+    window_exists = (PFNGLXWINDOWEXISTSPROC)
+       glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
+
+    if ( window_exists == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+       fprintf( stderr, "libGL error: libGL.so version (%08u) is too old.  "
+                "20021128 or later is required.\n", internal_api_version );
+       return NULL;
+#else
+       window_exists = (PFNGLXWINDOWEXISTSPROC) __driWindowExists;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+    }
+
+    create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+       glXGetProcAddress( (const GLubyte *) "__glXCreateContextWithConfig" );
+    if ( create_context_with_config == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+       fprintf( stderr, "libGL error: libGL.so version (%08u) is too old.  "
+                "20031201 or later is required.\n", internal_api_version );
+       return NULL;
+#else
+       create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+           fake_XF86DRICreateContextWithConfig;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+    }
+       
+    api_ver = internal_api_version;
+
+    psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
+    if (!psp) {
+       return NULL;
+    }
+
+    /* Create the hash table */
+    psp->drawHash = drmHashCreate();
+    if ( psp->drawHash == NULL ) {
+       Xfree( psp );
+       return NULL;
+    }
+
+    psp->display = dpy;
+    psp->myNum = scrn;
+    psp->psc = psc;
+    psp->modes = modes;
+
+    /*
+    ** NOT_DONE: This is used by the X server to detect when the client
+    ** has died while holding the drawable lock.  The client sets the
+    ** drawable lock to this value.
+    */
+    psp->drawLockID = 1;
+
+    psp->drmMajor = drm_version->major;
+    psp->drmMinor = drm_version->minor;
+    psp->drmPatch = drm_version->patch;
+    psp->ddxMajor = ddx_version->major;
+    psp->ddxMinor = ddx_version->minor;
+    psp->ddxPatch = ddx_version->patch;
+    psp->driMajor = dri_version->major;
+    psp->driMinor = dri_version->minor;
+    psp->driPatch = dri_version->patch;
+
+    /* install driver's callback functions */
+    memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
+
+    psp->pSAREA = pSAREA;
+
+    psp->pFB = frame_buffer->base;
+    psp->fbSize = frame_buffer->size;
+    psp->fbStride = frame_buffer->stride;
+    psp->fbWidth = frame_buffer->width;
+    psp->fbHeight = frame_buffer->height;
+    psp->devPrivSize = frame_buffer->dev_priv_size;
+    psp->pDevPriv = frame_buffer->dev_priv;
+
+    psp->fd = fd;
+
+    /*
+    ** Do not init dummy context here; actual initialization will be
+    ** done when the first DRI context is created.  Init screen priv ptr
+    ** to NULL to let CreateContext routine that it needs to be inited.
+    */
+    psp->dummyContextPriv.driScreenPriv = NULL;
+
+    psc->destroyScreen     = driDestroyScreen;
+#ifndef DRI_NEW_INTERFACE_ONLY
+    psc->createContext     = driCreateContext;
+#else
+    psc->createConteext    = NULL;
+#endif
+    psc->createNewDrawable = driCreateNewDrawable;
+    psc->getDrawable       = driGetDrawable;
+    if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+        psc->getMSC        = driGetMSC;
+
+       if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
+           psc->createNewContext = driCreateNewContext;
+       }
+    }
+
+    if ( (psp->DriverAPI.InitDriver != NULL)
+        && !(*psp->DriverAPI.InitDriver)(psp) ) {
+       Xfree( psp );
+       return NULL;
+    }
+
+
+    return psp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Utility function used to create a new driver-private screen structure.
+ * 
+ * \param dpy        Display pointer.
+ * \param scrn       Index of the screen.
+ * \param psc        DRI screen data (not driver private)
+ * \param numConfigs Number of visual configs pointed to by \c configs.
+ * \param configs    Array of GLXvisualConfigs exported by the 2D driver.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ * 
+ * \deprecated
+ * This function has been replaced by \c __driUtilCreateNewScreen.  In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL.  Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ */
+__DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                      int numConfigs, __GLXvisualConfig *configs,
+                      const struct __DriverAPIRec *driverAPI)
+{
+    int directCapable;
+    __DRIscreenPrivate *psp = NULL;
+    drmHandle hSAREA;
+    drmAddress pSAREA;
+    char *BusID;
+    __GLcontextModes *modes;
+    __GLcontextModes *temp;
+    int   i;
+    __DRIversion   ddx_version;
+    __DRIversion   dri_version;
+    __DRIversion   drm_version;
+    __DRIframebuffer  framebuffer;
+    int   fd = -1;
+    int   status;
+    const char * err_msg;
+    const char * err_extra;
+
+
+    if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)
+       || !directCapable) {
+       return NULL;
+    }
+
+
+    /* Create the linked list of context modes, and populate it with the
+     * GLX visual information passed in by libGL.
+     */
+
+    modes = _gl_context_modes_create( numConfigs, sizeof(__GLcontextModes) );
+    if ( modes == NULL ) {
+       return NULL;
+    }
+
+    temp = modes;
+    for ( i = 0 ; i < numConfigs ; i++ ) {
+       assert( temp != NULL );
+       _gl_copy_visual_to_context_mode( temp, & configs[i] );
+       temp->screen = scrn;
+
+       temp = temp->next;
+    }
+
+    err_msg = "XF86DRIOpenConnection";
+    err_extra = NULL;
+
+    if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+       fd = drmOpen(NULL,BusID);
+       Xfree(BusID); /* No longer needed */
+
+       err_msg = "open DRM";
+       err_extra = strerror( -fd );
+
+       if (fd >= 0) {
+           drmMagic magic;
+
+           err_msg = "drmGetMagic";
+           err_extra = NULL;
+
+           if (!drmGetMagic(fd, &magic)) {
+               drmVersionPtr 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;
+               }
+
+               err_msg = "XF86DRIAuthConnection";
+               if (XF86DRIAuthConnection(dpy, scrn, magic)) {
+                   char *driverName;
+
+                   /*
+                    * Get device name (like "tdfx") and the ddx version numbers.
+                    * We'll check the version in each DRI driver's "createScreen"
+                    * function.
+                    */
+                   err_msg = "XF86DRIGetClientDriverName";
+                   if (XF86DRIGetClientDriverName(dpy, scrn,
+                                                  &ddx_version.major,
+                                                  &ddx_version.minor,
+                                                  &ddx_version.patch,
+                                                  &driverName)) {
+
+                       /* No longer needed. */
+                       Xfree( driverName );
+
+                       /*
+                        * Get the DRI X extension version.
+                        */
+                       err_msg = "XF86DRIQueryVersion";
+                       if (XF86DRIQueryVersion(dpy,
+                                               &dri_version.major,
+                                               &dri_version.minor,
+                                               &dri_version.patch)) {
+                           drmHandle  hFB;
+                           int        junk;
+
+                           /*
+                            * 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.
+                            */
+                           err_msg = "XF86DRIGetDeviceInfo";
+                           if (XF86DRIGetDeviceInfo(dpy, scrn,
+                                                    &hFB,
+                                                    &junk,
+                                                    &framebuffer.size,
+                                                    &framebuffer.stride,
+                                                    &framebuffer.dev_priv_size,
+                                                    &framebuffer.dev_priv)) {
+                               framebuffer.width = DisplayWidth(dpy, scrn);
+                               framebuffer.height = DisplayHeight(dpy, scrn);
+
+                               /*
+                                * Map the framebuffer region.
+                                */
+                               status = drmMap(fd, hFB, framebuffer.size, 
+                                               (drmAddressPtr)&framebuffer.base);
+                               
+                               err_msg = "drmMap of framebuffer";
+                               err_extra = strerror( -status );
+
+                               if ( status == 0 ) {
+                                   /*
+                                    * Map the SAREA region.  Further mmap regions may be setup in
+                                    * each DRI driver's "createScreen" function.
+                                    */
+                                   status = drmMap(fd, hSAREA, SAREA_MAX, 
+                                                   &pSAREA);
+
+                                   err_msg = "drmMap of sarea";
+                                   err_extra = strerror( -status );
+
+                                   if ( status == 0 ) {
+                                       PFNGLXGETINTERNALVERSIONPROC get_ver;
+
+                                       get_ver = (PFNGLXGETINTERNALVERSIONPROC)
+                                           glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
+
+                                       err_msg = "InitDriver";
+                                       err_extra = NULL;
+                                       psp = __driUtilCreateNewScreen( dpy, scrn, psc, modes,
+                                                                       & ddx_version,
+                                                                       & dri_version,
+                                                                       & drm_version,
+                                                                       & framebuffer,
+                                                                       pSAREA,
+                                                                       fd,
+                                                                       (get_ver != NULL) ? (*get_ver)() : 1,
+                                                                       driverAPI );
+                                   }
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+       }
+    }
+
+    if ( psp == NULL ) {
+       if ( pSAREA != MAP_FAILED ) {
+           (void)drmUnmap(pSAREA, SAREA_MAX);
+       }
+
+       if ( framebuffer.base != MAP_FAILED ) {
+           (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
+       }
+
+       if ( framebuffer.dev_priv != NULL ) {
+           Xfree(framebuffer.dev_priv);
+       }
+
+       if ( fd >= 0 ) {
+           (void)drmClose(fd);
+       }
+
+       if ( modes != NULL ) {
+           _gl_context_modes_destroy( modes );
+       }
+
+       (void)XF86DRICloseConnection(dpy, scrn);
+
+       if ( err_extra != NULL ) {
+           fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
+                   err_extra);
+       }
+       else {
+           fprintf(stderr, "libGL error: %s failed\n", err_msg );
+       }
+
+        fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+    }
+
+    return psp;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+/**
+ * Compare the current GLX API version with a driver supplied required version.
+ * 
+ * The minimum required version is compared with the API version exported by
+ * the \c __glXGetInternalVersion function (in libGL.so).
+ * 
+ * \param   required_version Minimum required internal GLX API version.
+ * \return  A tri-value return, as from strcmp is returned.  A value less
+ *          than, equal to, or greater than zero will be returned if the
+ *          internal GLX API version is less than, equal to, or greater
+ *          than \c required_version.
+ *
+ * \sa __glXGetInternalVersion().
+ */
+int driCompareGLXAPIVersion( GLuint required_version )
+{
+   if ( api_ver > required_version ) {
+      return 1;
+   }
+   else if ( api_ver == required_version ) {
+      return 0;
+   }
+
+   return -1;
+}
+
+
+static int
+driQueryFrameTracking( Display * dpy, void * priv,
+                      int64_t * sbc, int64_t * missedFrames,
+                      float * lastMissedUsage, float * usage )
+{
+   static PFNGLXGETUSTPROC   get_ust;
+   __DRIswapInfo   sInfo;
+   int             status;
+   int64_t         ust;
+   __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
+
+   if ( get_ust == NULL ) {
+      get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
+   }
+
+   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
+   if ( status == 0 ) {
+      *sbc = sInfo.swap_count;
+      *missedFrames = sInfo.swap_missed_count;
+      *lastMissedUsage = sInfo.swap_missed_usage;
+
+      (*get_ust)( & ust );
+      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
+   }
+
+   return status;
+}
+
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ * 
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ *            \f$p = t_d / (i * t_r)\f$
+ * 
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ * 
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param   dPriv  Pointer to the private drawable structure.
+ * \return  If less than a single swap interval time period was required
+ *          between GLX buffer swaps, a number greater than 0 and less than
+ *          1.0 is returned.  If exactly one swap interval time period is
+ *          required, 1.0 is returned, and if more than one is required then
+ *          a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ * 
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ *       be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
+                      int64_t current_ust )
+{
+   static PFNGLXGETMSCRATEOMLPROC get_msc_rate = NULL;
+   int32_t   n;
+   int32_t   d;
+   int       interval;
+   float     usage = 1.0;
+
+
+   if ( get_msc_rate == NULL ) {
+      get_msc_rate = (PFNGLXGETMSCRATEOMLPROC)
+         glXGetProcAddress( (const GLubyte *) "glXGetMscRateOML" );
+   }
+   
+   if ( (get_msc_rate != NULL)
+       && get_msc_rate( dPriv->display, dPriv->draw, &n, &d ) ) {
+      interval = (dPriv->pdraw->swap_interval != 0)
+         ? dPriv->pdraw->swap_interval : 1;
+
+
+      /* We want to calculate
+       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
+       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
+       * dPriv->swap_ust.  interval has already been calculated.
+       *
+       * The only tricky part is us_per_refresh.  us_per_refresh is
+       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
+       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
+       * the denominator of the final calculation, we calculate
+       * (interval * 1000000 * d) and move n into the numerator.
+       */
+
+      usage = (current_ust - last_swap_ust);
+      usage *= n;
+      usage /= (interval * d);
+      usage /= 1000000.0;
+   }
+   
+   return usage;
+}
+
+/*@}*/
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/mesa/drivers/dri/dri_client/dri_util.h b/src/mesa/drivers/dri/dri_client/dri_util.h
new file mode 100644 (file)
index 0000000..f189b5a
--- /dev/null
@@ -0,0 +1,607 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define CAPI  /* XXX this should be globally defined somewhere */
+
+#include <inttypes.h>
+#include "glxclient.h"           /* for GLXDrawable */
+/* temporary */
+/* typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); */
+#include "xf86dri.h"             /* for XF86DRIClipRectPtr */
+#include "sarea.h"               /* for XF86DRISAREAPtr */
+#include "GL/internal/glcore.h"  /* for __GLcontextModes */
+
+
+typedef struct __DRIdisplayPrivateRec  __DRIdisplayPrivate;
+typedef struct __DRIscreenPrivateRec   __DRIscreenPrivate;
+typedef struct __DRIcontextPrivateRec  __DRIcontextPrivate;
+typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate;
+typedef struct __DRIswapInfoRec        __DRIswapInfo;
+
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv)              \
+    do {                                                        \
+       if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) {     \
+           __driUtilUpdateDrawableInfo(pDrawPriv);             \
+       }                                                       \
+    } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawablePrivate::pStamp and __DRIdrawablePrivate::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \
+do {                                                                    \
+    while (*(pdp->pStamp) != pdp->lastStamp) {                          \
+       DRM_UNLOCK(psp->fd, &psp->pSAREA->lock,                         \
+                  pdp->driContextPriv->hHWContext);                    \
+                                                                        \
+       DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);     \
+       DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
+       DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);   \
+                                                                        \
+       DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock,                     \
+                      pdp->driContextPriv->hHWContext);                \
+    }                                                                   \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ * 
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+    /** 
+     * Driver initialization callback
+     */
+    GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
+    
+    /**
+     * Screen destruction callback
+     */
+    void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
+
+    /**
+     * Context creation callback
+     */                    
+    GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+                               __DRIcontextPrivate *driContextPriv,
+                               void *sharedContextPrivate);
+
+    /**
+     * Context destruction callback
+     */
+    void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
+
+    /**
+     * Buffer (drawable) creation callback
+     */
+    GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
+                              __DRIdrawablePrivate *driDrawPriv,
+                              const __GLcontextModes *glVis,
+                              GLboolean pixmapBuffer);
+    
+    /**
+     * Buffer (drawable) destruction callback
+     */
+    void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
+
+    /**
+     * Buffer swapping callback 
+     */
+    void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
+
+    /**
+     * Context activation callback
+     */
+    GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
+                             __DRIdrawablePrivate *driDrawPriv,
+                             __DRIdrawablePrivate *driReadPriv);
+
+    /**
+     * Context unbinding callback
+     */
+    GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
+  
+    /**
+     * Full screen mode opening callback.
+     * 
+     * \deprecated
+     * Full screen functionality is no longer used by DRI.  Drivers should
+     * simply install a function returning \c GL_TRUE for backwards
+     * compatability.
+     *
+     * \todo
+     * Nothing calls this function anymore.  Since this data structure is only
+     * accessed with in the driver (i.e., libGL never sees it), we need to
+     * remove the other cases that set this field and remove the field.
+     */
+    GLboolean (*OpenFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+    /**
+     * Full screen mode closing callback.
+     *
+     * \deprecated
+     * Full screen functionality is no longer used by DRI.  Drivers should
+     * simply install a function returning \c GL_TRUE for backwards
+     * compatability.
+     *
+     * \todo
+     * Nothing calls this function anymore.  Since this data structure is only
+     * accessed with in the driver (i.e., libGL never sees it), we need to
+     * remove the other cases that set this field and remove the field.
+     */
+    GLboolean (*CloseFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+    /**
+     * Retrieves statistics about buffer swap operations.  Required if
+     * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+     */
+    int (*GetSwapInfo)( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+
+    /**
+     * Required if GLX_SGI_video_sync or GLX_OML_sync_control is
+     * supported.
+     */
+    int (*GetMSC)( __DRIscreenPrivate * priv, int64_t * count );
+
+    /**
+     * These are required if GLX_OML_sync_control is supported.
+     */
+    /*@{*/
+    int (*WaitForMSC)( __DRIdrawablePrivate *priv, int64_t target_msc, 
+                      int64_t divisor, int64_t remainder,
+                      int64_t * msc );
+    int (*WaitForSBC)( __DRIdrawablePrivate *priv, int64_t target_sbc,
+                      int64_t * msc, int64_t * sbc );
+
+    int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+                              int64_t divisor, int64_t remainder );
+    /*@}*/
+};
+
+
+struct __DRIswapInfoRec {
+    /** 
+     * Number of swapBuffers operations that have been *completed*. 
+     */
+    uint64_t  swap_count;
+
+    /**
+     * Unadjusted system time of the last buffer swap.  This is the time
+     * when the swap completed, not the time when swapBuffers was called.
+     */
+    int64_t   swap_ust;
+
+    /**
+     * Number of swap operations that occurred after the swap deadline.  That
+     * is if a swap happens more than swap_interval frames after the previous
+     * swap, it has missed its deadline.  If swap_interval is 0, then the
+     * swap deadline is 1 frame after the previous swap.
+     */
+    uint64_t  swap_missed_count;
+
+    /**
+     * Amount of time used by the last swap that missed its deadline.  This
+     * is calculated as (__glXGetUST() - swap_ust) / (swap_interval * 
+     * time_for_single_vrefresh)).  If the actual value of swap_interval is
+     * 0, then 1 is used instead.  If swap_missed_count is non-zero, this
+     * should be greater-than 1.0.
+     */
+    float     swap_missed_usage;
+};
+
+
+typedef Bool (GetDrawableInfo)( Display *dpy, int scrn, Drawable draw,
+    unsigned int * index, unsigned int * stamp,
+    int * x, int * y, int * width, int * height,
+    int * numClipRects, XF86DRIClipRectPtr * pClipRects,
+    int * backX, int * backY,
+    int * numBackClipRects, XF86DRIClipRectPtr * pBackClipRects );
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawablePrivateRec {
+    /**
+     * Kernel drawable handle
+     */
+    drmDrawable hHWDrawable;
+
+    /**
+     * Driver's private drawable information.  
+     *
+     * This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * X's drawable ID associated with this private drawable.
+     */
+    GLXDrawable draw;
+    __DRIdrawable *pdraw;
+
+    /**
+     * Reference count for number of context's currently bound to this
+     * drawable.  
+     *
+     * Once it reaches zero, the drawable can be destroyed.
+     *
+     * \note This behavior will change with GLX 1.3.
+     */
+    int refcount;
+
+    /**
+     * Index of this drawable information in the SAREA.
+     */
+    unsigned int index;
+
+    /**
+     * Pointer to the "drawable has changed ID" stamp in the SAREA.
+     */
+    unsigned int *pStamp;
+
+    /**
+     * Last value of the stamp.
+     *
+     * If this differs from the value stored at __DRIdrawablePrivate::pStamp,
+     * then the drawable information has been modified by the X server, and the
+     * drawable information (below) should be retrieved from the X server.
+     */
+    unsigned int lastStamp;
+
+    /**
+     * \name Drawable 
+     *
+     * Drawable information used in software fallbacks.
+     */
+    /*@{*/
+    int x;
+    int y;
+    int w;
+    int h;
+    int numClipRects;
+    XF86DRIClipRectPtr pClipRects;
+    /*@}*/
+
+    /**
+     * \name Back and depthbuffer
+     *
+     * Information about the back and depthbuffer where different from above.
+     */
+    /*@{*/
+    int backX;
+    int backY;
+    int backClipRectType;
+    int numBackClipRects;
+    XF86DRIClipRectPtr pBackClipRects;
+    /*@}*/
+
+    /**
+     * Pointer to context to which this drawable is currently bound.
+     */
+    __DRIcontextPrivate *driContextPriv;
+
+    /**
+     * Pointer to screen on which this drawable was created.
+     */
+    __DRIscreenPrivate *driScreenPriv;
+
+    /**
+     * \name Display and screen information.
+     * 
+     * Basically just need these for when the locking code needs to call
+     * __driUtilUpdateDrawableInfo() which calls XF86DRIGetDrawableInfo().
+     */
+    /*@{*/
+    Display *display;
+    int screen;
+    /*@}*/
+
+    /**
+     * Called via glXSwapBuffers().
+     */
+    void (*swapBuffers)( __DRIdrawablePrivate *dPriv );
+
+    /**
+     * Get information about the location, size, and clip rects of the
+     * drawable within the display.
+     */
+    GetDrawableInfo * getInfo;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextPrivateRec {
+    /**
+     * Kernel context handle used to access the device lock.
+     */
+    XID contextID;
+
+    /**
+     * Kernel context handle used to access the device lock.
+     */
+    drmContext hHWContext;
+
+    /**
+     * Device driver's private context data.  This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * This context's display pointer.
+     */
+    Display *display;
+
+    /**
+     * Pointer to drawable currently bound to this context.
+     */
+    __DRIdrawablePrivate *driDrawablePriv;
+
+    /**
+     * Pointer to screen on which this context was created.
+     */
+    __DRIscreenPrivate *driScreenPriv;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenPrivateRec {
+    /**
+     * Display for this screen
+     */
+    Display *display;
+
+    /**
+     * Current screen's number
+     */
+    int myNum;
+
+    /**
+     * Callback functions into the hardware-specific DRI driver code.
+     */
+    struct __DriverAPIRec DriverAPI;
+
+    /**
+     * \name DDX version
+     * DDX / 2D driver version information.
+     * \todo Replace these fields with a \c __DRIversionRec.
+     */
+    /*@{*/
+    int ddxMajor;
+    int ddxMinor;
+    int ddxPatch;
+    /*@}*/
+
+    /**
+     * \name DRI version
+     * DRI X extension version information.
+     * \todo Replace these fields with a \c __DRIversionRec.
+     */
+    /*@{*/
+    int driMajor;
+    int driMinor;
+    int driPatch;
+    /*@}*/
+
+    /**
+     * \name DRM version
+     * DRM (kernel module) version information.
+     * \todo Replace these fields with a \c __DRIversionRec.
+     */
+    /*@{*/
+    int drmMajor;
+    int drmMinor;
+    int drmPatch;
+    /*@}*/
+
+    /**
+     * ID used when the client sets the drawable lock.
+     *
+     * The X server uses this value to detect if the client has died while
+     * holding the drawable lock.
+     */
+    int drawLockID;
+
+    /**
+     * File descriptor returned when the kernel device driver is opened.
+     * 
+     * Used to:
+     *   - authenticate client to kernel
+     *   - map the frame buffer, SAREA, etc.
+     *   - close the kernel device driver
+     */
+    int fd;
+
+    /**
+     * SAREA pointer 
+     *
+     * Used to access:
+     *   - the device lock
+     *   - the device-independent per-drawable and per-context(?) information
+     */
+    XF86DRISAREAPtr pSAREA;
+
+    /**
+     * \name Direct frame buffer access information 
+     * Used for software fallbacks.
+     */
+    /*@{*/
+    unsigned char *pFB;
+    int fbSize;
+    int fbOrigin;
+    int fbStride;
+    int fbWidth;
+    int fbHeight;
+    int fbBPP;
+    /*@}*/
+
+    /**
+     * \name Device-dependent private information (stored in the SAREA).
+     *
+     * This data is accessed by the client driver only.
+     */
+    /*@{*/
+    void *pDevPriv;
+    int devPrivSize;
+    /*@}*/
+
+    /**
+     * Dummy context to which drawables are bound when not bound to any
+     * other context. 
+     *
+     * A dummy hHWContext is created for this context, and is used by the GL
+     * core when a hardware lock is required but the drawable is not currently
+     * bound (e.g., potentially during a SwapBuffers request).  The dummy
+     * context is created when the first "real" context is created on this
+     * screen.
+     */
+    __DRIcontextPrivate dummyContextPriv;
+
+    /**
+     * Hash table to hold the drawable information for this screen.
+     */
+    void *drawHash;
+
+    /**
+     * Device-dependent private information (not stored in the SAREA).
+     * 
+     * This pointer is never touched by the DRI layer.
+     */
+    void *private;
+
+    /**
+     * GLX visuals / FBConfigs for this screen.  These are stored as a
+     * linked list.
+     * 
+     * \note
+     * This field is \b only used in conjunction with the old interfaces.  If
+     * the new interfaces are used, this field will be set to \c NULL and will
+     * not be dereferenced.
+     */
+    __GLcontextModes *modes;
+
+    /**
+     * Pointer back to the \c __DRIscreen that contains this structure.
+     */
+
+    __DRIscreen *psc;
+};
+
+
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
+
+
+extern __DRIscreenPrivate * __driUtilCreateNewScreen( Display *dpy,
+    int scrn, __DRIscreen *psc, __GLcontextModes * modes,
+    const __DRIversion * ddx_version, const __DRIversion * dri_version,
+    const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer,
+    drmAddress pSAREA, int fd, int internal_api_version,
+    const struct __DriverAPIRec *driverAPI );
+
+extern __DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                      int numConfigs, __GLXvisualConfig *config,
+                      const struct __DriverAPIRec *driverAPI);
+
+/** This must be implemented in each driver
+ * \deprecated
+ */
+extern void *
+__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                  int numConfigs, __GLXvisualConfig *config);
+
+/** This must be implemented in each driver */
+extern void * __driCreateNewScreen( Display *dpy, int scrn, __DRIscreen *psc,
+    const __GLcontextModes * modes,
+    const __DRIversion * ddx_version, const __DRIversion * dri_version,
+    const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer,
+    drmAddress pSAREA, int fd, int internal_api_version,
+     __GLcontextModes ** driver_modes );
+
+/** This is optionally implemented in each driver */
+extern void
+__driRegisterExtensions( void );
+
+/* Test the version of the internal GLX API.  Returns a value like strcmp. */
+extern int
+driCompareGLXAPIVersion( GLuint required_version );
+
+extern float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv,
+                      int64_t last_swap_ust, int64_t current_ust );
+
+#endif /* GLX_DIRECT_RENDERING */
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/dri_client/drm.h b/src/mesa/drivers/dri/dri_client/drm.h
new file mode 100644 (file)
index 0000000..ceba242
--- /dev/null
@@ -0,0 +1,680 @@
+/**
+ * \file drm.h 
+ * Header for the Direct Rendering Manager
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * \par Acknowledgments:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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
+ * VA LINUX SYSTEMS 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.
+ */
+
+
+#ifndef _DRM_H_
+#define _DRM_H_
+
+#if defined(__linux__)
+#include <linux/config.h>
+#include <asm/ioctl.h>         /* For _IO* macros */
+#define DRM_IOCTL_NR(n)                _IOC_NR(n)
+#define DRM_IOC_VOID           _IOC_NONE
+#define DRM_IOC_READ           _IOC_READ
+#define DRM_IOC_WRITE          _IOC_WRITE
+#define DRM_IOC_READWRITE      _IOC_READ|_IOC_WRITE
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) && defined(IN_MODULE)
+/* Prevent name collision when including sys/ioccom.h */
+#undef ioctl
+#include <sys/ioccom.h>
+#define ioctl(a,b,c)           xf86ioctl(a,b,c)
+#else
+#include <sys/ioccom.h>
+#endif /* __FreeBSD__ && xf86ioctl */
+#define DRM_IOCTL_NR(n)                ((n) & 0xff)
+#define DRM_IOC_VOID           IOC_VOID
+#define DRM_IOC_READ           IOC_OUT
+#define DRM_IOC_WRITE          IOC_IN
+#define DRM_IOC_READWRITE      IOC_INOUT
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#endif
+
+#define XFREE86_VERSION(major,minor,patch,snap) \
+               ((major << 16) | (minor << 8) | patch)
+
+#ifndef CONFIG_XFREE86_VERSION
+#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
+#endif
+
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+#define DRM_PROC_DEVICES "/proc/devices"
+#define DRM_PROC_MISC   "/proc/misc"
+#define DRM_PROC_DRM    "/proc/drm"
+#define DRM_DEV_DRM     "/dev/drm"
+#define DRM_DEV_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+#define DRM_DEV_UID     0
+#define DRM_DEV_GID     0
+#endif
+
+#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
+#ifdef __OpenBSD__
+#define DRM_MAJOR       81
+#endif
+#if defined(__linux__) || defined(__NetBSD__)
+#define DRM_MAJOR       226
+#endif
+#define DRM_MAX_MINOR   15
+#endif
+#define DRM_NAME       "drm"     /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER  5         /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER  22        /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10       /**< How much system ram can we lock? */
+
+#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+#define _DRM_LOCK_IS_HELD(lock)           ((lock) & _DRM_LOCK_HELD)
+#define _DRM_LOCK_IS_CONT(lock)           ((lock) & _DRM_LOCK_CONT)
+#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
+
+typedef unsigned long drm_handle_t;
+typedef unsigned int  drm_context_t;
+typedef unsigned int  drm_drawable_t;
+typedef unsigned int  drm_magic_t;
+
+
+/**
+ * Cliprect.
+ * 
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
+ * backwards-compatibility reasons.
+ */
+typedef struct drm_clip_rect {
+       unsigned short  x1;
+       unsigned short  y1;
+       unsigned short  x2;
+       unsigned short  y2;
+} drm_clip_rect_t;
+
+
+/**
+ * Texture region,
+ */
+typedef struct drm_tex_region {
+       unsigned char   next;
+       unsigned char   prev;
+       unsigned char   in_use;
+       unsigned char   padding;
+       unsigned int    age;
+} drm_tex_region_t;
+
+/**
+ * Hardware lock.
+ *
+ * The lock structure is a simple cache-line aligned integer.  To avoid
+ * processor bus contention on a multiprocessor system, there should not be any
+ * other data stored in the same cache line.
+ */
+typedef struct drm_hw_lock {
+       __volatile__ unsigned int lock;         /**< lock variable */
+       char                      padding[60];  /**< Pad to cache line */
+} drm_hw_lock_t;
+
+
+/**
+ * DRM_IOCTL_VERSION ioctl argument type.
+ * 
+ * \sa drmGetVersion().
+ */
+typedef struct drm_version {
+       int    version_major;     /**< Major version */
+       int    version_minor;     /**< Minor version */
+       int    version_patchlevel;/**< Patch level */
+       size_t name_len;          /**< Length of name buffer */
+       char   *name;             /**< Name of driver */
+       size_t date_len;          /**< Length of date buffer */
+       char   *date;             /**< User-space buffer to hold date */
+       size_t desc_len;          /**< Length of desc buffer */
+       char   *desc;             /**< User-space buffer to hold desc */
+} drm_version_t;
+
+
+/**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
+typedef struct drm_unique {
+       size_t unique_len;        /**< Length of unique */
+       char   *unique;           /**< Unique name for driver instantiation */
+} drm_unique_t;
+
+
+typedef struct drm_list {
+       int              count;   /**< Length of user-space structures */
+       drm_version_t    *version;
+} drm_list_t;
+
+
+typedef struct drm_block {
+       int              unused;
+} drm_block_t;
+
+
+/**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
+typedef struct drm_control {
+       enum {
+               DRM_ADD_COMMAND,
+               DRM_RM_COMMAND,
+               DRM_INST_HANDLER,
+               DRM_UNINST_HANDLER
+       }                func;
+       int              irq;
+} drm_control_t;
+
+
+/**
+ * Type of memory to map.
+ */
+typedef enum drm_map_type {
+       _DRM_FRAME_BUFFER   = 0,  /**< WC (no caching), no core dump */
+       _DRM_REGISTERS      = 1,  /**< no caching, no core dump */
+       _DRM_SHM            = 2,  /**< shared, cached */
+       _DRM_AGP            = 3,  /**< AGP/GART */
+       _DRM_SCATTER_GATHER = 4   /**< Scatter/gather memory for PCI DMA */
+} drm_map_type_t;
+
+
+/**
+ * Memory mapping flags.
+ */
+typedef enum drm_map_flags {
+       _DRM_RESTRICTED      = 0x01, /**< Cannot be mapped to user-virtual */
+       _DRM_READ_ONLY       = 0x02,
+       _DRM_LOCKED          = 0x04, /**< shared, cached, locked */
+       _DRM_KERNEL          = 0x08, /**< kernel requires access */
+       _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+       _DRM_CONTAINS_LOCK   = 0x20, /**< SHM page that contains lock */
+       _DRM_REMOVABLE       = 0x40  /**< Removable mapping */
+} drm_map_flags_t;
+
+
+typedef struct drm_ctx_priv_map {
+       unsigned int    ctx_id;  /**< Context requesting private mapping */
+       void            *handle; /**< Handle of map */
+} drm_ctx_priv_map_t;
+
+
+/**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
+typedef struct drm_map {
+       unsigned long   offset;  /**< Requested physical address (0 for SAREA)*/
+       unsigned long   size;    /**< Requested physical size (bytes) */
+       drm_map_type_t  type;    /**< Type of memory to map */
+       drm_map_flags_t flags;   /**< Flags */
+       void            *handle; /**< User-space: "Handle" to pass to mmap() */
+                                /**< Kernel-space: kernel-virtual address */
+       int             mtrr;    /**< MTRR slot used */
+                                /*   Private data */
+} drm_map_t;
+
+
+/**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
+typedef struct drm_client {
+       int             idx;    /**< Which client desired? */
+       int             auth;   /**< Is client authenticated? */
+       unsigned long   pid;    /**< Process ID */
+       unsigned long   uid;    /**< User ID */
+       unsigned long   magic;  /**< Magic */
+       unsigned long   iocs;   /**< Ioctl count */
+} drm_client_t;
+
+
+typedef enum {
+       _DRM_STAT_LOCK,
+       _DRM_STAT_OPENS,
+       _DRM_STAT_CLOSES,
+       _DRM_STAT_IOCTLS,
+       _DRM_STAT_LOCKS,
+       _DRM_STAT_UNLOCKS,
+       _DRM_STAT_VALUE,        /**< Generic value */
+       _DRM_STAT_BYTE,         /**< Generic byte counter (1024bytes/K) */
+       _DRM_STAT_COUNT,        /**< Generic non-byte counter (1000/k) */
+
+       _DRM_STAT_IRQ,          /**< IRQ */
+       _DRM_STAT_PRIMARY,      /**< Primary DMA bytes */
+       _DRM_STAT_SECONDARY,    /**< Secondary DMA bytes */
+       _DRM_STAT_DMA,          /**< DMA */
+       _DRM_STAT_SPECIAL,      /**< Special DMA (e.g., priority or polled) */
+       _DRM_STAT_MISSED        /**< Missed DMA opportunity */
+
+                               /* Add to the *END* of the list */
+} drm_stat_type_t;
+
+
+/**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
+typedef struct drm_stats {
+       unsigned long count;
+       struct {
+               unsigned long   value;
+               drm_stat_type_t type;
+       } data[15];
+} drm_stats_t;
+
+
+/**
+ * Hardware locking flags.
+ */
+typedef enum drm_lock_flags {
+       _DRM_LOCK_READY      = 0x01, /**< Wait until hardware is ready for DMA */
+       _DRM_LOCK_QUIESCENT  = 0x02, /**< Wait until hardware quiescent */
+       _DRM_LOCK_FLUSH      = 0x04, /**< Flush this context's DMA queue first */
+       _DRM_LOCK_FLUSH_ALL  = 0x08, /**< Flush all DMA queues first */
+                               /* These *HALT* flags aren't supported yet
+                                  -- they will be used to support the
+                                  full-screen DGA-like mode. */
+       _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+       _DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
+} drm_lock_flags_t;
+
+
+/**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ * 
+ * \sa drmGetLock() and drmUnlock().
+ */
+typedef struct drm_lock {
+       int              context;
+       drm_lock_flags_t flags;
+} drm_lock_t;
+
+
+/**
+ * DMA flags
+ *
+ * \warning 
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+typedef enum drm_dma_flags {         
+                                     /* Flags for DMA buffer dispatch */
+       _DRM_DMA_BLOCK        = 0x01, /**<
+                                      * Block until buffer dispatched.
+                                      * 
+                                      * \note The buffer may not yet have
+                                      * been processed by the hardware --
+                                      * getting a hardware lock with the
+                                      * hardware quiescent will ensure
+                                      * that the buffer has been
+                                      * processed.
+                                      */
+       _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+       _DRM_DMA_PRIORITY     = 0x04, /**< High priority dispatch */
+
+                                     /* Flags for DMA buffer request */
+       _DRM_DMA_WAIT         = 0x10, /**< Wait for free buffers */
+       _DRM_DMA_SMALLER_OK   = 0x20, /**< Smaller-than-requested buffers OK */
+       _DRM_DMA_LARGER_OK    = 0x40  /**< Larger-than-requested buffers OK */
+} drm_dma_flags_t;
+
+
+/**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
+typedef struct drm_buf_desc {
+       int           count;     /**< Number of buffers of this size */
+       int           size;      /**< Size in bytes */
+       int           low_mark;  /**< Low water mark */
+       int           high_mark; /**< High water mark */
+       enum {
+               _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+               _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+               _DRM_SG_BUFFER  = 0x04  /**< Scatter/gather memory buffer */
+       }             flags;
+       unsigned long agp_start; /**< 
+                                 * Start address of where the AGP buffers are
+                                 * in the AGP aperture
+                                 */
+} drm_buf_desc_t;
+
+
+/**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_info {
+       int            count;   /**< Entries in list */
+       drm_buf_desc_t *list;
+} drm_buf_info_t;
+
+
+/**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_free {
+       int            count;
+       int            *list;
+} drm_buf_free_t;
+
+
+/**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
+typedef struct drm_buf_pub {
+       int               idx;         /**< Index into the master buffer list */
+       int               total;       /**< Buffer size */
+       int               used;        /**< Amount of buffer in use (for DMA) */
+       void              *address;    /**< Address of buffer */
+} drm_buf_pub_t;
+
+
+/**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_map {
+       int           count;    /**< Length of the buffer list */
+       void          *virtual; /**< Mmap'd area in user-virtual */
+       drm_buf_pub_t *list;    /**< Buffer information */
+} drm_buf_map_t;
+
+
+/**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
+typedef struct drm_dma {
+       int             context;          /**< Context handle */
+       int             send_count;       /**< Number of buffers to send */
+       int             *send_indices;    /**< List of handles to buffers */
+       int             *send_sizes;      /**< Lengths of data to send */
+       drm_dma_flags_t flags;            /**< Flags */
+       int             request_count;    /**< Number of buffers requested */
+       int             request_size;     /**< Desired size for buffers */
+       int             *request_indices; /**< Buffer information */
+       int             *request_sizes;
+       int             granted_count;    /**< Number of buffers granted */
+} drm_dma_t;
+
+
+typedef enum {
+       _DRM_CONTEXT_PRESERVED = 0x01,
+       _DRM_CONTEXT_2DONLY    = 0x02
+} drm_ctx_flags_t;
+
+
+/**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
+typedef struct drm_ctx {
+       drm_context_t   handle;
+       drm_ctx_flags_t flags;
+} drm_ctx_t;
+
+
+/**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
+typedef struct drm_ctx_res {
+       int             count;
+       drm_ctx_t       *contexts;
+} drm_ctx_res_t;
+
+
+/**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
+typedef struct drm_draw {
+       drm_drawable_t  handle;
+} drm_draw_t;
+
+
+/**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
+typedef struct drm_auth {
+       drm_magic_t     magic;
+} drm_auth_t;
+
+
+/**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
+typedef struct drm_irq_busid {
+       int irq;        /**< IRQ number */
+       int busnum;     /**< bus number */
+       int devnum;     /**< device number */
+       int funcnum;    /**< function number */
+} drm_irq_busid_t;
+
+
+typedef enum {
+    _DRM_VBLANK_ABSOLUTE = 0x0,                /**< Wait for specific vblank sequence number */
+    _DRM_VBLANK_RELATIVE = 0x1,                /**< Wait for given number of vblanks */
+    _DRM_VBLANK_SIGNAL   = 0x40000000  /**< Send signal instead of blocking */
+} drm_vblank_seq_type_t;
+
+
+#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
+
+struct drm_wait_vblank_request {
+       drm_vblank_seq_type_t type;
+       unsigned int sequence;
+       unsigned long signal;
+};
+
+
+struct drm_wait_vblank_reply {
+       drm_vblank_seq_type_t type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+};
+
+
+/**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
+typedef union drm_wait_vblank {
+       struct drm_wait_vblank_request request;
+       struct drm_wait_vblank_reply reply;
+} drm_wait_vblank_t;
+
+
+/**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
+typedef struct drm_agp_mode {
+       unsigned long mode;     /**< AGP mode */
+} drm_agp_mode_t;
+
+
+/**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
+typedef struct drm_agp_buffer {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for binding / unbinding */
+       unsigned long type;     /**< Type of memory to allocate */
+        unsigned long physical; /**< Physical used by i810 */
+} drm_agp_buffer_t;
+
+
+/**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
+typedef struct drm_agp_binding {
+       unsigned long handle;   /**< From drm_agp_buffer */
+       unsigned long offset;   /**< In bytes -- will round to page boundary */
+} drm_agp_binding_t;
+
+
+/**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
+typedef struct drm_agp_info {
+       int            agp_version_major;
+       int            agp_version_minor;
+       unsigned long  mode;
+       unsigned long  aperture_base;  /* physical address */
+       unsigned long  aperture_size;  /* bytes */
+       unsigned long  memory_allowed; /* bytes */
+       unsigned long  memory_used;
+
+                               /* PCI information */
+       unsigned short id_vendor;
+       unsigned short id_device;
+} drm_agp_info_t;
+
+
+/**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
+typedef struct drm_scatter_gather {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
+/**
+ * DRM_IOCTL_SET_VERSION ioctl argument type.
+ */
+typedef struct drm_set_version {
+       int drm_di_major;
+       int drm_di_minor;
+       int drm_dd_major;
+       int drm_dd_minor;
+} drm_set_version_t;
+
+
+#define DRM_IOCTL_BASE                 'd'
+#define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,type)               _IOR(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOW(nr,type)               _IOW(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOWR(nr,type)              _IOWR(DRM_IOCTL_BASE,nr,type)
+
+#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, drm_version_t)
+#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, drm_unique_t)
+#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, drm_auth_t)
+#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, drm_irq_busid_t)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
+#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, drm_set_version_t)
+
+#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, drm_unique_t)
+#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, drm_auth_t)
+#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, drm_block_t)
+#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, drm_block_t)
+#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, drm_control_t)
+#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, drm_map_t)
+#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, drm_buf_desc_t)
+#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, drm_buf_desc_t)
+#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, drm_buf_info_t)
+#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, drm_buf_map_t)
+#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, drm_buf_free_t)
+
+#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, drm_map_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, drm_ctx_priv_map_t)
+#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, drm_ctx_priv_map_t)
+
+#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, drm_ctx_t)
+#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, drm_ctx_t)
+#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, drm_ctx_t)
+#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, drm_ctx_t)
+#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, drm_ctx_t)
+#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, drm_ctx_t)
+#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, drm_ctx_res_t)
+#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, drm_draw_t)
+#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, drm_draw_t)
+#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, drm_dma_t)
+#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, drm_lock_t)
+#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, drm_lock_t)
+#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, drm_lock_t)
+
+#define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
+#define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
+#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, drm_agp_mode_t)
+#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, drm_agp_info_t)
+#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
+
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
+
+#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, drm_wait_vblank_t)
+
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x79.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
+#define DRM_COMMAND_BASE                0x40
+
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/glcontextmodes.c b/src/mesa/drivers/dri/dri_client/glcontextmodes.c
new file mode 100644 (file)
index 0000000..784ad30
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * (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>
+ */
+
+#include <X11/X.h>
+#include <GL/glx.h>
+#include "GL/glxint.h"
+
+#ifdef XFree86Server
+# include "GL/glx_ansic.h"
+extern void * __glXMalloc( size_t size );
+extern void __glXFree( void * ptr );
+# define Xmalloc __glXMalloc
+# define Xfree   __glXFree
+#else
+# include <X11/Xlibint.h>
+# define __glXMemset  memset
+#endif /* XFree86Server */
+
+#include "glcontextmodes.h"
+
+#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 derrived 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) __glXMemset( 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 = config->bufferSize;
+    mode->indexBits = config->bufferSize;
+
+    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->swapMethod = GLX_SWAP_UNDEFINED_OML;
+}
+
+
+/**
+ * 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, \c Success 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 Success;
+      case GLX_BUFFER_SIZE:
+       *value_return = mode->rgbBits;
+       return Success;
+      case GLX_RGBA:
+       *value_return = mode->rgbMode;
+       return Success;
+      case GLX_RED_SIZE:
+       *value_return = mode->redBits;
+       return Success;
+      case GLX_GREEN_SIZE:
+       *value_return = mode->greenBits;
+       return Success;
+      case GLX_BLUE_SIZE:
+       *value_return = mode->blueBits;
+       return Success;
+      case GLX_ALPHA_SIZE:
+       *value_return = mode->alphaBits;
+       return Success;
+      case GLX_DOUBLEBUFFER:
+       *value_return = mode->doubleBufferMode;
+       return Success;
+      case GLX_STEREO:
+       *value_return = mode->stereoMode;
+       return Success;
+      case GLX_AUX_BUFFERS:
+       *value_return = mode->numAuxBuffers;
+       return Success;
+      case GLX_DEPTH_SIZE:
+       *value_return = mode->depthBits;
+       return Success;
+      case GLX_STENCIL_SIZE:
+       *value_return = mode->stencilBits;
+       return Success;
+      case GLX_ACCUM_RED_SIZE:
+       *value_return = mode->accumRedBits;
+       return Success;
+      case GLX_ACCUM_GREEN_SIZE:
+       *value_return = mode->accumGreenBits;
+       return Success;
+      case GLX_ACCUM_BLUE_SIZE:
+       *value_return = mode->accumBlueBits;
+       return Success;
+      case GLX_ACCUM_ALPHA_SIZE:
+       *value_return = mode->accumAlphaBits;
+       return Success;
+      case GLX_LEVEL:
+       *value_return = mode->level;
+       return Success;
+      case GLX_TRANSPARENT_TYPE_EXT:
+       *value_return = mode->transparentPixel;
+       return Success;
+      case GLX_TRANSPARENT_RED_VALUE:
+       *value_return = mode->transparentRed;
+       return Success;
+      case GLX_TRANSPARENT_GREEN_VALUE:
+       *value_return = mode->transparentGreen;
+       return Success;
+      case GLX_TRANSPARENT_BLUE_VALUE:
+       *value_return = mode->transparentBlue;
+       return Success;
+      case GLX_TRANSPARENT_ALPHA_VALUE:
+       *value_return = mode->transparentAlpha;
+       return Success;
+      case GLX_TRANSPARENT_INDEX_VALUE:
+       *value_return = mode->transparentIndex;
+       return Success;
+      case GLX_X_VISUAL_TYPE:
+       *value_return = mode->visualType;
+       return Success;
+      case GLX_CONFIG_CAVEAT:
+       *value_return = mode->visualRating;
+       return Success;
+      case GLX_VISUAL_ID:
+       *value_return = mode->visualID;
+       return Success;
+      case GLX_DRAWABLE_TYPE:
+       *value_return = mode->drawableType;
+       return Success;
+      case GLX_RENDER_TYPE:
+       *value_return = mode->renderType;
+       return Success;
+      case GLX_X_RENDERABLE:
+       *value_return = mode->xRenderable;
+       return Success;
+      case GLX_FBCONFIG_ID:
+       *value_return = mode->fbconfigID;
+       return Success;
+      case GLX_MAX_PBUFFER_WIDTH:
+       *value_return = mode->maxPbufferWidth;
+       return Success;
+      case GLX_MAX_PBUFFER_HEIGHT:
+       *value_return = mode->maxPbufferHeight;
+       return Success;
+      case GLX_MAX_PBUFFER_PIXELS:
+       *value_return = mode->maxPbufferPixels;
+       return Success;
+      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+       *value_return = mode->optimalPbufferWidth;
+       return Success;
+      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+       *value_return = mode->optimalPbufferHeight;
+       return Success;
+      case GLX_SWAP_METHOD_OML:
+       *value_return = mode->swapMethod;
+       return Success;
+      case GLX_SAMPLE_BUFFERS_SGIS:
+       *value_return = mode->sampleBuffers;
+       return Success;
+      case GLX_SAMPLES_SGIS:
+       *value_return = mode->samples;
+       return Success;
+
+      /* 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;
+    }
+}
+
+
+/**
+ * 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 *) Xmalloc( size );
+      if ( *next == NULL ) {
+        _gl_context_modes_destroy( base );
+        base = NULL;
+        break;
+      }
+      
+      (void) __glXMemset( *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 = & ((*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;
+
+      Xfree( 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 )
+{
+    while ( modes != NULL ) {
+       if ( modes->visualID == vid ) {
+           break;
+       }
+
+       modes = modes->next;
+    }
+
+    return modes;
+}
+
+
+/**
+ * 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) );
+}
diff --git a/src/mesa/drivers/dri/dri_client/glcontextmodes.h b/src/mesa/drivers/dri/dri_client/glcontextmodes.h
new file mode 100644 (file)
index 0000000..5f8fa4f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * (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"
+
+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 );
+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 GLboolean _gl_context_modes_are_same( const __GLcontextModes * a,
+    const __GLcontextModes * b );
+
+#endif /* GLCONTEXTMODES_H */
diff --git a/src/mesa/drivers/dri/dri_client/imports/glxclient.h b/src/mesa/drivers/dri/dri_client/imports/glxclient.h
new file mode 100644 (file)
index 0000000..317ea01
--- /dev/null
@@ -0,0 +1,1143 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+** 
+** http://oss.sgi.com/projects/FreeB
+** 
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+** 
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+** 
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+/* $XFree86: xc/lib/GL/glx/glxclient.h,v 1.15 2002/10/30 12:51:26 alanh Exp $ */
+
+/**
+ * \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>
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <string.h>
+#include <stdlib.h>
+#include "GL/glxint.h"
+#include "GL/glxproto.h"
+#include "GL/internal/glcore.h"
+#include "glapitable.h"
+#ifdef NEED_GL_FUNCS_WRAPPED
+#include "indirect.h"
+#endif
+#ifdef XTHREADS
+#include "Xthreads.h"
+#endif
+#ifdef GLX_BUILT_IN_XMESA
+#include "realglx.h"  /* just silences prototype warnings */
+#endif
+
+#define GLX_MAJOR_VERSION      1       /* current version numbers */
+#define GLX_MINOR_VERSION      2
+
+#define __GLX_MAX_TEXTURE_UNITS 32
+
+typedef struct __GLXcontextRec __GLXcontext;
+typedef struct __GLXdisplayPrivateRec __GLXdisplayPrivate;
+typedef struct _glapi_table __GLapi;
+
+/************************************************************************/
+
+#ifdef GLX_DIRECT_RENDERING
+
+/**
+ * \name DRI interface structures
+ *
+ * The following structures define the interface between the GLX client
+ * side library and the DRI (direct rendering infrastructure).
+ */
+/*@{*/
+typedef struct __DRIdisplayRec  __DRIdisplay;
+typedef struct __DRIscreenRec   __DRIscreen;
+typedef struct __DRIcontextRec  __DRIcontext;
+typedef struct __DRIdrawableRec __DRIdrawable;
+typedef struct __DRIdriverRec   __DRIdriver;
+typedef struct __DRIframebufferRec __DRIframebuffer;
+typedef struct __DRIversionRec     __DRIversion;
+/*@}*/
+
+extern __DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn);
+
+/**
+ * Stored version of some component (i.e., server-side DRI module, kernel-side
+ * DRM, etc.).
+ * 
+ * \todo There are several data structures that explicitly store a major
+ *       version, minor version, and patch level.  These structures should
+ *       be modified to have a \c __DRIversionRec instead.
+ */
+struct __DRIversionRec {
+    int    major;        /**< Major version number. */
+    int    minor;        /**< Minor version number. */
+    int    patch;        /**< Patch-level. */
+};
+
+/**
+ * Framebuffer information record.  Used by libGL to communicate information
+ * about the framebuffer to the driver's \c __DRIdisplayRec::createNewScreen
+ * function.
+ * 
+ * In XFree86, most of this information is derrived from data returned by
+ * calling \c XF86DRIGetDeviceInfo.
+ *
+ * \sa XF86DRIGetDeviceInfo __DRIdisplayRec::createNewScreen
+ *     __driUtilCreateNewScreen CallCreateNewScreen
+ *
+ * \bug This structure could be better named.
+ */
+struct __DRIframebufferRec {
+    unsigned char *base;    /**< Framebuffer base address in the CPU's
+                            * address space.  This value is calculated by
+                            * calling \c drmMap on the framebuffer handle
+                            * returned by \c XF86DRIGetDeviceInfo (or a
+                            * similar function).
+                            */
+    int size;               /**< Framebuffer size, in bytes. */
+    int stride;             /**< Number of bytes from one line to the next. */
+    int width;              /**< Pixel width of the framebuffer. */
+    int height;             /**< Pixel height of the framebuffer. */
+    int dev_priv_size;      /**< Size of the driver's dev-priv structure. */
+    void *dev_priv;         /**< Pointer to the driver's dev-priv structure. */
+};
+
+typedef void *(*CreateScreenFunc)(Display *dpy, int scrn, __DRIscreen *psc,
+                                  int numConfigs, __GLXvisualConfig *config);
+
+typedef void *(*CreateNewScreenFunc)(Display *dpy, int scrn, __DRIscreen *psc,
+    const __GLcontextModes * modes, const __DRIversion * ddx_version,
+    const __DRIversion * dri_version, const __DRIversion * drm_version,
+    const __DRIframebuffer * frame_buffer, void * pSAREA,
+    int fd, int internal_api_version, __GLcontextModes ** driver_modes);
+
+/**
+ * Display dependent methods.  This structure is initialized during the
+ * \c driCreateDisplay call.
+ */
+struct __DRIdisplayRec {
+    /**
+     * Method to destroy the private DRI display data.
+     */
+    void (*destroyDisplay)(Display *dpy, void *displayPrivate);
+
+    /**
+     * Methods to create the private DRI screen data and initialize the
+     * screen dependent methods.
+     * This is an array [indexed by screen number] of function pointers.
+     * 
+     * \deprecated  This array of function pointers has been replaced by
+     *              \c __DRIdisplayRec::createNewScreen.
+     * \sa __DRIdisplayRec::createNewScreen
+     */
+    CreateScreenFunc * createScreen;
+
+    /**
+     * Opaque pointer to private per display direct rendering data.
+     * \c NULL if direct rendering is not supported on this display.
+     */
+    struct __DRIdisplayPrivateRec *private;
+
+    /**
+     * Array of pointers to methods to create and initialize the private DRI
+     * screen data.
+     *
+     * \sa __DRIdisplayRec::createScreen
+     */
+    CreateNewScreenFunc * createNewScreen;
+};
+
+/**
+ * Screen dependent methods.  This structure is initialized during the
+ * \c __DRIdisplayRec::createScreen call.
+ */
+struct __DRIscreenRec {
+    /**
+     * Method to destroy the private DRI screen data.
+     */
+    void (*destroyScreen)(Display *dpy, int scrn, void *screenPrivate);
+
+    /**
+     * Method to create the private DRI context data and initialize the
+     * context dependent methods.
+     *
+     * \sa __DRIscreenRec::createNewContext driCreateContext 
+     *     driCreateNewContext
+     * \deprecated  This function has been replaced by
+     *              __DRIscreenRec::createNewContext.  New drivers will
+     *              continue to export this method, but it will eventually
+     *              (in the next XFree86 major relearse) go away.
+     */
+    void *(*createContext)(Display *dpy, XVisualInfo *vis, void *sharedPrivate,
+                          __DRIcontext *pctx);
+
+    /**
+     * Method to create the private DRI drawable data and initialize the
+     * drawable dependent methods.
+     */
+    void *(*createNewDrawable)(Display *dpy, const __GLcontextModes *modes,
+                              GLXDrawable draw, __DRIdrawable *pdraw,
+                              int renderType, const int *attrs);
+
+    /**
+     * Method to return a pointer to the DRI drawable data.
+     */
+    __DRIdrawable *(*getDrawable)(Display *dpy, GLXDrawable draw,
+                                 void *drawablePrivate);
+
+    /**
+     * Opaque pointer to private per screen direct rendering data.  \c NULL
+     * if direct rendering is not supported on this screen.  Never
+     * dereferenced in libGL.
+     */
+    void *private;
+
+    /**
+     * Get the number of vertical refreshes since some point in time before
+     * this function was first called (i.e., system start up).
+     * 
+     * \since Internal API version 20030317.
+     */
+    int (*getMSC)( void *screenPrivate, int64_t *msc );
+
+    /**
+     * Opaque pointer that points back to the containing 
+     * \c __GLXscreenConfigs.  This data structure is shared with DRI drivers
+     * but \c __GLXscreenConfigs is not. However, they are needed by some GLX
+     * functions called by DRI drivers.
+     *
+     * \since Internal API version 20030813.
+     */
+    void *screenConfigs;
+
+    /**
+     * Functions associated with MESA_allocate_memory.
+     *
+     * \since Internal API version 20030815.
+     */
+    /*@{*/
+    void *(*allocateMemory)(Display *dpy, int scrn, GLsizei size,
+                           GLfloat readfreq, GLfloat writefreq,
+                           GLfloat priority);
+   
+    void (*freeMemory)(Display *dpy, int scrn, GLvoid *pointer);
+   
+    GLuint (*memoryOffset)(Display *dpy, int scrn, const GLvoid *pointer);
+    /*@}*/
+
+    /**
+     * Method to create the private DRI context data and initialize the
+     * context dependent methods.
+     *
+     * \since Internal API version 20031201.
+     */
+    void * (*createNewContext)(Display *dpy, const __GLcontextModes *modes,
+                              int render_type,
+                              void *sharedPrivate, __DRIcontext *pctx);
+};
+
+/**
+ * Context dependent methods.  This structure is initialized during the
+ * \c __DRIscreenRec::createContext call.
+ */
+struct __DRIcontextRec {
+    /**
+     * Method to destroy the private DRI context data.
+     */
+    void (*destroyContext)(Display *dpy, int scrn, void *contextPrivate);
+
+    /**
+     * Method to bind a DRI drawable to a DRI graphics context.
+     */
+    Bool (*bindContext)(Display *dpy, int scrn, GLXDrawable draw,
+                       GLXContext gc);
+
+    /**
+     * Method to unbind a DRI drawable to a DRI graphics context.
+     */
+    Bool (*unbindContext)(Display *dpy, int scrn, GLXDrawable draw,
+                         GLXContext gc, int will_rebind);
+
+    /**
+     * Opaque pointer to private per context direct rendering data.
+     * \c NULL if direct rendering is not supported on the display or
+     * screen used to create this context.  Never dereferenced in libGL.
+     */
+    void *private;
+
+    /**
+     * Method to bind a DRI drawable to a DRI graphics context.
+     *
+     * \since Internal API version 20030606.
+     */
+    Bool (*bindContext2)(Display *dpy, int scrn, GLXDrawable draw,
+                        GLXDrawable read, GLXContext gc);
+
+    /**
+     * Method to unbind a DRI drawable to a DRI graphics context.
+     *
+     * \since Internal API version 20030606.
+     */
+    Bool (*unbindContext2)(Display *dpy, int scrn, GLXDrawable draw,
+                          GLXDrawable read, GLXContext gc);
+};
+
+/**
+ * Drawable dependent methods.  This structure is initialized during the
+ * \c __DRIscreenRec::createDrawable call.  \c createDrawable is not called
+ * by libGL at this time.  It's currently used via the dri_util.c utility code
+ * instead.
+ */
+struct __DRIdrawableRec {
+    /**
+     * Method to destroy the private DRI drawable data.
+     */
+    void (*destroyDrawable)(Display *dpy, void *drawablePrivate);
+
+    /**
+     * Method to swap the front and back buffers.
+     */
+    void (*swapBuffers)(Display *dpy, void *drawablePrivate);
+
+    /**
+     * Opaque pointer to private per drawable direct rendering data.
+     * \c NULL if direct rendering is not supported on the display or
+     * screen used to create this drawable.  Never dereferenced in libGL.
+     */
+    void *private;
+
+    /**
+     * Get the number of completed swap buffers for this drawable.
+     *
+     * \since Internal API version 20030317.
+     */
+    int (*getSBC)(Display *dpy, void *drawablePrivate, int64_t *sbc );
+
+    /**
+     * Wait for the SBC to be greater than or equal target_sbc.
+     *
+     * \since Internal API version 20030317.
+     */
+    int (*waitForSBC)( Display * dpy, void *drawablePriv,
+                      int64_t target_sbc,
+                      int64_t * msc, int64_t * sbc );
+
+    /**
+     * Wait for the MSC to equal target_msc, or, if that has already passed,
+     * the next time (MSC % divisor) is equal to remainder.  If divisor is
+     * zero, the function will return as soon as MSC is greater than or equal
+     * to target_msc.
+     * 
+     * \since Internal API version 20030317.
+     */
+    int (*waitForMSC)( Display * dpy, void *drawablePriv,
+                      int64_t target_msc, int64_t divisor, int64_t remainder,
+                      int64_t * msc, int64_t * sbc );
+
+    /**
+     * Like \c swapBuffers, but does NOT have an implicit \c glFlush.  Once
+     * rendering is complete, waits until MSC is equal to target_msc, or
+     * if that has already passed, waits until (MSC % divisor) is equal
+     * to remainder.  If divisor is zero, the swap will happen as soon as
+     * MSC is greater than or equal to target_msc.
+     * 
+     * \since Internal API version 20030317.
+     */
+    int64_t (*swapBuffersMSC)(Display *dpy, void *drawablePrivate,
+                             int64_t target_msc,
+                             int64_t divisor, int64_t remainder);
+
+    /**
+     * Enable or disable frame usage tracking.
+     * 
+     * \since Internal API version 20030317.
+     */
+    int (*frameTracking)(Display *dpy, void *drawablePrivate, Bool enable);
+
+    /**
+     * Retrieve frame usage information.
+     * 
+     * \since Internal API version 20030317.
+     */
+    int (*queryFrameTracking)(Display *dpy, void *drawablePrivate,
+                             int64_t * sbc, int64_t * missedFrames,
+                             float * lastMissedUsage, float * usage );
+
+    /**
+     * Used by drivers that implement the GLX_SGI_swap_control or
+     * GLX_MESA_swap_control extension.
+     *
+     * \since Internal API version 20030317.
+     */
+    unsigned swap_interval;
+};
+
+
+/*
+** We keep a linked list of these structures, one per DRI device driver.
+*/
+struct __DRIdriverRec {
+   const char *name;
+   void *handle;
+   CreateScreenFunc createScreenFunc;
+   CreateNewScreenFunc createNewScreenFunc;
+   struct __DRIdriverRec *next;
+};
+
+/*
+** Function to create and DRI display data and initialize the display
+** dependent methods.
+*/
+extern void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp);
+
+extern  __DRIdriver *driGetDriver(Display *dpy, int scrNum);
+
+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;
+
+/* The next 3 structures are deprecated.  Client state is no longer tracked
+ * using them.  They only remain to maintain the layout / structure offset of
+ * __GLXcontextRec.  In XFree86 5.0 they will be removed altogether.
+ */
+
+typedef struct __GLXvertexArrayPointerStateRecDEPRECATED {
+    GLboolean enable;
+    void (*proc)(const void *);
+    const GLubyte *ptr;
+    GLsizei skip;
+    GLint size;
+    GLenum type;
+    GLsizei stride;
+} __GLXvertexArrayPointerStateDEPRECATED;
+
+typedef struct __GLXvertArrayStateRecDEPRECATED {
+    __GLXvertexArrayPointerStateDEPRECATED vertex;
+    __GLXvertexArrayPointerStateDEPRECATED normal;
+    __GLXvertexArrayPointerStateDEPRECATED color;
+    __GLXvertexArrayPointerStateDEPRECATED index;
+    __GLXvertexArrayPointerStateDEPRECATED texCoord[__GLX_MAX_TEXTURE_UNITS];
+    __GLXvertexArrayPointerStateDEPRECATED edgeFlag;
+    GLint maxElementsVertices;
+    GLint maxElementsIndices;
+    GLint activeTexture;
+} __GLXvertArrayStateDEPRECATED;
+
+typedef struct __GLXattributeRecDEPRECATED {
+       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;
+
+       /*
+       ** 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.
+       */
+       __GLXvertArrayStateDEPRECATED vertArray;
+} __GLXattributeDEPRECATED;
+
+typedef struct __GLXvertexArrayPointerStateRec {
+    void (*proc)(const void *);
+    void (*mtex_proc)(GLenum, const void *);
+    const GLubyte *ptr;
+    GLsizei skip;
+    GLint size;
+    GLenum type;
+    GLsizei stride;
+} __GLXvertexArrayPointerState;
+
+/**
+ * Define which entries of \c __GLXvertArrayState::arrays match which
+ * vertex arrays in the client-state vector.  These are only the one-of
+ * arrays.  See the \c __GLXvertArrayState::arrays documentation for more
+ * details.
+ * 
+ * \sa __GLXvertArrayState
+ */
+enum {
+    edgeFlag_ARRAY,       /**< \c GL_EDGE_FLAG_ARRAY */
+    index_ARRAY,          /**< \c GL_INDEX_ARRAY */
+    fogCoord_ARRAY,       /**< \c GL_FOG_COORD_ARRAY */
+    secondaryColor_ARRAY, /**< \c GL_SECONDARY_COLOR_ARRAY */
+    color_ARRAY,          /**< \c GL_COLOR_ARRAY */
+    normal_ARRAY,         /**< \c GL_NORMAL_ARRAY */
+       
+    /**
+     * \c GL_VERTEX_ARRAY \b must be last!  All of the code for emitting arrays
+     * and array elements is written based on the assumption that the vertex
+     * array is last.
+     */
+    vertex_ARRAY,
+
+    __GLX_MAX_ARRAYS      /**< Place holder entry. */
+};
+
+#define ENABLE_ARRAY(state,a) \
+    do { (state)->vertArray.enables |=  (1U << (a ## _ARRAY)); } while( 0 )
+#define DISABLE_ARRAY(state,a) \
+    do { (state)->vertArray.enables &= ~(1U << (a ## _ARRAY)); } while( 0 )
+#define IS_ARRAY_ENABLED_BY_INDEX(state, i) \
+    (((state)->vertArray.enables & (1U << (i))) != 0)
+#define IS_ARRAY_ENABLED(state, a) \
+    IS_ARRAY_ENABLED_BY_INDEX(state, a ## _ARRAY)
+
+#define ENABLE_TEXARRAY(state,a) \
+    do { (state)->vertArray.texture_enables |=  (1U << a); } while( 0 )
+#define DISABLE_TEXARRAY(state,a) \
+    do { (state)->vertArray.texture_enables &= ~(1U << a); } while( 0 )
+#define IS_TEXARRAY_ENABLED(state, a) \
+    (((state)->vertArray.texture_enables & (1U << a)) != 0)
+
+/**
+ * Client-side vertex array state.
+ */
+typedef struct __GLXvertArrayStateRec {
+    /**
+     * Which client-side arrays are enabled?  These are the flag bits for
+     * all of the non-texture coordinate arrays.
+     */
+    GLuint enables;
+
+    /**
+     * Which of the texture coordinate arrays are enabled?
+     */
+    GLuint texture_enables;
+
+    /**
+     * State for "one-of" arrays.  These are the arrays, such as
+     * GL_COLOR_ARRAY or GL_FOG_COORD_ARRAY for which there is only one
+     * array.  There are also "many-of" arrays, such as
+     * GL_TEXTURE_COORD_ARRAY.
+     */
+    __GLXvertexArrayPointerState arrays[__GLX_MAX_ARRAYS];
+
+    __GLXvertexArrayPointerState texCoord[__GLX_MAX_TEXTURE_UNITS];
+
+    GLint maxElementsVertices;
+    GLint maxElementsIndices;
+    GLint activeTexture;
+} __GLXvertArrayState;
+
+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;
+
+       /*
+       ** 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.
+       */
+       __GLXvertArrayState vertArray;
+
+       /**
+        * Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
+        * disabled?
+        */
+       GLboolean NoDrawArraysProtocol;
+} __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;
+
+    /**
+     * Visual id.
+     * 
+     * \deprecated
+     * This filed has been largely been replaced by the \c mode field, but
+     * the work is not quite done.
+     */
+    VisualID vid;
+
+    /**
+     * Screen number.
+     */
+    GLint screen;
+
+    /**
+     * \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*);
+
+    /**
+     * \name Client side attribs.
+     */
+    /*@{*/
+    __GLXattributeDEPRECATED stateDEPRECATED;
+    __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;
+
+#ifdef GLX_DIRECT_RENDERING
+    /**
+     * Per context direct rendering interface functions and data.
+     */
+    __DRIcontext driContext;
+#endif
+    
+    /**
+     * \c GLXFBConfigID used to create this context.  May be \c None.  This
+     * field has been replaced by the \c mode field.
+     *
+     * \since Internal API version 20030317.
+     *
+     * \deprecated
+     * This filed has been largely been replaced by the \c mode field, but
+     * the work is not quite done.
+     */
+    GLXFBConfigID  fbconfigID;
+
+    /**
+     * 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;
+
+#ifdef GLX_DIRECT_RENDERING
+    /**
+     * Pointer to the mode used to create this context.  This field replaces
+     * the \c vid and \c fbconfigID fields.
+     * 
+     * \since Internal API version 20031201.
+     */
+    const __GLcontextModes * mode;
+#endif /* GLX_DIRECT_RENDERING */
+};
+
+#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).
+ */
+typedef struct __GLXscreenConfigsRec {
+    /**
+     * GLX visuals formated as \c __GLXvisualConfig structures.
+     */
+    /*@{*/
+    __GLXvisualConfig * old_configs;
+    int numOldConfigs;
+    /*@}*/
+
+    /**
+     * 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;
+#endif
+
+    /**
+     * Linked list of configurations for this screen.  This is intended to
+     * be a superset of \c old_configs.
+     */
+    __GLcontextModes *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;
+    /*@}*/
+
+} __GLXscreenConfigs;
+
+/**
+ * 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.
+     */
+    /*@{*/
+    char *serverGLXvendor;
+    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.
+     */
+    __DRIdisplay driDisplay;
+#endif
+};
+
+void __glXFreeContext(__GLXcontext*);
+
+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 int __glXDebug;
+
+/* This is per-thread storage in an MT environment */
+#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+extern __GLXcontext *__glXGetCurrentContext(void);
+extern void __glXSetCurrentContext(__GLXcontext *c);
+#else
+extern __GLXcontext *__glXcurrentContext;
+#define __glXGetCurrentContext()       __glXcurrentContext
+#define __glXSetCurrentContext(gc)     __glXcurrentContext = gc
+#endif
+
+
+/*
+** Global lock for all threads in this address space using the GLX
+** extension
+*/
+#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+extern xmutex_rec __glXmutex;
+#define __glXLock()    xmutex_lock(&__glXmutex)
+#define __glXUnlock()  xmutex_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.
+*/
+
+/* Return the size, in bytes, of some pixel data */
+extern GLint __glImageSize(GLint, GLint, GLint, 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);
+
+/* Return the k value for a given map target */
+extern GLint __glEvalComputeK(GLenum);
+
+/*
+** 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 
+*/
+extern void __glXInitVertexArrayState(__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
+
+
+/*
+** GLX_BUILT_IN_XMESA controls whether libGL has a built-in verions of
+** Mesa that can render to non-GLX displays.
+*/
+#ifdef GLX_BUILT_IN_XMESA
+#define GLX_PREFIX(function)  _real_##function
+#else
+#define GLX_PREFIX(function)  function
+#endif
+
+
+extern void __glXInitializeVisualConfigFromTags( __GLcontextModes *config,
+    int count, const INT32 *bp, Bool tagged_only, Bool fbconfig_style_tags );
+
+extern char *__glXInternalQueryServerString( Display *dpy, int opcode,
+    int screen, int name );
+
+extern char *__glXstrdup(const char *str);
+
+
+extern const char __glXGLClientVersion[];
+extern const char __glXGLClientExtensions[];
+extern char *__glXCombineExtensionStrings( const char *cext_string,
+    const char *sext_string );
+
+/* Determine the internal API version */
+extern int __glXGetInternalVersion(void);
+
+/**
+ * Type of a pointer to \c __glXGetInternalVersion, as returned by
+ * \c glXGetProcAddress.
+ *
+ * \sa __glXGetInternalVersion, glXGetProcAddress
+ */
+typedef int (* PFNGLXGETINTERNALVERSIONPROC) ( void );
+
+/**
+ * Type of a pointer to \c __glXWindowExists, as returned by
+ * \c glXGetProcAddress.
+ *
+ * \sa __glXWindowExists, glXGetProcAddress
+ */
+typedef Bool (* PFNGLXWINDOWEXISTSPROC) (Display *dpy, GLXDrawable draw);
+
+/* Get the unadjusted system time */
+extern int __glXGetUST( int64_t * ust );
+
+/**
+ * Type of a pointer to \c __glXGetUST, as returned by \c glXGetProcAddress.
+ * 
+ * \sa __glXGetUST, glXGetProcAddress
+ */
+typedef int (* PFNGLXGETUSTPROC) ( int64_t * ust );
+
+
+/**
+ * Type of pointer to \c __glXCreateContextModes, as returned by
+ * \c glXGetProcAddress.
+ * 
+ * \sa _gl_context_modes_create, glXGetProcAddress
+ */
+
+typedef __GLcontextModes * (* PFNGLXCREATECONTEXTMODES) ( unsigned count,
+    size_t minimum_bytes_per_struct );
+
+#endif /* !__GLX_client_h__ */
diff --git a/src/mesa/drivers/dri/dri_client/imports/sarea.h b/src/mesa/drivers/dri/dri_client/imports/sarea.h
new file mode 100644 (file)
index 0000000..d4d83df
--- /dev/null
@@ -0,0 +1,94 @@
+/* $XFree86: xc/programs/Xserver/GL/dri/sarea.h,v 1.11 2002/10/30 12:52:03 alanh Exp $ */
+/**
+ * \file sarea.h 
+ * SAREA definitions.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+/*
+ * 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/GL/dri/sarea.h,v 1.11 2002/10/30 12:52:03 alanh Exp $ */
+
+#ifndef _SAREA_H_
+#define _SAREA_H_
+
+#include "xf86drm.h"
+
+/* SAREA area needs to be at least a page */
+#if defined(__alpha__)
+#define SAREA_MAX                      0x2000
+#elif defined(__ia64__)
+#define SAREA_MAX                      0x10000         /* 64kB */
+#else
+/* Intel 830M driver needs at least 8k SAREA */
+#define SAREA_MAX                      0x2000
+#endif
+
+#define SAREA_MAX_DRAWABLES            256
+
+#define SAREA_DRAWABLE_CLAIMED_ENTRY   0x80000000
+
+/**
+ * SAREA per drawable information.
+ *
+ * \sa _XF86DRISAREA.
+ */
+typedef struct _XF86DRISAREADrawable {
+    unsigned int       stamp;
+    unsigned int       flags;
+} XF86DRISAREADrawableRec, *XF86DRISAREADrawablePtr;
+
+/**
+ * SAREA frame information.
+ *
+ * \sa  _XF86DRISAREA.
+ */
+typedef struct _XF86DRISAREAFrame {
+    unsigned int        x;
+    unsigned int        y;
+    unsigned int        width;
+    unsigned int        height;
+    unsigned int        fullscreen;
+} XF86DRISAREAFrameRec, *XF86DRISAREAFramePtr;
+
+/**
+ * SAREA definition.
+ */
+typedef struct _XF86DRISAREA {
+    /** first thing is always the DRM locking structure */
+    drmLock                    lock;
+    /** \todo Use readers/writer lock for drawable_lock */
+    drmLock                    drawable_lock;
+    XF86DRISAREADrawableRec    drawableTable[SAREA_MAX_DRAWABLES];
+    XF86DRISAREAFrameRec        frame;
+    drmContext                 dummy_context;
+} XF86DRISAREARec, *XF86DRISAREAPtr;
+
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/imports/xf86drm.h b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h
new file mode 100644 (file)
index 0000000..c9f1007
--- /dev/null
@@ -0,0 +1,646 @@
+/**
+ * \file xf86drm.h 
+ * OS-independent header for DRM user-level library interface.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+/*
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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
+ * 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.
+ *
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.26 2003/08/16 19:26:37 dawes Exp $ */
+
+#ifndef _XF86DRM_H_
+#define _XF86DRM_H_
+
+                               /* Defaults, if nothing set in xf86config */
+#define DRM_DEV_UID     0
+#define DRM_DEV_GID     0
+/* Default /dev/dri directory permissions 0755 */
+#define DRM_DEV_DIRMODE                \
+       (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#define DRM_DEV_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+
+#define DRM_DIR_NAME  "/dev/dri"
+#define DRM_DEV_NAME  "%s/card%d"
+#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
+
+#define DRM_ERR_NO_DEVICE  (-1001)
+#define DRM_ERR_NO_ACCESS  (-1002)
+#define DRM_ERR_NOT_ROOT   (-1003)
+#define DRM_ERR_INVALID    (-1004)
+#define DRM_ERR_NO_FD      (-1005)
+
+#define DRM_AGP_NO_HANDLE 0
+
+typedef unsigned long drmHandle,   *drmHandlePtr;   /**< To mapped regions */
+typedef unsigned int  drmSize,     *drmSizePtr;            /**< For mapped regions */
+typedef void          *drmAddress, **drmAddressPtr; /**< For mapped regions */
+typedef unsigned int  drmContext,  *drmContextPtr;  /**< GLXContext handle */
+typedef unsigned int  drmDrawable, *drmDrawablePtr; /**< Unused */
+typedef unsigned int  drmMagic,    *drmMagicPtr;    /**< Magic for authentication */
+
+/**
+ * Driver version information.
+ *
+ * \sa drmGetVersion() and drmSetVersion().
+ */
+typedef struct _drmVersion {
+    int     version_major;        /**< Major version */
+    int     version_minor;        /**< Minor version */
+    int     version_patchlevel;   /**< Patch level */
+    int     name_len;            /**< Length of name buffer */
+    char    *name;               /**< Name of driver */
+    int     date_len;             /**< Length of date buffer */
+    char    *date;                /**< User-space buffer to hold date */
+    int     desc_len;            /**< Length of desc buffer */
+    char    *desc;                /**< User-space buffer to hold desc */
+} drmVersion, *drmVersionPtr;
+
+typedef struct _drmStats {
+    unsigned long count;            /**< Number of data */
+    struct {
+       unsigned long value;         /**< Value from kernel */
+       const char    *long_format;  /**< Suggested format for long_name */
+       const char    *long_name;    /**< Long name for value */
+       const char    *rate_format;  /**< Suggested format for rate_name */
+       const char    *rate_name;    /**< Short name for value per second */
+       int           isvalue;       /**< True if value (vs. counter) */
+       const char    *mult_names;   /**< Multiplier names (e.g., "KGM") */
+       int           mult;          /**< Multiplier value (e.g., 1024) */
+       int           verbose;       /**< Suggest only in verbose output */
+    } data[15];
+} drmStatsT;
+
+
+                               /* All of these enums *MUST* match with the
+                                   kernel implementation -- so do *NOT*
+                                   change them!  (The drmlib implementation
+                                   will just copy the flags instead of
+                                   translating them.) */
+typedef enum {
+    DRM_FRAME_BUFFER    = 0,      /**< WC, no caching, no core dump */
+    DRM_REGISTERS       = 1,      /**< no caching, no core dump */
+    DRM_SHM             = 2,      /**< shared, cached */
+    DRM_AGP             = 3,     /**< AGP/GART */
+    DRM_SCATTER_GATHER  = 4      /**< PCI scatter/gather */
+} drmMapType;
+
+typedef enum {
+    DRM_RESTRICTED      = 0x0001, /**< Cannot be mapped to client-virtual */
+    DRM_READ_ONLY       = 0x0002, /**< Read-only in client-virtual */
+    DRM_LOCKED          = 0x0004, /**< Physical pages locked */
+    DRM_KERNEL          = 0x0008, /**< Kernel requires access */
+    DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */
+    DRM_CONTAINS_LOCK   = 0x0020, /**< SHM page that contains lock */
+    DRM_REMOVABLE      = 0x0040  /**< Removable mapping */
+} drmMapFlags;
+
+/**
+ * \warning These values *MUST* match drm.h
+ */
+typedef enum {
+    /** \name Flags for DMA buffer dispatch */
+    /*@{*/
+    DRM_DMA_BLOCK        = 0x01, /**< 
+                                 * Block until buffer dispatched.
+                                 * 
+                                 * \note the buffer may not yet have been
+                                 * processed by the hardware -- getting a
+                                 * hardware lock with the hardware quiescent
+                                 * will ensure that the buffer has been
+                                 * processed.
+                                 */
+    DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+    DRM_DMA_PRIORITY     = 0x04, /**< High priority dispatch */
+    /*@}*/
+
+    /** \name Flags for DMA buffer request */
+    /*@{*/
+    DRM_DMA_WAIT         = 0x10, /**< Wait for free buffers */
+    DRM_DMA_SMALLER_OK   = 0x20, /**< Smaller-than-requested buffers OK */
+    DRM_DMA_LARGER_OK    = 0x40  /**< Larger-than-requested buffers OK */
+    /*@}*/
+} drmDMAFlags;
+
+typedef enum {
+    DRM_PAGE_ALIGN       = 0x01,
+    DRM_AGP_BUFFER       = 0x02,
+    DRM_SG_BUFFER        = 0x04
+} drmBufDescFlags;
+
+typedef enum {
+    DRM_LOCK_READY      = 0x01, /**< Wait until hardware is ready for DMA */
+    DRM_LOCK_QUIESCENT  = 0x02, /**< Wait until hardware quiescent */
+    DRM_LOCK_FLUSH      = 0x04, /**< Flush this context's DMA queue first */
+    DRM_LOCK_FLUSH_ALL  = 0x08, /**< Flush all DMA queues first */
+                               /* These *HALT* flags aren't supported yet
+                                   -- they will be used to support the
+                                   full-screen DGA-like mode. */
+    DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+    DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
+} drmLockFlags;
+
+typedef enum {
+    DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and
+                                    never swapped. */
+    DRM_CONTEXT_2DONLY    = 0x02  /**< This context is for 2D rendering only. */
+} drmContextFlags, *drmContextFlagsPtr;
+
+typedef struct _drmBufDesc {
+    int              count;      /**< Number of buffers of this size */
+    int              size;       /**< Size in bytes */
+    int              low_mark;   /**< Low water mark */
+    int              high_mark;          /**< High water mark */
+} drmBufDesc, *drmBufDescPtr;
+
+typedef struct _drmBufInfo {
+    int              count;      /**< Number of buffers described in list */
+    drmBufDescPtr    list;       /**< List of buffer descriptions */
+} drmBufInfo, *drmBufInfoPtr;
+
+typedef struct _drmBuf {
+    int              idx;        /**< Index into the master buffer list */
+    int              total;      /**< Buffer size */
+    int              used;       /**< Amount of buffer in use (for DMA) */
+    drmAddress       address;    /**< Address */
+} drmBuf, *drmBufPtr;
+
+/**
+ * Buffer mapping information.
+ *
+ * Used by drmMapBufs() and drmUnmapBufs() to store information about the
+ * mapped buffers.
+ */
+typedef struct _drmBufMap {
+    int              count;      /**< Number of buffers mapped */
+    drmBufPtr        list;       /**< Buffers */
+} drmBufMap, *drmBufMapPtr;
+
+typedef struct _drmLock {
+    volatile unsigned int lock;
+    char                      padding[60];
+    /* This is big enough for most current (and future?) architectures:
+       DEC Alpha:              32 bytes
+       Intel Merced:           ?
+       Intel P5/PPro/PII/PIII: 32 bytes
+       Intel StrongARM:        32 bytes
+       Intel i386/i486:        16 bytes
+       MIPS:                   32 bytes (?)
+       Motorola 68k:           16 bytes
+       Motorola PowerPC:       32 bytes
+       Sun SPARC:              32 bytes
+    */
+} drmLock, *drmLockPtr;
+
+/**
+ * Indices here refer to the offset into
+ * list in drmBufInfo
+ */
+typedef struct _drmDMAReq {
+    drmContext    context;       /**< Context handle */
+    int           send_count;     /**< Number of buffers to send */
+    int           *send_list;     /**< List of handles to buffers */
+    int           *send_sizes;    /**< Lengths of data to send, in bytes */
+    drmDMAFlags   flags;          /**< Flags */
+    int           request_count;  /**< Number of buffers requested */
+    int           request_size;          /**< Desired size of buffers requested */
+    int           *request_list;  /**< Buffer information */
+    int           *request_sizes; /**< Minimum acceptable sizes */
+    int           granted_count;  /**< Number of buffers granted at this size */
+} drmDMAReq, *drmDMAReqPtr;
+
+typedef struct _drmRegion {
+    drmHandle     handle;
+    unsigned int  offset;
+    drmSize       size;
+    drmAddress    map;
+} drmRegion, *drmRegionPtr;
+
+typedef struct _drmTextureRegion {
+    unsigned char next;
+    unsigned char prev;
+    unsigned char in_use;
+    unsigned char padding;     /**< Explicitly pad this out */
+    unsigned int  age;
+} drmTextureRegion, *drmTextureRegionPtr;
+
+
+typedef struct _drmClipRect {
+    unsigned short     x1; /* Upper left: inclusive */
+    unsigned short     y1;
+    unsigned short     x2; /* Lower right: exclusive */
+    unsigned short     y2;
+} drmClipRect, *drmClipRectPtr;
+
+
+typedef enum {
+    DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+    DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+    DRM_VBLANK_SIGNAL   = 0x40000000   /* Send signal instead of blocking */
+} drmVBlankSeqType;
+
+typedef struct _drmVBlankReq {
+       drmVBlankSeqType type;
+       unsigned int sequence;
+       unsigned long signal;
+} drmVBlankReq, *drmVBlankReqPtr;
+
+typedef struct _drmVBlankReply {
+       drmVBlankSeqType type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+} drmVBlankReply, *drmVBlankReplyPtr;
+
+typedef union _drmVBlank {
+       drmVBlankReq request;
+       drmVBlankReply reply;
+} drmVBlank, *drmVBlankPtr;
+
+typedef struct _drmSetVersion {
+       int drm_di_major;
+       int drm_di_minor;
+       int drm_dd_major;
+       int drm_dd_minor;
+} drmSetVersion, *drmSetVersionPtr;
+
+
+#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
+
+#define DRM_LOCK_HELD  0x80000000 /**< Hardware lock is held */
+#define DRM_LOCK_CONT  0x40000000 /**< Hardware lock is contended */
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# if defined(__i386) || defined(__AMD64__)
+                               /* Reflect changes here to drmP.h */
+#define DRM_CAS(lock,old,new,__ret)                                    \
+       do {                                                           \
+                int __dummy;   /* Can't mark eax as clobbered */      \
+               __asm__ __volatile__(                                  \
+                       "lock ; cmpxchg %4,%1\n\t"                     \
+                        "setnz %0"                                     \
+                       : "=d" (__ret),                                \
+                         "=m" (__drm_dummy_lock(lock)),               \
+                          "=a" (__dummy)                               \
+                       : "2" (old),                                   \
+                         "r" (new));                                  \
+       } while (0)
+
+#elif defined(__alpha__)
+
+#define        DRM_CAS(lock, old, new, ret)            \
+       do {                                    \
+               int old32;                      \
+               int cur32;                      \
+               __asm__ __volatile__(           \
+               "       mb\n"                   \
+               "       zap   %4, 0xF0, %0\n"   \
+               "       ldl_l %1, %2\n"         \
+               "       zap   %1, 0xF0, %1\n"   \
+                "       cmpeq %0, %1, %1\n"    \
+                "       beq   %1, 1f\n"                \
+               "       bis   %5, %5, %1\n"     \
+                "       stl_c %1, %2\n"                \
+                "1:     xor   %1, 1, %1\n"     \
+                "       stl   %1, %3"          \
+                : "+r" (old32),                 \
+                 "+&r" (cur32),                \
+                   "=m" (__drm_dummy_lock(lock)),\
+                   "=m" (ret)                  \
+               : "r" (old),                    \
+                 "r" (new));                   \
+       } while(0)
+
+#elif defined(__sparc__)
+
+#define DRM_CAS(lock,old,new,__ret)                            \
+do {   register unsigned int __old __asm("o0");                \
+       register unsigned int __new __asm("o1");                \
+       register volatile unsigned int *__lock __asm("o2");     \
+       __old = old;                                            \
+       __new = new;                                            \
+       __lock = (volatile unsigned int *)lock;                 \
+       __asm__ __volatile__(                                   \
+               /*"cas [%2], %3, %0"*/                          \
+               ".word 0xd3e29008\n\t"                          \
+               /*"membar #StoreStore | #StoreLoad"*/           \
+               ".word 0x8143e00a"                              \
+               : "=&r" (__new)                                 \
+               : "0" (__new),                                  \
+                 "r" (__lock),                                 \
+                 "r" (__old)                                   \
+               : "memory");                                    \
+       __ret = (__new != __old);                               \
+} while(0)
+
+#elif defined(__ia64__)
+
+#ifdef __INTEL_COMPILER
+/* this currently generates bad code (missing stop bits)... */
+#include <ia64intrin.h>
+
+#define DRM_CAS(lock,old,new,__ret)                                          \
+       do {                                                                  \
+               unsigned long __result, __old = (old) & 0xffffffff;             \
+               __mf();                                                         \
+               __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\
+               __ret = (__result) != (__old);                                  \
+/*             __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
+                                                    (old), (new))            \
+                        != (old));                                           */\
+       } while (0)
+
+#else
+#define DRM_CAS(lock,old,new,__ret)                                      \
+       do {                                                              \
+               unsigned int __result, __old = (old);                     \
+               __asm__ __volatile__(                                     \
+                       "mf\n"                                            \
+                       "mov ar.ccv=%2\n"                                 \
+                       ";;\n"                                            \
+                       "cmpxchg4.acq %0=%1,%3,ar.ccv"                    \
+                       : "=r" (__result), "=m" (__drm_dummy_lock(lock))  \
+                       : "r" ((unsigned long)__old), "r" (new)                   \
+                       : "memory");                                      \
+               __ret = (__result) != (__old);                            \
+       } while (0)
+
+#endif
+
+#elif defined(__powerpc__)
+
+#define DRM_CAS(lock,old,new,__ret)                    \
+       do {                                            \
+               __asm__ __volatile__(                   \
+                       "sync;"                         \
+                       "0:    lwarx %0,0,%1;"          \
+                       "      xor. %0,%3,%0;"          \
+                       "      bne 1f;"                 \
+                       "      stwcx. %2,0,%1;"         \
+                       "      bne- 0b;"                \
+                       "1:    "                        \
+                       "sync;"                         \
+               : "=&r"(__ret)                          \
+               : "r"(lock), "r"(new), "r"(old)         \
+               : "cr0", "memory");                     \
+       } while (0)
+
+#endif /* architecture */
+#endif /* __GNUC__ >= 2 */
+
+#ifndef DRM_CAS
+#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
+#endif
+
+#if defined(__alpha__) || defined(__powerpc__)
+#define DRM_CAS_RESULT(_result)                int _result
+#else
+#define DRM_CAS_RESULT(_result)                char _result
+#endif
+
+#define DRM_LIGHT_LOCK(fd,lock,context)                                \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
+                if (__ret) drmGetLock(fd,context,0);                   \
+        } while(0)
+
+                               /* This one counts fast locks -- for
+                                   benchmarking only. */
+#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count)                    \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
+                if (__ret) drmGetLock(fd,context,0);                   \
+                else       ++count;                                    \
+        } while(0)
+
+#define DRM_LOCK(fd,lock,context,flags)                                \
+       do {                                                           \
+               if (flags) drmGetLock(fd,context,flags);               \
+               else       DRM_LIGHT_LOCK(fd,lock,context);            \
+       } while(0)
+
+#define DRM_UNLOCK(fd,lock,context)                                    \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret);     \
+                if (__ret) drmUnlock(fd,context);                      \
+        } while(0)
+
+                               /* Simple spin locks */
+#define DRM_SPINLOCK(spin,val)                                         \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+           do {                                                       \
+               DRM_CAS(spin,0,val,__ret);                             \
+               if (__ret) while ((spin)->lock);                       \
+           } while (__ret);                                           \
+       } while(0)
+
+#define DRM_SPINLOCK_TAKE(spin,val)                                    \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+            int  cur;                                                  \
+           do {                                                       \
+                cur = (*spin).lock;                                    \
+               DRM_CAS(spin,cur,val,__ret);                           \
+           } while (__ret);                                           \
+       } while(0)
+
+#define DRM_SPINLOCK_COUNT(spin,val,count,__ret)                       \
+       do {                                                           \
+            int  __i;                                                  \
+            __ret = 1;                                                 \
+            for (__i = 0; __ret && __i < count; __i++) {               \
+               DRM_CAS(spin,0,val,__ret);                             \
+               if (__ret) for (;__i < count && (spin)->lock; __i++);  \
+           }                                                          \
+       } while(0)
+
+#define DRM_SPINUNLOCK(spin,val)                                       \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+            if ((*spin).lock == val) { /* else server stole lock */    \
+               do {                                                   \
+                   DRM_CAS(spin,val,0,__ret);                         \
+               } while (__ret);                                       \
+            }                                                          \
+       } while(0)
+
+/* General user-level programmer's API: unprivileged */
+extern int           drmAvailable(void);
+extern int           drmOpen(const char *name, const char *busid);
+extern int           drmClose(int fd);
+extern drmVersionPtr drmGetVersion(int fd);
+extern drmVersionPtr drmGetLibVersion(int fd);
+extern void          drmFreeVersion(drmVersionPtr);
+extern int           drmGetMagic(int fd, drmMagicPtr magic);
+extern char          *drmGetBusid(int fd);
+extern int           drmGetInterruptFromBusID(int fd, int busnum, int devnum,
+                                             int funcnum);
+extern int           drmGetMap(int fd, int idx, drmHandle *offset,
+                              drmSize *size, drmMapType *type,
+                              drmMapFlags *flags, drmHandle *handle,
+                              int *mtrr);
+extern int           drmGetClient(int fd, int idx, int *auth, int *pid,
+                                 int *uid, unsigned long *magic,
+                                 unsigned long *iocs);
+extern int           drmGetStats(int fd, drmStatsT *stats);
+extern int           drmSetInterfaceVersion(int fd, drmSetVersion *version);
+extern int           drmCommandNone(int fd, unsigned long drmCommandIndex);
+extern int           drmCommandRead(int fd, unsigned long drmCommandIndex,
+                                    void *data, unsigned long size);
+extern int           drmCommandWrite(int fd, unsigned long drmCommandIndex,
+                                     void *data, unsigned long size);
+extern int           drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+                                         void *data, unsigned long size);
+
+/* General user-level programmer's API: X server (root) only  */
+extern void          drmFreeBusid(const char *busid);
+extern int           drmSetBusid(int fd, const char *busid);
+extern int           drmAuthMagic(int fd, drmMagic magic);
+extern int           drmAddMap(int fd,
+                              drmHandle offset,
+                              drmSize size,
+                              drmMapType type,
+                              drmMapFlags flags,
+                              drmHandlePtr handle);
+extern int          drmRmMap(int fd, drmHandle handle);
+extern int          drmAddContextPrivateMapping(int fd, drmContext ctx_id,
+                                                drmHandle handle);
+
+extern int           drmAddBufs(int fd, int count, int size,
+                               drmBufDescFlags flags,
+                               int agp_offset);
+extern int           drmMarkBufs(int fd, double low, double high);
+extern int           drmCreateContext(int fd, drmContextPtr handle);
+extern int           drmSetContextFlags(int fd, drmContext context,
+                                       drmContextFlags flags);
+extern int           drmGetContextFlags(int fd, drmContext context,
+                                       drmContextFlagsPtr flags);
+extern int           drmAddContextTag(int fd, drmContext context, void *tag);
+extern int           drmDelContextTag(int fd, drmContext context);
+extern void          *drmGetContextTag(int fd, drmContext context);
+extern drmContextPtr drmGetReservedContextList(int fd, int *count);
+extern void          drmFreeReservedContextList(drmContextPtr);
+extern int           drmSwitchToContext(int fd, drmContext context);
+extern int           drmDestroyContext(int fd, drmContext handle);
+extern int           drmCreateDrawable(int fd, drmDrawablePtr handle);
+extern int           drmDestroyDrawable(int fd, drmDrawable handle);
+extern int           drmCtlInstHandler(int fd, int irq);
+extern int           drmCtlUninstHandler(int fd);
+extern int           drmInstallSIGIOHandler(int fd,
+                                           void (*f)(int fd,
+                                                     void *oldctx,
+                                                     void *newctx));
+extern int           drmRemoveSIGIOHandler(int fd);
+
+/* General user-level programmer's API: authenticated client and/or X */
+extern int           drmMap(int fd,
+                           drmHandle handle,
+                           drmSize size,
+                           drmAddressPtr address);
+extern int           drmUnmap(drmAddress address, drmSize size);
+extern drmBufInfoPtr drmGetBufInfo(int fd);
+extern drmBufMapPtr  drmMapBufs(int fd);
+extern int           drmUnmapBufs(drmBufMapPtr bufs);
+extern int           drmDMA(int fd, drmDMAReqPtr request);
+extern int           drmFreeBufs(int fd, int count, int *list);
+extern int           drmGetLock(int fd,
+                               drmContext context,
+                               drmLockFlags flags);
+extern int           drmUnlock(int fd, drmContext context);
+extern int           drmFinish(int fd, int context, drmLockFlags flags);
+extern int          drmGetContextPrivateMapping(int fd, drmContext ctx_id, 
+                                                drmHandlePtr handle);
+
+/* AGP/GART support: X server (root) only */
+extern int           drmAgpAcquire(int fd);
+extern int           drmAgpRelease(int fd);
+extern int           drmAgpEnable(int fd, unsigned long mode);
+extern int           drmAgpAlloc(int fd, unsigned long size,
+                                unsigned long type, unsigned long *address,
+                                unsigned long *handle);
+extern int           drmAgpFree(int fd, unsigned long handle);
+extern int          drmAgpBind(int fd, unsigned long handle,
+                               unsigned long offset);
+extern int           drmAgpUnbind(int fd, unsigned long handle);
+
+/* AGP/GART info: authenticated client and/or X */
+extern int           drmAgpVersionMajor(int fd);
+extern int           drmAgpVersionMinor(int fd);
+extern unsigned long drmAgpGetMode(int fd);
+extern unsigned long drmAgpBase(int fd); /* Physical location */
+extern unsigned long drmAgpSize(int fd); /* Bytes */
+extern unsigned long drmAgpMemoryUsed(int fd);
+extern unsigned long drmAgpMemoryAvail(int fd);
+extern unsigned int  drmAgpVendorId(int fd);
+extern unsigned int  drmAgpDeviceId(int fd);
+
+/* PCI scatter/gather support: X server (root) only */
+extern int           drmScatterGatherAlloc(int fd, unsigned long size,
+                                          unsigned long *handle);
+extern int           drmScatterGatherFree(int fd, unsigned long handle);
+
+extern int           drmWaitVBlank(int fd, drmVBlankPtr vbl);
+
+/* Support routines */
+extern int           drmError(int err, const char *label);
+extern void          *drmMalloc(int size);
+extern void          drmFree(void *pt);
+
+/* Hash table routines */
+extern void *drmHashCreate(void);
+extern int  drmHashDestroy(void *t);
+extern int  drmHashLookup(void *t, unsigned long key, void **value);
+extern int  drmHashInsert(void *t, unsigned long key, void *value);
+extern int  drmHashDelete(void *t, unsigned long key);
+extern int  drmHashFirst(void *t, unsigned long *key, void **value);
+extern int  drmHashNext(void *t, unsigned long *key, void **value);
+
+/* PRNG routines */
+extern void          *drmRandomCreate(unsigned long seed);
+extern int           drmRandomDestroy(void *state);
+extern unsigned long drmRandom(void *state);
+extern double        drmRandomDouble(void *state);
+
+/* Skip list routines */
+
+extern void *drmSLCreate(void);
+extern int  drmSLDestroy(void *l);
+extern int  drmSLLookup(void *l, unsigned long key, void **value);
+extern int  drmSLInsert(void *l, unsigned long key, void *value);
+extern int  drmSLDelete(void *l, unsigned long key);
+extern int  drmSLNext(void *l, unsigned long *key, void **value);
+extern int  drmSLFirst(void *l, unsigned long *key, void **value);
+extern void drmSLDump(void *l);
+extern int  drmSLLookupNeighbors(void *l, unsigned long key,
+                                unsigned long *prev_key, void **prev_value,
+                                unsigned long *next_key, void **next_value);
+
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86dri.h b/src/mesa/drivers/dri/dri_client/xf86dri.h
new file mode 100644 (file)
index 0000000..013f5b3
--- /dev/null
@@ -0,0 +1,221 @@
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.8 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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>
+ *
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <xf86drm.h>
+
+#define X_XF86DRIQueryVersion                  0
+#define X_XF86DRIQueryDirectRenderingCapable   1
+#define X_XF86DRIOpenConnection                        2
+#define X_XF86DRICloseConnection               3
+#define X_XF86DRIGetClientDriverName           4
+#define X_XF86DRICreateContext                 5
+#define X_XF86DRIDestroyContext                        6
+#define X_XF86DRICreateDrawable                        7
+#define X_XF86DRIDestroyDrawable               8
+#define X_XF86DRIGetDrawableInfo               9
+#define X_XF86DRIGetDeviceInfo                 10
+#define X_XF86DRIAuthConnection                 11
+#define X_XF86DRIOpenFullScreen                 12   /* Deprecated */
+#define X_XF86DRICloseFullScreen                13   /* Deprecated */
+
+#define XF86DRINumberEvents            0
+
+#define XF86DRIClientNotLocal          0
+#define XF86DRIOperationNotSupported   1
+#define XF86DRINumberErrors            (XF86DRIOperationNotSupported + 1)
+
+/* Warning : Do not change XF86DRIClipRect without changing the kernel 
+ * structure! */
+typedef struct _XF86DRIClipRect {
+    unsigned short     x1; /* Upper left: inclusive */
+    unsigned short     y1;
+    unsigned short     x2; /* Lower right: exclusive */
+    unsigned short     y2;
+} XF86DRIClipRectRec, *XF86DRIClipRectPtr;
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+
+Bool XF86DRIQueryExtension(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int*               /* event_base */,
+    int*               /* error_base */
+#endif
+);
+
+Bool XF86DRIQueryVersion(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int*               /* majorVersion */,
+    int*               /* minorVersion */,
+    int*               /* patchVersion */
+#endif
+);
+
+Bool XF86DRIQueryDirectRenderingCapable(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    Bool*              /* isCapable */
+#endif
+);
+
+Bool XF86DRIOpenConnection(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    drmHandlePtr       /* hSAREA */,
+    char**             /* busIDString */
+#endif
+);
+
+Bool XF86DRIAuthConnection(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    drmMagic            /* magic */
+#endif
+);
+
+Bool XF86DRICloseConnection(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */
+#endif
+);
+
+Bool XF86DRIGetClientDriverName(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    int*               /* ddxDriverMajorVersion */,
+    int*               /* ddxDriverMinorVersion */,
+    int*               /* ddxDriverPatchVersion */,
+    char**             /* clientDriverName */
+#endif
+);
+
+Bool XF86DRICreateContext(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    Visual*            /* visual */,
+    XID*               /* ptr to returned context id */,
+    drmContextPtr      /* hHWContext */
+#endif
+);
+
+Bool XF86DRICreateContextWithConfig(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    int                        /* visual ID / fbconfig ID */,
+    XID*               /* ptr to returned context id */,
+    drmContextPtr      /* hHWContext */
+#endif
+);
+
+Bool XF86DRIDestroyContext(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    XID                /* context id */
+#endif
+);
+
+Bool XF86DRICreateDrawable(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    Drawable           /* drawable */,
+    drmDrawablePtr     /* hHWDrawable */
+#endif
+);
+
+Bool XF86DRIDestroyDrawable(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    Drawable           /* drawable */
+#endif
+);
+
+Bool XF86DRIGetDrawableInfo(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    Drawable           /* drawable */,
+    unsigned int*      /* index */,
+    unsigned int*      /* stamp */,
+    int*               /* X */,
+    int*               /* Y */,
+    int*               /* W */,
+    int*               /* H */,
+    int*               /* numClipRects */,
+    XF86DRIClipRectPtr*,/* pClipRects */
+    int*               /* backX */,
+    int*               /* backY */,
+    int*               /* numBackClipRects */,
+    XF86DRIClipRectPtr*        /* pBackClipRects */    
+#endif
+);
+
+Bool XF86DRIGetDeviceInfo(
+#if NeedFunctionPrototypes
+    Display*           /* dpy */,
+    int                        /* screen */,
+    drmHandlePtr       /* hFrameBuffer */,
+    int*               /* fbOrigin */,
+    int*               /* fbSize */,
+    int*               /* fbStride */,
+    int*               /* devPrivateSize */,
+    void**             /* pDevPrivate */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/src/mesa/drivers/dri/dri_client/xf86dristr.h b/src/mesa/drivers/dri/dri_client/xf86dristr.h
new file mode 100644 (file)
index 0000000..ac05b18
--- /dev/null
@@ -0,0 +1,343 @@
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.10 2002/10/30 12:51:25 alanh Exp $ */
+/**************************************************************************
+
+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) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number.  This was originally set to be the same of the
+ * XFree86 version number.  However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ *    4.0.0: Original
+ *    4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ *    4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION  4
+#define XF86DRI_MINOR_VERSION  1
+#define XF86DRI_PATCH_VERSION  0
+
+typedef struct _XF86DRIQueryVersion {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIQueryVersion */
+    CARD16     length B16;
+} xXF86DRIQueryVersionReq;
+#define sz_xXF86DRIQueryVersionReq     4
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD16     majorVersion B16;       /* major version of DRI protocol */
+    CARD16     minorVersion B16;       /* minor version of DRI protocol */
+    CARD32     patchVersion B32;       /* patch version of DRI protocol */
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRIQueryVersionReply;
+#define sz_xXF86DRIQueryVersionReply   32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* X_DRIQueryDirectRenderingCapable */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+#define sz_xXF86DRIQueryDirectRenderingCapableReq      8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    BOOL       isCapable;
+    BOOL       pad2;
+    BOOL       pad3;
+    BOOL       pad4;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+    CARD32     pad7 B32;
+    CARD32     pad8 B32;
+    CARD32     pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+#define sz_xXF86DRIQueryDirectRenderingCapableReply    32
+
+typedef struct _XF86DRIOpenConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIOpenConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIOpenConnectionReq;
+#define sz_xXF86DRIOpenConnectionReq   8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hSAREALow B32;
+    CARD32     hSAREAHigh B32;
+    CARD32     busIdStringLength B32;
+    CARD32     pad6 B32;
+    CARD32     pad7 B32;
+    CARD32     pad8 B32;
+} xXF86DRIOpenConnectionReply;
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICloseConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32      magic B32;
+} xXF86DRIAuthConnectionReq;
+#define sz_xXF86DRIAuthConnectionReq   12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      authenticated B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+} xXF86DRIAuthConnectionReply;
+#define zx_xXF86DRIAuthConnectionReply  32
+
+typedef struct _XF86DRICloseConnection {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICloseConnection */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRICloseConnectionReq;
+#define sz_xXF86DRICloseConnectionReq  8
+
+typedef struct _XF86DRIGetClientDriverName {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetClientDriverName */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIGetClientDriverNameReq;
+#define sz_xXF86DRIGetClientDriverNameReq      8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     ddxDriverMajorVersion B32;
+    CARD32     ddxDriverMinorVersion B32;
+    CARD32     ddxDriverPatchVersion B32;
+    CARD32     clientDriverNameLength B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+#define sz_xXF86DRIGetClientDriverNameReply    32
+
+typedef struct _XF86DRICreateContext {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICreateContext */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     visual B32;
+    CARD32     context B32;
+} xXF86DRICreateContextReq;
+#define sz_xXF86DRICreateContextReq    16
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hHWContext B32;
+    CARD32     pad2 B32;
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRICreateContextReply;
+#define sz_xXF86DRICreateContextReply  32
+
+typedef struct _XF86DRIDestroyContext {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIDestroyContext */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     context B32;
+} xXF86DRIDestroyContextReq;
+#define sz_xXF86DRIDestroyContextReq   12
+
+typedef struct _XF86DRICreateDrawable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRICreateDrawable */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRICreateDrawableReq;
+#define sz_xXF86DRICreateDrawableReq   12
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hHWDrawable B32;
+    CARD32     pad2 B32;
+    CARD32     pad3 B32;
+    CARD32     pad4 B32;
+    CARD32     pad5 B32;
+    CARD32     pad6 B32;
+} xXF86DRICreateDrawableReply;
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIDestroyDrawable */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRIDestroyDrawableReq;
+#define sz_xXF86DRIDestroyDrawableReq  12
+
+typedef struct _XF86DRIGetDrawableInfo {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetDrawableInfo */
+    CARD16     length B16;
+    CARD32     screen B32;
+    CARD32     drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+#define sz_xXF86DRIGetDrawableInfoReq  12
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     drawableTableIndex B32;
+    CARD32     drawableTableStamp B32;
+    INT16      drawableX B16;
+    INT16      drawableY B16;
+    INT16      drawableWidth B16;
+    INT16      drawableHeight B16;
+    CARD32     numClipRects B32;
+    INT16       backX B16;
+    INT16       backY B16;
+    CARD32      numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply        36
+
+
+typedef struct _XF86DRIGetDeviceInfo {
+    CARD8      reqType;                /* always DRIReqCode */
+    CARD8      driReqType;             /* always X_DRIGetDeviceInfo */
+    CARD16     length B16;
+    CARD32     screen B32;
+} xXF86DRIGetDeviceInfoReq;
+#define sz_xXF86DRIGetDeviceInfoReq    8
+
+typedef struct {
+    BYTE       type;                   /* X_Reply */
+    BOOL       pad1;
+    CARD16     sequenceNumber B16;
+    CARD32     length B32;
+    CARD32     hFrameBufferLow B32;
+    CARD32     hFrameBufferHigh B32;
+    CARD32     framebufferOrigin B32;
+    CARD32     framebufferSize B32;
+    CARD32     framebufferStride B32;
+    CARD32     devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+#define sz_xXF86DRIGetDeviceInfoReply  32
+
+typedef struct _XF86DRIOpenFullScreen {
+    CARD8       reqType;       /* always DRIReqCode */
+    CARD8       driReqType;    /* always X_DRIOpenFullScreen */
+    CARD16      length B16;
+    CARD32      screen B32;
+    CARD32      drawable B32;
+} xXF86DRIOpenFullScreenReq;
+#define sz_xXF86DRIOpenFullScreenReq    12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      isFullScreen B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+#define sz_xXF86DRIOpenFullScreenReply  32
+
+typedef struct _XF86DRICloseFullScreen {
+    CARD8       reqType;       /* always DRIReqCode */
+    CARD8       driReqType;    /* always X_DRICloseFullScreen */
+    CARD16      length B16;
+    CARD32      screen B32;
+    CARD32      drawable B32;
+} xXF86DRICloseFullScreenReq;
+#define sz_xXF86DRICloseFullScreenReq   12
+
+typedef struct {
+    BYTE        type;
+    BOOL        pad1;
+    CARD16      sequenceNumber B16;
+    CARD32      length B32;
+    CARD32      pad2 B32;
+    CARD32      pad3 B32;
+    CARD32      pad4 B32;
+    CARD32      pad5 B32;
+    CARD32      pad6 B32;
+    CARD32      pad7 B32;
+} xXF86DRICloseFullScreenReply;
+#define sz_xXF86DRICloseFullScreenReply  32
+
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/src/mesa/drivers/dri/dri_client/xf86drm.c b/src/mesa/drivers/dri/dri_client/xf86drm.c
new file mode 100644 (file)
index 0000000..23750b9
--- /dev/null
@@ -0,0 +1,2326 @@
+/**
+ * \file xf86drm.c 
+ * User-level interface to DRM device
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Kevin E. Martin <martin@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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
+ * 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */
+
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "drm.h"
+# include "xf86_ansic.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE   xfree
+# ifndef XFree86LOADER
+#  include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# define stat_t struct stat
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# ifdef DRM_USE_MALLOC
+#  define _DRM_MALLOC malloc
+#  define _DRM_FREE   free
+extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern int xf86RemoveSIGIOHandler(int fd);
+# else
+#  include <X11/Xlibint.h>
+#  define _DRM_MALLOC Xmalloc
+#  define _DRM_FREE   Xfree
+# endif
+# include "drm.h"
+#endif
+
+/* No longer needed with CVS kernel modules on alpha 
+#if defined(__alpha__) && defined(__linux__)
+extern unsigned long _bus_base(void);
+#define BUS_BASE _bus_base()
+#endif
+*/
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "xf86drm.h"
+
+#ifdef __FreeBSD__
+#define DRM_MAJOR 145
+#endif
+
+#ifdef __NetBSD__
+#define DRM_MAJOR 34
+#endif
+
+# ifdef __OpenBSD__
+#  define DRM_MAJOR 81
+# endif
+
+#ifndef DRM_MAJOR
+#define DRM_MAJOR 226          /* Linux */
+#endif
+
+#ifndef DRM_MAX_MINOR
+#define DRM_MAX_MINOR 16
+#endif
+
+#ifdef __linux__
+#include <sys/sysmacros.h>     /* for makedev() */
+#endif
+
+#ifndef makedev
+                               /* This definition needs to be changed on
+                                   some systems if dev_t is a structure.
+                                   If there is a header file we can get it
+                                   from, there would be best. */
+#define makedev(x,y)    ((dev_t)(((x) << 8) | (y)))
+#endif
+
+#define DRM_MSG_VERBOSITY 3
+
+/**
+ * Output a message to stderr.
+ *
+ * \param format printf() like format string.
+ *
+ * \internal
+ * This function is a wrapper around vfprintf().
+ */
+static void
+drmMsg(const char *format, ...)
+{
+    va_list    ap;
+
+#ifndef XFree86Server
+    const char *env;
+    if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose"))
+#endif
+    {
+       va_start(ap, format);
+#ifdef XFree86Server
+       xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
+#else
+       vfprintf(stderr, format, ap);
+#endif
+       va_end(ap);
+    }
+}
+
+static void *drmHashTable = NULL; /* Context switch callbacks */
+
+typedef struct drmHashEntry {
+    int      fd;
+    void     (*f)(int, void *, void *);
+    void     *tagTable;
+} drmHashEntry;
+
+void *drmMalloc(int size)
+{
+    void *pt;
+    if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size);
+    return pt;
+}
+
+void drmFree(void *pt)
+{
+    if (pt) _DRM_FREE(pt);
+}
+
+/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */
+static char *drmStrdup(const char *s)
+{
+    char *retval = NULL;
+
+    if (s) {
+       retval = _DRM_MALLOC(strlen(s)+1);
+       strcpy(retval, s);
+    }
+    return retval;
+}
+
+
+static unsigned long drmGetKeyFromFd(int fd)
+{
+    stat_t     st;
+
+    st.st_rdev = 0;
+    fstat(fd, &st);
+    return st.st_rdev;
+}
+
+static drmHashEntry *drmGetEntry(int fd)
+{
+    unsigned long key = drmGetKeyFromFd(fd);
+    void          *value;
+    drmHashEntry  *entry;
+
+    if (!drmHashTable) drmHashTable = drmHashCreate();
+
+    if (drmHashLookup(drmHashTable, key, &value)) {
+       entry           = drmMalloc(sizeof(*entry));
+       entry->fd       = fd;
+       entry->f        = NULL;
+       entry->tagTable = drmHashCreate();
+       drmHashInsert(drmHashTable, key, entry);
+    } else {
+       entry = value;
+    }
+    return entry;
+}
+
+/**
+ * Compare two busid strings
+ *
+ * \param first
+ * \param second
+ *
+ * \return 1 if matched.
+ *
+ * \internal
+ * This function compares two bus ID strings.  It understands the older
+ * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format.  In the format, o is
+ * domain, b is bus, d is device, f is function.
+ */
+static int drmMatchBusID(const char *id1, const char *id2)
+{
+    /* First, check if the IDs are exactly the same */
+    if (strcasecmp(id1, id2) == 0)
+       return 1;
+
+    /* Try to match old/new-style PCI bus IDs. */
+    if (strncasecmp(id1, "pci", 3) == 0) {
+       int o1, b1, d1, f1;
+       int o2, b2, d2, f2;
+       int ret;
+
+       ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1);
+       if (ret != 4) {
+           o1 = 0;
+           ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1);
+           if (ret != 3)
+               return 0;
+       }
+
+       ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2);
+       if (ret != 4) {
+           o2 = 0;
+           ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2);
+           if (ret != 3)
+               return 0;
+       }
+
+       if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
+           return 0;
+       else
+           return 1;
+    }
+    return 0;
+}
+
+/**
+ * Open the DRM device, creating it if necessary.
+ *
+ * \param dev major and minor numbers of the device.
+ * \param minor minor number of the device.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Assembles the device name from \p minor and opens it, creating the device
+ * special file node with the major and minor numbers specified by \p dev and
+ * parent directory if necessary and was called by root.
+ */
+static int drmOpenDevice(long dev, int minor)
+{
+    stat_t          st;
+    char            buf[64];
+    int             fd;
+    mode_t          devmode = DRM_DEV_MODE;
+    int             isroot  = !geteuid();
+#if defined(XFree86Server)
+    uid_t           user    = DRM_DEV_UID;
+    gid_t           group   = DRM_DEV_GID;
+#endif
+
+    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    drmMsg("drmOpenDevice: node name is %s\n", buf);
+
+#if defined(XFree86Server)
+    devmode  = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
+    devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
+    group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID;
+#endif
+
+    if (stat(DRM_DIR_NAME, &st)) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+       chown(DRM_DIR_NAME, 0, 0); /* root:root */
+       chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+    }
+
+    /* Check if the device node exists and create it if necessary. */
+    if (stat(buf, &st)) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       remove(buf);
+       mknod(buf, S_IFCHR | devmode, dev);
+    }
+#if defined(XFree86Server)
+    chown(buf, user, group);
+    chmod(buf, devmode);
+#endif
+
+    fd = open(buf, O_RDWR, 0);
+    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+               fd, fd < 0 ? strerror(errno) : "OK");
+    if (fd >= 0) return fd;
+
+    /* Check if the device node is not what we expect it to be, and recreate it
+     * and try again if so.
+     */
+    if (st.st_rdev != dev) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       remove(buf);
+       mknod(buf, S_IFCHR | devmode, dev);
+#if defined(XFree86Server)
+       chown(buf, user, group);
+       chmod(buf, devmode);
+#endif
+    }
+    fd = open(buf, O_RDWR, 0);
+    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+               fd, fd < 0 ? strerror(errno) : "OK");
+    if (fd >= 0) return fd;
+
+    drmMsg("drmOpenDevice: Open failed\n");
+    remove(buf);
+    return -errno;
+}
+
+
+/**
+ * Open the DRM device
+ *
+ * \param minor device minor number.
+ * \param create allow to create the device if set.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
+ * name from \p minor and opens it.
+ */
+static int drmOpenMinor(int minor, int create)
+{
+    int  fd;
+    char buf[64];
+    
+    if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+    
+    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+    return -errno;
+}
+
+
+/**
+ * Determine whether the DRM kernel driver has been loaded.
+ * 
+ * \return 1 if the DRM driver is loaded, 0 otherwise.
+ *
+ * \internal 
+ * Determine the presence of the kernel driver by attempting to open the 0
+ * minor and get version information.  For backward compatibility with older
+ * Linux implementations, /proc/dri is also checked.
+ */
+int drmAvailable(void)
+{
+    drmVersionPtr version;
+    int           retval = 0;
+    int           fd;
+
+    if ((fd = drmOpenMinor(0, 1)) < 0) {
+#ifdef __linux__
+                               /* Try proc for backward Linux compatibility */
+       if (!access("/proc/dri/0", R_OK)) return 1;
+#endif
+       return 0;
+    }
+    
+    if ((version = drmGetVersion(fd))) {
+       retval = 1;
+       drmFreeVersion(version);
+    }
+    close(fd);
+
+    return retval;
+}
+
+
+/**
+ * Open the device by bus ID.
+ *
+ * \param busid bus ID.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
+ * comparing the device bus ID with the one supplied.
+ *
+ * \sa drmOpenMinor() and drmGetBusid().
+ */
+static int drmOpenByBusid(const char *busid)
+{
+    int        i;
+    int        fd;
+    const char *buf;
+    drmSetVersion sv;
+
+    drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+       fd = drmOpenMinor(i, 1);
+       drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
+       if (fd >= 0) {
+           sv.drm_di_major = 1;
+           sv.drm_di_minor = 1;
+           sv.drm_dd_major = -1;       /* Don't care */
+           drmSetInterfaceVersion(fd, &sv);
+           buf = drmGetBusid(fd);
+           drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
+           if (buf && drmMatchBusID(buf, busid)) {
+               drmFreeBusid(buf);
+               return fd;
+           }
+           if (buf) drmFreeBusid(buf);
+           close(fd);
+       }
+    }
+    return -1;
+}
+
+
+/**
+ * Open the device by name.
+ *
+ * \param name driver name.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * This function opens the first minor number that matches the driver name and
+ * isn't already in use.  If it's in use it then it will already have a bus ID
+ * assigned.
+ * 
+ * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
+ */
+static int drmOpenByName(const char *name)
+{
+    int           i;
+    int           fd;
+    drmVersionPtr version;
+    char *        id;
+    
+    if (!drmAvailable()) {
+#if !defined(XFree86Server)
+       return -1;
+#else
+        /* try to load the kernel module now */
+        if (!xf86LoadKernelModule(name)) {
+            ErrorF("[drm] failed to load kernel module \"%s\"\n",
+                  name);
+            return -1;
+        }
+#endif
+    }
+
+    /*
+     * Open the first minor number that matches the driver name and isn't
+     * already in use.  If it's in use it will have a busid assigned already.
+     */
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+       if ((fd = drmOpenMinor(i, 1)) >= 0) {
+           if ((version = drmGetVersion(fd))) {
+               if (!strcmp(version->name, name)) {
+                   drmFreeVersion(version);
+                   id = drmGetBusid(fd);
+                   drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
+                   if (!id || !*id) {
+                       if (id) {
+                           drmFreeBusid(id);
+                       }
+                       return fd;
+                   } else {
+                       drmFreeBusid(id);
+                   }
+               } else {
+                   drmFreeVersion(version);
+               }
+           }
+           close(fd);
+       }
+    }
+
+#ifdef __linux__
+                               /* Backward-compatibility /proc support */
+    for (i = 0; i < 8; i++) {
+       char proc_name[64], buf[512];
+       char *driver, *pt, *devstring;
+       int  retcode;
+       
+       sprintf(proc_name, "/proc/dri/%d/name", i);
+       if ((fd = open(proc_name, 0, 0)) >= 0) {
+           retcode = read(fd, buf, sizeof(buf)-1);
+           close(fd);
+           if (retcode) {
+               buf[retcode-1] = '\0';
+               for (driver = pt = buf; *pt && *pt != ' '; ++pt)
+                   ;
+               if (*pt) {      /* Device is next */
+                   *pt = '\0';
+                   if (!strcmp(driver, name)) { /* Match */
+                       for (devstring = ++pt; *pt && *pt != ' '; ++pt)
+                           ;
+                       if (*pt) { /* Found busid */
+                           return drmOpenByBusid(++pt);
+                       } else {        /* No busid */
+                           return drmOpenDevice(strtol(devstring, NULL, 0),i);
+                       }
+                   }
+               }
+           }
+       }
+    }
+#endif
+
+    return -1;
+}
+
+
+/**
+ * Open the DRM device.
+ *
+ * Looks up the specified name and bus ID, and opens the device found.  The
+ * entry in /dev/dri is created if necessary and if called by root.
+ *
+ * \param name driver name. Not referenced if bus ID is supplied.
+ * \param busid bus ID. Zero if not known.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
+ * otherwise.
+ */
+int drmOpen(const char *name, const char *busid)
+{
+#ifdef XFree86Server
+    if (!drmAvailable() && name != NULL) {
+       /* try to load the kernel */
+       if (!xf86LoadKernelModule(name)) {
+           ErrorF("[drm] failed to load kernel module \"%s\"\n",
+                  name);
+           return -1;
+       }
+    }
+#endif
+
+    if (busid) {
+       int fd;
+
+       fd = drmOpenByBusid(busid);
+       if (fd >= 0)
+           return fd;
+    }
+    if (name)
+       return drmOpenByName(name);
+    return -1;
+}
+
+
+/**
+ * Free the version information returned by drmGetVersion().
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * It frees the memory pointed by \p %v as well as all the non-null strings
+ * pointers in it.
+ */
+void drmFreeVersion(drmVersionPtr v)
+{
+    if (!v) return;
+    if (v->name) drmFree(v->name);
+    if (v->date) drmFree(v->date);
+    if (v->desc) drmFree(v->desc);
+    drmFree(v);
+}
+
+
+/**
+ * Free the non-public version information returned by the kernel.
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
+ * the non-null strings pointers in it.
+ */
+static void drmFreeKernelVersion(drm_version_t *v)
+{
+    if (!v) return;
+    if (v->name) drmFree(v->name);
+    if (v->date) drmFree(v->date);
+    if (v->desc) drmFree(v->desc);
+    drmFree(v);
+}
+
+
+/**
+ * Copy version information.
+ * 
+ * \param d destination pointer.
+ * \param s source pointer.
+ * 
+ * \internal
+ * Used by drmGetVersion() to translate the information returned by the ioctl
+ * interface in a private structure into the public structure counterpart.
+ */
+static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
+{
+    d->version_major      = s->version_major;
+    d->version_minor      = s->version_minor;
+    d->version_patchlevel = s->version_patchlevel;
+    d->name_len           = s->name_len;
+    d->name               = drmStrdup(s->name);
+    d->date_len           = s->date_len;
+    d->date               = drmStrdup(s->date);
+    d->desc_len           = s->desc_len;
+    d->desc               = drmStrdup(s->desc);
+}
+
+
+/**
+ * Query the driver version information.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return pointer to a drmVersion structure which should be freed with
+ * drmFreeVersion().
+ * 
+ * \note Similar information is available via /proc/dri.
+ * 
+ * \internal
+ * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
+ * first with zeros to get the string lengths, and then the actually strings.
+ * It also null-terminates them since they might not be already.
+ */
+drmVersionPtr drmGetVersion(int fd)
+{
+    drmVersionPtr retval;
+    drm_version_t *version = drmMalloc(sizeof(*version));
+
+                               /* First, get the lengths */
+    version->name_len    = 0;
+    version->name        = NULL;
+    version->date_len    = 0;
+    version->date        = NULL;
+    version->desc_len    = 0;
+    version->desc        = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+       drmFreeKernelVersion(version);
+       return NULL;
+    }
+
+                               /* Now, allocate space and get the data */
+    if (version->name_len)
+       version->name    = drmMalloc(version->name_len + 1);
+    if (version->date_len)
+       version->date    = drmMalloc(version->date_len + 1);
+    if (version->desc_len)
+       version->desc    = drmMalloc(version->desc_len + 1);
+
+    if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+       drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
+       drmFreeKernelVersion(version);
+       return NULL;
+    }
+
+                               /* The results might not be null-terminated
+                                   strings, so terminate them. */
+
+    if (version->name_len) version->name[version->name_len] = '\0';
+    if (version->date_len) version->date[version->date_len] = '\0';
+    if (version->desc_len) version->desc[version->desc_len] = '\0';
+
+                               /* Now, copy it all back into the
+                                   client-visible data structure... */
+    retval = drmMalloc(sizeof(*retval));
+    drmCopyVersion(retval, version);
+    drmFreeKernelVersion(version);
+    return retval;
+}
+
+
+/**
+ * Get version information for the DRM user space library.
+ * 
+ * This version number is driver independent.
+ * 
+ * \param fd file descriptor.
+ *
+ * \return version information.
+ * 
+ * \internal
+ * This function allocates and fills a drm_version structure with a hard coded
+ * version number.
+ */
+drmVersionPtr drmGetLibVersion(int fd)
+{
+    drm_version_t *version = drmMalloc(sizeof(*version));
+
+    /* Version history:
+     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
+     *                    entry point and many drm<Device> extensions
+     *   revision 1.1.x = added drmCommand entry points for device extensions
+     *                    added drmGetLibVersion to identify libdrm.a version
+     *   revision 1.2.x = added drmSetInterfaceVersion
+     *                    modified drmOpen to handle both busid and name
+     */
+    version->version_major      = 1;
+    version->version_minor      = 2;
+    version->version_patchlevel = 0;
+
+    return (drmVersionPtr)version;
+}
+
+
+/**
+ * Free the bus ID information.
+ *
+ * \param busid bus ID information string as given by drmGetBusid().
+ *
+ * \internal
+ * This function is just frees the memory pointed by \p busid.
+ */
+void drmFreeBusid(const char *busid)
+{
+    drmFree((void *)busid);
+}
+
+
+/**
+ * Get the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return bus ID string.
+ *
+ * \internal
+ * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
+ * get the string length and data, passing the arguments in a drm_unique
+ * structure.
+ */
+char *drmGetBusid(int fd)
+{
+    drm_unique_t u;
+
+    u.unique_len = 0;
+    u.unique     = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+    u.unique = drmMalloc(u.unique_len + 1);
+    if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+    u.unique[u.unique_len] = '\0';
+
+    return u.unique;
+}
+
+
+/**
+ * Set the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ * \param busid bus ID string.
+ *
+ * \return zero on success, negative on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
+ * the arguments in a drm_unique structure.
+ */
+int drmSetBusid(int fd, const char *busid)
+{
+    drm_unique_t u;
+
+    u.unique     = (char *)busid;
+    u.unique_len = strlen(busid);
+
+    if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
+       return -errno;
+    }
+    return 0;
+}
+
+int drmGetMagic(int fd, drmMagicPtr magic)
+{
+    drm_auth_t auth;
+
+    *magic = 0;
+    if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno;
+    *magic = auth.magic;
+    return 0;
+}
+
+int drmAuthMagic(int fd, drmMagic magic)
+{
+    drm_auth_t auth;
+
+    auth.magic = magic;
+    if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno;
+    return 0;
+}
+
+/**
+ * Specifies a range of memory that is available for mapping by a
+ * non-root process.
+ *
+ * \param fd file descriptor.
+ * \param offset usually the physical address. The actual meaning depends of
+ * the \p type parameter. See below.
+ * \param size of the memory in bytes.
+ * \param type type of the memory to be mapped.
+ * \param flags combination of several flags to modify the function actions.
+ * \param handle will be set to a value that may be used as the offset
+ * parameter for mmap().
+ * 
+ * \return zero on success or a negative value on error.
+ *
+ * \par Mapping the frame buffer
+ * For the frame buffer
+ * - \p offset will be the physical address of the start of the frame buffer,
+ * - \p size will be the size of the frame buffer in bytes, and
+ * - \p type will be DRM_FRAME_BUFFER.
+ *
+ * \par
+ * The area mapped will be uncached. If MTRR support is available in the
+ * kernel, the frame buffer area will be set to write combining. 
+ *
+ * \par Mapping the MMIO register area
+ * For the MMIO register area,
+ * - \p offset will be the physical address of the start of the register area,
+ * - \p size will be the size of the register area bytes, and
+ * - \p type will be DRM_REGISTERS.
+ * \par
+ * The area mapped will be uncached. 
+ * 
+ * \par Mapping the SAREA
+ * For the SAREA,
+ * - \p offset will be ignored and should be set to zero,
+ * - \p size will be the desired size of the SAREA in bytes,
+ * - \p type will be DRM_SHM.
+ * 
+ * \par
+ * A shared memory area of the requested size will be created and locked in
+ * kernel memory. This area may be mapped into client-space by using the handle
+ * returned. 
+ * 
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
+ * the arguments in a drm_map structure.
+ */
+int drmAddMap(int fd,
+             drmHandle offset,
+             drmSize size,
+             drmMapType type,
+             drmMapFlags flags,
+             drmHandlePtr handle)
+{
+    drm_map_t map;
+
+    map.offset  = offset;
+/* No longer needed with CVS kernel modules on alpha
+#ifdef __alpha__
+    if (type != DRM_SHM)
+       map.offset += BUS_BASE;
+#endif
+*/
+    map.size    = size;
+    map.handle  = 0;
+    map.type    = type;
+    map.flags   = flags;
+    if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
+    if (handle) *handle = (drmHandle)map.handle;
+    return 0;
+}
+
+int drmRmMap(int fd, drmHandle handle)
+{
+    drm_map_t map;
+
+    map.handle = (void *)handle;
+
+    if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno;
+    return 0;
+}
+
+/**
+ * Make buffers available for DMA transfers.
+ * 
+ * \param fd file descriptor.
+ * \param count number of buffers.
+ * \param size size of each buffer.
+ * \param flags buffer allocation flags.
+ * \param agp_offset offset in the AGP aperture 
+ *
+ * \return number of buffers allocated, negative on error.
+ *
+ * \internal
+ * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
+ *
+ * \sa drm_buf_desc.
+ */
+int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+              int agp_offset)
+{
+    drm_buf_desc_t request;
+
+    request.count     = count;
+    request.size      = size;
+    request.low_mark  = 0;
+    request.high_mark = 0;
+    request.flags     = flags;
+    request.agp_start = agp_offset;
+
+    if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
+    return request.count;
+}
+
+int drmMarkBufs(int fd, double low, double high)
+{
+    drm_buf_info_t info;
+    int            i;
+
+    info.count = 0;
+    info.list  = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
+
+    if (!info.count) return -EINVAL;
+
+    if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+       return -ENOMEM;
+
+    if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+       int retval = -errno;
+       drmFree(info.list);
+       return retval;
+    }
+
+    for (i = 0; i < info.count; i++) {
+       info.list[i].low_mark  = low  * info.list[i].count;
+       info.list[i].high_mark = high * info.list[i].count;
+       if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
+           int retval = -errno;
+           drmFree(info.list);
+           return retval;
+       }
+    }
+    drmFree(info.list);
+
+    return 0;
+}
+
+/**
+ * Free buffers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers to free.
+ * \param list list of buffers to be freed.
+ *
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note This function is primarily used for debugging.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
+ * the arguments in a drm_buf_free structure.
+ */
+int drmFreeBufs(int fd, int count, int *list)
+{
+    drm_buf_free_t request;
+
+    request.count = count;
+    request.list  = list;
+    if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Close the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \internal
+ * This function closes the file descriptor.
+ */
+int drmClose(int fd)
+{
+    unsigned long key    = drmGetKeyFromFd(fd);
+    drmHashEntry  *entry = drmGetEntry(fd);
+
+    drmHashDestroy(entry->tagTable);
+    entry->fd       = 0;
+    entry->f        = NULL;
+    entry->tagTable = NULL;
+
+    drmHashDelete(drmHashTable, key);
+    drmFree(entry);
+
+    return close(fd);
+}
+
+
+/**
+ * Map a region of memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle returned by drmAddMap().
+ * \param size size in bytes. Must match the size used by drmAddMap().
+ * \param address will contain the user-space virtual address where the mapping
+ * begins.
+ *
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper for mmap().
+ */
+int drmMap(int fd,
+          drmHandle handle,
+          drmSize size,
+          drmAddressPtr address)
+{
+    static unsigned long pagesize_mask = 0;
+
+    if (fd < 0) return -EINVAL;
+
+    if (!pagesize_mask)
+       pagesize_mask = getpagesize() - 1;
+
+    size = (size + pagesize_mask) & ~pagesize_mask;
+
+    *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
+    if (*address == MAP_FAILED) return -errno;
+    return 0;
+}
+
+
+/**
+ * Unmap mappings obtained with drmMap().
+ *
+ * \param address address as given by drmMap().
+ * \param size size in bytes. Must match the size used by drmMap().
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for unmap().
+ */
+int drmUnmap(drmAddress address, drmSize size)
+{
+    return munmap(address, size);
+}
+
+drmBufInfoPtr drmGetBufInfo(int fd)
+{
+    drm_buf_info_t info;
+    drmBufInfoPtr  retval;
+    int            i;
+
+    info.count = 0;
+    info.list  = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL;
+
+    if (info.count) {
+       if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+           return NULL;
+
+       if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+           drmFree(info.list);
+           return NULL;
+       }
+                               /* Now, copy it all back into the
+                                   client-visible data structure... */
+       retval = drmMalloc(sizeof(*retval));
+       retval->count = info.count;
+       retval->list  = drmMalloc(info.count * sizeof(*retval->list));
+       for (i = 0; i < info.count; i++) {
+           retval->list[i].count     = info.list[i].count;
+           retval->list[i].size      = info.list[i].size;
+           retval->list[i].low_mark  = info.list[i].low_mark;
+           retval->list[i].high_mark = info.list[i].high_mark;
+       }
+       drmFree(info.list);
+       return retval;
+    }
+    return NULL;
+}
+
+/**
+ * Map all DMA buffers into client-virtual space.
+ *
+ * \param fd file descriptor.
+ *
+ * \return a pointer to a ::drmBufMap structure.
+ *
+ * \note The client may not use these buffers until obtaining buffer indices
+ * with drmDMA().
+ * 
+ * \internal
+ * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
+ * information about the buffers in a drm_buf_map structure into the
+ * client-visible data structures.
+ */ 
+drmBufMapPtr drmMapBufs(int fd)
+{
+    drm_buf_map_t bufs;
+    drmBufMapPtr  retval;
+    int           i;
+
+    bufs.count = 0;
+    bufs.list  = NULL;
+    if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
+
+    if (bufs.count) {
+       if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
+           return NULL;
+
+       if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
+           drmFree(bufs.list);
+           return NULL;
+       }
+                               /* Now, copy it all back into the
+                                   client-visible data structure... */
+       retval = drmMalloc(sizeof(*retval));
+       retval->count = bufs.count;
+       retval->list  = drmMalloc(bufs.count * sizeof(*retval->list));
+       for (i = 0; i < bufs.count; i++) {
+           retval->list[i].idx     = bufs.list[i].idx;
+           retval->list[i].total   = bufs.list[i].total;
+           retval->list[i].used    = 0;
+           retval->list[i].address = bufs.list[i].address;
+       }
+       return retval;
+    }
+    return NULL;
+}
+
+
+/**
+ * Unmap buffers allocated with drmMapBufs().
+ *
+ * \return zero on success, or negative value on failure.
+ *
+ * \internal
+ * Calls munmap() for every buffer stored in \p bufs.
+ */
+int drmUnmapBufs(drmBufMapPtr bufs)
+{
+    int i;
+
+    for (i = 0; i < bufs->count; i++) {
+       munmap(bufs->list[i].address, bufs->list[i].total);
+    }
+    return 0;
+}
+
+
+#define DRM_DMA_RETRY          16
+
+/**
+ * Reserve DMA buffers.
+ *
+ * \param fd file descriptor.
+ * \param request 
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * Assemble the arguments into a drm_dma structure and keeps issuing the
+ * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
+ */
+int drmDMA(int fd, drmDMAReqPtr request)
+{
+    drm_dma_t dma;
+    int ret, i = 0;
+
+                               /* Copy to hidden structure */
+    dma.context         = request->context;
+    dma.send_count      = request->send_count;
+    dma.send_indices    = request->send_list;
+    dma.send_sizes      = request->send_sizes;
+    dma.flags           = request->flags;
+    dma.request_count   = request->request_count;
+    dma.request_size    = request->request_size;
+    dma.request_indices = request->request_list;
+    dma.request_sizes   = request->request_sizes;
+
+    do {
+       ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
+    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
+
+    if ( ret == 0 ) {
+       request->granted_count = dma.granted_count;
+       return 0;
+    } else {
+       return -errno;
+    }
+}
+
+
+/**
+ * Obtain heavyweight hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * \param flags flags that determine the sate of the hardware when the function
+ * returns.
+ * 
+ * \return always zero.
+ * 
+ * \internal
+ * This function translates the arguments into a drm_lock structure and issue
+ * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
+ */
+int drmGetLock(int fd, drmContext context, drmLockFlags flags)
+{
+    drm_lock_t lock;
+
+    lock.context = context;
+    lock.flags   = 0;
+    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
+    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
+    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
+    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
+    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+
+    while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
+       ;
+    return 0;
+}
+
+/**
+ * Release the hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
+ * argument in a drm_lock structure.
+ */
+int drmUnlock(int fd, drmContext context)
+{
+    drm_lock_t lock;
+
+    lock.context = context;
+    lock.flags   = 0;
+    return ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
+}
+
+drmContextPtr drmGetReservedContextList(int fd, int *count)
+{
+    drm_ctx_res_t res;
+    drm_ctx_t     *list;
+    drmContextPtr retval;
+    int           i;
+
+    res.count    = 0;
+    res.contexts = NULL;
+    if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+    if (!res.count) return NULL;
+
+    if (!(list   = drmMalloc(res.count * sizeof(*list)))) return NULL;
+    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
+       drmFree(list);
+       return NULL;
+    }
+
+    res.contexts = list;
+    if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+    for (i = 0; i < res.count; i++) retval[i] = list[i].handle;
+    drmFree(list);
+
+    *count = res.count;
+    return retval;
+}
+
+void drmFreeReservedContextList(drmContextPtr pt)
+{
+    drmFree(pt);
+}
+
+/**
+ * Create context.
+ *
+ * Used by the X server during GLXContext initialization. This causes
+ * per-context kernel-level resources to be allocated.
+ *
+ * \param fd file descriptor.
+ * \param handle is set on success. To be used by the client when requesting DMA
+ * dispatch with drmDMA().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note May only be called by root.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmCreateContext(int fd, drmContextPtr handle)
+{
+    drm_ctx_t ctx;
+
+    ctx.flags = 0;     /* Modified with functions below */
+    if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
+    *handle = ctx.handle;
+    return 0;
+}
+
+int drmSwitchToContext(int fd, drmContext context)
+{
+    drm_ctx_t ctx;
+
+    ctx.handle = context;
+    if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno;
+    return 0;
+}
+
+int drmSetContextFlags(int fd, drmContext context, drmContextFlags flags)
+{
+    drm_ctx_t ctx;
+
+                               /* Context preserving means that no context
+                                   switched are done between DMA buffers
+                                   from one context and the next.  This is
+                                   suitable for use in the X server (which
+                                   promises to maintain hardware context,
+                                   or in the client-side library when
+                                   buffers are swapped on behalf of two
+                                   threads. */
+    ctx.handle = context;
+    ctx.flags  = 0;
+    if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED;
+    if (flags & DRM_CONTEXT_2DONLY)    ctx.flags |= _DRM_CONTEXT_2DONLY;
+    if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno;
+    return 0;
+}
+
+int drmGetContextFlags(int fd, drmContext context, drmContextFlagsPtr flags)
+{
+    drm_ctx_t ctx;
+
+    ctx.handle = context;
+    if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno;
+    *flags = 0;
+    if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED;
+    if (ctx.flags & _DRM_CONTEXT_2DONLY)    *flags |= DRM_CONTEXT_2DONLY;
+    return 0;
+}
+
+/**
+ * Destroy context.
+ *
+ * Free any kernel-level resources allocated with drmCreateContext() associated
+ * with the context.
+ * 
+ * \param fd file descriptor.
+ * \param handle handle given by drmCreateContext().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note May only be called by root.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmDestroyContext(int fd, drmContext handle)
+{
+    drm_ctx_t ctx;
+    ctx.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
+    return 0;
+}
+
+int drmCreateDrawable(int fd, drmDrawablePtr handle)
+{
+    drm_draw_t draw;
+    if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno;
+    *handle = draw.handle;
+    return 0;
+}
+
+int drmDestroyDrawable(int fd, drmDrawable handle)
+{
+    drm_draw_t draw;
+    draw.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno;
+    return 0;
+}
+
+/**
+ * Acquire the AGP device.
+ *
+ * Must be called before any of the other AGP related calls.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
+ */
+int drmAgpAcquire(int fd)
+{
+    if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Release the AGP device.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
+ */
+int drmAgpRelease(int fd)
+{
+    if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Set the AGP mode.
+ *
+ * \param fd file descriptor.
+ * \param mode AGP mode.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
+ * argument in a drm_agp_mode structure.
+ */
+int drmAgpEnable(int fd, unsigned long mode)
+{
+    drm_agp_mode_t m;
+
+    m.mode = mode;
+    if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Allocate a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param size requested memory size in bytes. Will be rounded to page boundary.
+ * \param type type of memory to allocate.
+ * \param address if not zero, will be set to the physical address of the
+ * allocated memory.
+ * \param handle on success will be set to a handle of the allocated memory.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
+ * arguments in a drm_agp_buffer structure.
+ */
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+               unsigned long *address, unsigned long *handle)
+{
+    drm_agp_buffer_t b;
+
+    *handle = DRM_AGP_NO_HANDLE;
+    b.size   = size;
+    b.handle = 0;
+    b.type   = type;
+    if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
+    if (address != 0UL) *address = b.physical;
+    *handle = b.handle;
+    return 0;
+}
+
+
+/**
+ * Free a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
+ * argument in a drm_agp_buffer structure.
+ */
+int drmAgpFree(int fd, unsigned long handle)
+{
+    drm_agp_buffer_t b;
+
+    b.size   = 0;
+    b.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Bind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * \param offset offset in bytes. It will round to page boundary.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
+ * argument in a drm_agp_binding structure.
+ */
+int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
+{
+    drm_agp_binding_t b;
+
+    b.handle = handle;
+    b.offset = offset;
+    if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Unbind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
+ * the argument in a drm_agp_binding structure.
+ */
+int drmAgpUnbind(int fd, unsigned long handle)
+{
+    drm_agp_binding_t b;
+
+    b.handle = handle;
+    b.offset = 0;
+    if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Get AGP driver major version number.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return major version number on success, or a negative value on failure..
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMajor(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+    return i.agp_version_major;
+}
+
+
+/**
+ * Get AGP driver minor version number.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return minor version number on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMinor(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+    return i.agp_version_minor;
+}
+
+
+/**
+ * Get AGP mode.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return mode on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpGetMode(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.mode;
+}
+
+
+/**
+ * Get AGP aperture base.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return aperture base on success, zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpBase(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.aperture_base;
+}
+
+
+/**
+ * Get AGP aperture size.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return aperture size on success, zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpSize(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.aperture_size;
+}
+
+
+/**
+ * Get used AGP memory.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return memory used on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryUsed(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.memory_used;
+}
+
+
+/**
+ * Get available AGP memory.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return memory available on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryAvail(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.memory_allowed;
+}
+
+
+/**
+ * Get hardware vendor ID.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return vendor ID on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpVendorId(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.id_vendor;
+}
+
+
+/**
+ * Get hardware device ID.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpDeviceId(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.id_device;
+}
+
+int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
+{
+    drm_scatter_gather_t sg;
+
+    *handle = 0;
+    sg.size   = size;
+    sg.handle = 0;
+    if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+    *handle = sg.handle;
+    return 0;
+}
+
+int drmScatterGatherFree(int fd, unsigned long handle)
+{
+    drm_scatter_gather_t sg;
+
+    sg.size   = 0;
+    sg.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+    return 0;
+}
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param fd file descriptor.
+ * \param vbl pointer to a drmVBlank structure.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
+ */
+int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+{
+    int ret;
+
+    do {
+       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+       vbl->request.type &= ~DRM_VBLANK_RELATIVE;
+    } while (ret && errno == EINTR);
+
+    return ret;
+}
+
+int drmError(int err, const char *label)
+{
+    switch (err) {
+    case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label);   break;
+    case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label);   break;
+    case DRM_ERR_NOT_ROOT:  fprintf(stderr, "%s: not root\n", label);    break;
+    case DRM_ERR_INVALID:   fprintf(stderr, "%s: invalid args\n", label);break;
+    default:
+       if (err < 0) err = -err;
+       fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
+       break;
+    }
+
+    return 1;
+}
+
+/**
+ * Install IRQ handler.
+ *
+ * \param fd file descriptor.
+ * \param irq IRQ number.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlInstHandler(int fd, int irq)
+{
+    drm_control_t ctl;
+
+    ctl.func  = DRM_INST_HANDLER;
+    ctl.irq   = irq;
+    if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+    return 0;
+}
+
+
+/**
+ * Uninstall IRQ handler.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlUninstHandler(int fd)
+{
+    drm_control_t ctl;
+
+    ctl.func  = DRM_UNINST_HANDLER;
+    ctl.irq   = 0;
+    if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+    return 0;
+}
+
+int drmFinish(int fd, int context, drmLockFlags flags)
+{
+    drm_lock_t lock;
+
+    lock.context = context;
+    lock.flags   = 0;
+    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
+    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
+    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
+    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
+    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+    if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno;
+    return 0;
+}
+
+/**
+ * Get IRQ from bus ID.
+ *
+ * \param fd file descriptor.
+ * \param busnum bus number.
+ * \param devnum device number.
+ * \param funcnum function number.
+ * 
+ * \return IRQ number on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
+ * arguments in a drm_irq_busid structure.
+ */
+int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
+{
+    drm_irq_busid_t p;
+
+    p.busnum  = busnum;
+    p.devnum  = devnum;
+    p.funcnum = funcnum;
+    if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
+    return p.irq;
+}
+
+int drmAddContextTag(int fd, drmContext context, void *tag)
+{
+    drmHashEntry  *entry = drmGetEntry(fd);
+
+    if (drmHashInsert(entry->tagTable, context, tag)) {
+       drmHashDelete(entry->tagTable, context);
+       drmHashInsert(entry->tagTable, context, tag);
+    }
+    return 0;
+}
+
+int drmDelContextTag(int fd, drmContext context)
+{
+    drmHashEntry  *entry = drmGetEntry(fd);
+
+    return drmHashDelete(entry->tagTable, context);
+}
+
+void *drmGetContextTag(int fd, drmContext context)
+{
+    drmHashEntry  *entry = drmGetEntry(fd);
+    void          *value;
+
+    if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
+
+    return value;
+}
+
+int drmAddContextPrivateMapping(int fd, drmContext ctx_id, drmHandle handle)
+{
+    drm_ctx_priv_map_t map;
+
+    map.ctx_id = ctx_id;
+    map.handle = (void *)handle;
+
+    if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno;
+    return 0;
+}
+
+int drmGetContextPrivateMapping(int fd, drmContext ctx_id, drmHandlePtr handle)
+{
+    drm_ctx_priv_map_t map;
+
+    map.ctx_id = ctx_id;
+
+    if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno;
+    if (handle) *handle = (drmHandle)map.handle;
+
+    return 0;
+}
+
+int drmGetMap(int fd, int idx, drmHandle *offset, drmSize *size,
+             drmMapType *type, drmMapFlags *flags, drmHandle *handle,
+             int *mtrr)
+{
+    drm_map_t map;
+
+    map.offset = idx;
+    if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
+    *offset = map.offset;
+    *size   = map.size;
+    *type   = map.type;
+    *flags  = map.flags;
+    *handle = (unsigned long)map.handle;
+    *mtrr   = map.mtrr;
+    return 0;
+}
+
+int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
+                unsigned long *magic, unsigned long *iocs)
+{
+    drm_client_t client;
+
+    client.idx = idx;
+    if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
+    *auth      = client.auth;
+    *pid       = client.pid;
+    *uid       = client.uid;
+    *magic     = client.magic;
+    *iocs      = client.iocs;
+    return 0;
+}
+
+int drmGetStats(int fd, drmStatsT *stats)
+{
+    drm_stats_t s;
+    int         i;
+
+    if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
+
+    stats->count = 0;
+    memset(stats, 0, sizeof(*stats));
+    if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
+       return -1;
+
+#define SET_VALUE                              \
+    stats->data[i].long_format = "%-20.20s";   \
+    stats->data[i].rate_format = "%8.8s";      \
+    stats->data[i].isvalue     = 1;            \
+    stats->data[i].verbose     = 0
+
+#define SET_COUNT                              \
+    stats->data[i].long_format = "%-20.20s";   \
+    stats->data[i].rate_format = "%5.5s";      \
+    stats->data[i].isvalue     = 0;            \
+    stats->data[i].mult_names  = "kgm";        \
+    stats->data[i].mult        = 1000;         \
+    stats->data[i].verbose     = 0
+
+#define SET_BYTE                               \
+    stats->data[i].long_format = "%-20.20s";   \
+    stats->data[i].rate_format = "%5.5s";      \
+    stats->data[i].isvalue     = 0;            \
+    stats->data[i].mult_names  = "KGM";        \
+    stats->data[i].mult        = 1024;         \
+    stats->data[i].verbose     = 0
+
+
+    stats->count = s.count;
+    for (i = 0; i < s.count; i++) {
+       stats->data[i].value = s.data[i].value;
+       switch (s.data[i].type) {
+       case _DRM_STAT_LOCK:
+           stats->data[i].long_name = "Lock";
+           stats->data[i].rate_name = "Lock";
+           SET_VALUE;
+           break;
+       case _DRM_STAT_OPENS:
+           stats->data[i].long_name = "Opens";
+           stats->data[i].rate_name = "O";
+           SET_COUNT;
+           stats->data[i].verbose   = 1;
+           break;
+       case _DRM_STAT_CLOSES:
+           stats->data[i].long_name = "Closes";
+           stats->data[i].rate_name = "Lock";
+           SET_COUNT;
+           stats->data[i].verbose   = 1;
+           break;
+       case _DRM_STAT_IOCTLS:
+           stats->data[i].long_name = "Ioctls";
+           stats->data[i].rate_name = "Ioc/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_LOCKS:
+           stats->data[i].long_name = "Locks";
+           stats->data[i].rate_name = "Lck/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_UNLOCKS:
+           stats->data[i].long_name = "Unlocks";
+           stats->data[i].rate_name = "Unl/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_IRQ:
+           stats->data[i].long_name = "IRQs";
+           stats->data[i].rate_name = "IRQ/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_PRIMARY:
+           stats->data[i].long_name = "Primary Bytes";
+           stats->data[i].rate_name = "PB/s";
+           SET_BYTE;
+           break;
+       case _DRM_STAT_SECONDARY:
+           stats->data[i].long_name = "Secondary Bytes";
+           stats->data[i].rate_name = "SB/s";
+           SET_BYTE;
+           break;
+       case _DRM_STAT_DMA:
+           stats->data[i].long_name = "DMA";
+           stats->data[i].rate_name = "DMA/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_SPECIAL:
+           stats->data[i].long_name = "Special DMA";
+           stats->data[i].rate_name = "dma/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_MISSED:
+           stats->data[i].long_name = "Miss";
+           stats->data[i].rate_name = "Ms/s";
+           SET_COUNT;
+           break;
+       case _DRM_STAT_VALUE:
+           stats->data[i].long_name = "Value";
+           stats->data[i].rate_name = "Value";
+           SET_VALUE;
+           break;
+       case _DRM_STAT_BYTE:
+           stats->data[i].long_name = "Bytes";
+           stats->data[i].rate_name = "B/s";
+           SET_BYTE;
+           break;
+       case _DRM_STAT_COUNT:
+       default:
+           stats->data[i].long_name = "Count";
+           stats->data[i].rate_name = "Cnt/s";
+           SET_COUNT;
+           break;
+       }
+    }
+    return 0;
+}
+
+/**
+ * Issue a set-version ioctl.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a read-write ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmSetInterfaceVersion(int fd, drmSetVersion *version )
+{
+    int retcode = 0;
+    drm_set_version_t sv;
+
+    sv.drm_di_major = version->drm_di_major;
+    sv.drm_di_minor = version->drm_di_minor;
+    sv.drm_dd_major = version->drm_dd_major;
+    sv.drm_dd_minor = version->drm_dd_minor;
+
+    if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
+       retcode = -errno;
+    }
+
+    version->drm_di_major = sv.drm_di_major;
+    version->drm_di_minor = sv.drm_di_minor;
+    version->drm_dd_major = sv.drm_dd_major;
+    version->drm_dd_minor = sv.drm_dd_minor;
+
+    return retcode;
+}
+
+/**
+ * Send a device-specific command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandNone(int fd, unsigned long drmCommandIndex)
+{
+    void *data = NULL; /* dummy */
+    unsigned long request;
+
+    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * Send a device-specific read command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data destination pointer of the data to be read.
+ * \param size size of the data to be read.
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandRead(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * Send a device-specific write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data source pointer of the data to be written.
+ * \param size size of the data to be written.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a write ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * Send a device-specific read-write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a read-write ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+#if defined(XFree86Server) || defined(DRM_USE_MALLOC)
+static void drmSIGIOHandler(int interrupt, void *closure)
+{
+    unsigned long key;
+    void          *value;
+    ssize_t       count;
+    drm_ctx_t     ctx;
+    typedef void  (*_drmCallback)(int, void *, void *);
+    char          buf[256];
+    drmContext    old;
+    drmContext    new;
+    void          *oldctx;
+    void          *newctx;
+    char          *pt;
+    drmHashEntry  *entry;
+
+    if (!drmHashTable) return;
+    if (drmHashFirst(drmHashTable, &key, &value)) {
+       entry = value;
+       do {
+#if 0
+           fprintf(stderr, "Trying %d\n", entry->fd);
+#endif
+           if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
+               buf[count] = '\0';
+#if 0
+               fprintf(stderr, "Got %s\n", buf);
+#endif
+
+               for (pt = buf; *pt != ' '; ++pt); /* Find first space */
+               ++pt;
+               old    = strtol(pt, &pt, 0);
+               new    = strtol(pt, NULL, 0);
+               oldctx = drmGetContextTag(entry->fd, old);
+               newctx = drmGetContextTag(entry->fd, new);
+#if 0
+               fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
+#endif
+               ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
+               ctx.handle = new;
+               ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
+           }
+       } while (drmHashNext(drmHashTable, &key, &value));
+    }
+}
+
+int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
+{
+    drmHashEntry     *entry;
+
+    entry     = drmGetEntry(fd);
+    entry->f  = f;
+
+    return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
+}
+
+int drmRemoveSIGIOHandler(int fd)
+{
+    drmHashEntry     *entry = drmGetEntry(fd);
+
+    entry->f = NULL;
+
+    return xf86RemoveSIGIOHandler(fd);
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmHash.c b/src/mesa/drivers/dri/dri_client/xf86drmHash.c
new file mode 100644 (file)
index 0000000..1f1a05b
--- /dev/null
@@ -0,0 +1,435 @@
+/* xf86drmHash.c -- Small hash table support for integer -> integer mapping
+ * Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com
+ *
+ * Copyright 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, 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
+ * 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: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.4 2001/03/21 18:08:54 dawes Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward implementation of a fixed-sized
+ * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
+ * collision resolution.  There are two potentially interesting things
+ * about this implementation:
+ *
+ * 1) The table is power-of-two sized.  Prime sized tables are more
+ * traditional, but do not have a significant advantage over power-of-two
+ * sized table, especially when double hashing is not used for collision
+ * resolution.
+ *
+ * 2) The hash computation uses a table of random integers [Hanson97,
+ * pp. 39-41].
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * With a table size of 512, the current implementation is sufficient for a
+ * few hundred keys.  Since this is well above the expected size of the
+ * tables for which this implementation was designed, the implementation of
+ * dynamic hash tables was postponed until the need arises.  A common (and
+ * naive) approach to dynamic hash table implementation simply creates a
+ * new hash table when necessary, rehashes all the data into the new table,
+ * and destroys the old table.  The approach in [Larson88] is superior in
+ * two ways: 1) only a portion of the table is expanded when needed,
+ * distributing the expansion cost over several insertions, and 2) portions
+ * of the table can be locked, enabling a scalable thread-safe
+ * implementation.
+ *
+ * REFERENCES
+ *
+ * [Hanson97] David R. Hanson.  C Interfaces and Implementations:
+ * Techniques for Creating Reusable Software.  Reading, Massachusetts:
+ * Addison-Wesley, 1997.
+ *
+ * [Knuth73] Donald E. Knuth. The Art of Computer Programming.  Volume 3:
+ * Sorting and Searching.  Reading, Massachusetts: Addison-Wesley, 1973.
+ *
+ * [Larson88] Per-Ake Larson. "Dynamic Hash Tables".  CACM 31(4), April
+ * 1988, pp. 446-457.
+ *
+ */
+
+#define HASH_MAIN 0
+
+#if HASH_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+#  include "xf86.h"
+#  include "xf86_ansic.h"
+# else
+#  include <stdio.h>
+#  include <stdlib.h>
+# endif
+#endif
+
+#define N(x)  drm##x
+
+#define HASH_MAGIC 0xdeadbeef
+#define HASH_DEBUG 0
+#define HASH_SIZE  512         /* Good for about 100 entries */
+                               /* If you change this value, you probably
+                                   have to change the HashHash hashing
+                                   function! */
+
+#if HASH_MAIN
+#define HASH_ALLOC malloc
+#define HASH_FREE  free
+#define HASH_RANDOM_DECL
+#define HASH_RANDOM_INIT(seed)  srandom(seed)
+#define HASH_RANDOM             random()
+#else
+#define HASH_ALLOC drmMalloc
+#define HASH_FREE  drmFree
+#define HASH_RANDOM_DECL        void *state
+#define HASH_RANDOM_INIT(seed)  state = drmRandomCreate(seed)
+#define HASH_RANDOM             drmRandom(state)
+
+#endif
+
+typedef struct HashBucket {
+    unsigned long     key;
+    void              *value;
+    struct HashBucket *next;
+} HashBucket, *HashBucketPtr;
+
+typedef struct HashTable {
+    unsigned long    magic;
+    unsigned long    entries;
+    unsigned long    hits;     /* At top of linked list */
+    unsigned long    partials; /* Not at top of linked list */
+    unsigned long    misses;   /* Not in table */
+    HashBucketPtr    buckets[HASH_SIZE];
+    int              p0;
+    HashBucketPtr    p1;
+} HashTable, *HashTablePtr;
+
+#if HASH_MAIN
+extern void *N(HashCreate)(void);
+extern int  N(HashDestroy)(void *t);
+extern int  N(HashLookup)(void *t, unsigned long key, unsigned long *value);
+extern int  N(HashInsert)(void *t, unsigned long key, unsigned long value);
+extern int  N(HashDelete)(void *t, unsigned long key);
+#endif
+
+static unsigned long HashHash(unsigned long key)
+{
+    unsigned long        hash = 0;
+    unsigned long        tmp  = key;
+    static int           init = 0;
+    static unsigned long scatter[256];
+    int                  i;
+
+    if (!init) {
+       HASH_RANDOM_DECL;
+       HASH_RANDOM_INIT(37);
+       for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM;
+       ++init;
+    }
+
+    while (tmp) {
+       hash = (hash << 1) + scatter[tmp & 0xff];
+       tmp >>= 8;
+    }
+
+    hash %= HASH_SIZE;
+#if HASH_DEBUG
+    printf( "Hash(%d) = %d\n", key, hash);
+#endif
+    return hash;
+}
+
+void *N(HashCreate)(void)
+{
+    HashTablePtr table;
+    int          i;
+
+    table           = HASH_ALLOC(sizeof(*table));
+    if (!table) return NULL;
+    table->magic    = HASH_MAGIC;
+    table->entries  = 0;
+    table->hits     = 0;
+    table->partials = 0;
+    table->misses   = 0;
+
+    for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL;
+    return table;
+}
+
+int N(HashDestroy)(void *t)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+    HashBucketPtr bucket;
+    HashBucketPtr next;
+    int           i;
+
+    if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    for (i = 0; i < HASH_SIZE; i++) {
+       for (bucket = table->buckets[i]; bucket;) {
+           next = bucket->next;
+           HASH_FREE(bucket);
+           bucket = next;
+       }
+    }
+    HASH_FREE(table);
+    return 0;
+}
+
+/* Find the bucket and organize the list so that this bucket is at the
+   top. */
+
+static HashBucketPtr HashFind(HashTablePtr table,
+                             unsigned long key, unsigned long *h)
+{
+    unsigned long hash = HashHash(key);
+    HashBucketPtr prev = NULL;
+    HashBucketPtr bucket;
+
+    if (h) *h = hash;
+
+    for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
+       if (bucket->key == key) {
+           if (prev) {
+                               /* Organize */
+               prev->next           = bucket->next;
+               bucket->next         = table->buckets[hash];
+               table->buckets[hash] = bucket;
+               ++table->partials;
+           } else {
+               ++table->hits;
+           }
+           return bucket;
+       }
+       prev = bucket;
+    }
+    ++table->misses;
+    return NULL;
+}
+
+int N(HashLookup)(void *t, unsigned long key, void **value)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+    HashBucketPtr bucket;
+
+    if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    bucket = HashFind(table, key, NULL);
+    if (!bucket) return 1;     /* Not found */
+    *value = bucket->value;
+    return 0;                  /* Found */
+}
+
+int N(HashInsert)(void *t, unsigned long key, void *value)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+    HashBucketPtr bucket;
+    unsigned long hash;
+
+    if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    if (HashFind(table, key, &hash)) return 1; /* Already in table */
+
+    bucket               = HASH_ALLOC(sizeof(*bucket));
+    if (!bucket) return -1;    /* Error */
+    bucket->key          = key;
+    bucket->value        = value;
+    bucket->next         = table->buckets[hash];
+    table->buckets[hash] = bucket;
+#if HASH_DEBUG
+    printf("Inserted %d at %d/%p\n", key, hash, bucket);
+#endif
+    return 0;                  /* Added to table */
+}
+
+int N(HashDelete)(void *t, unsigned long key)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+    unsigned long hash;
+    HashBucketPtr bucket;
+
+    if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    bucket = HashFind(table, key, &hash);
+
+    if (!bucket) return 1;     /* Not found */
+
+    table->buckets[hash] = bucket->next;
+    HASH_FREE(bucket);
+    return 0;
+}
+
+int N(HashNext)(void *t, unsigned long *key, void **value)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+
+    for (; table->p0 < HASH_SIZE;
+        ++table->p0, table->p1 = table->buckets[table->p0]) {
+       if (table->p1) {
+           *key       = table->p1->key;
+           *value     = table->p1->value;
+           table->p1  = table->p1->next;
+           return 1;
+       }
+    }
+    return 0;
+}
+
+int N(HashFirst)(void *t, unsigned long *key, void **value)
+{
+    HashTablePtr  table = (HashTablePtr)t;
+
+    if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    table->p0 = 0;
+    table->p1 = table->buckets[0];
+    return N(HashNext)(table, key, value);
+}
+
+#if HASH_MAIN
+#define DIST_LIMIT 10
+static int dist[DIST_LIMIT];
+
+static void clear_dist(void) {
+    int i;
+
+    for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0;
+}
+
+static int count_entries(HashBucketPtr bucket)
+{
+    int count = 0;
+
+    for (; bucket; bucket = bucket->next) ++count;
+    return count;
+}
+
+static void update_dist(int count)
+{
+    if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1];
+    else                     ++dist[count];
+}
+
+static void compute_dist(HashTablePtr table)
+{
+    int           i;
+    HashBucketPtr bucket;
+
+    printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
+          table->entries, table->hits, table->partials, table->misses);
+    clear_dist();
+    for (i = 0; i < HASH_SIZE; i++) {
+       bucket = table->buckets[i];
+       update_dist(count_entries(bucket));
+    }
+    for (i = 0; i < DIST_LIMIT; i++) {
+       if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]);
+       else                   printf("other %10d\n", dist[i]);
+    }
+}
+
+static void check_table(HashTablePtr table,
+                       unsigned long key, unsigned long value)
+{
+    unsigned long retval  = 0;
+    int           retcode = N(HashLookup)(table, key, &retval);
+
+    switch (retcode) {
+    case -1:
+       printf("Bad magic = 0x%08lx:"
+              " key = %lu, expected = %lu, returned = %lu\n",
+              table->magic, key, value, retval);
+       break;
+    case 1:
+       printf("Not found: key = %lu, expected = %lu returned = %lu\n",
+              key, value, retval);
+       break;
+    case 0:
+       if (value != retval)
+           printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
+                  key, value, retval);
+       break;
+    default:
+       printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
+              retcode, key, value, retval);
+       break;
+    }
+}
+
+int main(void)
+{
+    HashTablePtr table;
+    int          i;
+
+    printf("\n***** 256 consecutive integers ****\n");
+    table = N(HashCreate)();
+    for (i = 0; i < 256; i++) N(HashInsert)(table, i, i);
+    for (i = 0; i < 256; i++) check_table(table, i, i);
+    for (i = 256; i >= 0; i--) check_table(table, i, i);
+    compute_dist(table);
+    N(HashDestroy)(table);
+
+    printf("\n***** 1024 consecutive integers ****\n");
+    table = N(HashCreate)();
+    for (i = 0; i < 1024; i++) N(HashInsert)(table, i, i);
+    for (i = 0; i < 1024; i++) check_table(table, i, i);
+    for (i = 1024; i >= 0; i--) check_table(table, i, i);
+    compute_dist(table);
+    N(HashDestroy)(table);
+
+    printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
+    table = N(HashCreate)();
+    for (i = 0; i < 1024; i++) N(HashInsert)(table, i*4096, i);
+    for (i = 0; i < 1024; i++) check_table(table, i*4096, i);
+    for (i = 1024; i >= 0; i--) check_table(table, i*4096, i);
+    compute_dist(table);
+    N(HashDestroy)(table);
+
+    printf("\n***** 1024 random integers ****\n");
+    table = N(HashCreate)();
+    srandom(0xbeefbeef);
+    for (i = 0; i < 1024; i++) N(HashInsert)(table, random(), i);
+    srandom(0xbeefbeef);
+    for (i = 0; i < 1024; i++) check_table(table, random(), i);
+    srandom(0xbeefbeef);
+    for (i = 0; i < 1024; i++) check_table(table, random(), i);
+    compute_dist(table);
+    N(HashDestroy)(table);
+
+    printf("\n***** 5000 random integers ****\n");
+    table = N(HashCreate)();
+    srandom(0xbeefbeef);
+    for (i = 0; i < 5000; i++) N(HashInsert)(table, random(), i);
+    srandom(0xbeefbeef);
+    for (i = 0; i < 5000; i++) check_table(table, random(), i);
+    srandom(0xbeefbeef);
+    for (i = 0; i < 5000; i++) check_table(table, random(), i);
+    compute_dist(table);
+    N(HashDestroy)(table);
+
+    return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmRandom.c b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c
new file mode 100644 (file)
index 0000000..9e1e9ee
--- /dev/null
@@ -0,0 +1,219 @@
+/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation
+ * Created: Mon Apr 19 08:28:13 1999 by faith@precisioninsight.com
+ *
+ * Copyright 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, 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
+ * 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: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.4 2000/06/17 00:03:34 martin Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a simple, straightforward implementation of the Park
+ * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer
+ * multiplicative linear congruential generator (MLCG) with a period of
+ * 2^31-1.
+ *
+ * This implementation is intended to provide a reliable, portable PRNG
+ * that is suitable for testing a hash table implementation and for
+ * implementing skip lists.
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * If initial seeds are not selected randomly, two instances of the PRNG
+ * can be correlated.  [Knuth81, pp. 32-33] describes a shuffling technique
+ * that can eliminate this problem.
+ *
+ * If PRNGs are used for simulation, the period of the current
+ * implementation may be too short.  [LE88] discusses methods of combining
+ * MLCGs to produce much longer periods, and suggests some alternative
+ * values for A and M.  [LE90 and Sch92] also provide information on
+ * long-period PRNGs.
+ *
+ * REFERENCES
+ *
+ * [Knuth81] Donald E. Knuth. The Art of Computer Programming.  Volume 2:
+ * Seminumerical Algorithms.  Reading, Massachusetts: Addison-Wesley, 1981.
+ *
+ * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number
+ * Generators".  CACM 31(6), June 1988, pp. 742-774.
+ *
+ * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10,
+ * October 1990, pp. 85-97.
+ *
+ * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators:
+ * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201.
+ *
+ * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit
+ * CPUs".  Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40.
+ *
+ * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer.  In
+ * "Technical Correspondence: Remarks on Choosing and Implementing Random
+ * Number Generators". CACM 36(7), July 1993, pp. 105-110.
+ *
+ */
+
+#define RANDOM_MAIN 0
+
+#if RANDOM_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+#  include "xf86.h"
+#  include "xf86_ansic.h"
+# else
+#  include <stdio.h>
+#  include <stdlib.h>
+# endif
+#endif
+
+#define N(x)  drm##x
+
+#define RANDOM_MAGIC 0xfeedbeef
+#define RANDOM_DEBUG 0
+
+#if RANDOM_MAIN
+#define RANDOM_ALLOC malloc
+#define RANDOM_FREE  free
+#else
+#define RANDOM_ALLOC drmMalloc
+#define RANDOM_FREE  drmFree
+#endif
+
+typedef struct RandomState {
+    unsigned long magic;
+    unsigned long a;
+    unsigned long m;
+    unsigned long q;           /* m div a */
+    unsigned long r;           /* m mod a */
+    unsigned long check;
+    long          seed;
+} RandomState;
+
+#if RANDOM_MAIN
+extern void          *N(RandomCreate)(unsigned long seed);
+extern int           N(RandomDestroy)(void *state);
+extern unsigned long N(Random)(void *state);
+extern double        N(RandomDouble)(void *state);
+#endif
+
+void *N(RandomCreate)(unsigned long seed)
+{
+    RandomState  *state;
+
+    state           = RANDOM_ALLOC(sizeof(*state));
+    if (!state) return NULL;
+    state->magic    = RANDOM_MAGIC;
+#if 0
+                               /* Park & Miller, October 1988 */
+    state->a        = 16807;
+    state->m        = 2147483647;
+    state->check    = 1043618065; /* After 10000 iterations */
+#else
+                               /* Park, Miller, and Stockmeyer, July 1993 */
+    state->a        = 48271;
+    state->m        = 2147483647;
+    state->check    = 399268537; /* After 10000 iterations */
+#endif
+    state->q        = state->m / state->a;
+    state->r        = state->m % state->a;
+
+    state->seed     = seed;
+                               /* Check for illegal boundary conditions,
+                                   and choose closest legal value. */
+    if (state->seed <= 0)        state->seed = 1;
+    if (state->seed >= state->m) state->seed = state->m - 1;
+
+    return state;
+}
+
+int N(RandomDestroy)(void *state)
+{
+    RANDOM_FREE(state);
+    return 0;
+}
+
+unsigned long N(Random)(void *state)
+{
+    RandomState   *s = (RandomState *)state;
+    long          hi;
+    long          lo;
+
+    hi      = s->seed / s->q;
+    lo      = s->seed % s->q;
+    s->seed = s->a * lo - s->r * hi;
+    if (s->seed <= 0) s->seed += s->m;
+
+    return s->seed;
+}
+
+double N(RandomDouble)(void *state)
+{
+    RandomState *s = (RandomState *)state;
+    
+    return (double)N(Random)(state)/(double)s->m;
+}
+
+#if RANDOM_MAIN
+static void check_period(long seed)
+{
+    unsigned long count = 0;
+    unsigned long initial;
+    void          *state;
+    
+    state = N(RandomCreate)(seed);
+    initial = N(Random)(state);
+    ++count;
+    while (initial != N(Random)(state)) {
+       if (!++count) break;
+    }
+    printf("With seed of %10ld, period = %10lu (0x%08lx)\n",
+          seed, count, count);
+    N(RandomDestroy)(state);
+}
+
+int main(void)
+{
+    RandomState   *state;
+    int           i;
+    unsigned long rand;
+
+    state = N(RandomCreate)(1);
+    for (i = 0; i < 10000; i++) {
+       rand = N(Random)(state);
+    }
+    printf("After 10000 iterations: %lu (%lu expected): %s\n",
+          rand, state->check,
+          rand - state->check ? "*INCORRECT*" : "CORRECT");
+    N(RandomDestroy)(state);
+
+    printf("Checking periods...\n");
+    check_period(1);
+    check_period(2);
+    check_period(31415926);
+    
+    return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmSL.c b/src/mesa/drivers/dri/dri_client/xf86drmSL.c
new file mode 100644 (file)
index 0000000..dd634c3
--- /dev/null
@@ -0,0 +1,490 @@
+/* xf86drmSL.c -- Skip list support
+ * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
+ *
+ * Copyright 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, 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
+ * 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: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.3 2000/06/17 00:03:34 martin Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward skip list implementation.n
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * REFERENCES
+ *
+ * [Pugh90] William Pugh.  Skip Lists: A Probabilistic Alternative to
+ * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
+ *
+ */
+
+#define SL_MAIN 0
+
+#if SL_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+#  include <sys/time.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+#  include "xf86.h"
+#  include "xf86_ansic.h"
+# else
+#  include <stdio.h>
+#  include <stdlib.h>
+# endif
+#endif
+
+#define N(x)  drm##x
+
+#define SL_LIST_MAGIC  0xfacade00LU
+#define SL_ENTRY_MAGIC 0x00fab1edLU
+#define SL_FREED_MAGIC 0xdecea5edLU
+#define SL_MAX_LEVEL   16
+#define SL_DEBUG       0
+#define SL_RANDOM_SEED 0xc01055a1LU
+
+#if SL_MAIN
+#define SL_ALLOC malloc
+#define SL_FREE  free
+#define SL_RANDOM_DECL        static int state = 0;
+#define SL_RANDOM_INIT(seed)  if (!state) { srandom(seed); ++state; }
+#define SL_RANDOM             random()
+#else
+#define SL_ALLOC drmMalloc
+#define SL_FREE  drmFree
+#define SL_RANDOM_DECL        static void *state = NULL
+#define SL_RANDOM_INIT(seed)  if (!state) state = drmRandomCreate(seed)
+#define SL_RANDOM             drmRandom(state)
+
+#endif
+
+typedef struct SLEntry {
+    unsigned long     magic;      /* SL_ENTRY_MAGIC */
+    unsigned long     key;
+    void              *value;
+    int               levels;
+    struct SLEntry    *forward[1]; /* variable sized array */
+} SLEntry, *SLEntryPtr;
+
+typedef struct SkipList {
+    unsigned long    magic;    /* SL_LIST_MAGIC */
+    int              level;
+    int              count;
+    SLEntryPtr       head;
+    SLEntryPtr       p0;       /* Position for iteration */
+} SkipList, *SkipListPtr;
+
+#if SL_MAIN
+extern void *N(SLCreate)(void);
+extern int  N(SLDestroy)(void *l);
+extern int  N(SLLookup)(void *l, unsigned long key, void **value);
+extern int  N(SLInsert)(void *l, unsigned long key, void *value);
+extern int  N(SLDelete)(void *l, unsigned long key);
+extern int  N(SLNext)(void *l, unsigned long *key, void **value);
+extern int  N(SLFirst)(void *l, unsigned long *key, void **value);
+extern void N(SLDump)(void *l);
+extern int  N(SLLookupNeighbors)(void *l, unsigned long key,
+                                unsigned long *prev_key, void **prev_value,
+                                unsigned long *next_key, void **next_value);
+#endif
+
+static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
+{
+    SLEntryPtr entry;
+    
+    if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
+
+    entry         = SL_ALLOC(sizeof(*entry)
+                            + (max_level + 1) * sizeof(entry->forward[0]));
+    if (!entry) return NULL;
+    entry->magic  = SL_ENTRY_MAGIC;
+    entry->key    = key;
+    entry->value  = value;
+    entry->levels = max_level + 1;
+
+    return entry;
+}
+
+static int SLRandomLevel(void)
+{
+    int level = 1;
+    SL_RANDOM_DECL;
+
+    SL_RANDOM_INIT(SL_RANDOM_SEED);
+    
+    while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
+    return level;
+}
+
+void *N(SLCreate)(void)
+{
+    SkipListPtr  list;
+    int          i;
+
+    list           = SL_ALLOC(sizeof(*list));
+    if (!list) return NULL;
+    list->magic    = SL_LIST_MAGIC;
+    list->level    = 0;
+    list->head     = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
+    list->count    = 0;
+
+    for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
+    
+    return list;
+}
+
+int N(SLDestroy)(void *l)
+{
+    SkipListPtr   list  = (SkipListPtr)l;
+    SLEntryPtr    entry;
+    SLEntryPtr    next;
+
+    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+    for (entry = list->head; entry; entry = next) {
+       if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
+       next         = entry->forward[0];
+       entry->magic = SL_FREED_MAGIC;
+       SL_FREE(entry);
+    }
+
+    list->magic = SL_FREED_MAGIC;
+    SL_FREE(list);
+    return 0;
+}
+
+static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
+{
+    SkipListPtr   list  = (SkipListPtr)l;
+    SLEntryPtr    entry;
+    int           i;
+
+    if (list->magic != SL_LIST_MAGIC) return NULL;
+
+    for (i = list->level, entry = list->head; i >= 0; i--) {
+       while (entry->forward[i] && entry->forward[i]->key < key)
+           entry = entry->forward[i];
+       update[i] = entry;
+    }
+
+    return entry->forward[0];
+}
+
+int N(SLInsert)(void *l, unsigned long key, void *value)
+{
+    SkipListPtr   list  = (SkipListPtr)l;
+    SLEntryPtr    entry;
+    SLEntryPtr    update[SL_MAX_LEVEL + 1];
+    int           level;
+    int           i;
+
+    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+    entry = SLLocate(list, key, update);
+
+    if (entry && entry->key == key) return 1; /* Already in list */
+
+
+    level = SLRandomLevel();
+    if (level > list->level) {
+       level = ++list->level;
+       update[level] = list->head;
+    }
+
+    entry = SLCreateEntry(level, key, value);
+
+                               /* Fix up forward pointers */
+    for (i = 0; i <= level; i++) {
+       entry->forward[i]     = update[i]->forward[i];
+       update[i]->forward[i] = entry;
+    }
+
+    ++list->count;
+    return 0;                  /* Added to table */
+}
+
+int N(SLDelete)(void *l, unsigned long key)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    SLEntryPtr    update[SL_MAX_LEVEL + 1];
+    SLEntryPtr    entry;
+    int           i;
+
+    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+    entry = SLLocate(list, key, update);
+
+    if (!entry || entry->key != key) return 1; /* Not found */
+
+                               /* Fix up forward pointers */
+    for (i = 0; i <= list->level; i++) {
+       if (update[i]->forward[i] == entry)
+           update[i]->forward[i] = entry->forward[i];
+    }
+
+    entry->magic = SL_FREED_MAGIC;
+    SL_FREE(entry);
+
+    while (list->level && !list->head->forward[list->level]) --list->level;
+    --list->count;
+    return 0;
+}
+
+int N(SLLookup)(void *l, unsigned long key, void **value)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    SLEntryPtr    update[SL_MAX_LEVEL + 1];
+    SLEntryPtr    entry;
+
+    entry = SLLocate(list, key, update);
+
+    if (entry && entry->key == key) {
+       *value = entry;
+       return 0;
+    }
+    *value = NULL;
+    return -1;
+}
+
+int N(SLLookupNeighbors)(void *l, unsigned long key,
+                        unsigned long *prev_key, void **prev_value,
+                        unsigned long *next_key, void **next_value)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    SLEntryPtr    update[SL_MAX_LEVEL + 1];
+    SLEntryPtr    entry;
+    int           retcode = 0;
+
+    entry = SLLocate(list, key, update);
+
+    *prev_key   = *next_key   = key;
+    *prev_value = *next_value = NULL;
+       
+    if (update[0]) {
+       *prev_key   = update[0]->key;
+       *prev_value = update[0]->value;
+       ++retcode;
+       if (update[0]->forward[0]) {
+           *next_key   = update[0]->forward[0]->key;
+           *next_value = update[0]->forward[0]->value;
+           ++retcode;
+       }
+    }
+    return retcode;
+}
+
+int N(SLNext)(void *l, unsigned long *key, void **value)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    SLEntryPtr    entry;
+    
+    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+    entry    = list->p0;
+
+    if (entry) {
+       list->p0 = entry->forward[0];
+       *key     = entry->key;
+       *value   = entry->value;
+       return 1;
+    }
+    list->p0 = NULL;
+    return 0;
+}
+
+int N(SLFirst)(void *l, unsigned long *key, void **value)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    
+    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+    
+    list->p0 = list->head->forward[0];
+    return N(SLNext)(list, key, value);
+}
+
+/* Dump internal data structures for debugging. */
+void N(SLDump)(void *l)
+{
+    SkipListPtr   list = (SkipListPtr)l;
+    SLEntryPtr    entry;
+    int           i;
+    
+    if (list->magic != SL_LIST_MAGIC) {
+       printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
+              list->magic, SL_LIST_MAGIC);
+       return;
+    }
+
+    printf("Level = %d, count = %d\n", list->level, list->count);
+    for (entry = list->head; entry; entry = entry->forward[0]) {
+       if (entry->magic != SL_ENTRY_MAGIC) {
+           printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
+                  list->magic, SL_ENTRY_MAGIC);
+       }
+       printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
+              entry, entry->key, entry->value, entry->levels);
+       for (i = 0; i < entry->levels; i++) {
+           if (entry->forward[i]) {
+               printf("   %2d: %p <0x%08lx, %p>\n",
+                      i,
+                      entry->forward[i],
+                      entry->forward[i]->key,
+                      entry->forward[i]->value);
+           } else {
+               printf("   %2d: %p\n", i, entry->forward[i]);
+           }
+       }
+    }
+}
+
+#if SL_MAIN
+static void print(SkipListPtr list)
+{
+    unsigned long key;
+    void          *value;
+    
+    if (N(SLFirst)(list, &key, &value)) {
+       do {
+           printf("key = %5lu, value = %p\n", key, value);
+       } while (N(SLNext)(list, &key, &value));
+    }
+}
+
+static double do_time(int size, int iter)
+{
+    SkipListPtr    list;
+    int            i, j;
+    unsigned long  keys[1000000];
+    unsigned long  previous;
+    unsigned long  key;
+    void           *value;
+    struct timeval start, stop;
+    double         usec;
+    SL_RANDOM_DECL;
+
+    SL_RANDOM_INIT(12345);
+    
+    list = N(SLCreate)();
+
+    for (i = 0; i < size; i++) {
+       keys[i] = SL_RANDOM;
+       N(SLInsert)(list, keys[i], NULL);
+    }
+
+    previous = 0;
+    if (N(SLFirst)(list, &key, &value)) {
+       do {
+           if (key <= previous) {
+               printf( "%lu !< %lu\n", previous, key);
+           }
+           previous = key;
+       } while (N(SLNext)(list, &key, &value));
+    }
+    
+    gettimeofday(&start, NULL);
+    for (j = 0; j < iter; j++) {
+       for (i = 0; i < size; i++) {
+           if (N(SLLookup)(list, keys[i], &value))
+               printf("Error %lu %d\n", keys[i], i);
+       }
+    }
+    gettimeofday(&stop, NULL);
+    
+    usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec
+                   - start.tv_sec * 1000000 - start.tv_usec) / (size * iter);
+    
+    printf("%0.2f microseconds for list length %d\n", usec, size);
+
+    N(SLDestroy)(list);
+    
+    return usec;
+}
+
+static void print_neighbors(void *list, unsigned long key)
+{
+    unsigned long prev_key = 0;
+    unsigned long next_key = 0;
+    void          *prev_value;
+    void          *next_value;
+    int           retval;
+
+    retval = drmSLLookupNeighbors(list, key,
+                                 &prev_key, &prev_value,
+                                 &next_key, &next_value);
+    printf("Neighbors of %5lu: %d %5lu %5lu\n",
+          key, retval, prev_key, next_key);
+}
+
+int main(void)
+{
+    SkipListPtr    list;
+    double         usec, usec2, usec3, usec4;
+
+    list = N(SLCreate)();
+    printf( "list at %p\n", list);
+
+    print(list);
+    printf("\n==============================\n\n");
+
+    N(SLInsert)(list, 123, NULL);
+    N(SLInsert)(list, 213, NULL);
+    N(SLInsert)(list, 50, NULL);
+    print(list);
+    printf("\n==============================\n\n");
+    
+    print_neighbors(list, 0);
+    print_neighbors(list, 50);
+    print_neighbors(list, 51);
+    print_neighbors(list, 123);
+    print_neighbors(list, 200);
+    print_neighbors(list, 213);
+    print_neighbors(list, 256);
+    printf("\n==============================\n\n");    
+    
+    N(SLDelete)(list, 50);
+    print(list);
+    printf("\n==============================\n\n");
+
+    N(SLDump)(list);
+    N(SLDestroy)(list);
+    printf("\n==============================\n\n");
+
+    usec  = do_time(100, 10000);
+    usec2 = do_time(1000, 500);
+    printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+          1000.0/100.0, usec2 / usec);
+    
+    usec3 = do_time(10000, 50);
+    printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+          10000.0/100.0, usec3 / usec);
+    
+    usec4 = do_time(100000, 4);
+    printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+          100000.0/100.0, usec4 / usec);
+
+    return 0;
+}
+#endif