This patch removes commit b5093063b5d76ff31519a2daf85ea32808f1afe6 and replaces it with the old 215_glx_drawable_refcounting.diff diff -uprN xorg-server-1.11.4-vanilla/glx/glxcmds.c xorg-server-1.11.4/glx/glxcmds.c --- xorg-server-1.11.4-vanilla/glx/glxcmds.c 2011-04-25 19:55:06.000000000 +0100 +++ xorg-server-1.11.4/glx/glxcmds.c 2013-03-15 19:14:15.000000000 +0000 @@ -496,6 +496,7 @@ __glXGetDrawable(__GLXcontext *glxc, GLX *error = BadAlloc; return NULL; } + pGlxDraw->refcnt++; return pGlxDraw; } @@ -1095,8 +1096,10 @@ __glXDrawableInit(__GLXdrawable *drawabl drawable->pDraw = pDraw; drawable->type = type; drawable->drawId = drawId; + drawable->otherId = 0; drawable->config = config; drawable->eventMask = 0; + drawable->refcnt = 0; return GL_TRUE; } @@ -1126,15 +1129,18 @@ DoCreateGLXDrawable(ClientPtr client, __ pGlxDraw->destroy (pGlxDraw); return BadAlloc; } + pGlxDraw->refcnt++; - /* - * Windows aren't refcounted, so track both the X and the GLX window - * so we get called regardless of destruction order. - */ - if (drawableId != glxDrawableId && type == GLX_DRAWABLE_WINDOW && - !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { - pGlxDraw->destroy (pGlxDraw); - return BadAlloc; + if (drawableId != glxDrawableId) { + /* Add the glx drawable under the XID of the underlying X drawable + * too. That way we'll get a callback in DrawableGone and can + * clean up properly when the drawable is destroyed. */ + if (!AddResource(drawableId, __glXDrawableRes, pGlxDraw)) { + pGlxDraw->destroy (pGlxDraw); + return BadAlloc; + } + pGlxDraw->refcnt++; + pGlxDraw->otherId = drawableId; } return Success; @@ -1162,8 +1168,6 @@ DoCreateGLXPixmap(ClientPtr client, __GL err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, glxDrawableId, GLX_DRAWABLE_PIXMAP); - ((PixmapPtr)pDraw)->refcnt++; - return err; } diff -uprN xorg-server-1.11.4-vanilla/glx/glxdrawable.h xorg-server-1.11.4/glx/glxdrawable.h --- xorg-server-1.11.4-vanilla/glx/glxdrawable.h 2011-04-25 19:55:06.000000000 +0100 +++ xorg-server-1.11.4/glx/glxdrawable.h 2013-03-15 19:15:44.000000000 +0000 @@ -51,8 +51,11 @@ struct __GLXdrawable { void (*waitX)(__GLXdrawable *); void (*waitGL)(__GLXdrawable *); + int refcnt; /* number of resources handles referencing this */ + DrawablePtr pDraw; XID drawId; + XID otherId; /* for glx1.3 we need to track the original Drawable as well */ /* ** Either GLX_DRAWABLE_PIXMAP, GLX_DRAWABLE_WINDOW or diff -uprN xorg-server-1.11.4-vanilla/glx/glxext.c xorg-server-1.11.4/glx/glxext.c --- xorg-server-1.11.4-vanilla/glx/glxext.c 2011-04-25 19:55:06.000000000 +0100 +++ xorg-server-1.11.4/glx/glxext.c 2013-03-15 19:18:32.000000000 +0000 @@ -118,17 +118,22 @@ static Bool DrawableGone(__GLXdrawable * { __GLXcontext *c, *next; - if (glxPriv->type == GLX_DRAWABLE_WINDOW) { - /* If this was created by glXCreateWindow, free the matching resource */ - if (glxPriv->drawId != glxPriv->pDraw->id) { - if (xid == glxPriv->drawId) - FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE); - else - FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); - } - /* otherwise this window was implicitly created by MakeCurrent */ + /* If this drawable was created using glx 1.3 drawable + * constructors, we added it as a glx drawable resource under both + * its glx drawable ID and it X drawable ID. Remove the other + * resource now so we don't a callback for freed memory. */ + if (glxPriv->otherId) { + XID other = glxPriv->otherId; + glxPriv->otherId = 0; + if (xid == other) + FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); + else + FreeResourceByType(other, __glXDrawableRes, TRUE); } + if (--glxPriv->refcnt) + return True; + for (c = glxAllContexts; c; c = next) { next = c->next; if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) { @@ -143,10 +148,6 @@ static Bool DrawableGone(__GLXdrawable * c->readPriv = NULL; } - /* drop our reference to any backing pixmap */ - if (glxPriv->type == GLX_DRAWABLE_PIXMAP) - glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr)glxPriv->pDraw); - glxPriv->destroy(glxPriv); return True;