modesetting: Use IN_FORMATS_ASYNC for async flips

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: notbabaisyou <though-went-some-simple@proton.me>
This commit is contained in:
Ville Syrjälä 2025-06-24 22:52:59 +02:00 committed by notbabaisyou
parent c5a23ada0e
commit c2eae14130
5 changed files with 82 additions and 3 deletions

View File

@ -913,6 +913,51 @@ msSetWindowVRRMode(WindowPtr window, WindowVRRMode mode)
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;
}
static void
FreeScreen(ScrnInfoPtr pScrn)
{
@ -1711,6 +1756,11 @@ modsetCreateScreenResources(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;
}

View File

@ -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,
@ -261,3 +266,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);

View File

@ -243,6 +243,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) {
@ -251,8 +252,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

View File

@ -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;

View File

@ -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;