backend/drm: add support for explicit sync APIs

master
Simon Ser 3 years ago
parent 1ad42bea99
commit 3067e45c2e

@ -1,6 +1,8 @@
#include <drm_fourcc.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <wlr/render/drm_syncobj.h>
#include <wlr/util/log.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@ -272,6 +274,15 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
state->primary_fb->wlr_buf->height, &state->base->damage, &fb_damage_clips);
}
int in_fence_fd = -1;
if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->base->wait_timeline,
state->base->wait_point);
if (in_fence_fd < 0) {
return false;
}
}
bool prev_vrr_enabled =
output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
bool vrr_enabled = prev_vrr_enabled;
@ -285,6 +296,7 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
state->mode_id = mode_id;
state->gamma_lut = gamma_lut;
state->fb_damage_clips = fb_damage_clips;
state->primary_in_fence_fd = in_fence_fd;
state->vrr_enabled = vrr_enabled;
return true;
}
@ -305,6 +317,15 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) {
WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
destroy_blob(drm, state->fb_damage_clips);
if (state->primary_in_fence_fd >= 0) {
close(state->primary_in_fence_fd);
}
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);
close(state->out_fence_fd);
}
}
void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state) {
@ -316,6 +337,12 @@ void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state)
rollback_blob(drm, &crtc->gamma_lut, state->gamma_lut);
destroy_blob(drm, state->fb_damage_clips);
if (state->primary_in_fence_fd >= 0) {
close(state->primary_in_fence_fd);
}
if (state->out_fence_fd >= 0) {
close(state->out_fence_fd);
}
}
static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
@ -357,8 +384,33 @@ static bool supports_cursor_hotspots(const struct wlr_drm_plane* plane) {
return plane->props.hotspot_x && plane->props.hotspot_y;
}
static void set_plane_in_fence_fd(struct atomic *atom,
struct wlr_drm_plane *plane, int sync_file_fd) {
if (!plane->props.in_fence_fd) {
wlr_log(WLR_ERROR, "Plane %"PRIu32 " is missing the IN_FENCE_FD property",
plane->id);
atom->failed = true;
return;
}
atomic_add(atom, plane->id, plane->props.in_fence_fd, sync_file_fd);
}
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 void atomic_connector_add(struct atomic *atom,
const struct wlr_drm_connector_state *state, bool modeset) {
struct wlr_drm_connector_state *state, bool modeset) {
struct wlr_drm_connector *conn = state->connector;
struct wlr_drm_backend *drm = conn->backend;
struct wlr_drm_crtc *crtc = conn->crtc;
@ -391,6 +443,12 @@ static void atomic_connector_add(struct atomic *atom,
atomic_add(atom, crtc->primary->id,
crtc->primary->props.fb_damage_clips, state->fb_damage_clips);
}
if (state->primary_in_fence_fd >= 0) {
set_plane_in_fence_fd(atom, crtc->primary, state->primary_in_fence_fd);
}
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
set_crtc_out_fence_ptr(atom, crtc, &state->out_fence_fd);
}
if (crtc->cursor) {
if (drm_connector_is_cursor_visible(conn)) {
set_plane_props(atom, drm, crtc->cursor, state->cursor_fb,

@ -42,7 +42,9 @@ static const uint32_t COMMIT_OUTPUT_STATE =
WLR_OUTPUT_STATE_ENABLED |
WLR_OUTPUT_STATE_GAMMA_LUT |
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED |
WLR_OUTPUT_STATE_LAYERS;
WLR_OUTPUT_STATE_LAYERS |
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;
@ -630,6 +632,8 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
.connector = conn,
.base = base,
.active = output_pending_enabled(&conn->output, base),
.primary_in_fence_fd = -1,
.out_fence_fd = -1,
};
struct wlr_output_mode *mode = conn->output.current_mode;
@ -1619,6 +1623,10 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
output->non_desktop = non_desktop;
}
// TODO: support sync timelines in multi-GPU mode
// TODO: support sync timelines with libliftoff
output->timeline = drm->parent == NULL && drm->iface == &atomic_iface;
memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds));
if (wlr_conn->props.max_bpc != 0) {
if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc,

@ -40,6 +40,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
};
@ -55,6 +56,7 @@ static const struct prop_info plane_info[] = {
{ "FB_ID", INDEX(fb_id) },
{ "HOTSPOT_X", INDEX(hotspot_x) },
{ "HOTSPOT_Y", INDEX(hotspot_y) },
{ "IN_FENCE_FD", INDEX(in_fence_fd) },
{ "IN_FORMATS", INDEX(in_formats) },
{ "SIZE_HINTS", INDEX(size_hints) },
{ "SRC_H", INDEX(src_h) },

@ -145,6 +145,7 @@ struct wlr_drm_connector_state {
uint32_t mode_id;
uint32_t gamma_lut;
uint32_t fb_damage_clips;
int primary_in_fence_fd, out_fence_fd;
bool vrr_enabled;
};

@ -38,6 +38,7 @@ struct wlr_drm_crtc_props {
uint32_t active;
uint32_t mode_id;
uint32_t out_fence_ptr;
};
struct wlr_drm_plane_props {
@ -61,6 +62,7 @@ struct wlr_drm_plane_props {
uint32_t fb_damage_clips;
uint32_t hotspot_x;
uint32_t hotspot_y;
uint32_t in_fence_fd;
};
bool get_drm_connector_props(int fd, uint32_t id,

Loading…
Cancel
Save