diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index ab1b21601..e3b8e38ec 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -1,6 +1,8 @@ #define _POSIX_C_SOURCE 200809L #include #include +#include +#include #include #include #include @@ -202,6 +204,41 @@ error: atom->failed = true; } +static int set_plane_in_fence_fd(struct atomic *atom, struct wlr_drm_plane *plane, + struct wlr_render_timeline *timeline, uint64_t src_point) { + if (!plane->props.in_fence_fd) { + wlr_log(WLR_ERROR, "Missing IN_FENCE_FD property"); + goto error; + } + + int sync_file_fd = wlr_render_timeline_export_sync_file(timeline, src_point); + if (sync_file_fd < 0) { + goto error; + } + + atomic_add(atom, plane->id, plane->props.in_fence_fd, sync_file_fd); + + return sync_file_fd; + +error: + wlr_log(WLR_ERROR, "Failed to set plane %"PRIu32" IN_FENCE_FD", plane->id); + atom->failed = true; + return -1; +} + +static void set_crtc_out_fence_ptr(struct atomic *atom, struct wlr_drm_crtc *crtc, + int *fd_ptr) { + if (!crtc->props.out_fence_ptr) { + wlr_log(WLR_ERROR, + "CRTC %"PRIu32" is missing the OUT_FENCE_PTR property", + crtc->id); + atom->failed = true; + return; + } + + atomic_add(atom, crtc->id, crtc->props.out_fence_ptr, (uintptr_t)fd_ptr); +} + static bool atomic_crtc_commit(struct wlr_drm_connector *conn, const struct wlr_drm_connector_state *state, uint32_t flags, bool test_only) { @@ -273,6 +310,8 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, flags |= DRM_MODE_ATOMIC_NONBLOCK; } + int in_fence_fd = -1, out_fence_fd = -1; + struct atomic atom; atomic_begin(&atom); atomic_add(&atom, conn->id, conn->props.crtc_id, active ? crtc->id : 0); @@ -301,6 +340,13 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, atomic_add(&atom, crtc->primary->id, crtc->primary->props.fb_damage_clips, fb_damage_clips); } + if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) { + in_fence_fd = set_plane_in_fence_fd(&atom, crtc->primary, + state->base->wait_timeline, state->base->wait_point); + } + if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) { + set_crtc_out_fence_ptr(&atom, crtc, &out_fence_fd); + } if (crtc->cursor) { if (drm_connector_is_cursor_visible(conn)) { set_plane_props(&atom, drm, crtc->cursor, crtc->id, @@ -340,6 +386,14 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, wlr_log_errno(WLR_ERROR, "Failed to destroy FB_DAMAGE_CLIPS property blob"); } + close(in_fence_fd); + + if (out_fence_fd > 0) { + ok = wlr_render_timeline_import_sync_file(state->base->signal_timeline, + state->base->signal_point, out_fence_fd); + close(out_fence_fd); + } + return ok; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 262a533e6..dc2d1cd83 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -36,7 +36,9 @@ static const uint32_t COMMIT_OUTPUT_STATE = WLR_OUTPUT_STATE_BUFFER | WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_ENABLED | - WLR_OUTPUT_STATE_GAMMA_LUT; + WLR_OUTPUT_STATE_GAMMA_LUT | + WLR_OUTPUT_STATE_WAIT_TIMELINE | + WLR_OUTPUT_STATE_SIGNAL_TIMELINE; static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE; @@ -491,6 +493,13 @@ static bool drm_connector_test(struct wlr_output *output, } } + if ((output->pending.committed & (WLR_OUTPUT_STATE_WAIT_TIMELINE | + WLR_OUTPUT_STATE_SIGNAL_TIMELINE)) && conn->backend->parent) { + wlr_drm_conn_log(conn, WLR_DEBUG, + "Sync timelines are unsupported in multi-GPU mode"); + return false; + } + struct wlr_drm_connector_state pending = {0}; drm_connector_state_init(&pending, conn, state); diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 84e8a914f..ccc531361 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -54,6 +54,13 @@ static bool legacy_crtc_test(struct wlr_drm_connector *conn, } } + if (state->base->committed & (WLR_OUTPUT_STATE_WAIT_TIMELINE | + WLR_OUTPUT_STATE_SIGNAL_TIMELINE)) { + wlr_drm_conn_log(conn, WLR_DEBUG, + "Sync timelines are unsupported with legacy KMS interface"); + return false; + } + return true; } diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 4f4951771..30305457f 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -41,6 +41,7 @@ static const struct prop_info crtc_info[] = { { "GAMMA_LUT", INDEX(gamma_lut) }, { "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) }, { "MODE_ID", INDEX(mode_id) }, + { "OUT_FENCE_PTR", INDEX(out_fence_ptr) }, { "VRR_ENABLED", INDEX(vrr_enabled) }, #undef INDEX }; @@ -54,6 +55,7 @@ static const struct prop_info plane_info[] = { { "CRTC_Y", INDEX(crtc_y) }, { "FB_DAMAGE_CLIPS", INDEX(fb_damage_clips) }, { "FB_ID", INDEX(fb_id) }, + { "IN_FENCE_FD", INDEX(in_fence_fd) }, { "IN_FORMATS", INDEX(in_formats) }, { "SRC_H", INDEX(src_h) }, { "SRC_W", INDEX(src_w) }, diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index b6ca14f19..10e2cb808 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -41,6 +41,7 @@ union wlr_drm_crtc_props { uint32_t active; uint32_t mode_id; + uint32_t out_fence_ptr; }; uint32_t props[6]; }; @@ -64,6 +65,7 @@ union wlr_drm_plane_props { uint32_t fb_id; uint32_t crtc_id; uint32_t fb_damage_clips; + uint32_t in_fence_fd; }; uint32_t props[14]; };