From 4eb2f5880956c8259d0b5e2084baf61a27ee82ad Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Tue, 7 Jul 2020 11:46:52 +0100 Subject: [PATCH] Addl fix #397: GPU acceleration https://github.com/BestImageViewer/geeqie/issues/397 If two windows are open, switching between the two windows may cause a crash with the message: The error was 'GLXBadDrawable' The bug happens with Nouveau drivers and Radeon drivers, but not with Nvidia drivers. This patch disables Clutter if the system is liable to this bug. The user is given the possibility to override this with an option in Preferences/Behavior. --- src/main.c | 26 ++++++++++++++++++++++++++ src/options.c | 3 +++ src/options.h | 4 ++++ src/pixbuf-renderer.c | 2 +- src/preferences.c | 18 +++++++++++++++++- src/rcfile.c | 7 +++++++ 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index e6d3e5b4..a1ae5d35 100644 --- a/src/main.c +++ b/src/main.c @@ -61,6 +61,10 @@ #include #endif +#ifdef HAVE_GTHREAD +/* FIXME: see below */ +#include +#endif gboolean thumb_format_changed = FALSE; static RemoteConnection *remote_connection = NULL; @@ -852,6 +856,11 @@ gint main(gint argc, gchar *argv[]) #ifdef HAVE_GTHREAD #if !GLIB_CHECK_VERSION(2,32,0) g_thread_init(NULL); +#endif +#ifdef HAVE_CLUTTER +/* FIXME: see below */ + putenv("LIBGL_ALWAYS_INDIRECT=1"); + XInitThreads(); #endif gdk_threads_init(); gdk_threads_enter(); @@ -947,6 +956,23 @@ gint main(gint argc, gchar *argv[]) filter_rebuild(); } +#ifdef HAVE_CLUTTER +/* FIXME: For the background of this see: + * https://github.com/BestImageViewer/geeqie/issues/397 + * The feature CLUTTER_FEATURE_SWAP_EVENTS indictates if the + * system is liable to exhibit this problem. + * The user is provided with an override in Preferences/Behavior + */ + if (!options->override_disable_gpu) + { + DEBUG_1("CLUTTER_FEATURE_SWAP_EVENTS %d",clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS)); + if (clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS) != 0) + { + options->disable_gpu = TRUE; + } + } +#endif + /* handle missing config file and commandline additions*/ if (!layout_window_list) { diff --git a/src/options.c b/src/options.c index f5441fc1..2ea1f991 100644 --- a/src/options.c +++ b/src/options.c @@ -215,6 +215,9 @@ ConfOptions *init_options(ConfOptions *options) options->mouse_button_8 = g_strdup("Back"); options->mouse_button_9 = g_strdup("Forward"); + options->disable_gpu = FALSE; + options->override_disable_gpu = FALSE; + for (i = 0; i < FILE_FORMAT_CLASSES; i++) { options->class_filter[i] = TRUE; diff --git a/src/options.h b/src/options.h index e677dba1..9de4ace5 100644 --- a/src/options.h +++ b/src/options.h @@ -328,6 +328,10 @@ struct _ConfOptions gboolean read_metadata_in_idle; + /* GPU - see main.c */ + gboolean disable_gpu; + gboolean override_disable_gpu; + GList *disabled_plugins; }; diff --git a/src/pixbuf-renderer.c b/src/pixbuf-renderer.c index b960cb91..4693943e 100644 --- a/src/pixbuf-renderer.c +++ b/src/pixbuf-renderer.c @@ -401,7 +401,7 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class) static RendererFuncs *pr_backend_renderer_new(PixbufRenderer *pr) { - if (options->image.use_clutter_renderer) + if (options->image.use_clutter_renderer && !options->disable_gpu) { #ifdef HAVE_CLUTTER return renderer_clutter_new(pr); diff --git a/src/preferences.c b/src/preferences.c index e8c27439..dee0b47e 100644 --- a/src/preferences.c +++ b/src/preferences.c @@ -454,6 +454,8 @@ static void config_window_apply(void) options->mouse_button_8 = c_options->mouse_button_8; options->mouse_button_9 = c_options->mouse_button_9; + options->override_disable_gpu = c_options->override_disable_gpu; + config_tab_keywords_save(); image_options_sync(); @@ -2186,6 +2188,7 @@ static void config_tab_image(GtkWidget *notebook) GtkWidget *table; GtkWidget *spin; GtkWidget *two_pass; + GtkWidget *gpu_accel; vbox = scrolled_notebook_page(notebook, _("Image")); @@ -2199,8 +2202,12 @@ static void config_tab_image(GtkWidget *notebook) } #ifdef HAVE_CLUTTER - pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"), + gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"), options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer); + if (options->disable_gpu && !options->override_disable_gpu) + { + gtk_widget_set_sensitive(gpu_accel, FALSE); + } #endif two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"), @@ -3253,6 +3260,7 @@ static void config_tab_behavior(GtkWidget *notebook) GtkWidget *marks; GtkWidget *with_rename; GtkWidget *collections_on_top; + GtkWidget *checkbox; vbox = scrolled_notebook_page(notebook, _("Behavior")); @@ -3363,6 +3371,14 @@ static void config_tab_behavior(GtkWidget *notebook) table = pref_table_new(group, 2, 1, FALSE, FALSE); add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9); + pref_spacer(group, PREF_PAD_GROUP); + + group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL); + + checkbox = pref_checkbox_new_int(group, _("Override disable GPU"), + options->override_disable_gpu, &c_options->override_disable_gpu); + gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage"); + #ifdef DEBUG pref_spacer(group, PREF_PAD_GROUP); diff --git a/src/rcfile.c b/src/rcfile.c index ba2f0fd0..4a7497da 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -517,6 +517,10 @@ static void write_global_attributes(GString *outstr, gint indent) WRITE_NL(); WRITE_CHAR(*options, mouse_button_8); WRITE_NL(); WRITE_CHAR(*options, mouse_button_9); WRITE_SEPARATOR(); + + /* GPU - see main.c */ + WRITE_NL(); WRITE_BOOL(*options, override_disable_gpu); + WRITE_SEPARATOR(); } static void write_color_profile(GString *outstr, gint indent) @@ -935,6 +939,9 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar ** if (READ_CHAR(*options, mouse_button_8)) continue; if (READ_CHAR(*options, mouse_button_9)) continue; + /* GPU - see main.c */ + if (READ_BOOL(*options, override_disable_gpu)) continue; + /* Dummy options */ if (READ_DUMMY(*options, image.dither_quality, "deprecated since 2012-08-13")) continue; -- 2.20.1