485e329
From 69cbca0b83a86ad1ab266314e76304ca4e35f57b Mon Sep 17 00:00:00 2001
cb51bc2
From: Owen Taylor <otaylor@redhat.com>
cb51bc2
Date: Fri, 30 Apr 2010 13:17:18 -0400
da36744
Subject: [PATCH] Merge fixes for DRI drawable handling from master
cb51bc2
MIME-Version: 1.0
cb51bc2
Content-Type: text/plain; charset=UTF-8
cb51bc2
Content-Transfer-Encoding: 8bit
a54aedc
cb51bc2
commit a92b2c2c8dd1e86ee852168146f01bdf72bfe2d0
cb51bc2
Author: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Date:   Fri Apr 16 05:55:35 2010 -0400
cb51bc2
cb51bc2
glx: Drop DestroyWindow hook
cb51bc2
cb51bc2
Now that glx doesn't call DRI2DestroyDrawable anymore, we don't need to
cb51bc2
force a specific resource destruction order in the DestroyWindow hook.
cb51bc2
cb51bc2
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Reviewed-by: Michel Dänzer <michel@daenzer.net>
cb51bc2
cb51bc2
https://bugs.freedesktop.org/show_bug.cgi?id=26394
cb51bc2
Signed-off-by: Keith Packard <keithp@keithp.com>
cb51bc2
485e329
commit 2b3f755254675933475b068ff20bd322ffb8631f
cb51bc2
Author: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Date:   Thu, 29 Apr 2010 16:36:10 -0400
cb51bc2
cb51bc2
dri2: Take an XID for tracking the DRI2 drawable
cb51bc2
cb51bc2
Some pixmaps (window pixmaps and scratch pixmaps) don't have the
cb51bc2
drawable->id set and thus DRI2 gets confused when using that field
cb51bc2
for looking up the DRI2 drawable.  Go back to using privates for getting
cb51bc2
at the DRI2 drawable from a DrawablePtr.  We need to keep the resource
cb51bc2
tracking in place so we can remove the DRI2 drawable when the X resource
cb51bc2
it was created for goes away.  Additionally, we also now track the DRI2
cb51bc2
drawable using a client XID so we can reclaim the DRI2 drawable even if
cb51bc2
the client goes before the drawable and doesn't destroy the DRI2 drawable.
cb51bc2
cb51bc2
commit 1da1f33f2dd5b437dd56cd9f5d6782de4ad5a1bc
cb51bc2
Author: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Date:   Fri Apr 16 05:55:34 2010 -0400
cb51bc2
cb51bc2
DRI2: Track DRI2 drawables as resources, not privates
cb51bc2
cb51bc2
The main motivation here is to have the resource system clean up the
cb51bc2
DRI2 drawable automatically so glx doesn't have to.  Right now, the
cb51bc2
glx drawable resource must be destroyed before the X drawable, so that
cb51bc2
calling DRI2DestroyDrawable doesn't crash.  By making the DRI2
cb51bc2
drawable a resource, GLX doesn't have to worry about that and the
cb51bc2
resource destruction order becomes irrelevant.
cb51bc2
cb51bc2
https://bugs.freedesktop.org/show_bug.cgi?id=26394
cb51bc2
cb51bc2
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Signed-off-by: Keith Packard <keithp@keithp.com>
cb51bc2
cb51bc2
commit f0006aa58f6cf7552a239e169ff6e7e4fda532f4
cb51bc2
Author: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Date:   Fri Apr 16 05:55:32 2010 -0400
cb51bc2
cb51bc2
glx: Track GLX 1.3 style GLX drawables under their X drawable ID as well
cb51bc2
cb51bc2
This ensures that the DrawableGone callback gets called as necessary
cb51bc2
when the X drawable goes away.  Otherwise, using a GLX drawable
cb51bc2
(say, glXSwapBuffers) in indirect mode after the X drawable has been
cb51bc2
destroyed will crash the server.
cb51bc2
cb51bc2
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Reviewed-by: Michel Dänzer <michel@daenzer.net>
cb51bc2
Signed-off-by: Keith Packard <keithp@keithp.com>
cb51bc2
cb51bc2
commit 22da7aa9d743deee198aaf6df5d370a446db9763
cb51bc2
Author: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Date:   Fri Apr 16 05:55:33 2010 -0400
cb51bc2
cb51bc2
glx: Let the resource system destroy pixmaps
cb51bc2
cb51bc2
GLX pbuffers are implemented using a pixmap allocated by the server.
cb51bc2
With the change to DRI2 to track DRI2 drawables as resources, we need to make
cb51bc2
sure that every drawable we create a DRI2 drawable for has an XID.  By
cb51bc2
using the XID of the pbuffer, the resource system will automatically
cb51bc2
reclaim the hidden pixmap and the DRI2 drawable when the pbuffer is
cb51bc2
destroyed or the client exits.
cb51bc2
cb51bc2
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
cb51bc2
Signed-off-by: Keith Packard <keithp@keithp.com>
a54aedc
---
485e329
 glx/glxcmds.c             |   60 ++++++++-----
cb51bc2
 glx/glxdri.c              |    8 +-
cb51bc2
 glx/glxdri2.c             |   17 ++--
cb51bc2
 glx/glxdriswrast.c        |    8 +-
cb51bc2
 glx/glxext.c              |   11 +++
