diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 0e981d59..abfd1c2f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -977,6 +977,37 @@ uint32_t wlr_drm_connector_get_id(struct wlr_output *output) { return conn->id; } +enum wl_output_transform wlr_drm_connector_get_panel_orientation( + struct wlr_output *output) { + struct wlr_drm_connector *conn = get_drm_connector_from_output(output); + if (conn->props.panel_orientation) { + return WL_OUTPUT_TRANSFORM_NORMAL; + } + + char *orientation = get_drm_prop_enum(conn->backend->fd, conn->id, + conn->props.panel_orientation); + if (orientation == NULL) { + return WL_OUTPUT_TRANSFORM_NORMAL; + } + + enum wl_output_transform tr; + if (strcmp(orientation, "Normal") == 0) { + tr = WL_OUTPUT_TRANSFORM_NORMAL; + } else if (strcmp(orientation, "Left Side Up") == 0) { + tr = WL_OUTPUT_TRANSFORM_90; + } else if (strcmp(orientation, "Upside Down") == 0) { + tr = WL_OUTPUT_TRANSFORM_180; + } else if (strcmp(orientation, "Right Side Up") == 0) { + tr = WL_OUTPUT_TRANSFORM_270; + } else { + wlr_drm_conn_log(conn, WLR_ERROR, "Unknown panel orientation: %s", orientation); + tr = WL_OUTPUT_TRANSFORM_NORMAL; + } + + free(orientation); + return tr; +} + static const int32_t subpixel_map[] = { [DRM_MODE_SUBPIXEL_UNKNOWN] = WL_OUTPUT_SUBPIXEL_UNKNOWN, [DRM_MODE_SUBPIXEL_HORIZONTAL_RGB] = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB, diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 2717e09e..f2696593 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -26,6 +26,7 @@ static const struct prop_info connector_info[] = { { "PATH", INDEX(path) }, { "link-status", INDEX(link_status) }, { "non-desktop", INDEX(non_desktop) }, + { "panel orientation", INDEX(panel_orientation) }, { "subconnector", INDEX(subconnector) }, { "vrr_capable", INDEX(vrr_capable) }, #undef INDEX diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index 99d5a92e..10c1ccd0 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -19,6 +19,7 @@ union wlr_drm_connector_props { uint32_t vrr_capable; // not guaranteed to exist uint32_t subconnector; // not guaranteed to exist uint32_t non_desktop; + uint32_t panel_orientation; // not guaranteed to exist // atomic-modesetting only diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 0d8c51e0..0e9f6108 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -61,4 +61,15 @@ typedef struct _drmModeModeInfo drmModeModeInfo; struct wlr_output_mode *wlr_drm_connector_add_mode(struct wlr_output *output, const drmModeModeInfo *mode); +/** + * Get the connector's panel orientation. + * + * On some devices the panel is mounted in the casing in such a way that the + * top side of the panel does not match with the top side of the device. This + * function returns the output transform which needs to be applied to compensate + * for this. + */ +enum wl_output_transform wlr_drm_connector_get_panel_orientation( + struct wlr_output *output); + #endif