mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-21 14:42:25 +00:00
backend/drm: add support for explicit sync APIs
This commit is contained in:
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) {
|
||||
@ -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,
|
||||
|
@ -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…
Reference in New Issue
Block a user