From 13e96c7ec86718dcec2066cf60e7ecbf7011ec17 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 5 Jan 2025 18:49:24 -0600 Subject: [PATCH 1/4] gtk: add config option to disable GTK OpenGL debug logging --- src/apprt/gtk/App.zig | 125 ++++++++++++++++++++++++++++++------------ src/config/Config.zig | 9 +++ 2 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 6fa98a011..ba01236cc 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -104,42 +104,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { c.gtk_get_micro_version(), }); - // Disabling Vulkan can improve startup times by hundreds of - // milliseconds on some systems. We don't use Vulkan so we can just - // disable it. - if (version.runtimeAtLeast(4, 16, 0)) { - // From gtk 4.16, GDK_DEBUG is split into GDK_DEBUG and GDK_DISABLE. - // For the remainder of "why" see the 4.14 comment below. - _ = internal_os.setenv("GDK_DISABLE", "gles-api,vulkan"); - _ = internal_os.setenv("GDK_DEBUG", "opengl,gl-no-fractional"); - } else if (version.runtimeAtLeast(4, 14, 0)) { - // We need to export GDK_DEBUG to run on Wayland after GTK 4.14. - // Older versions of GTK do not support these values so it is safe - // to always set this. Forwards versions are uncertain so we'll have to - // reassess... - // - // Upstream issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/6589 - // - // Specific details about values: - // - "opengl" - output OpenGL debug information - // - "gl-disable-gles" - disable GLES, Ghostty can't use GLES - // - "vulkan-disable" - disable Vulkan, Ghostty can't use Vulkan - // and initializing a Vulkan context was causing a longer delay - // on some systems. - _ = internal_os.setenv("GDK_DEBUG", "opengl,gl-disable-gles,vulkan-disable,gl-no-fractional"); - } else { - // Versions prior to 4.14 are a bit of an unknown for Ghostty. It - // is an environment that isn't tested well and we don't have a - // good understanding of what we may need to do. - _ = internal_os.setenv("GDK_DEBUG", "vulkan-disable"); - } - - if (version.runtimeAtLeast(4, 14, 0)) { - // We need to export GSK_RENDERER to opengl because GTK uses ngl by - // default after 4.14 - _ = internal_os.setenv("GSK_RENDERER", "opengl"); - } - // Load our configuration var config = try Config.load(core_app.alloc); errdefer config.deinit(); @@ -161,6 +125,95 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { } } + var gdk_debug: struct { + /// output OpenGL debug information + opengl: bool = false, + /// disable GLES, Ghostty can't use GLES + @"gl-disable-gles": bool = false, + @"gl-no-fractional": bool = false, + /// Disabling Vulkan can improve startup times by hundreds of + /// milliseconds on some systems. We don't use Vulkan so we can just + /// disable it. + @"vulkan-disable": bool = false, + } = .{ + .opengl = config.@"gtk-opengl-debug", + }; + + var gdk_disable: struct { + @"gles-api": bool = false, + /// Disabling Vulkan can improve startup times by hundreds of + /// milliseconds on some systems. We don't use Vulkan so we can just + /// disable it. + vulkan: bool = false, + } = .{}; + + environment: { + if (version.runtimeAtLeast(4, 16, 0)) { + // From gtk 4.16, GDK_DEBUG is split into GDK_DEBUG and GDK_DISABLE. + // For the remainder of "why" see the 4.14 comment below. + gdk_disable.@"gles-api" = true; + gdk_disable.vulkan = true; + gdk_debug.@"gl-no-fractional" = true; + break :environment; + } + if (version.runtimeAtLeast(4, 14, 0)) { + // We need to export GDK_DEBUG to run on Wayland after GTK 4.14. + // Older versions of GTK do not support these values so it is safe + // to always set this. Forwards versions are uncertain so we'll have + // to reassess... + // + // Upstream issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/6589 + gdk_debug.@"gl-disable-gles" = true; + gdk_debug.@"gl-no-fractional" = true; + gdk_debug.@"vulkan-disable" = true; + break :environment; + } + // Versions prior to 4.14 are a bit of an unknown for Ghostty. It + // is an environment that isn't tested well and we don't have a + // good understanding of what we may need to do. + gdk_debug.@"vulkan-disable" = true; + } + + { + var buf: [128]u8 = undefined; + var fmt = std.io.fixedBufferStream(&buf); + const writer = fmt.writer(); + var first: bool = true; + inline for (@typeInfo(@TypeOf(gdk_debug)).Struct.fields) |field| { + if (@field(gdk_debug, field.name)) { + if (!first) try writer.writeAll(","); + try writer.writeAll(field.name); + first = false; + } + } + try writer.writeByte(0); + log.warn("setting GDK_DEBUG={s}", .{fmt.getWritten()}); + _ = internal_os.setenv("GDK_DEBUG", buf[0 .. fmt.pos - 1 :0]); + } + + { + var buf: [128]u8 = undefined; + var fmt = std.io.fixedBufferStream(&buf); + const writer = fmt.writer(); + var first: bool = true; + inline for (@typeInfo(@TypeOf(gdk_disable)).Struct.fields) |field| { + if (@field(gdk_disable, field.name)) { + if (!first) try writer.writeAll(","); + try writer.writeAll(field.name); + first = false; + } + } + try writer.writeByte(0); + log.warn("setting GDK_DISABLE={s}", .{fmt.getWritten()}); + _ = internal_os.setenv("GDK_DISABLE", buf[0 .. fmt.pos - 1 :0]); + } + + if (version.runtimeAtLeast(4, 14, 0)) { + // We need to export GSK_RENDERER to opengl because GTK uses ngl by + // default after 4.14 + _ = internal_os.setenv("GSK_RENDERER", "opengl"); + } + c.gtk_init(); const display: *c.GdkDisplay = c.gdk_display_get_default() orelse { // I'm unsure of any scenario where this happens. Because we don't diff --git a/src/config/Config.zig b/src/config/Config.zig index 1de0ddaad..6c5d0b1e2 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1975,6 +1975,15 @@ keybind: Keybinds = .{}, /// must always be able to move themselves into an isolated cgroup. @"linux-cgroup-hard-fail": bool = false, +/// Enable or disable GTK's OpenGL debugging logs. The default depends on the +/// optimization level that Ghostty was built with: +/// +/// - `Debug`: `true` +/// - `ReleaseSafe`: `true` +/// - `ReleaseSmall`: `true` +/// - `ReleaseFast`: `false` +@"gtk-opengl-debug": bool = build_config.slow_runtime_safety, + /// If `true`, the Ghostty GTK application will run in single-instance mode: /// each new `ghostty` process launched will result in a new window if there is /// already a running process. From 06a57842af1c3c71d6103e63fe4321eda1c6a556 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Mon, 6 Jan 2025 19:27:53 -0600 Subject: [PATCH 2/4] gtk: add config option to control GSK_RENDERER env var --- src/apprt/gtk/App.zig | 13 ++++++++++--- src/config/Config.zig | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index ba01236cc..10b8f756a 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -209,9 +209,16 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { } if (version.runtimeAtLeast(4, 14, 0)) { - // We need to export GSK_RENDERER to opengl because GTK uses ngl by - // default after 4.14 - _ = internal_os.setenv("GSK_RENDERER", "opengl"); + switch (config.@"gtk-gsk-renderer") { + .default => {}, + else => |renderer| { + // Force the GSK renderer to a specific value. After GTK 4.14 the + // `ngl` renderer is used by default which causes artifacts when + // used with Ghostty so it should be avoided. + log.warn("setting GSK_RENDERER={s}", .{@tagName(renderer)}); + _ = internal_os.setenv("GSK_RENDERER", @tagName(renderer)); + }, + } } c.gtk_init(); diff --git a/src/config/Config.zig b/src/config/Config.zig index 6c5d0b1e2..6c10213e8 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1984,6 +1984,14 @@ keybind: Keybinds = .{}, /// - `ReleaseFast`: `false` @"gtk-opengl-debug": bool = build_config.slow_runtime_safety, +/// After GTK 4.14.0, we need to force the GSK renderer to OpenGL as the default +/// GSK renderer is broken on some systems. If you would like to override +/// that bekavior, set `gtk-gsk-renderer=default` and either use your system's +/// default GSK renderer, or set the GSK_RENDERER environment variable to your +/// renderer of choice before launching Ghostty. This setting has no effect when +/// using versions of GTK earlier than 4.14.0. +@"gtk-gsk-renderer": GtkGskRenderer = .opengl, + /// If `true`, the Ghostty GTK application will run in single-instance mode: /// each new `ghostty` process launched will result in a new window if there is /// already a running process. @@ -6167,6 +6175,12 @@ pub const WindowPadding = struct { } }; +/// See the `gtk-gsk-renderer` config. +pub const GtkGskRenderer = enum { + default, + opengl, +}; + test "parse duration" { inline for (Duration.units) |unit| { var buf: [16]u8 = undefined; From cd638588c4e8b0dc9420878aa348e7f19a4995c6 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Wed, 8 Jan 2025 08:34:47 -0600 Subject: [PATCH 3/4] gtk: better method for setting GDK env vars --- src/apprt/gtk/App.zig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 10b8f756a..70fc182e5 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -187,8 +187,9 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { } } try writer.writeByte(0); - log.warn("setting GDK_DEBUG={s}", .{fmt.getWritten()}); - _ = internal_os.setenv("GDK_DEBUG", buf[0 .. fmt.pos - 1 :0]); + const value = fmt.getWritten(); + log.warn("setting GDK_DEBUG={s}", .{value[0 .. value.len - 1]}); + _ = internal_os.setenv("GDK_DEBUG", value[0 .. value.len - 1 :0]); } { @@ -204,8 +205,9 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { } } try writer.writeByte(0); - log.warn("setting GDK_DISABLE={s}", .{fmt.getWritten()}); - _ = internal_os.setenv("GDK_DISABLE", buf[0 .. fmt.pos - 1 :0]); + const value = fmt.getWritten(); + log.warn("setting GDK_DISABLE={s}", .{value[0 .. value.len - 1]}); + _ = internal_os.setenv("GDK_DISABLE", value[0 .. value.len - 1 :0]); } if (version.runtimeAtLeast(4, 14, 0)) { From 96e427cd6a86b765ba411135789319f3b8501902 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Fri, 10 Jan 2025 15:48:20 -0600 Subject: [PATCH 4/4] gtk: default to opengl debugging only on debug builds --- src/config/Config.zig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/config/Config.zig b/src/config/Config.zig index 6c10213e8..144796554 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1975,14 +1975,9 @@ keybind: Keybinds = .{}, /// must always be able to move themselves into an isolated cgroup. @"linux-cgroup-hard-fail": bool = false, -/// Enable or disable GTK's OpenGL debugging logs. The default depends on the -/// optimization level that Ghostty was built with: -/// -/// - `Debug`: `true` -/// - `ReleaseSafe`: `true` -/// - `ReleaseSmall`: `true` -/// - `ReleaseFast`: `false` -@"gtk-opengl-debug": bool = build_config.slow_runtime_safety, +/// Enable or disable GTK's OpenGL debugging logs. The default is `true` for +/// debug builds, `false` for all others. +@"gtk-opengl-debug": bool = builtin.mode == .Debug, /// After GTK 4.14.0, we need to force the GSK renderer to OpenGL as the default /// GSK renderer is broken on some systems. If you would like to override