diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c index 2b21b1a79..d2faa0f26 100644 --- a/src/backends/meta-logical-monitor.c +++ b/src/backends/meta-logical-monitor.c @@ -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 * diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index 9e55d122b..41d6b4bce 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c @@ -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, diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index 59494db5d..c05a076e1 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -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 */ diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index cfd045956..20f25440b 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -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)); diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index faf4dd061..bc7977886 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -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, diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h index e65826fda..a63a1cd10 100644 --- a/src/backends/meta-output.h +++ b/src/backends/meta-output.h @@ -78,6 +78,7 @@ struct _MetaOutput CoglSubpixelOrder subpixel_order; MetaConnectorType connector_type; + MetaMonitorTransform panel_orientation_transform; MetaCrtcMode *preferred_mode; MetaCrtcMode **modes; diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index 544eb9593..b15ffd974 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -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); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 2e7878ae2..23d9fda26 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -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 * diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c index 48c8fbbb7..4fed6e5d9 100644 --- a/src/backends/x11/meta-output-xrandr.c +++ b/src/backends/x11/meta-output-xrandr.c @@ -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); diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c index d5ad77877..a0c26c9b5 100644 --- a/src/backends/x11/nested/meta-renderer-x11-nested.c +++ b/src/backends/x11/nested/meta-renderer-x11-nested.c @@ -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 *