da36744
 glx/glxscreens.c          |   28 ------
cb51bc2
 glx/glxscreens.h          |    7 +-
485e329
 hw/xfree86/dri2/dri2.c    |  215 +++++++++++++++++++++++++++------------------
cb51bc2
 hw/xfree86/dri2/dri2.h    |    3 +-
cb51bc2
 hw/xfree86/dri2/dri2ext.c |   24 +-----
cb51bc2
 include/list.h            |    6 ++
485e329
 11 files changed, 209 insertions(+), 178 deletions(-)
a54aedc
a54aedc
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
485e329
index 77afbf4..ec3bbe6 100644
a54aedc
--- a/glx/glxcmds.c
a54aedc
+++ b/glx/glxcmds.c
a54aedc
@@ -161,7 +161,11 @@ validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
a54aedc
 	return FALSE;
a54aedc
     }
a54aedc
 
a54aedc
+    /* If the ID of the glx drawable we looked up doesn't match the id
a54aedc
+     * we looked for, it's because we looked it up under the X
a54aedc
+     * drawable ID (see DoCreateGLXDrawable). */
a54aedc
     if (rc == BadValue ||
a54aedc
+	(*drawable)->drawId != id ||
a54aedc
 	(type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
a54aedc
 	client->errorValue = id;
a54aedc
 	switch (type) {
cb51bc2
@@ -508,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
cb51bc2
     if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
cb51bc2
 	return NULL;
cb51bc2
 
cb51bc2
-    pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen,
cb51bc2
-						pDraw, GLX_DRAWABLE_WINDOW,
cb51bc2
+    pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
cb51bc2
+						pDraw, drawId,
cb51bc2
+						GLX_DRAWABLE_WINDOW,
cb51bc2
 						drawId, glxc->config);
cb51bc2
 
cb51bc2
     /* since we are creating the drawablePrivate, drawId should be new */
cb51bc2
@@ -1097,28 +1102,20 @@ __glXDrawableInit(__GLXdrawable *drawable,
a54aedc
 void
a54aedc
 __glXDrawableRelease(__GLXdrawable *drawable)
a54aedc
 {
a54aedc
-    ScreenPtr pScreen = drawable->pDraw->pScreen;
a54aedc
-
a54aedc
-    switch (drawable->type) {
a54aedc
-    case GLX_DRAWABLE_PIXMAP:
a54aedc
-    case GLX_DRAWABLE_PBUFFER:
a54aedc
-	(*pScreen->DestroyPixmap)((PixmapPtr) drawable->pDraw);
a54aedc
-	break;
a54aedc
-    }
a54aedc
 }
a54aedc
 
a54aedc
 static int 
cb51bc2
-DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
cb51bc2
-		    DrawablePtr pDraw, XID glxDrawableId, int type)
cb51bc2
+DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
cb51bc2
+		    __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
cb51bc2
+		    XID glxDrawableId, int type)
a54aedc
 {
a54aedc
     __GLXdrawable *pGlxDraw;
a54aedc
 
a54aedc
-    LEGAL_NEW_RESOURCE(glxDrawableId, client);
a54aedc
-
a54aedc
     if (pGlxScreen->pScreen != pDraw->pScreen)
a54aedc
 	return BadMatch;
a54aedc
 
cb51bc2
-    pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type,
cb51bc2
+    pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
cb51bc2
+					  drawableId, type,
cb51bc2
 					  glxDrawableId, config);
cb51bc2
     if (pGlxDraw == NULL)
cb51bc2
 	return BadAlloc;
cb51bc2
@@ -1128,6 +1125,15 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
a54aedc
 	return BadAlloc;
a54aedc
     }
a54aedc
 
a54aedc
+    /* Add the glx drawable under the XID of the underlying X drawable
a54aedc
+     * too.  That way we'll get a callback in DrawableGone and can
a54aedc
+     * clean up properly when the drawable is destroyed. */
485e329
+    if (drawableId != glxDrawableId &&
a54aedc
+	!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
a54aedc
+	pGlxDraw->destroy (pGlxDraw);
a54aedc
+	return BadAlloc;
a54aedc
+    }
a54aedc
+
a54aedc
     return Success;
a54aedc
 }
a54aedc
 
cb51bc2
@@ -1138,6 +1144,8 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
a54aedc
     DrawablePtr pDraw;
a54aedc
     int err;
a54aedc
 
a54aedc
+    LEGAL_NEW_RESOURCE(glxDrawableId, client);
a54aedc
+
a54aedc
     err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
a54aedc
     if (err != Success) {
a54aedc
 	client->errorValue = drawableId;
cb51bc2
@@ -1148,12 +1156,9 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
cb51bc2
 	return BadPixmap;
cb51bc2
     }
cb51bc2
 
cb51bc2
-    err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw,
cb51bc2
+    err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
a54aedc
 			      glxDrawableId, GLX_DRAWABLE_PIXMAP);
a54aedc
 
a54aedc
-    if (err == Success)
a54aedc
-	((PixmapPtr) pDraw)->refcnt++;
a54aedc
-
a54aedc
     return err;
a54aedc
 }
a54aedc
 
cb51bc2
@@ -1294,6 +1299,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
a54aedc
     PixmapPtr		 pPixmap;
a54aedc
     int			 err;
a54aedc
 
a54aedc
+    LEGAL_NEW_RESOURCE(glxDrawableId, client);
a54aedc
+
a54aedc
     if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
