mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
## Summary - Heuristic and `--safe-rendering` now set `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` instead of `WEBKIT_DISABLE_DMABUF_RENDERER=1` - Legacy `DISABLE_DMABUF` stays owned so operators can still set `=0`/`=1` and take over the decision - Linux troubleshooting docs updated to match (#3654) ## Test plan - [ ] unit tests in `webkit_rendering::tests` - [ ] On NVIDIA + WebKitGTK 2.52: workspace switch no longer SIGSEGVs where the distro NVIDIA guard does not fire (Debian/Ubuntu proprietary-NVIDIA may still crash — #3654 stays open for that path) - [ ] `WEBKIT_DISABLE_DMABUF_RENDERER=0` still stands the heuristic down --------- Signed-off-by: Taksh <takshkothari09@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Alia <d32955ad69077062930cc46cfe2df30ca9aaf6f8e76422681265e9e9af704d78@buzz.block.builderlab.xyz> Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
co-authored by
Alia
Will Pfleger
parent
daa8877581
commit
60ae74b656
@@ -2,9 +2,14 @@
|
||||
//!
|
||||
//! WebKitGTK's dmabuf renderer aborts the web process during startup on some
|
||||
//! GPU/driver/compositor combinations, so Buzz comes up with no window at all
|
||||
//! and the user has no way to fix it (#2338, upstream tauri#9394). Setting
|
||||
//! `WEBKIT_DISABLE_DMABUF_RENDERER=1` avoids the abort by falling back to the
|
||||
//! shared-memory buffer path.
|
||||
//! and the user has no way to fix it (#2338, upstream tauri#9394).
|
||||
//!
|
||||
//! Historically Buzz set `WEBKIT_DISABLE_DMABUF_RENDERER=1`, which used to fall
|
||||
//! back to shared-memory buffers. On current WebKitGTK that variable leaves the
|
||||
//! transport mode empty, so `AcceleratedBackingStore::create()` returns null
|
||||
//! and the UI SIGSEGVs the first time compositing is needed (#3654).
|
||||
//! `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` is the documented replacement: it keeps
|
||||
//! SharedMemory in the transport set and still avoids the hardware dmabuf path.
|
||||
//!
|
||||
//! WebKit reads each of these variables exactly once per process, so the choice
|
||||
//! has to be made before anything initializes — there is no runtime toggle and
|
||||
@@ -20,7 +25,7 @@
|
||||
//!
|
||||
//! This is the shape the Tauri ecosystem converged on: clash-verge-rev's
|
||||
//! `utils/linux/workarounds.rs` and screenpipe's `linux_webkit_env.rs` both set
|
||||
//! the same variable from the same signals at the same point in startup.
|
||||
//! WebKit dmabuf env vars from the same signals at the same point in startup.
|
||||
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::Path;
|
||||
@@ -34,21 +39,30 @@ const NVIDIA_PCI_VENDOR: &str = "0x10de";
|
||||
/// Where DRM devices advertise their PCI vendor.
|
||||
const DRM_ROOT: &str = "/sys/class/drm";
|
||||
|
||||
/// Drops the zero-copy dmabuf buffer path. The workaround for #2338.
|
||||
/// Prefer shared-memory dmabuf transport. The #3654 replacement for
|
||||
/// `WEBKIT_DISABLE_DMABUF_RENDERER` on current WebKitGTK.
|
||||
const FORCE_SHM: &str = "WEBKIT_DMABUF_RENDERER_FORCE_SHM";
|
||||
/// Legacy kill-switch. Still owned so operators can set `=0` / `=1` and take
|
||||
/// the decision away from this module, but never written by the heuristic
|
||||
/// (it crashes modern WebKitGTK — see #3654).
|
||||
const DISABLE_DMABUF: &str = "WEBKIT_DISABLE_DMABUF_RENDERER";
|
||||
/// Drops accelerated compositing as well. `--safe-rendering` only.
|
||||
const DISABLE_COMPOSITING: &str = "WEBKIT_DISABLE_COMPOSITING_MODE";
|
||||
|
||||
/// What the heuristic applies: the #2338 workaround alone, matching the
|
||||
/// ecosystem precedents. `DISABLE_COMPOSITING` is deliberately not here — no
|
||||
/// report has isolated it as necessary, and it costs more rendering than this.
|
||||
const HEURISTIC: [&str; 1] = [DISABLE_DMABUF];
|
||||
/// What the heuristic applies: force shared-memory transport without emptying
|
||||
/// the buffer mode set (#3654).
|
||||
const HEURISTIC: [&str; 1] = [FORCE_SHM];
|
||||
|
||||
/// What `--safe-rendering` applies, which is also every variable this module may
|
||||
/// set and therefore every variable a user assignment takes away from it. Being
|
||||
/// the same list is the invariant: nothing outside it is ever written, so a user
|
||||
/// value for any other WebKit variable is not a conflict.
|
||||
const OWNED: [&str; 2] = [DISABLE_DMABUF, DISABLE_COMPOSITING];
|
||||
/// What `--safe-rendering` applies: FORCE_SHM plus compositing off. Deliberately
|
||||
/// omits DISABLE_DMABUF — that variable is the #3654 crash on current WebKit.
|
||||
const SAFE_VARS: [&str; 2] = [FORCE_SHM, DISABLE_COMPOSITING];
|
||||
|
||||
/// Every variable this module may set, and therefore every variable a user
|
||||
/// assignment takes away from it. Being the same list is the invariant: nothing
|
||||
/// outside it is ever written, so a user value for any other WebKit variable is
|
||||
/// not a conflict. DISABLE_DMABUF stays owned so `=0` still stands the heuristic
|
||||
/// down for operators who need the old path or an explicit override.
|
||||
const OWNED: [&str; 3] = [FORCE_SHM, DISABLE_DMABUF, DISABLE_COMPOSITING];
|
||||
|
||||
/// Reads one environment variable. Injected so the decision is testable without
|
||||
/// mutating the process environment. `OsString` rather than `String` because
|
||||
@@ -124,15 +138,29 @@ fn plan(
|
||||
true => Plan::Fatal {
|
||||
diagnostic: conflict(&user_set),
|
||||
},
|
||||
false => Plan::Leave {
|
||||
why: format!("{} set in the environment", describe(&user_set)),
|
||||
},
|
||||
false => {
|
||||
let mut why = format!("{} set in the environment", describe(&user_set));
|
||||
// Older docs told people to export DISABLE_DMABUF=1; on current
|
||||
// WebKitGTK that empties the transport and SIGSEGVs (#3654).
|
||||
// Leave the takeover alone, but point survivors at FORCE_SHM.
|
||||
if user_set
|
||||
.iter()
|
||||
.any(|(key, value)| *key == DISABLE_DMABUF && value.as_os_str() != "0")
|
||||
{
|
||||
why.push_str(&format!(
|
||||
"; warning: {DISABLE_DMABUF} (other than =0) empties the \
|
||||
transport on current WebKitGTK and SIGSEGVs — prefer \
|
||||
{FORCE_SHM}=1 (see #3654)"
|
||||
));
|
||||
}
|
||||
Plan::Leave { why }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if safe_rendering {
|
||||
return Plan::Apply {
|
||||
vars: &OWNED,
|
||||
vars: &SAFE_VARS,
|
||||
why: format!("{SAFE_RENDERING} requested, this launch only"),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ fn applied(plan: &Plan) -> Option<&[&str]> {
|
||||
// ── Detection ───────────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn test_nvidia_gpu_disables_the_dmabuf_renderer() {
|
||||
fn test_nvidia_gpu_forces_shared_memory_dmabuf_transport() {
|
||||
let drm = drm(&["0x10de"]);
|
||||
let plan = plan(NO_ARGS, &env_from(&[]), drm.path());
|
||||
|
||||
assert_eq!(
|
||||
applied(&plan),
|
||||
Some(&["WEBKIT_DISABLE_DMABUF_RENDERER"][..])
|
||||
Some(&["WEBKIT_DMABUF_RENDERER_FORCE_SHM"][..])
|
||||
);
|
||||
let Plan::Apply { why, .. } = &plan else {
|
||||
unreachable!()
|
||||
@@ -66,7 +66,7 @@ fn test_an_nvidia_gpu_alongside_another_vendor_still_counts() {
|
||||
|
||||
assert_eq!(
|
||||
applied(&plan(NO_ARGS, &env_from(&[]), drm.path())),
|
||||
Some(&["WEBKIT_DISABLE_DMABUF_RENDERER"][..])
|
||||
Some(&["WEBKIT_DMABUF_RENDERER_FORCE_SHM"][..])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,12 +76,12 @@ fn test_the_vendor_id_match_ignores_case() {
|
||||
|
||||
assert_eq!(
|
||||
applied(&plan(NO_ARGS, &env_from(&[]), drm.path())),
|
||||
Some(&["WEBKIT_DISABLE_DMABUF_RENDERER"][..])
|
||||
Some(&["WEBKIT_DMABUF_RENDERER_FORCE_SHM"][..])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_an_appimage_launch_disables_the_dmabuf_renderer() {
|
||||
fn test_an_appimage_launch_forces_shared_memory_dmabuf_transport() {
|
||||
// No NVIDIA GPU: the AppImage signal has to carry this on its own, which is
|
||||
// #2338's reporter (Intel Mesa under the AppRun's pinned XWayland backend).
|
||||
let drm = drm(&["0x8086"]);
|
||||
@@ -90,7 +90,7 @@ fn test_an_appimage_launch_disables_the_dmabuf_renderer() {
|
||||
|
||||
assert_eq!(
|
||||
applied(&plan),
|
||||
Some(&["WEBKIT_DISABLE_DMABUF_RENDERER"][..])
|
||||
Some(&["WEBKIT_DMABUF_RENDERER_FORCE_SHM"][..])
|
||||
);
|
||||
let Plan::Apply { why, .. } = &plan else {
|
||||
unreachable!()
|
||||
@@ -133,7 +133,7 @@ fn test_a_device_without_a_vendor_file_is_skipped_not_fatal() {
|
||||
|
||||
assert_eq!(
|
||||
applied(&plan(NO_ARGS, &env_from(&[]), root.path())),
|
||||
Some(&["WEBKIT_DISABLE_DMABUF_RENDERER"][..])
|
||||
Some(&["WEBKIT_DMABUF_RENDERER_FORCE_SHM"][..])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,6 +153,34 @@ fn test_a_user_set_variable_disables_the_heuristic_wholesale() {
|
||||
assert!(why.contains("WEBKIT_DISABLE_DMABUF_RENDERER=0"), "{why}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_user_set_force_shm_also_stands_the_heuristic_down() {
|
||||
// FORCE_SHM joined OWNED in the #3654 swap; a user export must take the
|
||||
// whole decision away, same as the older DISABLE_DMABUF takeover.
|
||||
let drm = drm(&["0x10de"]);
|
||||
let env = env_from(&[(FORCE_SHM, "1")]);
|
||||
let plan = plan(NO_ARGS, &env, drm.path());
|
||||
|
||||
let Plan::Leave { why } = &plan else {
|
||||
panic!("a user FORCE_SHM assignment must not be overwritten: {plan:?}");
|
||||
};
|
||||
assert!(why.contains("WEBKIT_DMABUF_RENDERER_FORCE_SHM=1"), "{why}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_user_set_disable_dmabuf_one_warns_about_the_crashy_var() {
|
||||
let drm = drm(&["0x10de"]);
|
||||
let env = env_from(&[(DISABLE_DMABUF, "1")]);
|
||||
let plan = plan(NO_ARGS, &env, drm.path());
|
||||
|
||||
let Plan::Leave { why } = &plan else {
|
||||
panic!("expected Leave: {plan:?}");
|
||||
};
|
||||
assert!(why.contains("WEBKIT_DISABLE_DMABUF_RENDERER=1"), "{why}");
|
||||
assert!(why.contains("WEBKIT_DMABUF_RENDERER_FORCE_SHM"), "{why}");
|
||||
assert!(why.contains("#3654"), "{why}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_an_empty_assignment_is_still_a_user_assignment() {
|
||||
let drm = drm(&["0x10de"]);
|
||||
@@ -192,7 +220,7 @@ fn test_safe_rendering_applies_the_safest_set_without_any_hardware_signal() {
|
||||
applied(&plan),
|
||||
Some(
|
||||
&[
|
||||
"WEBKIT_DISABLE_DMABUF_RENDERER",
|
||||
"WEBKIT_DMABUF_RENDERER_FORCE_SHM",
|
||||
"WEBKIT_DISABLE_COMPOSITING_MODE"
|
||||
][..]
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ This guide covers the most common rendering failures on Linux and how to resolve
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---------|-------------|-----|
|
||||
| Blank or transparent window, then `SIGABRT` with `colrv1_configure_skpaint` in the output | COLRv1 color emoji font (AppImage only) | Upgrade to the latest AppImage (v0.5.2+) |
|
||||
| Blank window on startup, no crash output | dmabuf renderer incompatibility (NVIDIA or AppImage) | `WEBKIT_DISABLE_DMABUF_RENDERER=1 ./Buzz.AppImage` or `--safe-rendering` |
|
||||
| Blank window on startup / SIGSEGV when switching workspaces | dmabuf renderer incompatibility (NVIDIA or AppImage) | Prefer `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` (shipped automatically) or `--safe-rendering`. Do **not** set `WEBKIT_DISABLE_DMABUF_RENDERER=1` on current WebKitGTK — see [#3654](https://github.com/block/buzz/issues/3654). On Debian/Ubuntu with the proprietary NVIDIA driver the crash can persist (distro WebKit patch) — [#3654](https://github.com/block/buzz/issues/3654) stays open for that path. |
|
||||
| Blank window on any hardware, no crash output | Unknown GPU/driver combination | `--safe-rendering` flag (see below) |
|
||||
|
||||
---
|
||||
@@ -69,9 +69,11 @@ FONTCONFIG_FILE=~/.config/buzz-fontconfig/fonts.conf ./Buzz_*.AppImage
|
||||
|
||||
**Root cause:** WebKitGTK's dmabuf zero-copy buffer path is incompatible with some GPU/driver/compositor combinations. The WebKit child process silently fails to paint.
|
||||
|
||||
**Fix (shipped automatically starting with the first release containing [#3271](https://github.com/block/buzz/pull/3271) (v0.5.1)):** Buzz sets `WEBKIT_DISABLE_DMABUF_RENDERER=1` automatically before WebKit initializes when it detects an NVIDIA GPU (`/sys/class/drm` vendor ID `0x10de`) or when running as an AppImage. This restores a slightly slower shared-memory rendering path that works universally.
|
||||
**Fix (shipped automatically starting with the first release containing [#3271](https://github.com/block/buzz/pull/3271) (v0.5.1), updated for [#3654](https://github.com/block/buzz/issues/3654)):** Buzz sets `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` automatically before WebKit initializes when it detects an NVIDIA GPU (`/sys/class/drm` vendor ID `0x10de`) or when running as an AppImage. That keeps SharedMemory in WebKit's transport set while skipping the hardware dmabuf path (upstream WebKitGTK; Debian/Ubuntu's NVIDIA dmabuf patch can bypass this, so the crash can persist there — [#3654](https://github.com/block/buzz/issues/3654) stays open for that path). `WEBKIT_DMABUF_RENDERER_FORCE_SHM` exists in WebKitGTK ≥ 2.44 (absent at 2.42); on older system WebKit the export is a silent no-op.
|
||||
|
||||
**If automatic detection doesn't help (`--safe-rendering`):** Pass `--safe-rendering` to force both `WEBKIT_DISABLE_DMABUF_RENDERER=1` and `WEBKIT_DISABLE_COMPOSITING_MODE=1` for that launch:
|
||||
**Do not use `WEBKIT_DISABLE_DMABUF_RENDERER=1` on current WebKitGTK** (2.52+): that variable no longer falls back to shared memory. It empties the transport mode, `AcceleratedBackingStore::create()` returns null, and the UI SIGSEGVs the first time compositing is needed (often on workspace switch). See [#3654](https://github.com/block/buzz/issues/3654).
|
||||
|
||||
**If automatic detection doesn't help (`--safe-rendering`):** Pass `--safe-rendering` to force both `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` and `WEBKIT_DISABLE_COMPOSITING_MODE=1` for that launch:
|
||||
|
||||
```bash
|
||||
./Buzz_*.AppImage --safe-rendering
|
||||
@@ -83,10 +85,10 @@ buzz-desktop --safe-rendering
|
||||
|
||||
```bash
|
||||
# ~/.bashrc or ~/.profile
|
||||
export WEBKIT_DISABLE_DMABUF_RENDERER=1
|
||||
export WEBKIT_DMABUF_RENDERER_FORCE_SHM=1
|
||||
```
|
||||
|
||||
**Conflict detection:** If you set a WebKit variable in your environment and also pass `--safe-rendering`, Buzz will refuse to start and print exactly which variable conflicts. Unset the conflicting variable or drop the flag.
|
||||
**Conflict detection:** If you set a WebKit variable in your environment and also pass `--safe-rendering`, Buzz will refuse to start and print exactly which variable conflicts. Unset the conflicting variable or drop the flag. Operators who previously exported `WEBKIT_DISABLE_DMABUF_RENDERER=0` to override the old heuristic can keep that — the module still treats that assignment as a user takeover.
|
||||
|
||||
---
|
||||
|
||||
@@ -96,11 +98,11 @@ export WEBKIT_DISABLE_DMABUF_RENDERER=1
|
||||
|
||||
**Symptom:** The Buzz window is transparent or renders with graphical corruption on AMD RDNA4 hardware.
|
||||
|
||||
**Workaround (verified by reporter):** Set these three variables before launching Buzz:
|
||||
**Workaround (recommended; FORCE_SHM swap not re-verified on RDNA4):** Set these three variables before launching Buzz. The reporter originally verified a three-var set that used `WEBKIT_DISABLE_DMABUF_RENDERER=1`; that var is the [#3654](https://github.com/block/buzz/issues/3654) crash on current WebKitGTK, so this recipe swaps in `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` instead. Please re-confirm on RDNA4 if you can.
|
||||
|
||||
```bash
|
||||
export GDK_BACKEND=x11
|
||||
export WEBKIT_DISABLE_DMABUF_RENDERER=1
|
||||
export WEBKIT_DMABUF_RENDERER_FORCE_SHM=1
|
||||
export WEBKIT_SKIA_ENABLE_CPU_RENDERING=1
|
||||
./Buzz_*.AppImage
|
||||
# or for native:
|
||||
@@ -109,7 +111,7 @@ buzz-desktop
|
||||
|
||||
- `WEBKIT_SKIA_ENABLE_CPU_RENDERING=1` forces Skia to use CPU rendering, bypassing the RDNA4 Skia/radv paint failure.
|
||||
- `GDK_BACKEND=x11` avoids the blank window that appears when running under a Plasma-Wayland compositor.
|
||||
- `WEBKIT_DISABLE_DMABUF_RENDERER=1` prevents post-first-paint transparency from the dmabuf renderer.
|
||||
- `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` keeps shared-memory transport without the #3654 empty-mode crash from `WEBKIT_DISABLE_DMABUF_RENDERER` (needs WebKitGTK ≥ 2.44).
|
||||
|
||||
A dedicated fix for RDNA4 detection is being tracked in [#2643](https://github.com/block/buzz/issues/2643).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user