mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
monitor-manager: Take drm-connector panel-orientation property into account
Some x86 clamshell design devices use portrait tablet LCD panels while they should use a landscape panel, resoluting in a 90 degree rotated picture. Newer kernels detect this and rotate the fb console in software to compensate. These kernels also export their knowledge of the LCD panel orientation vs the casing in a "panel orientation" drm_connector property. This commit adds support to mutter for reading the "panel orientation" and transparently (from a mutter consumer's pov) fixing this by applying a (hidden) rotation transform to compensate for the panel orientation. Related: https://bugs.freedesktop.org/show_bug.cgi?id=94894 https://bugzilla.gnome.org/show_bug.cgi?id=782294
This commit is contained in:
parent
2b3040d04f
commit
7917b083cb
@ -103,7 +103,8 @@ derive_monitor_transform (MetaMonitor *monitor)
|
||||
|
||||
main_output = meta_monitor_get_main_output (monitor);
|
||||
|
||||
return main_output->crtc->transform;
|
||||
return meta_monitor_crtc_to_logical_transform (monitor,
|
||||
main_output->crtc->transform);
|
||||
}
|
||||
|
||||
MetaLogicalMonitor *
|
||||
|
@ -152,11 +152,10 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
||||
}
|
||||
|
||||
transform = data->logical_monitor_config->transform;
|
||||
if (meta_monitor_manager_is_transform_handled (data->monitor_manager,
|
||||
crtc,
|
||||
transform))
|
||||
crtc_transform = transform;
|
||||
else
|
||||
crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
||||
if (!meta_monitor_manager_is_transform_handled (data->monitor_manager,
|
||||
crtc,
|
||||
crtc_transform))
|
||||
crtc_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
|
||||
|
@ -384,4 +384,11 @@ meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
|
||||
return (transform % 2);
|
||||
}
|
||||
|
||||
/* Returns true if transform involves flipping */
|
||||
static inline gboolean
|
||||
meta_monitor_transform_is_flipped (MetaMonitorTransform transform)
|
||||
{
|
||||
return (transform >= META_MONITOR_TRANSFORM_FLIPPED);
|
||||
}
|
||||
|
||||
#endif /* META_MONITOR_MANAGER_PRIVATE_H */
|
||||
|
@ -354,6 +354,37 @@ meta_monitor_get_connector_type (MetaMonitor *monitor)
|
||||
return output->connector_type;
|
||||
}
|
||||
|
||||
MetaMonitorTransform
|
||||
meta_monitor_logical_to_crtc_transform (MetaMonitor *monitor,
|
||||
MetaMonitorTransform transform)
|
||||
{
|
||||
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
||||
MetaMonitorTransform new_transform;
|
||||
|
||||
new_transform = (transform + output->panel_orientation_transform) %
|
||||
META_MONITOR_TRANSFORM_FLIPPED;
|
||||
if (meta_monitor_transform_is_flipped (transform))
|
||||
new_transform += META_MONITOR_TRANSFORM_FLIPPED;
|
||||
|
||||
return new_transform;
|
||||
}
|
||||
|
||||
MetaMonitorTransform
|
||||
meta_monitor_crtc_to_logical_transform (MetaMonitor *monitor,
|
||||
MetaMonitorTransform transform)
|
||||
{
|
||||
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
||||
MetaMonitorTransform new_transform;
|
||||
|
||||
new_transform = (transform + META_MONITOR_TRANSFORM_FLIPPED -
|
||||
output->panel_orientation_transform) %
|
||||
META_MONITOR_TRANSFORM_FLIPPED;
|
||||
if (meta_monitor_transform_is_flipped (transform))
|
||||
new_transform += META_MONITOR_TRANSFORM_FLIPPED;
|
||||
|
||||
return new_transform;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_finalize (GObject *object)
|
||||
{
|
||||
@ -423,6 +454,29 @@ meta_monitor_add_mode (MetaMonitor *monitor,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MetaMonitorModeSpec
|
||||
meta_monitor_create_spec (MetaMonitor *monitor,
|
||||
int width,
|
||||
int height,
|
||||
MetaCrtcMode *crtc_mode)
|
||||
{
|
||||
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
||||
|
||||
if (meta_monitor_transform_is_rotated (output->panel_orientation_transform))
|
||||
{
|
||||
int temp = width;
|
||||
width = height;
|
||||
height = temp;
|
||||
}
|
||||
|
||||
return (MetaMonitorModeSpec) {
|
||||
.width = width,
|
||||
.height = height,
|
||||
.refresh_rate = crtc_mode->refresh_rate,
|
||||
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
|
||||
{
|
||||
@ -443,12 +497,10 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
|
||||
gboolean replace;
|
||||
|
||||
mode = g_new0 (MetaMonitorMode, 1);
|
||||
mode->spec = (MetaMonitorModeSpec) {
|
||||
.width = crtc_mode->width,
|
||||
.height = crtc_mode->height,
|
||||
.refresh_rate = crtc_mode->refresh_rate,
|
||||
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
|
||||
},
|
||||
mode->spec = meta_monitor_create_spec (monitor,
|
||||
crtc_mode->width,
|
||||
crtc_mode->height,
|
||||
crtc_mode);
|
||||
mode->id = generate_mode_id (&mode->spec);
|
||||
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
|
||||
mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
|
||||
@ -780,12 +832,8 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
|
||||
mode->is_tiled = TRUE;
|
||||
meta_monitor_tiled_calculate_tiled_size (monitor, &width, &height);
|
||||
|
||||
mode->parent.spec = (MetaMonitorModeSpec) {
|
||||
.width = width,
|
||||
.height = height,
|
||||
.refresh_rate = reference_crtc_mode->refresh_rate,
|
||||
.flags = reference_crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
|
||||
};
|
||||
mode->parent.spec =
|
||||
meta_monitor_create_spec (monitor, width, height, reference_crtc_mode);
|
||||
mode->parent.id = generate_mode_id (&mode->parent.spec);
|
||||
|
||||
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
|
||||
@ -895,12 +943,10 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
|
||||
mode = g_new0 (MetaMonitorModeTiled, 1);
|
||||
|
||||
mode->is_tiled = FALSE;
|
||||
mode->parent.spec = (MetaMonitorModeSpec) {
|
||||
.width = crtc_mode->width,
|
||||
.height = crtc_mode->height,
|
||||
.refresh_rate = crtc_mode->refresh_rate,
|
||||
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
|
||||
};
|
||||
mode->parent.spec = meta_monitor_create_spec (monitor,
|
||||
crtc_mode->width,
|
||||
crtc_mode->height,
|
||||
crtc_mode);
|
||||
mode->parent.id = generate_mode_id (&mode->parent.spec);
|
||||
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
|
||||
g_list_length (monitor_priv->outputs));
|
||||
|
@ -145,6 +145,16 @@ const char * meta_monitor_get_serial (MetaMonitor *monitor);
|
||||
|
||||
MetaConnectorType meta_monitor_get_connector_type (MetaMonitor *monitor);
|
||||
|
||||
/* This function returns the transform corrected for the panel orientation */
|
||||
MetaMonitorTransform meta_monitor_logical_to_crtc_transform (MetaMonitor *monitor,
|
||||
MetaMonitorTransform transform);
|
||||
/*
|
||||
* This function converts a transform corrected for the panel orientation
|
||||
* to its logical (user-visible) transform.
|
||||
*/
|
||||
MetaMonitorTransform meta_monitor_crtc_to_logical_transform (MetaMonitor *monitor,
|
||||
MetaMonitorTransform transform);
|
||||
|
||||
uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled);
|
||||
|
||||
gboolean meta_monitor_get_suggested_position (MetaMonitor *monitor,
|
||||
|
@ -78,6 +78,7 @@ struct _MetaOutput
|
||||
CoglSubpixelOrder subpixel_order;
|
||||
|
||||
MetaConnectorType connector_type;
|
||||
MetaMonitorTransform panel_orientation_transform;
|
||||
|
||||
MetaCrtcMode *preferred_mode;
|
||||
MetaCrtcMode **modes;
|
||||
|
@ -229,9 +229,37 @@ meta_output_kms_read_edid (MetaOutput *output)
|
||||
}
|
||||
|
||||
static void
|
||||
find_connector_properties (MetaGpuKms *gpu_kms,
|
||||
MetaOutputKms *output_kms)
|
||||
handle_panel_orientation (MetaOutput *output,
|
||||
drmModePropertyPtr prop,
|
||||
int orientation)
|
||||
{
|
||||
const char *name = prop->enums[orientation].name;
|
||||
|
||||
if (strcmp (name, "Upside Down") == 0)
|
||||
{
|
||||
output->panel_orientation_transform = META_MONITOR_TRANSFORM_180;
|
||||
}
|
||||
else if (strcmp (name, "Left Side Up") == 0)
|
||||
{
|
||||
/* Left side up, rotate 90 degrees counter clockwise to correct */
|
||||
output->panel_orientation_transform = META_MONITOR_TRANSFORM_90;
|
||||
}
|
||||
else if (strcmp (name, "Right Side Up") == 0)
|
||||
{
|
||||
/* Right side up, rotate 270 degrees counter clockwise to correct */
|
||||
output->panel_orientation_transform = META_MONITOR_TRANSFORM_270;
|
||||
}
|
||||
else
|
||||
{
|
||||
output->panel_orientation_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_connector_properties (MetaGpuKms *gpu_kms,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaOutputKms *output_kms = output->driver_private;
|
||||
drmModeConnector *connector = output_kms->connector;
|
||||
int fd;
|
||||
int i;
|
||||
@ -268,6 +296,10 @@ find_connector_properties (MetaGpuKms *gpu_kms,
|
||||
output_kms->hotplug_mode_update = connector->prop_values[i];
|
||||
else if (strcmp (prop->name, "scaling mode") == 0)
|
||||
output_kms->has_scaling = TRUE;
|
||||
else if ((prop->flags & DRM_MODE_PROP_ENUM) &&
|
||||
strcmp (prop->name, "panel orientation") == 0)
|
||||
handle_panel_orientation (output, prop,
|
||||
output_kms->connector->prop_values[i]);
|
||||
|
||||
drmModeFreeProperty (prop);
|
||||
}
|
||||
@ -469,7 +501,7 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
|
||||
}
|
||||
|
||||
output_kms->connector = connector;
|
||||
find_connector_properties (gpu_kms, output_kms);
|
||||
find_connector_properties (gpu_kms, output);
|
||||
|
||||
init_output_modes (output, gpu_kms);
|
||||
|
||||
|
@ -2342,8 +2342,12 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
{
|
||||
MetaMonitor *main_monitor;
|
||||
MetaOutput *main_output;
|
||||
MetaMonitorTransform crtc_transform;
|
||||
main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
||||
main_output = meta_monitor_get_main_output (main_monitor);
|
||||
crtc_transform =
|
||||
meta_monitor_logical_to_crtc_transform (main_monitor,
|
||||
logical_monitor->transform);
|
||||
|
||||
/*
|
||||
* Pick any monitor and output and check; all CRTCs of a logical monitor will
|
||||
@ -2352,10 +2356,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
|
||||
if (meta_monitor_manager_is_transform_handled (monitor_manager,
|
||||
main_output->crtc,
|
||||
logical_monitor->transform))
|
||||
crtc_transform))
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
else
|
||||
return logical_monitor->transform;
|
||||
return crtc_transform;
|
||||
}
|
||||
|
||||
static MetaRendererView *
|
||||
|
@ -604,6 +604,38 @@ output_get_connector_type (MetaOutput *output)
|
||||
return META_CONNECTOR_TYPE_Unknown;
|
||||
}
|
||||
|
||||
static gint
|
||||
output_get_panel_orientation_transform (MetaOutput *output)
|
||||
{
|
||||
Display *xdisplay = xdisplay_from_output (output);
|
||||
unsigned long nitems, bytes_after;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
g_autofree unsigned char *buffer = NULL;
|
||||
g_autofree char *str = NULL;
|
||||
|
||||
atom = XInternAtom (xdisplay, "panel orientation", False);
|
||||
XRRGetOutputProperty (xdisplay, (XID)output->winsys_id, atom,
|
||||
0, G_MAXLONG, False, False, XA_ATOM,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
str = XGetAtomName (xdisplay, *(Atom *)buffer);
|
||||
if (strcmp (str, "Upside Down") == 0)
|
||||
return META_MONITOR_TRANSFORM_180;
|
||||
|
||||
if (strcmp (str, "Left Side Up") == 0)
|
||||
return META_MONITOR_TRANSFORM_90;
|
||||
|
||||
if (strcmp (str, "Right Side Up") == 0)
|
||||
return META_MONITOR_TRANSFORM_270;
|
||||
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
}
|
||||
|
||||
static void
|
||||
output_get_tile_info (MetaOutput *output)
|
||||
{
|
||||
@ -744,6 +776,8 @@ meta_create_xrandr_output (MetaGpuXrandr *gpu_xrandr,
|
||||
output->suggested_x = output_get_suggested_x (output);
|
||||
output->suggested_y = output_get_suggested_y (output);
|
||||
output->connector_type = output_get_connector_type (output);
|
||||
output->panel_orientation_transform =
|
||||
output_get_panel_orientation_transform (output);
|
||||
|
||||
output_get_tile_info (output);
|
||||
output_get_modes (output, xrandr_output);
|
||||
|
@ -50,8 +50,12 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
{
|
||||
MetaMonitor *main_monitor;
|
||||
MetaOutput *main_output;
|
||||
MetaMonitorTransform crtc_transform;
|
||||
main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
||||
main_output = meta_monitor_get_main_output (main_monitor);
|
||||
crtc_transform =
|
||||
meta_monitor_logical_to_crtc_transform (main_monitor,
|
||||
logical_monitor->transform);
|
||||
|
||||
/*
|
||||
* Pick any monitor and output and check; all CRTCs of a logical monitor will
|
||||
@ -60,10 +64,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
|
||||
if (meta_monitor_manager_is_transform_handled (monitor_manager,
|
||||
main_output->crtc,
|
||||
logical_monitor->transform))
|
||||
crtc_transform))
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
else
|
||||
return logical_monitor->transform;
|
||||
return crtc_transform;
|
||||
}
|
||||
|
||||
static MetaRendererView *
|
||||
|
Loading…
Reference in New Issue
Block a user