diff --git a/src/backends/native/meta-backend-native-types.h b/src/backends/native/meta-backend-native-types.h index a8c4dd544..c78d44ff8 100644 --- a/src/backends/native/meta-backend-native-types.h +++ b/src/backends/native/meta-backend-native-types.h @@ -43,6 +43,7 @@ typedef enum _MetaBackendNativeMode { META_BACKEND_NATIVE_MODE_DEFAULT = 0, META_BACKEND_NATIVE_MODE_HEADLESS, + META_BACKEND_NATIVE_MODE_TEST, } MetaBackendNativeMode; #endif /* META_BACKEND_NATIVE_TYPES_H */ diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index be133b100..432d2c2aa 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -127,10 +127,19 @@ meta_backend_native_create_default_seat (MetaBackend *backend, GError **error) { MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - const char *seat_id; + const char *seat_id = NULL; MetaSeatNativeFlag flags; - seat_id = meta_backend_native_get_seat_id (backend_native); + switch (backend_native->mode) + { + case META_BACKEND_NATIVE_MODE_DEFAULT: + case META_BACKEND_NATIVE_MODE_HEADLESS: + seat_id = meta_backend_native_get_seat_id (backend_native); + break; + case META_BACKEND_NATIVE_MODE_TEST: + seat_id = META_BACKEND_TEST_INPUT_SEAT; + break; + } if (meta_backend_is_headless (backend)) flags = META_SEAT_NATIVE_FLAG_NO_LIBINPUT; @@ -379,6 +388,7 @@ meta_backend_native_get_seat_id (MetaBackendNative *backend_native) switch (backend_native->mode) { case META_BACKEND_NATIVE_MODE_DEFAULT: + case META_BACKEND_NATIVE_MODE_TEST: return meta_launcher_get_seat_id (backend_native->launcher); case META_BACKEND_NATIVE_MODE_HEADLESS: return "seat0"; @@ -459,6 +469,21 @@ create_gpu_from_udev_device (MetaBackendNative *native, return meta_gpu_kms_new (native, kms_device, error); } +static gboolean +should_ignore_device (MetaBackendNative *backend_native, + GUdevDevice *device) +{ + switch (backend_native->mode) + { + case META_BACKEND_NATIVE_MODE_DEFAULT: + case META_BACKEND_NATIVE_MODE_HEADLESS: + return meta_is_udev_device_ignore (device); + case META_BACKEND_NATIVE_MODE_TEST: + return !meta_is_udev_test_device (device); + } + g_assert_not_reached (); +} + static void on_udev_device_added (MetaUdev *udev, GUdevDevice *device, @@ -488,9 +513,9 @@ on_udev_device_added (MetaUdev *udev, } } - if (meta_is_udev_device_ignore (device)) + if (should_ignore_device (native, device)) { - g_message ("Ignoring DRM device '%s' (from udev rule)", device_path); + g_message ("Ignoring DRM device '%s'", device_path); return; } @@ -524,9 +549,9 @@ init_gpus (MetaBackendNative *native, MetaGpuKms *gpu_kms; GError *local_error = NULL; - if (meta_is_udev_device_ignore (device)) + if (should_ignore_device (native, device)) { - g_message ("Ignoring DRM device '%s' (from udev rule)", + g_message ("Ignoring DRM device '%s'", g_udev_device_get_device_file (device)); continue; } diff --git a/src/backends/native/meta-backend-native.h b/src/backends/native/meta-backend-native.h index eac81acb0..fd867e5f7 100644 --- a/src/backends/native/meta-backend-native.h +++ b/src/backends/native/meta-backend-native.h @@ -31,6 +31,8 @@ #include "backends/native/meta-launcher.h" #include "backends/native/meta-udev.h" +#define META_BACKEND_TEST_INPUT_SEAT "meta-test-seat0" + #define META_TYPE_BACKEND_NATIVE (meta_backend_native_get_type ()) META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaBackendNative, meta_backend_native, diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c index 16c44dc13..0a9ed5fd1 100644 --- a/src/backends/native/meta-udev.c +++ b/src/backends/native/meta-udev.c @@ -108,6 +108,13 @@ meta_is_udev_device_ignore (GUdevDevice *device) return meta_has_udev_device_tag (device, "mutter-device-ignore"); } +gboolean +meta_is_udev_test_device (GUdevDevice *device) +{ + return g_strcmp0 (g_udev_device_get_property (device, "ID_PATH"), + "platform-vkms") == 0; +} + gboolean meta_is_udev_device_preferred_primary (GUdevDevice *device) { diff --git a/src/backends/native/meta-udev.h b/src/backends/native/meta-udev.h index 4d85c8f04..dfd6337a0 100644 --- a/src/backends/native/meta-udev.h +++ b/src/backends/native/meta-udev.h @@ -36,6 +36,8 @@ gboolean meta_is_udev_device_disable_modifiers (GUdevDevice *device); gboolean meta_is_udev_device_ignore (GUdevDevice *device); +gboolean meta_is_udev_test_device (GUdevDevice *device); + gboolean meta_is_udev_device_preferred_primary (GUdevDevice *device); gboolean meta_udev_is_drm_device (MetaUdev *udev, diff --git a/src/tests/meson.build b/src/tests/meson.build index 3408d72b9..02460b5f3 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -273,6 +273,17 @@ if have_native_tests install: have_installed_tests, install_dir: mutter_installed_tests_libexecdir, ) + + native_kms_render_tests = executable('mutter-native-kms-render', + sources: [ + 'native-kms-render.c', + ], + include_directories: tests_includes, + c_args: tests_c_args, + dependencies: libmutter_test_dep, + install: have_installed_tests, + install_dir: mutter_installed_tests_libexecdir, + ) endif stacking_tests = [ @@ -380,4 +391,11 @@ if have_native_tests is_parallel: false, timeout: 60, ) + + test('native-kms-render', native_kms_render_tests, + suite: ['core', 'mutter/native/kms/render'], + env: test_env, + is_parallel: false, + timeout: 60, + ) endif diff --git a/src/tests/meta-context-test.c b/src/tests/meta-context-test.c index 95a40de25..c07a66b7b 100644 --- a/src/tests/meta-context-test.c +++ b/src/tests/meta-context-test.c @@ -162,6 +162,17 @@ create_headless_backend (MetaContext *context, "mode", META_BACKEND_NATIVE_MODE_HEADLESS, NULL); } + +static MetaBackend * +create_native_backend (MetaContext *context, + GError **error) +{ + return g_initable_new (META_TYPE_BACKEND_NATIVE, + NULL, error, + "context", context, + "mode", META_BACKEND_NATIVE_MODE_TEST, + NULL); +} #endif /* HAVE_NATIVE_BACKEND */ static MetaBackend * @@ -179,6 +190,8 @@ meta_context_test_create_backend (MetaContext *context, #ifdef HAVE_NATIVE_BACKEND case META_CONTEXT_TEST_TYPE_HEADLESS: return create_headless_backend (context, error); + case META_CONTEXT_TEST_TYPE_VKMS: + return create_native_backend (context, error); #endif /* HAVE_NATIVE_BACKEND */ } @@ -233,8 +246,22 @@ meta_context_test_run_tests (MetaContextTest *context_test, if (!meta_context_setup (context, &error)) { - g_printerr ("Test case failed to start: %s\n", error->message); - return EXIT_FAILURE; + if ((flags & META_TEST_RUN_FLAG_CAN_SKIP) && + ((g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && + strstr (error->message, "No GPUs found")) || + (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR) && + strstr (error->message, "Could not take control")) || + (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) && + strstr (error->message, "Could not take control")))) + { + g_printerr ("Test skipped: %s\n", error->message); + return 77; + } + else + { + g_printerr ("Test case failed to setup: %s\n", error->message); + return EXIT_FAILURE; + } } if (!meta_context_start (context, &error)) diff --git a/src/tests/meta-test/meta-context-test.h b/src/tests/meta-test/meta-context-test.h index 70ce66956..9217ec20c 100644 --- a/src/tests/meta-test/meta-context-test.h +++ b/src/tests/meta-test/meta-context-test.h @@ -27,6 +27,7 @@ typedef enum _MetaContextTestType { META_CONTEXT_TEST_TYPE_HEADLESS, + META_CONTEXT_TEST_TYPE_VKMS, META_CONTEXT_TEST_TYPE_NESTED, } MetaContextTestType; @@ -40,6 +41,7 @@ typedef enum _MetaContextTestFlag typedef enum _MetaTestRunFlags { META_TEST_RUN_FLAG_NONE = 0, + META_TEST_RUN_FLAG_CAN_SKIP = 1 << 0, } MetaTestRunFlags; #define META_TYPE_CONTEXT_TEST (meta_context_test_get_type ()) diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c new file mode 100644 index 000000000..25295f594 --- /dev/null +++ b/src/tests/native-kms-render.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Red Hat Inc. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#include "config.h" + +#include "meta/meta-backend.h" +#include "meta-test/meta-context-test.h" + +typedef struct +{ + int number_of_frames_left; + GMainLoop *loop; +} KmsRenderingTest; + +static void +on_after_update (ClutterStage *stage, + ClutterStageView *stage_view, + KmsRenderingTest *test) +{ + test->number_of_frames_left--; + if (test->number_of_frames_left == 0) + g_main_loop_quit (test->loop); + else + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +static void +meta_test_kms_render_basic (void) +{ + MetaBackend *backend = meta_get_backend (); + ClutterActor *stage = meta_backend_get_stage (backend); + KmsRenderingTest test; + + test = (KmsRenderingTest) { + .number_of_frames_left = 10, + .loop = g_main_loop_new (NULL, FALSE), + }; + g_signal_connect (stage, "after-update", G_CALLBACK (on_after_update), &test); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + g_main_loop_run (test.loop); + g_main_loop_unref (test.loop); + + g_assert_cmpint (test.number_of_frames_left, ==, 0); +} + +static void +init_tests (void) +{ + g_test_add_func ("/backends/native/kms/render/basic", + meta_test_kms_render_basic); +} + +int +main (int argc, + char **argv) +{ + g_autoptr (MetaContext) context = NULL; + g_autoptr (GError) error = NULL; + + context = meta_create_test_context (META_CONTEXT_TEST_TYPE_VKMS, + META_CONTEXT_TEST_FLAG_NO_X11); + g_assert (meta_context_configure (context, &argc, &argv, NULL)); + + init_tests (); + + return meta_context_test_run_tests (META_CONTEXT_TEST (context), + META_TEST_RUN_FLAG_CAN_SKIP); +}