summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-01-25 09:21:51 -0800
committerKeith Packard <keithp@keithp.com>2010-01-27 14:35:18 -0800
commit711e26466ae04ae93ff4c48d377d83d68a6320e9 (patch)
tree2df99669c3474436d16904e631ab525929948feb
parentb68f0204a2e4fa9d8884cbdd84b6a5df21d6b36e (diff)
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>
-rw-r--r--hw/xfree86/dri2/dri2.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 3d0fa75ec..587a9285a 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -158,6 +158,31 @@ DRI2CreateDrawable(DrawablePtr pDraw)
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
find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
{
@@ -508,7 +533,7 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
if (pPriv->refCount == 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[DRI2] %s: bad drawable refcount\n", __func__);
- xfree(pPriv);
+ DRI2FreeDrawable(pDraw);
return;
}
@@ -729,8 +754,6 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
{
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv;
- WindowPtr pWin;
- PixmapPtr pPixmap;
pPriv = DRI2GetDrawable(pDraw);
if (pPriv == NULL)
@@ -753,18 +776,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
* actually free the priv yet. We'll need it in the DRI2SwapComplete()
* callback and we'll free it there once we're done. */
if (!pPriv->swapsPending)
- xfree(pPriv);
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
- }
+ DRI2FreeDrawable(pDraw);
}
Bool