xwayland/present: Add xwl_present_maybe_(un)redirect_window

A later commit will use these to (un)redirect the surface window on
demand.

Not used yet, so no functional change intended.

v2:
* Use "surface_window_damage" instead of "surf_win_damage".
  (Olivier Fourdan)
* Slightly simplify logic in xwl_unrealize_window.
v3:
* Add comment in xwl_present_maybe_unredirect_window explaining why we
  use a timer. (Olivier Fourdan)
v4:
* Rename unredir_timer field to unredirect_timer.

Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
This commit is contained in:
Michel Dänzer 2024-02-15 18:27:27 +01:00 committed by Marge Bot
parent fa7b1c20c4
commit fca63f8fb8
4 changed files with 75 additions and 3 deletions

View File

@ -25,6 +25,7 @@
#include <xwayland-config.h> #include <xwayland-config.h>
#include <compint.h>
#ifdef XWL_HAS_GLAMOR #ifdef XWL_HAS_GLAMOR
#include <glamor.h> #include <glamor.h>
#endif #endif
@ -484,6 +485,7 @@ xwl_present_cleanup(WindowPtr window)
/* Clear timer */ /* Clear timer */
xwl_present_free_timer(xwl_present_window); xwl_present_free_timer(xwl_present_window);
TimerFree(xwl_present_window->unredirect_timer);
/* Remove from privates so we don't try to access it later */ /* Remove from privates so we don't try to access it later */
dixSetPrivate(&window->devPrivates, dixSetPrivate(&window->devPrivates,
@ -1263,6 +1265,67 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window)
xwl_present_reset_timer(xwl_present_window); xwl_present_reset_timer(xwl_present_window);
} }
Bool
xwl_present_maybe_redirect_window(WindowPtr window, PixmapPtr pixmap)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
struct xwl_window *xwl_window = xwl_window_from_window(window);
if (xwl_present_window->redirect_failed)
return FALSE;
if (compRedirectWindow(serverClient, window, CompositeRedirectManual) != Success) {
xwl_present_window->redirect_failed = TRUE;
return FALSE;
}
xwl_window_update_surface_window(xwl_window);
if (xwl_window->surface_window != window) {
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
xwl_present_window->redirect_failed = TRUE;
return FALSE;
}
if (!xwl_window->surface_window_damage)
xwl_window->surface_window_damage = RegionCreate(NullBox, 1);
xwl_present_window->redirected = TRUE;
return TRUE;
}
static CARD32
unredirect_window(OsTimerPtr timer, CARD32 time, void *arg)
{
WindowPtr window = arg;
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
xwl_present_window->redirected = FALSE;
xwl_present_window->unredirect_timer = NULL;
return 0;
}
Bool
xwl_present_maybe_unredirect_window(WindowPtr window)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
if (!xwl_present_window || !xwl_present_window->redirected)
return FALSE;
/* This function may get called from composite layer code, in which case
* calling compUnredirectWindow would blow up. To avoid this, set up a timer
* which will call it "as soon as possible".
*/
if (!xwl_present_window->unredirect_timer) {
xwl_present_window->unredirect_timer =
TimerSet(NULL, 0, 1, unredirect_window, window);
}
return TRUE;
}
Bool Bool
xwl_present_init(ScreenPtr screen) xwl_present_init(ScreenPtr screen)
{ {

View File

@ -54,6 +54,10 @@ struct xwl_present_window {
present_vblank_ptr flip_active; present_vblank_ptr flip_active;
uint64_t blocking_event; uint64_t blocking_event;
OsTimerPtr unredirect_timer;
Bool redirected;
Bool redirect_failed;
}; };
struct xwl_present_event { struct xwl_present_event {
@ -77,5 +81,7 @@ void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window);
Bool xwl_present_init(ScreenPtr screen); Bool xwl_present_init(ScreenPtr screen);
void xwl_present_cleanup(WindowPtr window); void xwl_present_cleanup(WindowPtr window);
void xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window); void xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window);
Bool xwl_present_maybe_redirect_window(WindowPtr window, PixmapPtr pixmap);
Bool xwl_present_maybe_unredirect_window(WindowPtr window);
#endif /* XWAYLAND_PRESENT_H */ #endif /* XWAYLAND_PRESENT_H */

View File

@ -1221,7 +1221,7 @@ err_surf:
return FALSE; return FALSE;
} }
static void void
xwl_window_update_surface_window(struct xwl_window *xwl_window) xwl_window_update_surface_window(struct xwl_window *xwl_window)
{ {
WindowPtr surface_window = xwl_window->toplevel; WindowPtr surface_window = xwl_window->toplevel;
@ -1512,14 +1512,15 @@ xwl_unrealize_window(WindowPtr window)
xwl_screen = xwl_screen_get(screen); xwl_screen = xwl_screen_get(screen);
compUnredirectWindow(serverClient, window, CompositeRedirectManual); xwl_window = xwl_window_get(window);
if (xwl_window)
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
screen->UnrealizeWindow = xwl_screen->UnrealizeWindow; screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
ret = (*screen->UnrealizeWindow) (window); ret = (*screen->UnrealizeWindow) (window);
xwl_screen->UnrealizeWindow = screen->UnrealizeWindow; xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
screen->UnrealizeWindow = xwl_unrealize_window; screen->UnrealizeWindow = xwl_unrealize_window;
xwl_window = xwl_window_get(window);
if (!xwl_window) if (!xwl_window)
return ret; return ret;

View File

@ -82,6 +82,7 @@ struct xwl_window {
* can also be used for the X dimensions of the Wayland surface though. * can also be used for the X dimensions of the Wayland surface though.
*/ */
WindowPtr surface_window; WindowPtr surface_window;
RegionPtr surface_window_damage;
struct xorg_list link_damage; struct xorg_list link_damage;
struct xorg_list link_window; struct xorg_list link_window;
@ -121,6 +122,7 @@ void xwl_window_rootful_update_title(struct xwl_window *xwl_window);
void xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window, void xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window,
struct xwl_output *xwl_output); struct xwl_output *xwl_output);
void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap); void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap);
void xwl_window_update_surface_window(struct xwl_window *xwl_window);
void xwl_window_leave_output(struct xwl_window *xwl_window, void xwl_window_leave_output(struct xwl_window *xwl_window,
struct xwl_output *xwl_output); struct xwl_output *xwl_output);