diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 146ea82..3b5338b 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -70,6 +70,7 @@ struct __GLXDRIscreen {
 
     const __DRIcoreExtension *core;
     const __DRIdri2Extension *dri2;
+    const __DRI2flushExtension *flush;	
     const __DRIcopySubBufferExtension *copySubBuffer;
     const __DRIswapControlExtension *swapControl;
     const __DRItexBufferExtension *texBuffer;
@@ -135,10 +136,14 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
 static GLboolean
 __glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
 {
-    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+    __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
+    __GLXDRIscreen *screen = priv->screen;
+
+    if (!DRI2SwapBuffers(drawable->pDraw))
+		return FALSE;
 
-    __glXDRIdrawableCopySubBuffer(drawable, 0, 0,
-				  private->width, private->height);
+    if (screen->flush->flushInvalidate)
+	(*screen->flush->flushInvalidate)(priv->driDrawable);
 
     return TRUE;
 }
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 580383d..23e6467 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -70,6 +70,7 @@ typedef struct _DRI2Screen {
     DRI2CreateBufferProcPtr	 CreateBuffer;
     DRI2DestroyBufferProcPtr	 DestroyBuffer;
     DRI2CopyRegionProcPtr	 CopyRegion;
+    DRI2SwapBuffersProcPtr	 SwapBuffers;	
 
     HandleExposuresProcPtr       HandleExposures;
 } DRI2ScreenRec, *DRI2ScreenPtr;
@@ -422,6 +423,49 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
     return Success;
 }
 
+Bool
+DRI2SwapBuffers(DrawablePtr pDraw)
+{
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv;
+    DRI2BufferPtr   pDestBuffer, pSrcBuffer;
+    int		    i;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	return FALSE;
+
+    pDestBuffer = NULL;
+    pSrcBuffer = NULL;
+    for (i = 0; i < pPriv->bufferCount; i++)
+    {
+	if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
+	    pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+	if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
+	    pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+    }
+    if (pSrcBuffer == NULL || pDestBuffer == NULL)
+	return FALSE;
+
+    if (ds->SwapBuffers) {
+	if ((*ds->SwapBuffers)(pDraw, pDestBuffer, pSrcBuffer))
+	    return TRUE;
+    }
+
+    BoxRec box;
+    RegionRec region;
+
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = pDraw->width;
+    box.y2 = pDraw->height;
+    REGION_INIT(drawable->pDraw->pScreen, &region, &box, 0);
+    if (DRI2CopyRegion(pDraw, &region, DRI2BufferFrontLeft, DRI2BufferBackLeft) != Success)
+	return FALSE;
+
+    return TRUE;
+}
+
 void
 DRI2DestroyDrawable(DrawablePtr pDraw)
 {
@@ -538,6 +582,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     }
     ds->CopyRegion     = info->CopyRegion;
 
+    if (info->version >= 3)
+	ds->SwapBuffers    = info->SwapBuffers;
+
     dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
 
     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index f369267..e2784dd 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -67,6 +67,10 @@ typedef void		(*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
 						 DRI2BufferPtr pDestBuffer,
 						 DRI2BufferPtr pSrcBuffer);
 
+typedef Bool		(*DRI2SwapBuffersProcPtr)(DrawablePtr pDraw,
+						  DRI2BufferPtr pFrontBuffer,
+						  DRI2BufferPtr pBackBuffer);
+
 typedef void		(*DRI2WaitProcPtr)(WindowPtr pWin,
 					   unsigned int sequence);
 
@@ -90,6 +94,7 @@ typedef struct {
     DRI2CreateBuffersProcPtr	CreateBuffers;
     DRI2DestroyBuffersProcPtr	DestroyBuffers;
     DRI2CopyRegionProcPtr	CopyRegion;
+    DRI2SwapBuffersProcPtr	SwapBuffers;	
     DRI2WaitProcPtr		Wait;
 
     /**
@@ -153,4 +158,6 @@ extern _X_EXPORT DRI2Buffer2Ptr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
 	int *width, int *height, unsigned int *attachments, int count,
 	int *out_count);
 
+extern _X_EXPORT Bool DRI2SwapBuffers(DrawablePtr pDraw);
+
 #endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 3c06174..67b419b 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -81,7 +81,7 @@ ProcDRI2QueryVersion(ClientPtr client)
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
     rep.majorVersion = 1;
-    rep.minorVersion = 1;
+    rep.minorVersion = 2;
 
     if (client->swapped) {
     	swaps(&rep.sequenceNumber, n);
@@ -323,6 +323,24 @@ ProcDRI2CopyRegion(ClientPtr client)
 }
 
 static int
+ProcDRI2SwapBuffers(ClientPtr client)
+{
+    REQUEST(xDRI2SwapBuffersReq);
+    DrawablePtr pDrawable;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
+
+    if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+	return status;
+
+    if (!DRI2SwapBuffers(pDrawable))
+	return BadAlloc;
+
+    return client->noClientException;
+}
+
+static int
 ProcDRI2Dispatch (ClientPtr client)
 {
     REQUEST(xReq);
@@ -350,6 +368,8 @@ ProcDRI2Dispatch (ClientPtr client)
 	return ProcDRI2CopyRegion(client);
     case X_DRI2GetBuffersWithFormat:
 	return ProcDRI2GetBuffersWithFormat(client);
+    case X_DRI2SwapBuffers:
+	return ProcDRI2SwapBuffers(client);	
     default:
 	return BadRequest;
     }
