xserver: Branch 'master'

Kristian Høgsberg krh at kemper.freedesktop.org
Fri Aug 29 10:23:56 PDT 2008


 configure.ac              |   25 +-
 glx/glxcmds.c             |    1 
 glx/glxdri2.c             |  126 ++++++------
 hw/xfree86/dri2/dri2.c    |  452 +++++++++++++---------------------------------
 hw/xfree86/dri2/dri2.h    |   68 ++++--
 hw/xfree86/dri2/dri2ext.c |   86 ++++++--
 6 files changed, 310 insertions(+), 448 deletions(-)

New commits:
commit 5af77d43fe812e127d5d335527fa940ab9d95f38
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Mon Aug 11 16:59:17 2008 -0400

    DRI2: Drop sarea use, implement server side swap buffers.

diff --git a/configure.ac b/configure.ac
index 4250f80..aac6fbc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -356,7 +356,6 @@ AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes])
 AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes])
 
 DRI=no
-DRI2=no
 KDRIVE_HW=no
 dnl it would be nice to autodetect these *CONS_SUPPORTs
 case $host_os in
@@ -369,7 +368,6 @@ case $host_os in
 	AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console])
 	AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console])
 	DRI=yes
-	PKG_CHECK_EXISTS([dri2proto >= 1.1 libdrm >= 2.3.2], DRI2=yes, DRI2=no)
 	;;
   *netbsd*)
 	AC_DEFINE(CSRG_BASED, 1, [System is BSD-like])
@@ -377,7 +375,6 @@ case $host_os in
 	AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console])
 	AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console])
 	DRI=yes
-	PKG_CHECK_EXISTS([dri2proto >= 1.1 libdrm >= 2.3.2], DRI2=yes, DRI2=no)
 	;;
   *openbsd*)
 	AC_DEFINE(CSRG_BASED, 1, [System is BSD-like])
@@ -386,7 +383,6 @@ case $host_os in
 	;;
   *linux*)
 	DRI=yes
-	PKG_CHECK_EXISTS([dri2proto >= 1.1 libdrm >= 2.3.2], DRI2=yes, DRI2=no)
 	KDRIVE_HW=yes
 	;;
   *solaris*)
@@ -528,7 +524,7 @@ AC_ARG_ENABLE(xdmcp,          AS_HELP_STRING([--disable-xdmcp], [Build XDMCP ext
 AC_ARG_ENABLE(xdm-auth-1,     AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto])
 AC_ARG_ENABLE(glx,            AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes])
 AC_ARG_ENABLE(dri,            AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
-AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval])
+AC_ARG_ENABLE(dri2,           AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
 AC_ARG_ENABLE(xinerama,	      AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
 AC_ARG_ENABLE(xf86vidmode,    AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
 AC_ARG_ENABLE(xace,           AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
@@ -856,13 +852,18 @@ if test "x$DRI" = xyes; then
 	AC_SUBST(GL_CFLAGS)
 fi
 
-#AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
-#if test "x$DRI2" = xyes; then
-#	# FIXME: Bump the versions once we have releases of these.
-#	AC_DEFINE(DRI2, 1, [Build DRI2 extension])
-#	PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= 1.1])
-#	PKG_CHECK_MODULES([LIBDRM], [libdrm >= 2.3.2])
-#fi
+PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= 1.99.1],
+                  [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no])
+case "$DRI2,$HAVE_DRI2PROTO" in
+	yes,no)
+		AC_MSG_ERROR([DRI2 requested, but dri2proto not found.])
+		;;
+	yes,yes | auto,yes)
+		AC_DEFINE(DRI2, 1, [Build DRI2 extension])
+		DRI2=yes
+		;;
+esac
+AM_CONDITIONAL(DRI2, test "x$DRI2" == xyes)
 
 AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes])
 if test "x$XINERAMA" = xyes; then
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 0421026..00e5b2a 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -435,6 +435,7 @@ static void StopUsingContext(__GLXcontext *glxc)
 static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc)
 {
     glxc->isCurrent = GL_TRUE;
+    __glXLastContext = glxc;	
 }
 
 /**
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 7c1f00e..495de81 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -69,6 +69,7 @@ struct __GLXDRIscreen {
     xf86LeaveVTProc	*leaveVT;
 
     const __DRIcoreExtension *core;
+    const __DRIdri2Extension *dri2;
     const __DRIcopySubBufferExtension *copySubBuffer;
     const __DRIswapControlExtension *swapControl;
     const __DRItexBufferExtension *texBuffer;
@@ -85,6 +86,12 @@ struct __GLXDRIdrawable {
     __GLXdrawable	 base;
     __DRIdrawable	*driDrawable;
     __GLXDRIscreen	*screen;
+
+    /* Dimensions as last reported by DRI2GetBuffers. */
+    int width;
+    int height;
+    __DRIbuffer buffers[5];
+    int count;
 };
 
 static void
@@ -107,9 +114,9 @@ static GLboolean
 __glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
 {
     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-    const __DRIcoreExtension *core = private->screen->core;
 
-    (*core->swapBuffers)(private->driDrawable);
+    DRI2SwapBuffers(drawable->pDraw,
+		    0, 0, private->width, private->height);
 
     return TRUE;
 }
