monitor-unit-tests: Add tests to verify the computed scaling values

Scaling values computation code served us well in the past years but
it's quite delicate and it has some issues in edge cases, so add a test
that verifies that the computed scaling values for all the most common
resolutions (and some that may be common in future) are what we expect
to be.

This may also serve us in future when we'd define a better algorithm to
compute the preferred scale, but this not the day.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1878>
This commit is contained in:
Marco Trevisan (Treviño) 2021-05-28 15:48:46 +02:00
parent 4ca5a97ea8
commit b088dbd90b
3 changed files with 402 additions and 1 deletions

View File

@ -21,6 +21,8 @@
#include "tests/monitor-test-utils.h" #include "tests/monitor-test-utils.h"
#include <float.h>
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/meta-crtc.h" #include "backends/meta-crtc.h"
#include "backends/meta-logical-monitor.h" #include "backends/meta-logical-monitor.h"
@ -778,3 +780,83 @@ create_monitor_test_setup (MonitorTestCaseSetup *setup,
return test_setup; return test_setup;
} }
static void
check_expected_scales (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
MetaMonitorScalesConstraint constraints,
int n_expected_scales,
float *expected_scales)
{
g_autofree float *scales = NULL;
int n_supported_scales;
int width, height;
int i;
scales = meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
&n_supported_scales);
g_assert_cmpint (n_expected_scales, ==, n_supported_scales);
meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
for (i = 0; i < n_supported_scales; i++)
{
g_assert_cmpfloat (scales[i], >, 0.0);
g_assert_cmpfloat_with_epsilon (scales[i], expected_scales[i], 0.000001);
if (!(constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC))
{
/* Also ensure that the scale will generate an integral resolution */
g_assert_cmpfloat (fmodf (width / scales[i], 1.0), ==, 0.0);
g_assert_cmpfloat (fmodf (height / scales[i], 1.0), ==, 0.0);
}
}
}
void check_monitor_scales (MonitorTestCaseExpect *expect,
MetaMonitorScalesConstraint scales_constraints)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
GList *monitors;
GList *l;
int i;
monitors = meta_monitor_manager_get_monitors (monitor_manager);
g_assert_cmpuint (g_list_length (monitors), ==, expect->n_monitors);
for (l = monitors, i = 0; l; l = l->next, i++)
{
MetaMonitor *monitor = l->data;
MonitorTestCaseMonitor *expected_monitor = &expect->monitors[i];
GList *modes = meta_monitor_get_modes (monitor);
GList *k;
int j;
g_debug ("Checking monitor %d", i);
g_assert_cmpuint (g_list_length (modes), ==, expected_monitor->n_modes);
for (j = 0, k = modes; k; k = k->next, j++)
{
MetaMonitorMode *monitor_mode = k->data;
MetaMonitorTestCaseMonitorMode *expected_mode =
&expected_monitor->modes[j];
int width, height;
meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
g_debug ("Checking %s scaling values for mode %dx%d",
(scales_constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) ?
"integer" : "fractional", width, height);
g_assert_cmpint (width, ==, expected_mode->width);
g_assert_cmpint (height, ==, expected_mode->height);
check_expected_scales (monitor, monitor_mode, scales_constraints,
expected_mode->n_scales,
expected_mode->scales);
}
}
}

View File