a54aedc
 	return err;
a54aedc
     if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
cb51bc2
@@ -1304,8 +1311,16 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
a54aedc
 						    width, height, config->rgbBits, 0);
a54aedc
     __glXleaveServer(GL_FALSE);
a54aedc
 
a54aedc
+    /* Assign the pixmap the same id as the pbuffer and add it as a
a54aedc
+     * resource so it and the DRI2 drawable will be reclaimed when the
a54aedc
+     * pbuffer is destroyed. */
a54aedc
+    pPixmap->drawable.id = glxDrawableId;
a54aedc
+    if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
a54aedc
+	return BadAlloc;
a54aedc
+
a54aedc
     return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
cb51bc2
-			       glxDrawableId, GLX_DRAWABLE_PBUFFER);
cb51bc2
+			       glxDrawableId, glxDrawableId,
cb51bc2
+			       GLX_DRAWABLE_PBUFFER);
a54aedc
 }
cb51bc2
 
cb51bc2
 int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
cb51bc2
@@ -1411,6 +1426,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
a54aedc
     DrawablePtr		 pDraw;
a54aedc
     int			 err;
a54aedc
 
a54aedc
+    LEGAL_NEW_RESOURCE(req->glxwindow, client);
a54aedc
+
a54aedc
     if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
a54aedc
 	return err;
a54aedc
     if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
cb51bc2
@@ -1426,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
cb51bc2
 	return err;
cb51bc2
 
cb51bc2
     return DoCreateGLXDrawable(client, pGlxScreen, config,
cb51bc2
-			       pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW);
cb51bc2
+			       pDraw, req->window,
cb51bc2
+			       req->glxwindow, GLX_DRAWABLE_WINDOW);
cb51bc2
 }
cb51bc2
 
cb51bc2
 int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
cb51bc2
diff --git a/glx/glxdri.c b/glx/glxdri.c
da36744
index 30b820c..51b602d 100644
cb51bc2
--- a/glx/glxdri.c
cb51bc2
+++ b/glx/glxdri.c
cb51bc2
@@ -682,10 +682,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
cb51bc2
 }
cb51bc2
 
cb51bc2
 static __GLXdrawable *
cb51bc2
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
+__glXDRIscreenCreateDrawable(ClientPtr client,
cb51bc2
+			     __GLXscreen *screen,
cb51bc2
 			     DrawablePtr pDraw,
cb51bc2
-			     int type,
cb51bc2
 			     XID drawId,
cb51bc2
+			     int type,
cb51bc2
+			     XID glxDrawId,
cb51bc2
 			     __GLXconfig *glxConfig)
cb51bc2
 {
cb51bc2
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
cb51bc2
@@ -699,7 +701,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
 	return NULL;
cb51bc2
 
cb51bc2
     if (!__glXDrawableInit(&private->base, screen,
cb51bc2
-			   pDraw, type, drawId, glxConfig)) {
cb51bc2
+			   pDraw, type, glxDrawId, glxConfig)) {
cb51bc2
         xfree(private);
cb51bc2
 	return NULL;
cb51bc2
     }
a54aedc
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
da36744
index bc37285..5bdeedb 100644
a54aedc
--- a/glx/glxdri2.c
a54aedc
+++ b/glx/glxdri2.c
a54aedc
@@ -105,11 +105,6 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
a54aedc
     
a54aedc
     (*core->destroyDrawable)(private->driDrawable);
a54aedc
 
a54aedc
-    /* If the X window was destroyed, the dri DestroyWindow hook will
a54aedc
-     * aready have taken care of this, so only call if pDraw isn't NULL. */
a54aedc
-    if (drawable->pDraw != NULL)
a54aedc
-	DRI2DestroyDrawable(drawable->pDraw);
a54aedc
-
a54aedc
     __glXDrawableRelease(drawable);
a54aedc
 
a54aedc
     xfree(private);
cb51bc2
@@ -435,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
cb51bc2
 }
cb51bc2
 
cb51bc2
 static __GLXdrawable *
cb51bc2
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
+__glXDRIscreenCreateDrawable(ClientPtr client,
cb51bc2
+			     __GLXscreen *screen,
cb51bc2
 			     DrawablePtr pDraw,
cb51bc2
-			     int type,
cb51bc2
 			     XID drawId,
cb51bc2
+			     int type,
cb51bc2
+			     XID glxDrawId,
cb51bc2
 			     __GLXconfig *glxConfig)
cb51bc2
 {
cb51bc2
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
cb51bc2
@@ -451,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
 
cb51bc2
     private->screen = driScreen;
cb51bc2
     if (!__glXDrawableInit(&private->base, screen,
cb51bc2
-			   pDraw, type, drawId, glxConfig)) {
cb51bc2
+			   pDraw, type, glxDrawId, glxConfig)) {
cb51bc2
         xfree(private);
cb51bc2
 	return NULL;
cb51bc2
     }
cb51bc2
@@ -462,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
     private->base.waitGL	= __glXDRIdrawableWaitGL;
cb51bc2
     private->base.waitX		= __glXDRIdrawableWaitX;
cb51bc2
 
