From 82d41ada993d8cbdcdfea878d1a5b031afe4e593 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 21 Jun 2010 16:33:55 +1000 Subject: [PATCH] composite: fix freeing of old pixmap until after move/resize/cbw (bug 28345) The fixes for the composite reallocation failure, were freeing the oldpixmap straight after reallocating the new one, however this led to some wierd effects in e16 compositing, and I think in a few other places. This patch moves the freeing of the pixmap into the post wrapped stage. I'm not sure if we are actually better off breaking ABI and adding another callback from the ConfigureWindow to composite to make sure the old pixmap is always freed, but this should be satisfactory as we should always hit one of the freeing paths or else its a bug in the DIX. bug: https://bugs.freedesktop.org/show_bug.cgi?id=28435 Reported-by: Andrew Randrianasulu Signed-off-by: Dave Airlie Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- composite/compinit.c | 12 ++++++++ composite/compint.h | 17 ++++++++++- composite/compwindow.c | 68 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/composite/compinit.c b/composite/compinit.c index 1b2cd8ff6..5db9f0282 100644 --- a/composite/compinit.c +++ b/composite/compinit.c @@ -66,6 +66,9 @@ compCloseScreen (int index, ScreenPtr pScreen) pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; pScreen->ReparentWindow = cs->ReparentWindow; pScreen->ConfigNotify = cs->ConfigNotify; + pScreen->MoveWindow = cs->MoveWindow; + pScreen->ResizeWindow = cs->ResizeWindow; + pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; pScreen->ClipNotify = cs->ClipNotify; pScreen->UnrealizeWindow = cs->UnrealizeWindow; @@ -366,6 +369,15 @@ compScreenInit (ScreenPtr pScreen) cs->ConfigNotify = pScreen->ConfigNotify; pScreen->ConfigNotify = compConfigNotify; + cs->MoveWindow = pScreen->MoveWindow; + pScreen->MoveWindow = compMoveWindow; + + cs->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = compResizeWindow; + + cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; + pScreen->ChangeBorderWidth = compChangeBorderWidth; + cs->ReparentWindow = pScreen->ReparentWindow; pScreen->ReparentWindow = compReparentWindow; diff --git a/composite/compint.h b/composite/compint.h index 9c1ffd501..80083b01d 100644 --- a/composite/compint.h +++ b/composite/compint.h @@ -127,9 +127,14 @@ typedef struct _CompScreen { UnrealizeWindowProcPtr UnrealizeWindow; ClipNotifyProcPtr ClipNotify; /* - * Called from ConfigureWindow. + * Called from ConfigureWindow, these + * three track changes to the offscreen storage + * geometry */ ConfigNotifyProcPtr ConfigNotify; + MoveWindowProcPtr MoveWindow; + ResizeWindowProcPtr ResizeWindow; + ChangeBorderWidthProcPtr ChangeBorderWidth; /* * Reparenting has an effect on Subwindows redirect */ @@ -280,6 +285,16 @@ compUnrealizeWindow (WindowPtr pWin); void compClipNotify (WindowPtr pWin, int dx, int dy); +void +compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind); + +void +compResizeWindow (WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib); + +void +compChangeBorderWidth (WindowPtr pWin, unsigned int border_width); + void compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent); diff --git a/composite/compwindow.c b/composite/compwindow.c index 7d877b104..160b7644f 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -334,6 +334,65 @@ compImplicitRedirect (WindowPtr pWin, WindowPtr pParent) return FALSE; } +static void compFreeOldPixmap(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + if (pWin->redirectDraw != RedirectDrawNone) + { + CompWindowPtr cw = GetCompWindow (pWin); + if (cw->pOldPixmap) + { + (*pScreen->DestroyPixmap) (cw->pOldPixmap); + cw->pOldPixmap = NullPixmap; + } + } +} +void +compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + pScreen->MoveWindow = cs->MoveWindow; + (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); + cs->MoveWindow = pScreen->MoveWindow; + pScreen->MoveWindow = compMoveWindow; + + compFreeOldPixmap(pWin); + compCheckTree (pScreen); +} + +void +compResizeWindow (WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + pScreen->ResizeWindow = cs->ResizeWindow; + (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); + cs->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = compResizeWindow; + + compFreeOldPixmap(pWin); + compCheckTree (pWin->drawable.pScreen); +} + +void +compChangeBorderWidth (WindowPtr pWin, unsigned int bw) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + + pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; + (*pScreen->ChangeBorderWidth) (pWin, bw); + cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; + pScreen->ChangeBorderWidth = compChangeBorderWidth; + + compFreeOldPixmap(pWin); + compCheckTree (pWin->drawable.pScreen); +} + void compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent) { @@ -705,7 +764,6 @@ compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, CompScreenPtr cs = GetCompScreen (pScreen); Bool ret = 0; WindowPtr pParent = pWin->parent; - CompWindowPtr cw; int draw_x, draw_y; Bool alloc_ret; @@ -728,14 +786,6 @@ compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, draw_x = pParent->drawable.x + x + bw; draw_y = pParent->drawable.y + y + bw; alloc_ret = compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); - - cw = GetCompWindow (pWin); - if (cw->pOldPixmap) - { - (*pScreen->DestroyPixmap) (cw->pOldPixmap); - cw->pOldPixmap = NullPixmap; - } - compCheckTree (pScreen); if (alloc_ret == FALSE) return BadAlloc;