summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2004-04-14 12:39:58 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2004-04-14 12:39:58 +0000
commit680ec7f85158eae58fd5ab56da8c66a645883cb0 (patch)
tree1680892e7edd243e5c49dd40c0ae9b9750066229 /src/mesa/drivers
parent00e01091ceeb7f2d9e81962a7e0e57077e4d37f7 (diff)
First pass at support for building DRI drivers in mesa tree.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/dri_client/Makefile60
-rw-r--r--src/mesa/drivers/dri/dri_client/XF86dri.c636
-rw-r--r--src/mesa/drivers/dri/dri_client/dri_glx.c475
-rw-r--r--src/mesa/drivers/dri/dri_client/dri_glx.h61
-rw-r--r--src/mesa/drivers/dri/dri_client/dri_util.c1578
-rw-r--r--src/mesa/drivers/dri/dri_client/dri_util.h607
-rw-r--r--src/mesa/drivers/dri/dri_client/drm.h680
-rw-r--r--src/mesa/drivers/dri/dri_client/glcontextmodes.c483
-rw-r--r--src/mesa/drivers/dri/dri_client/glcontextmodes.h49
-rw-r--r--src/mesa/drivers/dri/dri_client/imports/glxclient.h1143
-rw-r--r--src/mesa/drivers/dri/dri_client/imports/sarea.h94
-rw-r--r--src/mesa/drivers/dri/dri_client/imports/xf86drm.h646
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86dri.h221
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86dristr.h343
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drm.c2326
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmHash.c435
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmRandom.c219
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmSL.c490
18 files changed, 10546 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/dri_client/Makefile b/src/mesa/drivers/dri/dri_client/Makefile
new file mode 100644
index 0000000000..14ba1948b2
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/Makefile
@@ -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
index 0000000000..ea14b7a070
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/XF86dri.c
@@ -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
index 0000000000..f0b5f19eed
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/dri_glx.c
@@ -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
index 0000000000..75561685c8
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/dri_glx.h
@@ -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
index 0000000000..428472873e
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/dri_util.c
@@ -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
index 0000000000..f189b5a967
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/dri_util.h
@@ -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
index 0000000000..ceba2424f7
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/drm.h
@@ -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
index 0000000000..784ad30259
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/glcontextmodes.c
@@ -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
index 0000000000..5f8fa4f311
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/glcontextmodes.h
@@ -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
index 0000000000..317ea01116
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/imports/glxclient.h
@@ -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
index 0000000000..d4d83df930
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/imports/sarea.h
@@ -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
index 0000000000..c9f1007498
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h
@@ -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
index 0000000000..013f5b32d5
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86dri.h
@@ -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
index 0000000000..ac05b183b3
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86dristr.h
@@ -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
index 0000000000..23750b9ca5
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drm.c
@@ -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
index 0000000000..1f1a05b3ac
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmHash.c
@@ -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
index 0000000000..9e1e9ee2c3
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c
@@ -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
index 0000000000..dd634c30f6
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmSL.c
@@ -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