From a9c9b8935849c10159c4abd5cfb4f88ba9a8ee1d Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Wed, 1 Mar 2023 23:36:42 +0100 Subject: tests/wayland: Add test for fractional-scale protocol For now test that a simple fullscreen client on a FullHD screen selects the expected values. Part-of: --- src/tests/meson.build | 5 +- .../full-hd-fractional-scale-1.25.xml | 23 +++ .../full-hd-fractional-scale-1.5.xml | 23 +++ src/tests/wayland-fractional-scale-test.c | 169 +++++++++++++++++++ src/tests/wayland-test-clients/fractional-scale.c | 182 +++++++++++++++++++++ src/tests/wayland-test-clients/meson.build | 3 + .../wayland-test-client-utils.c | 6 + .../wayland-test-client-utils.h | 2 + 8 files changed, 411 insertions(+), 2 deletions(-) create mode 100644 src/tests/monitor-configs/full-hd-fractional-scale-1.25.xml create mode 100644 src/tests/monitor-configs/full-hd-fractional-scale-1.5.xml create mode 100644 src/tests/wayland-fractional-scale-test.c create mode 100644 src/tests/wayland-test-clients/fractional-scale.c diff --git a/src/tests/meson.build b/src/tests/meson.build index 3dd8a59b9..3768b83da 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -431,10 +431,11 @@ if have_native_tests ], }, { - 'name': 'wayland-client-tests', + 'name': 'wayland-fractional-scale', 'suite': 'wayland', 'sources': [ - 'wayland-client-tests.c', + 'wayland-fractional-scale-test.c', + wayland_test_utils, ], }, { diff --git a/src/tests/monitor-configs/full-hd-fractional-scale-1.25.xml b/src/tests/monitor-configs/full-hd-fractional-scale-1.25.xml new file mode 100644 index 000000000..11b37d18b --- /dev/null +++ b/src/tests/monitor-configs/full-hd-fractional-scale-1.25.xml @@ -0,0 +1,23 @@ + + + + 0 + 0 + yes + 1.25 + + + Meta-0 + MetaTestVendor + MetaVirtualMonitor + 0x10000 + + + 1920 + 1080 + 60 + + + + + diff --git a/src/tests/monitor-configs/full-hd-fractional-scale-1.5.xml b/src/tests/monitor-configs/full-hd-fractional-scale-1.5.xml new file mode 100644 index 000000000..125d9f7e3 --- /dev/null +++ b/src/tests/monitor-configs/full-hd-fractional-scale-1.5.xml @@ -0,0 +1,23 @@ + + + + 0 + 0 + yes + 1.5 + + + Meta-0 + MetaTestVendor + MetaVirtualMonitor + 0x10000 + + + 1920 + 1080 + 60 + + + + + diff --git a/src/tests/wayland-fractional-scale-test.c b/src/tests/wayland-fractional-scale-test.c new file mode 100644 index 000000000..77b6d217d --- /dev/null +++ b/src/tests/wayland-fractional-scale-test.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * Copyright (C) 2023 Collabora, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "config.h" + +#include "backends/meta-virtual-monitor.h" +#include "core/window-private.h" +#include "meta-test/meta-context-test.h" +#include "tests/meta-test-utils.h" +#include "tests/meta-wayland-test-driver.h" +#include "tests/meta-wayland-test-utils.h" +#include "wayland/meta-wayland-surface.h" + +static MetaContext *test_context; +static MetaVirtualMonitor *virtual_monitor; +static MetaWaylandTestClient *wayland_test_client; +static MetaWaylandTestDriver *test_driver; +static MetaWindow *test_window = NULL; + +#define assert_wayland_surface_size(window, width, height) \ +{ \ + g_assert_cmpint (meta_wayland_surface_get_width (meta_window_get_wayland_surface (window)), \ + ==, \ + width); \ + g_assert_cmpint (meta_wayland_surface_get_height (meta_window_get_wayland_surface (window)), \ + ==, \ + height); \ +} + +#define assert_wayland_buffer_size(window, width, height) \ +{ \ + g_assert_cmpint (meta_wayland_surface_get_buffer_width (meta_window_get_wayland_surface (window)), \ + ==, \ + width); \ + g_assert_cmpint (meta_wayland_surface_get_buffer_height (meta_window_get_wayland_surface (window)), \ + ==, \ + height); \ +} + +static void +wait_for_sync_point (unsigned int sync_point) +{ + meta_wayland_test_driver_wait_for_sync_point (test_driver, sync_point); +} + +static void +fractional_scale (void) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaLogicalMonitor *logical_monitor; + MetaRectangle layout; + + wait_for_sync_point (0); + assert_wayland_surface_size (test_window, 1920, 1080); + assert_wayland_buffer_size (test_window, 1920, 1080); + + meta_set_custom_monitor_config_full (backend, + "full-hd-fractional-scale-1.25.xml", + META_MONITORS_CONFIG_FLAG_NONE); + meta_monitor_manager_reload (monitor_manager); + logical_monitor = + meta_monitor_manager_get_logical_monitors (monitor_manager)->data; + layout = meta_logical_monitor_get_layout (logical_monitor); + g_assert_cmpint (layout.x, ==, 0); + g_assert_cmpint (layout.y, ==, 0); + g_assert_cmpint (layout.width, ==, 1536); + g_assert_cmpint (layout.height, ==, 864); + + wait_for_sync_point (1); + assert_wayland_surface_size (test_window, 1536, 864); + assert_wayland_buffer_size (test_window, 1920, 1080); + + meta_set_custom_monitor_config_full (backend, + "full-hd-fractional-scale-1.5.xml", + META_MONITORS_CONFIG_FLAG_NONE); + meta_monitor_manager_reload (monitor_manager); + logical_monitor = + meta_monitor_manager_get_logical_monitors (monitor_manager)->data; + layout = meta_logical_monitor_get_layout (logical_monitor); + g_assert_cmpint (layout.x, ==, 0); + g_assert_cmpint (layout.y, ==, 0); + g_assert_cmpint (layout.width, ==, 1280); + g_assert_cmpint (layout.height, ==, 720); + + wait_for_sync_point (2); + assert_wayland_surface_size (test_window, 1280, 720); + assert_wayland_buffer_size (test_window, 1920, 1080); +} + +static void +on_before_tests (void) +{ + MetaWaylandCompositor *compositor = + meta_context_get_wayland_compositor (test_context); + + test_driver = meta_wayland_test_driver_new (compositor); + + virtual_monitor = meta_create_test_monitor (test_context, + 1920, 1080, 60.0); + + wayland_test_client = meta_wayland_test_client_new (test_context, + "fractional-scale"); + + while (!test_window) + { + g_main_context_iteration (NULL, TRUE); + test_window = + meta_find_window_from_title (test_context, "fractional-scale"); + } +} + +static void +on_after_tests (void) +{ + meta_window_delete (test_window, g_get_monotonic_time ()); + + meta_wayland_test_client_finish (wayland_test_client); + + g_clear_object (&virtual_monitor); + + g_clear_object (&test_driver); +} + +static void +init_tests (void) +{ + g_test_add_func ("/wayland/fractional-scale", + fractional_scale); +} + +int +main (int argc, + char *argv[]) +{ + g_autoptr (MetaContext) context = NULL; + + context = meta_create_test_context (META_CONTEXT_TEST_TYPE_HEADLESS, + META_CONTEXT_TEST_FLAG_NO_X11); + g_assert (meta_context_configure (context, &argc, &argv, NULL)); + + test_context = context; + + init_tests (); + + g_signal_connect (context, "before-tests", + G_CALLBACK (on_before_tests), NULL); + g_signal_connect (context, "after-tests", + G_CALLBACK (on_after_tests), NULL); + + return meta_context_test_run_tests (META_CONTEXT_TEST (context), + META_TEST_RUN_FLAG_NONE); +} diff --git a/src/tests/wayland-test-clients/fractional-scale.c b/src/tests/wayland-test-clients/fractional-scale.c new file mode 100644 index 000000000..b46e63f31 --- /dev/null +++ b/src/tests/wayland-test-clients/fractional-scale.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2023 Collabora, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "config.h" + +#include +#include + +#include "wayland-test-client-utils.h" + +static WaylandDisplay *display; +static struct wl_surface *surface; +static struct xdg_surface *xdg_surface; +static struct xdg_toplevel *xdg_toplevel; +static struct wp_viewport *viewport; +static struct wp_fractional_scale_v1 *fractional_scale_obj; + +static gboolean running; +static gboolean waiting_for_configure; +static gboolean waiting_for_scale; +static uint32_t logical_width = 0; +static uint32_t logical_height = 0; +static float fractional_buffer_scale = 1.0; +static int sync_point = 0; + +static void +handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) +{ + wl_callback_destroy (callback); + test_driver_sync_point (display->test_driver, sync_point++, NULL); +} + +static const struct wl_callback_listener frame_listener = { + handle_frame_callback, +}; + +static void +maybe_redraw (void) +{ + struct wl_callback *callback; + uint32_t buffer_width; + uint32_t buffer_height; + + if (waiting_for_configure || waiting_for_scale) + return; + + g_assert_cmpint (logical_width, >, 0); + g_assert_cmpint (logical_height, >, 0); + g_assert_cmpfloat (fractional_buffer_scale, >, 0.0); + + buffer_width = ceilf (logical_width * fractional_buffer_scale); + buffer_height = ceilf (logical_height * fractional_buffer_scale); + + draw_surface (display, surface, buffer_width, buffer_height, 0x1f109f20); + wp_viewport_set_destination (viewport, logical_width, logical_height); + + callback = wl_surface_frame (surface); + wl_callback_add_listener (callback, &frame_listener, NULL); + + wl_surface_commit (surface); + + waiting_for_configure = TRUE; + waiting_for_scale = TRUE; +} + +static void +handle_xdg_toplevel_configure (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *states) +{ + if (width > 0 && height > 0) + { + logical_width = width; + logical_height = height; + waiting_for_configure = TRUE; + } +} + +static void +handle_xdg_toplevel_close (void *data, + struct xdg_toplevel *xdg_toplevel) +{ + running = FALSE; +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_xdg_toplevel_configure, + handle_xdg_toplevel_close, +}; + +static void +handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) +{ + xdg_surface_ack_configure (xdg_surface, serial); + waiting_for_configure = FALSE; + + maybe_redraw (); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + handle_xdg_surface_configure, +}; + +static void handle_preferred_scale (void *data, + struct wp_fractional_scale_v1 *fractional_scale_obj, + uint32_t wire_scale) +{ + float new_fractional_buffer_scale; + + new_fractional_buffer_scale = wire_scale / 120.0; + if (G_APPROX_VALUE (new_fractional_buffer_scale, + fractional_buffer_scale, + FLT_EPSILON)) + return; + + fractional_buffer_scale = new_fractional_buffer_scale; + waiting_for_scale = FALSE; + maybe_redraw (); +} + +static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { + .preferred_scale = handle_preferred_scale, +}; + +int +main (int argc, + char **argv) +{ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); + xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "fractional-scale"); + xdg_toplevel_set_fullscreen (xdg_toplevel, NULL); + + viewport = wp_viewporter_get_viewport (display->viewporter, surface); + fractional_scale_obj = + wp_fractional_scale_manager_v1_get_fractional_scale (display->fractional_scale_mgr, + surface); + wp_fractional_scale_v1_add_listener (fractional_scale_obj, + &fractional_scale_listener, + NULL); + + wl_surface_commit (surface); + + waiting_for_configure = TRUE; + waiting_for_scale = FALSE; + + running = TRUE; + while (running) + { + if (wl_display_dispatch (display->display) == -1) + return EXIT_FAILURE; + } + + wl_display_roundtrip (display->display); + + return EXIT_SUCCESS; +} diff --git a/src/tests/wayland-test-clients/meson.build b/src/tests/wayland-test-clients/meson.build index 572e07bd0..e61781ba2 100644 --- a/src/tests/wayland-test-clients/meson.build +++ b/src/tests/wayland-test-clients/meson.build @@ -20,6 +20,9 @@ wayland_test_clients = [ { 'name': 'buffer-transform', }, + { + 'name': 'fractional-scale', + }, { 'name': 'single-pixel-buffer', }, diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.c b/src/tests/wayland-test-clients/wayland-test-client-utils.c index 9e044c003..97d28b8e1 100644 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.c +++ b/src/tests/wayland-test-clients/wayland-test-client-utils.c @@ -166,6 +166,12 @@ handle_registry_global (void *user_data, display->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1); } + else if (strcmp (interface, wp_fractional_scale_manager_v1_interface.name) == 0) + { + display->fractional_scale_mgr = + wl_registry_bind (registry, id, + &wp_fractional_scale_manager_v1_interface, 1); + } else if (strcmp (interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) { display->single_pixel_mgr = diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.h b/src/tests/wayland-test-clients/wayland-test-client-utils.h index 8508ae5a5..af5eb0e54 100644 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.h +++ b/src/tests/wayland-test-clients/wayland-test-client-utils.h @@ -5,6 +5,7 @@ #include #include +#include "fractional-scale-v1-client-protocol.h" #include "single-pixel-buffer-v1-client-protocol.h" #include "test-driver-client-protocol.h" #include "viewporter-client-protocol.h" @@ -28,6 +29,7 @@ typedef struct _WaylandDisplay struct wl_compositor *compositor; struct wl_subcompositor *subcompositor; struct wl_shm *shm; + struct wp_fractional_scale_manager_v1 *fractional_scale_mgr; struct wp_single_pixel_buffer_manager_v1 *single_pixel_mgr; struct wp_viewporter *viewporter; struct xdg_wm_base *xdg_wm_base; -- cgit v1.2.1