From 82f92113fd997a561d5f4d79b54a82df79a86daf Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Sun, 10 Jan 2021 19:04:58 +1100 Subject: [PATCH] backend/drm: add support for suggested output position prop Virtualised outputs use the "suggested X" and "suggested Y" DRM props to indicate their relative position on the host WM. This change adds members `suggested_x` and `suggested_y` to `struct wlr_output` which contain the value of these props. Also, a `suggested_position` signal is added so that compositors can be notified if there is a changed in the suggested position. --- backend/drm/drm.c | 48 +++++++++++++++++++++++++++++ backend/drm/properties.c | 2 ++ include/backend/drm/properties.h | 2 ++ include/wlr/interfaces/wlr_output.h | 7 +++++ include/wlr/types/wlr_output.h | 2 ++ types/wlr_output.c | 5 +++ 6 files changed, 66 insertions(+) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c040d0798..3426cb276 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -540,6 +540,30 @@ bool drm_connector_supports_vrr(struct wlr_drm_connector *conn) { return true; } +static int32_t drm_connector_get_suggested_x(struct wlr_drm_connector *conn) { + struct wlr_drm_backend *drm = conn->backend; + + uint64_t suggested_x; + if (conn->props.suggested_x == 0 || + !get_drm_prop(drm->fd, conn->id, conn->props.suggested_x, &suggested_x)) { + return -1; + } + + return suggested_x; +} + +static int32_t drm_connector_get_suggested_y(struct wlr_drm_connector *conn) { + struct wlr_drm_backend *drm = conn->backend; + + uint64_t suggested_y; + if (conn->props.suggested_y == 0 || + !get_drm_prop(drm->fd, conn->id, conn->props.suggested_y, &suggested_y)) { + return -1; + } + + return suggested_y; +} + static bool drm_connector_commit(struct wlr_output *output) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); struct wlr_drm_backend *drm = conn->backend; @@ -1315,6 +1339,25 @@ static bool update_modes(drmModeConnector *drm_conn, return changes_made; } +static bool update_suggested_position(struct wlr_drm_connector *wlr_conn) { + int32_t suggested_x = drm_connector_get_suggested_x(wlr_conn); + int32_t suggested_y = drm_connector_get_suggested_y(wlr_conn); + + bool position_changed = false; + + if (suggested_x != wlr_conn->output.suggested_x) { + position_changed = true; + wlr_conn->output.suggested_x = suggested_x; + } + + if (suggested_y != wlr_conn->output.suggested_y) { + position_changed = true; + wlr_conn->output.suggested_y = suggested_y; + } + + return position_changed; +} + void scan_drm_connectors(struct wlr_drm_backend *drm) { /* * This GPU is not really a modesetting device. @@ -1423,6 +1466,10 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { if (update_modes(drm_conn, wlr_conn)) { wlr_output_update_available_modes(&wlr_conn->output); } + + if (update_suggested_position(wlr_conn)) { + wlr_output_update_suggested_position(&wlr_conn->output); + } } if (wlr_conn->state == WLR_DRM_CONN_DISCONNECTED && @@ -1458,6 +1505,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { wlr_output_set_description(output, description); update_modes(drm_conn, wlr_conn); + update_suggested_position(wlr_conn); wlr_conn->possible_crtcs = get_possible_crtcs(drm->fd, res, drm_conn); if (wlr_conn->possible_crtcs == 0) { diff --git a/backend/drm/properties.c b/backend/drm/properties.c index de51a3dea..d9dbf06bc 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -25,6 +25,8 @@ static const struct prop_info connector_info[] = { { "PATH", INDEX(path) }, { "link-status", INDEX(link_status) }, { "vrr_capable", INDEX(vrr_capable) }, + { "suggested X", INDEX(suggested_x) }, + { "suggested Y", INDEX(suggested_y) }, #undef INDEX }; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index c2027c4f3..29df1b4b2 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -17,6 +17,8 @@ union wlr_drm_connector_props { uint32_t link_status; // not guaranteed to exist uint32_t path; uint32_t vrr_capable; // not guaranteed to exist + uint32_t suggested_x; + uint32_t suggested_y; // atomic-modesetting only diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 696c2c77f..f3aefc381 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -116,6 +116,13 @@ void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width, * to notify compositors about the change. */ void wlr_output_update_available_modes(struct wlr_output *output); +/** + * Update the output suggested position. + * + * The backend must call this function when the suggested position is updated + * to notify compositors about the change. + */ +void wlr_output_update_suggested_position (struct wlr_output *output); /** * Update the current output status. * diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 1d819aee5..057c479d3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -128,6 +128,7 @@ struct wlr_output { char model[16]; char serial[16]; int32_t phys_width, phys_height; // mm + int32_t suggested_x, suggested_y; // Note: some backends may have zero modes struct wl_list modes; // wlr_output_mode::link @@ -171,6 +172,7 @@ struct wlr_output { struct wl_signal enable; struct wl_signal mode; struct wl_signal available_modes; + struct wl_signal suggested_position; struct wl_signal scale; struct wl_signal transform; struct wl_signal description; diff --git a/types/wlr_output.c b/types/wlr_output.c index d200ac8ac..dbbc7d164 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -263,6 +263,10 @@ void wlr_output_update_available_modes(struct wlr_output *output) { wlr_signal_emit_safe(&output->events.available_modes, output); } +void wlr_output_update_suggested_position (struct wlr_output *output) { + wlr_signal_emit_safe(&output->events.suggested_position, output); +} + void wlr_output_set_transform(struct wlr_output *output, enum wl_output_transform transform) { if (output->transform == transform) { @@ -381,6 +385,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.enable); wl_signal_init(&output->events.mode); wl_signal_init(&output->events.available_modes); + wl_signal_init(&output->events.suggested_position); wl_signal_init(&output->events.scale); wl_signal_init(&output->events.transform); wl_signal_init(&output->events.description);