summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/egl/x11
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/egl/x11')
-rw-r--r--src/gallium/state_trackers/egl/x11/glxinit.c682
-rw-r--r--src/gallium/state_trackers/egl/x11/glxinit.h11
-rw-r--r--src/gallium/state_trackers/egl/x11/native_dri2.c693
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.c150
-rw-r--r--src/gallium/state_trackers/egl/x11/native_x11.h37
-rw-r--r--src/gallium/state_trackers/egl/x11/native_ximage.c684
-rw-r--r--src/gallium/state_trackers/egl/x11/sw_winsys.c231
-rw-r--r--src/gallium/state_trackers/egl/x11/sw_winsys.h40
-rw-r--r--src/gallium/state_trackers/egl/x11/x11_screen.c453
-rw-r--r--src/gallium/state_trackers/egl/x11/x11_screen.h105
10 files changed, 3086 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/egl/x11/glxinit.c b/src/gallium/state_trackers/egl/x11/glxinit.c
new file mode 100644
index 0000000000..1ed2afd345
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/glxinit.c
@@ -0,0 +1,682 @@
+/**
+ * GLX initialization. Code based on glxext.c, glx_query.c, and
+ * glcontextmodes.c under src/glx/. The major difference is that DRI
+ * related code is stripped out.
+ *
+ * If the maintenance of this file takes too much time, we should consider
+ * refactoring glxext.c.
+ */
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <sys/time.h>
+
+#include "glxinit.h"
+
+typedef struct GLXGenericGetString
+{
+ CARD8 reqType;
+ CARD8 glxCode;
+ CARD16 length B16;
+ CARD32 for_whom B32;
+ CARD32 name B32;
+} xGLXGenericGetStringReq;
+
+#define sz_xGLXGenericGetStringReq 12
+#define X_GLXGenericGetString 0
+
+/* Extension required boiler plate */
+
+static char *__glXExtensionName = GLX_EXTENSION_NAME;
+static XExtensionInfo *__glXExtensionInfo = NULL;
+
+static int
+__glXCloseDisplay(Display * dpy, XExtCodes * codes)
+{
+ return XextRemoveDisplay(__glXExtensionInfo, dpy);
+}
+
+static /* const */ XExtensionHooks __glXExtensionHooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ __glXCloseDisplay, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
+ __glXExtensionName, &__glXExtensionHooks,
+ __GLX_NUMBER_EVENTS, NULL)
+
+static GLint
+_gl_convert_from_x_visual_type(int visualType)
+{
+#define NUM_VISUAL_TYPES 6
+ static const int glx_visual_types[NUM_VISUAL_TYPES] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ((unsigned) visualType < NUM_VISUAL_TYPES)
+ ? glx_visual_types[visualType] : GLX_NONE;
+}
+
+static __GLcontextModes *
+_gl_context_modes_create(unsigned count, size_t minimum_size)
+{
+ const size_t size = (minimum_size > sizeof(__GLcontextModes))
+ ? minimum_size : sizeof(__GLcontextModes);
+ __GLcontextModes *base = NULL;
+ __GLcontextModes **next;
+ unsigned i;
+
+ next = &base;
+ for (i = 0; i < count; i++) {
+ *next = (__GLcontextModes *) Xmalloc(size);
+ if (*next == NULL) {
+ _gl_context_modes_destroy(base);
+ base = NULL;
+ break;
+ }
+
+ memset(*next, 0, size);
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+ (*next)->bindToTextureRgb = GLX_DONT_CARE;
+ (*next)->bindToTextureRgba = GLX_DONT_CARE;
+ (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+ (*next)->bindToTextureTargets = GLX_DONT_CARE;
+ (*next)->yInverted = GLX_DONT_CARE;
+
+ next = &((*next)->next);
+ }
+
+ return base;
+}
+
+_X_HIDDEN void
+_gl_context_modes_destroy(__GLcontextModes * modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *const next = modes->next;
+
+ Xfree(modes);
+ modes = next;
+ }
+}
+
+_X_HIDDEN char *
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
+{
+ xGLXGenericGetStringReq *req;
+ xGLXSingleReply reply;
+ int length;
+ int numbytes;
+ char *buf;
+ CARD32 for_whom = screen;
+ CARD32 glxCode = X_GLXQueryServerString;
+
+
+ LockDisplay(dpy);
+
+
+ /* All of the GLX protocol requests for getting a string from the server
+ * look the same. The exact meaning of the for_whom field is usually
+ * either the screen number (for glXQueryServerString) or the context tag
+ * (for GLXSingle).
+ */
+
+ GetReq(GLXGenericGetString, req);
+ req->reqType = opcode;
+ req->glxCode = glxCode;
+ req->for_whom = for_whom;
+ req->name = name;
+
+ _XReply(dpy, (xReply *) & reply, 0, False);
+
+ length = reply.length * 4;
+ numbytes = reply.size;
+
+ buf = (char *) Xmalloc(numbytes);
+ if (buf != NULL) {
+ _XRead(dpy, buf, numbytes);
+ length -= numbytes;
+ }
+
+ _XEatData(dpy, length);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return buf;
+}
+
+/************************************************************************/
+/*
+** Free the per screen configs data as well as the array of
+** __glXScreenConfigs.
+*/
+static void
+FreeScreenConfigs(__GLXdisplayPrivate * priv)
+{
+ __GLXscreenConfigs *psc;
+ GLint i, screens;
+
+ /* Free screen configuration information */
+ psc = priv->screenConfigs;
+ screens = ScreenCount(priv->dpy);
+ for (i = 0; i < screens; i++, psc++) {
+ if (psc->configs) {
+ _gl_context_modes_destroy(psc->configs);
+ psc->configs = NULL; /* NOTE: just for paranoia */
+ }
+ if (psc->visuals) {
+ _gl_context_modes_destroy(psc->visuals);
+ psc->visuals = NULL; /* NOTE: just for paranoia */
+ }
+ Xfree((char *) psc->serverGLXexts);
+ }
+ XFree((char *) priv->screenConfigs);
+ priv->screenConfigs = NULL;
+}
+
+/*
+** Release the private memory referred to in a display private
+** structure. The caller will free the extension structure.
+*/
+static int
+__glXFreeDisplayPrivate(XExtData * extension)
+{
+ __GLXdisplayPrivate *priv;
+
+ priv = (__GLXdisplayPrivate *) extension->private_data;
+ FreeScreenConfigs(priv);
+ if (priv->serverGLXvendor) {
+ Xfree((char *) priv->serverGLXvendor);
+ priv->serverGLXvendor = 0x0; /* to protect against double free's */
+ }
+ if (priv->serverGLXversion) {
+ Xfree((char *) priv->serverGLXversion);
+ priv->serverGLXversion = 0x0; /* to protect against double free's */
+ }
+
+ Xfree((char *) priv);
+ return 0;
+}
+
+/************************************************************************/
+
+/*
+** Query the version of the GLX extension. This procedure works even if
+** the client extension is not completely set up.
+*/
+static Bool
+QueryVersion(Display * dpy, int opcode, int *major, int *minor)
+{
+ xGLXQueryVersionReq *req;
+ xGLXQueryVersionReply reply;
+
+ /* Send the glXQueryVersion request */
+ LockDisplay(dpy);
+ GetReq(GLXQueryVersion, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXQueryVersion;
+ req->majorVersion = GLX_MAJOR_VERSION;
+ req->minorVersion = GLX_MINOR_VERSION;
+ _XReply(dpy, (xReply *) & reply, 0, False);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (reply.majorVersion != GLX_MAJOR_VERSION) {
+ /*
+ ** The server does not support the same major release as this
+ ** client.
+ */
+ return GL_FALSE;
+ }
+ *major = reply.majorVersion;
+ *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
+ return GL_TRUE;
+}
+
+_X_HIDDEN void
+__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
+ const INT32 * bp, Bool tagged_only,
+ Bool fbconfig_style_tags)
+{
+ int i;
+
+ if (!tagged_only) {
+ /* Copy in the first set of properties */
+ config->visualID = *bp++;
+
+ config->visualType = _gl_convert_from_x_visual_type(*bp++);
+
+ config->rgbMode = *bp++;
+
+ config->redBits = *bp++;
+ config->greenBits = *bp++;
+ config->blueBits = *bp++;
+ config->alphaBits = *bp++;
+ config->accumRedBits = *bp++;
+ config->accumGreenBits = *bp++;
+ config->accumBlueBits = *bp++;
+ config->accumAlphaBits = *bp++;
+
+ config->doubleBufferMode = *bp++;
+ config->stereoMode = *bp++;
+
+ config->rgbBits = *bp++;
+ config->depthBits = *bp++;
+ config->stencilBits = *bp++;
+ config->numAuxBuffers = *bp++;
+ config->level = *bp++;
+
+ count -= __GLX_MIN_CONFIG_PROPS;
+ }
+
+ /*
+ ** Additional properties may be in a list at the end
+ ** of the reply. They are in pairs of property type
+ ** and property value.
+ */
+
+#define FETCH_OR_SET(tag) \
+ config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
+
+ for (i = 0; i < count; i += 2) {
+ switch (*bp++) {
+ case GLX_RGBA:
+ FETCH_OR_SET(rgbMode);
+ break;
+ case GLX_BUFFER_SIZE:
+ config->rgbBits = *bp++;
+ break;
+ case GLX_LEVEL:
+ config->level = *bp++;
+ break;
+ case GLX_DOUBLEBUFFER:
+ FETCH_OR_SET(doubleBufferMode);
+ break;
+ case GLX_STEREO:
+ FETCH_OR_SET(stereoMode);
+ break;
+ case GLX_AUX_BUFFERS:
+ config->numAuxBuffers = *bp++;
+ break;
+ case GLX_RED_SIZE:
+ config->redBits = *bp++;
+ break;
+ case GLX_GREEN_SIZE:
+ config->greenBits = *bp++;
+ break;
+ case GLX_BLUE_SIZE:
+ config->blueBits = *bp++;
+ break;
+ case GLX_ALPHA_SIZE:
+ config->alphaBits = *bp++;
+ break;
+ case GLX_DEPTH_SIZE:
+ config->depthBits = *bp++;
+ break;
+ case GLX_STENCIL_SIZE:
+ config->stencilBits = *bp++;
+ break;
+ case GLX_ACCUM_RED_SIZE:
+ config->accumRedBits = *bp++;
+ break;
+ case GLX_ACCUM_GREEN_SIZE:
+ config->accumGreenBits = *bp++;
+ break;
+ case GLX_ACCUM_BLUE_SIZE:
+ config->accumBlueBits = *bp++;
+ break;
+ case GLX_ACCUM_ALPHA_SIZE:
+ config->accumAlphaBits = *bp++;
+ break;
+ case GLX_VISUAL_CAVEAT_EXT:
+ config->visualRating = *bp++;
+ break;
+ case GLX_X_VISUAL_TYPE:
+ config->visualType = *bp++;
+ break;
+ case GLX_TRANSPARENT_TYPE:
+ config->transparentPixel = *bp++;
+ break;
+ case GLX_TRANSPARENT_INDEX_VALUE:
+ config->transparentIndex = *bp++;
+ break;
+ case GLX_TRANSPARENT_RED_VALUE:
+ config->transparentRed = *bp++;
+ break;
+ case GLX_TRANSPARENT_GREEN_VALUE:
+ config->transparentGreen = *bp++;
+ break;
+ case GLX_TRANSPARENT_BLUE_VALUE:
+ config->transparentBlue = *bp++;
+ break;
+ case GLX_TRANSPARENT_ALPHA_VALUE:
+ config->transparentAlpha = *bp++;
+ break;
+ case GLX_VISUAL_ID:
+ config->visualID = *bp++;
+ break;
+ case GLX_DRAWABLE_TYPE:
+ config->drawableType = *bp++;
+ break;
+ case GLX_RENDER_TYPE:
+ config->renderType = *bp++;
+ break;
+ case GLX_X_RENDERABLE:
+ config->xRenderable = *bp++;
+ break;
+ case GLX_FBCONFIG_ID:
+ config->fbconfigID = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_WIDTH:
+ config->maxPbufferWidth = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ config->maxPbufferHeight = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_PIXELS:
+ config->maxPbufferPixels = *bp++;
+ break;
+ case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+ config->optimalPbufferWidth = *bp++;
+ break;
+ case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+ config->optimalPbufferHeight = *bp++;
+ break;
+ case GLX_VISUAL_SELECT_GROUP_SGIX:
+ config->visualSelectGroup = *bp++;
+ break;
+ case GLX_SWAP_METHOD_OML:
+ config->swapMethod = *bp++;
+ break;
+ case GLX_SAMPLE_BUFFERS_SGIS:
+ config->sampleBuffers = *bp++;
+ break;
+ case GLX_SAMPLES_SGIS:
+ config->samples = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_RGB_EXT:
+ config->bindToTextureRgb = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+ config->bindToTextureRgba = *bp++;
+ break;
+ case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+ config->bindToMipmapTexture = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+ config->bindToTextureTargets = *bp++;
+ break;
+ case GLX_Y_INVERTED_EXT:
+ config->yInverted = *bp++;
+ break;
+ case None:
+ i = count;
+ break;
+ default:
+ break;
+ }
+ }
+
+ config->renderType =
+ (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+
+ config->haveAccumBuffer = ((config->accumRedBits +
+ config->accumGreenBits +
+ config->accumBlueBits +
+ config->accumAlphaBits) > 0);
+ config->haveDepthBuffer = (config->depthBits > 0);
+ config->haveStencilBuffer = (config->stencilBits > 0);
+}
+
+static __GLcontextModes *
+createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
+ int screen, GLboolean tagged_only)
+{
+ INT32 buf[__GLX_TOTAL_CONFIG], *props;
+ unsigned prop_size;
+ __GLcontextModes *modes, *m;
+ int i;
+
+ if (nprops == 0)
+ return NULL;
+
+ /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
+
+ /* Check number of properties */
+ if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
+ return NULL;
+
+ /* Allocate memory for our config structure */
+ modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
+ if (!modes)
+ return NULL;
+
+ prop_size = nprops * __GLX_SIZE_INT32;
+ if (prop_size <= sizeof(buf))
+ props = buf;
+ else
+ props = Xmalloc(prop_size);
+
+ /* Read each config structure and convert it into our format */
+ m = modes;
+ for (i = 0; i < nvisuals; i++) {
+ _XRead(dpy, (char *) props, prop_size);
+ /* Older X servers don't send this so we default it here. */
+ m->drawableType = GLX_WINDOW_BIT;
+ __glXInitializeVisualConfigFromTags(m, nprops, props,
+ tagged_only, GL_TRUE);
+ m->screen = screen;
+ m = m->next;
+ }
+
+ if (props != buf)
+ Xfree(props);
+
+ return modes;
+}
+
+static GLboolean
+getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+{
+ xGLXGetVisualConfigsReq *req;
+ __GLXscreenConfigs *psc;
+ xGLXGetVisualConfigsReply reply;
+
+ LockDisplay(dpy);
+
+ psc = priv->screenConfigs + screen;
+ psc->visuals = NULL;
+ GetReq(GLXGetVisualConfigs, req);
+ req->reqType = priv->majorOpcode;
+ req->glxCode = X_GLXGetVisualConfigs;
+ req->screen = screen;
+
+ if (!_XReply(dpy, (xReply *) & reply, 0, False))
+ goto out;
+
+ psc->visuals = createConfigsFromProperties(dpy,
+ reply.numVisuals,
+ reply.numProps,
+ screen, GL_FALSE);
+
+ out:
+ UnlockDisplay(dpy);
+ return psc->visuals != NULL;
+}
+
+static GLboolean
+getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+{
+ xGLXGetFBConfigsReq *fb_req;
+ xGLXGetFBConfigsSGIXReq *sgi_req;
+ xGLXVendorPrivateWithReplyReq *vpreq;
+ xGLXGetFBConfigsReply reply;
+ __GLXscreenConfigs *psc;
+
+ psc = priv->screenConfigs + screen;
+ psc->serverGLXexts =
+ __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
+
+ LockDisplay(dpy);
+
+ psc->configs = NULL;
+ if (atof(priv->serverGLXversion) >= 1.3) {
+ GetReq(GLXGetFBConfigs, fb_req);
+ fb_req->reqType = priv->majorOpcode;
+ fb_req->glxCode = X_GLXGetFBConfigs;
+ fb_req->screen = screen;
+ }
+ else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
+ GetReqExtra(GLXVendorPrivateWithReply,
+ sz_xGLXGetFBConfigsSGIXReq +
+ sz_xGLXVendorPrivateWithReplyReq, vpreq);
+ sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
+ sgi_req->reqType = priv->majorOpcode;
+ sgi_req->glxCode = X_GLXVendorPrivateWithReply;
+ sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
+ sgi_req->screen = screen;
+ }
+ else
+ goto out;
+
+ if (!_XReply(dpy, (xReply *) & reply, 0, False))
+ goto out;
+
+ psc->configs = createConfigsFromProperties(dpy,
+ reply.numFBConfigs,
+ reply.numAttribs * 2,
+ screen, GL_TRUE);
+
+ out:
+ UnlockDisplay(dpy);
+ return psc->configs != NULL;
+}
+
+static GLboolean
+AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
+{
+ __GLXscreenConfigs *psc;
+ GLint i, screens;
+
+ /*
+ ** First allocate memory for the array of per screen configs.
+ */
+ screens = ScreenCount(dpy);
+ psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
+ if (!psc) {
+ return GL_FALSE;
+ }
+ memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
+ priv->screenConfigs = psc;
+
+ priv->serverGLXversion =
+ __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
+ if (priv->serverGLXversion == NULL) {
+ FreeScreenConfigs(priv);
+ return GL_FALSE;
+ }
+
+ for (i = 0; i < screens; i++, psc++) {
+ getFBConfigs(dpy, priv, i);
+ getVisualConfigs(dpy, priv, i);
+ psc->scr = i;
+ psc->dpy = dpy;
+ }
+
+ SyncHandle();
+
+ return GL_TRUE;
+}
+
+_X_HIDDEN __GLXdisplayPrivate *
+__glXInitialize(Display * dpy)
+{
+ XExtDisplayInfo *info = __glXFindDisplay(dpy);
+ XExtData **privList, *private, *found;
+ __GLXdisplayPrivate *dpyPriv;
+ XEDataObject dataObj;
+ int major, minor;
+
+ if (!XextHasExtension(info))
+ return NULL;
+
+ /* See if a display private already exists. If so, return it */
+ dataObj.display = dpy;
+ privList = XEHeadOfExtensionList(dataObj);
+ found = XFindOnExtensionList(privList, info->codes->extension);
+ if (found)
+ return (__GLXdisplayPrivate *) found->private_data;
+
+ /* See if the versions are compatible */
+ if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor))
+ return NULL;
+
+ /*
+ ** Allocate memory for all the pieces needed for this buffer.
+ */
+ private = (XExtData *) Xmalloc(sizeof(XExtData));
+ if (!private)
+ return NULL;
+ dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
+ if (!dpyPriv) {
+ Xfree(private);
+ return NULL;
+ }
+
+ /*
+ ** Init the display private and then read in the screen config
+ ** structures from the server.
+ */
+ dpyPriv->majorOpcode = info->codes->major_opcode;
+ dpyPriv->majorVersion = major;
+ dpyPriv->minorVersion = minor;
+ dpyPriv->dpy = dpy;
+
+ dpyPriv->serverGLXvendor = NULL;
+ dpyPriv->serverGLXversion = NULL;
+
+ if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
+ Xfree(dpyPriv);
+ Xfree(private);
+ return NULL;
+ }
+
+ /*
+ ** Fill in the private structure. This is the actual structure that
+ ** hangs off of the Display structure. Our private structure is
+ ** referred to by this structure. Got that?
+ */
+ private->number = info->codes->extension;
+ private->next = 0;
+ private->free_private = __glXFreeDisplayPrivate;
+ private->private_data = (char *) dpyPriv;
+ XAddToExtensionList(privList, private);
+
+ return dpyPriv;
+}
diff --git a/src/gallium/state_trackers/egl/x11/glxinit.h b/src/gallium/state_trackers/egl/x11/glxinit.h
new file mode 100644
index 0000000000..1cc7c460fe
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/glxinit.h
@@ -0,0 +1,11 @@
+#ifndef GLXINIT_INCLUDED
+#define GLXINIT_INCLUDED
+
+#include <X11/Xlib.h>
+#include "glxclient.h"
+
+/* this is used by DRI loaders */
+extern void
+_gl_context_modes_destroy(__GLcontextModes * modes);
+
+#endif /* GLXINIT_INCLUDED */
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
new file mode 100644
index 0000000000..5f2fd41260
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -0,0 +1,693 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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.
+ */
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum dri2_surface_type {
+ DRI2_SURFACE_TYPE_WINDOW,
+ DRI2_SURFACE_TYPE_PIXMAP,
+ DRI2_SURFACE_TYPE_PBUFFER
+};
+
+struct dri2_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct drm_api *api;
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ struct dri2_config *configs;
+ int num_configs;
+};
+
+struct dri2_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum dri2_surface_type type;
+ enum pipe_format color_format;
+ struct dri2_display *dri2dpy;
+
+ struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
+ boolean have_back, have_fake;
+ int width, height;
+ unsigned int sequence_number;
+};
+
+struct dri2_config {
+ struct native_config base;
+};
+
+static INLINE struct dri2_display *
+dri2_display(const struct native_display *ndpy)
+{
+ return (struct dri2_display *) ndpy;
+}
+
+static INLINE struct dri2_surface *
+dri2_surface(const struct native_surface *nsurf)
+{
+ return (struct dri2_surface *) nsurf;
+}
+
+static INLINE struct dri2_config *
+dri2_config(const struct native_config *nconf)
+{
+ return (struct dri2_config *) nconf;
+}
+
+static boolean
+dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to real front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ /* pbuffer is private */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ /* copy to front buffer */
+ if (dri2surf->have_back)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferBackLeft, DRI2BufferFrontLeft);
+
+ /* and update fake front buffer */
+ if (dri2surf->have_fake)
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+
+ return TRUE;
+}
+
+static boolean
+dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+ unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
+ struct pipe_texture templ;
+ struct x11_drawable_buffer *xbufs;
+ int num_ins, num_outs, att, i;
+
+ if (attachment_mask) {
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ templ.depth0 = 1;
+ templ.format = dri2surf->color_format;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (textures)
+ memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
+ }
+
+ /* create textures for pbuffer */
+ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
+ struct pipe_screen *screen = dri2dpy->base.screen;
+
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
+
+ /* delay the allocation */
+ if (!native_attachment_mask_test(attachment_mask, att))
+ continue;
+
+ if (!ptex) {
+ ptex = screen->texture_create(screen, &templ);
+ dri2surf->pbuffer_textures[att] = ptex;
+ }
+
+ if (textures)
+ pipe_texture_reference(&textures[att], ptex);
+ }
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ return TRUE;
+ }
+
+ /* prepare the attachments */
+ num_ins = 0;
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ if (native_attachment_mask_test(attachment_mask, att)) {
+ unsigned int dri2att;
+
+ switch (att) {
+ case NATIVE_ATTACHMENT_FRONT_LEFT:
+ dri2att = DRI2BufferFrontLeft;
+ break;
+ case NATIVE_ATTACHMENT_BACK_LEFT:
+ dri2att = DRI2BufferBackLeft;
+ break;
+ case NATIVE_ATTACHMENT_FRONT_RIGHT:
+ dri2att = DRI2BufferFrontRight;
+ break;
+ case NATIVE_ATTACHMENT_BACK_RIGHT:
+ dri2att = DRI2BufferBackRight;
+ break;
+ default:
+ assert(0);
+ dri2att = 0;
+ break;
+ }
+
+ dri2atts[num_ins] = dri2att;
+ num_ins++;
+ }
+ }
+
+ dri2surf->have_back = FALSE;
+ dri2surf->have_fake = FALSE;
+
+ /* remember old geometry */
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+
+ xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
+ &dri2surf->width, &dri2surf->height,
+ dri2atts, FALSE, num_ins, &num_outs);
+ if (!xbufs)
+ return FALSE;
+
+ if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
+ /* are there cases where the buffers change and the geometry doesn't? */
+ dri2surf->sequence_number++;
+
+ templ.width0 = dri2surf->width;
+ templ.height0 = dri2surf->height;
+ }
+
+ for (i = 0; i < num_outs; i++) {
+ struct x11_drawable_buffer *xbuf = &xbufs[i];
+ const char *desc;
+ enum native_attachment natt;
+
+ switch (xbuf->attachment) {
+ case DRI2BufferFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Front Buffer";
+ break;
+ case DRI2BufferFakeFrontLeft:
+ natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+ desc = "DRI2 Fake Front Buffer";
+ dri2surf->have_fake = TRUE;
+ break;
+ case DRI2BufferBackLeft:
+ natt = NATIVE_ATTACHMENT_BACK_LEFT;
+ desc = "DRI2 Back Buffer";
+ dri2surf->have_back = TRUE;
+ break;
+ default:
+ desc = NULL;
+ break;
+ }
+
+ if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
+ (textures && textures[natt])) {
+ if (!desc)
+ _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
+ else if (!native_attachment_mask_test(attachment_mask, natt))
+ _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
+ else
+ _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
+ continue;
+ }
+
+ if (textures) {
+ struct pipe_texture *ptex =
+ dri2dpy->api->texture_from_shared_handle(dri2dpy->api,
+ dri2dpy->base.screen, &templ,
+ desc, xbuf->pitch, xbuf->name);
+ if (ptex) {
+ /* the caller owns the textures */
+ textures[natt] = ptex;
+ }
+ }
+ }
+
+ free(xbufs);
+
+ if (seq_num)
+ *seq_num = dri2surf->sequence_number;
+ if (width)
+ *width = dri2surf->width;
+ if (height)
+ *height = dri2surf->height;
+
+ return TRUE;
+}
+
+static void
+dri2_surface_wait(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ struct dri2_display *dri2dpy = dri2surf->dri2dpy;
+
+ if (dri2surf->have_fake) {
+ x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
+ 0, 0, dri2surf->width, dri2surf->height,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+ }
+}
+
+static void
+dri2_surface_destroy(struct native_surface *nsurf)
+{
+ struct dri2_surface *dri2surf = dri2_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct pipe_texture *ptex = dri2surf->pbuffer_textures[i];
+ pipe_texture_reference(&ptex, NULL);
+ }
+
+ if (dri2surf->drawable)
+ x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
+ dri2surf->drawable, FALSE);
+ free(dri2surf);
+}
+
+static struct dri2_surface *
+dri2_display_create_surface(struct native_display *ndpy,
+ enum dri2_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ struct dri2_config *dri2conf = dri2_config(nconf);
+ struct dri2_surface *dri2surf;
+
+ dri2surf = CALLOC_STRUCT(dri2_surface);
+ if (!dri2surf)
+ return NULL;
+
+ if (drawable)
+ x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
+
+ dri2surf->dri2dpy = dri2dpy;
+ dri2surf->type = type;
+ dri2surf->drawable = drawable;
+ dri2surf->color_format = dri2conf->base.color_format;
+
+ dri2surf->base.destroy = dri2_surface_destroy;
+ dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
+ dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
+ dri2surf->base.validate = dri2_surface_validate;
+ dri2surf->base.wait = dri2_surface_wait;
+
+ return dri2surf;
+}
+
+static struct native_surface *
+dri2_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static struct native_surface *
+dri2_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct dri2_surface *dri2surf;
+
+ dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (dri2surf) {
+ dri2surf->width = width;
+ dri2surf->height = height;
+ }
+ return (dri2surf) ? &dri2surf->base : NULL;
+}
+
+static int
+choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->rgbBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 24:
+ formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
+ formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
+ formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static int
+choose_depth_stencil_format(const __GLcontextModes *mode,
+ enum pipe_format formats[32])
+{
+ int count = 0;
+
+ switch (mode->depthBits) {
+ case 32:
+ formats[count++] = PIPE_FORMAT_Z32_UNORM;
+ break;
+ case 24:
+ if (mode->stencilBits) {
+ formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
+ }
+ else {
+ formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
+ formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
+ }
+ break;
+ case 16:
+ formats[count++] = PIPE_FORMAT_Z16_UNORM;
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+static boolean
+is_format_supported(struct pipe_screen *screen,
+ enum pipe_format fmt, boolean is_color)
+{
+ return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+ (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+}
+
+static boolean
+dri2_display_convert_config(struct native_display *ndpy,
+ const __GLcontextModes *mode,
+ struct native_config *nconf)
+{
+ enum pipe_format formats[32];
+ int num_formats, i;
+
+ if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
+ return FALSE;
+
+ /* skip single-buffered configs */
+ if (!mode->doubleBufferMode)
+ return FALSE;
+
+ nconf->mode = *mode;
+ nconf->mode.renderType = GLX_RGBA_BIT;
+ nconf->mode.rgbMode = TRUE;
+ /* pbuffer is allocated locally and is always supported */
+ nconf->mode.drawableType |= GLX_PBUFFER_BIT;
+ /* the swap method is always copy */
+ nconf->mode.swapMethod = GLX_SWAP_COPY_OML;
+
+ /* fix up */
+ nconf->mode.rgbBits =
+ nconf->mode.redBits + nconf->mode.greenBits +
+ nconf->mode.blueBits + nconf->mode.alphaBits;
+ if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) {
+ nconf->mode.visualID = 0;
+ nconf->mode.visualType = GLX_NONE;
+ }
+ if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) {
+ nconf->mode.bindToTextureRgb = FALSE;
+ nconf->mode.bindToTextureRgba = FALSE;
+ }
+
+ nconf->color_format = PIPE_FORMAT_NONE;
+ nconf->depth_format = PIPE_FORMAT_NONE;
+ nconf->stencil_format = PIPE_FORMAT_NONE;
+
+ /* choose color format */
+ num_formats = choose_color_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
+ nconf->color_format = formats[i];
+ break;
+ }
+ }
+ if (nconf->color_format == PIPE_FORMAT_NONE)
+ return FALSE;
+
+ /* choose depth/stencil format */
+ num_formats = choose_depth_stencil_format(mode, formats);
+ for (i = 0; i < num_formats; i++) {
+ if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
+ nconf->depth_format = formats[i];
+ nconf->stencil_format = formats[i];
+ break;
+ }
+ }
+ if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
+ (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
+ return FALSE;
+
+ return TRUE;
+}
+
+static const struct native_config **
+dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!dri2dpy->configs) {
+ const __GLcontextModes *modes;
+ int num_modes, count;
+
+ modes = x11_screen_get_glx_configs(dri2dpy->xscr);
+ if (!modes)
+ return NULL;
+ num_modes = x11_context_modes_count(modes);
+
+ dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
+ if (!dri2dpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_modes; i++) {
+ struct native_config *nconf = &dri2dpy->configs[count].base;
+ if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
+ count++;
+ modes = modes->next;
+ }
+
+ dri2dpy->num_configs = count;
+ }
+
+ configs = malloc(dri2dpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < dri2dpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &dri2dpy->configs[i];
+ if (num_configs)
+ *num_configs = dri2dpy->num_configs;
+ }
+
+ return configs;
+}
+
+static boolean
+dri2_display_is_pixmap_supported(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ uint depth, nconf_depth;
+
+ depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
+ nconf_depth = util_format_get_blocksizebits(nconf->color_format);
+
+ /* simple depth match for now */
+ return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth));
+}
+
+static void
+dri2_display_destroy(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+ if (dri2dpy->configs)
+ free(dri2dpy->configs);
+
+ if (dri2dpy->base.screen)
+ dri2dpy->base.screen->destroy(dri2dpy->base.screen);
+
+ if (dri2dpy->xscr)
+ x11_screen_destroy(dri2dpy->xscr);
+ if (dri2dpy->own_dpy)
+ XCloseDisplay(dri2dpy->dpy);
+ if (dri2dpy->api && dri2dpy->api->destroy)
+ dri2dpy->api->destroy(dri2dpy->api);
+ free(dri2dpy);
+}
+
+/**
+ * Initialize DRI2 and pipe screen.
+ */
+static boolean
+dri2_display_init_screen(struct native_display *ndpy)
+{
+ struct dri2_display *dri2dpy = dri2_display(ndpy);
+ const char *driver = dri2dpy->api->name;
+ struct drm_create_screen_arg arg;
+ int fd;
+
+ if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
+ !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
+ _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
+ return FALSE;
+ }
+
+ fd = x11_screen_enable_dri2(dri2dpy->xscr, driver);
+ if (fd < 0)
+ return FALSE;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mode = DRM_CREATE_NORMAL;
+ dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
+ if (!dri2dpy->base.screen) {
+ _eglLog(_EGL_WARNING, "failed to create DRM screen");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api)
+{
+ struct dri2_display *dri2dpy;
+
+ dri2dpy = CALLOC_STRUCT(dri2_display);
+ if (!dri2dpy)
+ return NULL;
+
+ dri2dpy->api = api;
+ if (!dri2dpy->api) {
+ _eglLog(_EGL_WARNING, "failed to create DRM API");
+ free(dri2dpy);
+ return NULL;
+ }
+
+ dri2dpy->dpy = dpy;
+ if (!dri2dpy->dpy) {
+ dri2dpy->dpy = XOpenDisplay(NULL);
+ if (!dri2dpy->dpy) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+ dri2dpy->own_dpy = TRUE;
+ }
+
+ dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
+ dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
+ if (!dri2dpy->xscr) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ if (!dri2_display_init_screen(&dri2dpy->base)) {
+ dri2_display_destroy(&dri2dpy->base);
+ return NULL;
+ }
+
+ dri2dpy->base.destroy = dri2_display_destroy;
+ dri2dpy->base.get_configs = dri2_display_get_configs;
+ dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
+ dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
+ dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
+ dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface;
+
+ return &dri2dpy->base;
+}
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c
new file mode 100644
index 0000000000..8eb542bd82
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/native_x11.c
@@ -0,0 +1,150 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "state_tracker/drm_api.h"
+#include "egllog.h"
+
+#include "native_x11.h"
+#include "x11_screen.h"
+
+#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */
+
+static struct drm_api *api;
+
+static void
+x11_probe_destroy(struct native_probe *nprobe)
+{
+ if (nprobe->data)
+ free(nprobe->data);
+ free(nprobe);
+}
+
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy)
+{
+ struct native_probe *nprobe;
+ struct x11_screen *xscr;
+ int scr;
+ const char *driver_name = NULL;
+ Display *xdpy;
+
+ nprobe = CALLOC_STRUCT(native_probe);
+ if (!nprobe)
+ return NULL;
+
+ xdpy = dpy;
+ if (!xdpy) {
+ xdpy = XOpenDisplay(NULL);
+ if (!xdpy) {
+ free(nprobe);
+ return NULL;
+ }
+ }
+
+ scr = DefaultScreen(xdpy);
+ xscr = x11_screen_create(xdpy, scr);
+ if (xscr) {
+ if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) {
+ driver_name = x11_screen_probe_dri2(xscr);
+ if (driver_name)
+ nprobe->data = strdup(driver_name);
+ }
+
+ x11_screen_destroy(xscr);
+ }
+
+ if (xdpy != dpy)
+ XCloseDisplay(xdpy);
+
+ nprobe->magic = X11_PROBE_MAGIC;
+ nprobe->display = dpy;
+
+ nprobe->destroy = x11_probe_destroy;
+
+ return nprobe;
+}
+
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe)
+{
+ if (!nprobe || nprobe->magic != X11_PROBE_MAGIC)
+ return NATIVE_PROBE_UNKNOWN;
+
+ if (!api)
+ api = drm_api_create();
+
+ /* this is a software driver */
+ if (!api)
+ return NATIVE_PROBE_SUPPORTED;
+
+ /* the display does not support DRI2 or the driver mismatches */
+ if (!nprobe->data || strcmp(api->name, (const char *) nprobe->data) != 0)
+ return NATIVE_PROBE_FALLBACK;
+
+ return NATIVE_PROBE_EXACT;
+}
+
+const char *
+native_get_name(void)
+{
+ static char x11_name[32];
+
+ if (!api)
+ api = drm_api_create();
+
+ if (api)
+ snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name);
+ else
+ snprintf(x11_name, sizeof(x11_name), "X11");
+
+ return x11_name;
+}
+
+struct native_display *
+native_create_display(EGLNativeDisplayType dpy)
+{
+ struct native_display *ndpy = NULL;
+ boolean force_sw;
+
+ if (!api)
+ api = drm_api_create();
+
+ force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
+ if (api && !force_sw) {
+ ndpy = x11_create_dri2_display(dpy, api);
+ }
+
+ if (!ndpy) {
+ EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
+
+ _eglLog(level, "use software fallback");
+ ndpy = x11_create_ximage_display(dpy, TRUE);
+ }
+
+ return ndpy;
+}
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h
new file mode 100644
index 0000000000..622ddac5df
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/native_x11.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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 _NATIVE_X11_H_
+#define _NATIVE_X11_H_
+
+#include "state_tracker/drm_api.h"
+#include "common/native.h"
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm);
+
+struct native_display *
+x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api);
+
+#endif /* _NATIVE_X11_H_ */
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c
new file mode 100644
index 0000000000..92a62f230e
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/native_ximage.c
@@ -0,0 +1,684 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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.
+ */
+
+#include <assert.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "pipe/p_compiler.h"
+#include "util/u_simple_screen.h"
+#include "util/u_inlines.h"
+#include "softpipe/sp_winsys.h"
+#include "egllog.h"
+
+#include "sw_winsys.h"
+#include "native_x11.h"
+#include "x11_screen.h"
+
+enum ximage_surface_type {
+ XIMAGE_SURFACE_TYPE_WINDOW,
+ XIMAGE_SURFACE_TYPE_PIXMAP,
+ XIMAGE_SURFACE_TYPE_PBUFFER
+};
+
+struct ximage_display {
+ struct native_display base;
+ Display *dpy;
+ boolean own_dpy;
+
+ struct x11_screen *xscr;
+ int xscr_number;
+
+ boolean use_xshm;
+
+ struct pipe_winsys *winsys;
+ struct ximage_config *configs;
+ int num_configs;
+};
+
+struct ximage_buffer {
+ XImage *ximage;
+
+ struct pipe_texture *texture;
+ XShmSegmentInfo *shm_info;
+ boolean xshm_attached;
+};
+
+struct ximage_surface {
+ struct native_surface base;
+ Drawable drawable;
+ enum ximage_surface_type type;
+ enum pipe_format color_format;
+ XVisualInfo visual;
+ struct ximage_display *xdpy;
+
+ int width, height;
+ GC gc;
+
+ struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
+ unsigned int sequence_number;
+};
+
+struct ximage_config {
+ struct native_config base;
+ const XVisualInfo *visual;
+};
+
+static INLINE struct ximage_display *
+ximage_display(const struct native_display *ndpy)
+{
+ return (struct ximage_display *) ndpy;
+}
+
+static INLINE struct ximage_surface *
+ximage_surface(const struct native_surface *nsurf)
+{
+ return (struct ximage_surface *) nsurf;
+}
+
+static INLINE struct ximage_config *
+ximage_config(const struct native_config *nconf)
+{
+ return (struct ximage_config *) nconf;
+}
+
+static void
+ximage_surface_free_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+
+ pipe_texture_reference(&xbuf->texture, NULL);
+
+ if (xbuf->shm_info) {
+ if (xbuf->xshm_attached)
+ XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info);
+ if (xbuf->shm_info->shmaddr != (void *) -1)
+ shmdt(xbuf->shm_info->shmaddr);
+ if (xbuf->shm_info->shmid != -1)
+ shmctl(xbuf->shm_info->shmid, IPC_RMID, 0);
+
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->shmid = -1;
+ }
+}
+
+static boolean
+ximage_surface_alloc_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+ struct pipe_texture templ;
+
+ /* free old data */
+ if (xbuf->texture)
+ ximage_surface_free_buffer(&xsurf->base, which);
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = xsurf->color_format;
+ templ.width0 = xsurf->width;
+ templ.height0 = xsurf->height;
+ templ.depth0 = 1;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ if (xbuf->shm_info) {
+ struct pipe_buffer *pbuf;
+ unsigned stride, size;
+ void *addr = NULL;
+
+ stride = util_format_get_stride(xsurf->color_format, xsurf->width);
+ /* alignment should depend on visual? */
+ stride = align(stride, 4);
+ size = stride * xsurf->height;
+
+ /* create and attach shm object */
+ xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755);
+ if (xbuf->shm_info->shmid != -1) {
+ xbuf->shm_info->shmaddr =
+ shmat(xbuf->shm_info->shmid, NULL, 0);
+ if (xbuf->shm_info->shmaddr != (void *) -1) {
+ if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) {
+ addr = xbuf->shm_info->shmaddr;
+ xbuf->xshm_attached = TRUE;
+ }
+ }
+ }
+
+ if (addr) {
+ pbuf = screen->user_buffer_create(screen, addr, size);
+ if (pbuf) {
+ xbuf->texture =
+ screen->texture_blanket(screen, &templ, &stride, pbuf);
+ pipe_buffer_reference(&pbuf, NULL);
+ }
+ }
+ }
+ else {
+ xbuf->texture = screen->texture_create(screen, &templ);
+ }
+
+ /* clean up the buffer if allocation failed */
+ if (!xbuf->texture)
+ ximage_surface_free_buffer(&xsurf->base, which);
+
+ return (xbuf->texture != NULL);
+}
+
+static boolean
+ximage_surface_draw_buffer(struct native_surface *nsurf,
+ enum native_attachment which)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xbuf = &xsurf->buffers[which];
+ struct pipe_screen *screen = xsurf->xdpy->base.screen;
+ struct pipe_transfer *transfer;
+
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return TRUE;
+
+ assert(xsurf->drawable && xbuf->ximage && xbuf->texture);
+
+ transfer = screen->get_tex_transfer(screen, xbuf->texture,
+ 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height);
+ if (!transfer)
+ return FALSE;
+
+ xbuf->ximage->bytes_per_line = transfer->stride;
+ xbuf->ximage->data = screen->transfer_map(screen, transfer);
+ if (!xbuf->ximage->data) {
+ screen->tex_transfer_destroy(transfer);
+ return FALSE;
+ }
+
+
+ if (xbuf->shm_info)
+ XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False);
+ else
+ XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc,
+ xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height);
+
+ xbuf->ximage->data = NULL;
+ screen->transfer_unmap(screen, transfer);
+
+ /*
+ * softpipe allows the pipe transfer to be re-used, but we don't want to
+ * rely on that behavior.
+ */
+ screen->tex_transfer_destroy(transfer);
+
+ XSync(xsurf->xdpy->dpy, FALSE);
+
+ return TRUE;
+}
+
+static boolean
+ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
+{
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static boolean
+ximage_surface_swap_buffers(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ struct ximage_buffer *xfront, *xback, xtmp;
+
+ xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
+ xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
+
+ /* draw the back buffer directly if there is no front buffer */
+ if (!xfront->texture)
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
+
+ /* swap the buffers */
+ xtmp = *xfront;
+ *xfront = *xback;
+ *xback = xtmp;
+
+ /* the front/back textures are swapped */
+ xsurf->sequence_number++;
+
+ return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+}
+
+static void
+ximage_surface_update_geometry(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ Status ok;
+ Window root;
+ int x, y;
+ unsigned int w, h, border, depth;
+
+ /* pbuffer has fixed geometry */
+ if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER)
+ return;
+
+ ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
+ &root, &x, &y, &w, &h, &border, &depth);
+ if (ok) {
+ xsurf->width = w;
+ xsurf->height = h;
+ }
+}
+
+static boolean
+ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+ unsigned int *seq_num, struct pipe_texture **textures,
+ int *width, int *height)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ boolean new_buffers = FALSE;
+ int att;
+
+ ximage_surface_update_geometry(&xsurf->base);
+
+ for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[att];
+
+ /* delay the allocation */
+ if (!native_attachment_mask_test(attachment_mask, att))
+ continue;
+
+ /* reallocate the texture */
+ if (!xbuf->texture ||
+ xsurf->width != xbuf->texture->width0 ||
+ xsurf->height != xbuf->texture->height0) {
+ new_buffers = TRUE;
+ if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
+ /* update ximage */
+ if (xbuf->ximage) {
+ xbuf->ximage->width = xsurf->width;
+ xbuf->ximage->height = xsurf->height;
+ }
+ }
+ }
+
+ if (textures) {
+ textures[att] = NULL;
+ pipe_texture_reference(&textures[att], xbuf->texture);
+ }
+ }
+
+ /* increase the sequence number so that caller knows */
+ if (new_buffers)
+ xsurf->sequence_number++;
+
+ if (seq_num)
+ *seq_num = xsurf->sequence_number;
+ if (width)
+ *width = xsurf->width;
+ if (height)
+ *height = xsurf->height;
+
+ return TRUE;
+}
+
+static void
+ximage_surface_wait(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ XSync(xsurf->xdpy->dpy, FALSE);
+ /* TODO XGetImage and update the front texture */
+}
+
+static void
+ximage_surface_destroy(struct native_surface *nsurf)
+{
+ struct ximage_surface *xsurf = ximage_surface(nsurf);
+ int i;
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+ ximage_surface_free_buffer(&xsurf->base, i);
+ /* xbuf->shm_info is owned by xbuf->ximage? */
+ if (xbuf->ximage) {
+ XDestroyImage(xbuf->ximage);
+ xbuf->ximage = NULL;
+ }
+ }
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER)
+ XFreeGC(xsurf->xdpy->dpy, xsurf->gc);
+ free(xsurf);
+}
+
+static struct ximage_surface *
+ximage_display_create_surface(struct native_display *ndpy,
+ enum ximage_surface_type type,
+ Drawable drawable,
+ const struct native_config *nconf)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ struct ximage_config *xconf = ximage_config(nconf);
+ struct ximage_surface *xsurf;
+ int i;
+
+ xsurf = CALLOC_STRUCT(ximage_surface);
+ if (!xsurf)
+ return NULL;
+
+ xsurf->xdpy = xdpy;
+ xsurf->type = type;
+ xsurf->color_format = xconf->base.color_format;
+ xsurf->drawable = drawable;
+
+ if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) {
+ xsurf->drawable = drawable;
+ xsurf->visual = *xconf->visual;
+
+ xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL);
+ if (!xsurf->gc) {
+ free(xsurf);
+ return NULL;
+ }
+
+ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
+ struct ximage_buffer *xbuf = &xsurf->buffers[i];
+
+ if (xdpy->use_xshm) {
+ xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info));
+ if (xbuf->shm_info) {
+ /* initialize shm info */
+ xbuf->shm_info->shmid = -1;
+ xbuf->shm_info->shmaddr = (void *) -1;
+ xbuf->shm_info->readOnly = TRUE;
+
+ xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, NULL,
+ xbuf->shm_info,
+ 0, 0);
+ }
+ }
+ else {
+ xbuf->ximage = XCreateImage(xsurf->xdpy->dpy,
+ xsurf->visual.visual,
+ xsurf->visual.depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* size */
+ 8, /* bitmap_pad */
+ 0); /* bytes_per_line */
+ }
+
+ if (!xbuf->ximage) {
+ XFreeGC(xdpy->dpy, xsurf->gc);
+ free(xsurf);
+ return NULL;
+ }
+ }
+ }
+
+ xsurf->base.destroy = ximage_surface_destroy;
+ xsurf->base.swap_buffers = ximage_surface_swap_buffers;
+ xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer;
+ xsurf->base.validate = ximage_surface_validate;
+ xsurf->base.wait = ximage_surface_wait;
+
+ return xsurf;
+}
+
+static struct native_surface *
+ximage_display_create_window_surface(struct native_display *ndpy,
+ EGLNativeWindowType win,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW,
+ (Drawable) win, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pixmap_surface(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP,
+ (Drawable) pix, nconf);
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static struct native_surface *
+ximage_display_create_pbuffer_surface(struct native_display *ndpy,
+ const struct native_config *nconf,
+ uint width, uint height)
+{
+ struct ximage_surface *xsurf;
+
+ xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER,
+ (Drawable) None, nconf);
+ if (xsurf) {
+ xsurf->width = width;
+ xsurf->height = height;
+ }
+ return (xsurf) ? &xsurf->base : NULL;
+}
+
+static enum pipe_format
+choose_format(const XVisualInfo *vinfo)
+{
+ enum pipe_format fmt;
+ /* TODO elaborate the formats */
+ switch (vinfo->depth) {
+ case 32:
+ fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ case 24:
+ fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ case 16:
+ fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ fmt = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return fmt;
+}
+
+static const struct native_config **
+ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ const struct native_config **configs;
+ int i;
+
+ /* first time */
+ if (!xdpy->configs) {
+ const XVisualInfo *visuals;
+ int num_visuals, count, j;
+
+ visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals);
+ if (!visuals)
+ return NULL;
+
+ /*
+ * Create two configs for each visual.
+ * One with depth/stencil buffer; one without
+ */
+ xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs));
+ if (!xdpy->configs)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < num_visuals; i++) {
+ for (j = 0; j < 2; j++) {
+ struct ximage_config *xconf = &xdpy->configs[count];
+ __GLcontextModes *mode = &xconf->base.mode;
+
+ xconf->visual = &visuals[i];
+ xconf->base.color_format = choose_format(xconf->visual);
+ if (xconf->base.color_format == PIPE_FORMAT_NONE)
+ continue;
+
+ x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode);
+ /* support double buffer mode */
+ mode->doubleBufferMode = TRUE;
+
+ xconf->base.depth_format = PIPE_FORMAT_NONE;
+ xconf->base.stencil_format = PIPE_FORMAT_NONE;
+ /* create the second config with depth/stencil buffer */
+ if (j == 1) {
+ xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM;
+ xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM;
+ mode->depthBits = 24;
+ mode->stencilBits = 8;
+ mode->haveDepthBuffer = TRUE;
+ mode->haveStencilBuffer = TRUE;
+ }
+
+ mode->maxPbufferWidth = 4096;
+ mode->maxPbufferHeight = 4096;
+ mode->maxPbufferPixels = 4096 * 4096;
+ mode->drawableType =
+ GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+ mode->swapMethod = GLX_SWAP_EXCHANGE_OML;
+
+ if (mode->alphaBits)
+ mode->bindToTextureRgba = TRUE;
+ else
+ mode->bindToTextureRgb = TRUE;
+
+ count++;
+ }
+ }
+
+ xdpy->num_configs = count;
+ }
+
+ configs = malloc(xdpy->num_configs * sizeof(*configs));
+ if (configs) {
+ for (i = 0; i < xdpy->num_configs; i++)
+ configs[i] = (const struct native_config *) &xdpy->configs[i];
+ if (num_configs)
+ *num_configs = xdpy->num_configs;
+ }
+ return configs;
+}
+
+static boolean
+ximage_display_is_pixmap_supported(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ const struct native_config *nconf)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+ enum pipe_format fmt;
+ uint depth;
+
+ depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix);
+ switch (depth) {
+ case 32:
+ fmt = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ case 24:
+ fmt = PIPE_FORMAT_X8R8G8B8_UNORM;
+ break;
+ case 16:
+ fmt = PIPE_FORMAT_R5G6B5_UNORM;
+ break;
+ default:
+ fmt = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return (fmt == nconf->color_format);
+}
+
+static void
+ximage_display_destroy(struct native_display *ndpy)
+{
+ struct ximage_display *xdpy = ximage_display(ndpy);
+
+ if (xdpy->configs)
+ free(xdpy->configs);
+
+ xdpy->base.screen->destroy(xdpy->base.screen);
+ free(xdpy->winsys);
+
+ x11_screen_destroy(xdpy->xscr);
+ if (xdpy->own_dpy)
+ XCloseDisplay(xdpy->dpy);
+ free(xdpy);
+}
+
+struct native_display *
+x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm)
+{
+ struct ximage_display *xdpy;
+
+ xdpy = CALLOC_STRUCT(ximage_display);
+ if (!xdpy)
+ return NULL;
+
+ xdpy->dpy = dpy;
+ if (!xdpy->dpy) {
+ xdpy->dpy = XOpenDisplay(NULL);
+ if (!xdpy->dpy) {
+ free(xdpy);
+ return NULL;
+ }
+ xdpy->own_dpy = TRUE;
+ }
+
+ xdpy->xscr_number = DefaultScreen(xdpy->dpy);
+ xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
+ if (!xdpy->xscr) {
+ free(xdpy);
+ return NULL;
+ }
+
+ xdpy->use_xshm =
+ (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM));
+
+ xdpy->winsys = create_sw_winsys();
+ xdpy->base.screen = softpipe_create_screen(xdpy->winsys);
+
+ xdpy->base.destroy = ximage_display_destroy;
+
+ xdpy->base.get_configs = ximage_display_get_configs;
+ xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported;
+ xdpy->base.create_window_surface = ximage_display_create_window_surface;
+ xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface;
+ xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface;
+
+ return &xdpy->base;
+}
diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c
new file mode 100644
index 0000000000..33328aadf2
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/sw_winsys.c
@@ -0,0 +1,231 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * Totally software-based winsys layer.
+ * Note that the one winsys function that we can't implement here
+ * is flush_frontbuffer().
+ * Whoever uses this code will have to provide that.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "util/u_simple_screen.h"
+#include "pipe/p_state.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "sw_winsys.h"
+
+
+
+/** Subclass of pipe_winsys */
+struct sw_pipe_winsys
+{
+ struct pipe_winsys Base;
+ /* no extra fields for now */
+};
+
+
+/** subclass of pipe_buffer */
+struct sw_pipe_buffer
+{
+ struct pipe_buffer Base;
+ boolean UserBuffer; /** Is this a user-space buffer? */
+ void *Data;
+ void *Mapped;
+};
+
+
+/** cast wrapper */
+static INLINE struct sw_pipe_buffer *
+sw_pipe_buffer(struct pipe_buffer *b)
+{
+ return (struct sw_pipe_buffer *) b;
+}
+
+
+static const char *
+get_name(struct pipe_winsys *pws)
+{
+ return "software";
+}
+
+
+/** Create new pipe_buffer and allocate storage of given size */
+static struct pipe_buffer *
+buffer_create(struct pipe_winsys *pws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.alignment = alignment;
+ buffer->Base.usage = usage;
+ buffer->Base.size = size;
+
+ /* align to 16-byte multiple for Cell */
+ buffer->Data = align_malloc(size, MAX2(alignment, 16));
+
+ return &buffer->Base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.size = bytes;
+ buffer->UserBuffer = TRUE;
+ buffer->Data = ptr;
+
+ return &buffer->Base;
+}
+
+
+static void *
+buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = buffer->Data;
+ return buffer->Mapped;
+}
+
+
+static void
+buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = NULL;
+}
+
+
+static void
+buffer_destroy(struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+
+ if (buffer->Data && !buffer->UserBuffer) {
+ align_free(buffer->Data);
+ buffer->Data = NULL;
+ }
+
+ free(buffer);
+}
+
+
+static struct pipe_buffer *
+surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ unsigned nblocksy;
+
+ nblocksy = util_format_get_nblocksy(format, height);
+ *stride = align(util_format_get_stride(format, width), alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ /* no-op */
+}
+
+
+static int
+fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+static int
+fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+/**
+ * Create/return a new pipe_winsys object.
+ */
+struct pipe_winsys *
+create_sw_winsys(void)
+{
+ struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
+ if (!ws)
+ return NULL;
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ ws->Base.buffer_create = buffer_create;
+ ws->Base.user_buffer_create = user_buffer_create;
+ ws->Base.buffer_map = buffer_map;
+ ws->Base.buffer_unmap = buffer_unmap;
+ ws->Base.buffer_destroy = buffer_destroy;
+
+ ws->Base.surface_buffer_create = surface_buffer_create;
+
+ ws->Base.fence_reference = fence_reference;
+ ws->Base.fence_signalled = fence_signalled;
+ ws->Base.fence_finish = fence_finish;
+
+ ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
+
+ ws->Base.get_name = get_name;
+
+ return &ws->Base;
+}
diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.h b/src/gallium/state_trackers/egl/x11/sw_winsys.h
new file mode 100644
index 0000000000..f96c5a14b0
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/sw_winsys.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef SW_WINSYS_H
+#define SW_WINSYS_H
+
+
+struct pipe_winsys;
+
+
+extern struct pipe_winsys *
+create_sw_winsys(void);
+
+
+#endif /* SW_WINSYS_H */
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c
new file mode 100644
index 0000000000..d72bfc99d3
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.c
@@ -0,0 +1,453 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <X11/Xlibint.h>
+#include <X11/extensions/XShm.h>
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "xf86drm.h"
+#include "egllog.h"
+
+#include "x11_screen.h"
+#include "dri2.h"
+#include "glxinit.h"
+
+struct x11_screen {
+ Display *dpy;
+ int number;
+
+ /*
+ * This is used to fetch GLX visuals/fbconfigs. It steals code from GLX.
+ * It might be better to rewrite the part in Xlib or XCB.
+ */
+ __GLXdisplayPrivate *glx_dpy;
+
+ int dri_major, dri_minor;
+ char *dri_driver;
+ char *dri_device;
+ int dri_fd;
+
+ XVisualInfo *visuals;
+ int num_visuals;
+
+ /* cached values for x11_drawable_get_depth */
+ Drawable last_drawable;
+ unsigned int last_depth;
+};
+
+
+/**
+ * Create a X11 screen.
+ */
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen)
+{
+ struct x11_screen *xscr;
+
+ if (screen >= ScreenCount(dpy))
+ return NULL;
+
+ xscr = CALLOC_STRUCT(x11_screen);
+ if (xscr) {
+ xscr->dpy = dpy;
+ xscr->number = screen;
+
+ xscr->dri_major = -1;
+ xscr->dri_fd = -1;
+ }
+ return xscr;
+}
+
+/**
+ * Destroy a X11 screen.
+ */
+void
+x11_screen_destroy(struct x11_screen *xscr)
+{
+ if (xscr->dri_fd >= 0)
+ close(xscr->dri_fd);
+ if (xscr->dri_driver)
+ Xfree(xscr->dri_driver);
+ if (xscr->dri_device)
+ Xfree(xscr->dri_device);
+
+ /* xscr->glx_dpy will be destroyed with the X display */
+
+ if (xscr->visuals)
+ XFree(xscr->visuals);
+ free(xscr);
+}
+
+static boolean
+x11_screen_init_dri2(struct x11_screen *xscr)
+{
+ if (xscr->dri_major < 0) {
+ int eventBase, errorBase;
+
+ if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
+ !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
+ xscr->dri_major = -1;
+ }
+ return (xscr->dri_major >= 0);
+}
+
+static boolean
+x11_screen_init_glx(struct x11_screen *xscr)
+{
+ if (!xscr->glx_dpy)
+ xscr->glx_dpy = __glXInitialize(xscr->dpy);
+ return (xscr->glx_dpy != NULL);
+}
+
+/**
+ * Return true if the screen supports the extension.
+ */
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
+{
+ boolean supported = FALSE;
+
+ switch (ext) {
+ case X11_SCREEN_EXTENSION_XSHM:
+ supported = XShmQueryExtension(xscr->dpy);
+ break;
+ case X11_SCREEN_EXTENSION_GLX:
+ supported = x11_screen_init_glx(xscr);
+ break;
+ case X11_SCREEN_EXTENSION_DRI2:
+ supported = x11_screen_init_dri2(xscr);
+ break;
+ default:
+ break;
+ }
+
+ return supported;
+}
+
+/**
+ * Return the X visuals.
+ */
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
+{
+ if (!xscr->visuals) {
+ XVisualInfo vinfo_template;
+ vinfo_template.screen = xscr->number;
+ xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
+ &vinfo_template, &xscr->num_visuals);
+ }
+
+ if (num_visuals)
+ *num_visuals = xscr->num_visuals;
+ return xscr->visuals;
+}
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode)
+{
+ int r, g, b, a;
+ int visual_type;
+
+ r = util_bitcount(visual->red_mask);
+ g = util_bitcount(visual->green_mask);
+ b = util_bitcount(visual->blue_mask);
+ a = visual->depth - (r + g + b);
+#if defined(__cplusplus) || defined(c_plusplus)
+ visual_type = visual->c_class;
+#else
+ visual_type = visual->class;
+#endif
+
+ /* convert to GLX visual type */
+ switch (visual_type) {
+ case TrueColor:
+ visual_type = GLX_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visual_type = GLX_DIRECT_COLOR;
+ break;
+ case PseudoColor:
+ visual_type = GLX_PSEUDO_COLOR;
+ break;
+ case StaticColor:
+ visual_type = GLX_STATIC_COLOR;
+ break;
+ case GrayScale:
+ visual_type = GLX_GRAY_SCALE;
+ break;
+ case StaticGray:
+ visual_type = GLX_STATIC_GRAY;
+ break;
+ default:
+ visual_type = GLX_NONE;
+ break;
+ }
+
+ mode->rgbBits = r + g + b + a;
+ mode->redBits = r;
+ mode->greenBits = g;
+ mode->blueBits = b;
+ mode->alphaBits = a;
+ mode->visualID = visual->visualid;
+ mode->visualType = visual_type;
+
+ /* sane defaults */
+ mode->renderType = GLX_RGBA_BIT;
+ mode->rgbMode = TRUE;
+ mode->visualRating = GLX_SLOW_CONFIG;
+ mode->xRenderable = TRUE;
+}
+
+/**
+ * Return the GLX fbconfigs.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].configs
+ : NULL;
+}
+
+/**
+ * Return the GLX visuals.
+ */
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr)
+{
+ return (x11_screen_init_glx(xscr))
+ ? xscr->glx_dpy->screenConfigs[xscr->number].visuals
+ : NULL;
+}
+
+static boolean
+x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
+{
+ return (strcmp(xscr->dri_driver, driver) == 0);
+}
+
+/**
+ * Probe the screen for the DRI2 driver name.
+ */
+const char *
+x11_screen_probe_dri2(struct x11_screen *xscr)
+{
+ /* get the driver name and the device name */
+ if (!xscr->dri_driver) {
+ if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
+ &xscr->dri_driver, &xscr->dri_device))
+ xscr->dri_driver = xscr->dri_device = NULL;
+ }
+
+ return xscr->dri_driver;
+}
+
+/**
+ * Enable DRI2 and returns the file descriptor of the DRM device. The file
+ * descriptor will be closed automatically when the screen is destoryed.
+ */
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
+{
+ if (xscr->dri_fd < 0) {
+ int fd;
+ drm_magic_t magic;
+
+ /* get the driver name and the device name first */
+ if (!x11_screen_probe_dri2(xscr))
+ return -1;
+
+ if (!x11_screen_is_driver_equal(xscr, driver)) {
+ _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
+ xscr->dri_driver, driver);
+ return -1;
+ }
+
+ fd = open(xscr->dri_device, O_RDWR);
+ if (fd < 0) {
+ _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
+ return -1;
+ }
+
+ memset(&magic, 0, sizeof(magic));
+ if (drmGetMagic(fd, &magic)) {
+ _eglLog(_EGL_WARNING, "failed to get magic");
+ close(fd);
+ return -1;
+ }
+
+ if (!DRI2Authenticate(xscr->dpy,
+ RootWindow(xscr->dpy, xscr->number), magic)) {
+ _eglLog(_EGL_WARNING, "failed to authenticate magic");
+ close(fd);
+ return -1;
+ }
+
+ xscr->dri_fd = fd;
+ }
+
+ return xscr->dri_fd;
+}
+
+/**
+ * Create/Destroy the DRI drawable.
+ */
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on)
+{
+ if (on)
+ DRI2CreateDrawable(xscr->dpy, drawable);
+ else
+ DRI2DestroyDrawable(xscr->dpy, drawable);
+}
+
+/**
+ * Copy between buffers of the DRI2 drawable.
+ */
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf)
+{
+ XRectangle rect;
+ XserverRegion region;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ region = XFixesCreateRegion(xscr->dpy, &rect, 1);
+ DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
+ XFixesDestroyRegion(xscr->dpy, region);
+}
+
+/**
+ * Get the buffers of the DRI2 drawable. The returned array should be freed.
+ */
+struct x11_drawable_buffer *
+x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
+ int *width, int *height, unsigned int *attachments,
+ boolean with_format, int num_ins, int *num_outs)
+{
+ DRI2Buffer *dri2bufs;
+
+ if (with_format)
+ dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+ else
+ dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
+ attachments, num_ins, num_outs);
+
+ return (struct x11_drawable_buffer *) dri2bufs;
+}
+
+/**
+ * Return the depth of a drawable.
+ *
+ * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
+ */
+uint
+x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable)
+{
+ unsigned int depth;
+
+ if (drawable != xscr->last_drawable) {
+ Window root;
+ int x, y;
+ unsigned int w, h, border;
+ Status ok;
+
+ ok = XGetGeometry(xscr->dpy, drawable, &root,
+ &x, &y, &w, &h, &border, &depth);
+ if (!ok)
+ depth = 0;
+
+ xscr->last_drawable = drawable;
+ xscr->last_depth = depth;
+ }
+ else {
+ depth = xscr->last_depth;
+ }
+
+ return depth;
+}
+
+/**
+ * Create a mode list of the given size.
+ */
+__GLcontextModes *
+x11_context_modes_create(unsigned count)
+{
+ const size_t size = sizeof(__GLcontextModes);
+ __GLcontextModes *base = NULL;
+ __GLcontextModes **next;
+ unsigned i;
+
+ next = &base;
+ for (i = 0; i < count; i++) {
+ *next = (__GLcontextModes *) calloc(1, size);
+ if (*next == NULL) {
+ x11_context_modes_destroy(base);
+ base = NULL;
+ break;
+ }
+ next = &((*next)->next);
+ }
+
+ return base;
+}
+
+/**
+ * Destroy a mode list.
+ */
+void
+x11_context_modes_destroy(__GLcontextModes *modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *next = modes->next;
+ free(modes);
+ modes = next;
+ }
+}
+
+/**
+ * Return the number of the modes in the mode list.
+ */
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes)
+{
+ const __GLcontextModes *mode;
+ int count = 0;
+ for (mode = modes; mode; mode = mode->next)
+ count++;
+ return count;
+}
diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h
new file mode 100644
index 0000000000..5432858ac3
--- /dev/null
+++ b/src/gallium/state_trackers/egl/x11/x11_screen.h
@@ -0,0 +1,105 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.8
+ *
+ * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
+ *
+ * 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 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
+ * BRIAN PAUL 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 _X11_SCREEN_H_
+#define _X11_SCREEN_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/dri2tokens.h>
+#include "pipe/p_compiler.h"
+#include "common/native.h"
+
+enum x11_screen_extension {
+ X11_SCREEN_EXTENSION_XSHM,
+ X11_SCREEN_EXTENSION_GLX,
+ X11_SCREEN_EXTENSION_DRI2,
+};
+
+/* the same as DRI2Buffer */
+struct x11_drawable_buffer {
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
+};
+
+struct x11_screen;
+
+struct x11_screen *
+x11_screen_create(Display *dpy, int screen);
+
+void
+x11_screen_destroy(struct x11_screen *xscr);
+
+boolean
+x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext);
+
+const XVisualInfo *
+x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals);
+
+void
+x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
+ __GLcontextModes *mode);
+
+const __GLcontextModes *
+x11_screen_get_glx_configs(struct x11_screen *xscr);
+
+const __GLcontextModes *
+x11_screen_get_glx_visuals(struct x11_screen *xscr);
+
+const char *
+x11_screen_probe_dri2(struct x11_screen *xscr);
+
+int
+x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);
+
+__GLcontextModes *
+x11_context_modes_create(unsigned count);
+
+void
+x11_context_modes_destroy(__GLcontextModes *modes);
+
+unsigned
+x11_context_modes_count(const __GLcontextModes *modes);
+
+void
+x11_drawable_enable_dri2(struct x11_screen *xscr,
+ Drawable drawable, boolean on);
+
+void
+x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
+ int x, int y, int width, int height,
+ int src_buf, int dst_buf);
+
+struct x11_drawable_buffer *
+x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
+ int *width, int *height, unsigned int *attachments,
+ boolean with_format, int num_ins, int *num_outs);
+
+uint
+x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable);
+
+#endif /* _X11_SCREEN_H_ */