diff --git a/src/drm.cpp b/src/drm.cpp index c4fde20..54e12eb 100644 --- a/src/drm.cpp +++ b/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); diff --git a/src/drm.hpp b/src/drm.hpp index 8462945..59eaa14 100644 --- a/src/drm.hpp +++ b/src/drm.hpp @@ -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 ); diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index f128501..28704df 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -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 );