From 3e1e2cb91f6f1f9332a72f65d737b727260b2a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 28 May 2021 19:45:42 +0200 Subject: [PATCH] monitor: Do not overlap when checking for applicable scaling values With some resolutions (such as 4096x2160) we may compute duplicated scale factors because we used a too wide threshold to check for an applicable value. In fact, while when we're at the first and last values it's fine to search applicable values up to SCALE_FACTORS_STEP, on intermediate ones we should stop in the middle of it, or we're end up overlapping the previous scaling value domain. In the said example in fact we were returning 2.666667 both when looking to a scaling value close to 2.75 and 3.00 as the upper bound of 2.75 (3.0) was overlapping with the lower bound of 3.0 (2.75). With the current code, the lower and upper bounds will be instead 2.875. Adapt test to this, and this allows to also ensure that we're always returning a sorted and unique list of scales (which is useful as also g-c-c can ensure that this is true). Part-of: --- src/backends/meta-monitor.c | 19 ++++++++++++++----- src/tests/monitor-test-utils.c | 7 +++++++ src/tests/monitor-unit-tests.c | 4 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index e4e803672..5fc8b1f85 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -1767,7 +1767,8 @@ meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode) static float get_closest_scale_factor_for_resolution (float width, float height, - float scale) + float scale, + float threshold) { unsigned int i, j; float scaled_h; @@ -1799,8 +1800,8 @@ get_closest_scale_factor_for_resolution (float width, current_scale = width / scaled_w; scaled_h = height / current_scale; - if (current_scale >= scale + SCALE_FACTORS_STEPS || - current_scale <= scale - SCALE_FACTORS_STEPS || + if (current_scale >= scale + threshold || + current_scale <= scale - threshold || current_scale < MINIMUM_SCALE_FACTOR || current_scale > MAXIMUM_SCALE_FACTOR) { @@ -1851,14 +1852,22 @@ meta_monitor_calculate_supported_scales (MetaMonitor *monitor, } else { + float max_bound; + + if (i == floorf (MINIMUM_SCALE_FACTOR) || + i == ceilf (MAXIMUM_SCALE_FACTOR)) + max_bound = SCALE_FACTORS_STEPS; + else + max_bound = SCALE_FACTORS_STEPS / 2.0; + for (j = 0; j < SCALE_FACTORS_PER_INTEGER; j++) { float scale; float scale_value = i + j * SCALE_FACTORS_STEPS; scale = get_closest_scale_factor_for_resolution (width, height, - scale_value); - + scale_value, + max_bound); if (scale > 0.0) g_array_append_val (supported_scales, scale); } diff --git a/src/tests/monitor-test-utils.c b/src/tests/monitor-test-utils.c index 00823d22f..c5e838c85 100644 --- a/src/tests/monitor-test-utils.c +++ b/src/tests/monitor-test-utils.c @@ -811,6 +811,13 @@ check_expected_scales (MetaMonitor *monitor, g_assert_cmpfloat (fmodf (width / scales[i], 1.0), ==, 0.0); g_assert_cmpfloat (fmodf (height / scales[i], 1.0), ==, 0.0); } + + if (i > 0) + { + /* And that scales are sorted and unique */ + g_assert_cmpfloat (scales[i], >, scales[i-1]); + g_assert_false (G_APPROX_VALUE (scales[i], scales[i-1], 0.000001)); + } } } diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c index 06b170318..d7d3fdc35 100644 --- a/src/tests/monitor-unit-tests.c +++ b/src/tests/monitor-unit-tests.c @@ -6273,9 +6273,9 @@ meta_test_monitor_supported_fractional_scales (void) { .width = 4096, .height = 2160, - .n_scales = 10, + .n_scales = 8, .scales = { 1.000000, 1.333333, 1.454545, 1.777778, 2.000000, - 2.666667, 2.666667, 3.200000, 3.200000, 4.000000 + 2.666667, 3.200000, 4.000000 } }, {