@@ -118,26 +125,15 @@ __glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
 static int
 __glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
 {
-    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-    const __DRIswapControlExtension *swapControl = private->screen->swapControl;
-
-    if (swapControl)
-	swapControl->setSwapInterval(private->driDrawable, interval);
-
     return 0;
 }
 
 
 static void
-__glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
+__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
 			       int x, int y, int w, int h)
 {
-    __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
-    const __DRIcopySubBufferExtension *copySubBuffer =
-	    private->screen->copySubBuffer;
-
-    if (copySubBuffer)
-	(*copySubBuffer->copySubBuffer)(private->driDrawable, x, y, w, h);
+	DRI2SwapBuffers(drawable->pDraw, x, y, w, h);
 }
 
 static void
@@ -275,7 +271,6 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
     __GLXDRIcontext *context, *shareContext;
     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
-    const __DRIcoreExtension *core = screen->core;
     __DRIcontext *driShare;
 
     shareContext = (__GLXDRIcontext *) baseShareContext;
@@ -297,8 +292,9 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
 
     context->driContext =
-	(*core->createNewContext)(screen->driScreen,
-				  config->driConfig, driShare, context);
+	(*screen->dri2->createNewContext)(screen->driScreen,
+					  config->driConfig,
+					  driShare, context);
 
     return &context->base;
 }
@@ -313,8 +309,6 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
     __GLXDRIdrawable *private;
-    GLboolean retval;
-    unsigned int handle, head;
 
     private = xalloc(sizeof *private);
     if (private == NULL)
@@ -333,42 +327,54 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
     private->base.swapBuffers   = __glXDRIdrawableSwapBuffers;
     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
 
-    retval = DRI2CreateDrawable(pDraw, &handle, &head);
+    if (DRI2CreateDrawable(pDraw)) {
+	    xfree(private);
+	    return NULL;
+    }
 
     private->driDrawable =
-	(*driScreen->core->createNewDrawable)(driScreen->driScreen, 
-					      config->driConfig,
-					      handle, head, private);
+	(*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
+					      config->driConfig, private);
 
     return &private->base;
 }
 
-static void dri2ReemitDrawableInfo(__DRIdrawable *draw, unsigned int *tail,
-				   void *loaderPrivate)
+static __DRIbuffer *
+dri2GetBuffers(__DRIdrawable *driDrawable,
+	       int *width, int *height,
+	       unsigned int *attachments, int count,
+	       int *out_count, void *loaderPrivate)
 {
-    __GLXDRIdrawable *pdraw = loaderPrivate;
+    __GLXDRIdrawable *private = loaderPrivate;
+    DRI2BufferPtr buffers;
+    int i;
 
-    DRI2ReemitDrawableInfo(pdraw->base.pDraw, tail);
-}
+    buffers = DRI2GetBuffers(private->base.pDraw,
+			     width, height, attachments, count, out_count);
+    if (*out_count > 5) {
+	*out_count = 0;
+	return NULL;
+    }
+	
+    private->width = *width;
+    private->height = *height;
+
+    /* This assumes the DRI2 buffer attachment tokens matches the
+     * __DRIbuffer tokens. */
+    for (i = 0; i < *out_count; i++) {
+	private->buffers[i].attachment = buffers[i].attachment;
+	private->buffers[i].name = buffers[i].name;
+	private->buffers[i].pitch = buffers[i].pitch;
+	private->buffers[i].cpp = buffers[i].cpp;
+	private->buffers[i].flags = buffers[i].flags;
+    }
 
-static void dri2PostDamage(__DRIdrawable *draw,
-			   struct drm_clip_rect *rects,
-			   int numRects, void *loaderPrivate)
-{ 
-    __GLXDRIdrawable *drawable = loaderPrivate;
-    DrawablePtr pDraw = drawable->base.pDraw;
-    RegionRec region;
-
-    REGION_INIT(pDraw->pScreen, &region, (BoxPtr) rects, numRects);
-    REGION_TRANSLATE(pScreen, &region, pDraw->x, pDraw->y);
-    DamageDamageRegion(pDraw, &region);
-    REGION_UNINIT(pDraw->pScreen, &region);
+    return private->buffers;
 }
 
