[PATCH xserver 1/2] present: cancel flip on reparenting

Olivier Fourdan ofourdan at redhat.com
Thu Sep 27 15:31:05 UTC 2018


If a window is reparented and the new parent already has a child
flipping, we need to cancel the flipping on the reparented window.

Install a new ReparentWindow handler in present screen with hooks in
wnmd implementation to check if the new parent has flip pending or
active in which case we cancel flip on the reparented window.

Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
---
 present/present_priv.h   |  3 +++
 present/present_scmd.c   |  1 +
 present/present_screen.c | 16 ++++++++++++++++
 present/present_wnmd.c   | 17 +++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/present/present_priv.h b/present/present_priv.h
index f62456755..668322416 100644
--- a/present/present_priv.h
+++ b/present/present_priv.h
@@ -106,6 +106,7 @@ typedef Bool (*present_priv_check_flip_ptr)(RRCrtcPtr crtc,
                                             PresentFlipReason *reason);
 typedef void (*present_priv_check_flip_window_ptr)(WindowPtr window);
 typedef Bool (*present_priv_can_window_flip_ptr)(WindowPtr window);
+typedef void (*present_priv_reparent_window_ptr)(WindowPtr pWin);
 
 typedef int (*present_priv_pixmap_ptr)(WindowPtr window,
                                        PixmapPtr pixmap,
@@ -147,6 +148,7 @@ struct present_screen_priv {
     ConfigNotifyProcPtr         ConfigNotify;
     DestroyWindowProcPtr        DestroyWindow;
     ClipNotifyProcPtr           ClipNotify;
+    ReparentWindowProcPtr       ReparentWindow;
 
     present_vblank_ptr          flip_pending;
     uint64_t                    unflip_event_id;
@@ -171,6 +173,7 @@ struct present_screen_priv {
     present_priv_check_flip_ptr         check_flip;
     present_priv_check_flip_window_ptr  check_flip_window;
     present_priv_can_window_flip_ptr    can_window_flip;
+    present_priv_reparent_window_ptr    reparent_window;
 
     present_priv_pixmap_ptr             present_pixmap;
     present_priv_create_event_id_ptr    create_event_id;
diff --git a/present/present_scmd.c b/present/present_scmd.c
index 0803a0c0b..a3ca16333 100644
--- a/present/present_scmd.c
+++ b/present/present_scmd.c
@@ -828,6 +828,7 @@ present_scmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
 
     screen_priv->abort_vblank       =   &present_scmd_abort_vblank;
     screen_priv->flip_destroy       =   &present_scmd_flip_destroy;
+    screen_priv->reparent_window    =   NULL;
 }
 
 Bool
diff --git a/present/present_screen.c b/present/present_screen.c
index c7e37c5fd..f3f2ddef9 100644
--- a/present/present_screen.c
+++ b/present/present_screen.c
@@ -207,6 +207,21 @@ present_clip_notify(WindowPtr window, int dx, int dy)
     wrap(screen_priv, screen, ClipNotify, present_clip_notify);
 }
 
+static void
+present_reparent_window(WindowPtr pWin, WindowPtr pPriorParent)
+{
+    ScreenPtr screen = pWin->drawable.pScreen;
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    if (screen_priv->reparent_window)
+        screen_priv->reparent_window(pWin);
+
+    unwrap(screen_priv, screen, ReparentWindow)
+    if (screen->ReparentWindow)
+        screen->ReparentWindow(pWin, pPriorParent);
+    wrap(screen_priv, screen, ReparentWindow, present_reparent_window);
+}
+
 static Bool
 present_screen_register_priv_keys(void)
 {
@@ -232,6 +247,7 @@ present_screen_priv_init(ScreenPtr screen)
     wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
     wrap(screen_priv, screen, ConfigNotify, present_config_notify);
     wrap(screen_priv, screen, ClipNotify, present_clip_notify);
+    wrap(screen_priv, screen, ReparentWindow, present_reparent_window);
 
     dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
 
diff --git a/present/present_wnmd.c b/present/present_wnmd.c
index 8f3836440..0c49a3507 100644
--- a/present/present_wnmd.c
+++ b/present/present_wnmd.c
@@ -682,6 +682,22 @@ present_wnmd_flush(WindowPtr window)
     (*screen_priv->wnmd_info->flush) (window);
 }
 
+static void
+present_wnmd_reparent_window(WindowPtr pWin)
+{
+    present_window_priv_ptr parent_window_priv;
+
+    parent_window_priv = present_window_priv(pWin->parent);
+    if (!parent_window_priv)
+        return;
+
+    /* If the new parent window already has a child flipping, cancel the
+     * flip on the reparented window
+     */
+    if (parent_window_priv->flip_pending || parent_window_priv->flip_active)
+        present_wnmd_cancel_flip(pWin);
+}
+
 void
 present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
 {
@@ -700,4 +716,5 @@ present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
 
     screen_priv->abort_vblank       =   &present_wnmd_abort_vblank;
     screen_priv->flip_destroy       =   &present_wnmd_flip_destroy;
+    screen_priv->reparent_window    =   &present_wnmd_reparent_window;
 }
-- 
2.19.0



More information about the xorg-devel mailing list