kmsdrm: Report the panel orientation hint property

Queries the "panel orientation" property on the connector and reports it in degrees of clockwise rotation via the 'SDL.display.KMSDRM.panel_orientation' display property.

This is provided by the kernel as a hint to userspace applications, and the application itself is ultimately responsible for any required coordinate transformations needed to conform to the requested orientation.
This commit is contained in:
Frank Praznik
2024-05-05 11:05:15 -04:00
parent 0411633bb2
commit 7d47d16526
2 changed files with 91 additions and 4 deletions

View File

@@ -409,6 +409,13 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
* enabled, this will be 1.0. This property can change dynamically when
* SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent.
*
* On KMS/DRM:
*
* - `SDL_PROP_DISPLAY_KMSDRM_ORIENTATION_NUMBER`: the "panel orientation" property
* for the display in degrees of clockwise rotation. Note that this is provided
* only as a hint, and the application is responsible for any coordinate transformations
* needed to conform to the requested display orientation.
*
* \param displayID the instance ID of the display to query
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
@@ -420,9 +427,10 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
*/
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID);
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled"
#define SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT "SDL.display.SDR_white_point"
#define SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT "SDL.display.HDR_headroom"
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled"
#define SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT "SDL.display.SDR_white_point"
#define SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT "SDL.display.HDR_headroom"
#define SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER "SDL.display.KMSDRM.panel_orientation"
/**
* Get the name of a display in UTF-8 encoding.

View File

@@ -673,6 +673,77 @@ static SDL_bool KMSDRM_CrtcGetVrr(uint32_t drm_fd, uint32_t crtc_id)
return SDL_FALSE;
}
static SDL_bool KMSDRM_OrientationPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *orientation_prop_id)
{
drmModeObjectPropertiesPtr drm_props;
drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!drm_props) {
return SDL_FALSE;
}
*orientation_prop_id = KMSDRM_CrtcGetPropId(drm_fd,
drm_props,
"panel orientation");
KMSDRM_drmModeFreeObjectProperties(drm_props);
return SDL_TRUE;
}
static int KMSDRM_CrtcGetOrientation(uint32_t drm_fd, uint32_t crtc_id)
{
uint32_t orientation_prop_id;
drmModeObjectPropertiesPtr props;
int i;
SDL_bool done = SDL_FALSE;
int orientation = 0;
if (!KMSDRM_OrientationPropId(drm_fd, crtc_id, &orientation_prop_id)) {
return orientation;
}
props = KMSDRM_drmModeObjectGetProperties(drm_fd,
crtc_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!props) {
return orientation;
}
for (i = 0; i < props->count_props && !done; ++i) {
drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
if (!drm_prop) {
continue;
}
if (drm_prop->prop_id == orientation_prop_id && (drm_prop->flags & DRM_MODE_PROP_ENUM)) {
if (drm_prop->count_enums) {
/* "Normal" is the default of no rotation (0 degrees) */
if (SDL_strcmp(drm_prop->enums[0].name, "Left Side Up") == 0) {
orientation = 90;
} else if (SDL_strcmp(drm_prop->enums[0].name, "Upside Down") == 0) {
orientation = 180;
} else if (SDL_strcmp(drm_prop->enums[0].name, "Right Side Up") == 0) {
orientation = 270;
}
}
done = SDL_TRUE;
}
KMSDRM_drmModeFreeProperty(drm_prop);
}
KMSDRM_drmModeFreeObjectProperties(props);
return orientation;
}
/* Gets a DRM connector, builds an SDL_Display with it, and adds it to the
list of SDL Displays in _this->displays[] */
static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connector, drmModeRes *resources)
@@ -683,6 +754,9 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
SDL_DisplayModeData *modedata = NULL;
drmModeEncoder *encoder = NULL;
drmModeCrtc *crtc = NULL;
SDL_DisplayID display_id;
SDL_PropertiesID display_properties;
int orientation;
int mode_index;
int i, j;
int ret = 0;
@@ -867,11 +941,16 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
display.desktop_mode.driverdata = modedata;
/* Add the display to the list of SDL displays. */
if (SDL_AddVideoDisplay(&display, SDL_FALSE) == 0) {
display_id = SDL_AddVideoDisplay(&display, SDL_FALSE);
if (!display_id) {
ret = -1;
goto cleanup;
}
orientation = KMSDRM_CrtcGetOrientation(viddata->drm_fd, crtc->crtc_id);
display_properties = SDL_GetDisplayProperties(display_id);
SDL_SetNumberProperty(display_properties, SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER, orientation);
cleanup:
if (encoder) {
KMSDRM_drmModeFreeEncoder(encoder);