xwayland: Enable Present extension support also without glamor

This allows e.g.

 xfwm4 --vblank=xpresent

to hit the page flip path instead of copies.

In the future, Mesa might also use the Present extension with software
rendering.
This commit is contained in:
Michel Dänzer 2024-01-18 16:48:50 +01:00 committed by Michel Dänzer
parent 17986658bf
commit abe3a08245
8 changed files with 48 additions and 37 deletions

View File

@ -9,6 +9,7 @@ srcs = [
'xwayland-glamor.h',
'xwayland-pixmap.c',
'xwayland-pixmap.h',
'xwayland-present.c',
'xwayland-present.h',
'xwayland-screen.c',
'xwayland-screen.h',
@ -107,7 +108,6 @@ if build_glamor
if gbm_dep.found()
srcs += [
'xwayland-glamor-gbm.c',
'xwayland-present.c'
]
endif
if build_eglstream

View File

@ -97,9 +97,6 @@ xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap)
if (pixmap->drawable.depth != backing_pixmap->drawable.depth)
return FALSE;
if (!xwl_glamor_pixmap_get_wl_buffer(pixmap))
return FALSE;
if (xwl_screen->egl_backend->check_flip)
return xwl_screen->egl_backend->check_flip(pixmap);

View File

@ -25,14 +25,17 @@
#include <xwayland-config.h>
#ifdef XWL_HAS_GLAMOR
#include <glamor.h>
#endif
#include <windowstr.h>
#include <present.h>
#include "xwayland-present.h"
#include "xwayland-screen.h"
#include "xwayland-shm.h"
#include "xwayland-window.h"
#include "xwayland-pixmap.h"
#include "glamor.h"
#include "tearing-control-v1-client-protocol.h"
@ -608,7 +611,13 @@ xwl_present_abort_vblank(ScreenPtr screen,
static void
xwl_present_flush(WindowPtr window)
{
glamor_block_handler(window->drawable.pScreen);
#ifdef XWL_HAS_GLAMOR
ScreenPtr screen = window->drawable.pScreen;
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
if (xwl_screen->glamor)
glamor_block_handler(screen);
#endif
}
static void
@ -670,6 +679,9 @@ xwl_present_check_flip(RRCrtcPtr crtc,
present_window->drawable.height != pixmap->drawable.height)
return FALSE;
if (!xwl_pixmap_get_wl_buffer(pixmap))
return FALSE;
/* Window must be same region as toplevel window */
if ( !RegionEqual(&present_window->winSize, &toplvl_window->winSize) )
return FALSE;
@ -678,8 +690,11 @@ xwl_present_check_flip(RRCrtcPtr crtc,
if (!RegionEqual(&present_window->clipList, &present_window->winSize))
return FALSE;
if (!xwl_glamor_check_flip(present_window, pixmap))
#ifdef XWL_HAS_GLAMOR
if (xwl_window->xwl_screen->glamor &&
!xwl_glamor_check_flip(present_window, pixmap))
return FALSE;
#endif
/* Can't flip if the window pixmap doesn't match the xwl_window parent
* window's, e.g. because a client redirected this window or one of its
@ -766,7 +781,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
if (!xwl_window)
return FALSE;
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
buffer = xwl_pixmap_get_wl_buffer(pixmap);
if (!buffer) {
ErrorF("present: Error getting buffer\n");
return FALSE;
@ -1053,12 +1068,8 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window)
Bool
xwl_present_init(ScreenPtr screen)
{
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
present_screen_priv_ptr screen_priv;
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
return FALSE;
if (!present_screen_register_priv_keys())
return FALSE;

View File

@ -33,7 +33,6 @@
#include "xwayland-types.h"
#ifdef GLAMOR_HAS_GBM
struct xwl_present_window {
WindowPtr window;
@ -71,6 +70,4 @@ Bool xwl_present_init(ScreenPtr screen);
void xwl_present_cleanup(WindowPtr window);
void xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window);
#endif /* GLAMOR_HAS_GBM */
#endif /* XWAYLAND_PRESENT_H */

View File

@ -1015,11 +1015,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->glamor = XWL_GLAMOR_NONE;
}
}
#ifdef GLAMOR_HAS_GBM
if (xwl_screen->glamor)
xwl_screen->present = xwl_present_init(pScreen);
#endif /* GLAMOR_HAS_GBM */
#endif /* XWL_HAS_GLAMOR */
#endif
xwl_screen->present = xwl_present_init(pScreen);
if (!xwl_screen->glamor) {
xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;

View File

@ -213,6 +213,28 @@ shm_format_for_depth(int depth)
}
}
static Bool
dimensions_match_toplevel_window(ScreenPtr screen, int width, int height)
{
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
WindowPtr toplevel;
if (xwl_screen->rootless)
toplevel = screen->root->firstChild;
else
toplevel = screen->root;
while (toplevel) {
if (width == toplevel->drawable.width &&
height == toplevel->drawable.height)
return TRUE;
toplevel = toplevel->nextSib;
}
return FALSE;
}
static const struct wl_buffer_listener xwl_shm_buffer_listener = {
xwl_pixmap_buffer_release_cb,
};
@ -230,8 +252,9 @@ xwl_shm_create_pixmap(ScreenPtr screen,
int fd;
if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
(!xwl_screen->rootless && hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) ||
(width == 0 && height == 0) || depth < 15)
(width == 0 && height == 0) || depth < 15 ||
(hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
!dimensions_match_toplevel_window(screen, width, height)))
return fbCreatePixmap(screen, width, height, depth, hint);
stride = PixmapBytePad(width, depth);

