backend/drm: add support for explicit sync APIs

This commit is contained in:
Simon Ser 2021-10-20 20:09:38 +02:00
parent 26aa4f5f5c
commit 7aff45fa0d
5 changed files with 75 additions and 1 deletions

View file

@ -1,6 +1,8 @@
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <wlr/render/timeline.h>
#include <wlr/util/log.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@ -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;
}

View file

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

View file

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

View file

@ -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) },

View file

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