add missed files for DRI2 merge
authorAlan Hourihane <alanh@tungstengraphics.com>
Wed, 11 Jun 2008 14:25:35 +0000 (15:25 +0100)
committerAlan Hourihane <alanh@tungstengraphics.com>
Wed, 11 Jun 2008 14:25:35 +0000 (15:25 +0100)
include/GL/internal/dri_sarea.h [new file with mode: 0644]
src/glx/x11/dri2.c [new file with mode: 0644]
src/glx/x11/dri2.h [new file with mode: 0644]
src/glx/x11/dri2_glx.c [new file with mode: 0644]
src/glx/x11/dri_common.c [new file with mode: 0644]
src/glx/x11/dri_common.h [new file with mode: 0644]
src/glx/x11/glxcurrent.c [new file with mode: 0644]
src/glx/x11/glxhash.c [new file with mode: 0644]
src/glx/x11/glxhash.h [new file with mode: 0644]
src/glx/x11/indirect_texture_compression.c [new file with mode: 0644]
src/glx/x11/indirect_vertex_array_priv.h [new file with mode: 0644]

diff --git a/include/GL/internal/dri_sarea.h b/include/GL/internal/dri_sarea.h
new file mode 100644 (file)
index 0000000..849161f
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2007 Red Hat, 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DRI_SAREA_H
+#define DRI_SAREA_H
+
+#include <drm.h>
+
+/* The DRI2 SAREA holds a list of self-describing blocks.  Each block
+ * is 8 byte aligned and has a common 32-bit header word.  The upper
+ * 16 bits describe the type of the block and the lower 16 bits the
+ * size.  DRI2 only defines a couple of blocks and allows drivers to
+ * define driver specific blocks using type codes from 0x8000 and up.
+ * The type code 0x0000 defines the end of the sarea. */
+
+#define DRI2_SAREA_BLOCK_HEADER(type, size) (((type) << 16) | (size))
+#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16)
+#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff)
+#define DRI2_SAREA_BLOCK_NEXT(p)                               \
+    ((void *) ((unsigned char *) (p) +                         \
+               DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p)))
+
+#define DRI2_SAREA_BLOCK_END           0x0000
+#define DRI2_SAREA_BLOCK_LOCK          0x0001
+#define DRI2_SAREA_BLOCK_EVENT_BUFFER  0x0002
+
+/* Chipset specific blocks start at 0x8000, 0xffff is reserved. */
+
+typedef struct __DRILock __DRILock;
+typedef struct __DRIEventBuffer __DRIEventBuffer;
+typedef struct __DRIDrawableBuffer __DRIDrawableBuffer;
+typedef struct __DRIDrawableConfigEvent __DRIDrawableConfigEvent;
+typedef struct __DRIBufferAttachEvent __DRIBufferAttachEvent;
+
+struct __DRILock {
+    unsigned int block_header;
+    drm_hw_lock_t lock;
+
+    /* We use this with DRM_CAS to allocate lock IDs for the real lock.*/
+    unsigned int next_id;
+};
+
+struct __DRIEventBuffer {
+    unsigned int block_header;
+    unsigned int head;         /* last valid event */
+    unsigned int prealloc;     /* event currently being written */
+    unsigned int size;         /* size of data */
+    unsigned char data[0];
+};
+
+enum {
+        /* the four standard color buffers */
+        DRI_DRAWABLE_BUFFER_FRONT_LEFT  = 0,
+        DRI_DRAWABLE_BUFFER_BACK_LEFT   = 1,
+        DRI_DRAWABLE_BUFFER_FRONT_RIGHT = 2,
+        DRI_DRAWABLE_BUFFER_BACK_RIGHT  = 3,
+        /* optional aux buffer */
+        DRI_DRAWABLE_BUFFER_AUX0        = 4,
+        DRI_DRAWABLE_BUFFER_AUX1        = 5,
+        DRI_DRAWABLE_BUFFER_AUX2        = 6,
+        DRI_DRAWABLE_BUFFER_AUX3        = 7,
+        DRI_DRAWABLE_BUFFER_DEPTH       = 8,
+        DRI_DRAWABLE_BUFFER_STENCIL     = 9,
+        DRI_DRAWABLE_BUFFER_ACCUM       = 10,
+        /* generic renderbuffers */
+        DRI_DRAWABLE_BUFFER_COLOR0      = 11,
+        DRI_DRAWABLE_BUFFER_COLOR1      = 12,
+        DRI_DRAWABLE_BUFFER_COLOR2      = 13,
+        DRI_DRAWABLE_BUFFER_COLOR3      = 14,
+        DRI_DRAWABLE_BUFFER_COLOR4      = 15,
+        DRI_DRAWABLE_BUFFER_COLOR5      = 16,
+        DRI_DRAWABLE_BUFFER_COLOR6      = 17,
+        DRI_DRAWABLE_BUFFER_COLOR7      = 18,
+        DRI_DRAWABLE_BUFFER_COUNT       = 19
+};
+
+struct __DRIDrawableBuffer {
+    unsigned int attachment;
+    unsigned int handle;
+    unsigned int pitch;
+    unsigned short cpp;
+
+    /* Upper 8 bits are driver specific, lower 8 bits generic.  The
+     * bits can inidicate buffer properties such as tiled, swizzled etc. */
+    unsigned short flags;
+};
+
+#define DRI2_EVENT_HEADER(type, size) (((type) << 16) | (size))
+#define DRI2_EVENT_TYPE(b) ((b) >> 16)
+#define DRI2_EVENT_SIZE(b) ((b) & 0xffff)
+
+#define DRI2_EVENT_PAD                 0x0000
+#define DRI2_EVENT_DRAWABLE_CONFIG     0x0001
+#define DRI2_EVENT_BUFFER_ATTACH       0x0002
+
+struct __DRIDrawableConfigEvent {
+    unsigned int               event_header;
+    unsigned int               drawable;
+    short                      x;
+    short                      y;
+    unsigned int               width;
+    unsigned int               height;
+    unsigned int               num_rects;
+    struct drm_clip_rect       rects[0];
+};
+
+struct __DRIBufferAttachEvent {
+    unsigned int       event_header;
+    unsigned int       drawable;
+    __DRIDrawableBuffer        buffer;
+};
+
+#endif /* DRI_SAREA_H */
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c
new file mode 100644 (file)
index 0000000..e7044ab
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/dri2proto.h>
+#include "glheader.h"
+#include "xf86drm.h"
+#include "dri2.h"
+
+static char dri2ExtensionName[] = DRI2_NAME;
+static XExtensionInfo *dri2Info;
+static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
+static /* const */ XExtensionHooks dri2ExtensionHooks = {
+    NULL,                              /* create_gc */
+    NULL,                              /* copy_gc */
+    NULL,                              /* flush_gc */
+    NULL,                              /* free_gc */
+    NULL,                              /* create_font */
+    NULL,                              /* free_font */
+    DRI2CloseDisplay,                  /* close_display */
+    NULL,                              /* wire_to_event */
+    NULL,                              /* event_to_wire */
+    NULL,                              /* error */
+    NULL,                              /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, 
+                                  dri2ExtensionName, 
+                                  &dri2ExtensionHooks, 
+                                  0, NULL)
+
+Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+
+    if (XextHasExtension(info)) {
+       *eventBase = info->codes->first_event;
+       *errorBase = info->codes->first_error;
+       return True;
+    }
+
+    return False;
+}
+
+Bool DRI2QueryVersion(Display *dpy, int *major, int *minor)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay (dpy);
+    xDRI2QueryVersionReply rep;
+    xDRI2QueryVersionReq *req;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2QueryVersion, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2QueryVersion;
+    req->majorVersion = DRI2_MAJOR;
+    req->minorVersion = DRI2_MINOR;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    *major = rep.majorVersion;
+    *minor = rep.minorVersion;
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+
+Bool DRI2Connect(Display *dpy, int screen,
+                char **driverName, char **busId, unsigned int *sareaHandle)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2ConnectReply rep;
+    xDRI2ConnectReq *req;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2Connect, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2Connect;
+    req->screen = screen;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+
+    *sareaHandle = rep.sareaHandle;
+
+    *driverName = Xmalloc(rep.driverNameLength + 1);
+    if (*driverName == NULL) {
+       _XEatData(dpy, 
+                 ((rep.driverNameLength + 3) & ~3) +
+                 ((rep.busIdLength + 3) & ~3));
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    _XReadPad(dpy, *driverName, rep.driverNameLength);
+    (*driverName)[rep.driverNameLength] = '\0';
+
+    *busId = Xmalloc(rep.busIdLength + 1);
+    if (*busId == NULL) {
+       Xfree(*driverName);
+       _XEatData(dpy, ((rep.busIdLength + 3) & ~3));
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    _XReadPad(dpy, *busId, rep.busIdLength);
+    (*busId)[rep.busIdLength] = '\0';
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return rep.sareaHandle != 0;
+}
+
+Bool DRI2AuthConnection(Display *dpy, int screen, drm_magic_t magic)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2AuthConnectionReq *req;
+    xDRI2AuthConnectionReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2AuthConnection, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2AuthConnection;
+    req->screen = screen;
+    req->magic = magic;
+    rep.authenticated = 0;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return rep.authenticated;
+}
+
+Bool DRI2CreateDrawable(Display *dpy, XID drawable,
+                       unsigned int *handle, unsigned int *head)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2CreateDrawableReply rep;
+    xDRI2CreateDrawableReq *req;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2CreateDrawable, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2CreateDrawable;
+    req->drawable = drawable;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    *handle = rep.handle;
+    *head = rep.head;
+
+    return True;
+}
+
+void DRI2DestroyDrawable(Display *dpy, XID drawable)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2DestroyDrawableReq *req;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    XSync(dpy, GL_FALSE);
+
+    LockDisplay(dpy);
+    GetReq(DRI2DestroyDrawable, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2DestroyDrawable;
+    req->drawable = drawable;
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+
+Bool DRI2ReemitDrawableInfo(Display *dpy, XID drawable, unsigned int *head)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2ReemitDrawableInfoReply rep;
+    xDRI2ReemitDrawableInfoReq *req;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2ReemitDrawableInfo, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2ReemitDrawableInfo;
+    req->drawable = drawable;
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+       UnlockDisplay(dpy);
+       SyncHandle();
+       return False;
+    }
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    *head = rep.head;
+
+    return True;
+}
diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h
new file mode 100644 (file)
index 0000000..1dfd044
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2007,2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI2_H_
+#define _DRI2_H_
+
+extern Bool
+DRI2QueryExtension(Display *display, int *eventBase, int *errorBase);
+extern Bool
+DRI2QueryVersion(Display *display, int *major, int *minor);
+extern Bool
+DRI2Connect(Display *display, int screen,
+           char **driverName, char **busId, unsigned int *sareaHandle);
+extern Bool
+DRI2AuthConnection(Display *display, int screen, drm_magic_t magic);
+extern Bool
+DRI2CreateDrawable(Display *display, XID drawable,
+                  unsigned int *handle, unsigned int *head);
+extern void
+DRI2DestroyDrawable(Display *display, XID handle);
+extern Bool
+DRI2ReemitDrawableInfo(Display *dpy, XID handle, unsigned int *head);
+
+#endif
diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
new file mode 100644 (file)
index 0000000..b679c72
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
+#include "glheader.h"
+#include "glxclient.h"
+#include "glcontextmodes.h"
+#include "xf86dri.h"
+#include "sarea.h"
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "xf86drm.h"
+#include "dri2.h"
+#include "dri_common.h"
+
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
+
+struct __GLXDRIdisplayPrivateRec {
+    __GLXDRIdisplay base;
+
+    /*
+    ** XFree86-DRI version information
+    */
+    int driMajor;
+    int driMinor;
+    int driPatch;
+};
+
+struct __GLXDRIcontextPrivateRec {
+    __GLXDRIcontext base;
+    __DRIcontext *driContext;
+    __GLXscreenConfigs *psc;
+};
+
+static void dri2DestroyContext(__GLXDRIcontext *context,
+                             __GLXscreenConfigs *psc, Display *dpy)
+{
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+    const __DRIcoreExtension *core = pcp->psc->core;
+
+    (*core->destroyContext)(pcp->driContext);
+
+    Xfree(pcp);
+}
+
+static Bool dri2BindContext(__GLXDRIcontext *context,
+                          __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
+{
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+    const __DRIcoreExtension *core = pcp->psc->core;
+
+    return (*core->bindContext)(pcp->driContext,
+                               draw->driDrawable,
+                               read->driDrawable);
+}
+
+static void dri2UnbindContext(__GLXDRIcontext *context)
+{
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+    const __DRIcoreExtension *core = pcp->psc->core;
+
+    (*core->unbindContext)(pcp->driContext);
+}
+
+static __GLXDRIcontext *dri2CreateContext(__GLXscreenConfigs *psc,
+                                        const __GLcontextModes *mode,
+                                        GLXContext gc,
+                                        GLXContext shareList, int renderType)
+{
+    __GLXDRIcontextPrivate *pcp, *pcp_shared;
+    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+    const __DRIcoreExtension *core = psc->core;
+    __DRIcontext *shared = NULL;
+
+    if (shareList) {
+       pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+       shared = pcp_shared->driContext;
+    }
+
+    pcp = Xmalloc(sizeof *pcp);
+    if (pcp == NULL)
+       return NULL;
+
+    pcp->psc = psc;
+    pcp->driContext = 
+       (*core->createNewContext)(psc->__driScreen,
+                                 config->driConfig, shared, pcp);
+    gc->__driContext = pcp->driContext;
+
+    if (pcp->driContext == NULL) {
+       Xfree(pcp);
+       return NULL;
+    }
+
+    pcp->base.destroyContext = dri2DestroyContext;
+    pcp->base.bindContext = dri2BindContext;
+    pcp->base.unbindContext = dri2UnbindContext;
+
+    return &pcp->base;
+}
+
+static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
+{
+    const __DRIcoreExtension *core = pdraw->psc->core;
+
+    (*core->destroyDrawable)(pdraw->driDrawable);
+    DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable);
+    Xfree(pdraw);
+}
+
+static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc,
+                                           XID xDrawable,
+                                           GLXDrawable drawable,
+                                           const __GLcontextModes *modes)
+{
+    __GLXDRIdrawable *pdraw;
+    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+    unsigned int handle, head;
+    const __DRIcoreExtension *core = psc->core;
+
+    pdraw = Xmalloc(sizeof(*pdraw));
+    if (!pdraw)
+       return NULL;
+
+    pdraw->destroyDrawable = dri2DestroyDrawable;
+    pdraw->xDrawable = xDrawable;
+    pdraw->drawable = drawable;
+    pdraw->psc = psc;
+
+    fprintf(stderr, "calling DRI2CreateDrawable, XID 0x%lx, GLX ID 0x%lx\n",
+           xDrawable, drawable);
+
+    if (!DRI2CreateDrawable(psc->dpy, xDrawable, &handle, &head)) {
+       Xfree(pdraw);
+       return NULL;
+    }
+
+    fprintf(stderr, "success, head 0x%x, handle 0x%x\n", head, handle);
+
+    /* Create a new drawable */
+    pdraw->driDrawable =
+       (*core->createNewDrawable)(psc->__driScreen,
+                                  config->driConfig,
+                                  handle,
+                                  head,
+                                  pdraw);
+
+    if (!pdraw->driDrawable) {
+       DRI2DestroyDrawable(psc->dpy, drawable);
+       Xfree(pdraw);
+       return NULL;
+    }
+
+    return pdraw;
+}
+
+static void dri2DestroyScreen(__GLXscreenConfigs *psc)
+{
+    /* Free the direct rendering per screen data */
+    (*psc->core->destroyScreen)(psc->__driScreen);
+    drmClose(psc->fd);
+    psc->__driScreen = NULL;
+}
+
+
+static void dri2ReemitDrawableInfo(__DRIdrawable *draw, unsigned int *tail,
+                                   void *loaderPrivate)
+{
+    __GLXDRIdrawable *pdraw = loaderPrivate;
+
+    DRI2ReemitDrawableInfo(pdraw->psc->dpy, pdraw->drawable, tail);
+}
+
+static void dri2PostDamage(__DRIdrawable *draw,
+                          struct drm_clip_rect *rects,
+                          int numRects, void *loaderPrivate)
+{ 
+    XRectangle *xrects;
+    XserverRegion region;
+    __GLXDRIdrawable *glxDraw = loaderPrivate;
+    __GLXscreenConfigs *psc = glxDraw->psc;
+    Display *dpy = psc->dpy;
+    int i;
+
+    xrects = malloc(sizeof(XRectangle) * numRects);
+    if (xrects == NULL)
+       return;
+
+    for (i = 0; i < numRects; i++) {
+       xrects[i].x = rects[i].x1;
+       xrects[i].y = rects[i].y1;
+       xrects[i].width = rects[i].x2 - rects[i].x1;
+       xrects[i].height = rects[i].y2 - rects[i].y1;
+    }
+    region = XFixesCreateRegion(dpy, xrects, numRects);
+    free(xrects);
+    XDamageAdd(dpy, glxDraw->xDrawable, region);
+    XFixesDestroyRegion(dpy, region);
+}
+
+static const __DRIloaderExtension dri2LoaderExtension = {
+    { __DRI_LOADER, __DRI_LOADER_VERSION },
+    dri2ReemitDrawableInfo,
+    dri2PostDamage
+};
+
+static const __DRIextension *loader_extensions[] = {
+    &dri2LoaderExtension.base,
+    &systemTimeExtension.base,
+    NULL
+};
+
+static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen,
+                                       __GLXdisplayPrivate *priv)
+{
+    const __DRIconfig **driver_configs;
+    const __DRIextension **extensions;
+    __GLXDRIscreen *psp;
+    unsigned int sareaHandle;
+    char *driverName, *busID;
+    drm_magic_t magic;
+    int i;
+
+    psp = Xmalloc(sizeof *psp);
+    if (psp == NULL)
+       return NULL;
+
+    /* Initialize per screen dynamic client GLX extensions */
+    psc->ext_list_first_time = GL_TRUE;
+
+    if (!DRI2Connect(psc->dpy, screen, &driverName, &busID, &sareaHandle))
+       return NULL;
+
+    psc->driver = driOpenDriver(driverName);
+    if (psc->driver == NULL)
+       goto handle_error;
+
+    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+    if (extensions == NULL) {
+       ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+       goto handle_error;
+    }
+    
+    for (i = 0; extensions[i]; i++) {
+       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+           psc->core = (__DRIcoreExtension *) extensions[i];
+    }
+
+    if (psc->core == NULL) {
+       ErrorMessageF("core dri extension not found\n");
+       goto handle_error;
+    }
+
+    psc->fd = drmOpen(NULL, busID);
+    if (psc->fd < 0) {
+       ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
+       return NULL;
+    }
+
+    if (drmGetMagic(psc->fd, &magic))
+       return NULL;
+
+    if (!DRI2AuthConnection(psc->dpy, screen, magic)) {
+       ErrorMessageF("failed to authenticate drm access\n");
+       return NULL;
+    }
+
+    psc->__driScreen = 
+       psc->core->createNewScreen(screen, psc->fd, sareaHandle,
+                                  loader_extensions, &driver_configs, psc);
+    if (psc->__driScreen == NULL) {
+       ErrorMessageF("failed to create dri screen\n");
+       return NULL;
+    }
+
+    driBindExtensions(psc);
+
+    psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+    psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+    psp->destroyScreen = dri2DestroyScreen;
+    psp->createContext = dri2CreateContext;
+    psp->createDrawable = dri2CreateDrawable;
+
+    Xfree(driverName);
+    Xfree(busID);
+
+    return psp;
+
+ handle_error:
+    Xfree(driverName);
+    Xfree(busID);
+
+    /* FIXME: clean up here */
+
+    return NULL;
+}
+
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void dri2DestroyDisplay(__GLXDRIdisplay *dpy)
+{
+    Xfree(dpy);
+}
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+_X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
+{
+    __GLXDRIdisplayPrivate *pdp;
+    int eventBase, errorBase;
+
+    if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
+       return NULL;
+
+    pdp = Xmalloc(sizeof *pdp);
+    if (pdp == NULL)
+       return NULL;
+
+    if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
+       Xfree(pdp);
+       return NULL;
+    }
+
+    pdp->driPatch = 0;
+
+    pdp->base.destroyDisplay = dri2DestroyDisplay;
+    pdp->base.createScreen = dri2CreateScreen;
+
+    return &pdp->base;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c
new file mode 100644 (file)
index 0000000..b159d19
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <unistd.h>
+#include <dlfcn.h>
+#include "glheader.h"
+#include "glxclient.h"
+#include "glcontextmodes.h"
+#include "dri_common.h"
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+_X_HIDDEN void InfoMessageF(const char *f, ...)
+{
+    va_list args;
+    const char *env;
+
+    if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
+       fprintf(stderr, "libGL: ");
+       va_start(args, f);
+       vfprintf(stderr, f, args);
+       va_end(args);
+    }
+}
+
+/**
+ * Print error to stderr, unless LIBGL_DEBUG=="quiet".
+ */
+_X_HIDDEN void ErrorMessageF(const char *f, ...)
+{
+    va_list args;
+    const char *env;
+
+    if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
+       fprintf(stderr, "libGL error: ");
+       va_start(args, f);
+       vfprintf(stderr, f, args);
+       va_end(args);
+    }
+}
+
+#ifndef DEFAULT_DRIVER_DIR
+/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
+#define DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
+#endif
+
+/**
+ * Try to \c dlopen the named driver.
+ *
+ * This function adds the "_dri.so" suffix to the driver name and searches the
+ * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
+ * order to find the driver.
+ *
+ * \param driverName - a name like "tdfx", "i810", "mga", etc.
+ *
+ * \returns
+ * A handle from \c dlopen, or \c NULL if driver file not found.
+ */
+_X_HIDDEN void *driOpenDriver(const char *driverName)
+{
+   void *glhandle, *handle;
+   const char *libPaths, *p, *next;
+   char realDriverName[200];
+   int len;
+
+   /* Attempt to make sure libGL symbols will be visible to the driver */
+   glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
+
+   libPaths = NULL;
+   if (geteuid() == getuid()) {
+      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
+      libPaths = getenv("LIBGL_DRIVERS_PATH");
+      if (!libPaths)
+         libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
+   }
+   if (libPaths == NULL)
+       libPaths = DEFAULT_DRIVER_DIR;
+
+   handle = NULL;
+   for (p = libPaths; *p; p = next) {
+       next = strchr(p, ':');
+       if (next == NULL) {
+          len = strlen(p);
+          next = p + len;
+       } else {
+          len = next - p;
+          next++;
+       }
+
+#ifdef GLX_USE_TLS
+      snprintf(realDriverName, sizeof realDriverName,
+              "%.*s/tls/%s_dri.so", len, p, driverName);
+      InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+      handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+#endif
+
+      if ( handle == NULL ) {
+        snprintf(realDriverName, sizeof realDriverName,
+                 "%.*s/%s_dri.so", len, p, driverName);
+        InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+        handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+      }
+
+      if ( handle != NULL )
+         break;
+      else
+        ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
+   }
+
+   if (!handle)
+      ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);
+
+   if (glhandle)
+      dlclose(glhandle);
+
+   return handle;
+}
+
+_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = {
+    { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
+    __glXGetUST,
+    __driGetMscRateOML
+};
+
+#define __ATTRIB(attrib, field) \
+    { attrib, offsetof(__GLcontextModes, field) }
+
+static const struct { unsigned int attrib, offset; } attribMap[] = {
+    __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE,                 rgbBits),
+    __ATTRIB(__DRI_ATTRIB_LEVEL,                       level),
+    __ATTRIB(__DRI_ATTRIB_RED_SIZE,                    redBits),
+    __ATTRIB(__DRI_ATTRIB_GREEN_SIZE,                  greenBits),
+    __ATTRIB(__DRI_ATTRIB_BLUE_SIZE,                   blueBits),
+    __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE,                  alphaBits),
+    __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE,                  depthBits),
+    __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE,                        stencilBits),
+    __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE,              accumRedBits),
+    __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE,            accumGreenBits),
+    __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE,             accumBlueBits),
+    __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE,            accumAlphaBits),
+    __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS,              sampleBuffers),
+    __ATTRIB(__DRI_ATTRIB_SAMPLES,                     samples),
+    __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER,               doubleBufferMode),
+    __ATTRIB(__DRI_ATTRIB_STEREO,                      stereoMode),
+    __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS,                 numAuxBuffers),
+#if 0
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE,            transparentPixel),
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE,     transparentIndex),
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE,       transparentRed),
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE,     transparentGreen),
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,      transparentBlue),
+    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,     transparentAlpha),
+    __ATTRIB(__DRI_ATTRIB_RED_MASK,                    redMask),
+    __ATTRIB(__DRI_ATTRIB_GREEN_MASK,                  greenMask),
+    __ATTRIB(__DRI_ATTRIB_BLUE_MASK,                   blueMask),
+    __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,                  alphaMask),
+#endif
+    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,           maxPbufferWidth),
+    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,          maxPbufferHeight),
+    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,          maxPbufferPixels),
+    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH,       optimalPbufferWidth),
+    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT,      optimalPbufferHeight),
+#if 0
+    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,                 swapMethod),
+#endif
+    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB,         bindToTextureRgb),
+    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA,                bindToTextureRgba),
+    __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,      bindToMipmapTexture),
+    __ATTRIB(__DRI_ATTRIB_YINVERTED,                   yInverted),
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+static int
+scalarEqual(__GLcontextModes *mode, unsigned int attrib, unsigned int value)
+{
+    unsigned int glxValue;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(attribMap); i++)
+       if (attribMap[i].attrib == attrib) {
+           glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
+           return glxValue == GLX_DONT_CARE || glxValue == value;
+       }
+
+    return GL_TRUE; /* Is a non-existing attribute equal to value? */
+}
+
+static int
+driConfigEqual(const __DRIcoreExtension *core,
+              __GLcontextModes *modes, const __DRIconfig *driConfig)
+{
+    unsigned int attrib, value, glxValue;
+    int i;
+
+    i = 0;
+    while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
+       switch (attrib) {
+       case __DRI_ATTRIB_RENDER_TYPE:
+           glxValue = 0;
+           if (value & __DRI_ATTRIB_RGBA_BIT) {
+               glxValue |= GLX_RGBA_BIT;
+           } else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
+               glxValue |= GLX_COLOR_INDEX_BIT;
+           }
+           if (glxValue != modes->renderType)
+               return GL_FALSE;
+           break;
+
+       case __DRI_ATTRIB_CONFIG_CAVEAT:
+           if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+               glxValue = GLX_NON_CONFORMANT_CONFIG;
+           else if (value & __DRI_ATTRIB_SLOW_BIT)
+               glxValue = GLX_SLOW_CONFIG;
+           else
+               glxValue = GLX_NONE;
+           if (glxValue != modes->visualRating)
+               return GL_FALSE;
+           break;
+
+       case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
+           glxValue = 0;
+           if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
+               glxValue |= GLX_TEXTURE_1D_BIT_EXT;
+           if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
+               glxValue |= GLX_TEXTURE_2D_BIT_EXT;
+           if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
+               glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
+           if (modes->bindToTextureTargets != GLX_DONT_CARE &&
+               glxValue != modes->bindToTextureTargets)
+               return GL_FALSE;
+           break;      
+
+       default:
+           if (!scalarEqual(modes, attrib, value))
+               return GL_FALSE;
+       }
+    }
+
+    return GL_TRUE;
+}
+
+static __GLcontextModes *
+createDriMode(const __DRIcoreExtension *core,
+             __GLcontextModes *modes, const __DRIconfig **driConfigs)
+{
+    __GLXDRIconfigPrivate *config;
+    int i;
+
+    for (i = 0; driConfigs[i]; i++) {
+       if (driConfigEqual(core, modes, driConfigs[i]))
+           break;
+    }
+
+    if (driConfigs[i] == NULL)
+       return NULL;
+
+    config = Xmalloc(sizeof *config);
+    if (config == NULL)
+       return NULL;
+
+    config->modes = *modes;
+    config->driConfig = driConfigs[i];
+
+    return &config->modes;
+}
+
+_X_HIDDEN __GLcontextModes *
+driConvertConfigs(const __DRIcoreExtension *core,
+                 __GLcontextModes *modes, const __DRIconfig **configs)
+{
+    __GLcontextModes head, *tail, *m;
+
+    tail = &head;
+    head.next = NULL;
+    for (m = modes; m; m = m->next) {
+       tail->next = createDriMode(core, m, configs);
+       if (tail->next == NULL) {
+           /* no matching dri config for m */
+           continue;
+       }
+
+
+       tail = tail->next;
+    }
+
+    _gl_context_modes_destroy(modes);
+
+    return head.next;
+}
+
+_X_HIDDEN void
+driBindExtensions(__GLXscreenConfigs *psc)
+{
+    const __DRIextension **extensions;
+    int i;
+
+    extensions = psc->core->getExtensions(psc->__driScreen);
+
+    for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_COPY_SUB_BUFFER
+       if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
+           psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer_bit");
+       }
+#endif
+
+#ifdef __DRI_SWAP_CONTROL
+       if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
+           psc->swapControl = (__DRIswapControlExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
+           __glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
+       }
+#endif
+
+#ifdef __DRI_ALLOCATE
+       if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) {
+           psc->allocate = (__DRIallocateExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory");
+       }
+#endif
+
+#ifdef __DRI_FRAME_TRACKING
+       if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) {
+           psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage");
+       }
+#endif
+
+#ifdef __DRI_MEDIA_STREAM_COUNTER
+       if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
+           psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
+       }
+#endif
+
+#ifdef __DRI_SWAP_BUFFER_COUNTER
+       /* No driver supports this at this time and the extension is
+        * not defined in dri_interface.h.  Will enable
+        * GLX_OML_sync_control if implemented. */
+#endif
+
+#ifdef __DRI_READ_DRAWABLE
+       if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+           __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read");
+       }
+#endif
+
+#ifdef __DRI_TEX_BUFFER
+       if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
+           psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
+           __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap");
+       }
+#endif
+
+       /* Ignore unknown extensions */
+    }
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/dri_common.h b/src/glx/x11/dri_common.h
new file mode 100644 (file)
index 0000000..3556510
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kevin E. Martin <kevin@precisioninsight.com>
+ *   Brian Paul <brian@precisioninsight.com>
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI_COMMON_H
+#define _DRI_COMMON_H
+
+typedef struct __GLXDRIconfigPrivateRec  __GLXDRIconfigPrivate;
+
+struct __GLXDRIconfigPrivateRec {
+    __GLcontextModes modes;
+    const __DRIconfig *driConfig;
+};
+
+extern __GLcontextModes *
+driConvertConfigs(const __DRIcoreExtension *core,
+                 __GLcontextModes *modes, const __DRIconfig **configs);
+
+extern const __DRIsystemTimeExtension systemTimeExtension;
+
+extern void InfoMessageF(const char *f, ...);
+
+extern void ErrorMessageF(const char *f, ...);
+
+extern void *driOpenDriver(const char *driverName);
+
+extern void driBindExtensions(__GLXscreenConfigs *psc);
+
+#endif /* _DRI_COMMON_H */
diff --git a/src/glx/x11/glxcurrent.c b/src/glx/x11/glxcurrent.c
new file mode 100644 (file)
index 0000000..ad648fd
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+** 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.
+**
+*/
+
+/**
+ * \file glxcurrent.c
+ * Client-side GLX interface for current context management.
+ */
+
+#include "glxclient.h"
+#include "glapi.h"
+#include "glheader.h"
+#include "indirect_init.h"
+
+#ifdef GLX_DIRECT_RENDERING
+#include "xf86dri.h"
+#endif
+
+/*
+** We setup some dummy structures here so that the API can be used
+** even if no context is current.
+*/
+
+static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
+
+/*
+** Dummy context used by small commands when there is no current context.
+** All the
+** gl and glx entry points are designed to operate as nop's when using
+** the dummy context structure.
+*/
+static __GLXcontext dummyContext = {
+    &dummyBuffer[0],
+    &dummyBuffer[0],
+    &dummyBuffer[0],
+    &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
+    sizeof(dummyBuffer),
+};
+
+
+/*
+** All indirect rendering contexts will share the same indirect dispatch table.
+*/
+static __GLapi *IndirectAPI = NULL;
+
+
+/*
+ * Current context management and locking
+ */
+
+#if defined( USE_XTHREADS )
+
+/* thread safe */
+static GLboolean TSDinitialized = GL_FALSE;
+static xthread_key_t ContextTSD;
+
+_X_HIDDEN __GLXcontext *__glXGetCurrentContext(void)
+{
+   if (!TSDinitialized) {
+      xthread_key_create(&ContextTSD, NULL);
+      TSDinitialized = GL_TRUE;
+      return &dummyContext;
+   }
+   else {
+      void *p;
+      xthread_get_specific(ContextTSD, &p);
+      if (!p)
+         return &dummyContext;
+      else
+         return (__GLXcontext *) p;
+   }
+}
+
+_X_HIDDEN void __glXSetCurrentContext(__GLXcontext *c)
+{
+   if (!TSDinitialized) {
+      xthread_key_create(&ContextTSD, NULL);
+      TSDinitialized = GL_TRUE;
+   }
+   xthread_set_specific(ContextTSD, c);
+}
+
+
+/* Used by the __glXLock() and __glXUnlock() macros */
+_X_HIDDEN xmutex_rec __glXmutex;
+
+#elif defined( PTHREADS )
+
+_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
+
+# if defined( GLX_USE_TLS )
+
+/**
+ * Per-thread GLX context pointer.
+ * 
+ * \c __glXSetCurrentContext is written is such a way that this pointer can
+ * \b never be \c NULL.  This is important!  Because of this
+ * \c __glXGetCurrentContext can be implemented as trivial macro.
+ */
+__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
+    = &dummyContext;
+
+_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
+{
+    __glX_tls_Context = (c != NULL) ? c : &dummyContext;
+}
+
+# else
+
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+/**
+ * Per-thread data key.
+ * 
+ * Once \c init_thread_data has been called, the per-thread data key will
+ * take a value of \c NULL.  As each new thread is created the default
+ * value, in that thread, will be \c NULL.
+ */
+static pthread_key_t ContextTSD;
+
+/**
+ * Initialize the per-thread data key.
+ * 
+ * This function is called \b exactly once per-process (not per-thread!) to
+ * initialize the per-thread data key.  This is ideally done using the
+ * \c pthread_once mechanism.
+ */
+static void init_thread_data( void )
+{
+    if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
+       perror( "pthread_key_create" );
+       exit( -1 );
+    }
+}
+
+_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c )
+{
+    pthread_once( & once_control, init_thread_data );
+    pthread_setspecific( ContextTSD, c );
+}
+
+_X_HIDDEN __GLXcontext * __glXGetCurrentContext( void )
+{
+    void * v;
+
+    pthread_once( & once_control, init_thread_data );
+
+    v = pthread_getspecific( ContextTSD );
+    return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
+}
+
+# endif /* defined( GLX_USE_TLS ) */
+
+#elif defined( THREADS )
+
+#error Unknown threading method specified.
+
+#else
+
+/* not thread safe */
+_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext;
+
+#endif
+
+
+_X_HIDDEN void __glXSetCurrentContextNull(void)
+{
+    __glXSetCurrentContext(&dummyContext);
+#ifdef GLX_DIRECT_RENDERING
+    _glapi_set_dispatch(NULL);  /* no-op functions */
+#endif
+}
+
+
+/************************************************************************/
+
+PUBLIC GLXContext glXGetCurrentContext(void)
+{
+    GLXContext cx = __glXGetCurrentContext();
+    
+    if (cx == &dummyContext) {
+       return NULL;
+    } else {
+       return cx;
+    }
+}
+
+PUBLIC GLXDrawable glXGetCurrentDrawable(void)
+{
+    GLXContext gc = __glXGetCurrentContext();
+    return gc->currentDrawable;
+}
+
+
+/************************************************************************/
+
+/**
+ * Sends a GLX protocol message to the specified display to make the context
+ * and the drawables current.
+ *
+ * \param dpy     Display to send the message to.
+ * \param opcode  Major opcode value for the display.
+ * \param gc_id   Context tag for the context to be made current.
+ * \param draw    Drawable ID for the "draw" drawable.
+ * \param read    Drawable ID for the "read" drawable.
+ * \param reply   Space to store the X-server's reply.
+ *
+ * \warning
+ * This function assumes that \c dpy is locked with \c LockDisplay on entry.
+ */
+static Bool SendMakeCurrentRequest(Display *dpy, CARD8 opcode,
+                                  GLXContextID gc_id, GLXContextTag gc_tag,
+                                  GLXDrawable draw, GLXDrawable read,
+                                  xGLXMakeCurrentReply *reply)
+{
+    Bool ret;
+
+
+    LockDisplay(dpy);
+
+    if (draw == read) {
+       xGLXMakeCurrentReq *req;
+
+       GetReq(GLXMakeCurrent,req);
+       req->reqType = opcode;
+       req->glxCode = X_GLXMakeCurrent;
+       req->drawable = draw;
+       req->context = gc_id;
+       req->oldContextTag = gc_tag;
+    }
+    else {
+       __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+
+       /* If the server can support the GLX 1.3 version, we should
+        * perfer that.  Not only that, some servers support GLX 1.3 but
+        * not the SGI extension.
+        */
+
+       if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+           xGLXMakeContextCurrentReq *req;
+
+           GetReq(GLXMakeContextCurrent,req);
+           req->reqType = opcode;
+           req->glxCode = X_GLXMakeContextCurrent;
+           req->drawable = draw;
+           req->readdrawable = read;
+           req->context = gc_id;
+           req->oldContextTag = gc_tag;
+       }
+       else {
+           xGLXVendorPrivateWithReplyReq *vpreq;
+           xGLXMakeCurrentReadSGIReq *req;
+
+           GetReqExtra(GLXVendorPrivateWithReply,
+                       sz_xGLXMakeCurrentReadSGIReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
+           req = (xGLXMakeCurrentReadSGIReq *)vpreq;
+           req->reqType = opcode;
+           req->glxCode = X_GLXVendorPrivateWithReply;
+           req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
+           req->drawable = draw;
+           req->readable = read;
+           req->context = gc_id;
+           req->oldContextTag = gc_tag;
+       }
+    }
+
+    ret = _XReply(dpy, (xReply*) reply, 0, False);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return ret;
+}
+
+
+#ifdef GLX_DIRECT_RENDERING
+static __GLXDRIdrawable *
+FetchDRIDrawable(Display *dpy,
+                GLXDrawable glxDrawable, GLXContext gc, Bool pre13)
+{
+    __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
+    __GLXDRIdrawable *pdraw;
+    __GLXscreenConfigs *psc;
+    XID drawable;
+
+    if (priv == NULL)
+       return NULL;
+    
+    psc = &priv->screenConfigs[gc->screen];
+    if (psc->drawHash == NULL)
+       return NULL;
+
+    if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0)
+       return pdraw;
+
+    /* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the
+     * GLX drawable on the fly.  Otherwise we pass None as the X
+     * drawable */
+    if (pre13)
+       drawable = glxDrawable;
+    else
+       drawable = None;
+
+    pdraw = psc->driScreen->createDrawable(psc, drawable,
+                                          glxDrawable, gc->mode);
+    if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) {
+       (*pdraw->destroyDrawable)(pdraw);
+       return NULL;
+    }
+
+    return pdraw;
+}
+#endif /* GLX_DIRECT_RENDERING */
+
+
+/**
+ * Make a particular context current.
+ * 
+ * \note This is in this file so that it can access dummyContext.
+ */
+static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
+                              GLXDrawable read, GLXContext gc,
+                              Bool pre13)
+{
+    xGLXMakeCurrentReply reply;
+    const GLXContext oldGC = __glXGetCurrentContext();
+    const CARD8 opcode = __glXSetupForCommand(dpy);
+    const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext))
+      ? opcode : __glXSetupForCommand(oldGC->currentDpy);
+    Bool bindReturnValue;
+
+
+    if (!opcode || !oldOpcode) {
+       return GL_FALSE;
+    }
+
+    /* Make sure that the new context has a nonzero ID.  In the request,
+     * a zero context ID is used only to mean that we bind to no current
+     * context.
+     */
+    if ((gc != NULL) && (gc->xid == None)) {
+       return GL_FALSE;
+    }
+
+    _glapi_check_multithread();
+
+#ifdef GLX_DIRECT_RENDERING
+    /* Bind the direct rendering context to the drawable */
+    if (gc && gc->driContext) {
+       __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13);
+       __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13);
+
+       bindReturnValue =
+           (gc->driContext->bindContext) (gc->driContext, pdraw, pread);
+    } else
+#endif
+    {
+       /* Send a glXMakeCurrent request to bind the new context. */
+       bindReturnValue = 
+         SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None,
+                                ((dpy != oldGC->currentDpy) || oldGC->isDirect)
+                                ? None : oldGC->currentContextTag,
+                                draw, read, &reply);
+    }
+
+
+    if (!bindReturnValue) {
+       return False;
+    }
+
+    if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) &&
+       !oldGC->isDirect && oldGC != &dummyContext) {
+       xGLXMakeCurrentReply dummy_reply;
+
+       /* We are either switching from one dpy to another and have to
+        * send a request to the previous dpy to unbind the previous
+        * context, or we are switching away from a indirect context to
+        * a direct context and have to send a request to the dpy to
+        * unbind the previous context.
+        */
+       (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None,
+                                     oldGC->currentContextTag, None, None,
+                                     & dummy_reply);
+    }
+#ifdef GLX_DIRECT_RENDERING
+    else if (oldGC->driContext) {
+       oldGC->driContext->unbindContext(oldGC->driContext);
+    }
+#endif
+
+
+    /* Update our notion of what is current */
+    __glXLock();
+    if (gc == oldGC) {
+       /* Even though the contexts are the same the drawable might have
+        * changed.  Note that gc cannot be the dummy, and that oldGC
+        * cannot be NULL, therefore if they are the same, gc is not
+        * NULL and not the dummy.
+        */
+       gc->currentDrawable = draw;
+       gc->currentReadable = read;
+    } else {
+       if (oldGC != &dummyContext) {
+           /* Old current context is no longer current to anybody */
+           oldGC->currentDpy = 0;
+           oldGC->currentDrawable = None;
+           oldGC->currentReadable = None;
+           oldGC->currentContextTag = 0;
+
+           if (oldGC->xid == None) {
+               /* We are switching away from a context that was
+                * previously destroyed, so we need to free the memory
+                * for the old handle.
+                */
+#ifdef GLX_DIRECT_RENDERING
+               /* Destroy the old direct rendering context */
+               if (oldGC->driContext) {
+                   oldGC->driContext->destroyContext(oldGC->driContext,
+                                                     oldGC->psc,
+                                                     oldGC->createDpy);
+                   oldGC->driContext = NULL;
+               }
+#endif
+               __glXFreeContext(oldGC);
+           }
+       }
+       if (gc) {
+           __glXSetCurrentContext(gc);
+
+           gc->currentDpy = dpy;
+           gc->currentDrawable = draw;
+           gc->currentReadable = read;
+
+            if (!gc->driContext) {
+               if (!IndirectAPI)
+                  IndirectAPI = __glXNewIndirectAPI();
+               _glapi_set_dispatch(IndirectAPI);
+
+#ifdef GLX_USE_APPLEGL
+               do {
+                   extern void XAppleDRIUseIndirectDispatch(void);
+                   XAppleDRIUseIndirectDispatch();
+               } while (0);
+#endif
+
+               __GLXattribute *state = 
+                 (__GLXattribute *)(gc->client_state_private);
+
+               gc->currentContextTag = reply.contextTag;
+               if (state->array_state == NULL) {
+                   (void) glGetString(GL_EXTENSIONS);
+                   (void) glGetString(GL_VERSION);
+                   __glXInitVertexArrayState(gc);
+               }
+           }
+           else {
+               gc->currentContextTag = -1;
+           }
+       } else {
+           __glXSetCurrentContextNull();
+       }
+    }
+    __glXUnlock();
+    return GL_TRUE;
+}
+
+
+PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc)
+{
+    return MakeContextCurrent(dpy, draw, draw, gc, True);
+}
+
+PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
+         (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
+         (dpy, d, r, ctx, False), MakeContextCurrent)
+
+PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent,
+         (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
+         (dpy, d, r, ctx, False), MakeContextCurrent)
diff --git a/src/glx/x11/glxhash.c b/src/glx/x11/glxhash.c
new file mode 100644 (file)
index 0000000..9ed0429
--- /dev/null
@@ -0,0 +1,416 @@
+/* glxhash.c -- Small hash table support for integer -> integer mapping
+ * Taken from libdrm.
+ *
+ * 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>
+ *
+ * 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.
+ *
+ */
+
+#include "glxhash.h"
+#include <X11/Xfuncproto.h>
+
+#define HASH_MAIN 0
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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! */
+
+#define HASH_ALLOC malloc
+#define HASH_FREE  free
+#define HASH_RANDOM_DECL
+#define HASH_RANDOM_INIT(seed)  srandom(seed)
+#define HASH_RANDOM             random()
+#define HASH_RANDOM_DESTROY
+
+typedef struct __glxHashBucket {
+    unsigned long     key;
+    void              *value;
+    struct __glxHashBucket *next;
+} __glxHashBucket, *__glxHashBucketPtr;
+
+typedef struct __glxHashTable *__glxHashTablePtr;
+struct __glxHashTable {
+    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 */
+    __glxHashBucketPtr    buckets[HASH_SIZE];
+    int              p0;
+    __glxHashBucketPtr    p1;
+};
+
+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;
+       HASH_RANDOM_DESTROY;
+       ++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;
+}
+
+_X_HIDDEN __glxHashTable *__glxHashCreate(void)
+{
+    __glxHashTablePtr 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;
+}
+
+_X_HIDDEN int __glxHashDestroy(__glxHashTable *t)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+    __glxHashBucketPtr bucket;
+    __glxHashBucketPtr 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 __glxHashBucketPtr HashFind(__glxHashTablePtr table,
+                             unsigned long key, unsigned long *h)
+{
+    unsigned long hash = HashHash(key);
+    __glxHashBucketPtr prev = NULL;
+    __glxHashBucketPtr 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;
+}
+
+_X_HIDDEN int __glxHashLookup(__glxHashTable *t,
+                             unsigned long key, void **value)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+    __glxHashBucketPtr 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 */
+}
+
+_X_HIDDEN int __glxHashInsert(__glxHashTable *t,
+                             unsigned long key, void *value)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+    __glxHashBucketPtr 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 */
+}
+
+_X_HIDDEN int __glxHashDelete(__glxHashTable *t, unsigned long key)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+    unsigned long hash;
+    __glxHashBucketPtr 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;
+}
+
+_X_HIDDEN int __glxHashNext(__glxHashTable *t,
+                           unsigned long *key, void **value)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+
+    while (table->p0 < HASH_SIZE) {
+       if (table->p1) {
+           *key       = table->p1->key;
+           *value     = table->p1->value;
+           table->p1  = table->p1->next;
+           return 1;
+       }
+       table->p1 = table->buckets[table->p0];
+       ++table->p0;
+    }
+    return 0;
+}
+
+_X_HIDDEN int __glxHashFirst(__glxHashTable *t,
+                            unsigned long *key, void **value)
+{
+    __glxHashTablePtr  table = (__glxHashTablePtr)t;
+
+    if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+    table->p0 = 0;
+    table->p1 = table->buckets[0];
+    return __glxHashNext(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(__glxHashBucketPtr 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(__glxHashTablePtr table)
+{
+    int           i;
+    __glxHashBucketPtr 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(__glxHashTablePtr table,
+                       unsigned long key, unsigned long value)
+{
+    unsigned long retval  = 0;
+    int           retcode = __glxHashLookup(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)
+{
+    __glxHashTablePtr table;
+    int          i;
+
+    printf("\n***** 256 consecutive integers ****\n");
+    table = __glxHashCreate();
+    for (i = 0; i < 256; i++) __glxHashInsert(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);
+    __glxHashDestroy(table);
+
+    printf("\n***** 1024 consecutive integers ****\n");
+    table = __glxHashCreate();
+    for (i = 0; i < 1024; i++) __glxHashInsert(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);
+    __glxHashDestroy(table);
+
+    printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
+    table = __glxHashCreate();
+    for (i = 0; i < 1024; i++) __glxHashInsert(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);
+    __glxHashDestroy(table);
+
+    printf("\n***** 1024 random integers ****\n");
+    table = __glxHashCreate();
+    srandom(0xbeefbeef);
+    for (i = 0; i < 1024; i++) __glxHashInsert(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);
+    __glxHashDestroy(table);
+
+    printf("\n***** 5000 random integers ****\n");
+    table = __glxHashCreate();
+    srandom(0xbeefbeef);
+    for (i = 0; i < 5000; i++) __glxHashInsert(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);
+    __glxHashDestroy(table);
+
+    return 0;
+}
+#endif
diff --git a/src/glx/x11/glxhash.h b/src/glx/x11/glxhash.h
new file mode 100644 (file)
index 0000000..66012fb
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _GLX_HASH_H_
+#define _GLX_HASH_H_
+
+
+typedef struct __glxHashTable __glxHashTable;
+
+/* Hash table routines */
+extern __glxHashTable *__glxHashCreate(void);
+extern int  __glxHashDestroy(__glxHashTable *t);
+extern int  __glxHashLookup(__glxHashTable *t, unsigned long key, void **value);
+extern int  __glxHashInsert(__glxHashTable *t, unsigned long key, void *value);
+extern int  __glxHashDelete(__glxHashTable *t, unsigned long key);
+extern int  __glxHashFirst(__glxHashTable *t, unsigned long *key, void **value);
+extern int  __glxHashNext(__glxHashTable *t, unsigned long *key, void **value);
+
+#endif /* _GLX_HASH_H_ */
diff --git a/src/glx/x11/indirect_texture_compression.c b/src/glx/x11/indirect_texture_compression.c
new file mode 100644 (file)
index 0000000..5676858
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glx_texture_compression.c
+ * Contains the routines required to implement GLX protocol for
+ * ARB_texture_compression and related extensions.
+ *
+ * \sa http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_compression.txt
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "packrender.h"
+#include "packsingle.h"
+#include "indirect.h"
+
+#include <assert.h>
+
+
+void
+__indirect_glGetCompressedTexImageARB( GLenum target, GLint level, 
+                                   GLvoid * img )
+{
+    __GLX_SINGLE_DECLARE_VARIABLES();
+    xGLXGetTexImageReply reply;
+    size_t image_bytes;
+
+    __GLX_SINGLE_LOAD_VARIABLES();
+    __GLX_SINGLE_BEGIN( X_GLsop_GetCompressedTexImage, 8 );
+    __GLX_SINGLE_PUT_LONG( 0, target );
+    __GLX_SINGLE_PUT_LONG( 4, level );
+    __GLX_SINGLE_READ_XREPLY();
+
+    image_bytes = reply.width;
+    assert( image_bytes <= ((4 * reply.length) - 0) );
+    assert( image_bytes >= ((4 * reply.length) - 3) );
+    
+    if ( image_bytes != 0 ) {
+       _XRead( dpy, (char *) img, image_bytes );
+       if ( image_bytes < (4 * reply.length) ) {
+           _XEatData( dpy, (4 * reply.length) - image_bytes );
+       }
+    }
+
+    __GLX_SINGLE_END();
+}
+
+
+/**
+ * Internal function used for \c glCompressedTexImage1D and
+ * \c glCompressedTexImage2D.
+ */
+static void
+CompressedTexImage1D2D( GLenum target, GLint level,
+                       GLenum internal_format, 
+                       GLsizei width, GLsizei height,
+                       GLint border, GLsizei image_size,
+                       const GLvoid *data, CARD32 rop )
+{
+    __GLX_DECLARE_VARIABLES();
+
+    __GLX_LOAD_VARIABLES();
+    if ( gc->currentDpy == NULL ) {
+       return;
+    }
+
+    if ( (target == GL_PROXY_TEXTURE_1D)
+        || (target == GL_PROXY_TEXTURE_2D)
+        || (target == GL_PROXY_TEXTURE_CUBE_MAP) ) {
+       compsize = 0;
+    }
+    else {
+       compsize = image_size;
+    }
+
+    cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE 
+                       + compsize );
+    if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+       __GLX_BEGIN_VARIABLE( rop, cmdlen );
+       __GLX_PUT_LONG( 4, target );
+       __GLX_PUT_LONG( 8, level );
+       __GLX_PUT_LONG( 12, internal_format );
+       __GLX_PUT_LONG( 16, width );
+       __GLX_PUT_LONG( 20, height );
+       __GLX_PUT_LONG( 24, border );
+       __GLX_PUT_LONG( 28, image_size );
+       if ( compsize != 0 ) {
+           __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE,
+                                 data, image_size );
+       }
+       __GLX_END( cmdlen );
+    }
+    else {
+       assert( compsize != 0 );
+
+       __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
+       __GLX_PUT_LONG( 8, target );
+       __GLX_PUT_LONG( 12, level );
+       __GLX_PUT_LONG( 16, internal_format );
+       __GLX_PUT_LONG( 20, width );
+       __GLX_PUT_LONG( 24, height );
+       __GLX_PUT_LONG( 28, border );
+       __GLX_PUT_LONG( 32, image_size );
+       __glXSendLargeCommand( gc, gc->pc,
+                              __GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + 4,
+                              data, image_size );
+    }
+}
+
+
+/**
+ * Internal function used for \c glCompressedTexSubImage1D and
+ * \c glCompressedTexSubImage2D.
+ */
+static void
+CompressedTexSubImage1D2D( GLenum target, GLint level,
+                          GLsizei xoffset, GLsizei yoffset,
+                          GLsizei width, GLsizei height,
+                          GLenum format, GLsizei image_size,
+                          const GLvoid *data, CARD32 rop )
+{
+    __GLX_DECLARE_VARIABLES();
+
+    __GLX_LOAD_VARIABLES();
+    if ( gc->currentDpy == NULL ) {
+       return;
+    }
+
+    if ( target == GL_PROXY_TEXTURE_3D ) {
+       compsize = 0;
+    }
+    else {
+       compsize = image_size;
+    }
+
+    cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE
+                       + compsize );
+    if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+       __GLX_BEGIN_VARIABLE( rop, cmdlen );
+       __GLX_PUT_LONG( 4, target );
+       __GLX_PUT_LONG( 8, level );
+       __GLX_PUT_LONG( 12, xoffset );
+       __GLX_PUT_LONG( 16, yoffset );
+       __GLX_PUT_LONG( 20, width );
+       __GLX_PUT_LONG( 24, height );
+       __GLX_PUT_LONG( 28, format );
+       __GLX_PUT_LONG( 32, image_size );
+       if ( compsize != 0 ) {
+           __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE, 
+                                 data, image_size );
+       }
+       __GLX_END( cmdlen );
+    }
+    else {
+       assert( compsize != 0 );
+
+       __GLX_BEGIN_VARIABLE_LARGE( rop, cmdlen + 4 );
+       __GLX_PUT_LONG( 8, target );
+       __GLX_PUT_LONG( 12, level );
+       __GLX_PUT_LONG( 16, xoffset );
+       __GLX_PUT_LONG( 20, yoffset );
+       __GLX_PUT_LONG( 24, width );
+       __GLX_PUT_LONG( 28, height );
+       __GLX_PUT_LONG( 32, format );
+       __GLX_PUT_LONG( 36, image_size );
+       __glXSendLargeCommand( gc, gc->pc,
+                              __GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + 4,
+                              data, image_size );
+    }
+}
+
+
+void
+__indirect_glCompressedTexImage1DARB( GLenum target, GLint level,
+                                  GLenum internal_format, GLsizei width,
+                                  GLint border, GLsizei image_size,
+                                  const GLvoid *data )
+{
+    CompressedTexImage1D2D( target, level, internal_format, width, 0,
+                           border, image_size, data,
+                           X_GLrop_CompressedTexImage1D );
+}
+
+
+void
+__indirect_glCompressedTexImage2DARB( GLenum target, GLint level,
+                                  GLenum internal_format,
+                                  GLsizei width, GLsizei height,
+                                  GLint border, GLsizei image_size,
+                                  const GLvoid *data )
+{
+    CompressedTexImage1D2D( target, level, internal_format, width, height,
+                           border, image_size, data,
+                           X_GLrop_CompressedTexImage2D );
+}
+
+
+void
+__indirect_glCompressedTexImage3DARB( GLenum target, GLint level,
+                                  GLenum internal_format,
+                                  GLsizei width, GLsizei height, GLsizei depth,
+                                  GLint border, GLsizei image_size,
+                                  const GLvoid *data )
+{
+    __GLX_DECLARE_VARIABLES();
+    
+    __GLX_LOAD_VARIABLES();
+    if ( gc->currentDpy == NULL ) {
+       return;
+    }
+
+    cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE
+                       + image_size );
+    if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+       __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexImage3D, cmdlen );
+       __GLX_PUT_LONG( 4, target );
+       __GLX_PUT_LONG( 8, level );
+       __GLX_PUT_LONG( 12, internal_format );
+       __GLX_PUT_LONG( 16, width );
+       __GLX_PUT_LONG( 20, height );
+       __GLX_PUT_LONG( 24, depth );
+       __GLX_PUT_LONG( 28, border );
+       __GLX_PUT_LONG( 32, image_size );
+       if ( image_size != 0 ) {
+           __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE,
+                                 data, image_size );
+       }
+       __GLX_END( cmdlen );
+    }
+    else {
+       __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexImage3D,
+                                   cmdlen + 4 );
+       __GLX_PUT_LONG( 8, target );
+       __GLX_PUT_LONG( 12, level );
+       __GLX_PUT_LONG( 16, internal_format );
+       __GLX_PUT_LONG( 20, width );
+       __GLX_PUT_LONG( 24, height );
+       __GLX_PUT_LONG( 28, depth );
+       __GLX_PUT_LONG( 32, border );
+       __GLX_PUT_LONG( 36, image_size );
+       __glXSendLargeCommand( gc, gc->pc,
+                              __GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + 4,
+                              data, image_size );
+    }
+}
+
+
+void
+__indirect_glCompressedTexSubImage1DARB( GLenum target, GLint level,
+                                     GLint xoffset,
+                                     GLsizei width,
+                                     GLenum format, GLsizei image_size,
+                                     const GLvoid *data )
+{
+    CompressedTexSubImage1D2D( target, level, xoffset, 0, width, 0,
+                              format, image_size, data,
+                              X_GLrop_CompressedTexSubImage1D );
+}
+
+
+void
+__indirect_glCompressedTexSubImage2DARB( GLenum target, GLint level,
+                                     GLint xoffset, GLint yoffset,
+                                     GLsizei width, GLsizei height,
+                                     GLenum format, GLsizei image_size,
+                                     const GLvoid *data )
+{
+    CompressedTexSubImage1D2D( target, level, xoffset, yoffset, width, height,
+                              format, image_size, data,
+                              X_GLrop_CompressedTexSubImage2D );
+}
+
+
+void
+__indirect_glCompressedTexSubImage3DARB( GLenum target, GLint level,
+                                     GLint xoffset, GLint yoffset, GLint zoffset,
+                                     GLsizei width, GLsizei height, GLsizei depth,
+                                     GLenum format, GLsizei image_size,
+                                     const GLvoid *data )
+{
+    __GLX_DECLARE_VARIABLES();
+    
+    __GLX_LOAD_VARIABLES();
+    if ( gc->currentDpy == NULL ) {
+       return;
+    }
+
+    cmdlen = __GLX_PAD( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE
+                       + image_size );
+    if ( cmdlen <= gc->maxSmallRenderCommandSize ) {
+       __GLX_BEGIN_VARIABLE( X_GLrop_CompressedTexSubImage3D, cmdlen );
+       __GLX_PUT_LONG( 4, target );
+       __GLX_PUT_LONG( 8, level );
+       __GLX_PUT_LONG( 12, xoffset );
+       __GLX_PUT_LONG( 16, yoffset );
+       __GLX_PUT_LONG( 20, zoffset );
+       __GLX_PUT_LONG( 24, width );
+       __GLX_PUT_LONG( 28, height );
+       __GLX_PUT_LONG( 32, depth );
+       __GLX_PUT_LONG( 36, format );
+       __GLX_PUT_LONG( 40, image_size );
+       if ( image_size != 0 ) {
+           __GLX_PUT_CHAR_ARRAY( __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE,
+                                 data, image_size );
+       }
+       __GLX_END( cmdlen );
+    }
+    else {
+       __GLX_BEGIN_VARIABLE_LARGE( X_GLrop_CompressedTexSubImage3D,
+                                   cmdlen + 4 );
+       __GLX_PUT_LONG( 8, target );
+       __GLX_PUT_LONG( 12, level );
+       __GLX_PUT_LONG( 16, xoffset );
+       __GLX_PUT_LONG( 20, yoffset );
+       __GLX_PUT_LONG( 24, zoffset );
+       __GLX_PUT_LONG( 28, width );
+       __GLX_PUT_LONG( 32, height );
+       __GLX_PUT_LONG( 36, depth );
+       __GLX_PUT_LONG( 40, format );
+       __GLX_PUT_LONG( 44, image_size );
+       __glXSendLargeCommand( gc, gc->pc,
+                              __GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE + 4,
+                              data, image_size );
+    }
+}
diff --git a/src/glx/x11/indirect_vertex_array_priv.h b/src/glx/x11/indirect_vertex_array_priv.h
new file mode 100644 (file)
index 0000000..ab97dc6
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * (C) Copyright IBM Corporation 2004, 2005
+ * 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
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _INDIRECT_VA_PRIVATE_
+#define _INDIRECT_VA_PRIVATE_
+
+/**
+ * \file indirect_va_private.h
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <inttypes.h>
+
+#include "glxclient.h"
+#include "indirect.h"
+#include <GL/glxproto.h>
+
+
+/**
+ * State descriptor for a single array of vertex data.
+ */
+struct array_state {
+    /**
+     * Pointer to the application supplied data.
+     */
+    const void * data;
+    
+    /**
+     * Enum representing the type of the application supplied data.
+     */
+    GLenum data_type;
+
+    /**
+     * Stride value supplied by the application.  This value is not used
+     * internally.  It is only kept so that it can be queried by the
+     * application using glGet*v.
+     */
+    GLsizei user_stride;
+
+    /**
+     * Calculated size, in bytes, of a single element in the array.  This
+     * is calculated based on \c count and the size of the data type
+     * represented by \c data_type.
+     */
+    GLsizei element_size;
+
+    /**
+     * Actual byte-stride from one element to the next.  This value will
+     * be equal to either \c user_stride or \c element_stride.
+     */
+    GLsizei true_stride;
+
+    /**
+     * Number of data values in each element.
+     */
+    GLint count;
+
+    /**
+     * "Normalized" data is on the range [0,1] (unsigned) or [-1,1] (signed).
+     * This is used for mapping integral types to floating point types.
+     */
+    GLboolean normalized;
+
+    /**
+     * Pre-calculated GLX protocol command header.
+     */
+    uint32_t header[2];
+    
+    /**
+     * Size of the header data.  For simple data, like glColorPointerfv,
+     * this is 4.  For complex data that requires either a count (e.g.,
+     * glWeightfvARB), an index (e.g., glVertexAttrib1fvARB), or a
+     * selector enum (e.g., glMultiTexCoord2fv) this is 8.
+     */
+    unsigned header_size;
+    
+    /**
+     * Set to \c GL_TRUE if this array is enabled.  Otherwise, it is set
+     * to \c GL_FALSE.
+     */
+    GLboolean  enabled;
+
+    /**
+     * For multi-arrayed data (e.g., texture coordinates, generic vertex
+     * program attributes, etc.), this specifies which array this is.
+     */
+    unsigned index;
+    
+    /**
+     * Per-array-type key.  For most arrays, this will be the GL enum for
+     * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+     * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+     * etc.).
+     */
+    GLenum key;
+
+    /**
+     * If this array can be used with the "classic" \c glDrawArrays protocol,
+     * this is set to \c GL_TRUE.  Otherwise, it is set to \c GL_FALSE.
+     */
+    GLboolean old_DrawArrays_possible;
+};
+
+
+/**
+ * Array state that is pushed / poped by \c glPushClientAttrib and
+ * \c glPopClientAttrib.
+ */
+struct array_stack_state {
+    /**
+     * Pointer to the application supplied data.
+     */
+    const void * data;
+    
+    /**
+     * Enum representing the type of the application supplied data.
+     */
+    GLenum data_type;
+
+    /**
+     * Stride value supplied by the application.  This value is not used
+     * internally.  It is only kept so that it can be queried by the
+     * application using glGet*v.
+     */
+    GLsizei user_stride;
+
+    /**
+     * Number of data values in each element.
+     */
+    GLint count;
+
+    /**
+     * Per-array-type key.  For most arrays, this will be the GL enum for
+     * that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
+     * for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
+     * etc.).
+     */
+    GLenum key;
+
+    /**
+     * For multi-arrayed data (e.g., texture coordinates, generic vertex
+     * program attributes, etc.), this specifies which array this is.
+     */
+    unsigned index;
+
+    /**
+     * Set to \c GL_TRUE if this array is enabled.  Otherwise, it is set
+     * to \c GL_FALSE.
+     */
+    GLboolean  enabled;
+};
+
+
+/**
+ * Collection of all the vertex array state.
+ */
+struct array_state_vector {
+    /**
+     * Number of arrays tracked by \c ::arrays.
+     */
+    size_t num_arrays;
+
+    /**
+     * Array of vertex array state.  This array contains all of the valid
+     * vertex arrays.  If a vertex array isn't in this array, then it isn't
+     * valid.  For example, if an implementation does not support
+     * EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
+     * array.
+     */
+    struct array_state * arrays;
+
+    /**
+     * Number of currently enabled client-side arrays.  The value of this 
+     * field is only valid if \c array_info_cache_valid is true.
+     */
+    size_t enabled_client_array_count;
+
+    /**
+     * \name ARRAY_INFO cache.
+     * 
+     * These fields track the state of the ARRAY_INFO cache.  The
+     * \c array_info_cache_size is the size of the actual data stored in
+     * \c array_info_cache.  \c array_info_cache_buffer_size is the size of
+     * the buffer.  This will always be greater than or equal to
+     * \c array_info_cache_size.
+     *
+     * \note
+     * There are some bytes of extra data before \c array_info_cache that is
+     * used to hold the header for RenderLarge commands.  This is
+     * \b not included in \c array_info_cache_size or
+     * \c array_info_cache_buffer_size.  \c array_info_cache_base stores a
+     * pointer to the true start of the buffer (i.e., what malloc returned).
+     */
+    /*@{*/
+    size_t array_info_cache_size;
+    size_t array_info_cache_buffer_size;
+    void * array_info_cache;
+    void * array_info_cache_base;
+    /*@}*/
+
+
+    /**
+     * Is the cache of ARRAY_INFO data valid?  The cache can become invalid
+     * when one of several state changes occur.  Among these chages are
+     * modifying the array settings for an enabled array and enabling /
+     * disabling an array.
+     */
+    GLboolean array_info_cache_valid;
+
+    /**
+     * Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol?  Use
+     * of this protocol is disabled with really old servers (i.e., servers
+     * that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
+     * variable is set.
+     * 
+     * \todo
+     * GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
+     * opcodes for \c glDrawArrays.  For servers that advertise one or the
+     * other, there should be a way to select which opcode to use.
+     */
+    GLboolean old_DrawArrays_possible;
+
+    /**
+     * Is it possible to use the new GL X.X / ARB_vertex_buffer_object
+     * protocol?
+     * 
+     * \todo
+     * This protocol has not yet been defined by the ARB, but is currently a
+     * work in progress.  This field is a place-holder.
+     */
+    GLboolean new_DrawArrays_possible;
+
+    /**
+     * Active texture unit set by \c glClientActiveTexture.
+     * 
+     * \sa __glXGetActiveTextureUnit
+     */
+    unsigned active_texture_unit;
+    
+    /**
+     * Number of supported texture units.  Even if ARB_multitexture /
+     * GL 1.3 are not supported, this will be at least 1.  When multitexture
+     * is supported, this will be the value queried by calling
+     * \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
+     * 
+     * \todo
+     * Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
+     * instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
+     * NV_fragment_program are supported).
+     */
+    unsigned num_texture_units;
+
+    /**
+     * Number of generic vertex program attribs.  If GL_ARB_vertex_program
+     * is not supported, this will be zero.  Otherwise it will be the value
+     * queries by calling \c glGetProgramiv with \c GL_VERTEX_PROGRAM_ARB
+     * and \c GL_MAX_PROGRAM_ATTRIBS_ARB.
+     */
+    unsigned num_vertex_program_attribs;
+
+    /**
+     * \n Methods for implementing various GL functions.
+     * 
+     * These method pointers are only valid \c array_info_cache_valid is set.
+     * When each function starts, it much check \c array_info_cache_valid.
+     * If it is not set, it must call \c fill_array_info_cache and call
+     * the new method.
+     * 
+     * \sa fill_array_info_cache
+     * 
+     * \todo
+     * Write code to plug these functions directly into the dispatch table.
+     */
+    /*@{*/
+    void (*DrawArrays)( GLenum, GLint, GLsizei );
+    void (*DrawElements)( GLenum mode, GLsizei count, GLenum type,
+                         const GLvoid *indices );
+    /*@}*/
+
+    struct array_stack_state * stack;
+    unsigned active_texture_unit_stack[ __GL_CLIENT_ATTRIB_STACK_DEPTH ];
+    unsigned stack_index;
+};
+
+#endif /* _INDIRECT_VA_PRIVATE_ */