From ab34b8b131eb2d60e7d22838dd6d77b98fec04b3 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Thu, 17 Sep 2026 22:07:14 +0800 Subject: [PATCH 1/5] opengl: explicitly set EGL_SURFACE_TYPE Co-authored-by: Daniel Kinzler --- src/renderer/OpenGL.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 31e9df4f2..fea0e4201 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -59,6 +59,11 @@ pub fn init(alloc: Allocator, opts: rendererpkg.Options) !OpenGL { // Choose a config. We need a config that is renderable with // OpenGL and a RGBA8 color buffer. const config = egl.Config.choose(display, &.{ + // EGL_SURFACE_TYPE defaults to EGL_WINDOW_BIT even though + // we are rendering exclusively through surfaceless mode. + // This is no problem on Mesa but we need to specify this + // explicitly for proprietary Nvidia drivers. + egl.c.EGL_SURFACE_TYPE, 0, egl.c.EGL_RENDERABLE_TYPE, egl.c.EGL_OPENGL_BIT, egl.c.EGL_RED_SIZE, 8, egl.c.EGL_GREEN_SIZE, 8, From c15e2f79922620f8651b92bb55662b19ce9505bb Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Thu, 17 Sep 2026 22:11:03 +0800 Subject: [PATCH 2/5] opengl: EGLattrib arrays need no explicit sentinel Array literals automagically gain the sentinel when assigned the correct type. Neat, huh? See https://ziglang.org/documentation/0.16.0/#Sentinel-Terminated-Arrays --- src/renderer/OpenGL.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index fea0e4201..21f277025 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -69,7 +69,6 @@ pub fn init(alloc: Allocator, opts: rendererpkg.Options) !OpenGL { egl.c.EGL_GREEN_SIZE, 8, egl.c.EGL_BLUE_SIZE, 8, egl.c.EGL_ALPHA_SIZE, 8, - egl.c.EGL_NONE, }) catch |err| { log.warn("failed to choose config err={}", .{err}); return err; @@ -80,7 +79,6 @@ pub fn init(alloc: Allocator, opts: rendererpkg.Options) !OpenGL { egl.c.EGL_CONTEXT_MAJOR_VERSION, MIN_VERSION_MAJOR, egl.c.EGL_CONTEXT_MINOR_VERSION, MIN_VERSION_MINOR, egl.c.EGL_CONTEXT_OPENGL_PROFILE_MASK, egl.c.EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, - egl.c.EGL_NONE, }) catch |err| { log.warn("failed to create EGL context err={}", .{err}); return err; From 851cd4dc13adbd17886ab1baf46280d27a6c9fa6 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Thu, 17 Sep 2026 22:14:43 +0800 Subject: [PATCH 3/5] gtk: disable Vulkan again, remove old version gates Vulkan is causing problems again... Also our minimum GTK version requirement is 4.18 now, so we can nuke all the old checks --- src/apprt/gtk/class/application.zig | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/apprt/gtk/class/application.zig b/src/apprt/gtk/class/application.zig index 4c3aa673c..05dc90910 100644 --- a/src/apprt/gtk/class/application.zig +++ b/src/apprt/gtk/class/application.zig @@ -3376,32 +3376,23 @@ const Action = struct { fn setGtkEnv(config: *const CoreConfig) std.Io.Writer.Error!void { assert(gtk.isInitialized() == 0); - var gdk_debug: struct { - /// output OpenGL debug information + const gdk_debug: struct { + /// Output OpenGL debug information, + /// `gtk-opengl-debug` dumps logs directly to stderr so both must be true + /// to enable OpenGL debugging. opengl: bool = false, - // GTK's new renderer can cause blurry font when using fractional scaling. - @"gl-no-fractional": bool = false, } = .{ - // `gtk-opengl-debug` dumps logs directly to stderr so both must be true - // to enable OpenGL debugging. .opengl = global.logging().stderr and config.@"gtk-opengl-debug", }; - var gdk_disable: struct { - /// current gtk implementation for color management is not good enough. - /// see: https://bugs.kde.org/show_bug.cgi?id=495647 - /// gtk issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/6864 - @"color-mgmt": bool = true, + const gdk_disable: struct { + // Even though we don't use GTK's GL context anymore, there can still + // occasionally be conflicts when Vulkan and OpenGL are used together. + // Disabling Vulkan also saves hundreds of milliseconds of initialization + // time on certain systems. + vulkan: bool = true, } = .{}; - if (gtk_version.runtimeAtLeast(4, 18, 0)) { - gdk_disable.@"color-mgmt" = false; - } - if (gtk_version.runtimeUntil(4, 17, 5)) { - // Removed at GTK v4.17.5 - gdk_debug.@"gl-no-fractional" = true; - } - { var buf: [1024]u8 = undefined; var writer: std.Io.Writer = .fixed(&buf); From 0fca3d34a56a420da92a7cb20109e71d523f7bf6 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Thu, 17 Sep 2026 23:35:11 +0800 Subject: [PATCH 4/5] gtk/imgui_widget: remove direct call to glClearColor Since the refactor to move our OpenGL context off-thread there is no more GLAD context loaded on the main thread for this widget, so calling ANY OpenGL function will crash the entire app. I don't think the call even worked as intended? I at least can't seem to tell any difference when the clear commands are simply removed. Maybe they were useful before. --- passthrough.glsl | 4 ++++ src/apprt/gtk/class/imgui_widget.zig | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 passthrough.glsl diff --git a/passthrough.glsl b/passthrough.glsl new file mode 100644 index 000000000..1102f4559 --- /dev/null +++ b/passthrough.glsl @@ -0,0 +1,4 @@ +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + vec2 uv = fragCoord / iResolution.xy; + fragColor = vec4(texture(iChannel0, uv).rgb, 1.0); +} diff --git a/src/apprt/gtk/class/imgui_widget.zig b/src/apprt/gtk/class/imgui_widget.zig index 50247fbf1..7961d7a83 100644 --- a/src/apprt/gtk/class/imgui_widget.zig +++ b/src/apprt/gtk/class/imgui_widget.zig @@ -317,9 +317,6 @@ pub const ImguiWidget = extern struct { cimgui.c.ImGui_Render(); } - // OpenGL final render - gl.clearColor(0x28 / 0xFF, 0x2C / 0xFF, 0x34 / 0xFF, 1.0); - gl.clear(gl.c.GL_COLOR_BUFFER_BIT); cimgui.ImGui_ImplOpenGL3_RenderDrawData(cimgui.c.ImGui_GetDrawData()); return @intFromBool(true); From 590ab157f4f05286888f5838f4167fe4fcc07be2 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Fri, 18 Sep 2026 00:05:01 +0800 Subject: [PATCH 5/5] opengl/Sampler: handle enum parameters correctly I'm so dumb like honestly, always double check if your unreachables are *comptime*. Whether the value being switched on is comptime or not does not matter --- pkg/opengl/Sampler.zig | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/opengl/Sampler.zig b/pkg/opengl/Sampler.zig index 8e1a1951a..d271f971e 100644 --- a/pkg/opengl/Sampler.zig +++ b/pkg/opengl/Sampler.zig @@ -27,13 +27,22 @@ pub fn parameter( comptime name: Texture.Parameter, value: name.Type(), ) errors.Error!void { - switch (@TypeOf(value)) { + const T = name.Type(); + + switch (T) { c.GLint => glad.context.SamplerParameteri.?( self.id, @intFromEnum(name), value, ), - else => unreachable, + else => switch (@typeInfo(T)) { + .@"enum" => glad.context.SamplerParameteri.?( + self.id, + @intFromEnum(name), + @intFromEnum(value), + ), + else => @compileLog("unsupported parameter type", T), + }, } try errors.getError(); }