diff --git a/bin/system-info.c b/bin/system-info.c index 7bd36df9bef41f0c8e60dbeb86f35fea51226054..fe89cbe387a462c84c788b4be47adeb4f57cc6b8 100644 --- a/bin/system-info.c +++ b/bin/system-info.c @@ -1060,6 +1060,28 @@ main (int argc, SRT_DRIVER_FLAGS_INCLUDE_ALL); print_glx_details (builder, glx_list); + json_builder_set_member_name (builder, "graphics-verification"); + json_builder_begin_object (builder); + { + gboolean can_run_vdpau; + gchar *vdpau_additional_info = NULL; + + can_run_vdpau = srt_system_info_can_run_vdpau (info, multiarch_tuples[i]); + vdpau_additional_info = srt_system_info_dup_vdpau_additional_info (info, multiarch_tuples[i]); + json_builder_set_member_name (builder, "vdpau"); + json_builder_begin_object (builder); + json_builder_set_member_name (builder, "can-run"); + json_builder_add_boolean_value (builder, can_run_vdpau); + if (vdpau_additional_info != NULL) + { + json_builder_set_member_name (builder, "additional-info"); + json_builder_add_string_value (builder, vdpau_additional_info); + } + json_builder_end_object (builder); + g_free (vdpau_additional_info); + } + json_builder_end_object (builder); + 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); diff --git a/bin/system-info.md b/bin/system-info.md index 12a745421276ccba1695eb73ac0fb95615f11362..58ddd5d5db75d2e27616a4f7af7b6ea8d3819341 100644 --- a/bin/system-info.md +++ b/bin/system-info.md @@ -516,6 +516,20 @@ keys: **library_path** : Absolute path to the library that imlements the **library_soname**. + **graphics-verification** + : An object describing the ability to use a specific graphics module. + At the moment the only available key is **vdpau**. + The values are objects with the following keys: + + **can-run** + : A boolean value indicating whether we are able to successfully use + this graphics module. + + **additional-info** + : Any additional information that we were able to gather about this + graphics module. For example it can contain information about the + driver in use or any eventual error message. + **locale-issues** : An array of strings indicating locale-related issues. The array is empty if no problems were detected. diff --git a/helpers/check-vdpau.c b/helpers/check-vdpau.c index 9480f943320603fb49e037f41f39b9125964b32c..8f9519a1b3e6a2d0d3953a3c6f24aa484b7ab6bf 100644 --- a/helpers/check-vdpau.c +++ b/helpers/check-vdpau.c @@ -27,6 +27,7 @@ */ #include <assert.h> +#include <stdbool.h> #include <errno.h> #include <getopt.h> #include <stdio.h> @@ -37,6 +38,7 @@ #include <vdpau/vdpau.h> #include <vdpau/vdpau_x11.h> +static VdpGetInformationString *vdp_get_information_string; static VdpGetProcAddress *vdp_get_proc_address; static VdpDeviceDestroy *vdp_device_destroy; static VdpGetErrorString *vdp_get_error_string; @@ -48,12 +50,14 @@ static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_sur enum { OPTION_HELP = 1, + OPTION_VERBOSE, OPTION_VERSION, }; struct option long_options[] = { { "help", no_argument, NULL, OPTION_HELP }, + { "verbose", no_argument, NULL, OPTION_VERBOSE }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, 0, NULL, 0 } }; @@ -103,12 +107,13 @@ load_vdpau (VdpDevice dev) { #define GET_POINTER(fid, fn) do_vdpau_or_exit (vdp_get_proc_address (dev, fid, (void**)&fn)) - GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY, vdp_device_destroy); - GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING, vdp_get_error_string); - GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, vdp_output_surface_create); - GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, vdp_output_surface_get_bits_native); - GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE, vdp_output_surface_put_bits_native); - GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface); + GET_POINTER(VDP_FUNC_ID_GET_INFORMATION_STRING, vdp_get_information_string); + GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY, vdp_device_destroy); + GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING, vdp_get_error_string); + GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, vdp_output_surface_create); + GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, vdp_output_surface_get_bits_native); + GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE, vdp_output_surface_put_bits_native); + GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface); } int @@ -119,8 +124,10 @@ main (int argc, VdpDevice device; VdpOutputSurface out_surface_1; VdpOutputSurface out_surface_2; + bool verbose = false; int screen; int opt; + const char* information = NULL; /* Arbitrarily declare two 4x4 source images */ uint32_t black_box[] = @@ -151,6 +158,10 @@ main (int argc, usage (0); break; + case OPTION_VERBOSE: + verbose = true; + break; + case OPTION_VERSION: /* Output version number as YAML for machine-readability, * inspired by `ostree --version` and `docker version` */ @@ -180,6 +191,12 @@ main (int argc, load_vdpau (device); + if (verbose) + { + do_vdpau_or_exit (vdp_get_information_string (&information)); + printf ("%s\n", information); + } + do_vdpau_or_exit (vdp_output_surface_create (device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_1)); do_vdpau_or_exit (vdp_output_surface_create (device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_2)); diff --git a/steam-runtime-tools/graphics-internal.h b/steam-runtime-tools/graphics-internal.h index 6b31220ca091cbdb179b4167a521c3ceffaef816..81f8a8cbc1269416be34c675929b973e03412a42 100644 --- a/steam-runtime-tools/graphics-internal.h +++ b/steam-runtime-tools/graphics-internal.h @@ -174,3 +174,9 @@ GList *_srt_list_graphics_modules (const gchar *sysroot, const char *helpers_path, const char *multiarch_tuple, SrtGraphicsModule which); + +G_GNUC_INTERNAL +gboolean _srt_graphics_can_run (const char *helpers_path, + const char *multiarch_tuple, + SrtGraphicsModule which, + gchar **info_out); diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c index ab90bbec2383bb3861e64898c364d25f8664d40f..310106ee77c86c65d5f0fa6feea69ccc51335976 100644 --- a/steam-runtime-tools/graphics.c +++ b/steam-runtime-tools/graphics.c @@ -3523,6 +3523,120 @@ _srt_list_graphics_modules (const char *sysroot, return g_list_reverse (drivers); } +/** + * _srt_graphics_can_run: + * @helpers_path: (nullable): An optional path to find the graphics check helpers, + * PATH is used if %NULL + * @multiarch_tuple: (not nullable) (type filename): A Debian-style multiarch tuple + * such as %SRT_ABI_X86_64 + * @which: Graphics modules to look for + * @info_out: (out) (type utf8) (transfer full) (optional): Used to return + * additional information gathered from the graphics helper. + * + * After running the @which graphics helper, its stdout and stderr will be combined + * and stored in @info_out (if provided). So it usually contains additional + * information like the graphics driver in use or any eventual error message. + * + * Returns: %TRUE if we are able to use the @which graphics module. + */ +gboolean +_srt_graphics_can_run (const char *helpers_path, + const char *multiarch_tuple, + SrtGraphicsModule which, + gchar **info_out) +{ + GPtrArray *argv; + int exit_status = -1; + gboolean can_run = FALSE; + GStrv my_environ = NULL; + gchar *filtered_preload = NULL; + gchar *output = NULL; + gchar *child_stderr = NULL; + const gchar *helper = NULL; + const gchar *ld_preload; + GError *error = NULL; + + g_return_val_if_fail (multiarch_tuple != NULL, FALSE); + g_return_val_if_fail (info_out == NULL || *info_out == NULL, FALSE); + + switch (which) + { + case SRT_GRAPHICS_VDPAU_MODULE: + helper = "check-vdpau"; + break; + + case SRT_GRAPHICS_VAAPI_MODULE: + case SRT_GRAPHICS_DRI_MODULE: + case SRT_GRAPHICS_GLX_MODULE: + case NUM_SRT_GRAPHICS_MODULES: + default: + g_return_val_if_reached (FALSE); + } + + argv = _srt_get_helper (helpers_path, multiarch_tuple, helper, + SRT_HELPER_FLAGS_NONE, &error); + + if (argv == NULL) + { + /* Put the error message in the additional info */ + if (info_out != NULL) + *info_out = g_strdup (error->message); + goto out; + } + + g_ptr_array_add (argv, g_strdup ("--verbose")); + g_ptr_array_add (argv, NULL); + + my_environ = g_get_environ (); + ld_preload = g_environ_getenv (my_environ, "LD_PRELOAD"); + if (ld_preload != NULL) + { + filtered_preload = _srt_filter_gameoverlayrenderer (ld_preload); + my_environ = g_environ_setenv (my_environ, "LD_PRELOAD", filtered_preload, TRUE); + } + + if (!g_spawn_sync (NULL, /* working directory */ + (gchar **) argv->pdata, + my_environ, /* envp */ + G_SPAWN_SEARCH_PATH, /* flags */ + _srt_child_setup_unblock_signals, + NULL, /* user data */ + &output, /* stdout */ + &child_stderr, + &exit_status, + &error)) + { + g_debug ("An error occurred calling the helper: %s", error->message); + if (info_out != NULL) + *info_out = g_strdup (error->message); + goto out; + } + + if (exit_status != 0) + g_debug ("... wait status %d", exit_status); + else + can_run = TRUE; + + if (info_out != NULL) + { + if (output == NULL) + *info_out = g_strdup (child_stderr); + else if (child_stderr == NULL) + *info_out = g_strdup (output); + else + *info_out = g_strconcat (output, child_stderr, NULL); + } + +out: + g_clear_pointer (&argv, g_ptr_array_unref); + g_free (filtered_preload); + g_free (output); + g_free (child_stderr); + g_strfreev (my_environ); + g_clear_error (&error); + return can_run; +} + /** * SrtVaApiDriver: * diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index 19c5208e7f5949a183e44a3be1970510f3009a6b..bca0deb6c7025ba31a50a24ac0776d13d6279188 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -228,6 +228,8 @@ typedef struct { GList *modules; gboolean available; + Tristate can_run; + gchar *additional_info; } ModuleList; typedef struct @@ -276,6 +278,8 @@ ensure_abi (SrtSystemInfo *self, { abi->graphics_modules[i].modules = NULL; abi->graphics_modules[i].available = FALSE; + abi->graphics_modules[i].can_run = TRI_MAYBE; + abi->graphics_modules[i].additional_info = NULL; } /* transfer ownership to self->abis */ @@ -296,7 +300,10 @@ abi_free (gpointer self) g_hash_table_unref (abi->cached_graphics_results); for (i = 0; i < G_N_ELEMENTS (abi->graphics_modules); i++) - g_list_free_full (abi->graphics_modules[i].modules, g_object_unref); + { + g_list_free_full (abi->graphics_modules[i].modules, g_object_unref); + g_free (abi->graphics_modules[i].additional_info); + } g_slice_free (Abi, self); } @@ -3087,3 +3094,85 @@ srt_system_info_get_x86_features (SrtSystemInfo *self) return self->cpu_features.x86_features; } + +static void +ensure_can_run_graphics_cached (SrtSystemInfo *self, + Abi *abi, + SrtGraphicsModule which) +{ + g_return_if_fail (SRT_IS_SYSTEM_INFO (self)); + g_return_if_fail (abi != NULL); + /* We can do this check only for VDPAU */ + g_return_if_fail (which == SRT_GRAPHICS_VDPAU_MODULE); + + if (abi->graphics_modules[which].can_run != TRI_MAYBE) + return; + + g_assert (abi->graphics_modules[which].additional_info == NULL); + + if (_srt_graphics_can_run (self->helpers_path, + g_quark_to_string (abi->multiarch_tuple), + which, + &(abi->graphics_modules[which].additional_info))) + { + abi->graphics_modules[which].can_run = TRI_YES; + } + else + { + abi->graphics_modules[which].can_run = TRI_NO; + } +} + +/** + * srt_system_info_can_run_vdpau: + * @self: A #SrtSystemInfo object + * @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI. + * + * Check whether VDPAU for the given ABI can be run successfully. + * + * Returns: %TRUE if we are able to use VDPAU for the provided @multiarch_tuple + */ +gboolean +srt_system_info_can_run_vdpau (SrtSystemInfo *self, + const char *multiarch_tuple) +{ + Abi *abi = NULL; + + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), FALSE); + g_return_val_if_fail (multiarch_tuple != NULL, FALSE); + + abi = ensure_abi (self, multiarch_tuple); + + ensure_can_run_graphics_cached (self, abi, SRT_GRAPHICS_VDPAU_MODULE); + + return (abi->graphics_modules[SRT_GRAPHICS_VDPAU_MODULE].can_run == TRI_YES); +} + +/** + * srt_system_info_dup_vdpau_additional_info: + * @self: A #SrtSystemInfo object + * @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386, representing an ABI. + * + * Return addtional information gathered from the VDPAU graphics helper. + * Usually the returned string will contain either information about the graphics + * driver in use or any eventual error message encountered running the helper. + * + * Returns: (type utf8) (transfer full) (nullable): Any additional information + * gathered from the graphics helper for the provided @multiarch_tuple, or %NULL + * if no information is available. + */ +gchar * +srt_system_info_dup_vdpau_additional_info (SrtSystemInfo *self, + const char *multiarch_tuple) +{ + Abi *abi = NULL; + + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), FALSE); + g_return_val_if_fail (multiarch_tuple != NULL, FALSE); + + abi = ensure_abi (self, multiarch_tuple); + + ensure_can_run_graphics_cached (self, abi, SRT_GRAPHICS_VDPAU_MODULE); + + return g_strdup (abi->graphics_modules[SRT_GRAPHICS_VDPAU_MODULE].additional_info); +} diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h index 08ecca115be109d3272339415ca364b986d8bd26..ccf1ca54111ecc6b96a740d1881e40acd2a0db68 100644 --- a/steam-runtime-tools/system-info.h +++ b/steam-runtime-tools/system-info.h @@ -200,6 +200,10 @@ GList *srt_system_info_list_desktop_entries (SrtSystemInfo *self); SrtX86FeatureFlags srt_system_info_get_x86_features (SrtSystemInfo *self); +gboolean srt_system_info_can_run_vdpau (SrtSystemInfo *self, + const char *multiarch_tuple); +gchar *srt_system_info_dup_vdpau_additional_info (SrtSystemInfo *self, + const char *multiarch_tuple); #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtSystemInfo, g_object_unref) #endif diff --git a/tests/graphics.c b/tests/graphics.c index 4087d294e4bbcb72e83733a60b8929068d3ec09b..c97543fe1df983c09023e67d069dfc535179751d 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -2493,6 +2493,37 @@ test_vdpau (Fixture *f, } } +static void +test_vdpau_can_run (Fixture *f, + gconstpointer context) +{ + gboolean can_run; + gchar *additional_info; + + SrtSystemInfo *info = srt_system_info_new (NULL); + srt_system_info_set_helpers_path (info, f->builddir); + + can_run = srt_system_info_can_run_vdpau (info, "mock-good"); + g_assert_true (can_run); + + additional_info = srt_system_info_dup_vdpau_additional_info (info, "mock-good"); + g_assert_cmpstr (additional_info, ==, "G3DVL VDPAU Driver Shared Library version 1.0\n"); + g_free (additional_info); + + const gchar *error_message = + "Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n" + "vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n"; + + can_run = srt_system_info_can_run_vdpau (info, "mock-bad"); + g_assert_false (can_run); + + additional_info = srt_system_info_dup_vdpau_additional_info (info, "mock-bad"); + g_assert_cmpstr (additional_info, ==, error_message); + g_free (additional_info); + + g_object_unref (info); +} + static gint glx_icd_compare (SrtGlxIcd *a, SrtGlxIcd *b) { @@ -2670,8 +2701,10 @@ main (int argc, g_test_add ("/graphics/dri/flatpak", Fixture, NULL, setup, test_dri_flatpak, teardown); - g_test_add ("/graphics/vdpau", Fixture, NULL, + g_test_add ("/graphics/vdpau/basic", Fixture, NULL, setup, test_vdpau, teardown); + g_test_add ("/graphics/vdpau/can-run", Fixture, NULL, + setup, test_vdpau_can_run, teardown); g_test_add ("/graphics/glx/debian", Fixture, NULL, setup, test_glx_debian, teardown); diff --git a/tests/meson.build b/tests/meson.build index 7e2e59a8d09f19a78c2b6fc39e60773d4b923232..260adff8f1e7ff0a3078e1f419dd58a9d0c4c4e4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -179,8 +179,10 @@ executable( # Helpers with no dependencies and one source file of the same name # as the helper itself. foreach helper : [ + 'mock-bad-check-vdpau', 'mock-bad-check-vulkan', 'mock-bad-vulkaninfo', + 'mock-good-check-vdpau', 'mock-good-vulkaninfo', 'mock-hanging-wflinfo', 'mock-sigusr-wflinfo', diff --git a/tests/mock-bad-check-vdpau.c b/tests/mock-bad-check-vdpau.c new file mode 100644 index 0000000000000000000000000000000000000000..d9904229b414c2504131e02bc7804dc809a603a1 --- /dev/null +++ b/tests/mock-bad-check-vdpau.c @@ -0,0 +1,37 @@ +/* + * 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 <stdio.h> + +int +main (int argc, + char **argv) +{ + // Give bad output + fprintf (stderr, "Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n"); + fprintf (stderr, "vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n"); + return 1; +} + diff --git a/tests/mock-good-check-vdpau.c b/tests/mock-good-check-vdpau.c new file mode 100644 index 0000000000000000000000000000000000000000..ebc90fc5d047d4f64055854d94ec80151754fe39 --- /dev/null +++ b/tests/mock-good-check-vdpau.c @@ -0,0 +1,36 @@ +/* + * 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 <stdio.h> + +int +main (int argc, + char **argv) +{ + // Give good output + printf ("G3DVL VDPAU Driver Shared Library version 1.0\n"); + return 0; +} + diff --git a/tests/system-info-cli.c b/tests/system-info-cli.c index 9744747842e8d49d305bf25c3706eb0e0936e3f5..64b833ead3ceef315241387682f0cd9f120f6827 100644 --- a/tests/system-info-cli.c +++ b/tests/system-info-cli.c @@ -156,6 +156,7 @@ libraries_presence (Fixture *f, 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_assert_true (json_object_has_member (json_arch, "graphics-verification")); } g_object_unref (parser); @@ -280,6 +281,7 @@ libraries_missing (Fixture *f, 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_assert_true (json_object_has_member (json_arch, "graphics-verification")); check_libraries_missing (json_arch); } @@ -401,6 +403,7 @@ libraries_presence_verbose (Fixture *f, 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_assert_true (json_object_has_member (json_arch, "graphics-verification")); check_libraries_verbose (json_arch); } @@ -472,6 +475,7 @@ no_arguments (Fixture *f, 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_assert_true (json_object_has_member (json_arch, "graphics-verification")); } g_object_unref (parser);