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 <randrik@mail.ru>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Dave Airlie 2010-06-21 16:33:55 +10:00 committed by Keith Packard
parent c6bc52cb66
commit 82d41ada99
3 changed files with 87 additions and 10 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;