summaryrefslogtreecommitdiff
path: root/hw/xfree86/dri2/dri2.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2011-12-18 18:29:40 +0200
committerKeith Packard <keithp@keithp.com>2011-12-19 22:31:14 -0800
commite8fd23fad046877ca0ee08c1e147557756debc8e (patch)
tree0efcf3f5a9ca501e785d045311902d9707daa8ce /hw/xfree86/dri2/dri2.c
parent6f916ffec7767eeab62132eb6575043969104c81 (diff)
dri2: Invalidate DRI2 buffers for all windows with the same pixmap on swap
Without this, when a compositing manager unredirects a fullscreen window which uses DRI2 and page flipping, the DRI2 buffer information for the compositing manager's output window (typically the Composite Overlay Window or root window) may become stale, resulting in all kinds of hilarity. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=35452 . [Original patch by Michel Dänzer <michel@daenzer.net>] [Tree walk optimized version by Keith Packard <keithp@keithp.com>] Signed-off-by: Ville Syrjälä <syrjala@sci.fi> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'hw/xfree86/dri2/dri2.c')
-rw-r--r--hw/xfree86/dri2/dri2.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index eb84aa5f5..86e98a5e0 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -830,6 +830,19 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
return FALSE;
}
+/*
+ * A TraverseTree callback to invalidate all windows using the same
+ * pixmap
+ */
+static int
+DRI2InvalidateWalk(WindowPtr pWin, pointer data)
+{
+ if (pWin->drawable.pScreen->GetWindowPixmap(pWin) != data)
+ return WT_DONTWALKCHILDREN;
+ DRI2InvalidateDrawable(&pWin->drawable);
+ return WT_WALKCHILDREN;
+}
+
int
DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
@@ -930,7 +943,23 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
*/
*swap_target = pPriv->swap_count + pPriv->swapsPending;
- DRI2InvalidateDrawable(pDraw);
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr) pDraw;
+ PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
+
+ /*
+ * Find the top-most window using this pixmap
+ */
+ while (pWin->parent && pScreen->GetWindowPixmap(pWin->parent) == pPixmap)
+ pWin = pWin->parent;
+
+ /*
+ * Walk the sub-tree to invalidate all of the
+ * windows using the same pixmap
+ */
+ TraverseTree(pWin, DRI2InvalidateWalk, pPixmap);
+ } else
+ DRI2InvalidateDrawable(pDraw);
return Success;
}