diff --git a/Changelog.md b/Changelog.md index 924602514..c0853940e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -24,5 +24,6 @@ - 应用内更新日志支持解析并渲染 HTML 标签 - 性能优化前后端在渲染流量图时的资源 +- 在 Linux NVIDIA 显卡环境下尝试禁用 WebKit DMABUF 渲染以规避潜在问题 diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 08b3c358b..26f9c7121 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -229,6 +229,9 @@ pub fn run() { return; } + #[cfg(target_os = "linux")] + utils::workarounds::apply_nvidia_dmabuf_renderer_workaround(); + let _ = utils::dirs::init_portable_flag(); let builder = app_init::setup_plugins(tauri::Builder::default()) diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index d0143ad47..92b1bb7f7 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -13,3 +13,5 @@ pub mod server; pub mod singleton; pub mod tmpl; pub mod window_manager; +#[cfg(target_os = "linux")] +pub mod workarounds; diff --git a/src-tauri/src/utils/workarounds.rs b/src-tauri/src/utils/workarounds.rs new file mode 100644 index 000000000..ff5e589d0 --- /dev/null +++ b/src-tauri/src/utils/workarounds.rs @@ -0,0 +1,55 @@ +//! Best-effort platform workarounds for known upstream issues. +//! +//! NOTE: +//! These helpers are not fixes and may stop working as environments change. + +use clash_verge_logging::{Type, logging}; +use std::{fs, path::Path}; + +pub fn apply_nvidia_dmabuf_renderer_workaround() { + if std::env::var_os("WEBKIT_DISABLE_DMABUF_RENDERER").is_some() { + return; + } + + if has_nvidia_gpu() { + unsafe { + std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); + } + logging!( + info, + Type::Setup, + "Detected NVIDIA GPU, set WEBKIT_DISABLE_DMABUF_RENDERER=1" + ); + } +} + +fn has_nvidia_gpu() -> bool { + if Path::new("/proc/driver/nvidia/version").exists() + || Path::new("/sys/module/nvidia").exists() + || Path::new("/sys/module/nvidia_drm").exists() + { + return true; + } + + let Ok(entries) = fs::read_dir("/sys/class/drm") else { + return false; + }; + + for entry in entries.flatten() { + let name = entry.file_name(); + let name = name.to_string_lossy(); + if !name.starts_with("card") || name.contains('-') { + continue; + } + + let vendor_path = entry.path().join("device/vendor"); + let Ok(vendor) = fs::read_to_string(vendor_path) else { + continue; + }; + if vendor.trim().eq_ignore_ascii_case("0x10de") { + return true; + } + } + + false +}