cb51bc2
-    if (DRI2CreateDrawable(pDraw)) {
cb51bc2
+    if (DRI2CreateDrawable(client, pDraw, drawId)) {
cb51bc2
 	    xfree(private);
cb51bc2
 	    return NULL;
cb51bc2
     }
da36744
@@ -725,7 +722,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
cb51bc2
 		screen->core = (const __DRIcoreExtension *) extensions[i];
cb51bc2
 	}
cb51bc2
         if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
cb51bc2
-	    extensions[i]->version >= __DRI_DRI2_VERSION) {
cb51bc2
+	    extensions[i]->version >= 1) {
cb51bc2
 		screen->dri2 = (const __DRIdri2Extension *) extensions[i];
cb51bc2
 	}
cb51bc2
     }
cb51bc2
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
cb51bc2
index c647d83..6a34393 100644
cb51bc2
--- a/glx/glxdriswrast.c
cb51bc2
+++ b/glx/glxdriswrast.c
cb51bc2
@@ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val)
cb51bc2
 }
cb51bc2
 
cb51bc2
 static __GLXdrawable *
cb51bc2
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
+__glXDRIscreenCreateDrawable(ClientPtr client,
cb51bc2
+			     __GLXscreen *screen,
cb51bc2
 			     DrawablePtr pDraw,
cb51bc2
-			     int type,
cb51bc2
 			     XID drawId,
cb51bc2
+			     int type,
cb51bc2
+			     XID glxDrawId,
cb51bc2
 			     __GLXconfig *glxConfig)
cb51bc2
 {
cb51bc2
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
cb51bc2
@@ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
cb51bc2
 
cb51bc2
     private->screen = driScreen;
cb51bc2
     if (!__glXDrawableInit(&private->base, screen,
cb51bc2
-			   pDraw, type, drawId, glxConfig)) {
cb51bc2
+			   pDraw, type, glxDrawId, glxConfig)) {
cb51bc2
         xfree(private);
cb51bc2
 	return NULL;
cb51bc2
     }
