From 0b9a9e1217a64b72150900440fc37e26bba19966 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Tue, 25 Feb 2020 17:57:31 +0000 Subject: [PATCH] runtime: Add an off-switch for the host graphics stack In practice we always want the host graphics stack, but maybe this will be useful when debugging. Signed-off-by: Simon McVittie <smcv@collabora.com> --- meson.build | 14 ++++++++++- pressure-vessel-test-ui | 52 +++++++++++++++++++++++++++++++++++++++++ src/runtime.c | 30 ++++++++++++++++++++++-- src/runtime.h | 14 +++++++++++ src/wrap.c | 17 ++++++++++++++ 5 files changed, 124 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 3cf5dcd1e..89efe5df8 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,7 @@ project( ], ) +gnome = import('gnome') prove = find_program('prove', required : false) sh = find_program('sh', required : true) @@ -107,6 +108,7 @@ project_warning_cflags = [ project_include_dirs = include_directories( '.', + 'src', 'subprojects', ) @@ -178,6 +180,16 @@ add_project_arguments( language : 'c', ) +# Headers to scan for enum/flags types. +headers = [ + 'src/runtime.h', +] + +enums = gnome.mkenums_simple( + 'enumtypes', + sources : headers, +) + executable( 'pressure-vessel-with-lock', sources : [ @@ -231,7 +243,7 @@ executable( 'src/wrap.c', 'src/wrap-interactive.c', 'src/wrap-interactive.h', - ], + ] + enums, c_args : [ '-Wno-unused-local-typedefs', ], diff --git a/pressure-vessel-test-ui b/pressure-vessel-test-ui index a0b5270e9..dbb93d939 100755 --- a/pressure-vessel-test-ui +++ b/pressure-vessel-test-ui @@ -61,6 +61,23 @@ def tristate_environment(name): return None +def boolean_environment(name, default): + # type: (str, bool) -> bool + value = os.getenv(name) + + if value is None: + return default + + if value == '1': + return True + + if value in ('', '0'): + return False + + logger.warning('Unrecognised value %r for $%s', value, name) + return default + + class Gui: def __init__(self): # type: (...) -> None @@ -145,6 +162,30 @@ class Gui: row += 1 + self.host_graphics_check = Gtk.CheckButton.new_with_label( + 'Use host-system graphics stack' + ) + value = boolean_environment('PRESSURE_VESSEL_HOST_GRAPHICS', True) + self.host_graphics_check.set_active(value) + self.grid.attach(self.host_graphics_check, 1, row, 1, 1) + row += 1 + + label = Gtk.Label.new('') + label.set_markup( + '<small><i>' + "Most games and GPUs won't work when this is disabled." + '</i></small>' + ) + label.set_halign(Gtk.Align.START) + label.set_line_wrap(True) + self.grid.attach(label, 1, row, 1, 1) + row += 1 + + self._container_runtime_changed(self.container_runtime_combo) + self.container_runtime_combo.connect( + 'changed', + self._container_runtime_changed) + self.unshare_home_check = Gtk.CheckButton.new_with_label( 'Use a separate home directory per game' ) @@ -258,6 +299,12 @@ class Gui: else: self.xterm_check.set_sensitive(True) + def _container_runtime_changed(self, combo): + if combo.get_active_id() == '/': + self.host_graphics_check.set_sensitive(False) + else: + self.host_graphics_check.set_sensitive(True) + def _describe_runtime( self, path # type: str @@ -362,6 +409,11 @@ class Gui: argv.append('--runtime') argv.append(os.path.join(id, 'files')) + if self.host_graphics_check.get_active(): + argv.append('--with-host-graphics') + else: + argv.append('--without-host-graphics') + if self.unshare_home_check.get_active(): argv.append('--unshare-home') else: diff --git a/src/runtime.c b/src/runtime.c index 20133cf91..cb02a96dc 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -32,6 +32,7 @@ #include "bwrap.h" #include "bwrap-lock.h" +#include "enumtypes.h" #include "flatpak-run-private.h" #include "utils.h" @@ -55,6 +56,8 @@ struct _PvRuntime gchar *overrides_bin; gchar *container_access; FlatpakBwrap *container_access_adverb; + + PvRuntimeFlags flags; gboolean any_libc_from_host; gboolean all_libc_from_host; }; @@ -67,6 +70,7 @@ struct _PvRuntimeClass enum { PROP_0, PROP_BUBBLEWRAP, + PROP_FLAGS, PROP_SOURCE_FILES, PROP_TOOLS_DIRECTORY, N_PROPERTIES @@ -128,6 +132,10 @@ pv_runtime_get_property (GObject *object, g_value_set_string (value, self->bubblewrap); break; + case PROP_FLAGS: + g_value_set_flags (value, self->flags); + break; + case PROP_SOURCE_FILES: g_value_set_string (value, self->source_files); break; @@ -157,6 +165,10 @@ pv_runtime_set_property (GObject *object, self->bubblewrap = g_value_dup_string (value); break; + case PROP_FLAGS: + self->flags = g_value_get_flags (value); + break; + case PROP_SOURCE_FILES: /* Construct-only */ g_return_if_fail (self->source_files == NULL); @@ -294,6 +306,13 @@ pv_runtime_class_init (PvRuntimeClass *cls) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + properties[PROP_FLAGS] = + g_param_spec_flags ("flags", "Flags", + "Flags affecting how we set up the runtime", + PV_TYPE_RUNTIME_FLAGS, PV_RUNTIME_FLAGS_NONE, + (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + properties[PROP_SOURCE_FILES] = g_param_spec_string ("source-files", "Source files", ("Path to read-only runtime files (merged-/usr " @@ -316,11 +335,14 @@ PvRuntime * pv_runtime_new (const char *source_files, const char *bubblewrap, const char *tools_dir, + PvRuntimeFlags flags, GError **error) { g_return_val_if_fail (source_files != NULL, NULL); g_return_val_if_fail (bubblewrap != NULL, NULL); g_return_val_if_fail (tools_dir != NULL, NULL); + g_return_val_if_fail ((flags & ~(PV_RUNTIME_FLAGS_HOST_GRAPHICS_STACK)) == 0, + NULL); return g_initable_new (PV_TYPE_RUNTIME, NULL, @@ -328,6 +350,7 @@ pv_runtime_new (const char *source_files, "bubblewrap", bubblewrap, "source-files", source_files, "tools-directory", tools_dir, + "flags", flags, NULL); } @@ -942,8 +965,11 @@ bind_runtime (PvRuntime *self, "--ro-bind", "/etc/group", "/etc/group", NULL); - if (!pv_runtime_use_host_graphics_stack (self, bwrap, error)) - return FALSE; + if (self->flags & PV_RUNTIME_FLAGS_HOST_GRAPHICS_STACK) + { + if (!pv_runtime_use_host_graphics_stack (self, bwrap, error)) + return FALSE; + } /* This needs to be done after pv_runtime_use_host_graphics_stack() * has decided whether to bring in the host system's libc. */ diff --git a/src/runtime.h b/src/runtime.h index 5eef8b552..0fc2ec30e 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -29,6 +29,19 @@ #include "flatpak-bwrap-private.h" #include "flatpak-utils-base-private.h" +/** + * PvRuntimeFlags: + * @PV_RUNTIME_FLAGS_HOST_GRAPHICS_STACK: Use host system graphics stack + * @PV_RUNTIME_FLAGS_NONE: None of the above + * + * Flags affecting how we set up the runtime. + */ +typedef enum +{ + PV_RUNTIME_FLAGS_HOST_GRAPHICS_STACK = (1 << 0), + PV_RUNTIME_FLAGS_NONE = 0 +} PvRuntimeFlags; + typedef struct _PvRuntime PvRuntime; typedef struct _PvRuntimeClass PvRuntimeClass; @@ -43,6 +56,7 @@ GType pv_runtime_get_type (void); PvRuntime *pv_runtime_new (const char *source_files, const char *bubblewrap, const char *tools_dir, + PvRuntimeFlags flags, GError **error); void pv_runtime_append_lock_adverb (PvRuntime *self, diff --git a/src/wrap.c b/src/wrap.c index 2c5232335..f70843a12 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -322,6 +322,7 @@ static char *opt_freedesktop_app_id = NULL; static char *opt_steam_app_id = NULL; static char *opt_home = NULL; static gboolean opt_host_fallback = FALSE; +static gboolean opt_host_graphics = TRUE; static PvShell opt_shell = PV_SHELL_NONE; static GPtrArray *opt_ld_preload = NULL; static char *opt_runtime_base = NULL; @@ -583,6 +584,14 @@ static GOptionEntry options[] = { "version-only", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_version_only, "Print version number (no other information) and exit.", NULL }, + { "with-host-graphics", '\0', + G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_host_graphics, + "If using --runtime, use the host graphics stack (default)", NULL }, + { "without-host-graphics", '\0', + G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_host_graphics, + "If using --runtime, don't use the host graphics stack. " + "This is likely to result in software rendering or a crash.", + NULL }, { "test", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_test, "Smoke test pressure-vessel-wrap and exit.", NULL }, @@ -692,6 +701,8 @@ main (int argc, g_clear_pointer (&opt_home, g_free); opt_share_home = tristate_environment ("PRESSURE_VESSEL_SHARE_HOME"); + opt_host_graphics = boolean_environment ("PRESSURE_VESSEL_HOST_GRAPHICS", + TRUE); opt_verbose = boolean_environment ("PRESSURE_VESSEL_VERBOSE", FALSE); if (!opt_shell_cb ("$PRESSURE_VESSEL_SHELL", @@ -1019,11 +1030,17 @@ main (int argc, if (opt_runtime != NULL && opt_runtime[0] != '\0') { + PvRuntimeFlags flags = PV_RUNTIME_FLAGS_NONE; + + if (opt_host_graphics) + flags |= PV_RUNTIME_FLAGS_HOST_GRAPHICS_STACK; + g_debug ("Configuring runtime %s...", opt_runtime); runtime = pv_runtime_new (opt_runtime, bwrap_executable, tools_dir, + flags, error); if (runtime == NULL) -- GitLab