From 10b0351a595690d74a71c8c62e2f8df5dcaf6dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 25 May 2017 17:20:59 +0800 Subject: [PATCH] Add support for rudimentary fractional scaling When the logical layout mode is used, allow configuring the scaling to be non-integer. Supported scales are so far hard coded to include at most 1, 1.5 and 2, and scales that doesn't result in non-fractional logical monitor sizes are discarded. Wayland outputs are set to have scale ceil(actual_scale) meaning well behaving Wayland clients will provide buffers with buffer scale 2, thus being scaled down to the fractional scale. https://bugzilla.gnome.org/show_bug.cgi?id=765011 --- src/backends/meta-monitor-config-manager.c | 5 +- src/backends/meta-monitor-config-manager.h | 1 + src/backends/meta-monitor-config-store.c | 9 +++- src/backends/meta-monitor-manager-dummy.c | 46 ++++++++++--------- src/backends/meta-monitor-manager-private.h | 11 +++-- src/backends/meta-monitor-manager.c | 23 ++++++---- .../native/meta-monitor-manager-kms.c | 28 ++++++++--- .../x11/meta-monitor-manager-xrandr.c | 7 +-- src/tests/meta-monitor-manager-test.c | 28 ++++++++--- src/tests/monitor-store-unit-tests.c | 8 ++-- src/tests/monitor-unit-tests.c | 6 +-- src/wayland/meta-wayland-outputs.c | 13 +++++- 12 files changed, 126 insertions(+), 59 deletions(-) diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index fae932825..4a12bc6b9 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c @@ -943,13 +943,16 @@ meta_verify_monitor_config (MetaMonitorConfig *monitor_config, gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorManager *monitor_manager, GError **error) { GList *l; int expected_mode_width = 0; int expected_mode_height = 0; - if (logical_monitor_config->scale < 1.0) + if (!meta_monitor_manager_is_scale_supported (monitor_manager, + layout_mode, + logical_monitor_config->scale)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid logical monitor config scale %g", diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h index d9f53424c..f2f21bcfa 100644 --- a/src/backends/meta-monitor-config-manager.h +++ b/src/backends/meta-monitor-config-manager.h @@ -117,6 +117,7 @@ gboolean meta_verify_monitor_config (MetaMonitorConfig *monitor_config, gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorManager *monitor_manager, GError **error); gboolean meta_verify_monitors_config (MetaMonitorsConfig *config, diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c index 1dd6402e5..d86c7a02b 100644 --- a/src/backends/meta-monitor-config-store.c +++ b/src/backends/meta-monitor-config-store.c @@ -630,6 +630,7 @@ handle_end_element (GMarkupParseContext *context, if (!meta_verify_logical_monitor_config (logical_monitor_config, layout_mode, + store->monitor_manager, error)) return; } @@ -1069,13 +1070,17 @@ static void append_logical_monitor_xml (GString *buffer, MetaLogicalMonitorConfig *logical_monitor_config) { + char scale_str[G_ASCII_DTOSTR_BUF_SIZE]; + g_string_append (buffer, " \n"); g_string_append_printf (buffer, " %d\n", logical_monitor_config->layout.x); g_string_append_printf (buffer, " %d\n", logical_monitor_config->layout.y); - g_string_append_printf (buffer, " %g\n", - logical_monitor_config->scale); + g_ascii_dtostr (scale_str, G_ASCII_DTOSTR_BUF_SIZE, + logical_monitor_config->scale); + g_string_append_printf (buffer, " %s\n", + scale_str); if (logical_monitor_config->is_primary) g_string_append (buffer, " yes\n"); if (logical_monitor_config->is_presentation) diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c index c4949df3f..00607265f 100644 --- a/src/backends/meta-monitor-manager-dummy.c +++ b/src/backends/meta-monitor-manager-dummy.c @@ -40,7 +40,13 @@ #define MAX_CRTCS (MAX_MONITORS * 2) #define MAX_MODES (MAX_MONITORS * 4) -static float supported_scales_dummy[] = { +static float supported_scales_dummy_logical[] = { + 1.0, + 1.5, + 2.0 +}; + +static float supported_scales_dummy_physical[] = { 1.0, 2.0 }; @@ -242,20 +248,6 @@ meta_output_dummy_notify_destroy (MetaOutput *output) g_clear_pointer (&output->driver_private, g_free); } -static gboolean -is_scale_supported (float scale) -{ - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (supported_scales_dummy); i++) - { - if (scale == supported_scales_dummy[i]) - return TRUE; - } - - return FALSE; -} - static void meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) { @@ -328,7 +320,9 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) for (i = 0; i < num_monitors && scales_str_list[i]; i++) { float scale = g_ascii_strtod (scales_str_list[i], NULL); - if (is_scale_supported (scale)) + if (meta_monitor_manager_is_scale_supported (manager, + manager->layout_mode, + scale)) monitor_scales[i] = scale; else meta_warning ("Invalid dummy monitor scale\n"); @@ -621,12 +615,22 @@ meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *man } static void -meta_monitor_manager_dummy_get_supported_scales (MetaMonitorManager *manager, - float **scales, - int *n_scales) +meta_monitor_manager_dummy_get_supported_scales (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float **scales, + int *n_scales) { - *scales = supported_scales_dummy; - *n_scales = G_N_ELEMENTS (supported_scales_dummy); + switch (layout_mode) + { + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + *scales = supported_scales_dummy_logical; + *n_scales = G_N_ELEMENTS (supported_scales_dummy_logical); + break; + case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: + *scales = supported_scales_dummy_physical; + *n_scales = G_N_ELEMENTS (supported_scales_dummy_physical); + break; + } } static gboolean diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index 38ec7c7d4..53ffc50a2 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -394,9 +394,10 @@ struct _MetaMonitorManagerClass MetaMonitor *, MetaMonitorMode *); - void (*get_supported_scales) (MetaMonitorManager *, - float **, - int *); + void (*get_supported_scales) (MetaMonitorManager *, + MetaLogicalMonitorLayoutMode , + float **, + int *); MetaMonitorManagerCapability (*get_capabilities) (MetaMonitorManager *); @@ -508,6 +509,10 @@ float meta_monitor_manager_calculate_monitor_mode_scale (MetaMonito MetaMonitor *monitor, MetaMonitorMode *monitor_mode); +gboolean meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float scale); + MetaMonitorManagerCapability meta_monitor_manager_get_capabilities (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 96fde4ad0..43ef91b92 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -407,14 +407,15 @@ meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager, } static void -meta_monitor_manager_get_supported_scales (MetaMonitorManager *manager, - float **scales, - int *n_scales) +meta_monitor_manager_get_supported_scales (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float **scales, + int *n_scales) { MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); - manager_class->get_supported_scales (manager, scales, n_scales); + manager_class->get_supported_scales (manager, layout_mode, scales, n_scales); } MetaMonitorManagerCapability @@ -1633,6 +1634,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, g_variant_builder_init (&supported_scales_builder, G_VARIANT_TYPE ("ad")); meta_monitor_manager_get_supported_scales (manager, + manager->layout_mode, &supported_scales, &n_supported_scales); for (i = 0; i < n_supported_scales; i++) @@ -1703,15 +1705,17 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, #undef LOGICAL_MONITOR_FORMAT #undef LOGICAL_MONITORS_FORMAT -static gboolean -meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, - float scale) +gboolean +meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float scale) { float *supported_scales; int n_supported_scales; int i; meta_monitor_manager_get_supported_scales (manager, + layout_mode, &supported_scales, &n_supported_scales); for (i = 0; i < n_supported_scales; i++) @@ -1736,7 +1740,9 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager, float scale = logical_monitor_config->scale; GList *k; - if (!meta_monitor_manager_is_scale_supported (manager, scale)) + if (!meta_monitor_manager_is_scale_supported (manager, + config->layout_mode, + scale)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Scale not supported by backend"); @@ -1982,6 +1988,7 @@ create_logical_monitor_config_from_variant (MetaMonitorManager *manager if (!meta_verify_logical_monitor_config (logical_monitor_config, layout_mode, + manager, error)) { meta_logical_monitor_config_free (logical_monitor_config); diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 12b4df44c..bb4f2e0d1 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -52,7 +52,13 @@ #define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1) #define SYNC_TOLERANCE 0.01 /* 1 percent */ -static float supported_scales_kms[] = { +static float supported_scales_kms_logical[] = { + 1.0, + 1.5, + 2.0 +}; + +static float supported_scales_kms_physical[] = { 1.0, 2.0 }; @@ -1847,12 +1853,22 @@ meta_monitor_manager_kms_calculate_monitor_mode_scale (MetaMonitorManager *manag } static void -meta_monitor_manager_kms_get_supported_scales (MetaMonitorManager *manager, - float **scales, - int *n_scales) +meta_monitor_manager_kms_get_supported_scales (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float **scales, + int *n_scales) { - *scales = supported_scales_kms; - *n_scales = G_N_ELEMENTS (supported_scales_kms); + switch (layout_mode) + { + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + *scales = supported_scales_kms_logical; + *n_scales = G_N_ELEMENTS (supported_scales_kms_logical); + break; + case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: + *scales = supported_scales_kms_physical; + *n_scales = G_N_ELEMENTS (supported_scales_kms_physical); + break; + } } static MetaMonitorManagerCapability diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index 487978e14..e5d52162c 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -1800,9 +1800,10 @@ meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *ma } static void -meta_monitor_manager_xrandr_get_supported_scales (MetaMonitorManager *manager, - float **scales, - int *n_scales) +meta_monitor_manager_xrandr_get_supported_scales (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float **scales, + int *n_scales) { *scales = supported_scales_xrandr; *n_scales = G_N_ELEMENTS (supported_scales_xrandr); diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c index 2055861bc..cf33102d1 100644 --- a/src/tests/meta-monitor-manager-test.c +++ b/src/tests/meta-monitor-manager-test.c @@ -24,7 +24,13 @@ #include "backends/meta-backend-private.h" #include "backends/meta-monitor-config-manager.h" -static float supported_scales_test[] = { +static float supported_scales_test_logical[] = { + 1.0, + 1.5, + 2.0 +}; + +static float supported_scales_test_physical[] = { 1.0, 2.0 }; @@ -415,12 +421,22 @@ meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *mana } static void -meta_monitor_manager_test_get_supported_scales (MetaMonitorManager *manager, - float **scales, - int *n_scales) +meta_monitor_manager_test_get_supported_scales (MetaMonitorManager *manager, + MetaLogicalMonitorLayoutMode layout_mode, + float **scales, + int *n_scales) { - *scales = supported_scales_test; - *n_scales = G_N_ELEMENTS (supported_scales_test); + switch (layout_mode) + { + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + *scales = supported_scales_test_logical; + *n_scales = G_N_ELEMENTS (supported_scales_test_logical); + break; + case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: + *scales = supported_scales_test_physical; + *n_scales = G_N_ELEMENTS (supported_scales_test_physical); + break; + } } static gboolean diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c index e01562deb..b9a879891 100644 --- a/src/tests/monitor-store-unit-tests.c +++ b/src/tests/monitor-store-unit-tests.c @@ -51,7 +51,7 @@ typedef struct _MonitorTestCaseMonitor typedef struct _MonitorTestCaseLogicalMonitor { MetaRectangle layout; - int scale; + float scale; MetaMonitorTransform transform; gboolean is_primary; gboolean is_presentation; @@ -141,9 +141,9 @@ check_monitor_configuration (MetaMonitorConfigStore *config_store, g_assert (meta_rectangle_equal (&logical_monitor_config->layout, &config_expect->logical_monitors[i].layout)); - g_assert_cmpint (logical_monitor_config->scale, - ==, - config_expect->logical_monitors[i].scale); + g_assert_cmpfloat (logical_monitor_config->scale, + ==, + config_expect->logical_monitors[i].scale); g_assert_cmpint (logical_monitor_config->transform, ==, config_expect->logical_monitors[i].transform); diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c index ae592bb8b..aadd162f9 100644 --- a/src/tests/monitor-unit-tests.c +++ b/src/tests/monitor-unit-tests.c @@ -437,9 +437,9 @@ check_logical_monitor (MonitorTestCase *test_case, g_assert_cmpint (logical_monitor->rect.height, ==, test_logical_monitor->layout.height); - g_assert_cmpint (logical_monitor->scale, - ==, - test_logical_monitor->scale); + g_assert_cmpfloat (logical_monitor->scale, + ==, + test_logical_monitor->scale); g_assert_cmpuint (logical_monitor->transform, ==, test_logical_monitor->transform); diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c index 356a01df9..7cb10f98e 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -111,6 +111,15 @@ calculate_suitable_subpixel_order (MetaLogicalMonitor *logical_monitor) return cogl_subpixel_order_to_wl_output_subpixel (subpixel_order); } +static int +calculate_wayland_output_scale (MetaLogicalMonitor *logical_monitor) +{ + float scale; + + scale = meta_logical_monitor_get_scale (logical_monitor); + return ceilf (scale); +} + static void send_output_events (struct wl_resource *resource, MetaWaylandOutput *wayland_output, @@ -205,7 +214,7 @@ send_output_events (struct wl_resource *resource, { int scale; - scale = (int) meta_logical_monitor_get_scale (logical_monitor); + scale = calculate_wayland_output_scale (logical_monitor); if (need_all_events || old_scale != scale) { @@ -273,7 +282,7 @@ meta_wayland_output_set_logical_monitor (MetaWaylandOutput *wayland_output, if (current_mode == preferred_mode) wayland_output->mode_flags |= WL_OUTPUT_MODE_PREFERRED; - wayland_output->scale = (int) meta_logical_monitor_get_scale (logical_monitor); + wayland_output->scale = calculate_wayland_output_scale (logical_monitor); wayland_output->refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode); }