From ce9eff9e4c30deb16f059ed84b436d37da45d5d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 20 Dec 2010 16:33:36 +0200 Subject: [PATCH 1/6] composite: Call ValidateGC after ChangeGC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChangeGC changes the GC, so ValidateGC should be called after it, not before. Also pass NullClient instead of serverClient to ChangeGC() since we know the changed values to be valid, and setting serverClient->errorValue seems pointless anyway. Signed-off-by: Ville Syrjälä Reviewed-by: Keith Packard Reviewed-by: Adam Jackson Reviewed-by: Daniel Stone --- composite/compalloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composite/compalloc.c b/composite/compalloc.c index 7164c0d3c..2b6864519 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -536,9 +536,8 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map) { ChangeGCVal val; val.val = IncludeInferiors; - + ChangeGC (NullClient, pGC, GCSubwindowMode, &val); ValidateGC(&pPixmap->drawable, pGC); - ChangeGC (serverClient, pGC, GCSubwindowMode, &val); (*pGC->ops->CopyArea) (&pParent->drawable, &pPixmap->drawable, pGC, From a6ae91746212203a19450ac955fbb7abffff1ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 20 Dec 2010 16:30:52 +0200 Subject: [PATCH 2/6] composite: Initialize borderClip with current values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ValidateTree needs a valid borderClip so initialize the parent constrained border clip with the window's current borderClip in compRedirectWindow. Signed-off-by: Ville Syrjälä Reviewed-by: Adam Jackson Reviewed-by: Daniel Stone --- composite/compalloc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/composite/compalloc.c b/composite/compalloc.c index 2b6864519..6d10b2ea0 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -170,9 +170,11 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) EnableMapUnmapEvents (pWin); } + /* Make sure our borderClip is correct for ValidateTree */ RegionNull(&cw->borderClip); - cw->borderClipX = 0; - cw->borderClipY = 0; + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; From 193ecc8b453b22b3e60248b9354c768dbd405598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 17 Dec 2010 23:46:34 +0200 Subject: [PATCH 3/6] composite: Get rid of the internal UnmapWindow+MapWindow cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ä Reviewed-by: Adam Jackson Reviewed-by: Daniel Stone --- composite/compalloc.c | 87 ++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/composite/compalloc.c b/composite/compalloc.c index 6d10b2ea0..23654a7bd 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -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); } /* From 74663e61528346aeea9c11908b6980b51dcaeb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 20 Dec 2010 16:37:24 +0200 Subject: [PATCH 4/6] composite: Copy the window contents back from the pixmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since extra expose events are no longer generated during window unredirection, the window contents must be preserved by the server. So copy the window contents back from the pixmap. The copy can only be done after the clips have been recomputed, so delay the copy and the pixmap destruction until ValidateTree is done. Window borders are restored by HandleExposures and thus don't need to be copied back. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Stone --- composite/compalloc.c | 47 ++++++++++++++++++++++++++++++++++++------ composite/compint.h | 5 ++++- composite/compwindow.c | 16 ++++++++++---- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/composite/compalloc.c b/composite/compalloc.c index 23654a7bd..37d2245d4 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -239,6 +239,34 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) return Success; } +void +compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); + int bw = (int) pWin->borderWidth; + int x = bw; + int y = bw; + int w = pWin->drawable.width; + int h = pWin->drawable.height; + + if (pGC) { + ChangeGCVal val; + val.val = IncludeInferiors; + ChangeGC (NullClient, pGC, GCSubwindowMode, &val); + ValidateGC(&pWin->drawable, pGC); + (*pGC->ops->CopyArea) (&pPixmap->drawable, + &pWin->drawable, + pGC, + x, y, w, h, 0, 0); + FreeScratchGC (pGC); + } + } +} + /* * Free one of the per-client per-window resources, clearing * redirect and the per-window pointer as appropriate @@ -246,10 +274,12 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) void compFreeClientWindow (WindowPtr pWin, XID id) { + ScreenPtr pScreen = pWin->drawable.pScreen; CompWindowPtr cw = GetCompWindow (pWin); CompClientWindowPtr ccw, *prev; Bool anyMarked = FALSE; WindowPtr pLayerWin; + PixmapPtr pPixmap = NULL; if (!cw) return; @@ -268,8 +298,10 @@ compFreeClientWindow (WindowPtr pWin, XID id) { anyMarked = compMarkWindows (pWin, &pLayerWin); - if (pWin->redirectDraw != RedirectDrawNone) - compFreePixmap (pWin); + if (pWin->redirectDraw != RedirectDrawNone) { + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap (pWin); + } if (cw->damage) DamageDestroy (cw->damage); @@ -290,6 +322,11 @@ compFreeClientWindow (WindowPtr pWin, XID id) if (anyMarked) compHandleMarkedWindows (pWin, pLayerWin); + + if (pPixmap) { + compRestoreWindow (pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } } /* @@ -621,10 +658,10 @@ compAllocPixmap (WindowPtr pWin) } void -compFreePixmap (WindowPtr pWin) +compSetParentPixmap (WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; - PixmapPtr pRedirectPixmap, pParentPixmap; + PixmapPtr pParentPixmap; CompWindowPtr cw = GetCompWindow (pWin); if (cw->damageRegistered) @@ -640,11 +677,9 @@ compFreePixmap (WindowPtr pWin) * parent exposed area; regions beyond the parent cause crashes */ RegionCopy(&pWin->borderClip, &cw->borderClip); - pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin); pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); pWin->redirectDraw = RedirectDrawNone; compSetPixmap (pWin, pParentPixmap); - (*pScreen->DestroyPixmap) (pRedirectPixmap); } /* diff --git a/composite/compint.h b/composite/compint.h index 57e0b5dea..bb5335d70 100644 --- a/composite/compint.h +++ b/composite/compint.h @@ -215,7 +215,10 @@ Bool compAllocPixmap (WindowPtr pWin); void -compFreePixmap (WindowPtr pWin); +compSetParentPixmap (WindowPtr pWin); + +void +compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap); Bool compReallocPixmap (WindowPtr pWin, int x, int y, diff --git a/composite/compwindow.c b/composite/compwindow.c index 2440f1897..bcbdf3572 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -164,8 +164,13 @@ compCheckRedirect (WindowPtr pWin) { if (should) return compAllocPixmap (pWin); - else - compFreePixmap (pWin); + else { + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap (pWin); + compRestoreWindow (pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } } return TRUE; } @@ -583,8 +588,11 @@ compDestroyWindow (WindowPtr pWin) while ((csw = GetCompSubwindows (pWin))) FreeResource (csw->clients->id, RT_NONE); - if (pWin->redirectDraw != RedirectDrawNone) - compFreePixmap (pWin); + if (pWin->redirectDraw != RedirectDrawNone) { + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap (pWin); + (*pScreen->DestroyPixmap) (pPixmap); + } ret = (*pScreen->DestroyWindow) (pWin); cs->DestroyWindow = pScreen->DestroyWindow; pScreen->DestroyWindow = compDestroyWindow; From f2001b0f6dffa0a8f05def4a86ea37c4c91db724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 13 Apr 2011 21:45:43 +0300 Subject: [PATCH 5/6] composite: Fix pWin->redirectDraw when changing between manual and automatic redirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compAllowPixmap() is not called when changing between manual and automatic redirection modes. That means pWin->redirectDraw is left with an incorrect value, and miComputeClips() gets confused whether the window is supposed to be treated as transparent or not. Fix the issue by updating pWin->redirectDraw in compCheckRedirect() even when not calling compAllocPixmap(). Signed-off-by: Ville Syrjälä --- composite/compwindow.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composite/compwindow.c b/composite/compwindow.c index bcbdf3572..d2a866d6f 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -171,6 +171,11 @@ compCheckRedirect (WindowPtr pWin) compRestoreWindow (pWin, pPixmap); (*pScreen->DestroyPixmap) (pPixmap); } + } else if (should) { + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; + else + pWin->redirectDraw = RedirectDrawManual; } return TRUE; } From eac37f32b85b631d94ee3ba11fa65b9d2cb72c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 13 Apr 2011 21:46:20 +0300 Subject: [PATCH 6/6] composite: Recompute clipping when changing between manual and automatic redirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call compMarkWindows() when changing between manual and automatic redirection modes. Otherwise the window clipping won't be recomputed correctly. Signed-off-by: Ville Syrjälä --- composite/compalloc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/composite/compalloc.c b/composite/compalloc.c index 37d2245d4..5c27631e1 100644 --- a/composite/compalloc.c +++ b/composite/compalloc.c @@ -226,6 +226,10 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) } cw->update = CompositeRedirectManual; } + else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { + if (!anyMarked) + anyMarked = compMarkWindows (pWin, &pLayerWin); + } if (!compCheckRedirect (pWin)) { @@ -314,6 +318,8 @@ compFreeClientWindow (WindowPtr pWin, XID id) else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { + anyMarked = compMarkWindows (pWin, &pLayerWin); + DamageRegister (&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; pWin->redirectDraw = RedirectDrawAutomatic;