backend/drm: add support for explicit sync APIs

This commit is contained in:
Simon Ser 2021-10-20 20:09:38 +02:00
parent 1ad42bea99
commit 3067e45c2e
5 changed files with 74 additions and 3 deletions

View file

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