a54aedc
diff --git a/glx/glxext.c b/glx/glxext.c
a54aedc
index 59bcfbe..89e58b0 100644
a54aedc
--- a/glx/glxext.c
a54aedc
+++ b/glx/glxext.c
a54aedc
@@ -126,6 +126,17 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
a54aedc
 {
a54aedc
     __GLXcontext *c;
a54aedc
 
a54aedc
+    /* If this drawable was created using glx 1.3 drawable
a54aedc
+     * constructors, we added it as a glx drawable resource under both
a54aedc
+     * its glx drawable ID and it X drawable ID.  Remove the other
a54aedc
+     * resource now so we don't a callback for freed memory. */
a54aedc
+    if (glxPriv->drawId != glxPriv->pDraw->id) {
a54aedc
+	if (xid == glxPriv->drawId)
a54aedc
+	    FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
a54aedc
+	else
a54aedc
+	    FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
a54aedc
+    }
a54aedc
+
a54aedc
     for (c = glxAllContexts; c; c = c->next) {
a54aedc
 	if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
a54aedc
 	    int i;
a54aedc
diff --git a/glx/glxscreens.c b/glx/glxscreens.c
da36744
index 58d8ee0..b75aea6 100644
a54aedc
--- a/glx/glxscreens.c
a54aedc
+++ b/glx/glxscreens.c
a54aedc
@@ -215,7 +215,6 @@ glxCloseScreen (int index, ScreenPtr pScreen)
a54aedc
     __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
a54aedc
 
a54aedc
     pScreen->CloseScreen = pGlxScreen->CloseScreen;
a54aedc
-    pScreen->DestroyWindow = pGlxScreen->DestroyWindow;
a54aedc
 
a54aedc
     pGlxScreen->destroy(pGlxScreen);
a54aedc
 
a54aedc
@@ -347,31 +346,6 @@ pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
a54aedc
     return best;
a54aedc
 }
a54aedc
 
a54aedc
-static Bool
a54aedc
-glxDestroyWindow(WindowPtr pWin)
a54aedc
-{
a54aedc
-    ScreenPtr pScreen = pWin->drawable.pScreen;
a54aedc
-    __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
a54aedc
-    Bool retval = TRUE;
a54aedc
-
a54aedc
-    FreeResource(pWin->drawable.id, FALSE);
a54aedc
-
a54aedc
-    /* call lower wrapped functions */
a54aedc
-    if (pGlxScreen->DestroyWindow) {
a54aedc
-	/* unwrap */
a54aedc
-	pScreen->DestroyWindow = pGlxScreen->DestroyWindow;
a54aedc
-
a54aedc
-	/* call lower layers */
a54aedc
-	retval = (*pScreen->DestroyWindow)(pWin);
a54aedc
-
a54aedc
-	/* rewrap */
a54aedc
-	pGlxScreen->DestroyWindow = pScreen->DestroyWindow;
a54aedc
-	pScreen->DestroyWindow = glxDestroyWindow;
a54aedc
-    }
a54aedc
-
a54aedc
-    return retval;
a54aedc
-}
a54aedc
-
a54aedc
 void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
a54aedc
 {
a54aedc
     __GLXconfig *m;
a54aedc
@@ -394,8 +368,6 @@ void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
a54aedc
 
a54aedc
     pGlxScreen->CloseScreen = pScreen->CloseScreen;
a54aedc
     pScreen->CloseScreen = glxCloseScreen;
a54aedc
-    pGlxScreen->DestroyWindow = pScreen->DestroyWindow;
a54aedc
-    pScreen->DestroyWindow = glxDestroyWindow;
a54aedc
 
a54aedc
     i = 0;
a54aedc
     for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
a54aedc
diff --git a/glx/glxscreens.h b/glx/glxscreens.h
cb51bc2
index bff4363..861e03c 100644
a54aedc
--- a/glx/glxscreens.h
a54aedc
+++ b/glx/glxscreens.h
cb51bc2
@@ -134,10 +134,12 @@ struct __GLXscreen {
cb51bc2
 				    __GLXconfig *modes,
cb51bc2
 				    __GLXcontext *shareContext);
cb51bc2
 
cb51bc2
-    __GLXdrawable *(*createDrawable)(__GLXscreen *context,
cb51bc2
+    __GLXdrawable *(*createDrawable)(ClientPtr client,
cb51bc2
+				     __GLXscreen *context,
cb51bc2
 				     DrawablePtr pDraw,
cb51bc2
-				     int type,
cb51bc2
 				     XID drawId,
cb51bc2
+				     int type,
cb51bc2
+				     XID glxDrawId,
cb51bc2
 				     __GLXconfig *modes);
cb51bc2
     int            (*swapInterval)  (__GLXdrawable *drawable,
cb51bc2
 				     int interval);
cb51bc2
@@ -173,7 +175,6 @@ struct __GLXscreen {
a54aedc
     /*@}*/
a54aedc
 
a54aedc
     Bool (*CloseScreen)(int index, ScreenPtr pScreen);
a54aedc
-    Bool (*DestroyWindow)(WindowPtr pWindow);
a54aedc
 };
a54aedc
 
a54aedc
 
a54aedc
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
485e329
index 2bdb733..11442d0 100644
a54aedc
--- a/hw/xfree86/dri2/dri2.c
a54aedc
+++ b/hw/xfree86/dri2/dri2.c
cb51bc2
@@ -37,6 +37,7 @@
cb51bc2
 #include <errno.h>
cb51bc2
 #include <xf86drm.h>
cb51bc2
 #include "xf86Module.h"
cb51bc2
+#include "list.h"
cb51bc2
 #include "scrnintstr.h"
cb51bc2
 #include "windowstr.h"
cb51bc2
 #include "dixstruct.h"
da36744
@@ -48,15 +49,20 @@
cb51bc2
 CARD8 dri2_major; /* version of DRI2 supported by DDX */
cb51bc2
 CARD8 dri2_minor;
a54aedc
 
a54aedc
-static int dri2ScreenPrivateKeyIndex;
a54aedc
+static int           dri2ScreenPrivateKeyIndex;
a54aedc
 static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
da36744
 static int dri2WindowPrivateKeyIndex;
da36744
 static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
da36744
 static int dri2PixmapPrivateKeyIndex;
da36744
 static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
a54aedc
+static RESTYPE       dri2DrawableRes;
a54aedc
+
a54aedc
+typedef struct _DRI2Screen *DRI2ScreenPtr;
a54aedc
 
a54aedc
 typedef struct _DRI2Drawable {
a54aedc
-    unsigned int	 refCount;
a54aedc
+    DRI2ScreenPtr        dri2_screen;
cb51bc2
+    DrawablePtr		 drawable;
cb51bc2
+    struct list		 reference_list;
a54aedc
     int			 width;
a54aedc
     int			 height;
a54aedc
     DRI2BufferPtr	*buffers;
da36744
@@ -73,9 +79,9 @@ typedef struct _DRI2Drawable {
a54aedc
     int			 swap_limit; /* for N-buffering */
a54aedc
 } DRI2DrawableRec, *DRI2DrawablePtr;
a54aedc
 
a54aedc
-typedef struct _DRI2Screen *DRI2ScreenPtr;
a54aedc
-
a54aedc
 typedef struct _DRI2Screen {
a54aedc
+    ScreenPtr			 screen;
cb51bc2
+    int				 refcnt;
a54aedc
     unsigned int		 numDrivers;
a54aedc
     const char			**driverNames;
a54aedc
     const char			*deviceName;
da36744
@@ -101,45 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen)
a54aedc
 static DRI2DrawablePtr
a54aedc
 DRI2GetDrawable(DrawablePtr pDraw)
a54aedc
 {
a54aedc
-    WindowPtr		  pWin;
a54aedc
-    PixmapPtr		  pPixmap;
da36744
+    WindowPtr pWin;
da36744
+    PixmapPtr pPixmap;
a54aedc
 
a54aedc
-    if (!pDraw)
da36744
-	return NULL;
da36744
-
a54aedc
-    if (pDraw->type == DRAWABLE_WINDOW)
a54aedc
-    {
da36744
+    if (pDraw->type == DRAWABLE_WINDOW) {
da36744
 	pWin = (WindowPtr) pDraw;
da36744
 	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
a54aedc
-    }
a54aedc
-    else
a54aedc
-    {
da36744
+    } else {
da36744
 	pPixmap = (PixmapPtr) pDraw;
da36744
 	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
da36744
     }
a54aedc
 }
a54aedc
 
cb51bc2
-int
cb51bc2
-DRI2CreateDrawable(DrawablePtr pDraw)
cb51bc2
+static DRI2DrawablePtr
cb51bc2
+DRI2AllocateDrawable(DrawablePtr pDraw)
a54aedc
 {
cb51bc2
     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
a54aedc
-    WindowPtr	    pWin;
a54aedc
-    PixmapPtr	    pPixmap;
a54aedc
     DRI2DrawablePtr pPriv;
cb51bc2
     CARD64          ust;
da36744
-
a54aedc
-    pPriv = DRI2GetDrawable(pDraw);
a54aedc
-    if (pPriv != NULL)
a54aedc
-    {
a54aedc
-	pPriv->refCount++;
a54aedc
-	return Success;
a54aedc
-    }
da36744
+    WindowPtr pWin;
da36744
+    PixmapPtr pPixmap;
da36744
 
a54aedc
     pPriv = xalloc(sizeof *pPriv);
a54aedc
     if (pPriv == NULL)
cb51bc2
-	return BadAlloc;
cb51bc2
+	return NULL;
a54aedc
 
a54aedc
-    pPriv->refCount = 1;
cb51bc2
+    pPriv->dri2_screen = ds;
cb51bc2
+    pPriv->drawable = pDraw;
a54aedc
     pPriv->width = pDraw->width;
a54aedc
     pPriv->height = pDraw->height;
a54aedc
     pPriv->buffers = NULL;
485e329
@@ -157,44 +151,131 @@ DRI2CreateDrawable(DrawablePtr pDraw)
a54aedc
     pPriv->swap_limit = 1; /* default to double buffering */
cb51bc2
     pPriv->last_swap_msc = 0;
cb51bc2
     pPriv->last_swap_ust = 0;
cb51bc2
+    list_init(&pPriv->reference_list);
a54aedc
 
a54aedc
-    if (pDraw->type == DRAWABLE_WINDOW)
a54aedc
-    {
da36744
+    if (pDraw->type == DRAWABLE_WINDOW) {
da36744
 	pWin = (WindowPtr) pDraw;
da36744
 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
a54aedc
-    }
a54aedc
-    else
a54aedc
-    {
da36744
+    } else {
da36744
 	pPixmap = (PixmapPtr) pDraw;
da36744
 	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
da36744
     }
da36744
 
cb51bc2
+    return pPriv;
cb51bc2
+}
cb51bc2
+
cb51bc2
+typedef struct DRI2DrawableRefRec {
cb51bc2
+    XID id;
cb51bc2
+    XID dri2_id;
cb51bc2
+    struct list link;
cb51bc2
+} DRI2DrawableRefRec, *DRI2DrawableRefPtr;
cb51bc2
+
cb51bc2
+static DRI2DrawableRefPtr
da36744
+DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
cb51bc2
+{
cb51bc2
+    DRI2DrawableRefPtr ref;
cb51bc2
+
cb51bc2
+    list_for_each_entry(ref, &pPriv->reference_list, link) {
da36744
+	if (ref->id == id)
cb51bc2
+	    return ref;
da36744
+    }
cb51bc2
+    
cb51bc2
+    return NULL;
cb51bc2
+}
cb51bc2
+
cb51bc2
+static int
cb51bc2
+DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id)
cb51bc2
+{
cb51bc2
+    DRI2DrawableRefPtr ref;
cb51bc2
+
cb51bc2
+    ref = malloc(sizeof *ref);
cb51bc2
+    if (ref == NULL)
cb51bc2
+	return BadAlloc;
cb51bc2
+	
cb51bc2
+    if (!AddResource(dri2_id, dri2DrawableRes, pPriv))
a54aedc
+	return BadAlloc;
da36744
+    if (!DRI2LookupDrawableRef(pPriv, id))
cb51bc2
+	if (!AddResource(id, dri2DrawableRes, pPriv))
cb51bc2
+	    return BadAlloc;
cb51bc2
+
cb51bc2
+    ref->id = id;
cb51bc2
+    ref->dri2_id = dri2_id; 
cb51bc2
+    list_add(&ref->link, &pPriv->reference_list);
da36744
+
a54aedc
     return Success;
a54aedc
 }
a54aedc
 
a54aedc
-static void
a54aedc
-DRI2FreeDrawable(DrawablePtr pDraw)
cb51bc2
+int
cb51bc2
+DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
a54aedc
 {
cb51bc2
     DRI2DrawablePtr pPriv;
a54aedc
-    WindowPtr  	    pWin;
a54aedc
-    PixmapPtr	    pPixmap;
cb51bc2
+    XID dri2_id;
cb51bc2
+    int rc;
a54aedc
 
cb51bc2
     pPriv = DRI2GetDrawable(pDraw);
cb51bc2
     if (pPriv == NULL)
a54aedc
-	return;
cb51bc2
+	pPriv = DRI2AllocateDrawable(pDraw);
cb51bc2
+    if (pPriv == NULL)
cb51bc2
+	return BadAlloc;
cb51bc2
+    
cb51bc2
+    dri2_id = FakeClientID(client->index);
cb51bc2
+    rc = DRI2AddDrawableRef(pPriv, id, dri2_id);
cb51bc2
+    if (rc != Success)
cb51bc2
+	return rc;
a54aedc
 
cb51bc2
-    xfree(pPriv);
cb51bc2
+    return Success;
cb51bc2
+}
a54aedc
 
a54aedc
-    if (pDraw->type == DRAWABLE_WINDOW)
a54aedc
-    {
cb51bc2
+static int DRI2DrawableGone(pointer p, XID id)
cb51bc2
+{
cb51bc2
+    DRI2DrawablePtr pPriv = p;
cb51bc2
+    DRI2ScreenPtr   ds = pPriv->dri2_screen;
cb51bc2
+    DRI2DrawableRefPtr ref, next;
da36744
+    WindowPtr pWin;
da36744
+    PixmapPtr pPixmap;
da36744
+    DrawablePtr pDraw;
cb51bc2
+    int i;
cb51bc2
+
cb51bc2
+    list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
cb51bc2
+	if (ref->dri2_id == id) {
cb51bc2
+	    list_del(&ref->link);
cb51bc2
+	    /* If this was the last ref under this X drawable XID,
cb51bc2
+	     * unregister the X drawable resource. */
da36744
+	    if (!DRI2LookupDrawableRef(pPriv, ref->id))
cb51bc2
+		FreeResourceByType(ref->id, dri2DrawableRes, TRUE);
485e329
+	    free(ref);
cb51bc2
+	    break;
cb51bc2
+	}
cb51bc2
+
cb51bc2
+	if (ref->id == id) {
cb51bc2
+	    list_del(&ref->link);
cb51bc2
+	    FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE);
cb51bc2
+	    free(ref);
cb51bc2
+	}
da36744
+    }
cb51bc2
+
cb51bc2
+    if (!list_is_empty(&pPriv->reference_list))
cb51bc2
+	return Success;
cb51bc2
+
da36744
+    pDraw = pPriv->drawable;
da36744
+    if (pDraw->type == DRAWABLE_WINDOW) {
da36744
 	pWin = (WindowPtr) pDraw;
da36744
 	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
da36744
-    }
da36744
-    else
da36744
-    {
da36744
+    } else {
da36744
 	pPixmap = (PixmapPtr) pDraw;
da36744
 	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
da36744
     }
cb51bc2
+
cb51bc2
+    if (pPriv->buffers != NULL) {
cb51bc2
+	for (i = 0; i < pPriv->bufferCount; i++)
da36744
+	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
cb51bc2
+
cb51bc2
+	xfree(pPriv->buffers);
da36744
+    }
cb51bc2
+
cb51bc2
+    xfree(pPriv);
cb51bc2
+
a54aedc
+    return Success;
a54aedc
 }
a54aedc
 
a54aedc
 static int
485e329
@@ -505,10 +586,6 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
a54aedc
 
cb51bc2
     pPriv->blockedClient = NULL;
cb51bc2
     pPriv->blockedOnMsc = FALSE;
cb51bc2
-
cb51bc2
-    /* If there's still a swap pending, let DRI2SwapComplete free it */
cb51bc2
-    if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
a54aedc
-	DRI2FreeDrawable(pDraw);
cb51bc2
 }
cb51bc2
 
cb51bc2
 static void
485e329
@@ -576,13 +653,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
cb51bc2
     pPriv->last_swap_ust = ust;
cb51bc2
 
cb51bc2
     DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
a54aedc
-
cb51bc2
-    /*
cb51bc2
-     * It's normal for the app to have exited with a swap outstanding, but
cb51bc2
-     * don't free the drawable until they're all complete.
cb51bc2
-     */
cb51bc2
-    if (pPriv->swapsPending == 0 && pPriv->refCount == 0)
cb51bc2
-	DRI2FreeDrawable(pDraw);
cb51bc2
 }
cb51bc2
 
cb51bc2
 Bool
485e329
@@ -750,7 +820,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
cb51bc2
     Bool ret;
cb51bc2
 
cb51bc2
     pPriv = DRI2GetDrawable(pDraw);
cb51bc2
-    if (pPriv == NULL || pPriv->refCount == 0)
cb51bc2
+    if (pPriv == NULL)
cb51bc2
 	return BadDrawable;
cb51bc2
 
cb51bc2
     /* Old DDX just completes immediately */
485e329
@@ -774,7 +844,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
cb51bc2
     DRI2DrawablePtr pPriv;
cb51bc2
 
cb51bc2
     pPriv = DRI2GetDrawable(pDraw);
cb51bc2
-    if (pPriv == NULL || pPriv->refCount == 0)
cb51bc2
+    if (pPriv == NULL)
cb51bc2
 	return BadDrawable;
cb51bc2
 
cb51bc2
     /* target_sbc == 0 means to block until all pending swaps are
485e329
@@ -800,36 +870,6 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
a54aedc
     return Success;
a54aedc
 }
a54aedc
 
a54aedc
-void
a54aedc
-DRI2DestroyDrawable(DrawablePtr pDraw)
a54aedc
-{
a54aedc
-    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
a54aedc
-    DRI2DrawablePtr pPriv;
a54aedc
-
a54aedc
-    pPriv = DRI2GetDrawable(pDraw);
a54aedc
-    if (pPriv == NULL)
a54aedc
-	return;
a54aedc
-
a54aedc
-    pPriv->refCount--;
a54aedc
-    if (pPriv->refCount > 0)
a54aedc
-	return;
a54aedc
-
a54aedc
-    if (pPriv->buffers != NULL) {
a54aedc
-	int i;
a54aedc
-
a54aedc
-	for (i = 0; i < pPriv->bufferCount; i++)
a54aedc
-	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
a54aedc
-
a54aedc
-	xfree(pPriv->buffers);
a54aedc
-    }
a54aedc
-
cb51bc2
-    /* If the window is destroyed while we have a swap or wait pending, don't
a54aedc
-     * actually free the priv yet.  We'll need it in the DRI2SwapComplete()
a54aedc
-     * callback and we'll free it there once we're done. */
cb51bc2
-    if (!pPriv->swapsPending && !pPriv->blockedClient)
a54aedc
-	DRI2FreeDrawable(pDraw);
a54aedc
-}
a54aedc
-
a54aedc
 Bool
cb51bc2
 DRI2HasSwapControl(ScreenPtr pScreen)
cb51bc2
 {
485e329
@@ -890,6 +930,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
a54aedc
     if (!ds)
a54aedc
 	return FALSE;
a54aedc
 
a54aedc
+    ds->screen         = pScreen;
a54aedc
     ds->fd	       = info->fd;
a54aedc
     ds->deviceName     = info->deviceName;
cb51bc2
     dri2_major         = 1;
485e329
@@ -961,6 +1002,8 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
a54aedc
 {
a54aedc
     static Bool setupDone = FALSE;
a54aedc
 
a54aedc
+    dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
a54aedc
+
a54aedc
     if (!setupDone)
a54aedc
     {
a54aedc
 	setupDone = TRUE;
cb51bc2
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
cb51bc2
index ce8a5df..5415a0b 100644
cb51bc2
--- a/hw/xfree86/dri2/dri2.h
cb51bc2
+++ b/hw/xfree86/dri2/dri2.h
cb51bc2
@@ -198,7 +198,8 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
cb51bc2
 
cb51bc2
 extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
cb51bc2
 
cb51bc2
-extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
cb51bc2
+extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
cb51bc2
+					DrawablePtr pDraw, XID id);
cb51bc2
 
cb51bc2
 extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
cb51bc2
 
a54aedc
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
cb51bc2
index 094d54d..58eaa10 100644
a54aedc
--- a/hw/xfree86/dri2/dri2ext.c
a54aedc
+++ b/hw/xfree86/dri2/dri2ext.c
a54aedc
@@ -51,7 +51,6 @@
a54aedc
 #include "xf86Module.h"
a54aedc
 
a54aedc
 static ExtensionEntry	*dri2Extension;
a54aedc
-static RESTYPE		 dri2DrawableRes;
a54aedc
 
a54aedc
 static Bool
a54aedc
 validDrawable(ClientPtr client, XID drawable, Mask access_mode,
cb51bc2
@@ -168,15 +167,10 @@ ProcDRI2CreateDrawable(ClientPtr client)
cb51bc2
 		       &pDrawable, &status))
cb51bc2
 	return status;
cb51bc2
 
cb51bc2
-    status = DRI2CreateDrawable(pDrawable);
cb51bc2
+    status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
a54aedc
     if (status != Success)
a54aedc
 	return status;
a54aedc
 
a54aedc
-    if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
a54aedc
-	DRI2DestroyDrawable(pDrawable);
a54aedc
-	return BadAlloc;
a54aedc
-    }
a54aedc
-
a54aedc
     return client->noClientException;
a54aedc
 }