View File

@ -188,7 +188,6 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
xwl_screen = xwl_window->xwl_screen;
#ifdef GLAMOR_HAS_GBM
if (xwl_window->present_flipped) {
/* This damage is from a Present flip, which already committed a new
* buffer for the surface, so we don't need to do anything in response
@ -198,7 +197,6 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
xwl_window->present_flipped = FALSE;
return;
}
#endif
if (xorg_list_is_empty(&xwl_window->link_damage))
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
@ -950,10 +948,7 @@ ensure_surface_for_window(WindowPtr window)
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
xorg_list_init(&xwl_window->link_damage);
xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list);
#ifdef GLAMOR_HAS_GBM
xorg_list_init(&xwl_window->frame_callback_list);
#endif
xwl_window_buffers_init(xwl_window);
@ -1181,10 +1176,8 @@ xwl_unrealize_window(WindowPtr window)
xwl_dmabuf_feedback_destroy(&xwl_window->feedback);
#ifdef GLAMOR_HAS_GBM
if (xwl_window->xwl_screen->present)
xwl_present_for_each_frame_callback(xwl_window, xwl_present_unrealize_window);
#endif
if (xwl_window->tearing_control)
wp_tearing_control_v1_destroy(xwl_window->tearing_control);
@ -1323,7 +1316,6 @@ frame_callback(void *data,
wl_callback_destroy (xwl_window->frame_callback);
xwl_window->frame_callback = NULL;
#ifdef GLAMOR_HAS_GBM
if (xwl_window->xwl_screen->present) {
xwl_present_for_each_frame_callback(xwl_window, xwl_present_frame_callback);
@ -1334,7 +1326,6 @@ frame_callback(void *data,
if (xwl_window->frame_callback)
xwl_present_for_each_frame_callback(xwl_window, xwl_present_reset_timer);
}
#endif
}
static const struct wl_callback_listener frame_listener = {
@ -1348,14 +1339,12 @@ xwl_window_create_frame_callback(struct xwl_window *xwl_window)
wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
xwl_window);
#ifdef GLAMOR_HAS_GBM
/* If we get called from frame_callback, it will take care of calling
* xwl_present_reset_timer.
*/
if (xwl_window->xwl_screen->present &&
!xwl_present_entered_for_each_frame_callback())
xwl_present_for_each_frame_callback(xwl_window, xwl_present_reset_timer);
#endif
}
Bool
@ -1365,10 +1354,8 @@ xwl_destroy_window(WindowPtr window)
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
Bool ret;
#ifdef GLAMOR_HAS_GBM
if (xwl_screen->present)
xwl_present_cleanup(window);
#endif
screen->DestroyWindow = xwl_screen->DestroyWindow;

View File

@ -110,10 +110,8 @@ struct xwl_window {
OsTimerPtr window_buffers_timer;
struct wl_output *wl_output;
struct wl_output *wl_output_fullscreen;
#ifdef GLAMOR_HAS_GBM
struct xorg_list frame_callback_list;
Bool present_flipped;
#endif
#ifdef XWL_HAS_LIBDECOR
struct libdecor_frame *libdecor_frame;
#endif