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);