-static const __DRIloaderExtension loaderExtension = {
-    { __DRI_LOADER, __DRI_LOADER_VERSION },
-    dri2ReemitDrawableInfo,
-    dri2PostDamage
+static const __DRIdri2LoaderExtension loaderExtension = {
+    { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
+    dri2GetBuffers,
 };
 
 static const __DRIextension *loader_extensions[] = {
@@ -416,18 +422,11 @@ initializeExtensions(__GLXDRIscreen *screen)
 
     extensions = screen->core->getExtensions(screen->driScreen);
 
-    for (i = 0; extensions[i]; i++) {
-#ifdef __DRI_COPY_SUB_BUFFER
-	if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
-	    screen->copySubBuffer =
-		(const __DRIcopySubBufferExtension *) extensions[i];
-	    __glXEnableExtension(screen->glx_enable_bits,
-				 "GLX_MESA_copy_sub_buffer");
-	    
-	    LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
-	}
-#endif
+    __glXEnableExtension(screen->glx_enable_bits,
+			 "GLX_MESA_copy_sub_buffer");
+    LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
 
+    for (i = 0; extensions[i]; i++) {
 #ifdef __DRI_SWAP_CONTROL
 	if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
 	    screen->swapControl =
@@ -461,7 +460,6 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
     char filename[128];
     size_t buffer_size;
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    unsigned int sareaHandle;
     const __DRIextension **extensions;
     const __DRIconfig **driConfigs;
     int i;
@@ -472,7 +470,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
     memset(screen, 0, sizeof *screen);
 
     if (!xf86LoaderCheckSymbol("DRI2Connect") ||
-	!DRI2Connect(pScreen, &screen->fd, &driverName, &sareaHandle)) {
+	!DRI2Connect(pScreen, &screen->fd, &driverName)) {
 	LogMessage(X_INFO,
 		   "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
 	return NULL;
@@ -508,24 +506,28 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
 	    extensions[i]->version >= __DRI_CORE_VERSION) {
 		screen->core = (const __DRIcoreExtension *) extensions[i];
 	}
+        if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
+	    extensions[i]->version >= __DRI_DRI2_VERSION) {
+		screen->dri2 = (const __DRIdri2Extension *) extensions[i];
+	}
     }
 
-    if (screen->core == NULL) {
+    if (screen->core == NULL || screen->dri2 == NULL) {
 	LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
 		   driverName);
 	goto handle_error;
     }
 
     screen->driScreen =
-	(*screen->core->createNewScreen)(pScreen->myNum,
+	(*screen->dri2->createNewScreen)(pScreen->myNum,
 					 screen->fd,
-					 sareaHandle,
 					 loader_extensions,
 					 &driConfigs,
 					 screen);
 
     if (screen->driScreen == NULL) {
-	LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed");
+	LogMessage(X_ERROR,
+		   "AIGLX error: Calling driver entry point failed\n");
 	goto handle_error;
     }
 
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index a5aef91..7bb6ac1 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2007 Red Hat, Inc.
+ * 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-
@@ -38,8 +38,6 @@
 #include "xf86Module.h"
 #include "scrnintstr.h"
 #include "windowstr.h"
-#include "region.h" 
-#include "damage.h" 
 #include "dri2.h"
 #include <GL/internal/dri_sarea.h>
 
@@ -52,29 +50,20 @@ static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
 static int dri2PixmapPrivateKeyIndex;
 static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
 
-typedef struct _DRI2DrawablePriv {
-    unsigned int		 refCount;
-    unsigned int		 boHandle;
-    unsigned int		 dri2Handle;
-} DRI2DrawablePrivRec, *DRI2DrawablePrivPtr;
+typedef struct _DRI2Drawable {
+    unsigned int	 refCount;
+    int			 width;
+    int			 height;
+    DRI2BufferPtr	 buffers;
+    int			 bufferCount;
+} DRI2DrawableRec, *DRI2DrawablePtr;
 
 typedef struct _DRI2Screen {
-    int				 fd;
-    drmBO			 sareaBO;
-    void			*sarea;
-    unsigned int		 sareaSize;
     const char			*driverName;
-    unsigned int		 nextHandle;
-
-    __DRIEventBuffer		*buffer;
-    int				 locked;
-
-    DRI2GetPixmapHandleProcPtr   getPixmapHandle;
-    DRI2BeginClipNotifyProcPtr	 beginClipNotify;
-    DRI2EndClipNotifyProcPtr	 endClipNotify;
-
-    ClipNotifyProcPtr		 ClipNotify;
-    HandleExposuresProcPtr	 HandleExposures;
+    int				 fd;
+    DRI2CreateBuffersProcPtr	 CreateBuffers;
+    DRI2DestroyBuffersProcPtr	 DestroyBuffers;
+    DRI2SwapBuffersProcPtr	 SwapBuffers;
 } DRI2ScreenRec, *DRI2ScreenPtr;
 
 static DRI2ScreenPtr
@@ -83,277 +72,145 @@ DRI2GetScreen(ScreenPtr pScreen)
     return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
 }
 
-static void *
-DRI2ScreenAllocEvent(DRI2ScreenPtr ds, size_t size)
-{
-    unsigned int *pad, mask = ds->buffer->size - 1;
-    size_t pad_size;
-    void *p;
-    
-    if ((ds->buffer->head & mask) + size > ds->buffer->size) {
-	/* The requested event size would wrap the buffer, so pad to
-	 * the end and allocate the event from the start. */
-	pad_size = ds->buffer->size - (ds->buffer->head & mask);
-	pad = (unsigned int *)
-	    (ds->buffer->data + (ds->buffer->prealloc & mask));
-	*pad = DRI2_EVENT_HEADER(DRI2_EVENT_PAD, pad_size);
-	ds->buffer->prealloc += pad_size;
-    }
-
-    p = ds->buffer->data + (ds->buffer->prealloc & mask);
-    ds->buffer->prealloc += size;
-
-    return p;
-}
-
-static void
-DRI2ScreenCommitEvents(DRI2ScreenPtr ds)
+static DRI2DrawablePtr
+DRI2GetDrawable(DrawablePtr pDraw)
 {
-    ds->buffer->head = ds->buffer->prealloc;
-}
+    WindowPtr		  pWin;
+    PixmapPtr		  pPixmap;
 
-static void
-DRI2PostDrawableConfig(DrawablePtr pDraw)
-{
-    ScreenPtr			 pScreen = pDraw->pScreen;
-    DRI2ScreenPtr		 ds = DRI2GetScreen(pScreen);
-    DRI2DrawablePrivPtr		 pPriv;
-    WindowPtr			 pWin;
-    PixmapPtr			 pPixmap;
-    BoxPtr			 pBox;
-    BoxRec			 pixmapBox;
-    int				 nBox;
-    int				 i;
-    __DRIDrawableConfigEvent	*e;
-    size_t			 size;
-
-    if (pDraw->type == DRAWABLE_WINDOW) {
+    if (pDraw->type == DRAWABLE_WINDOW)
+    {
 	pWin = (WindowPtr) pDraw;
-	pPriv = dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
-
-	nBox = REGION_NUM_RECTS(&pWin->clipList);
-	pBox = REGION_RECTS(&pWin->clipList);
-
-	pPixmap = pScreen->GetWindowPixmap(pWin);
-    } else {
-	pPixmap = (PixmapPtr) pDraw;
-	pPriv = dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
-
-	pixmapBox.x1 = 0;
-	pixmapBox.y1 = 0;
-	pixmapBox.x2 = pDraw->width;
-	pixmapBox.y2 = pDraw->height;
-	nBox = 1;
-	pBox = &pixmapBox;
+	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
     }
-
-    if (!pPriv)
-	return;
-
-    size = sizeof *e + nBox * sizeof e->rects[0];
-
-    e = DRI2ScreenAllocEvent(ds, size);
-    e->event_header = DRI2_EVENT_HEADER(DRI2_EVENT_DRAWABLE_CONFIG, size);
-    e->drawable = pPriv->dri2Handle;
-    e->x = pDraw->x - pPixmap->screen_x;
-    e->y = pDraw->y - pPixmap->screen_y;
-    e->width = pDraw->width;
-    e->height = pDraw->height;
-
-    e->num_rects = nBox;
-    for (i = 0; i < nBox; i++) {
-	e->rects[i].x1 = pBox->x1 - pPixmap->screen_x;
-	e->rects[i].y1 = pBox->y1 - pPixmap->screen_y;
-	e->rects[i].x2 = pBox->x2 - pPixmap->screen_x;
-	e->rects[i].y2 = pBox->y2 - pPixmap->screen_y;
-	pBox++;
+    else
+    {
+	pPixmap = (PixmapPtr) pDraw;
+	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
     }
 }
 
-static void
-DRI2PostBufferAttach(DrawablePtr pDraw, Bool force)
+int
+DRI2CreateDrawable(DrawablePtr pDraw)
 {
-    ScreenPtr			 pScreen = pDraw->pScreen;
-    DRI2ScreenPtr		 ds = DRI2GetScreen(pScreen);
-    DRI2DrawablePrivPtr		 pPriv;
-    WindowPtr			 pWin;
-    PixmapPtr			 pPixmap;
-    __DRIBufferAttachEvent	*e;
-    size_t			 size;
-    unsigned int		 flags;
-    unsigned int		 boHandle;
-
-    if (pDraw->type == DRAWABLE_WINDOW) {
-	pWin = (WindowPtr) pDraw;
-	pPixmap = pScreen->GetWindowPixmap(pWin);
-	pPriv = dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
-    } else {
-	pPixmap = (PixmapPtr) pDraw;
-	pPriv = dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
-    }
-
-    if (!pPriv)
-	return;
+    WindowPtr	    pWin;
+    PixmapPtr	    pPixmap;
+    DRI2DrawablePtr pPriv;
 
-    boHandle = ds->getPixmapHandle(pPixmap, &flags);
-    if (boHandle == pPriv->boHandle && !force)
-	return;
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv != NULL)
+    {
+	pPriv->refCount++;
+	return Success;
+    }
 
-    pPriv->boHandle = boHandle;
-    size = sizeof *e;
-    e = DRI2ScreenAllocEvent(ds, size);
-    e->event_header = DRI2_EVENT_HEADER(DRI2_EVENT_BUFFER_ATTACH, size);
-    e->drawable = pPriv->dri2Handle;
-    e->buffer.attachment = DRI_DRAWABLE_BUFFER_FRONT_LEFT;
-    e->buffer.handle = pPriv->boHandle;
-    e->buffer.pitch = pPixmap->devKind;
-    e->buffer.cpp = pPixmap->drawable.bitsPerPixel / 8;
-    e->buffer.flags = flags;
-}
+    pPriv = xalloc(sizeof *pPriv);
+    if (pPriv == NULL)
+	return BadAlloc;
 
-static void
-DRI2ClipNotify(WindowPtr pWin, int dx, int dy)
-{
-    ScreenPtr		pScreen = pWin->drawable.pScreen;
-    DRI2ScreenPtr	ds = DRI2GetScreen(pScreen);
+    pPriv->refCount = 1;
+    pPriv->width = pDraw->width;
+    pPriv->height = pDraw->height;
+    pPriv->buffers = NULL;
+    pPriv->bufferCount = 0;
 
-    if (!ds->locked) {
-        ds->beginClipNotify(pScreen);
-	ds->locked = 1;
+    if (pDraw->type == DRAWABLE_WINDOW)
+    {
+	pWin = (WindowPtr) pDraw;
+	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
     }
-
-    if (ds->ClipNotify) {
-	pScreen->ClipNotify = ds->ClipNotify;
-	pScreen->ClipNotify(pWin, dx, dy);
-	pScreen->ClipNotify = DRI2ClipNotify;
+    else
+    {
+	pPixmap = (PixmapPtr) pDraw;
+	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
     }
 
-    DRI2PostDrawableConfig(&pWin->drawable);
-    DRI2PostBufferAttach(&pWin->drawable, FALSE);
+    return Success;
 }
 
-static void
-DRI2HandleExposures(WindowPtr pWin)
+DRI2BufferPtr
+DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
+	       unsigned int *attachments, int count, int *out_count)
 {
-    ScreenPtr		pScreen = pWin->drawable.pScreen;
-    DRI2ScreenPtr	ds = DRI2GetScreen(pScreen);
-
-    if (ds->HandleExposures) {
-	pScreen->HandleExposures = ds->HandleExposures;
-	pScreen->HandleExposures(pWin);
-	pScreen->HandleExposures = DRI2HandleExposures;
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+    DRI2BufferPtr   buffers;
+
+    if (pPriv->buffers == NULL ||
+	pDraw->width != pPriv->width || pDraw->height != pPriv->height)
+    {
+	buffers = (*ds->CreateBuffers)(pDraw, attachments, count);
+	(*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
+	pPriv->buffers = buffers;
+	pPriv->bufferCount = count;
+	pPriv->width = pDraw->width;
+	pPriv->height = pDraw->height;
     }
 
-    DRI2ScreenCommitEvents(ds);
+    *width = pPriv->width;
+    *height = pPriv->height;
+    *out_count = pPriv->bufferCount;
 
-    if (ds->locked) {
-        ds->endClipNotify(pScreen);
-	ds->locked = 0;
-    }
+    return pPriv->buffers;
 }
 
 void
-DRI2CloseScreen(ScreenPtr pScreen)
+DRI2SwapBuffers(DrawablePtr pDraw, int x, int y, int width, int height)
 {
-    DRI2ScreenPtr	ds = DRI2GetScreen(pScreen);
-
-    pScreen->ClipNotify		= ds->ClipNotify;
-    pScreen->HandleExposures	= ds->HandleExposures;
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    DRI2BufferPtr   pSrcBuffer;
+    int		    i;
 
-    drmBOUnmap(ds->fd, &ds->sareaBO);
-    drmBOUnreference(ds->fd, &ds->sareaBO);
-
-    xfree(ds);
-    dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
-}
-
-Bool
-DRI2CreateDrawable(DrawablePtr pDraw,
-		   unsigned int *handle, unsigned int *head)
-{
-    DRI2ScreenPtr	ds = DRI2GetScreen(pDraw->pScreen);
-    WindowPtr		pWin;
-    PixmapPtr		pPixmap;
-    DRI2DrawablePrivPtr pPriv;
-    DevPrivateKey	key;
-    PrivateRec		**devPrivates;
-
-    if (pDraw->type == DRAWABLE_WINDOW) {
-	pWin = (WindowPtr) pDraw;
-	devPrivates = &pWin->devPrivates;
-	key = dri2WindowPrivateKey;
-    } else {
-	pPixmap = (PixmapPtr) pDraw;
-	devPrivates = &pPixmap->devPrivates;
-	key = dri2PixmapPrivateKey;
-    }
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return;
 
-    pPriv = dixLookupPrivate(devPrivates, key);
-    if (pPriv != NULL) {
-	pPriv->refCount++;
-    } else {
-	pPriv = xalloc(sizeof *pPriv);
-	pPriv->refCount = 1;
-	pPriv->boHandle = 0;
-	pPriv->dri2Handle = ds->nextHandle++;
-	dixSetPrivate(devPrivates, key, pPriv);
+    pSrcBuffer = NULL;
+    for (i = 0; i < pPriv->bufferCount; i++)
+    {
+	if (pPriv->buffers[i].attachment == DRI2_BUFFER_BACK_LEFT)
+	    pSrcBuffer = &pPriv->buffers[i];
     }
-
-    *handle = pPriv->dri2Handle;
-    *head = ds->buffer->head;
-
-    DRI2PostDrawableConfig(pDraw);
-    DRI2PostBufferAttach(pDraw, TRUE);
-    DRI2ScreenCommitEvents(ds);
-
-    return TRUE;
+    if (pSrcBuffer == NULL)
+	return;
+		
+    (*ds->SwapBuffers)(pDraw, pSrcBuffer, x, y, width, height);
 }
 
 void
 DRI2DestroyDrawable(DrawablePtr pDraw)
 {
-    PixmapPtr		  pPixmap;
-    WindowPtr		  pWin;
-    DRI2DrawablePrivPtr   pPriv;
-    DevPrivateKey	  key;
-    PrivateRec		**devPrivates;
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    WindowPtr  	    pWin;
+    PixmapPtr	    pPixmap;
 
-    if (pDraw->type == DRAWABLE_WINDOW) {
-	pWin = (WindowPtr) pDraw;
-	devPrivates = &pWin->devPrivates;
-	key = dri2WindowPrivateKey;
-    } else {
-	pPixmap = (PixmapPtr) pDraw;
-	devPrivates = &pPixmap->devPrivates;
-	key = dri2PixmapPrivateKey;
-    }
-
-    pPriv = dixLookupPrivate(devPrivates, key);
+    pPriv = DRI2GetDrawable(pDraw);
     if (pPriv == NULL)
 	return;
     
     pPriv->refCount--;
-    if (pPriv->refCount == 0) {
-	dixSetPrivate(devPrivates, key, NULL);
-	xfree(pPriv);
-    }
-}
-
-void
-DRI2ReemitDrawableInfo(DrawablePtr pDraw, unsigned int *head)
-{
-    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    if (pPriv->refCount > 0)
+	return;
 
-    *head = ds->buffer->head;
+    (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
+    xfree(pPriv);
 
-    DRI2PostDrawableConfig(pDraw);
-    DRI2PostBufferAttach(pDraw, TRUE);
-    DRI2ScreenCommitEvents(ds);
+    if (pDraw->type == DRAWABLE_WINDOW)
+    {
+	pWin = (WindowPtr) pDraw;
+	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+    }
+    else
+    {
+	pPixmap = (PixmapPtr) pDraw;
+	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+    }
 }
 
 Bool
-DRI2Connect(ScreenPtr pScreen, int *fd, const char **driverName,
-	    unsigned int *sareaHandle)
+DRI2Connect(ScreenPtr pScreen, int *fd, const char **driverName)
 {
     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
 
@@ -362,7 +219,6 @@ DRI2Connect(ScreenPtr pScreen, int *fd, const char **driverName,
 
     *fd = ds->fd;
     *driverName = ds->driverName;
-    *sareaHandle = ds->sareaBO.handle;
 
     return TRUE;
 }
@@ -378,86 +234,35 @@ DRI2AuthConnection(ScreenPtr pScreen, drm_magic_t magic)
     return TRUE;
 }
 
-unsigned int
-DRI2GetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags)
-{
-    DRI2ScreenPtr ds = DRI2GetScreen(pPixmap->drawable.pScreen);
-
-    return ds->getPixmapHandle(pPixmap, flags);
-}
-
-static void *
-DRI2SetupSAREA(ScreenPtr pScreen, size_t driverSareaSize)
-{
-    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-    unsigned long mask;
-    const size_t event_buffer_size = 32 * 1024;
-
-    ds->sareaSize = 
-	sizeof(*ds->buffer) + event_buffer_size +
-	driverSareaSize +
-	sizeof (unsigned int);
-
-    mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
-	DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_SHAREABLE;
-
-    if (drmBOCreate(ds->fd, ds->sareaSize, 1, NULL, mask, 0, &ds->sareaBO))
-	return NULL;
-
-    if (drmBOMap(ds->fd, &ds->sareaBO,
-		 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &ds->sarea)) {
-	drmBOUnreference(ds->fd, &ds->sareaBO);
-	return NULL;
-    }
-
-    xf86DrvMsg(pScreen->myNum, X_INFO,
-	       "[DRI2] Allocated %d byte SAREA, BO handle 0x%08x\n",
-	       ds->sareaSize, ds->sareaBO.handle);
-    memset(ds->sarea, 0, ds->sareaSize);
-
-    ds->buffer = ds->sarea;
-    ds->buffer->block_header =
-	DRI2_SAREA_BLOCK_HEADER(DRI2_SAREA_BLOCK_EVENT_BUFFER,
-				sizeof *ds->buffer + event_buffer_size);
-    ds->buffer->size = event_buffer_size;
-
-    return DRI2_SAREA_BLOCK_NEXT(ds->buffer);
-}
-
-void *
+Bool
 DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 {
     DRI2ScreenPtr ds;
-    void *p;
 
     ds = xalloc(sizeof *ds);
     if (!ds)
-	return NULL;
-
-    ds->fd			= info->fd;
-    ds->driverName		= info->driverName;
-    ds->nextHandle		= 1;
-
-    ds->getPixmapHandle		= info->getPixmapHandle;
-    ds->beginClipNotify		= info->beginClipNotify;
-    ds->endClipNotify		= info->endClipNotify;
+	return FALSE;
 
-    ds->ClipNotify		= pScreen->ClipNotify;
-    pScreen->ClipNotify		= DRI2ClipNotify;
-    ds->HandleExposures		= pScreen->HandleExposures;
-    pScreen->HandleExposures	= DRI2HandleExposures;
+    ds->fd	       = info->fd;
+    ds->driverName     = info->driverName;
+    ds->CreateBuffers  = info->CreateBuffers;
+    ds->DestroyBuffers = info->DestroyBuffers;
+    ds->SwapBuffers    = info->SwapBuffers;
 
     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
 
-    p = DRI2SetupSAREA(pScreen, info->driverSareaSize);
-    if (p == NULL) {
-	xfree(ds);
-	return NULL;
-    }
-
     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
 
-    return p;
+    return TRUE;
+}
+
+void
+DRI2CloseScreen(ScreenPtr pScreen)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+    xfree(ds);
+    dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
 }
 
 extern ExtensionModule dri2ExtensionModule;
@@ -467,10 +272,13 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
 {
     static Bool setupDone = FALSE;
 
-    if (!setupDone) {
+    if (!setupDone)
+    {
 	setupDone = TRUE;
 	LoadExtension(&dri2ExtensionModule, FALSE);
-    } else {
+    }
+    else
+    {
 	if (errmaj)
 	    *errmaj = LDR_ONCEONLY;
     }
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 85b3da4..2f4e4fe 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -33,49 +33,67 @@
 #ifndef _DRI2_H_
 #define _DRI2_H_
 
-typedef unsigned int	(*DRI2GetPixmapHandleProcPtr)(PixmapPtr p,
-						      unsigned int *flags);
-typedef void		(*DRI2BeginClipNotifyProcPtr)(ScreenPtr pScreen);
-typedef void		(*DRI2EndClipNotifyProcPtr)(ScreenPtr pScreen);
+#include <X11/extensions/dri2tokens.h>
+
+typedef struct {
+    unsigned int attachment;
+    unsigned int name;
+    unsigned int pitch;
+    unsigned int cpp;
+    unsigned int flags;
+    void *driverPrivate;
+} DRI2BufferRec, *DRI2BufferPtr;
+
+typedef DRI2BufferPtr	(*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
+						    unsigned int *attachments,
+						    int count);
+typedef void		(*DRI2DestroyBuffersProcPtr)(DrawablePtr pDraw,
+						     DRI2BufferPtr buffers,
+						     int count);
+typedef void		(*DRI2SwapBuffersProcPtr)(DrawablePtr pDraw,
+						  DRI2BufferPtr pSrcBuffer,
+						  int x,
+						  int y,
+						  int width,
+						  int height);
 
 typedef struct {
     unsigned int version;	/* Version of this struct */
     int fd;
-    size_t driverSareaSize;
     const char *driverName;
-    DRI2GetPixmapHandleProcPtr getPixmapHandle;
-    DRI2BeginClipNotifyProcPtr beginClipNotify;
-    DRI2EndClipNotifyProcPtr endClipNotify;
+
+    DRI2CreateBuffersProcPtr	CreateBuffers;
+    DRI2DestroyBuffersProcPtr	DestroyBuffers;
+    DRI2SwapBuffersProcPtr	SwapBuffers;
+
 }  DRI2InfoRec, *DRI2InfoPtr;
 
-void *DRI2ScreenInit(ScreenPtr	pScreen,
-		     DRI2InfoPtr info);
+Bool DRI2ScreenInit(ScreenPtr	pScreen,
+		    DRI2InfoPtr info);
 
 void DRI2CloseScreen(ScreenPtr pScreen);
 
 Bool DRI2Connect(ScreenPtr pScreen,
 		 int *fd,
-		 const char **driverName,
-		 unsigned int *sareaHandle);
+		 const char **driverName);
 
 Bool DRI2AuthConnection(ScreenPtr pScreen, drm_magic_t magic);
 
-unsigned int DRI2GetPixmapHandle(PixmapPtr pPixmap,
-				 unsigned int *flags);
-
-void DRI2Lock(ScreenPtr pScreen);
-void DRI2Unlock(ScreenPtr pScreen);
-
-Bool DRI2CreateDrawable(DrawablePtr pDraw,
-			unsigned int *handle,
-			unsigned int *head);
+int DRI2CreateDrawable(DrawablePtr pDraw);
 
 void DRI2DestroyDrawable(DrawablePtr pDraw);
 
-void DRI2ReemitDrawableInfo(DrawablePtr pDraw,
-			    unsigned int *head);
+DRI2BufferPtr DRI2GetBuffers(DrawablePtr pDraw,
+			     int *width,
+			     int *height,
+			     unsigned int *attachments,
+			     int count,
+			     int *out_count);
 
-Bool DRI2PostDamage(DrawablePtr pDrawable,
-		    struct drm_clip_rect *rects, int numRects);
+void DRI2SwapBuffers(DrawablePtr pDraw,
+		     int x,
+		     int y,
+		     int width,
+		     int height);
 
 #endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 8b93914..ce2290b 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -115,7 +115,6 @@ ProcDRI2Connect(ClientPtr client)
     int fd;
     const char *driverName;
     char *busId = NULL;
-    unsigned int sareaHandle;
 
     REQUEST_SIZE_MATCH(xDRI2ConnectReq);
     if (!validScreen(client, stuff->screen, &pScreen))
@@ -126,9 +125,8 @@ ProcDRI2Connect(ClientPtr client)
     rep.sequenceNumber = client->sequence;
     rep.driverNameLength = 0;
     rep.busIdLength = 0;
-    rep.sareaHandle = 0;
 
-    if (!DRI2Connect(pScreen, &fd, &driverName, &sareaHandle))
+    if (!DRI2Connect(pScreen, &fd, &driverName))
 	goto fail;
 
     busId = drmGetBusid(fd);
@@ -137,7 +135,6 @@ ProcDRI2Connect(ClientPtr client)
 
     rep.driverNameLength = strlen(driverName);
     rep.busIdLength = strlen(busId);
-    rep.sareaHandle = sareaHandle;
     rep.length = (rep.driverNameLength + 3) / 4 + (rep.busIdLength + 3) / 4;
 
  fail:
@@ -180,9 +177,7 @@ static int
 ProcDRI2CreateDrawable(ClientPtr client)
 {
     REQUEST(xDRI2CreateDrawableReq);
-    xDRI2CreateDrawableReply rep;
     DrawablePtr pDrawable;
-    unsigned int handle, head;
     int status;
 
     REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq);
@@ -190,22 +185,15 @@ ProcDRI2CreateDrawable(ClientPtr client)
     if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
 	return status;
 
-    if (!DRI2CreateDrawable(pDrawable, &handle, &head))
-	return BadMatch;
+    status = DRI2CreateDrawable(pDrawable);
+    if (status != Success)
+	return status;
 
     if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
 	DRI2DestroyDrawable(pDrawable);
 	return BadAlloc;
     }
 
-    rep.type = X_Reply;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.handle = handle;
-    rep.head = head;
-
-    WriteToClient(client, sizeof(xDRI2CreateDrawableReply), &rep);
-
     return client->noClientException;
 }
 
@@ -226,26 +214,69 @@ ProcDRI2DestroyDrawable(ClientPtr client)
 }
 
 static int
-ProcDRI2ReemitDrawableInfo(ClientPtr client)
+ProcDRI2GetBuffers(ClientPtr client)
 {
-    REQUEST(xDRI2ReemitDrawableInfoReq);
-    xDRI2ReemitDrawableInfoReply rep;
+    REQUEST(xDRI2GetBuffersReq);
+    xDRI2GetBuffersReply rep;
+    DrawablePtr pDrawable;
+    DRI2BufferPtr buffers;
+    int i, status, width, height, count;
+    unsigned int *attachments;
+    xDRI2Buffer buffer;
+
+    REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
+    if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+	return status;
+
+    attachments = (CARD32 *) &stuff[1];
+    buffers = DRI2GetBuffers(pDrawable, &width, &height,
+			     attachments, stuff->count, &count);
+
+    rep.type = X_Reply;
+    rep.length = count * sizeof(xDRI2Buffer) / 4;
+    rep.sequenceNumber = client->sequence;
+    rep.width = width;
+    rep.height = height;
+    rep.count = count;
+    WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep);
+
+    for (i = 0; i < count; i++) {
+	buffer.attachment = buffers[i].attachment;
+	buffer.name = buffers[i].name;
+	buffer.pitch = buffers[i].pitch;
+	buffer.cpp = buffers[i].cpp;
+	buffer.flags = buffers[i].flags;
+	WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
+    }
+
+    return client->noClientException;
+}
+
+static int
+ProcDRI2SwapBuffers(ClientPtr client)
+{
+    REQUEST(xDRI2SwapBuffersReq);
+    xDRI2SwapBuffersReply rep;
     DrawablePtr pDrawable;
-    unsigned int head;
     int status;
 
-    REQUEST_SIZE_MATCH(xDRI2ReemitDrawableInfoReq);
+    REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
     if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
 	return status;
 
-    DRI2ReemitDrawableInfo(pDrawable, &head);
+    /* Swap buffers need to do a round trip to make sure the X server
+     * queues the swap buffer rendering commands before the DRI client
+     * continues rendering.
+     */
+
+    DRI2SwapBuffers(pDrawable, stuff->x, stuff->y,
+		    stuff->width, stuff->height);
 
     rep.type = X_Reply;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
-    rep.head = head;
 
-    WriteToClient(client, sizeof(xDRI2ReemitDrawableInfoReply), &rep);
+    WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
 
     return client->noClientException;
 }
@@ -272,8 +303,10 @@ ProcDRI2Dispatch (ClientPtr client)
 	return ProcDRI2CreateDrawable(client);
     case X_DRI2DestroyDrawable:
 	return ProcDRI2DestroyDrawable(client);
-    case X_DRI2ReemitDrawableInfo:
-	return ProcDRI2ReemitDrawableInfo(client);
+    case X_DRI2GetBuffers:
+	return ProcDRI2GetBuffers(client);
+    case X_DRI2SwapBuffers:
+	return ProcDRI2SwapBuffers(client);
     default:
 	return BadRequest;
     }
@@ -297,7 +330,6 @@ SProcDRI2Connect(ClientPtr client)
     rep.length = 0;
     rep.driverNameLength = 0;
     rep.busIdLength = 0;
-    rep.sareaHandle = 0;
 
     return client->noClientException;
 }


More information about the xorg-commit mailing list