@ -24,13 +24,15 @@
#include "tests/meta-monitor-manager-test.h" #include "tests/meta-monitor-manager-test.h"
#include "backends/meta-crtc.h" #include "backends/meta-crtc.h"
#include "backends/meta-monitor.h"
#include "backends/meta-output.h" #include "backends/meta-output.h"
#define MAX_N_MODES 10 #define MAX_N_MODES 25
#define MAX_N_OUTPUTS 10 #define MAX_N_OUTPUTS 10
#define MAX_N_CRTCS 10 #define MAX_N_CRTCS 10
#define MAX_N_MONITORS 10 #define MAX_N_MONITORS 10
#define MAX_N_LOGICAL_MONITORS 10 #define MAX_N_LOGICAL_MONITORS 10
#define MAX_N_SCALES 20
/* /*
* The following structures are used to define test cases. * The following structures are used to define test cases.
@ -138,6 +140,8 @@ typedef struct _MonitorTestCaseMonitorMode
int width; int width;
int height; int height;
float refresh_rate; float refresh_rate;
int n_scales;
float scales[MAX_N_SCALES];
MetaCrtcModeFlag flags; MetaCrtcModeFlag flags;
MetaTestCaseMonitorCrtcMode crtc_modes[MAX_N_CRTCS]; MetaTestCaseMonitorCrtcMode crtc_modes[MAX_N_CRTCS];
} MetaMonitorTestCaseMonitorMode; } MetaMonitorTestCaseMonitorMode;
@ -199,6 +203,8 @@ void set_custom_monitor_config (const char *filename);
char * read_file (const char *file_path); char * read_file (const char *file_path);
void check_monitor_configuration (MonitorTestCaseExpect *expect); void check_monitor_configuration (MonitorTestCaseExpect *expect);
void check_monitor_scales (MonitorTestCaseExpect *expect,
MetaMonitorScalesConstraint scales_constraints);
MetaMonitorTestSetup * create_monitor_test_setup (MonitorTestCaseSetup *setup, MetaMonitorTestSetup * create_monitor_test_setup (MonitorTestCaseSetup *setup,
MonitorTestFlag flags); MonitorTestFlag flags);

View File

@ -5727,6 +5727,316 @@ meta_test_monitor_migrated_wiggle (void)
g_error ("Failed to remove test data output file: %s", error->message); g_error ("Failed to remove test data output file: %s", error->message);
} }
static void
meta_test_monitor_supported_fractional_scales (void)
{
MonitorTestCase test_case = {
.setup = {
.n_modes = 21,
.modes = {
{
.width = 800,
.height = 600,
.refresh_rate = 60.0
},
{
.width = 1024,
.height = 768,
.refresh_rate = 60.0
},
{
.width = 1280,
.height = 720,
.refresh_rate = 60.0,
},
{
.width = 1280,
.height = 800,
.refresh_rate = 60.0,
},
{
.width = 1280,
.height = 1024,
.refresh_rate = 60.0,
},
{
.width = 1366,
.height = 768,
.refresh_rate = 60.0,
},
{
.width = 1440,
.height = 900,
.refresh_rate = 60.0,
},
{
.width = 1400,
.height = 1050,
.refresh_rate = 60.0,
},
{
.width = 1600,
.height = 900,
.refresh_rate = 60.0,
},
{
.width = 1920,
.height = 1080,
.refresh_rate = 60.0,
},
{
.width = 1920,
.height = 1200,
.refresh_rate = 60.0,
},
{
.width = 2650,
.height = 1440,
.refresh_rate = 60.0,
},
{
.width = 2880,
.height = 1800,
.refresh_rate = 60.0,
},
{
.width = 3200,
.height = 1800,
.refresh_rate = 60.0,
},
{
.width = 3200,
.height = 2048,
.refresh_rate = 60.0,
},
{
.width = 3840,
.height = 2160,
.refresh_rate = 60.0,
},
{
.width = 3840,
.height = 2400,
.refresh_rate = 60.0,
},
{
.width = 4096,
.height = 2160,
.refresh_rate = 60.0,
},
{
.width = 4096,
.height = 3072,
.refresh_rate = 60.0,
},
{
.width = 5120,
.height = 2880,
.refresh_rate = 60.0,
},
{
.width = 7680,
.height = 4320,
.refresh_rate = 60.0,
},
},
.outputs = {
{
.crtc = -1,
.modes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20 },
.n_modes = 21,
.preferred_mode = 5,
.possible_crtcs = { 0 },
.n_possible_crtcs = 1,
.width_mm = 222,
.height_mm = 125
}
},
.n_outputs = 1,
.crtcs = {
{
.current_mode = 0
}
},
.n_crtcs = 1
},
.expect = {
.n_monitors = 1,
.monitors = {
{
.n_modes = 21,
.modes = {
{
.width = 800,
.height = 600,
.n_scales = 1,
.scales = { 1.000000 },
},
{
.width = 1024,
.height = 768,
.n_scales = 2,
.scales = { 1.000000, 1.24878049 },
},
{
.width = 1280,
.height = 720,
.n_scales = 3,
.scales = { 1.000000, 1.250000, 1.509434 },
},
{
.width = 1280,
.height = 800,
.n_scales = 3,
.scales = { 1.000000, 1.250000, 1.495327 },
},
{
.width = 1280,
.height = 1024,
.n_scales = 4,
.scales = { 1.000000, 1.248780, 1.497076, 1.753425 },
},
{
.width = 1366,
.height = 768,
.n_scales = 1,
.scales = { 1.000000 },
},
{
.width = 1440,
.height = 900,
.n_scales = 4,
.scales = { 1.000000, 1.250000, 1.500000, 1.747573 },
},
{
.width = 1400,
.height = 1050,
.n_scales = 4,
.scales = { 1.000000, 1.250000, 1.502146, 1.750000 },
},
{
.width = 1600,
.height = 900,
.n_scales = 4,
.scales = { 1.000000, 1.250000, 1.492537, 1.754386 },
},
{
.width = 1920,
.height = 1080,
.n_scales = 6,
.scales = { 1.000000, 1.250000, 1.500000, 1.739130, 2.000000,
2.307692 },
},
{
.width = 1920,
.height = 1200,
.n_scales = 6,
.scales = { 1.000000, 1.250000, 1.500000, 1.751825, 2.000000,
2.242991 },
},
{
.width = 2650,
.height = 1440,
.n_scales = 6,
.scales = { 1.000000, 1.250000, 1.428571, 1.666667, 2.000000,
2.500000
},
},
{
.width = 2880,
.height = 1800,
.n_scales = 11,
.scales = { 1.000000, 1.250000, 1.500000, 1.747573, 2.000000,
2.250000, 2.500000, 2.748092, 3.000000, 3.243243,
3.495146
},
},
{
.width = 3200,
.height = 1800,
.n_scales = 12,
.scales = { 1.000000, 1.250000, 1.503759, 1.754386, 2.000000,
2.247191, 2.500000, 2.739726, 2.985075, 3.225806,
3.508772, 3.773585
},
},
{
.width = 3200,
.height = 2048,
.n_scales = 13,
.scales = { 1.000000, 1.254902, 1.505882, 1.753425, 2.000000,
2.245614, 2.509804, 2.723404, 2.976744, 3.282051,
3.459460, 3.764706, 4.000000,
},
},
{
.width = 3840,
.height = 2160,
.n_scales = 13,
.scales = { 1.000000, 1.250000, 1.500000, 1.751825, 2.000000,
2.201835, 2.500000, 2.758621, 3.000000, 3.243243,
3.478261, 3.750000, 4.000000
},
},
{
.width = 3840,
.height = 2400,
.n_scales = 13,
.scales = { 1.000000, 1.250000, 1.500000, 1.751825, 2.000000,
2.253521, 2.500000, 2.742857, 3.000000, 3.243243,
3.503650, 3.750000, 4.000000
},
},
{
.width = 4096,
.height = 2160,
.n_scales = 10,
.scales = { 1.000000, 1.333333, 1.454545, 1.777778, 2.000000,
2.666667, 2.666667, 3.200000, 3.200000, 4.000000
}
},
{
.width = 4096,
.height = 3072,
.n_scales = 13,
.scales = { 1.000000, 1.250305, 1.499268, 1.750427, 2.000000,
2.245614, 2.497561, 2.752688, 3.002933, 3.250794,
3.494880, 3.750916, 4.000000
},
},
{
.width = 5120,
.height = 2880,
.n_scales = 13,
.scales = { 1.000000, 1.250000, 1.495327, 1.748634, 2.000000,
2.253521, 2.500000, 2.758621, 2.990654, 3.265306,
3.516484, 3.764706, 4.000000
},
},
{
.width = 7680,
.height = 4320,
.n_scales = 13,
.scales = { 1.000000, 1.250000, 1.500000, 1.751825, 2.000000,
2.211982, 2.500000, 2.742857, 3.000000, 3.243243,
3.503650, 3.750000, 4.000000
},
},
},
},
},
},
};
MetaMonitorTestSetup *test_setup;
test_setup = create_monitor_test_setup (&test_case.setup,
MONITOR_TEST_FLAG_NO_STORED);
emulate_hotplug (test_setup);
check_monitor_scales (&test_case.expect, META_MONITOR_SCALES_CONSTRAINT_NONE);
}
static void static void
test_case_setup (void **fixture, test_case_setup (void **fixture,
const void *data) const void *data)
@ -5853,6 +6163,9 @@ init_monitor_tests (void)
add_monitor_test ("/backends/monitor/wm/tiling", add_monitor_test ("/backends/monitor/wm/tiling",
meta_test_monitor_wm_tiling); meta_test_monitor_wm_tiling);
add_monitor_test ("/backends/monitor/suppported_scales/fractional",
meta_test_monitor_supported_fractional_scales);
} }
void void