From 4f3d2d4b9edf340a7f70afb798c379534f83f8c1 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Wed, 22 Nov 2023 14:14:22 +0000 Subject: [PATCH] pv-runtime: Delegate setup of VDPAU to pv-adverb This lets us use a path based on ${LIB} rather than ${PLATFORM}, which will work under FEX-Emu. Helps: steamrt/tasks#349 Signed-off-by: Simon McVittie <smcv@collabora.com> --- pressure-vessel/adverb.c | 17 +++++++++ pressure-vessel/per-arch-dirs.c | 35 +++++++++++++++++++ pressure-vessel/per-arch-dirs.h | 6 ++++ pressure-vessel/runtime.c | 61 +++++++++------------------------ 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c index bc9773675..9e9037cfc 100644 --- a/pressure-vessel/adverb.c +++ b/pressure-vessel/adverb.c @@ -59,6 +59,7 @@ static gboolean opt_batch = FALSE; static gboolean opt_create = FALSE; static gboolean opt_exit_with_parent = FALSE; static gboolean opt_generate_locales = FALSE; +static gchar *opt_overrides = NULL; static gchar *opt_regenerate_ld_so_cache = NULL; static gchar *opt_set_ld_library_path = NULL; static PvShell opt_shell = PV_SHELL_NONE; @@ -927,6 +928,11 @@ static GOptionEntry options[] = "earlier on the command-line. May be repeated.", "PATH" }, + { "overrides-path", '\0', + G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_overrides, + "Libraries and drivers set up by pressure-vessel are in PATH.", + "PATH" }, + { "pass-fd", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, opt_pass_fd_cb, "Let the launched process inherit the given fd.", @@ -1198,6 +1204,16 @@ main (int argc, g_clear_error (error); } + if (opt_overrides != NULL + && !pv_adverb_set_up_overrides (wrapped_command, + lib_temp_dirs, + opt_overrides, + error)) + { + g_warning ("%s", local_error->message); + g_clear_error (error); + } + if (opt_preload_modules != NULL && !pv_adverb_set_up_preload_modules (wrapped_command, lib_temp_dirs, @@ -1414,6 +1430,7 @@ out: global_ld_so_conf_entries = NULL; global_locks = NULL; global_pass_fds = NULL; + g_clear_pointer (&opt_overrides, g_free); g_clear_pointer (&opt_regenerate_ld_so_cache, g_free); if (locales_temp_dir != NULL) diff --git a/pressure-vessel/per-arch-dirs.c b/pressure-vessel/per-arch-dirs.c index b9a86a3a8..49ea25935 100644 --- a/pressure-vessel/per-arch-dirs.c +++ b/pressure-vessel/per-arch-dirs.c @@ -276,3 +276,38 @@ pv_per_arch_dirs_new (GError **error) return g_steal_pointer (&self); } + +gboolean +pv_adverb_set_up_overrides (FlatpakBwrap *wrapped_command, + PvPerArchDirs *lib_temp_dirs, + const char *overrides, + GError **error) +{ + g_autofree gchar *value = NULL; + gsize abi; + + g_return_val_if_fail (wrapped_command != NULL, FALSE); + + if (lib_temp_dirs == NULL) + return glnx_throw (error, "Unable to set up VDPAU driver search path"); + + for (abi = 0; abi < PV_N_SUPPORTED_ARCHITECTURES; abi++) + { + const char *multiarch_tuple = pv_multiarch_details[abi].tuple; + gchar *abi_path = g_build_filename (lib_temp_dirs->abi_paths[abi], "vdpau", NULL); + gchar *target = g_build_filename (overrides, multiarch_tuple, "vdpau", NULL); + + if (!g_file_test (target, G_FILE_TEST_IS_DIR)) + continue; + + g_debug ("Creating \"%s\" -> \"%s\"", abi_path, target); + + if (symlink (target, abi_path) != 0) + return glnx_throw_errno_prefix (error, "Cannot create symlink \"%s\"", abi_path); + } + + value = g_build_filename (lib_temp_dirs->libdl_token_path, "vdpau", NULL); + g_debug ("Setting VDPAU_DRIVER_PATH=\"%s\"", value); + flatpak_bwrap_set_env (wrapped_command, "VDPAU_DRIVER_PATH", value, TRUE); + return TRUE; +} diff --git a/pressure-vessel/per-arch-dirs.h b/pressure-vessel/per-arch-dirs.h index ab5f58a7a..67539b1eb 100644 --- a/pressure-vessel/per-arch-dirs.h +++ b/pressure-vessel/per-arch-dirs.h @@ -22,6 +22,7 @@ #include "steam-runtime-tools/glib-backports-internal.h" #include "libglnx.h" +#include "flatpak-bwrap-private.h" #include "supported-architectures.h" /* @@ -42,3 +43,8 @@ PvPerArchDirs *pv_per_arch_dirs_new (GError **error); void pv_per_arch_dirs_free (PvPerArchDirs *self); G_DEFINE_AUTOPTR_CLEANUP_FUNC (PvPerArchDirs, pv_per_arch_dirs_free) + +gboolean pv_adverb_set_up_overrides (FlatpakBwrap *wrapped_command, + PvPerArchDirs *lib_temp_dirs, + const char *overrides, + GError **error); diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c index 0ff2ae027..e3e663e86 100644 --- a/pressure-vessel/runtime.c +++ b/pressure-vessel/runtime.c @@ -111,6 +111,7 @@ struct _PvRuntime unsigned is_steamrt : 1; unsigned is_scout : 1; unsigned is_flatpak_env : 1; + unsigned any_vdpau_drivers : 1; }; struct _PvRuntimeClass @@ -2265,6 +2266,11 @@ pv_runtime_get_adverb (PvRuntime *self, pv_runtime_adverb_regenerate_ld_so_cache (self, bwrap); + if (self->any_vdpau_drivers) + flatpak_bwrap_add_args (bwrap, + "--overrides-path", self->overrides_in_container, + NULL); + return TRUE; } @@ -6583,6 +6589,10 @@ collect_vdpau_drivers (PvRuntime *self, SRT_DRIVER_FLAGS_NONE); } + if (vdpau_drivers == NULL) + return TRUE; + + self->any_vdpau_drivers = TRUE; details_arr = g_ptr_array_new_full (g_list_length (vdpau_drivers), (GDestroyNotify) G_CALLBACK (icd_details_free)); @@ -7184,7 +7194,6 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, g_autofree gchar *libdrm_amdgpu = NULL; g_autofree gchar *libglx_mesa = NULL; g_autofree gchar *libglx_nvidia = NULL; - g_autofree gchar *platform_token = NULL; g_autoptr(GPtrArray) patterns = NULL; SrtSystemInfo *arch_system_info; struct stat stat_buf; @@ -7372,42 +7381,6 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, return FALSE; } - /* Unfortunately VDPAU_DRIVER_PATH can hold just a single path, so we can't - * easily list both x86_64 and i386 paths. As a workaround we set - * VDPAU_DRIVER_PATH based on ${PLATFORM} - but each of our - * supported ABIs can have multiple values for ${PLATFORM}, so we - * need to create symlinks. Try to avoid making use of this, - * because it's fragile (a new glibc version can introduce - * new platform strings), but for some things like VDPAU it's our - * only choice. */ - for (j = 0; j < G_N_ELEMENTS (arch->details->platforms); j++) - { - g_autofree gchar *platform_link = NULL; - - if (arch->details->platforms[j] == NULL) - break; - - platform_link = g_strdup_printf ("%s/lib/platform-%s", - self->overrides, - arch->details->platforms[j]); - - if (symlink (arch->details->tuple, platform_link) != 0) - return glnx_throw_errno_prefix (error, - "Unable to create symlink %s -> %s", - platform_link, arch->details->tuple); - } - - platform_token = srt_system_info_dup_libdl_platform (arch_system_info, - pv_multiarch_tuples[i], - &local_error); - if (platform_token == NULL) - { - /* This is not a critical error, try to continue */ - g_warning ("The dynamic linker expansion of \"$PLATFORM\" is not what we " - "expected, VDPAU drivers might not work: %s", local_error->message); - g_clear_error (&local_error); - } - if (!pv_runtime_create_aliases (self, arch, &local_error)) { /* This is not a critical error, try to continue */ @@ -7659,14 +7632,12 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, /* We binded the VDPAU drivers in "%{libdir}/vdpau". * Unfortunately VDPAU_DRIVER_PATH can hold just a single path, so we can't - * easily list both x86_64 and i386 drivers path. - * As a workaround we set VDPAU_DRIVER_PATH to - * "/overrides/lib/platform-${PLATFORM}/vdpau" (which is a symlink that we - * already created). */ - g_autofree gchar *vdpau_val = g_strdup_printf ("%s/lib/platform-${PLATFORM}/vdpau", - self->overrides_in_container); - - pv_environ_setenv (container_env, "VDPAU_DRIVER_PATH", vdpau_val); + * easily list both x86_64 and i386 driver paths; instead, we delegate the + * setup of VDPAU drivers to pv-adverb, which is running with our final + * choice of glibc and therefore can do something more clever with + * dynamic string tokens. */ + pv_environ_setenv (container_env, "VDPAU_DRIVER_PATH", NULL); + return TRUE; } -- GitLab