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

2018-09-27 Thread Olivier Fourdan
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 
---
 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;
 DestroyWindowProcPtrDestroyWindow;
 ClipNotifyProcPtr   ClipNotify;
+ReparentWindowProcPtr   ReparentWindow;
 
 present_vblank_ptr  flip_pending;
 uint64_tunflip_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_ptrcan_window_flip;
+present_priv_reparent_window_ptrreparent_window;
 
 present_priv_pixmap_ptr present_pixmap;
 present_priv_create_event_id_ptrcreate_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

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH xserver 2/2] xwayland: update Xwayland present window on reparent

2018-09-27 Thread Olivier Fourdan
When reparenting a window, the Xwayland present window either on the
prior parent or on the new parent may need to be updated:

1. If the window is flipping, clear the present window on its old
   parent.
2. If the new parent has no flipping already, set its flipping window to
   the reparented window.

Install new ReparentWindow hooks in Xwayland to handle those cases.

Signed-off-by: Olivier Fourdan 
---
 hw/xwayland/xwayland-present.c | 16 
 hw/xwayland/xwayland.c | 23 +++
 hw/xwayland/xwayland.h |  2 ++
 3 files changed, 41 insertions(+)

diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 316e04443..f54fe2ac4 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -558,3 +558,19 @@ xwl_present_init(ScreenPtr screen)
 
 return present_wnmd_screen_init(screen, &xwl_present_info);
 }
+
+void
+xwl_present_reparent_window(WindowPtr pWin, WindowPtr pPriorParent)
+{
+struct xwl_window *xwl_window;
+
+/* If the window is flipping, clear the present window on its old parent */
+xwl_window = xwl_window_from_window(pPriorParent);
+if (xwl_present_is_flipping(pWin, xwl_window))
+xwl_window->present_window = NULL;
+
+/* If the new parent window has no child flipping, update its 
present_window */
+xwl_window = xwl_window_from_window(pWin->parent);
+if (xwl_window && xwl_window->present_window == NULL)
+xwl_window->present_window = pWin;
+}
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 96b4db18c..345b62f59 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -660,6 +660,26 @@ xwl_destroy_window(WindowPtr window)
 return ret;
 }
 
+static void
+xwl_reparent_window(WindowPtr pWin, WindowPtr pPriorParent)
+{
+ScreenPtr screen = pWin->drawable.pScreen;
+struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+#ifdef GLAMOR_HAS_GBM
+if (xwl_screen->present)
+xwl_present_reparent_window(pWin, pPriorParent);
+#endif
+
+/* Chain up with previous ReparentWindow, if any */
+if (xwl_screen->ReparentWindow) {
+screen->ReparentWindow = xwl_screen->ReparentWindow;
+(*screen->ReparentWindow) (pWin, pPriorParent);
+xwl_screen->ReparentWindow = screen->ReparentWindow;
+screen->ReparentWindow = xwl_reparent_window;
+}
+}
+
 static void
 xwl_window_post_damage(struct xwl_window *xwl_window)
 {
@@ -1109,6 +1129,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
 xwl_screen->CloseScreen = pScreen->CloseScreen;
 pScreen->CloseScreen = xwl_close_screen;
 
+xwl_screen->ReparentWindow = pScreen->ReparentWindow;
+pScreen->ReparentWindow = xwl_reparent_window;
+
 pScreen->CursorWarpedTo = xwl_cursor_warped_to;
 pScreen->CursorConfinedTo = xwl_cursor_confined_to;
 
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 67819e178..a7c7f2aee 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -132,6 +132,7 @@ struct xwl_screen {
 RealizeWindowProcPtr RealizeWindow;
 UnrealizeWindowProcPtr UnrealizeWindow;
 DestroyWindowProcPtr DestroyWindow;
+ReparentWindowProcPtr ReparentWindow;
 XYToWindowProcPtr XYToWindow;
 
 struct xorg_list output_list;
@@ -451,6 +452,7 @@ void xwl_glamor_egl_make_current(struct xwl_screen 
*xwl_screen);
 #ifdef GLAMOR_HAS_GBM
 Bool xwl_present_init(ScreenPtr screen);
 void xwl_present_cleanup(WindowPtr window);
+void xwl_present_reparent_window(WindowPtr pWin, WindowPtr pPriorParent);
 #endif /* GLAMOR_HAS_GBM */
 
 #ifdef XV
-- 
2.19.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

[PATCH xserver 0/2] RE: xwayland: Avoid assert failure in flips_stop()

2018-09-27 Thread Olivier Fourdan
Hi Roman,

On Fri, Sep 21, 2018 at 11:53 AM Roman Gilg  wrote:
>
> Great detailed analysis in the backtrace! :)
>
> What confused me at first was that the present_wnmd_flips_stop function
> is called at all in this state because it should only be called when at
> least one flip has been done and in this case xwl_window->present_window
> must have been set to the presenting (child) window.
>
> I believe now the root problem is that the window did in fact some flips
> in the past, but on the reparent operation a new parent window with a
> new xwl_window struct is set, which then has a different present_window
> value. That means when reparenting of a child window with flips the
> xwl_window->present_window values must be updated on the old parent
> (to NULL) and on the new parent (to the new child window). Or more
> generic this must be done on any unmap/map operation.
>
> One extra case must be considered: if there is already a different
> child window doing flips on the new parent window the reparented child
> window must be instructed to stop its flips.

So the following two patches are my attempt at implementing your suggestion,
but I am not familiar with Present so this is a bit of a shot in the dark
for me, also because that issue is quite difficult to reproduce.

Those patches have been barely tested, expect dragons!

Anyway, please let me know if that's what you had in mind...

Cheers,
Olivier

Olivier Fourdan (2):
  present: cancel flip on reparenting
  xwayland: update Xwayland present window on reparent

 hw/xwayland/xwayland-present.c | 16 
 hw/xwayland/xwayland.c | 23 +++
 hw/xwayland/xwayland.h |  2 ++
 present/present_priv.h |  3 +++
 present/present_scmd.c |  1 +
 present/present_screen.c   | 16 
 present/present_wnmd.c | 17 +
 7 files changed, 78 insertions(+)

-- 
2.19.0

___
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel