From 0bf0901a959e4c8c0ba1013d2fbf318d55598dcc Mon Sep 17 00:00:00 2001 From: peachismomo Date: Fri, 9 Oct 2026 03:31:44 +0800 Subject: [PATCH] fix: use WEBKIT_DISABLE_DMABUF_RENDERER 1 when using WebKitGTK >= 2.46 --- .../references/webview-gl-aui-media.md | 25 +++++++++++-- src/OrcaSlicer.cpp | 35 +++++++++++++++++++ src/slic3r/GUI/Widgets/WebView.cpp | 19 ++++++++++ src/slic3r/GUI/Widgets/WebView.hpp | 4 +++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/.claude/skills/orca-wxwidgets/references/webview-gl-aui-media.md b/.claude/skills/orca-wxwidgets/references/webview-gl-aui-media.md index b8856b21ca..320641e30d 100644 --- a/.claude/skills/orca-wxwidgets/references/webview-gl-aui-media.md +++ b/.claude/skills/orca-wxwidgets/references/webview-gl-aui-media.md @@ -61,8 +61,10 @@ available; GTK2/WebKit1 is an opt-out configuration the GUI does not support. 11. A web host that re-themes in place handles `EVT_WEBVIEW_RECREATED` without `Skip()`; one that needs a reload lets it through. §[Orca wrapper](#orca-webview-wrapper-widgetswebview) 12. Keep `WebViewWebKit`'s destructor removing the `"wx"` handler. §[Orca wrapper](#orca-webview-wrapper-widgetswebview) -13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case, and never - make a page's progress depend only on a C++→JS callback. §[WebKitGTK on Linux](#webkitgtk-on-linux-sessions) +13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case. Disable the + WebKit DMA-BUF renderer only for the NVIDIA proprietary driver on native Wayland (GNOME/gtk#8056), and + never make a page's progress depend only on a C++→JS callback. + §[WebKitGTK on Linux](#webkitgtk-on-linux-sessions) 14. GL attribute lists: legacy `int[]` lists end with `0` and spell out `WX_GL_RGBA` and `WX_GL_DOUBLEBUFFER`; `wxGLAttributes`/`wxGLContextAttrs` end with `EndList()`; MSAA is requested explicitly. §[wxGLCanvas](#wxglcanvas-and-wxglcontext) @@ -599,6 +601,25 @@ Runtime backend detection elsewhere uses Orca's `is_running_on_wayland()` / `is_ Cite: c12912e0df (`src/OrcaSlicer.cpp`; `resources/web/guide/0/load.js` `OnInit` `setTimeout("JumpToTarget()", …)`), 9446030079 (the `GDK_BACKEND=x11` opt-in branch). +**DMA-BUF renderer / explicit sync (NVIDIA + Wayland).** +- **Rule:** On the Wayland default path, set `WEBKIT_DISABLE_DMABUF_RENDERER=1` non-replacing, gated to + `__linux__` + native Wayland (not the forced-X11 fallback) + `/proc/driver/nvidia/version` + + `WebView::WebKitAtLeast(2, 46)`. The version gate uses the runtime `webkit_get_major_version()` / + `webkit_get_minor_version()` getters (no GTK init needed), not a compile-time macro, and 2.46 is the + oldest release with a confirmed crash report — narrower gates (e.g. 2.54) would miss 2.46–2.52 victims. + **Why:** WebKitGTK's DMA-BUF renderer arms `linux-drm-syncobj-v1` on the toplevel surface; GTK3 then + commits its first shared-memory frame without an acquire point, and KWin/Mutter reject the commit with + `Error 71 (Protocol error)` — GDK turns that into `_exit(1)` before Orca logs anything. The defect is + GTK3's `gdk_wayland_window_attach_image()` (GNOME/gtk#8056); WebKit only triggers it, the NVIDIA + proprietary driver has no implicit-sync fallback (Mesa tolerates it), and no upstream fix or PR exists. + This is a different variable from `WEBKIT_DISABLE_COMPOSITING_MODE` and does not replace it. + ```cpp + // Wayland default path, before GTK init + if (!x11_backend && wayland && ::access("/proc/driver/nvidia/version", F_OK) == 0 && + WebView::WebKitAtLeast(2, 46)) + ::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", /* replace */ false); + ``` + ## wxGLCanvas and wxGLContext **Attributes.** diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index b895c25e89..30ac8c0e7a 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -165,6 +165,7 @@ using json = nlohmann::json; #ifdef SLIC3R_GUI #include "slic3r/GUI/GUI_Init.hpp" + #include "slic3r/GUI/Widgets/WebView.hpp" // BBLPrinterAgent::from_orca_filament_id(); the map and its lookups live in libslic3r_gui, // which only a SLIC3R_GUI build links (see target_link_libraries(OrcaSlicer libslic3r_gui) // in CMakeLists). @@ -1155,6 +1156,12 @@ int CLI::run(int argc, char **argv) // unset preserves WebKit hardware acceleration on Device / Setup // Wizard / login / store. The default path still applies it on // XWayland sessions as a conservative fallback for older WebKit. + // + // The default path also disables WebKit's DMA-BUF renderer when the + // NVIDIA proprietary driver is in use on native Wayland. That is a + // separate switch from compositing and is needed because GTK3 commits + // a shared-memory frame onto an explicit-sync surface (GNOME/gtk#8056), + // which KWin/Mutter reject with "Error 71 (Protocol error)". // ------------------------------------------------------------------ { const char* gdk_backend = ::getenv("GDK_BACKEND"); @@ -1218,6 +1225,34 @@ int CLI::run(int argc, char **argv) } } + // WebKitGTK's DMA-BUF renderer arms explicit sync + // (linux-drm-syncobj-v1) on the toplevel Wayland surface. If the + // first painted frame is a shared-memory buffer, GTK3's + // gdk_wayland_window_attach_image() commits it without an acquire + // point, and compositors that enforce the protocol (KWin, Mutter) + // terminate the client with "Error 71 (Protocol error)" before the + // app can log anything (GNOME/gtk#8056). NVIDIA's proprietary + // driver has no implicit-sync fallback, so the crash only happens + // there; Mesa tolerates the missing point. Scope the workaround to + // NVIDIA on native Wayland, on WebKitGTK >= 2.46 (the oldest release + // with a confirmed report; the DMA-BUF renderer predates it). + // Non-replacing, so a user who does not hit the bug can opt back in + // with WEBKIT_DISABLE_DMABUF_RENDERER=0. + #if defined(__linux__) + { + const char* gdk_backend_wk = ::getenv("GDK_BACKEND"); + // The EGL-less fallback above may have just forced X11. + const bool x11_backend_wk = gdk_backend_wk && boost::starts_with(gdk_backend_wk, "x11"); + const char* wayland_env_dmabuf = ::getenv("WAYLAND_DISPLAY"); + if (!x11_backend_wk && wayland_env_dmabuf && *wayland_env_dmabuf && + ::access("/proc/driver/nvidia/version", F_OK) == 0 && + WebView::WebKitAtLeast(2, 46)) { + BOOST_LOG_TRIVIAL(info) << "NVIDIA proprietary driver on Wayland: disabling the WebKit DMA-BUF renderer (GNOME/gtk#8056 workaround)."; + ::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", /* replace */ false); + } + } + #endif + // XInitThreads is needed before GStreamer may use Xlib. On // native Wayland without DISPLAY, GStreamer uses waylandsink // (no Xlib involved), so the call is skipped. diff --git a/src/slic3r/GUI/Widgets/WebView.cpp b/src/slic3r/GUI/Widgets/WebView.cpp index 498fa4ec43..02f4b64d4a 100644 --- a/src/slic3r/GUI/Widgets/WebView.cpp +++ b/src/slic3r/GUI/Widgets/WebView.cpp @@ -69,6 +69,10 @@ webkit_web_view_run_javascript_finish (WebKitWebView GError **error); WEBKIT_API void webkit_javascript_result_unref (WebKitJavascriptResult *js_result); +WEBKIT_API unsigned int +webkit_get_major_version (void); +WEBKIT_API unsigned int +webkit_get_minor_version (void); } #endif @@ -401,6 +405,21 @@ bool WebView::NeedsRecreateOnShow() return false; #endif } + +bool WebView::WebKitAtLeast(int major, int minor) +{ +#if defined(__linux__) + const unsigned int running_major = webkit_get_major_version(); + if (running_major != static_cast(major)) + return running_major > static_cast(major); + return webkit_get_minor_version() >= static_cast(minor); +#else + (void) major; + (void) minor; + return false; +#endif +} + #if wxUSE_WEBVIEW_EDGE bool WebView::CheckWebViewRuntime() { diff --git a/src/slic3r/GUI/Widgets/WebView.hpp b/src/slic3r/GUI/Widgets/WebView.hpp index cdd885f9bd..a2aba65dbf 100644 --- a/src/slic3r/GUI/Widgets/WebView.hpp +++ b/src/slic3r/GUI/Widgets/WebView.hpp @@ -30,6 +30,10 @@ public: // ignoring every navigation. A panel that gets true here recreates its view on first Show(). static bool NeedsRecreateOnShow(); + // Runtime version of the linked WebKitGTK, for gating the Linux DMA-BUF + // renderer workaround. Returns false on non-GTK builds. + static bool WebKitAtLeast(int major, int minor); + static void RecreateAll(); };