diff --git a/bin/system-info.c b/bin/system-info.c index 7a11d2267958a75a7fce086bfb0d78d31aefd399..1577047503d78c6417c3ed6e749a93d644daba63 100644 --- a/bin/system-info.c +++ b/bin/system-info.c @@ -672,6 +672,28 @@ jsonify_container (JsonBuilder *builder, g_strfreev (env); } +static void +print_glx_details (JsonBuilder *builder, + GList *glx_list) +{ + GList *iter; + + json_builder_set_member_name (builder, "glx_drivers"); + json_builder_begin_array (builder); + { + for (iter = glx_list; iter != NULL; iter = iter->next) + { + json_builder_begin_object (builder); + json_builder_set_member_name (builder, "library_soname"); + json_builder_add_string_value (builder, srt_glx_icd_get_library_soname (iter->data)); + json_builder_set_member_name (builder, "library_path"); + json_builder_add_string_value (builder, srt_glx_icd_get_library_path (iter->data)); + json_builder_end_object (builder); + } + } + json_builder_end_array (builder); // End glx_drivers +} + static const char * const locales[] = { "", @@ -914,6 +936,7 @@ main (int argc, GList *dri_list = NULL; GList *va_api_list = NULL; GList *vdpau_list = NULL; + GList *glx_list = NULL; json_builder_set_member_name (builder, multiarch_tuples[i]); json_builder_begin_object (builder); @@ -951,12 +974,17 @@ main (int argc, extra_driver_flags); print_vdpau_details (builder, vdpau_list); + glx_list = srt_system_info_list_glx_icds (info, multiarch_tuples[i], + SRT_DRIVER_FLAGS_INCLUDE_ALL); + print_glx_details (builder, glx_list); + json_builder_end_object (builder); // End multiarch_tuple object g_list_free_full (libraries, g_object_unref); g_list_free_full (graphics_list, g_object_unref); g_list_free_full (dri_list, g_object_unref); g_list_free_full (va_api_list, g_object_unref); g_list_free_full (vdpau_list, g_object_unref); + g_list_free_full (glx_list, g_object_unref); } json_builder_end_object (builder); diff --git a/bin/system-info.md b/bin/system-info.md index 6c342e024727f92aef4b80dd8fed38e7ef0a8147..1c60ef6b746b0c71a6ec1af6b1f94f4ce0a91bbf 100644 --- a/bin/system-info.md +++ b/bin/system-info.md @@ -491,6 +491,19 @@ keys: This key is optional and if is not provided, the default %FALSE value should be assumed. + **glx_drivers** + : An array of objects describing the GLX ICD modules that have been + found. These drivers provide the OpenGL API for the X Window System, + and are used by the `libGL.so.1` or `libGLX.so.0` loaders provided by + [GLVND](https://github.com/NVIDIA/libglvnd). + Every object can have the following keys: + + **library_soname** + : SONAME of the ICD module that has been found. + + **library_path** + : Absolute path to the library that imlements the **library_soname**. + **locale-issues** : An array of strings indicating locale-related issues. The array is empty if no problems were detected. diff --git a/debian/control b/debian/control index 75d0b1adc8894a2a7f4e7ef5c3e707824ffd5b6d..dc321a04e64be46fa92961b0aa7099c11ee7778f 100644 --- a/debian/control +++ b/debian/control @@ -84,6 +84,7 @@ Section: misc Depends: ${misc:Depends}, ${shlibs:Depends}, + libcapsule-tools-relocatable, waffle-utils-multiarch, Description: The Steam Runtime is the library stack used to run the Steam client diff --git a/debian/rules b/debian/rules index 1f095d13ce3fcffd2719259ef283334b1c159598..e0bef9f6d0846e19b634b4f8bfc15517cf857e79 100755 --- a/debian/rules +++ b/debian/rules @@ -75,6 +75,8 @@ override_dh_auto_install: $(DESTDIR)/usr/$(pkglibexecdir)/ ln -s ../../bin/$(DEB_HOST_MULTIARCH)-wflinfo \ $(DESTDIR)/usr/$(pkglibexecdir)/ + ln -s ../../lib/libcapsule/relocatable/$(DEB_HOST_MULTIARCH)-capsule-capture-libs \ + $(DESTDIR)/usr/$(pkglibexecdir)/ set -e; for x in $(DESTDIR)/usr/libexec/installed-tests/steam-runtime-tools-0/*; do \ if [ -f "$$x" ] \ && cmp -s "$$x" \ diff --git a/steam-runtime-tools/graphics-internal.h b/steam-runtime-tools/graphics-internal.h index 824f1d1dd9e9c71724d50cb2916a4e906f8da030..6b31220ca091cbdb179b4167a521c3ceffaef816 100644 --- a/steam-runtime-tools/graphics-internal.h +++ b/steam-runtime-tools/graphics-internal.h @@ -147,6 +147,7 @@ _srt_graphics_rendering_interface_string (SrtRenderingInterface rendering_interf * @SRT_GRAPHICS_DRI_MODULE: Mesa DRI driver module * @SRT_GRAPHICS_VAAPI_MODULE: VA-API driver module * @SRT_GRAPHICS_VDPAU_MODULE: VDPAU driver module + * @SRT_GRAPHICS_GLX_MODULE: GLX ICD module * @NUM_SRT_GRAPHICS_MODULES: 1 more than the last valid enum value */ typedef enum @@ -154,6 +155,7 @@ typedef enum SRT_GRAPHICS_DRI_MODULE = 0, SRT_GRAPHICS_VAAPI_MODULE, SRT_GRAPHICS_VDPAU_MODULE, + SRT_GRAPHICS_GLX_MODULE, NUM_SRT_GRAPHICS_MODULES /* Always add new values before this one */ } SrtGraphicsModule; diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c index 54d3c3871ef7a278cf69b680489612f54d5c772f..17e754723a5f651226b95e2b5d47ccc95fd6cfef 100644 --- a/steam-runtime-tools/graphics.c +++ b/steam-runtime-tools/graphics.c @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Collabora Ltd. + * Copyright © 2019-2020 Collabora Ltd. * * SPDX-License-Identifier: MIT * @@ -625,6 +625,64 @@ _argv_for_check_gl (const char *helpers_path, return argv; } +static GPtrArray * +_argv_for_list_glx_icds (const char *helpers_path, + const char *multiarch_tuple, + const char *temp_dir, + GError **error) +{ + GPtrArray *argv; + + argv = _srt_get_helper (helpers_path, multiarch_tuple, "capsule-capture-libs", + SRT_HELPER_FLAGS_SEARCH_PATH, error); + + if (argv == NULL) + return NULL; + + g_ptr_array_add (argv, g_strdup ("--dest")); + g_ptr_array_add (argv, g_strdup (temp_dir)); + g_ptr_array_add (argv, g_strdup ("no-dependencies:if-exists:even-if-older:soname-match:libGLX_*.so.0")); + /* This one might seem redundant but it is required because "libGLX_indirect" + * is usually a symlink to someone else's implementation and can't be found + * in the ld.so cache, that "capsule-capture-libs" uses. So instead of using + * a wildcard-matching we have to look it up explicitly. */ + g_ptr_array_add (argv, g_strdup ("no-dependencies:if-exists:even-if-older:soname:libGLX_indirect.so.0")); + /* If we are in a container the same might happen also for the other GLX drivers. + * To increase our chances to find all the libraries we hard code "mesa" and + * "nvidia" that, in the vast majority of the cases, are all we care about. */ + g_ptr_array_add (argv, g_strdup ("no-dependencies:if-exists:even-if-older:soname:libGLX_mesa.so.0")); + g_ptr_array_add (argv, g_strdup ("no-dependencies:if-exists:even-if-older:soname:libGLX_nvidia.so.0")); + g_ptr_array_add (argv, NULL); + return argv; +} + +static GPtrArray * +_argv_for_list_glx_icds_in_path (const char *helpers_path, + const char *multiarch_tuple, + const char *temp_dir, + const char *base_path, + GError **error) +{ + GPtrArray *argv; + + argv = _srt_get_helper (helpers_path, multiarch_tuple, "capsule-capture-libs", + SRT_HELPER_FLAGS_SEARCH_PATH, error); + + if (argv == NULL) + return NULL; + + gchar *lib_full_path = g_build_filename (base_path, "lib", multiarch_tuple, "libGLX_*.so.*", NULL); + + g_ptr_array_add (argv, g_strdup ("--dest")); + g_ptr_array_add (argv, g_strdup (temp_dir)); + g_ptr_array_add (argv, g_strjoin (NULL, + "no-dependencies:if-exists:even-if-older:path-match:", lib_full_path, + NULL)); + g_ptr_array_add (argv, NULL); + g_free (lib_full_path); + return argv; +} + /** * _srt_check_library_vendor: * @multiarch_tuple: A multiarch tuple to check e.g. i386-linux-gnu @@ -2534,6 +2592,9 @@ static SrtVdpauDriver * srt_vdpau_driver_new (const gchar *library_path, const gchar *library_link, gboolean is_extra); +static SrtGlxIcd * +srt_glx_icd_new (const gchar *library_soname, + const gchar *library_path); /** * _srt_get_modules_from_path: @@ -2598,6 +2659,7 @@ _srt_get_modules_from_path (gchar **envp, module_suffix[2] = NULL; break; + case SRT_GRAPHICS_GLX_MODULE: case NUM_SRT_GRAPHICS_MODULES: default: g_return_if_reached (); @@ -2650,6 +2712,7 @@ _srt_get_modules_from_path (gchar **envp, g_free (this_driver_link); break; + case SRT_GRAPHICS_GLX_MODULE: case NUM_SRT_GRAPHICS_MODULES: default: g_return_if_reached (); @@ -2719,6 +2782,7 @@ _srt_get_modules_full (const char *sysroot, env_override = "VDPAU_DRIVER_PATH"; break; + case SRT_GRAPHICS_GLX_MODULE: case NUM_SRT_GRAPHICS_MODULES: default: g_return_if_reached (); @@ -2946,6 +3010,205 @@ _srt_get_modules_full (const char *sysroot, g_free (flatpak_info); } +/* + * _srt_list_glx_icds_from_directory: + * @envp: (array zero-terminated=1): Behave as though `environ` was this array + * @argv: (array zero-terminated=1) (not nullable): The `argv` of the helper to use + * @tmp_directory: (not nullable) (type filename): Full path to the destination + * directory used by the "capsule-capture-libs" helper + * @known_libs: (not optional): set of library names, plus their links, that + * we already found. Newely found libraries will be added to this list + * @glxs: (element-type SrtGlxIcd) (not optional) (inout): Prepend all the unique + * #SrtGlxIcd found to this list in an unspecified order. + */ +static void +_srt_list_glx_icds_from_directory (gchar **envp, + GPtrArray *argv, + const gchar *tmp_directory, + GHashTable *known_libs, + GList **glxs) +{ + int exit_status = -1; + GError *error = NULL; + gchar *stderr = NULL; + gchar *output = NULL; + GDir *dir_iter = NULL; + const gchar *member; + gchar *full_path = NULL; + gchar *glx_path = NULL; + gchar *soname_path = NULL; + + g_return_if_fail (argv != NULL); + g_return_if_fail (tmp_directory != NULL); + g_return_if_fail (known_libs != NULL); + g_return_if_fail (glxs != NULL); + + if (!g_spawn_sync (NULL, /* working directory */ + (gchar **) argv->pdata, + envp, + G_SPAWN_SEARCH_PATH, /* flags */ + _srt_child_setup_unblock_signals, + NULL, /* user data */ + &output, /* stdout */ + &stderr, + &exit_status, + &error)) + { + g_debug ("An error occurred calling the helper: %s", error->message); + goto out; + } + + if (exit_status != 0) + { + g_debug ("... wait status %d", exit_status); + goto out; + } + + dir_iter = g_dir_open (tmp_directory, 0, &error); + + if (dir_iter == NULL) + { + g_debug ("Failed to open \"%s\": %s", tmp_directory, error->message); + goto out; + } + + while ((member = g_dir_read_name (dir_iter)) != NULL) + { + full_path = g_build_filename (tmp_directory, member, NULL); + glx_path = g_file_read_link (full_path, &error); + if (glx_path == NULL) + { + g_debug ("An error occurred trying to read the symlink: %s", error->message); + g_free (full_path); + goto out; + } + if (!g_path_is_absolute (glx_path)) + { + g_free (full_path); + g_free (glx_path); + g_debug ("We were expecting an absolute path, instead we have: %s", glx_path); + goto out; + } + /* Instead of just using just the library name to filter duplicates, we use it in + * combination with its path. Because in one of the multiple iterations we might + * find the same library that points to two different locations. And in this + * case we want to log both of them. + * + * `member` cannot contain `/`, so we know we can use `/` to make + * a composite key for deduplication. */ + soname_path = g_strjoin ("/", member, glx_path, NULL); + if (!g_hash_table_contains (known_libs, soname_path)) + { + g_hash_table_add (known_libs, g_strdup (soname_path)); + *glxs = g_list_prepend (*glxs, srt_glx_icd_new (member, glx_path)); + } + g_free (soname_path); + g_free (full_path); + g_free (glx_path); + } + +out: + if (dir_iter != NULL) + g_dir_close (dir_iter); + g_free (output); + g_free (stderr); + g_clear_error (&error); +} + +/* + * _srt_list_glx_icds: + * @sysroot: (nullable): Look in this directory instead of the real root + * @envp: (array zero-terminated=1): Behave as though `environ` was this array + * @helpers_path: (nullable): An optional path to find "capsule-capture-libs" helper, + * PATH is used if %NULL + * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple + * such as %SRT_ABI_X86_64 + * @drivers_out: (inout): Prepend the found drivers to this list as opaque + * #SrtGlxIcd objects. There is no guarantee about the order of the list + * + * Implementation of srt_system_info_list_glx_icds(). + */ +static void +_srt_list_glx_icds (const char *sysroot, + gchar **envp, + const char *helpers_path, + const char *multiarch_tuple, + GList **drivers_out) +{ + GPtrArray *by_soname_argv = NULL; + GPtrArray *overrides_argv = NULL; + GError *error = NULL; + gchar *by_soname_tmp_dir = NULL; + gchar *overrides_tmp_dir = NULL; + gchar *overrides_path = NULL; + GHashTable *known_libs = NULL; + + g_return_if_fail (multiarch_tuple != NULL); + g_return_if_fail (drivers_out != NULL); + g_return_if_fail (_srt_check_not_setuid ()); + + known_libs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + by_soname_tmp_dir = g_dir_make_tmp ("glx-icds-XXXXXX", &error); + if (by_soname_tmp_dir == NULL) + { + g_debug ("An error occurred trying to create a temporary folder: %s", error->message); + goto out; + } + + by_soname_argv = _argv_for_list_glx_icds (helpers_path, multiarch_tuple, by_soname_tmp_dir, &error); + + if (by_soname_argv == NULL) + { + g_debug ("An error occurred trying to capture glx ICDs: %s", error->message); + goto out; + } + + _srt_list_glx_icds_from_directory (envp, by_soname_argv, by_soname_tmp_dir, known_libs, drivers_out); + + /* When in a container we might miss valid GLX drivers because the `ld.so.cache` in + * use doesn't have a reference about them. To fix that we also include every + * "libGLX_*.so.*" libraries that we find in the "/overrides/lib/${multiarch}" folder */ + overrides_path = sysroot ? g_build_filename (sysroot, "/overrides", NULL) : g_strdup ("/overrides"); + if (g_file_test (overrides_path, G_FILE_TEST_IS_DIR)) + { + overrides_tmp_dir = g_dir_make_tmp ("glx-icds-XXXXXX", &error); + if (overrides_tmp_dir == NULL) + { + g_debug ("An error occurred trying to create a temporary folder: %s", error->message); + goto out; + } + + overrides_argv = _argv_for_list_glx_icds_in_path (helpers_path, multiarch_tuple, overrides_tmp_dir, overrides_path, &error); + + if (overrides_argv == NULL) + { + g_debug ("An error occurred trying to capture glx ICDs: %s", error->message); + goto out; + } + + _srt_list_glx_icds_from_directory (envp, overrides_argv, overrides_tmp_dir, known_libs, drivers_out); + } + +out: + g_clear_pointer (&by_soname_argv, g_ptr_array_unref); + g_clear_pointer (&overrides_argv, g_ptr_array_unref); + if (by_soname_tmp_dir) + { + if (!_srt_rm_rf (by_soname_tmp_dir)) + g_debug ("Unable to remove the temporary directory: %s", by_soname_tmp_dir); + } + if (overrides_tmp_dir) + { + if (!_srt_rm_rf (overrides_tmp_dir)) + g_debug ("Unable to remove the temporary directory: %s", overrides_tmp_dir); + } + g_free (by_soname_tmp_dir); + g_free (overrides_tmp_dir); + g_free (overrides_path); + g_hash_table_unref (known_libs); + g_clear_error (&error); +} + /** * _srt_list_graphics_modules: * @sysroot: (nullable): Look in this directory instead of the real root @@ -2957,10 +3220,12 @@ _srt_get_modules_full (const char *sysroot, * * Implementation of srt_system_info_list_dri_drivers() etc. * - * The returned list will have the most-preferred directories first and the - * least-preferred directories last. Within a directory, the drivers will be in - * lexicographic order, for example `nouveau_dri.so`, `r200_dri.so`, `r600_dri.so` - * in that order. + * The returned list for GLX modules is in an unspecified order. + * + * Instead the returned list for all the other graphics modules will have the + * most-preferred directories first and the least-preferred directories last. + * Within a directory, the drivers will be in lexicographic order, for example + * `nouveau_dri.so`, `r200_dri.so`, `r600_dri.so` in that order. * * Returns: (transfer full) (element-type GObject) (nullable): A list of * opaque #SrtDriDriver, etc. objects, or %NULL if nothing was found. Free with @@ -2977,8 +3242,12 @@ _srt_list_graphics_modules (const char *sysroot, g_return_val_if_fail (multiarch_tuple != NULL, NULL); - _srt_get_modules_full (sysroot, envp, helpers_path, multiarch_tuple, - which, &drivers); + if (which == SRT_GRAPHICS_GLX_MODULE) + _srt_list_glx_icds (sysroot, envp, helpers_path, multiarch_tuple, &drivers); + else + _srt_get_modules_full (sysroot, envp, helpers_path, multiarch_tuple, which, + &drivers); + return g_list_reverse (drivers); } @@ -3997,3 +4266,177 @@ _srt_load_vulkan_icds (const char *sysroot, g_strfreev (environ_copy); return g_list_reverse (ret); } + +/** + * SrtGlxIcd: + * + * Opaque object representing a GLVND GLX ICD. + */ + +struct _SrtGlxIcd +{ + /*< private >*/ + GObject parent; + gchar *library_soname; + gchar *library_path; +}; + +struct _SrtGlxIcdClass +{ + /*< private >*/ + GObjectClass parent_class; +}; + +enum +{ + GLX_ICD_PROP_0, + GLX_ICD_PROP_LIBRARY_SONAME, + GLX_ICD_PROP_LIBRARY_PATH, + N_GLX_ICD_PROPERTIES +}; + +G_DEFINE_TYPE (SrtGlxIcd, srt_glx_icd, G_TYPE_OBJECT) + +static void +srt_glx_icd_init (SrtGlxIcd *self) +{ +} + +static void +srt_glx_icd_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SrtGlxIcd *self = SRT_GLX_ICD (object); + + switch (prop_id) + { + case GLX_ICD_PROP_LIBRARY_SONAME: + g_value_set_string (value, self->library_soname); + break; + + case GLX_ICD_PROP_LIBRARY_PATH: + g_value_set_string (value, self->library_path); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +srt_glx_icd_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SrtGlxIcd *self = SRT_GLX_ICD (object); + + switch (prop_id) + { + case GLX_ICD_PROP_LIBRARY_SONAME: + g_return_if_fail (self->library_soname == NULL); + self->library_soname = g_value_dup_string (value); + break; + + case GLX_ICD_PROP_LIBRARY_PATH: + g_return_if_fail (self->library_path == NULL); + self->library_path = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +srt_glx_icd_finalize (GObject *object) +{ + SrtGlxIcd *self = SRT_GLX_ICD (object); + + g_clear_pointer (&self->library_soname, g_free); + g_clear_pointer (&self->library_path, g_free); + + G_OBJECT_CLASS (srt_glx_icd_parent_class)->finalize (object); +} + +static GParamSpec *glx_icd_properties[N_GLX_ICD_PROPERTIES] = { NULL }; + +static void +srt_glx_icd_class_init (SrtGlxIcdClass *cls) +{ + GObjectClass *object_class = G_OBJECT_CLASS (cls); + + object_class->get_property = srt_glx_icd_get_property; + object_class->set_property = srt_glx_icd_set_property; + object_class->finalize = srt_glx_icd_finalize; + + glx_icd_properties[GLX_ICD_PROP_LIBRARY_SONAME] = + g_param_spec_string ("library-soname", "Library soname", + "SONAME of the GLX ICD library", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + glx_icd_properties[GLX_ICD_PROP_LIBRARY_PATH] = + g_param_spec_string ("library-path", "Library absolute path", + "Absolute path to the GLX ICD library", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_GLX_ICD_PROPERTIES, + glx_icd_properties); +} + +/** + * srt_glx_icd_new: + * @library_soname: (transfer none): the soname of the library + * @library_path: (transfer none): the absolute path of the library + * + * Returns: (transfer full): a new GLVND GLX ICD + */ +static SrtGlxIcd * +srt_glx_icd_new (const gchar *library_soname, + const gchar *library_path) +{ + g_return_val_if_fail (library_soname != NULL, NULL); + g_return_val_if_fail (library_path != NULL, NULL); + g_return_val_if_fail (g_path_is_absolute (library_path), NULL); + + return g_object_new (SRT_TYPE_GLX_ICD, + "library-soname", library_soname, + "library-path", library_path, + NULL); +} + +/** + * srt_glx_icd_get_library_soname: + * @self: The GLX ICD + * + * Return the library SONAME for this GLX ICD, for example `libGLX_mesa.so.0`. + * + * Returns: (type filename) (transfer none): #SrtGlxIcd:library-soname + */ +const gchar * +srt_glx_icd_get_library_soname (SrtGlxIcd *self) +{ + g_return_val_if_fail (SRT_IS_GLX_ICD (self), NULL); + return self->library_soname; +} + +/** + * srt_glx_icd_get_library_path: + * @self: The GLX ICD + * + * Return the absolute path to the library that implements this GLX soname. + * + * Returns: (type filename) (transfer none): #SrtGlxIcd:library-path + */ +const gchar * +srt_glx_icd_get_library_path (SrtGlxIcd *self) +{ + g_return_val_if_fail (SRT_IS_GLX_ICD (self), NULL); + return self->library_path; +} diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h index c9906af2b5bd11b4356aab65db150f40046cc000..d45c128845a59a91b0d0eb87ddc8c18f34b2214e 100644 --- a/steam-runtime-tools/graphics.h +++ b/steam-runtime-tools/graphics.h @@ -221,6 +221,20 @@ gboolean srt_vulkan_icd_write_to_file (SrtVulkanIcd *self, const char *path, GError **error); +typedef struct _SrtGlxIcd SrtGlxIcd; +typedef struct _SrtGlxIcdClass SrtGlxIcdClass; + +#define SRT_TYPE_GLX_ICD (srt_glx_icd_get_type ()) +#define SRT_GLX_ICD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SRT_TYPE_GLX_ICD, SrtGlxIcd)) +#define SRT_GLX_ICD_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), SRT_TYPE_GLX_ICD, SrtGlxIcdClass)) +#define SRT_IS_GLX_ICD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SRT_TYPE_GLX_ICD)) +#define SRT_IS_GLX_ICD_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), SRT_TYPE_GLX_ICD)) +#define SRT_GLX_ICD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SRT_TYPE_GLX_ICD, SrtGlxIcdClass) +GType srt_glx_icd_get_type (void); + +const gchar *srt_glx_icd_get_library_soname (SrtGlxIcd *self); +const gchar *srt_glx_icd_get_library_path (SrtGlxIcd *self); + #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtGraphics, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtEglIcd, g_object_unref) @@ -228,4 +242,5 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtDriDriver, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtVaApiDriver, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtVdpauDriver, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtVulkanIcd, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtGlxIcd, g_object_unref) #endif diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index 8693849b8c74be67c22640f3fda23f4675911125..625838230ff92942b5bad06b7ba16a0acd5ea182 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -2537,6 +2537,10 @@ graphics_module_is_extra (SrtGraphicsModule which, case SRT_GRAPHICS_VDPAU_MODULE: return srt_vdpau_driver_is_extra (object); + /* We don't have extras for GLX, yet */ + case SRT_GRAPHICS_GLX_MODULE: + return FALSE; + case NUM_SRT_GRAPHICS_MODULES: default: g_return_val_if_reached (FALSE); @@ -2680,6 +2684,37 @@ srt_system_info_list_vdpau_drivers (SrtSystemInfo *self, SRT_GRAPHICS_VDPAU_MODULE); } +/** + * srt_system_info_list_glx_icds: + * @self: The #SrtSystemInfo object + * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch + * tuple such as %SRT_ABI_X86_64 + * @flags: Filter the list of GLX ICDs accordingly to these flags. + * At the moment no filters are available, so there are no practical + * differences between %SRT_DRIVER_FLAGS_INCLUDE_ALL and + * %SRT_DRIVER_FLAGS_NONE. + * + * List the available GLX ICDs, in an unspecified order. + * These are the drivers used by `libGL.so.1` or `libGLX.so.0` + * if it is the loader library provided by + * [GLVND](https://github.com/NVIDIA/libglvnd) + * (if this is the case, srt_graphics_library_is_vendor_neutral() for + * the combination of %SRT_WINDOW_SYSTEM_X11 and %SRT_RENDERING_INTERFACE_GL + * will return %TRUE and indicate %SRT_GRAPHICS_LIBRARY_VENDOR_GLVND). + * + * Returns: (transfer full) (element-type SrtGlxIcd) (nullable): A list of + * opaque #SrtGlxIcd objects, or %NULL if nothing was found. Free with + * `g_list_free_full(list, g_object_unref)`. + */ +GList * +srt_system_info_list_glx_icds (SrtSystemInfo *self, + const char *multiarch_tuple, + SrtDriverFlags flags) +{ + return _srt_system_info_list_graphics_modules (self, multiarch_tuple, flags, + SRT_GRAPHICS_GLX_MODULE); +} + static void ensure_driver_environment (SrtSystemInfo *self) { diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h index da5e80e43257f0eb9fc2316463c0c59f3e6eea7b..f860b5a0305114e9ec623f636aa295d61338e848 100644 --- a/steam-runtime-tools/system-info.h +++ b/steam-runtime-tools/system-info.h @@ -141,6 +141,9 @@ GList *srt_system_info_list_va_api_drivers (SrtSystemInfo *self, GList *srt_system_info_list_vdpau_drivers (SrtSystemInfo *self, const char *multiarch_tuple, SrtDriverFlags flags); +GList *srt_system_info_list_glx_icds (SrtSystemInfo *self, + const char *multiarch_tuple, + SrtDriverFlags flags); void srt_system_info_set_environ (SrtSystemInfo *self, gchar * const *env); diff --git a/tests/graphics.c b/tests/graphics.c index 7cc123be6ed3fdfda83fc8d6eb37a5266d23ca04..d00d6c4a07e3b0f4a2857649c4a7880141101bcb 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -1715,12 +1715,25 @@ check_list_suffixes (const GList *list, gsize i = 0; for (const GList *iter = list; iter != NULL; iter = iter->next, i++) { - if (module == SRT_GRAPHICS_DRI_MODULE) - value = srt_dri_driver_get_library_path (iter->data); - else if (module == SRT_GRAPHICS_VAAPI_MODULE) - value = srt_va_api_driver_get_library_path (iter->data); - else if (module == SRT_GRAPHICS_VDPAU_MODULE) - value = srt_vdpau_driver_get_library_path (iter->data); + switch (module) + { + case SRT_GRAPHICS_DRI_MODULE: + value = srt_dri_driver_get_library_path (iter->data); + break; + case SRT_GRAPHICS_VAAPI_MODULE: + value = srt_va_api_driver_get_library_path (iter->data); + break; + case SRT_GRAPHICS_VDPAU_MODULE: + value = srt_vdpau_driver_get_library_path (iter->data); + break; + case SRT_GRAPHICS_GLX_MODULE: + value = srt_glx_icd_get_library_soname (iter->data); + break; + + case NUM_SRT_GRAPHICS_MODULES: + default: + g_return_if_reached (); + } g_assert_nonnull (suffixes[i]); g_assert_true (g_str_has_suffix (value, suffixes[i])); } @@ -1750,6 +1763,7 @@ check_list_extra (const GList *list, g_assert_cmpint (is_extra, ==, srt_vdpau_driver_is_extra (iter->data)); break; + case SRT_GRAPHICS_GLX_MODULE: case NUM_SRT_GRAPHICS_MODULES: default: g_return_if_reached (); @@ -1772,6 +1786,10 @@ check_list_links (const GList *list, value = srt_vdpau_driver_get_library_link (iter->data); break; + case SRT_GRAPHICS_GLX_MODULE: + value = srt_glx_icd_get_library_path (iter->data); + break; + case SRT_GRAPHICS_VAAPI_MODULE: case SRT_GRAPHICS_DRI_MODULE: case NUM_SRT_GRAPHICS_MODULES: @@ -2240,7 +2258,7 @@ test_vdpau_with_env (Fixture *f, static void test_vdpau_flatpak (Fixture *f, - gconstpointer context) + gconstpointer context) { SrtSystemInfo *info; gchar **envp; @@ -2269,6 +2287,112 @@ test_vdpau_flatpak (Fixture *f, g_strfreev (envp); } +static gint +glx_icd_compare (SrtGlxIcd *a, SrtGlxIcd *b) +{ + return g_strcmp0 (srt_glx_icd_get_library_soname (a), srt_glx_icd_get_library_soname (b)); +} + +static void +test_glx_debian (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar *sysroot; + GList *glx; + const gchar *multiarch_tuples[] = {"i386-mock-debian", "x86_64-mock-debian", NULL}; + const gchar *glx_suffixes_i386[] = {"libGLX_mesa.so.0", + "libGLX_nvidia.so.0", + NULL}; + const gchar *glx_paths_i386[] = {"/lib/i386-linux-gnu/libGLX_mesa.so.0", + "/lib/i386-linux-gnu/libGLX_nvidia.so.0", + NULL}; + const gchar *glx_suffixes_x86_64[] = {"libGLX_mesa.so.0", + NULL}; + const gchar *glx_paths_x86_64[] = {"/lib/x86_64-linux-gnu/libGLX_mesa.so.0", + NULL}; + + sysroot = g_build_filename (f->srcdir, "sysroots", "debian10", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + srt_system_info_set_sysroot (info, sysroot); + srt_system_info_set_helpers_path (info, f->builddir); + + glx = srt_system_info_list_glx_icds (info, multiarch_tuples[0], SRT_DRIVER_FLAGS_NONE); + /* The icds are not provided in a guaranteed order. Sort them before checking + * with the expectations */ + glx = g_list_sort (glx, (GCompareFunc) glx_icd_compare); + check_list_suffixes (glx, glx_suffixes_i386, SRT_GRAPHICS_GLX_MODULE); + check_list_links (glx, glx_paths_i386, SRT_GRAPHICS_GLX_MODULE); + g_list_free_full (glx, g_object_unref); + + glx = srt_system_info_list_glx_icds (info, multiarch_tuples[1], SRT_DRIVER_FLAGS_NONE); + /* The icds are not provided in a guaranteed order. Sort them before checking + * with the expectations */ + glx = g_list_sort (glx, (GCompareFunc) glx_icd_compare); + check_list_suffixes (glx, glx_suffixes_x86_64, SRT_GRAPHICS_GLX_MODULE); + check_list_links (glx, glx_paths_x86_64, SRT_GRAPHICS_GLX_MODULE); + g_list_free_full (glx, g_object_unref); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +test_glx_container (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar *sysroot; + GList *glx; + const gchar *multiarch_tuples[] = {"i386-mock-container", "x86_64-mock-container", NULL}; + const gchar *glx_suffixes_i386[] = {"libGLX_nvidia.so.0", + NULL}; + const gchar *glx_paths_i386[] = {"/lib/i386-linux-gnu/libGLX_nvidia.so.0", + NULL}; + const gchar *glx_suffixes_x86_64[] = {"libGLX_custom.so.0", + "libGLX_mesa.so.0", + NULL}; + const gchar *glx_paths_x86_64[] = {"/lib/x86_64-linux-gnu/libGLX_custom.so.0", + "/lib/x86_64-linux-gnu/libGLX_mesa.so.0", + NULL}; + + sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + srt_system_info_set_sysroot (info, sysroot); + srt_system_info_set_helpers_path (info, f->builddir); + + glx = srt_system_info_list_glx_icds (info, multiarch_tuples[0], SRT_DRIVER_FLAGS_NONE); + /* The icds are not provided in a guaranteed order. Sort them before checking + * with the expectations */ + glx = g_list_sort (glx, (GCompareFunc) glx_icd_compare); + check_list_suffixes (glx, glx_suffixes_i386, SRT_GRAPHICS_GLX_MODULE); + check_list_links (glx, glx_paths_i386, SRT_GRAPHICS_GLX_MODULE); + g_list_free_full (glx, g_object_unref); + + glx = srt_system_info_list_glx_icds (info, multiarch_tuples[1], SRT_DRIVER_FLAGS_NONE); + /* The icds are not provided in a guaranteed order. Sort them before checking + * with the expectations */ + glx = g_list_sort (glx, (GCompareFunc) glx_icd_compare); + check_list_suffixes (glx, glx_suffixes_x86_64, SRT_GRAPHICS_GLX_MODULE); + check_list_links (glx, glx_paths_x86_64, SRT_GRAPHICS_GLX_MODULE); + g_list_free_full (glx, g_object_unref); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + static const Config dir_config = { ICD_MODE_EXPLICIT_DIRS }; static const Config filename_config = { ICD_MODE_EXPLICIT_FILENAMES }; static const Config flatpak_config = { ICD_MODE_FLATPAK }; @@ -2347,5 +2471,10 @@ main (int argc, g_test_add ("/graphics/vdpau/flatpak", Fixture, NULL, setup, test_vdpau_flatpak, teardown); + g_test_add ("/graphics/glx/debian", Fixture, NULL, + setup, test_glx_debian, teardown); + g_test_add ("/graphics/glx/container", Fixture, NULL, + setup, test_glx_container, teardown); + return g_test_run (); } diff --git a/tests/meson.build b/tests/meson.build index 8b4b3a201e090b8c94d894dcac1c7cd13445306c..9fded0f179fc0f4a77109678869d6fd6eef76236 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -241,4 +241,26 @@ foreach helper : [ ) endforeach +# i386 and x86_64 helpers with GLib and Gio dependencies, and one source file of +# the same name as the helper itself (with the arch prefix). +foreach arch : [ + 'i386', + 'x86_64', +] + foreach helper : [ + 'mock-container-capsule-capture-libs', + 'mock-debian-capsule-capture-libs', + ] + executable( + arch + '-' + helper, + helper + '.c', + c_args : ['-DMOCK_ARCHITECTURE_' + arch], + dependencies : [glib, gio], + include_directories : project_include_dirs, + install: true, + install_dir: tests_dir + ) + endforeach +endforeach + # vim:set sw=2 sts=2 et: diff --git a/tests/mock-container-capsule-capture-libs.c b/tests/mock-container-capsule-capture-libs.c new file mode 100644 index 0000000000000000000000000000000000000000..2626bba15ca86a3d0929d51e33e5567c60bfb395 --- /dev/null +++ b/tests/mock-container-capsule-capture-libs.c @@ -0,0 +1,125 @@ +/* + * Copyright © 2020 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <steam-runtime-tools/glib-compat.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <glib.h> +#include <gio/gio.h> + +#include "test-utils.h" + +int +main (int argc, + char **argv) +{ + g_return_val_if_fail (argc > 3, EXIT_FAILURE); + g_return_val_if_fail (g_strcmp0 (argv[1], "--dest") == 0, EXIT_FAILURE); + + const char *dest = argv[2]; + +#if defined(MOCK_ARCHITECTURE_x86_64) + const gchar *multiarch = "x86_64-linux-gnu"; + const gchar *multiarch_mock = "x86_64-mock-container"; +#else + const gchar *multiarch = "i386-linux-gnu"; + const gchar *multiarch_mock = "i386-mock-container"; +#endif + + gchar **envp = g_get_environ (); + gchar *path = g_build_filename (g_environ_getenv (envp, "SRT_TEST_SYSROOT"), "overrides", "lib", multiarch, NULL); + + for (int i = 3; i < argc; i++) + { + /* We are in a container. A soname-match it's likely to fail because `ld.so.cache` + * doesn't have a reference to them. We mimic this behavior here. */ + if (g_strrstr (argv[i], "soname-match:")) + { + continue; + } + + const gchar *soname_match = g_strrstr (argv[i], "soname:"); + if (soname_match) + { + gchar **soname_split = g_strsplit (soname_match, "soname:", 2); + const gchar *soname = soname_split[1]; + gchar *file_path = g_build_filename (path, soname, NULL); + /* We continue only if we have the soname that we are searching for */ + if (g_file_test (file_path, G_FILE_TEST_EXISTS)) + { + gchar *dest_full_path = g_build_filename (dest, soname, NULL); + gchar *target = g_build_filename ("/lib", multiarch, soname, NULL); + /* `path-match:` might have already created the symlink */ + if (symlink (target, dest_full_path) != 0 && errno != EEXIST) + g_error ("symlink: %s", g_strerror (errno)); + + g_free (dest_full_path); + g_free (target); + } + g_strfreev (soname_split); + g_free (file_path); + } + + const gchar *path_match = g_strrstr (argv[i], "path-match:"); + if (path_match) + { + const gchar *filename; + gchar *expected_path = g_build_filename (g_environ_getenv (envp, "SRT_TEST_SYSROOT"), + "overrides", "lib", multiarch_mock, NULL); + gchar *expected_match_path = g_strdup_printf ("path-match:%s/libGLX_*.so.*", expected_path); + /* We expect to be asked to look in /overrides/lib/MULTIARCH as a "path match" */ + g_assert_cmpstr (path_match, ==, expected_match_path); + GDir *dir = g_dir_open (path, 0, NULL); + g_assert_nonnull (dir); + while ((filename = g_dir_read_name (dir))) + { + /* The real regex should be "libGLX_*.so.*" but for our testing purpose + * checking only for files with "libGLX_" suffix is enough */ + if (g_str_has_prefix (filename, "libGLX_")) + { + gchar *dest_full_path = g_build_filename (dest, filename, NULL); + gchar *target = g_build_filename ("/lib", multiarch, filename, NULL); + /* `soname:` might have already created the symlink */ + if (symlink (target, dest_full_path) != 0 && errno != EEXIST) + g_error ("symlink: %s", g_strerror (errno)); + + g_free (dest_full_path); + g_free (target); + } + } + g_free (expected_path); + g_free (expected_match_path); + if (dir != NULL) + g_dir_close (dir); + } + } + + g_free (path); + g_strfreev (envp); + return EXIT_SUCCESS; +} diff --git a/tests/mock-debian-capsule-capture-libs.c b/tests/mock-debian-capsule-capture-libs.c new file mode 100644 index 0000000000000000000000000000000000000000..d41d603fad6584b7e7066d19373ebc6a01f81121 --- /dev/null +++ b/tests/mock-debian-capsule-capture-libs.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2020 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <steam-runtime-tools/glib-compat.h> + +#include <stdio.h> +#include <stdlib.h> +#include <glib.h> +#include <gio/gio.h> + +int +main (int argc, + char **argv) +{ + GError *error = NULL; + gchar *file_path = NULL; + gchar *target = NULL; + GFile *file = NULL; + +#if defined(MOCK_ARCHITECTURE_x86_64) + const gchar *multiarch = "x86_64-linux-gnu"; + static const char *const sonames[] = { "libGLX_mesa.so.0", NULL }; +#else + const gchar *multiarch = "i386-linux-gnu"; + static const char *const sonames[] = { "libGLX_mesa.so.0", "libGLX_nvidia.so.0", NULL }; +#endif + + g_return_val_if_fail (argc > 3, EXIT_FAILURE); + g_return_val_if_fail (g_strcmp0 (argv[1], "--dest") == 0, EXIT_FAILURE); + + for (gsize i = 0; sonames[i] != NULL; i++) + { + file_path = g_build_filename (argv[2], sonames[i], NULL); + file = g_file_new_for_path (file_path); + target = g_build_filename ("/lib", multiarch, sonames[i], NULL); + if (!g_file_make_symbolic_link (file, target, NULL, &error)) + { + g_critical ("An error occurred creating a symlink: %s", error->message); + g_clear_error (&error); + g_clear_pointer (&file, g_object_unref); + g_free (file_path); + g_free (target); + return EXIT_FAILURE; + } + g_clear_pointer (&file, g_object_unref); + g_free (file_path); + g_free (target); + } + + return EXIT_SUCCESS; +} diff --git a/tests/sysroots/debian10/usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0 b/tests/sysroots/steamrt/overrides/lib/i386-linux-gnu/libGLX_nvidia.so.0 similarity index 100% rename from tests/sysroots/debian10/usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0 rename to tests/sysroots/steamrt/overrides/lib/i386-linux-gnu/libGLX_nvidia.so.0 diff --git a/tests/sysroots/steamrt/overrides/lib/i386-linux-gnu/.keep b/tests/sysroots/steamrt/overrides/lib/x86_64-linux-gnu/libGLX_custom.so.0 similarity index 100% rename from tests/sysroots/steamrt/overrides/lib/i386-linux-gnu/.keep rename to tests/sysroots/steamrt/overrides/lib/x86_64-linux-gnu/libGLX_custom.so.0 diff --git a/tests/sysroots/steamrt/overrides/lib/x86_64-linux-gnu/libGLX_mesa.so.0 b/tests/sysroots/steamrt/overrides/lib/x86_64-linux-gnu/libGLX_mesa.so.0 new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/system-info-cli.c b/tests/system-info-cli.c index a94bf2a6a2a2d444cd781c849b73fbc0e51c3afa..12051e8725c1f70c10edc5246e6c4c4d8765b424 100644 --- a/tests/system-info-cli.c +++ b/tests/system-info-cli.c @@ -153,6 +153,7 @@ libraries_presence (Fixture *f, g_assert_true (json_object_has_member (json_arch, "dri_drivers")); g_assert_true (json_object_has_member (json_arch, "va-api_drivers")); g_assert_true (json_object_has_member (json_arch, "vdpau_drivers")); + g_assert_true (json_object_has_member (json_arch, "glx_drivers")); } g_object_unref (parser); @@ -276,6 +277,7 @@ libraries_missing (Fixture *f, g_assert_true (json_object_has_member (json_arch, "dri_drivers")); g_assert_true (json_object_has_member (json_arch, "va-api_drivers")); g_assert_true (json_object_has_member (json_arch, "vdpau_drivers")); + g_assert_true (json_object_has_member (json_arch, "glx_drivers")); check_libraries_missing (json_arch); } @@ -396,6 +398,7 @@ libraries_presence_verbose (Fixture *f, g_assert_true (json_object_has_member (json_arch, "dri_drivers")); g_assert_true (json_object_has_member (json_arch, "va-api_drivers")); g_assert_true (json_object_has_member (json_arch, "vdpau_drivers")); + g_assert_true (json_object_has_member (json_arch, "glx_drivers")); check_libraries_verbose (json_arch); } @@ -466,6 +469,7 @@ no_arguments (Fixture *f, g_assert_true (json_object_has_member (json_arch, "dri_drivers")); g_assert_true (json_object_has_member (json_arch, "va-api_drivers")); g_assert_true (json_object_has_member (json_arch, "vdpau_drivers")); + g_assert_true (json_object_has_member (json_arch, "glx_drivers")); } g_object_unref (parser); diff --git a/tests/system-info.c b/tests/system-info.c index 76f679ac4a4316b2c358acc846e7553f4afdcdfa..6d6baa17c4d66fe7a38d01fd2aa87fa4eb25a969 100644 --- a/tests/system-info.c +++ b/tests/system-info.c @@ -1702,9 +1702,9 @@ overrides (Fixture *f, if (strstr (output[i], "/run/host/usr/lib/libgcc_s.so.1") != NULL) seen_link = TRUE; } - /* The overrides folder contains 4 folders plus the root folder, plus one symlink, - * plus 2 ".keep" files */ - g_assert_cmpint (i, ==, 8); + /* The overrides folder contains 4 folders plus the root folder, plus 4 files, + * plus one ".keep" file */ + g_assert_cmpint (i, ==, 10); g_assert_true (seen_link); g_strfreev (output); @@ -1721,7 +1721,7 @@ overrides (Fixture *f, if (strstr (output[i], "/run/host/usr/lib/libgcc_s.so.1") != NULL) seen_link = TRUE; } - g_assert_cmpint (i, ==, 8); + g_assert_cmpint (i, ==, 10); g_assert_true (seen_link); g_strfreev (output);