From cd555f9261d5443ba13f484fe4baa6dc3978c859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Poisot?= Date: Fri, 31 Jan 2025 18:59:10 +0000 Subject: [PATCH] backend/drm: properly delay syncobj signalling DRM CRTC signals when scanout begins, but wlr_output_state_set_signal_timeline() is defined to signal buffer release. Delay to the next page flip --- backend/drm/atomic.c | 9 +++++++-- backend/drm/drm.c | 30 ++++++++++++++++++++++++++++++ include/backend/drm/drm.h | 4 ++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 9bccff6ce..f12c56907 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -426,8 +426,13 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) { } if (state->out_fence_fd >= 0) { // TODO: error handling - wlr_drm_syncobj_timeline_import_sync_file(state->base->signal_timeline, - state->base->signal_point, state->out_fence_fd); + if (crtc->primary->current_release_timeline != NULL) { + wlr_drm_syncobj_timeline_import_sync_file(crtc->primary->current_release_timeline, + crtc->primary->current_release_point, state->out_fence_fd); + wlr_drm_syncobj_timeline_unref(crtc->primary->current_release_timeline); + crtc->primary->current_release_timeline = NULL; + crtc->primary->current_release_point = 0; + } close(state->out_fence_fd); } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 9b90022d2..7cfea5a14 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -368,7 +368,17 @@ static void drm_plane_finish_surface(struct wlr_drm_plane *plane) { } drm_fb_clear(&plane->queued_fb); + if (plane->queued_release_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(plane->queued_release_timeline, plane->queued_release_point); + wlr_drm_syncobj_timeline_unref(plane->queued_release_timeline); + plane->queued_release_timeline = NULL; + } drm_fb_clear(&plane->current_fb); + if (plane->current_release_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(plane->current_release_timeline, plane->current_release_point); + wlr_drm_syncobj_timeline_unref(plane->current_release_timeline); + plane->current_release_timeline = NULL; + } finish_drm_surface(&plane->mgpu_surf); } @@ -557,6 +567,18 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta struct wlr_drm_crtc *crtc = conn->crtc; drm_fb_copy(&crtc->primary->queued_fb, state->primary_fb); + if (crtc->primary->queued_release_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(crtc->primary->queued_release_timeline, crtc->primary->queued_release_point); + wlr_drm_syncobj_timeline_unref(crtc->primary->queued_release_timeline); + } + if (state->base->signal_timeline != NULL) { + crtc->primary->queued_release_timeline = wlr_drm_syncobj_timeline_ref(state->base->signal_timeline); + crtc->primary->queued_release_point = state->base->signal_point; + } else { + crtc->primary->queued_release_timeline = NULL; + crtc->primary->queued_release_point = 0; + } + crtc->primary->viewport = state->primary_viewport; if (crtc->cursor != NULL) { drm_fb_copy(&crtc->cursor->queued_fb, state->cursor_fb); @@ -2019,6 +2041,14 @@ static void handle_page_flip(int fd, unsigned seq, struct wlr_drm_plane *plane = conn->crtc->primary; if (plane->queued_fb) { drm_fb_move(&plane->current_fb, &plane->queued_fb); + if (plane->current_release_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(plane->current_release_timeline, plane->current_release_point); + wlr_drm_syncobj_timeline_unref(plane->current_release_timeline); + } + plane->current_release_timeline = plane->queued_release_timeline; + plane->current_release_point = plane->queued_release_point; + plane->queued_release_timeline = NULL; + plane->queued_release_point = 0; } if (conn->crtc->cursor && conn->crtc->cursor->queued_fb) { drm_fb_move(&conn->crtc->cursor->current_fb, diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index af4231f54..e07c16efe 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -29,8 +29,12 @@ struct wlr_drm_plane { /* Buffer submitted to the kernel, will be presented on next vblank */ struct wlr_drm_fb *queued_fb; + struct wlr_drm_syncobj_timeline *queued_release_timeline; + uint64_t queued_release_point; /* Buffer currently displayed on screen */ struct wlr_drm_fb *current_fb; + struct wlr_drm_syncobj_timeline *current_release_timeline; + uint64_t current_release_point; /* Viewport belonging to the last committed fb */ struct wlr_drm_viewport viewport;