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 <drm_fourcc.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <wlr/render/drm_syncobj.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.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); 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 = bool prev_vrr_enabled =
output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED; output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
bool vrr_enabled = prev_vrr_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->mode_id = mode_id;
state->gamma_lut = gamma_lut; state->gamma_lut = gamma_lut;
state->fb_damage_clips = fb_damage_clips; state->fb_damage_clips = fb_damage_clips;
state->primary_in_fence_fd = in_fence_fd;
state->vrr_enabled = vrr_enabled; state->vrr_enabled = vrr_enabled;
return true; 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; WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
destroy_blob(drm, state->fb_damage_clips); 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) { 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); rollback_blob(drm, &crtc->gamma_lut, state->gamma_lut);
destroy_blob(drm, state->fb_damage_clips); 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) { static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
@ -353,12 +380,37 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
atomic_add(atom, id, props->crtc_y, (uint64_t)y); atomic_add(atom, id, props->crtc_y, (uint64_t)y);
} }
static bool supports_cursor_hotspots(const struct wlr_drm_plane* plane) { static bool supports_cursor_hotspots(const struct wlr_drm_plane *plane) {
return plane->props.hotspot_x && plane->props.hotspot_y; 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, 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_connector *conn = state->connector;
struct wlr_drm_backend *drm = conn->backend; struct wlr_drm_backend *drm = conn->backend;
struct wlr_drm_crtc *crtc = conn->crtc; 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, atomic_add(atom, crtc->primary->id,
crtc->primary->props.fb_damage_clips, state->fb_damage_clips); 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 (crtc->cursor) {
if (drm_connector_is_cursor_visible(conn)) { if (drm_connector_is_cursor_visible(conn)) {
set_plane_props(atom, drm, crtc->cursor, state->cursor_fb, 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_ENABLED |
WLR_OUTPUT_STATE_GAMMA_LUT | WLR_OUTPUT_STATE_GAMMA_LUT |
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED | 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 = static const uint32_t SUPPORTED_OUTPUT_STATE =
WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_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, .connector = conn,
.base = base, .base = base,
.active = output_pending_enabled(&conn->output, 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; 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; 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)); memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds));
if (wlr_conn->props.max_bpc != 0) { if (wlr_conn->props.max_bpc != 0) {
if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc, 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", INDEX(gamma_lut) },
{ "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) }, { "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) },
{ "MODE_ID", INDEX(mode_id) }, { "MODE_ID", INDEX(mode_id) },
{ "OUT_FENCE_PTR", INDEX(out_fence_ptr) },
{ "VRR_ENABLED", INDEX(vrr_enabled) }, { "VRR_ENABLED", INDEX(vrr_enabled) },
#undef INDEX #undef INDEX
}; };
@ -55,6 +56,7 @@ static const struct prop_info plane_info[] = {
{ "FB_ID", INDEX(fb_id) }, { "FB_ID", INDEX(fb_id) },
{ "HOTSPOT_X", INDEX(hotspot_x) }, { "HOTSPOT_X", INDEX(hotspot_x) },
{ "HOTSPOT_Y", INDEX(hotspot_y) }, { "HOTSPOT_Y", INDEX(hotspot_y) },
{ "IN_FENCE_FD", INDEX(in_fence_fd) },
{ "IN_FORMATS", INDEX(in_formats) }, { "IN_FORMATS", INDEX(in_formats) },
{ "SIZE_HINTS", INDEX(size_hints) }, { "SIZE_HINTS", INDEX(size_hints) },
{ "SRC_H", INDEX(src_h) }, { "SRC_H", INDEX(src_h) },

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

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

Loading…
Cancel
Save