From ac6afb292fb12693a01d0c804e8f81b20deb83b9 Mon Sep 17 00:00:00 2001 From: Ludovico de Nittis <ludovico.denittis@collabora.com> Date: Thu, 9 Apr 2020 15:55:17 +0200 Subject: [PATCH] Bind VDPAU drivers If available, and newer, we bind VDPAU drivers from the host system. Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com> --- debian/control | 2 +- meson.build | 2 +- src/runtime.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/debian/control b/debian/control index 59eb42a4d..4bba83d20 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Build-Depends: debhelper (>= 9), g++ (>= 4:4.8) | g++-4.8, libglib2.0-dev, - libsteam-runtime-tools-0-dev (>= 0.20190926.0~), + libsteam-runtime-tools-0-dev (>= 0.20200331.1~), libxau-dev, locales <!nocheck> | locales-all <!nocheck>, meson, diff --git a/meson.build b/meson.build index 74f6430d2..b16bd8c3d 100644 --- a/meson.build +++ b/meson.build @@ -257,7 +257,7 @@ executable( dependencies : [ dependency( 'steam-runtime-tools-0', - version : '>=0.20190926.0', + version : '>=0.20200331.1', required : true, fallback : ['steam-runtime-tools', 'libsteamrt_dep'], default_options : ['gtk_doc=false'], diff --git a/src/runtime.c b/src/runtime.c index 3792fad69..57decd0df 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -678,7 +678,7 @@ typedef enum typedef struct { - /* (type SrtEglIcd) or (type SrtVulkanIcd) */ + /* (type SrtEglIcd) or (type SrtVulkanIcd) or (type SrtVdpauDriver) */ gpointer icd; gchar *resolved_library; /* Last entry is always NONEXISTENT */ @@ -694,7 +694,9 @@ icd_details_new (gpointer icd) gsize i; g_return_val_if_fail (G_IS_OBJECT (icd), NULL); - g_return_val_if_fail (SRT_IS_EGL_ICD (icd) || SRT_IS_VULKAN_ICD (icd), + g_return_val_if_fail (SRT_IS_EGL_ICD (icd) || + SRT_IS_VULKAN_ICD (icd) || + SRT_IS_VDPAU_DRIVER (icd), NULL); self = g_slice_new0 (IcdDetails); @@ -726,6 +728,10 @@ icd_details_free (IcdDetails *self) G_DEFINE_AUTOPTR_CLEANUP_FUNC (IcdDetails, icd_details_free) +/* + * @sequence_number: numbered directory to use. Set to G_MAXSIZE to + * use just @subdir without a numbered sub directory + */ static gboolean bind_icd (PvRuntime *self, gsize multiarch_index, @@ -766,8 +772,15 @@ bind_icd (PvRuntime *self, /* Because the ICDs might have collisions among their * basenames (might differ only by directory), we put each * in its own numbered directory. */ - seq_str = g_strdup_printf ("%" G_GSIZE_FORMAT, sequence_number); - on_host = g_build_filename (libdir_on_host, subdir, seq_str, NULL); + if (sequence_number != G_MAXSIZE) + { + seq_str = g_strdup_printf ("%" G_GSIZE_FORMAT, sequence_number); + on_host = g_build_filename (libdir_on_host, subdir, seq_str, NULL); + } + else + { + on_host = g_build_filename (libdir_on_host, subdir, NULL); + } g_debug ("Ensuring %s exists", on_host); @@ -837,11 +850,10 @@ bind_icd (PvRuntime *self, if (details->kinds[multiarch_index] == ICD_KIND_ABSOLUTE) { - g_assert (seq_str != NULL); g_assert (on_host != NULL); details->paths_in_container[multiarch_index] = g_build_filename (libdir_in_container, subdir, - seq_str, + seq_str ? seq_str : "", glnx_basename (details->resolved_library), NULL); } @@ -1064,6 +1076,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self, g_autoptr(SrtSystemInfo) system_info = srt_system_info_new (NULL); g_autoptr(SrtObjectList) egl_icds = NULL; g_autoptr(SrtObjectList) vulkan_icds = NULL; + g_autoptr(SrtObjectList) vdpau_drivers = NULL; g_autoptr(GPtrArray) egl_icd_details = NULL; /* (element-type IcdDetails) */ g_autoptr(GPtrArray) vulkan_icd_details = NULL; /* (element-type IcdDetails) */ guint n_egl_icds; @@ -1237,6 +1250,8 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self, "gl:", /* Vulkan */ "if-exists:if-same-abi:soname:libvulkan.so.1", + /* VDPAU */ + "if-exists:if-same-abi:soname:libvdpau.so.1", /* NVIDIA proprietary stack */ "if-exists:even-if-older:soname-match:libEGL.so.*", "if-exists:even-if-older:soname-match:libEGL_nvidia.so.*", @@ -1332,6 +1347,33 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self, return FALSE; } + g_debug ("Enumerating %s VDPAU ICDs on host system...", multiarch_tuples[i]); + vdpau_drivers = srt_system_info_list_vdpau_drivers (system_info, + multiarch_tuples[i], + SRT_DRIVER_FLAGS_NONE); + + for (icd_iter = vdpau_drivers; icd_iter != NULL; icd_iter = icd_iter->next) + { + g_autoptr(IcdDetails) details = icd_details_new (icd_iter->data); + details->resolved_library = srt_vdpau_driver_resolve_library_path (details->icd); + g_assert (details->resolved_library != NULL); + g_assert (g_path_is_absolute (details->resolved_library)); + + /* We avoid using the sequence number for VDPAU because they can only + * be located in a single directory, so by definition we can't have + * collisions */ + if (!bind_icd (self, + i, + G_MAXSIZE, + tool_path, + libdir_on_host, + libdir_in_container, + "vdpau", + details, + error)) + return FALSE; + } + libc = g_build_filename (libdir_on_host, "libc.so.6", NULL); /* If we are going to use the host system's libc6 (likely) @@ -1854,6 +1896,49 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self, "--unsetenv", "VK_ICD_FILENAMES", NULL); + /* 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}-linux-gnu/vdpau". And because we can't control + * the ${PLATFORM} placeholder value we also create symlinks from `i486`, up + * to `i686`, to the library directory `i386` that we expect to have + * already. */ + flatpak_bwrap_add_args (bwrap, + "--setenv", "VDPAU_DRIVER_PATH", + "/overrides/lib/${PLATFORM}-linux-gnu/vdpau", + NULL); + + static const char * const extra_multiarch_tuples[] = + { + "i486-linux-gnu", + "i586-linux-gnu", + "i686-linux-gnu", + NULL + }; + + g_autofree gchar *i386_libdir_on_host = g_build_filename (self->overrides, "lib", + "i386-linux-gnu", + NULL); + + for (i = 0; i < G_N_ELEMENTS (extra_multiarch_tuples) - 1; i++) + { + g_autofree gchar *extra_libdir_on_host = g_build_filename (self->overrides, "lib", + extra_multiarch_tuples[i], + NULL); + + if (!g_file_test (extra_libdir_on_host, G_FILE_TEST_EXISTS) && + g_file_test (i386_libdir_on_host, G_FILE_TEST_IS_DIR)) + { + g_unlink (extra_libdir_on_host); + + if (symlink ("i386-linux-gnu", extra_libdir_on_host) != 0) + return glnx_throw_errno_prefix (error, + "Unable to create symlink %s -> i386-linux-gnu", + extra_libdir_on_host); + } + } + return TRUE; } -- GitLab