summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2003-02-05 04:37:12 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2003-02-05 04:37:12 +0000
commit78e1fee39b321a59d3607c7611805b1ce391e982 (patch)
tree4bfe0349d2e31cfbd424f0c56f7560638798c279
parent75ccd62be83b59eab7e545473075c9f6839d50c2 (diff)
Add files to allow the subset driver to be built as a dri driver.
At the moment have to choose to build as *either* a dri or a miniglx driver, but shouldn't be too hard to build one driver that will work in both environments.
-rw-r--r--src/dri-es/Makefile67
-rw-r--r--src/dri-es/dri_glx.c472
-rw-r--r--src/dri-es/dri_glx.h59
-rw-r--r--src/dri-es/dri_util.c1109
-rw-r--r--src/dri-es/dri_util.h375
-rw-r--r--src/dri-es/drm.h474
-rw-r--r--src/dri-es/extutil.h224
-rw-r--r--src/dri-es/glxclient.h678
-rw-r--r--src/dri-es/sarea.h80
-rw-r--r--src/dri-es/xf86dri.h227
-rw-r--r--src/dri-es/xf86dristr.h343
-rw-r--r--src/dri-es/xf86drm.c1500
-rw-r--r--src/dri-es/xf86drm.h607
-rw-r--r--src/dri-es/xf86drmHash.c435
-rw-r--r--src/dri-es/xf86drmRandom.c219
-rw-r--r--src/dri-es/xf86drmSL.c490
16 files changed, 7359 insertions, 0 deletions
diff --git a/src/dri-es/Makefile b/src/dri-es/Makefile
new file mode 100644
index 0000000000..5cf418f4c8
--- /dev/null
+++ b/src/dri-es/Makefile
@@ -0,0 +1,67 @@
+# $Id: Makefile,v 1.1.2.1 2003/02/05 04:37:12 keithw Exp $
+
+# Mesa 3-D graphics library
+# Version: 5.0
+# Copyright (C) 1995-2002 Brian Paul
+
+
+
+MESA = ../..
+MESABUILDDIR = ..
+
+
+INCLUDES = -I/usr/X11R6/include -I/usr/X11R6/include/X11/extensions -I$(MESA)/include -I. -I..
+DEFINES =
+
+CFLAGS = $(INCLUDES) $(DEFINES) -g -MD -Wall -Wpointer-arith \
+ -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations -Wnested-externs
+
+# The .a files for each mesa module required by this driver:
+#
+DRI_SOURCES = dri_glx.c \
+ dri_util.c \
+ xf86drm.c \
+ xf86drmHash.c \
+ xf86drmRandom.c \
+ xf86drmSL.c
+
+
+C_SOURCES = $(DRI_SOURCES)
+
+ASM_SOURCES =
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+
+
+##### RULES #####
+
+.S.o:
+ $(CC) -c $(CFLAGS) $< -o $@
+
+.c.o:
+ $(CC) -c $(CFLAGS) $< -o $@
+
+##### TARGETS #####
+
+default: dri.a
+
+dri.a: $(OBJECTS) Makefile
+ rm -f $@ && ar rcv $@ $(OBJECTS) && ranlib $@
+
+clean:
+ -rm -f *.o *~ *.d .\#* *.so
+
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+##### DEPENDENCIES #####
+
+-include $(C_SOURCES:.c=.d)
+
+.SUFFIXES: .c .d
+
+.c.d:
+ $(CC) -M $(INCLUDES) $(DEFINES) $< > $@
diff --git a/src/dri-es/dri_glx.c b/src/dri-es/dri_glx.c
new file mode 100644
index 0000000000..d4888b6a47
--- /dev/null
+++ b/src/dri-es/dri_glx.c
@@ -0,0 +1,472 @@
+/**************************************************************************
+
+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.10 2001/08/27 17:40:57 dawes Exp $ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ * Brian Paul <brian@precisioninsight.com>
+ *
+ */
+
+
+#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>
+
+
+#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");
+ if (!driver->createScreenFunc) {
+ /* If the driver doesn't have this symbol then something's
+ * really, really wrong.
+ */
+ ErrorMessageF("__driCreateScreen() not defined in %s_dri.so!\n",
+ driverName);
+ Xfree(driver);
+ dlclose(handle);
+ continue;
+ }
+ driver->registerExtensionsFunc = (RegisterExtensionsFunc)
+ dlsym(handle, "__driRegisterExtensions");
+ 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");
+ return False;
+ }
+ if (!directCapable) {
+ ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false");
+ 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)) {
+ return OpenDriver(driverName);
+ }
+ 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 library handles */
+ pdpyp->libraryHandles = (void **) Xmalloc(numScreens * sizeof(void*));
+ if (!pdpyp->libraryHandles) {
+ 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;
+ 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.
+ */
+ __glXRegisterExtensions();
+ for (scrn = 0; scrn < numScreens; scrn++) {
+ __DRIdriver *driver = driGetDriver(dpy, scrn);
+ if (driver) {
+ pdisp->createScreen[scrn] = driver->createScreenFunc;
+ pdpyp->libraryHandles[scrn] = driver->handle;
+ }
+ else {
+ pdisp->createScreen[scrn] = DummyCreateScreen;
+ pdpyp->libraryHandles[scrn] = NULL;
+ }
+ }
+#endif
+
+ return (void *)pdpyp;
+}
+
+
+
+/*
+** Here we'll query the DRI driver for each screen and let each
+** driver register its GL extension functions. We only have to
+** do this once.
+**
+** In older versions of libGL (prior to October 2002) we _always_
+** called this function during libGL start-up. Now, we only call
+** it from glXGetProcAddress() as a last resort.
+**
+** Two key things changed along the way:
+** 1. _glapi_get_proc_address() now generates new dispatch stub functions
+** anytime it gets an unknown "gl*" function name. I.e. we always return
+** a valid function address and later patch it up to use the correct
+** dispatch offset.
+** 2. The GL API dispatch table is a fixed size (with plenty of extra slots).
+** This means we don't have to register all new functions before we create
+** the first dispatch table.
+*/
+void
+__glXRegisterExtensions(void)
+{
+#ifndef BUILT_IN_DRI_DRIVER
+ static GLboolean alreadyCalled = GL_FALSE;
+ int displayNum, maxDisplays;
+
+ if (alreadyCalled)
+ return;
+ alreadyCalled = GL_TRUE;
+
+ if (getenv("LIBGL_MULTIHEAD")) {
+ /* we'd like to always take this path but doing so causes a second
+ * or more of delay while the XOpenDisplay() function times out.
+ */
+ maxDisplays = 10; /* infinity, really */
+ }
+ else {
+ /* just open the :0 display */
+ maxDisplays = 1;
+ }
+
+ for (displayNum = 0; displayNum < maxDisplays; displayNum++) {
+ char displayName[200];
+ Display *dpy;
+ snprintf(displayName, 199, ":%d.0", displayNum);
+ dpy = XOpenDisplay(displayName);
+ if (dpy) {
+ const int numScreens = ScreenCount(dpy);
+ int screenNum;
+ for (screenNum = 0; screenNum < numScreens; screenNum++) {
+ __DRIdriver *driver = driGetDriver(dpy, screenNum);
+ if (driver && driver->registerExtensionsFunc) {
+ (*driver->registerExtensionsFunc)();
+ }
+ }
+ XCloseDisplay(dpy);
+ }
+ else {
+ break;
+ }
+ }
+#endif
+}
+
+
diff --git a/src/dri-es/dri_glx.h b/src/dri-es/dri_glx.h
new file mode 100644
index 0000000000..4915318445
--- /dev/null
+++ b/src/dri-es/dri_glx.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+
+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_
+
+
+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 /* _DRI_GLX_H_ */
diff --git a/src/dri-es/dri_util.c b/src/dri-es/dri_util.c
new file mode 100644
index 0000000000..a9a2bf6d5d
--- /dev/null
+++ b/src/dri-es/dri_util.c
@@ -0,0 +1,1109 @@
+/* $XFree86$ */
+/**************************************************************************
+
+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 E. Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * This file gets compiled into each of the DRI 3D drivers. This is
+ * basically just a collection of utility functions that are useful
+ * for most drivers. A DRI driver doesn't have to use any of this,
+ * but it's useful boilerplate.
+ *
+ *
+ * Many of the functions defined here are called from the GL library
+ * via function pointers in the __DRIdisplayRec, __DRIscreenRec,
+ * __DRIcontextRec, __DRIdrawableRec structures defined in glxclient.h
+ *
+ * Those function pointers are initialized by code in this file.
+ * The process starts when libGL calls the __driCreateScreen() function
+ * at the end of this file.
+ *
+ * The above-mentioned DRI structures have no dependencies on Mesa.
+ * Each structure instead has a generic (void *) private pointer that
+ * points to a private structure. For the current drivers, these private
+ * structures are the __DRIdrawablePrivateRec, __DRIcontextPrivateRec,
+ * __DRIscreenPrivateRec, and __DRIvisualPrivateRec structures defined
+ * in dri_util.h. We allocate and attach those structs here in
+ * this file.
+ */
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <X11/Xlibint.h>
+#include <Xext.h>
+#include <extutil.h>
+#include <stdio.h>
+#include "glxclient.h"
+#include "xf86dri.h"
+#include "sarea.h"
+#include "dri_util.h"
+
+
+/* forward declarations */
+static void *driCreateDrawable(Display *dpy, int scrn, GLXDrawable draw,
+ GLboolean isPixmap,
+ VisualID vid, __DRIdrawable *pdraw);
+
+static void driDestroyDrawable(Display *dpy, void *drawablePrivate);
+
+
+
+
+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;
+}
+
+
+/*
+** Print message to stderr if LIBGL_DEBUG env var is set.
+*/
+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");
+ }
+}
+
+
+/*****************************************************************/
+
+
+/*
+ * Initialize a __GLcontextModes structure with the GLX parameters
+ * specified by the given visual ID. Too bad that the __GLXvisualConfig
+ * and __GLcontextModes structures are so similar, but separate.
+ */
+static GLboolean
+findConfigMode(Display *dpy, int scrn, VisualID vid, __GLcontextModes *modes)
+{
+ const __GLXvisualConfig *config;
+ const __DRIscreen *pDRIScreen;
+ const __DRIscreenPrivate *screenPriv;
+ int i;
+
+ pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+ if (!pDRIScreen)
+ return GL_FALSE;
+ screenPriv = (const __DRIscreenPrivate *) pDRIScreen->private;
+
+ /* Search list of configs for matching vid */
+ config = NULL;
+ for (i = 0; i < screenPriv->numConfigs; i++) {
+ if (screenPriv->configs[i].vid == vid) {
+ config = screenPriv->configs + i;
+ break;
+ }
+ }
+ if (!config)
+ return GL_FALSE;
+
+ /* return mode parameters */
+ memset(modes, 0, sizeof(__GLcontextModes));
+
+ modes->rgbMode = (config->rgba != 0);
+ modes->colorIndexMode = !(modes->rgbMode);
+ modes->doubleBufferMode = (config->doubleBuffer != 0);
+ modes->stereoMode = (config->stereo != 0);
+
+ modes->haveAccumBuffer = ((config->accumRedSize +
+ config->accumGreenSize +
+ config->accumBlueSize +
+ config->accumAlphaSize) > 0);
+ modes->haveDepthBuffer = (config->depthSize > 0);
+ modes->haveStencilBuffer = (config->stencilSize > 0);
+
+ modes->redBits = config->redSize;
+ modes->greenBits = config->greenSize;
+ modes->blueBits = config->blueSize;
+ modes->alphaBits = config->alphaSize;
+ modes->redMask = config->redMask;
+ modes->greenMask = config->greenMask;
+ modes->blueMask = config->blueMask;
+ modes->alphaMask = config->alphaMask;
+ modes->rgbBits = config->bufferSize;
+ modes->indexBits = config->bufferSize;
+
+ modes->accumRedBits = config->accumRedSize;
+ modes->accumGreenBits = config->accumGreenSize;
+ modes->accumBlueBits = config->accumBlueSize;
+ modes->accumAlphaBits = config->accumAlphaSize;
+ modes->depthBits = config->depthSize;
+ modes->stencilBits = config->stencilSize;
+
+ modes->numAuxBuffers = 0; /* XXX: should be picked up from the visual */
+ modes->level = config->level;
+
+ return GL_TRUE;
+}
+
+
+/*****************************************************************/
+
+/* Maintain a list of drawables */
+
+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);
+ }
+}
+
+static Bool __driWindowExistsFlag;
+
+static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
+{
+ if (xerr->error_code == BadWindow) {
+ __driWindowExistsFlag = GL_FALSE;
+ }
+ return 0;
+}
+
+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;
+}
+
+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;
+ /* XXX someday, use libGL's __glXWindowExists() function */
+ if (!__driWindowExists(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));
+ }
+}
+
+/*****************************************************************/
+
+static Bool driUnbindContext(Display *dpy, int scrn,
+ GLXDrawable draw, GLXContext gc,
+ int will_rebind)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIdrawable *pdraw;
+ __DRIcontextPrivate *pcp;
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext.
+ */
+
+ if (gc == NULL || draw == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ } else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pcp = (__DRIcontextPrivate *)gc->driContext.private;
+
+ pdraw = __driFindDrawable(psp->drawHash, draw);
+ if (!pdraw) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+ pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ /* Don't leave fullscreen mode if the
+ drawable will be rebound in the next
+ step -- this avoids a protocol
+ request. */
+ if (!will_rebind && psp->fullscreen) {
+ psp->DriverAPI.CloseFullScreen(pcp);
+ XF86DRICloseFullScreen(dpy, scrn, draw);
+ psp->fullscreen = NULL;
+ }
+
+ /* Let driver unbind drawable from context */
+ (*psp->DriverAPI.UnbindContext)(pcp);
+
+ if (pdp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ } else if (--pdp->refcount == 0) {
+#if 0
+ /*
+ ** NOT_DONE: When a drawable is unbound from one direct
+ ** rendering context and then bound to another, we do not want
+ ** to destroy the drawable data structure each time only to
+ ** recreate it immediatly afterwards when binding to the next
+ ** context. This also causes conflicts with caching of the
+ ** drawable stamp.
+ **
+ ** In addition, we don't destroy the drawable here since Mesa
+ ** keeps private data internally (e.g., software accumulation
+ ** buffers) that should not be destroyed unless the client
+ ** explicitly requests that the window be destroyed.
+ **
+ ** When GLX 1.3 is integrated, the create and destroy drawable
+ ** functions will have user level counterparts and the memory
+ ** will be able to be recovered.
+ **
+ ** Below is an example of what needs to go into the destroy
+ ** drawable routine to support GLX 1.3.
+ */
+ __driRemoveDrawable(psp->drawHash, pdraw);
+ (*pdraw->destroyDrawable)(dpy, pdraw->private);
+ Xfree(pdraw);
+#endif
+ }
+
+ /* 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 glXMakeCurrentReadSGI() or GLX 1.3's
+ * glxMakeContextCurrent() function.
+ */
+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;
+ static Bool envchecked = False;
+ static Bool checkfullscreen = False;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driBindContext.
+ */
+
+ if (gc == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ } else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* Find the _DRIdrawable which corresponds to the writing GLXDrawable */
+ 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 */
+ pdraw->private = driCreateDrawable(dpy, scrn, draw, GL_FALSE,
+ gc->vid, pdraw);
+ if (!pdraw->private) {
+ /* ERROR!!! */
+ Xfree(pdraw);
+ return GL_FALSE;
+ }
+
+ /* Add pdraw to drawable list */
+ if (!__driAddDrawable(psp->drawHash, pdraw)) {
+ /* ERROR!!! */
+ (*pdraw->destroyDrawable)(dpy, pdraw->private);
+ 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 */
+ pread->private = driCreateDrawable(dpy, scrn, read, GL_FALSE,
+ gc->vid, pread);
+ if (!pread->private) {
+ /* ERROR!!! */
+ Xfree(pread);
+ return GL_FALSE;
+ }
+
+ /* Add pread to drawable list */
+ if (!__driAddDrawable(psp->drawHash, pread)) {
+ /* ERROR!!! */
+ (*pread->destroyDrawable)(dpy, pread->private);
+ 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++;
+
+ /*
+ ** Now that we have a context associated with this drawable, we can
+ ** initialize the drawable information if has not been done before.
+ ** Also, since we need it when LIBGL_DRI_FULLSCREEN, pick up any changes
+ ** that are outstanding.
+ */
+ 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);
+
+ /* Check for the potential to enter an automatic full-screen mode.
+ This may need to be moved up. */
+ if (!envchecked) {
+ checkfullscreen = driFeatureOn("LIBGL_DRI_AUTOFULLSCREEN");
+ envchecked = GL_TRUE;
+ }
+ if (checkfullscreen && pdp->numClipRects == 1) {
+ /* If there is valid information in the SAREA, we can use it to
+ avoid a protocol request. The only time when the SAREA
+ information won't be valid will be initially, so in the worst
+ case, we'll make one protocol request that we could have
+ avoided. */
+ int try = 1;
+ int clw = pdp->pClipRects[0].x2 - pdp->pClipRects[0].x1;
+ int clh = pdp->pClipRects[0].y2 - pdp->pClipRects[0].y1;
+
+#if 0
+ /* Useful client-side debugging message */
+ fprintf(stderr,
+ "********************************************\n"
+ "********************************************\n"
+ "********************************************\n"
+ "%d @ %d,%d,%d,%d\n"
+ "frame %d,%d,%d,%d\n"
+ "win %d,%d,%d,%d\n"
+ "fs = %p pdp = %p sarea = %d\n"
+ "********************************************\n"
+ "********************************************\n"
+ "********************************************\n",
+ pdp->numClipRects,
+ pdp->pClipRects[0].x1,
+ pdp->pClipRects[0].y1,
+ pdp->pClipRects[0].x2,
+ pdp->pClipRects[0].y2,
+ psp->pSAREA->frame.x,
+ psp->pSAREA->frame.y,
+ psp->pSAREA->frame.width,
+ psp->pSAREA->frame.height,
+ pdp->x, pdp->y, pdp->w, pdp->h,
+ psp->fullscreen, pdp, psp->pSAREA->frame.fullscreen);
+#endif
+
+
+ if (pdp->x != pdp->pClipRects[0].x1
+ || pdp->y != pdp->pClipRects[0].y1
+ || pdp->w != clw
+ || pdp->h != clh) try = 0;
+
+ if (try && psp->pSAREA->frame.width && psp->pSAREA->frame.height) {
+ if (pdp->x != psp->pSAREA->frame.x
+ || pdp->y != psp->pSAREA->frame.y
+ || pdp->w != psp->pSAREA->frame.width
+ || pdp->h != psp->pSAREA->frame.height) try = 0;
+ }
+
+ if (try) {
+ if (psp->fullscreen && !psp->pSAREA->frame.fullscreen) {
+ /* Server has closed fullscreen mode */
+ __driUtilMessage("server closed fullscreen mode\n");
+ psp->fullscreen = NULL;
+ }
+ if (XF86DRIOpenFullScreen(dpy, scrn, draw)) {
+ psp->fullscreen = pdp;
+ psp->DriverAPI.OpenFullScreen(pcp);
+ }
+ }
+ }
+
+ 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);
+}
+
+
+/*****************************************************************/
+
+/*
+ * This function basically updates the __DRIdrawablePrivate struct's
+ * cliprect information by calling XF86DRIGetDrawableInfo(). 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 (!XF86DRIGetDrawableInfo(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 = 0;
+ }
+ else
+ pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+}
+
+/*****************************************************************/
+
+/*
+ * Called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers( Display *dpy, void *drawablePrivate )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ dPriv->swapBuffers(dPriv);
+ (void) dpy;
+}
+
+
+/*
+ * This is called via __DRIscreenRec's createDrawable pointer.
+ * libGL doesn't use it at this time. See comments in glxclient.h.
+ */
+static void *driCreateDrawable_dummy(Display *dpy, int scrn,
+ GLXDrawable draw,
+ VisualID vid, __DRIdrawable *pdraw)
+{
+ return driCreateDrawable(dpy, scrn, draw, GL_FALSE, vid, pdraw);
+}
+
+
+
+static void *driCreateDrawable(Display *dpy, int scrn, GLXDrawable draw,
+ GLboolean isPixmap,
+ VisualID vid, __DRIdrawable *pdraw)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+ __GLcontextModes modes;
+
+ pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
+ if (!pdp) {
+ return NULL;
+ }
+
+ if (!XF86DRICreateDrawable(dpy, scrn, draw, &pdp->hHWDrawable)) {
+ Xfree(pdp);
+ return NULL;
+ }
+
+ pdp->draw = draw;
+ 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 = scrn;
+
+ if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ Xfree(pdp);
+ return NULL;
+ } else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ Xfree(pdp);
+ return NULL;
+ }
+ pdp->driScreenPriv = psp;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+
+ if (!findConfigMode(dpy, scrn, vid, &modes))
+ return NULL;
+
+ if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &modes, isPixmap)) {
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ Xfree(pdp);
+ return NULL;
+ }
+
+ pdraw->destroyDrawable = driDestroyDrawable;
+ pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
+ pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
+
+ 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 (__driWindowExists(dpy, pdp->draw))
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ if (pdp->pClipRects)
+ Xfree(pdp->pClipRects);
+ Xfree(pdp);
+ }
+}
+
+/*****************************************************************/
+
+static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate)
+{
+ __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate;
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+
+ if (pcp) {
+ if ((pdp = pcp->driDrawablePriv)) {
+ /* Shut down fullscreen mode */
+ if ((psp = pdp->driScreenPriv) && psp->fullscreen) {
+ psp->DriverAPI.CloseFullScreen(pcp);
+ XF86DRICloseFullScreen(dpy, scrn, pdp->draw);
+ psp->fullscreen = NULL;
+ }
+ }
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+ (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+ (void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
+ Xfree(pcp);
+ }
+}
+
+static void *driCreateContext(Display *dpy, XVisualInfo *vis,
+ void *sharedPrivate,
+ __DRIcontext *pctx)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIcontextPrivate *pcp;
+ __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
+ __DRIscreenPrivate *psp;
+ __GLcontextModes modes;
+ void *shareCtx;
+
+ if (!(pDRIScreen = __glXFindDRIScreen(dpy, vis->screen))) {
+ /* ERROR!!! */
+ return NULL;
+ } else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
+ /* ERROR!!! */
+ return NULL;
+ }
+
+ if (!psp->dummyContextPriv.driScreenPriv) {
+ if (!XF86DRICreateContext(dpy, vis->screen, vis->visual,
+ &psp->dummyContextPriv.contextID,
+ &psp->dummyContextPriv.hHWContext)) {
+ return NULL;
+ }
+ psp->dummyContextPriv.driScreenPriv = psp;
+ psp->dummyContextPriv.driDrawablePriv = NULL;
+ psp->dummyContextPriv.driverPrivate = NULL;
+ /* No other fields should be used! */
+ }
+
+ /* Create the hash table */
+ if (!psp->drawHash) psp->drawHash = drmHashCreate();
+
+ pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
+ if (!pcp) {
+ return NULL;
+ }
+
+ pcp->display = dpy;
+ pcp->driScreenPriv = psp;
+ pcp->driDrawablePriv = NULL;
+
+ if (!XF86DRICreateContext(dpy, vis->screen, vis->visual,
+ &pcp->contextID, &pcp->hHWContext)) {
+ Xfree(pcp);
+ return NULL;
+ }
+
+ /* This is moved because the Xserver creates a global dummy context
+ * the first time XF86DRICreateContext is called.
+ */
+
+ if (!psp->dummyContextPriv.driScreenPriv) {
+#if 0
+ /* We no longer use this cause we have the shared dummyContext
+ * in the SAREA.
+ */
+ if (!XF86DRICreateContext(dpy, vis->screen, vis->visual,
+ &psp->dummyContextPriv.contextID,
+ &psp->dummyContextPriv.hHWContext)) {
+ return NULL;
+ }
+#endif
+ 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! */
+ }
+
+ /* Setup a __GLcontextModes struct corresponding to vis->visualid
+ * and create the rendering context.
+ */
+ if (!findConfigMode(dpy, vis->screen, vis->visualid, &modes))
+ return NULL;
+
+ shareCtx = pshare ? pshare->driverPrivate : NULL;
+ if (!(*psp->DriverAPI.CreateContext)(&modes, pcp, shareCtx)) {
+ (void)XF86DRIDestroyContext(dpy, vis->screen, pcp->contextID);
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pctx->destroyContext = driDestroyContext;
+ pctx->bindContext = driBindContext;
+ pctx->unbindContext = driUnbindContext;
+
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+
+ return pcp;
+}
+
+/*****************************************************************/
+
+static void driDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
+{
+ __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+ if (psp) {
+#if 0
+ /*
+ ** NOT_DONE: For the same reason as that listed below, we cannot
+ ** call the X server here to destroy the dummy context.
+ */
+ if (psp->dummyContextPriv.driScreenPriv) {
+ (void)XF86DRIDestroyContext(dpy, scrn,
+ psp->dummyContextPriv.contextID);
+ }
+#endif
+ 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);
+ Xfree(psp);
+
+#if 0
+ /*
+ ** NOT_DONE: Normally, we would call XF86DRICloseConnection()
+ ** here, but since this routine is called after the
+ ** XCloseDisplay() function has already shut down the connection
+ ** to the Display, there is no protocol stream open to the X
+ ** server anymore. Luckily, XF86DRICloseConnection() does not
+ ** really do anything (for now).
+ */
+ (void)XF86DRICloseConnection(dpy, scrn);
+#endif
+ }
+}
+
+
+__DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *configs,
+ const struct __DriverAPIRec *driverAPI)
+{
+ int directCapable;
+ __DRIscreenPrivate *psp;
+ drmHandle hFB, hSAREA;
+ char *BusID, *driverName;
+ drmMagic magic;
+
+ if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)) {
+ return NULL;
+ }
+
+ if (!directCapable) {
+ return NULL;
+ }
+
+ psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
+ if (!psp) {
+ return NULL;
+ }
+
+ psp->display = dpy;
+ psp->myNum = scrn;
+
+ psp->numConfigs = numConfigs;
+ psp->configs = configs;
+
+ if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ /*
+ ** 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->fd = drmOpen(NULL,BusID);
+ if (psp->fd < 0) {
+ fprintf(stderr, "libGL error: failed to open DRM: %s\n", strerror(-psp->fd));
+ fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+ Xfree(BusID);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+ Xfree(BusID); /* No longer needed */
+
+ if (drmGetMagic(psp->fd, &magic)) {
+ fprintf(stderr, "libGL error: drmGetMagic failed\n");
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ {
+ drmVersionPtr version = drmGetVersion(psp->fd);
+ if (version) {
+ psp->drmMajor = version->version_major;
+ psp->drmMinor = version->version_minor;
+ psp->drmPatch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ psp->drmMajor = -1;
+ psp->drmMinor = -1;
+ psp->drmPatch = -1;
+ }
+ }
+
+ if (!XF86DRIAuthConnection(dpy, scrn, magic)) {
+ fprintf(stderr, "libGL error: XF86DRIAuthConnection failed\n");
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ /*
+ * Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createScreen"
+ * function.
+ */
+ if (!XF86DRIGetClientDriverName(dpy, scrn,
+ &psp->ddxMajor,
+ &psp->ddxMinor,
+ &psp->ddxPatch,
+ &driverName)) {
+ fprintf(stderr, "libGL error: XF86DRIGetClientDriverName failed\n");
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ /*
+ * Get the DRI X extension version.
+ */
+ if (!XF86DRIQueryVersion(dpy,
+ &psp->driMajor,
+ &psp->driMinor,
+ &psp->driPatch)) {
+ fprintf(stderr, "libGL error: XF86DRIQueryVersion failed\n");
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ /* install driver's callback functions */
+ memcpy(&psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec));
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
+ * that has information about the screen size, depth, pitch,
+ * ancilliary buffers, DRM mmap handles, etc.
+ */
+ if (!XF86DRIGetDeviceInfo(dpy, scrn,
+ &hFB,
+ &psp->fbOrigin,
+ &psp->fbSize,
+ &psp->fbStride,
+ &psp->devPrivSize,
+ &psp->pDevPriv)) {
+ fprintf(stderr, "libGL error: XF86DRIGetDeviceInfo failed\n");
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+ psp->fbWidth = DisplayWidth(dpy, scrn);
+ psp->fbHeight = DisplayHeight(dpy, scrn);
+ psp->fbBPP = 32; /* NOT_DONE: Get this from X server */
+
+ /*
+ * Map the framebuffer region.
+ */
+ if (drmMap(psp->fd, hFB, psp->fbSize, (drmAddressPtr)&psp->pFB)) {
+ fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
+ Xfree(psp->pDevPriv);
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ /*
+ * Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createScreen" function.
+ */
+ if (drmMap(psp->fd, hSAREA, SAREA_MAX, (drmAddressPtr)&psp->pSAREA)) {
+ fprintf(stderr, "libGL error: drmMap of sarea failed\n");
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ Xfree(psp->pDevPriv);
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+
+ /* Initialize the screen specific GLX driver */
+ if (psp->DriverAPI.InitDriver) {
+ if (!(*psp->DriverAPI.InitDriver)(psp)) {
+ fprintf(stderr, "libGL error: InitDriver failed\n");
+ (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ Xfree(psp->pDevPriv);
+ (void)drmClose(psp->fd);
+ Xfree(psp);
+ (void)XF86DRICloseConnection(dpy, scrn);
+ return NULL;
+ }
+ }
+
+ /*
+ ** 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;
+
+ /* Initialize the drawHash when the first context is created */
+ psp->drawHash = NULL;
+
+ psc->destroyScreen = driDestroyScreen;
+ psc->createContext = driCreateContext;
+ psc->createDrawable = driCreateDrawable_dummy;
+ psc->getDrawable = driGetDrawable;
+
+ return psp;
+}
+
+
diff --git a/src/dri-es/dri_util.h b/src/dri-es/dri_util.h
new file mode 100644
index 0000000000..f66576e457
--- /dev/null
+++ b/src/dri-es/dri_util.h
@@ -0,0 +1,375 @@
+/* $XFree86$ */
+/**************************************************************************
+
+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>
+ */
+
+/*
+ * This module acts as glue between GLX and the actual hardware driver.
+ * A DRI driver doesn't really _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.
+ *
+ * Look for more comments in the dri_util.c file.
+ */
+
+
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#define CAPI /* XXX this should be globally defined somewhere */
+
+#include "glxclient.h" /* for GLXDrawable */
+#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;
+
+
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
+ do { \
+ if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
+ __driUtilUpdateDrawableInfo(pDrawPriv); \
+ } \
+ } while (0)
+
+
+#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)
+
+
+/* Each DRI driver must have one of these structs 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 CreateContext
+ * pointer in this structure.
+ */
+struct __DriverAPIRec {
+ GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
+ void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
+ GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+ void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
+ GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *glVis,
+ GLboolean pixmapBuffer);
+ void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
+ void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
+ GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv);
+ GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
+ GLboolean (*OpenFullScreen)(__DRIcontextPrivate *driContextPriv);
+ GLboolean (*CloseFullScreen)(__DRIcontextPrivate *driContextPriv);
+};
+
+
+struct __DRIdrawablePrivateRec {
+ /*
+ ** Kernel drawable handle (not currently used).
+ */
+ drmDrawable hHWDrawable;
+
+ /*
+ ** Driver's private drawable information. This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /*
+ ** X's drawable ID associated with this private drawable.
+ */
+ GLXDrawable draw;
+
+ /*
+ ** Reference count for number of context's currently bound to this
+ ** drawable. Once the refcount reaches 0, the drawable can be
+ ** destroyed. This behavior will change with GLX 1.3.
+ */
+ int refcount;
+
+ /*
+ ** Index of this drawable's 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 *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;
+
+ /*
+ ** Drawable information used in software fallbacks.
+ */
+ int x;
+ int y;
+ int w;
+ int h;
+ int numClipRects;
+ XF86DRIClipRectPtr pClipRects;
+
+ /*
+ ** 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;
+
+ /*
+ ** 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 );
+};
+
+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;
+};
+
+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;
+
+ /*
+ ** DDX / 2D driver version information.
+ */
+ int ddxMajor;
+ int ddxMinor;
+ int ddxPatch;
+
+ /*
+ ** DRI X extension version information.
+ */
+ int driMajor;
+ int driMinor;
+ int driPatch;
+
+ /*
+ ** DRM (kernel module) version information.
+ */
+ 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.
+ ** It is 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;
+
+ /*
+ ** Direct frame buffer access information used for software
+ ** fallbacks.
+ */
+ unsigned char *pFB;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ int fbWidth;
+ int fbHeight;
+ int fbBPP;
+
+ /*
+ ** 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 HW 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;
+
+ /* If we're in full screen mode (via DRIOpenFullScreen), this points
+ to the drawable that was bound. Otherwise, this is NULL. */
+ __DRIdrawablePrivate *fullscreen;
+
+ /*
+ ** Number of visuals (configs) for this screen, and a pointer to them.
+ */
+ int numConfigs;
+ __GLXvisualConfig *configs;
+};
+
+
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
+
+
+extern __DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config,
+ const struct __DriverAPIRec *driverAPI);
+
+/* This must be implemented in each driver */
+extern void *
+__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config);
+
+
+/* This is optionally implemented in each driver */
+extern void
+__driRegisterExtensions( void );
+
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/src/dri-es/drm.h b/src/dri-es/drm.h
new file mode 100644
index 0000000000..d1d669437f
--- /dev/null
+++ b/src/dri-es/drm.h
@@ -0,0 +1,474 @@
+/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.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
+ * 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.
+ *
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * Acknowledgements:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg.
+ *
+ */
+
+#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__)
+#if defined(__FreeBSD__) && defined(XFree86Server)
+/* 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)
+#define DRM_MAJOR 226
+#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;
+
+/* Warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well */
+
+/* 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;
+
+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;
+
+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;
+
+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;
+
+typedef struct drm_control {
+ enum {
+ DRM_ADD_COMMAND,
+ DRM_RM_COMMAND,
+ DRM_INST_HANDLER,
+ DRM_UNINST_HANDLER
+ } func;
+ int irq;
+} drm_control_t;
+
+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;
+
+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;
+
+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;
+
+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;
+
+typedef struct drm_stats {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats_t;
+
+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;
+
+typedef struct drm_lock {
+ int context;
+ drm_lock_flags_t flags;
+} drm_lock_t;
+
+typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
+ /* 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;
+
+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;
+
+typedef struct drm_buf_info {
+ int count; /* Entries in list */
+ drm_buf_desc_t *list;
+} drm_buf_info_t;
+
+typedef struct drm_buf_free {
+ int count;
+ int *list;
+} drm_buf_free_t;
+
+typedef struct drm_buf_pub {
+ int idx; /* Index into master buflist */
+ int total; /* Buffer size */
+ int used; /* Amount of buffer in use (for DMA) */
+ void *address; /* Address of buffer */
+} drm_buf_pub_t;
+
+typedef struct drm_buf_map {
+ int count; /* Length of buflist */
+ void *virtual; /* Mmaped area in user-virtual */
+ drm_buf_pub_t *list; /* Buffer information */
+} drm_buf_map_t;
+
+typedef struct drm_dma {
+ /* Indices here refer to the offset into
+ buflist in drm_buf_get_t. */
+ 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;
+
+typedef struct drm_ctx {
+ drm_context_t handle;
+ drm_ctx_flags_t flags;
+} drm_ctx_t;
+
+typedef struct drm_ctx_res {
+ int count;
+ drm_ctx_t *contexts;
+} drm_ctx_res_t;
+
+typedef struct drm_draw {
+ drm_drawable_t handle;
+} drm_draw_t;
+
+typedef struct drm_auth {
+ drm_magic_t magic;
+} drm_auth_t;
+
+typedef struct drm_irq_busid {
+ int irq;
+ int busnum;
+ int devnum;
+ int funcnum;
+} 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;
+};
+
+typedef union drm_wait_vblank {
+ struct drm_wait_vblank_request request;
+ struct drm_wait_vblank_reply reply;
+} drm_wait_vblank_t;
+
+typedef struct drm_agp_mode {
+ unsigned long mode;
+} drm_agp_mode_t;
+
+ /* For drm_agp_alloc -- allocated a buffer */
+typedef struct drm_agp_buffer {
+ unsigned long size; /* In bytes -- will round to page boundary */
+ unsigned long handle; /* Used for BIND/UNBIND ioctls */
+ unsigned long type; /* Type of memory to allocate */
+ unsigned long physical; /* Physical used by i810 */
+} drm_agp_buffer_t;
+
+ /* For drm_agp_bind */
+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;
+
+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;
+
+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;
+
+#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_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 specfic ioctls should only be in their respective headers
+ * The device specific ioctl range is 0x40 to 0x79. */
+#define DRM_COMMAND_BASE 0x40
+
+#endif
diff --git a/src/dri-es/extutil.h b/src/dri-es/extutil.h
new file mode 100644
index 0000000000..cb3592770a
--- /dev/null
+++ b/src/dri-es/extutil.h
@@ -0,0 +1,224 @@
+/*
+ * $Xorg: extutil.h,v 1.4 2001/02/09 02:03:24 xorgcvs Exp $
+ *
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Jim Fulton, MIT The Open Group
+ *
+ * Xlib Extension-Writing Utilities
+ *
+ * This package contains utilities for writing the client API for various
+ * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND
+ * ARE SUBJECT TO CHANGE!
+ */
+/* $XFree86: xc/include/extensions/extutil.h,v 1.9 2001/12/14 19:53:28 dawes Exp $ */
+
+#ifndef _EXTUTIL_H_
+#define _EXTUTIL_H_
+
+#include <X11/extensions/Xext.h>
+
+/*
+ * We need to keep a list of open displays since the Xlib display list isn't
+ * public. We also have to per-display info in a separate block since it isn't
+ * stored directly in the Display structure.
+ */
+typedef struct _XExtDisplayInfo {
+ struct _XExtDisplayInfo *next; /* keep a linked list */
+ Display *display; /* which display this is */
+ XExtCodes *codes; /* the extension protocol codes */
+ XPointer data; /* extra data for extension to use */
+} XExtDisplayInfo;
+
+typedef struct _XExtensionInfo {
+ XExtDisplayInfo *head; /* start of list */
+ XExtDisplayInfo *cur; /* most recently used */
+ int ndisplays; /* number of displays */
+} XExtensionInfo;
+
+typedef struct _XExtensionHooks {
+ int (*create_gc)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ GC /* gc */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*copy_gc)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ GC /* gc */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*flush_gc)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ GC /* gc */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*free_gc)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ GC /* gc */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*create_font)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ XFontStruct* /* fs */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*free_font)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ XFontStruct* /* fs */,
+ XExtCodes* /* codes */
+#endif
+);
+ int (*close_display)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ XExtCodes* /* codes */
+#endif
+);
+ Bool (*wire_to_event)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ XEvent* /* re */,
+ xEvent* /* event */
+#endif
+);
+ Status (*event_to_wire)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ XEvent* /* re */,
+ xEvent* /* event */
+#endif
+);
+ int (*error)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ xError* /* err */,
+ XExtCodes* /* codes */,
+ int* /* ret_code */
+#endif
+);
+ char *(*error_string)(
+#if NeedNestedPrototypes
+ Display* /* display */,
+ int /* code */,
+ XExtCodes* /* codes */,
+ char* /* buffer */,
+ int /* nbytes */
+#endif
+);
+} XExtensionHooks;
+
+extern XExtensionInfo *XextCreateExtension(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+extern void XextDestroyExtension(
+#if NeedFunctionPrototypes
+ XExtensionInfo* /* info */
+#endif
+);
+extern XExtDisplayInfo *XextAddDisplay(
+#if NeedFunctionPrototypes
+ XExtensionInfo* /* extinfo */,
+ Display* /* dpy */,
+ char* /* ext_name */,
+ XExtensionHooks* /* hooks */,
+ int /* nevents */,
+ XPointer /* data */
+#endif
+);
+extern int XextRemoveDisplay(
+#if NeedFunctionPrototypes
+ XExtensionInfo* /* extinfo */,
+ Display* /* dpy */
+#endif
+);
+extern XExtDisplayInfo *XextFindDisplay(
+#if NeedFunctionPrototypes
+ XExtensionInfo* /* extinfo */,
+ Display* /* dpy */
+#endif
+);
+
+#define XextHasExtension(i) ((i) && ((i)->codes))
+#define XextCheckExtension(dpy,i,name,val) \
+ if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; }
+#define XextSimpleCheckExtension(dpy,i,name) \
+ if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; }
+
+
+/*
+ * helper macros to generate code that is common to all extensions; caller
+ * should prefix it with static if extension source is in one file; this
+ * could be a utility function, but have to stack 6 unused arguments for
+ * something that is called many, many times would be bad.
+ */
+#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \
+XExtDisplayInfo *proc (Display *dpy) \
+{ \
+ XExtDisplayInfo *dpyinfo; \
+ if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \
+ if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \
+ dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \
+ return dpyinfo; \
+}
+
+#define XEXT_FIND_DISPLAY_PROTO(proc) \
+ XExtDisplayInfo *proc(Display *dpy)
+
+#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \
+int proc (Display *dpy, XExtCodes *codes) \
+{ \
+ return XextRemoveDisplay (extinfo, dpy); \
+}
+
+#define XEXT_CLOSE_DISPLAY_PROTO(proc) \
+ int proc(Display *dpy, XExtCodes *codes)
+
+#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \
+char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \
+{ \
+ code -= codes->first_error; \
+ if (code >= 0 && code < nerr) { \
+ char tmp[256]; \
+ sprintf (tmp, "%s.%d", extname, code); \
+ XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \
+ return buf; \
+ } \
+ return (char *)0; \
+}
+
+#define XEXT_ERROR_STRING_PROTO(proc) \
+ char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n)
+#endif
diff --git a/src/dri-es/glxclient.h b/src/dri-es/glxclient.h
new file mode 100644
index 0000000000..610d3e4fec
--- /dev/null
+++ b/src/dri-es/glxclient.h
@@ -0,0 +1,678 @@
+/*
+** 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.14 2002/02/22 21:32:53 dawes Exp $ */
+
+/*
+ * Direct rendering support added by Precision Insight, Inc.
+ *
+ * Authors:
+ * 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 <string.h>
+#include <stdlib.h>
+#include "GL/glxint.h"
+#include "GL/glxproto.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 __GL_BOOLEAN_ARRAY (GL_BYTE - 1)
+
+#define __GLX_MAX_TEXTURE_UNITS 32
+
+typedef struct __GLXcontextRec __GLXcontext;
+typedef struct __GLXdisplayPrivateRec __GLXdisplayPrivate;
+typedef struct _glapi_table __GLapi;
+
+/************************************************************************/
+
+
+/*
+** 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;
+
+extern __DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn);
+
+/*
+** Display dependent methods. This structure is initialized during the
+** 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.
+ */
+ void *(**createScreen)(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config);
+
+ /*
+ ** Opaque pointer to private per display direct rendering data.
+ ** NULL if direct rendering is not supported on this display. Never
+ ** dereferenced in libGL.
+ */
+ void *private;
+};
+
+/*
+** Screen dependent methods. This structure is initialized during the
+** (*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.
+ */
+ 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 *(*createDrawable)(Display *dpy, int scrn, GLXDrawable draw,
+ VisualID vid, __DRIdrawable *pdraw);
+
+ /*
+ ** Method to return a pointer to the DRI drawable data.
+ */
+ __DRIdrawable *(*getDrawable)(Display *dpy, GLXDrawable draw,
+ void *drawablePrivate);
+
+ /*
+ ** XXX in the future, implement this:
+ void *(*createPBuffer)(Display *dpy, int scrn, GLXPbuffer pbuffer,
+ GLXFBConfig config, __DRIdrawable *pdraw);
+ **/
+
+ /*
+ ** Opaque pointer to private per screen direct rendering data. NULL
+ ** if direct rendering is not supported on this screen. Never
+ ** dereferenced in libGL.
+ */
+ void *private;
+};
+
+/*
+** Context dependent methods. This structure is initialized during the
+** (*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.
+ ** XXX in the future, also pass a 'read' GLXDrawable for
+ ** glXMakeCurrentReadSGI() and GLX 1.3's glXMakeContextCurrent().
+ */
+ 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.
+ ** NULL if direct rendering is not supported on the display or
+ ** screen used to create this context. Never dereferenced in libGL.
+ */
+ void *private;
+};
+
+/*
+** Drawable dependent methods. This structure is initialized during the
+** (*createDrawable)() call. 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.
+ ** NULL if direct rendering is not supported on the display or
+ ** screen used to create this drawable. Never dereferenced in libGL.
+ */
+ void *private;
+};
+
+
+typedef void *(*CreateScreenFunc)(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config);
+
+typedef void *(*RegisterExtensionsFunc)(void);
+
+/*
+** We keep a linked list of these structures, one per DRI device driver.
+*/
+struct __DRIdriverRec {
+ const char *name;
+ void *handle;
+ CreateScreenFunc createScreenFunc;
+ RegisterExtensionsFunc registerExtensionsFunc;
+ 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 );
+
+/************************************************************************/
+
+#define __GL_CLIENT_ATTRIB_STACK_DEPTH 16
+
+typedef struct __GLXpixelStoreModeRec {
+ GLboolean swapEndian;
+ GLboolean lsbFirst;
+ GLuint rowLength;
+ GLuint imageHeight;
+ GLuint imageDepth;
+ GLuint skipRows;
+ GLuint skipPixels;
+ GLuint skipImages;
+ GLuint alignment;
+} __GLXpixelStoreMode;
+
+typedef struct __GLXvertexArrayPointerStateRec {
+ GLboolean enable;
+ void (*proc)(const void *);
+ const GLubyte *ptr;
+ GLsizei skip;
+ GLint size;
+ GLenum type;
+ GLsizei stride;
+} __GLXvertexArrayPointerState;
+
+typedef struct __GLXvertArrayStateRec {
+ __GLXvertexArrayPointerState vertex;
+ __GLXvertexArrayPointerState normal;
+ __GLXvertexArrayPointerState color;
+ __GLXvertexArrayPointerState index;
+ __GLXvertexArrayPointerState texCoord[__GLX_MAX_TEXTURE_UNITS];
+ __GLXvertexArrayPointerState edgeFlag;
+ 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;
+} __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 {
+ /*
+ ** 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
+ ** __glXFlushRenderBuffer. "pc" is the next location in the buffer
+ ** to be filled. "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 shareList context.
+ */
+ XID share_xid;
+
+ /*
+ ** Visual id.
+ */
+ VisualID vid;
+
+ /*
+ ** screen number.
+ */
+ GLint screen;
+
+ /*
+ ** 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., Render, RenderLarge,
+ ** WaitX, WaitGL, UseXFont, and MakeCurrent (for the old context)).
+ */
+ GLXContextTag currentContextTag;
+
+ /*
+ ** The rendering mode is kept on the client as well as the server.
+ ** When glRenderMode() is called, the buffer associated with the
+ ** previous rendering mode (feedback or select) is filled.
+ */
+ GLenum renderMode;
+ GLfloat *feedbackBuf;
+ GLuint *selectBuf;
+
+ /*
+ ** This is 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 oldImage getting it
+ ** ready for transport to the server.
+ */
+ void (*fillImage)(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum,
+ GLenum, const GLvoid*, GLubyte*, GLubyte*);
+
+ /*
+ ** Client side attribs.
+ */
+ __GLXattribute state;
+ __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;
+
+ /*
+ ** dpy of current display for this context. Will be 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.
+ */
+ GLXDrawable currentDrawable;
+
+ /*
+ ** 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;
+
+ /*
+ ** Per context direct rendering interface functions and data.
+ */
+ __DRIcontext driContext;
+};
+
+#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
+** 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 {
+ __GLXvisualConfig *configs;
+ int numConfigs;
+ const char *serverGLXexts;
+ char *effectiveGLXexts;
+
+ /*
+ ** Per screen direct rendering interface functions and data.
+ */
+ __DRIscreen driScreen;
+} __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 majorOpcode is common to all connections to the same server.
+ ** It is also copied into the context structure.
+ */
+ int majorOpcode;
+
+ /*
+ ** Major and minor version returned by the server during initialization.
+ */
+ int majorVersion, minorVersion;
+
+ /* 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 GLX_EXTENSION
+ ** string.
+ */
+ __GLXscreenConfigs *screenConfigs;
+
+ /*
+ ** Per display direct rendering interface functions and data.
+ */
+ __DRIdisplay driDisplay;
+};
+
+void __glXFreeContext(__GLXcontext*);
+
+extern GLubyte *__glXFlushRenderBuffer(__GLXcontext*, GLubyte*);
+
+extern void __glXSendLargeCommand(__GLXcontext *, const GLvoid *, GLint,
+ const GLvoid *, GLint);
+
+/* Initialize the GLX extension for dpy */
+extern __GLXdisplayPrivate *__glXInitialize(Display*);
+
+/* Query drivers for dynamically registered extensions */
+extern void __glXRegisterExtensions(void);
+
+/* Functions for extending the GLX API: */
+extern void *__glXRegisterGLXFunction(const char *funcName, void *funcAddr);
+extern void __glXRegisterGLXExtensionString(const char *extName);
+
+
+/************************************************************************/
+
+extern int __glXDebug;
+
+/* This is per-thread storage in an MT environment */
+#if 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(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 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 char *__glXstrdup(const char *str);
+
+extern int __glXGetInternalVersion(void);
+
+extern Bool __glXWindowExists(Display *dpy, GLXDrawable draw);
+
+#endif /* !__GLX_client_h__ */
diff --git a/src/dri-es/sarea.h b/src/dri-es/sarea.h
new file mode 100644
index 0000000000..b990bb9dac
--- /dev/null
+++ b/src/dri-es/sarea.h
@@ -0,0 +1,80 @@
+/* $XFree86: xc/programs/Xserver/GL/dri/sarea.h,v 1.10 2001/10/04 18:28:20 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 <kevin@precisioninsight.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#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
+
+typedef struct _XF86DRISAREADrawable {
+ unsigned int stamp;
+ unsigned int flags;
+} XF86DRISAREADrawableRec, *XF86DRISAREADrawablePtr;
+
+typedef struct _XF86DRISAREAFrame {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned int fullscreen;
+} XF86DRISAREAFrameRec, *XF86DRISAREAFramePtr;
+
+typedef struct _XF86DRISAREA {
+ /* first thing is always the drm locking structure */
+ drmLock lock;
+ /* NOT_DONE: 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/dri-es/xf86dri.h b/src/dri-es/xf86dri.h
new file mode 100644
index 0000000000..10d5ec926e
--- /dev/null
+++ b/src/dri-es/xf86dri.h
@@ -0,0 +1,227 @@
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.7 2000/12/07 20:26:02 dawes 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
+#define X_XF86DRICloseFullScreen 13
+
+#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 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
+);
+
+Bool XF86DRIOpenFullScreen(
+#if NeedFunctionPrototypes
+ Display* /* dpy */,
+ int /* screen */,
+ Drawable /* drawable */
+#endif
+);
+
+Bool XF86DRICloseFullScreen(
+#if NeedFunctionPrototypes
+ Display* /* dpy */,
+ int /* screen */,
+ Drawable /* drawable */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/src/dri-es/xf86dristr.h b/src/dri-es/xf86dristr.h
new file mode 100644
index 0000000000..e9c8ccb1ea
--- /dev/null
+++ b/src/dri-es/xf86dristr.h
@@ -0,0 +1,343 @@
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.9 2001/03/21 16:01:08 dawes 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/dri-es/xf86drm.c b/src/dri-es/xf86drm.c
new file mode 100644
index 0000000000..6c830664bd
--- /dev/null
+++ b/src/dri-es/xf86drm.c
@@ -0,0 +1,1500 @@
+/* xf86drm.c -- User-level interface to DRM device
+ * Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.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.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.28 2002/10/16 01:26:49 dawes 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"
+
+#ifndef DRM_MAJOR
+#define DRM_MAJOR 226 /* Linux */
+#endif
+
+#ifndef __linux__
+#undef DRM_MAJOR
+#define DRM_MAJOR 145 /* Should set in drm.h for *BSD */
+#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
+
+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;
+}
+
+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
+
+ drmMsg("drmOpenDevice: minor is %d\n", minor);
+
+#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);
+ }
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ drmMsg("drmOpenDevice: node name is %s\n", buf);
+ 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;
+
+ if (st.st_rdev != dev) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+ }
+ 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;
+}
+
+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;
+}
+
+/* drmAvailable looks for (DRM_MAJOR, 0) and returns 1 if it returns
+ information for DRM_IOCTL_VERSION. 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) {
+ /* Try proc for backward Linux compatibility */
+ if (!access("/proc/dri/0", R_OK)) return 1;
+ return 0;
+ }
+
+ if ((version = drmGetVersion(fd))) {
+ retval = 1;
+ drmFreeVersion(version);
+ }
+ close(fd);
+
+ return retval;
+}
+
+static int drmOpenByBusid(const char *busid)
+{
+ int i;
+ int fd;
+ const char *buf;
+
+ drmMsg("drmOpenByBusid: busid is %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) {
+ buf = drmGetBusid(fd);
+ drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
+ if (buf && !strcmp(buf, busid)) {
+ drmFreeBusid(buf);
+ return fd;
+ }
+ if (buf) drmFreeBusid(buf);
+ close(fd);
+ }
+ }
+ return -1;
+}
+
+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;
+}
+
+/* drmOpen looks up the specified name and busid, and opens the device
+ found. The entry in /dev/dri is created if necessary (and if root).
+ A file descriptor is returned. On error, the return value is
+ negative. */
+
+int drmOpen(const char *name, const char *busid)
+{
+
+ if (busid) return drmOpenByBusid(busid);
+ return drmOpenByName(name);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+/* drmGet Version obtains the driver version information via an ioctl. Similar
+ * information is available via /proc/dri. */
+
+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)) {
+ 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;
+}
+
+/* drmGetLibVersion set version information for the drm user space library.
+ * this version number is driver indepedent */
+
+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
+ */
+ version->version_major = 1;
+ version->version_minor = 1;
+ version->version_patchlevel = 0;
+
+ return (drmVersionPtr)version;
+}
+
+void drmFreeBusid(const char *busid)
+{
+ drmFree((void *)busid);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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
+
+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;
+ }
+}
+
+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;
+}
+
+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);
+}
+
+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;
+}
+
+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;
+}
+
+int drmAgpAcquire(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+ return 0;
+}
+
+int drmAgpRelease(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+ return 0;
+}
+
+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;
+}
+
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+ unsigned long *address, unsigned long *handle)
+{
+ drm_agp_buffer_t b;
+ *handle = 0;
+ 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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+int drmAgpVersionMajor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_major;
+}
+
+int drmAgpVersionMinor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_minor;
+}
+
+unsigned long drmAgpGetMode(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.mode;
+}
+
+unsigned long drmAgpBase(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_base;
+}
+
+unsigned long drmAgpSize(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_size;
+}
+
+unsigned long drmAgpMemoryUsed(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_used;
+}
+
+unsigned long drmAgpMemoryAvail(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_allowed;
+}
+
+unsigned int drmAgpVendorId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_vendor;
+}
+
+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;
+}
+
+int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+{
+ int ret;
+
+ do {
+ ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+ } 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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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)))) {
+ 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/dri-es/xf86drm.h b/src/dri-es/xf86drm.h
new file mode 100644
index 0000000000..6ae17f1ffb
--- /dev/null
+++ b/src/dri-es/xf86drm.h
@@ -0,0 +1,607 @@
+/* xf86drm.h -- OS-independent header for DRM user-level library interface
+ * Created: Tue Jan 5 08:17:23 1999 by faith@precisioninsight.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.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.17 2002/10/16 01:26:48 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 backware 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)
+
+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 auth */
+
+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;
+
+typedef enum { /* These values *MUST* match drm.h */
+ /* 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 */
+} 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 master buflist */
+ int total; /* Buffer size */
+ int used; /* Amount of buffer in use (for DMA) */
+ drmAddress address; /* Address */
+} drmBuf, *drmBufPtr;
+
+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;
+
+typedef struct _drmDMAReq {
+ /* Indices here refer to the offset into
+ list in drmBufInfo */
+ 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;
+
+
+
+#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 __GNUC__ >= 2
+# if defined(__i386) || defined(__x86_64__)
+ /* 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__)
+
+#if 0
+/* this currently generates bad code (missing stop bits)... */
+#include <ia64intrin.h>
+
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ __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" (__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 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/dri-es/xf86drmHash.c b/src/dri-es/xf86drmHash.c
new file mode 100644
index 0000000000..1f1a05b3ac
--- /dev/null
+++ b/src/dri-es/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/dri-es/xf86drmRandom.c b/src/dri-es/xf86drmRandom.c
new file mode 100644
index 0000000000..9e1e9ee2c3
--- /dev/null
+++ b/src/dri-es/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/dri-es/xf86drmSL.c b/src/dri-es/xf86drmSL.c
new file mode 100644
index 0000000000..dd634c30f6
--- /dev/null
+++ b/src/dri-es/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