a54aedc
 
a54aedc
@@ -192,8 +186,6 @@ ProcDRI2DestroyDrawable(ClientPtr client)
a54aedc
 		       &pDrawable, &status))
a54aedc
 	return status;
a54aedc
 
a54aedc
-    FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
a54aedc
-
a54aedc
     return client->noClientException;
a54aedc
 }
a54aedc
 
cb51bc2
@@ -627,25 +619,11 @@ SProcDRI2Dispatch (ClientPtr client)
a54aedc
     }
a54aedc
 }
a54aedc
 
a54aedc
-static int DRI2DrawableGone(pointer p, XID id)
a54aedc
-{
a54aedc
-    DrawablePtr pDrawable = p;
a54aedc
-
a54aedc
-    DRI2DestroyDrawable(pDrawable);
a54aedc
-
a54aedc
-    return Success;
a54aedc
-}
a54aedc
-
a54aedc
 int DRI2EventBase;
a54aedc
 
a54aedc
 static void
a54aedc
 DRI2ExtensionInit(void)
a54aedc
 {
a54aedc
-    dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
a54aedc
-
a54aedc
-    if (!dri2DrawableRes)
a54aedc
-	return;
a54aedc
-
a54aedc
     dri2Extension = AddExtension(DRI2_NAME,
a54aedc
 				 DRI2NumberEvents,
a54aedc
 				 DRI2NumberErrors,
cb51bc2
diff --git a/include/list.h b/include/list.h
cb51bc2
index a126a65..89dc29d 100644
cb51bc2
--- a/include/list.h
cb51bc2
+++ b/include/list.h
cb51bc2
@@ -94,4 +94,10 @@ list_is_empty(struct list *head)
cb51bc2
 	 &pos->member != (head);					\
cb51bc2
 	 pos = __container_of(pos->member.next, pos, member))
cb51bc2
 
cb51bc2
+#define list_for_each_entry_safe(pos, next, head, member)		\
cb51bc2
+    for (pos = __container_of((head)->next, pos, member),		\
cb51bc2
+	 next = __container_of(pos->member.next, pos, member);		\
cb51bc2
+	 &pos->member != (head);					\
cb51bc2
+	 pos = next, next = __container_of(next->member.next, next, member))
cb51bc2
+
cb51bc2
 #endif
a54aedc
-- 
cb51bc2
1.7.0.1
a54aedc