drm: Don't forget about modesetting + modesetting robustness
Makes it so that we don't forget about any required modesets we need to undertake, and makes modesetting robust by trying again when compositing (in case the error was not mode but plane related), and falling back to the previous mode if that fails. If we have no mode to fall back to then we abort, same if we fail our mode fallback commit. Co-authored-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
parent
bbfbf0dd8d
commit
95eba7e549
3 changed files with 36 additions and 9 deletions
18
src/drm.cpp
18
src/drm.cpp
|
@ -1226,17 +1226,23 @@ int drm_prepare( struct drm_t *drm, const struct Composite_t *pComposite, const
|
|||
|
||||
drm->fbids_in_req.clear();
|
||||
|
||||
drm->pending = drm->current;
|
||||
|
||||
for ( size_t i = 0; i < drm->crtcs.size(); i++ )
|
||||
{
|
||||
drm->crtcs[i].pending = drm->crtcs[i].current;
|
||||
}
|
||||
if ( needs_modeset )
|
||||
drm->needs_modeset = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drm_rollback( struct drm_t *drm )
|
||||
{
|
||||
drm->pending = drm->current;
|
||||
|
||||
for ( size_t i = 0; i < drm->crtcs.size(); i++ )
|
||||
{
|
||||
drm->crtcs[i].pending = drm->crtcs[i].current;
|
||||
}
|
||||
}
|
||||
|
||||
bool drm_poll_state( struct drm_t *drm )
|
||||
{
|
||||
bool out_of_date = drm->out_of_date.exchange(false);
|
||||
|
|
|
@ -142,6 +142,7 @@ bool init_drm(struct drm_t *drm, int width, int height, int refresh);
|
|||
void finish_drm(struct drm_t *drm);
|
||||
int drm_commit(struct drm_t *drm, struct Composite_t *pComposite, struct VulkanPipeline_t *pPipeline );
|
||||
int drm_prepare( struct drm_t *drm, const struct Composite_t *pComposite, const struct VulkanPipeline_t *pPipeline );
|
||||
void drm_rollback( struct drm_t *drm );
|
||||
bool drm_poll_state(struct drm_t *drm);
|
||||
uint32_t drm_fbid_from_dmabuf( struct drm_t *drm, struct wlr_buffer *buf, struct wlr_dmabuf_attributes *dma_buf );
|
||||
void drm_lock_fbid( struct drm_t *drm, uint32_t fbid );
|
||||
|
|
|
@ -1643,9 +1643,29 @@ paint_all(Display *dpy, MouseCursor *cursor)
|
|||
|
||||
if ( ret != 0 )
|
||||
{
|
||||
xwm_log.errorf( "Failed to prepare 1-layer flip: %s", strerror( -ret ) );
|
||||
// We should always handle a 1-layer flip
|
||||
abort();
|
||||
if ( g_DRM.current.mode_id == 0 )
|
||||
{
|
||||
xwm_log.errorf("We failed our modeset and have no mode to fall back to! (Initial modeset failed?): %s", strerror(-ret));
|
||||
abort();
|
||||
}
|
||||
|
||||
xwm_log.errorf("Failed to prepare 1-layer flip (%s), trying again with previous mode if modeset needed", strerror( -ret ));
|
||||
|
||||
drm_rollback( &g_DRM );
|
||||
|
||||
// Try once again to in case we need to fall back to another mode.
|
||||
ret = drm_prepare( &g_DRM, &composite, &pipeline );
|
||||
|
||||
// Happens when we're VT-switched away
|
||||
if ( ret == -EACCES )
|
||||
return;
|
||||
|
||||
if ( ret != 0 )
|
||||
{
|
||||
xwm_log.errorf("Failed to prepare 1-layer flip entirely: %s", strerror( -ret ));
|
||||
// We should always handle a 1-layer flip
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
drm_commit( &g_DRM, &composite, &pipeline );
|
||||
|
|
Loading…
Reference in a new issue