composite: Get rid of the internal UnmapWindow+MapWindow cycle

Eliminate the internal MapWindow+UnmapWindow cycle around window
redirection changes. Instead do the work in a single pass by marking
the afected windows and calling ValidateTree and HandleExposures
directly. This gets rid of unnecessary expose events, and invalid
ClipNotify calls during rediredction changes. Now ClipNotify will only
get called with the final clip values, and expose events are only sent
to areas that actually got exposed.

Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Daniel Stone <daniel@fooishbar.org>
This commit is contained in:
Ville Syrjälä 2010-12-17 23:46:34 +02:00
parent a6ae917462
commit 193ecc8b45
1 changed files with 45 additions and 42 deletions

View File

@ -104,6 +104,35 @@ compDestroyDamage (DamagePtr pDamage, void *closure)
cw->damage = 0;
}
static Bool
compMarkWindows(WindowPtr pWin,
WindowPtr *ppLayerWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
WindowPtr pLayerWin = pWin;
if (!pWin->viewable)
return FALSE;
(*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
(*pScreen->MarkWindow)(pLayerWin->parent);
*ppLayerWin = pLayerWin;
return TRUE;
}
static void
compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
(*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
(*pScreen->HandleExposures)(pLayerWin->parent);
if (pScreen->PostValidateTree)
(*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
}
/*
* Redirect one window for one client
*/
@ -112,8 +141,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
{
CompWindowPtr cw = GetCompWindow (pWin);
CompClientWindowPtr ccw;
Bool wasMapped = pWin->mapped;
CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
WindowPtr pLayerWin;
Bool anyMarked = FALSE;
if (pWin == cs->pOverlayWin) {
return Success;
@ -163,12 +193,8 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
free(cw);
return BadAlloc;
}
if (wasMapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
anyMarked = compMarkWindows (pWin, &pLayerWin);
/* Make sure our borderClip is correct for ValidateTree */
RegionNull(&cw->borderClip);
@ -190,16 +216,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
return BadAlloc;
if (ccw->update == CompositeRedirectManual)
{
/* If the window was CompositeRedirectAutomatic, then
* unmap the window so that the parent clip list will
* be correctly recomputed.
*/
if (pWin->mapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
if (!anyMarked)
anyMarked = compMarkWindows (pWin, &pLayerWin);
if (cw->damageRegistered)
{
DamageUnregister (&pWin->drawable, cw->damage);
@ -213,15 +232,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
FreeResource (ccw->id, RT_NONE);
return BadAlloc;
}
if (wasMapped && !pWin->mapped)
{
Bool overrideRedirect = pWin->overrideRedirect;
pWin->overrideRedirect = TRUE;
DisableMapUnmapEvents (pWin);
MapWindow (pWin, pClient);
EnableMapUnmapEvents (pWin);
pWin->overrideRedirect = overrideRedirect;
}
if (anyMarked)
compHandleMarkedWindows (pWin, pLayerWin);
return Success;
}
@ -235,7 +248,8 @@ compFreeClientWindow (WindowPtr pWin, XID id)
{
CompWindowPtr cw = GetCompWindow (pWin);
CompClientWindowPtr ccw, *prev;
Bool wasMapped = pWin->mapped;
Bool anyMarked = FALSE;
WindowPtr pLayerWin;
if (!cw)
return;
@ -252,12 +266,7 @@ compFreeClientWindow (WindowPtr pWin, XID id)
}
if (!cw->clients)
{
if (wasMapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
anyMarked = compMarkWindows (pWin, &pLayerWin);
if (pWin->redirectDraw != RedirectDrawNone)
compFreePixmap (pWin);
@ -278,15 +287,9 @@ compFreeClientWindow (WindowPtr pWin, XID id)
pWin->redirectDraw = RedirectDrawAutomatic;
DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
}
if (wasMapped && !pWin->mapped)
{
Bool overrideRedirect = pWin->overrideRedirect;
pWin->overrideRedirect = TRUE;
DisableMapUnmapEvents (pWin);
MapWindow (pWin, clients[CLIENT_ID(id)]);
EnableMapUnmapEvents (pWin);
pWin->overrideRedirect = overrideRedirect;
}
if (anyMarked)
compHandleMarkedWindows (pWin, pLayerWin);
}
/*