From 26d3f8bc7edf6f92bc64f45d253b82de13077b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 19 Feb 2025 20:11:14 +0200 Subject: [PATCH] modesetting: Use IN_FORMATS_ASYNC for async flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the IN_FORMATS_ASYNC blob (as opposed to the normal IN_FORMATS blob) to determine which formats/modifiers are supported. This will allow the client to allocate buffers which can actually be async flipped. In order to guarantee that the most optimal modifier is always used we also need to force a modifier renegotiation when swicthing between sync and async flips. Otherwise eg. sync flips might end up using a less optimal sync+async modifier instead of a more optimal sync-only modifier. Signed-off-by: Ville Syrjälä --- hw/xfree86/drivers/modesetting/driver.c | 49 +++++++++++++++++++ hw/xfree86/drivers/modesetting/driver.h | 9 ++++ .../drivers/modesetting/drmmode_display.c | 6 ++- .../drivers/modesetting/drmmode_display.h | 1 + hw/xfree86/drivers/modesetting/present.c | 19 ++++++- 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index 264c6fe33..6ddd6c810 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -919,6 +919,50 @@ ms_vrr_property_update(WindowPtr window, Bool variable_refresh) ms_present_set_screen_vrr(scrn, variable_refresh); } +Bool +ms_window_has_async_flip(WindowPtr win) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(win->drawable.pScreen); + modesettingPtr ms = modesettingPTR(scrn); + struct ms_async_flip_priv *priv = dixLookupPrivate(&win->devPrivates, + &ms->drmmode.asyncFlipPrivateKeyRec); + + return priv->async_flip; +} + +void +ms_window_update_async_flip(WindowPtr win, Bool async_flip) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(win->drawable.pScreen); + modesettingPtr ms = modesettingPTR(scrn); + struct ms_async_flip_priv *priv = dixLookupPrivate(&win->devPrivates, + &ms->drmmode.asyncFlipPrivateKeyRec); + + priv->async_flip = async_flip; +} + +Bool +ms_window_has_async_flip_modifiers(WindowPtr win) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(win->drawable.pScreen); + modesettingPtr ms = modesettingPTR(scrn); + struct ms_async_flip_priv *priv = dixLookupPrivate(&win->devPrivates, + &ms->drmmode.asyncFlipPrivateKeyRec); + + return priv->async_flip_modifiers; +} + +void +ms_window_update_async_flip_modifiers(WindowPtr win, Bool async_flip) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(win->drawable.pScreen); + modesettingPtr ms = modesettingPTR(scrn); + struct ms_async_flip_priv *priv = dixLookupPrivate(&win->devPrivates, + &ms->drmmode.asyncFlipPrivateKeyRec); + + priv->async_flip_modifiers = async_flip; +} + /* Wrapper for xserver/dix/property.c:ProcChangeProperty */ static int ms_change_property(ClientPtr client) @@ -1827,6 +1871,11 @@ CreateScreenResources(ScreenPtr pScreen) sizeof(struct ms_vrr_priv))) return FALSE; + if (!dixRegisterPrivateKey(&ms->drmmode.asyncFlipPrivateKeyRec, + PRIVATE_WINDOW, + sizeof(struct ms_async_flip_priv))) + return FALSE; + return ret; } diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 74630cac4..e291bfa90 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -49,6 +49,11 @@ struct ms_vrr_priv { Bool variable_refresh; }; +struct ms_async_flip_priv { + Bool async_flip; + Bool async_flip_modifiers; +}; + typedef enum { OPTION_SW_CURSOR, OPTION_DEVICE_PATH, @@ -262,3 +267,7 @@ void ms_drain_drm_events(ScreenPtr screen); Bool ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win); void ms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled); Bool ms_tearfree_is_active_on_crtc(xf86CrtcPtr crtc); +Bool ms_window_has_async_flip(WindowPtr win); +void ms_window_update_async_flip(WindowPtr win, Bool async_flip); +Bool ms_window_has_async_flip_modifiers(WindowPtr win); +void ms_window_update_async_flip_modifiers(WindowPtr win, Bool async_flip); diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index d103acbe9..b2d3f24b4 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -240,6 +240,7 @@ get_drawable_modifiers(DrawablePtr draw, uint32_t format, { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); modesettingPtr ms = modesettingPTR(scrn); + Bool async_flip; if (!present_can_window_flip((WindowPtr) draw) || !ms->drmmode.pageflip || ms->drmmode.dri2_flipping || !scrn->vtSema) { @@ -248,8 +249,11 @@ get_drawable_modifiers(DrawablePtr draw, uint32_t format, return TRUE; } + async_flip = ms_window_has_async_flip((WindowPtr)draw); + ms_window_update_async_flip_modifiers((WindowPtr)draw, async_flip); + *num_modifiers = get_modifiers_set(scrn, format, modifiers, - TRUE, FALSE, FALSE); + TRUE, FALSE, async_flip); return TRUE; } #endif diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index df36b8ff6..5e7ba9df1 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -119,6 +119,7 @@ typedef struct { DevPrivateKeyRec pixmapPrivateKeyRec; DevScreenPrivateKeyRec spritePrivateKeyRec; DevPrivateKeyRec vrrPrivateKeyRec; + DevPrivateKeyRec asyncFlipPrivateKeyRec; /* Number of SW cursors currently visible on this screen */ int sprites_visible; diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index 56dea8754..80ac5c9d3 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -294,7 +294,7 @@ ms_present_check_unflip(RRCrtcPtr crtc, modifier = gbm_bo_get_modifier(gbm); gbm_bo_destroy(gbm); - if (!drmmode_is_format_supported(scrn, format, modifier, FALSE)) { + if (!drmmode_is_format_supported(scrn, format, modifier, !sync_flip)) { if (reason) *reason = PRESENT_FLIP_REASON_BUFFER_FORMAT; return FALSE; @@ -321,6 +321,7 @@ ms_present_check_flip(RRCrtcPtr crtc, ScreenPtr screen = window->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); modesettingPtr ms = modesettingPTR(scrn); + Bool async_flip = !sync_flip; if (ms->drmmode.sprites_visible > 0) goto no_flip; @@ -328,8 +329,22 @@ ms_present_check_flip(RRCrtcPtr crtc, if (ms->drmmode.pending_modeset) goto no_flip; - if(!ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason)) + if (!ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason)) { + if (reason && *reason == PRESENT_FLIP_REASON_BUFFER_FORMAT) + ms_window_update_async_flip(window, async_flip); goto no_flip; + } + + ms_window_update_async_flip(window, async_flip); + + /* + * Force a format renegotiation when switching between sync and async, + * otherwise we may end up with a working but suboptimal modifier. + */ + if (reason && async_flip != ms_window_has_async_flip_modifiers(window)) { + *reason = PRESENT_FLIP_REASON_BUFFER_FORMAT; + goto no_flip; + } ms->flip_window = window;