DRI2: handle drawable destruction properly at DRI2SwapComplete time

Simon reported an issue with kwin that turned out to be a general problem.  If
a drawable goes away before its swap completes, we'll try to free it up.
However, we free it improperly, which causes a server crash in
DRI2DestroyDrawable.  Fix that up by splitting the free code out and calling
it from DRI2SwapComplete.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Michel Dänzer <michel@daenzer.net>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Jesse Barnes 2010-01-25 09:21:51 -08:00 committed by Keith Packard
parent b68f0204a2
commit 711e26466a

View File

@ -158,6 +158,31 @@ DRI2CreateDrawable(DrawablePtr pDraw)
return Success; return Success;
} }
static void
DRI2FreeDrawable(DrawablePtr pDraw)
{
DRI2DrawablePtr pPriv;
WindowPtr pWin;
PixmapPtr pPixmap;
pPriv = DRI2GetDrawable(pDraw);
if (pPriv == NULL)
return;
xfree(pPriv);
if (pDraw->type == DRAWABLE_WINDOW)
{
pWin = (WindowPtr) pDraw;
dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
}
else
{
pPixmap = (PixmapPtr) pDraw;
dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
}
}
static int static int
find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
{ {
@ -508,7 +533,7 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
if (pPriv->refCount == 0) { if (pPriv->refCount == 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, xf86DrvMsg(pScreen->myNum, X_ERROR,
"[DRI2] %s: bad drawable refcount\n", __func__); "[DRI2] %s: bad drawable refcount\n", __func__);
xfree(pPriv); DRI2FreeDrawable(pDraw);
return; return;
} }
@ -729,8 +754,6 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
{ {
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv; DRI2DrawablePtr pPriv;
WindowPtr pWin;
PixmapPtr pPixmap;
pPriv = DRI2GetDrawable(pDraw); pPriv = DRI2GetDrawable(pDraw);
if (pPriv == NULL) if (pPriv == NULL)
@ -753,18 +776,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
* actually free the priv yet. We'll need it in the DRI2SwapComplete() * actually free the priv yet. We'll need it in the DRI2SwapComplete()
* callback and we'll free it there once we're done. */ * callback and we'll free it there once we're done. */
if (!pPriv->swapsPending) if (!pPriv->swapsPending)
xfree(pPriv); DRI2FreeDrawable(pDraw);
if (pDraw->type == DRAWABLE_WINDOW)
{
pWin = (WindowPtr) pDraw;
dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
}
else
{
pPixmap = (PixmapPtr) pDraw;
dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
}
} }
Bool Bool