From 9286e921a659cc5e3199d54ed61c0cc1c8c0d724 Mon Sep 17 00:00:00 2001 From: Sline Date: Sun, 7 Dec 2025 16:06:54 +0800 Subject: [PATCH] chore(linux): remove WebKit DMABUF env setup logic (#5758) --- src-tauri/src/lib.rs | 5 - src-tauri/src/utils/linux.rs | 506 +---------------------------------- 2 files changed, 1 insertion(+), 510 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index eb27f8116..f9ea71faf 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -10,8 +10,6 @@ mod feat; mod module; mod process; pub mod utils; -#[cfg(target_os = "linux")] -use crate::utils::linux; use crate::utils::resolve::init_signal; use crate::{constants::files, utils::resolve::prioritize_initialization}; use crate::{ @@ -232,9 +230,6 @@ pub fn run() { let _ = utils::dirs::init_portable_flag(); - #[cfg(target_os = "linux")] - linux::configure_environment(); - let builder = app_init::setup_plugins(tauri::Builder::default()) .setup(|app| { #[allow(clippy::expect_used)] diff --git a/src-tauri/src/utils/linux.rs b/src-tauri/src/utils/linux.rs index 0c8be9dab..f0b03de19 100644 --- a/src-tauri/src/utils/linux.rs +++ b/src-tauri/src/utils/linux.rs @@ -1,464 +1,9 @@ use anyhow::Result; -use clash_verge_logging::{Type, logging}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::env; use std::fs; use std::path::PathBuf; -const DRM_PATH: &str = "/sys/class/drm"; -const INTEL_VENDOR_ID: &str = "0x8086"; -const NVIDIA_VENDOR_ID: &str = "0x10de"; -const NVIDIA_VERSION_PATH: &str = "/proc/driver/nvidia/version"; - -#[derive(Debug, Default, Clone, Copy)] -struct IntelGpuDetection { - has_intel: bool, - intel_is_primary: bool, - inconclusive: bool, -} - -impl IntelGpuDetection { - const fn should_disable_dmabuf(&self) -> bool { - self.intel_is_primary || self.inconclusive - } -} - -#[derive(Debug, Default, Clone)] -struct NvidiaGpuDetection { - has_nvidia: bool, - nvidia_is_primary: bool, - missing_boot_vga: bool, - open_kernel_module: bool, - driver_summary: Option, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum NvidiaDmabufDisableReason { - PrimaryOpenKernelModule, - MissingBootVga, - PreferNativeWayland, -} - -impl NvidiaGpuDetection { - const fn disable_reason(&self, session: &SessionEnv) -> Option { - if !session.is_wayland { - return None; - } - - if !self.has_nvidia { - return None; - } - - if !self.open_kernel_module { - return None; - } - - if self.nvidia_is_primary { - return Some(NvidiaDmabufDisableReason::PrimaryOpenKernelModule); - } - - if self.missing_boot_vga { - return Some(NvidiaDmabufDisableReason::MissingBootVga); - } - - if session.prefer_native_wayland { - return Some(NvidiaDmabufDisableReason::PreferNativeWayland); - } - - None - } -} - -#[derive(Debug)] -struct SessionEnv { - is_kde_plasma: bool, - is_wayland: bool, - prefer_native_wayland: bool, - compositor_label: String, -} - -impl SessionEnv { - fn gather() -> Self { - let desktop_env = env::var("XDG_CURRENT_DESKTOP").unwrap_or_default().to_uppercase(); - let session_desktop = env::var("XDG_SESSION_DESKTOP").unwrap_or_default().to_uppercase(); - let desktop_session = env::var("DESKTOP_SESSION").unwrap_or_default().to_uppercase(); - - let is_kde_plasma = desktop_env.contains("KDE") - || session_desktop.contains("KDE") - || desktop_session.contains("KDE") - || desktop_env.contains("PLASMA") - || session_desktop.contains("PLASMA") - || desktop_session.contains("PLASMA"); - let is_hyprland = - desktop_env.contains("HYPR") || session_desktop.contains("HYPR") || desktop_session.contains("HYPR"); - let is_wayland = env::var("XDG_SESSION_TYPE") - .map(|value| value.eq_ignore_ascii_case("wayland")) - .unwrap_or(false) - || env::var("WAYLAND_DISPLAY").is_ok(); - let prefer_native_wayland = is_wayland && (is_kde_plasma || is_hyprland); - let compositor_label = if is_hyprland { - String::from("Hyprland") - } else if is_kde_plasma { - String::from("KDE Plasma") - } else { - String::from("Wayland compositor") - }; - - Self { - is_kde_plasma, - is_wayland, - prefer_native_wayland, - compositor_label, - } - } -} - -#[derive(Debug)] -struct DmabufOverrides { - user_preference: Option, - dmabuf_override: Option, -} - -impl DmabufOverrides { - fn gather() -> Self { - let user_preference = - env::var("CLASH_VERGE_DMABUF") - .ok() - .and_then(|value| match value.trim().to_ascii_lowercase().as_str() { - "1" | "true" | "enable" | "on" => Some(true), - "0" | "false" | "disable" | "off" => Some(false), - _ => None, - }); - let dmabuf_override = env::var("WEBKIT_DISABLE_DMABUF_RENDERER").ok(); - - Self { - user_preference, - dmabuf_override, - } - } - - const fn has_env_override(&self) -> bool { - self.dmabuf_override.is_some() - } - - const fn should_override_env(&self, decision: &DmabufDecision) -> bool { - if self.user_preference.is_some() { - return true; - } - - if decision.enable_dmabuf { - return true; - } - - !self.has_env_override() - } -} - -#[derive(Debug)] -struct DmabufDecision { - enable_dmabuf: bool, - force_x11_backend: bool, - warn: bool, - message: Option, -} - -impl DmabufDecision { - fn resolve( - session: &SessionEnv, - overrides: &DmabufOverrides, - intel_gpu: IntelGpuDetection, - nvidia_gpu: &NvidiaGpuDetection, - ) -> Self { - let mut decision = Self { - enable_dmabuf: true, - force_x11_backend: false, - warn: false, - message: None, - }; - - match overrides.user_preference { - Some(true) => { - decision.enable_dmabuf = true; - decision.message = Some("CLASH_VERGE_DMABUF=1: 强制启用 WebKit DMABUF 渲染。".into()); - } - Some(false) => { - decision.enable_dmabuf = false; - decision.message = Some("CLASH_VERGE_DMABUF=0: 强制禁用 WebKit DMABUF 渲染。".into()); - if session.is_wayland && !session.prefer_native_wayland { - decision.force_x11_backend = true; - } - } - None => { - if overrides.has_env_override() { - if overrides.dmabuf_override.as_deref() == Some("1") { - decision.enable_dmabuf = false; - decision.message = - Some("检测到 WEBKIT_DISABLE_DMABUF_RENDERER=1,沿用用户的软件渲染配置。".into()); - if session.is_wayland && !session.prefer_native_wayland { - decision.force_x11_backend = true; - } - } else { - decision.enable_dmabuf = true; - let value = overrides.dmabuf_override.clone().unwrap_or_default(); - decision.message = Some(format!( - "检测到 WEBKIT_DISABLE_DMABUF_RENDERER={},沿用用户配置。", - value - )); - } - } else if let Some(reason) = nvidia_gpu.disable_reason(session) { - decision.enable_dmabuf = false; - decision.warn = true; - if session.is_wayland && !session.prefer_native_wayland { - decision.force_x11_backend = true; - } - let summary = nvidia_gpu - .driver_summary - .as_deref() - .and_then(|line| { - extract_nvidia_driver_version(line) - .map(|version| format!("NVIDIA Open Kernel Module {}", version)) - }) - .unwrap_or_else(|| String::from("NVIDIA Open Kernel Module")); - let message = match reason { - NvidiaDmabufDisableReason::PrimaryOpenKernelModule => { - format!( - "Wayland 会话检测到 {}:禁用 WebKit DMABUF 渲染以规避协议错误。", - summary - ) - } - NvidiaDmabufDisableReason::MissingBootVga => { - format!( - "Wayland 会话检测到 {},但缺少 boot_vga 信息:预防性禁用 WebKit DMABUF。", - summary - ) - } - NvidiaDmabufDisableReason::PreferNativeWayland => format!( - "Wayland ({}) + {}:检测到 NVIDIA Open Kernel Module 在辅 GPU 上运行,预防性禁用 WebKit DMABUF。", - session.compositor_label, summary - ), - }; - decision.message = Some(message); - } else if session.prefer_native_wayland && !intel_gpu.should_disable_dmabuf() { - decision.enable_dmabuf = true; - decision.message = Some(format!( - "Wayland + {} detected: 使用原生 DMABUF 渲染。", - session.compositor_label - )); - } else { - decision.enable_dmabuf = false; - if session.is_wayland && !session.prefer_native_wayland { - decision.force_x11_backend = true; - } - - if intel_gpu.should_disable_dmabuf() && session.is_wayland { - decision.warn = true; - if intel_gpu.inconclusive { - decision.message = Some("Wayland 上检测到 Intel GPU,但缺少 boot_vga 信息:预防性禁用 WebKit DMABUF,若确认非主 GPU 可通过 CLASH_VERGE_DMABUF=1 覆盖。".into()); - } else { - decision.message = Some( - "Wayland 上检测到 Intel 主 GPU (0x8086):禁用 WebKit DMABUF 以避免帧缓冲失败。".into(), - ); - } - } else if session.is_wayland { - decision.message = Some("Wayland 会话未匹配受支持的合成器:禁用 WebKit DMABUF 渲染。".into()); - } else { - decision.message = Some("禁用 WebKit DMABUF 渲染以获得更稳定的输出。".into()); - } - } - } - } - - decision - } -} - -fn detect_intel_gpu() -> IntelGpuDetection { - let Ok(entries) = fs::read_dir(DRM_PATH) else { - return IntelGpuDetection::default(); - }; - - let mut detection = IntelGpuDetection::default(); - let mut seen_devices: HashSet = HashSet::new(); - let mut missing_boot_vga = false; - - for entry in entries.flatten() { - let name = entry.file_name(); - let name = name.to_string_lossy(); - - if !(name.starts_with("renderD") || name.starts_with("card")) { - continue; - } - - let device_path = entry.path().join("device"); - let device_key = fs::canonicalize(&device_path).unwrap_or(device_path); - - if !seen_devices.insert(device_key.clone()) { - continue; - } - - let vendor_path = device_key.join("vendor"); - let Ok(vendor) = fs::read_to_string(&vendor_path) else { - continue; - }; - - if !vendor.trim().eq_ignore_ascii_case(INTEL_VENDOR_ID) { - continue; - } - - detection.has_intel = true; - - let boot_vga_path = device_key.join("boot_vga"); - match fs::read_to_string(&boot_vga_path) { - Ok(flag) => { - if flag.trim() == "1" { - detection.intel_is_primary = true; - } - } - Err(_) => { - missing_boot_vga = true; - } - } - } - - if detection.has_intel && !detection.intel_is_primary && missing_boot_vga { - detection.inconclusive = true; - } - - detection -} - -fn detect_nvidia_gpu() -> NvidiaGpuDetection { - let mut detection = NvidiaGpuDetection::default(); - let entries = match fs::read_dir(DRM_PATH) { - Ok(entries) => entries, - Err(err) => { - logging!( - info, - Type::Setup, - "无法读取 DRM 设备目录 {}({}),尝试通过 NVIDIA 驱动摘要进行降级检测。", - DRM_PATH, - err - ); - detection.driver_summary = read_nvidia_driver_summary(); - if let Some(summary) = detection.driver_summary.as_ref() { - detection.open_kernel_module = summary_indicates_open_kernel_module(summary); - detection.has_nvidia = true; - detection.missing_boot_vga = true; - } else { - logging!( - info, - Type::Setup, - "降级检测失败:未能读取 NVIDIA 驱动摘要,保留 WebKit DMABUF。" - ); - } - return detection; - } - }; - - let mut seen_devices: HashSet = HashSet::new(); - - for entry in entries.flatten() { - let name = entry.file_name(); - let name = name.to_string_lossy(); - - if !(name.starts_with("renderD") || name.starts_with("card")) { - continue; - } - - let device_path = entry.path().join("device"); - let device_key = fs::canonicalize(&device_path).unwrap_or(device_path); - - if !seen_devices.insert(device_key.clone()) { - continue; - } - - let vendor_path = device_key.join("vendor"); - let Ok(vendor) = fs::read_to_string(&vendor_path) else { - continue; - }; - - if !vendor.trim().eq_ignore_ascii_case(NVIDIA_VENDOR_ID) { - continue; - } - - detection.has_nvidia = true; - - let boot_vga_path = device_key.join("boot_vga"); - match fs::read_to_string(&boot_vga_path) { - Ok(flag) => { - if flag.trim() == "1" { - detection.nvidia_is_primary = true; - } - } - Err(_) => { - detection.missing_boot_vga = true; - } - } - } - - if detection.has_nvidia { - detection.driver_summary = read_nvidia_driver_summary(); - match detection.driver_summary.as_ref() { - Some(summary) => { - detection.open_kernel_module = summary_indicates_open_kernel_module(summary); - } - None => { - logging!( - info, - Type::Setup, - "检测到 NVIDIA 设备,但无法读取 {},默认视为未启用开源内核模块。", - NVIDIA_VERSION_PATH - ); - } - } - } - - detection -} - -fn read_nvidia_driver_summary() -> Option { - match fs::read_to_string(NVIDIA_VERSION_PATH) { - Ok(content) => content - .lines() - .next() - .map(|line| line.trim().to_string()) - .filter(|line| !line.is_empty()), - Err(err) => { - logging!(info, Type::Setup, "读取 {} 失败:{}", NVIDIA_VERSION_PATH, err); - None - } - } -} - -fn summary_indicates_open_kernel_module(summary: &str) -> bool { - let normalized = summary.to_ascii_lowercase(); - const PATTERNS: [&str; 4] = [ - "open kernel module", - "open kernel modules", - "open gpu kernel module", - "open gpu kernel modules", - ]; - - let is_open = PATTERNS.iter().any(|pattern| normalized.contains(pattern)); - - if !is_open && normalized.contains("open") { - logging!( - info, - Type::Setup, - "检测到 NVIDIA 驱动摘要包含 open 关键字但未匹配已知开源模块格式:{}", - summary - ); - } - - is_open -} - -fn extract_nvidia_driver_version(summary: &str) -> Option<&str> { - summary - .split_whitespace() - .find(|token| token.chars().all(|c| c.is_ascii_digit() || c == '.')) -} - pub fn ensure_mimeapps_entries(desktop_file: &str, schemes: &[&str]) -> Result<()> { let Some(path) = mimeapps_list_path() else { return Ok(()); @@ -716,52 +261,3 @@ fn match_scheme<'a>(key: &str, schemes: &'a [&str]) -> Option<&'a str> { schemes.iter().copied().find(|candidate| *candidate == key) } - -pub fn configure_environment() { - let session = SessionEnv::gather(); - let overrides = DmabufOverrides::gather(); - let intel_gpu = detect_intel_gpu(); - let nvidia_gpu = detect_nvidia_gpu(); - let decision = DmabufDecision::resolve(&session, &overrides, intel_gpu, &nvidia_gpu); - - if overrides.should_override_env(&decision) { - unsafe { - if decision.enable_dmabuf { - env::remove_var("WEBKIT_DISABLE_DMABUF_RENDERER"); - } else { - env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); - } - } - } - - if let Some(message) = decision.message { - if decision.warn { - logging!(warn, Type::Setup, "{}", message); - } else { - logging!(info, Type::Setup, "{}", message); - } - } - - if decision.force_x11_backend { - unsafe { - env::set_var("GDK_BACKEND", "x11"); - env::remove_var("WAYLAND_DISPLAY"); - } - logging!( - info, - Type::Setup, - "Wayland detected: Forcing X11 backend for WebKit stability." - ); - } - - if session.is_kde_plasma { - unsafe { - env::set_var("GTK_CSD", "0"); - } - logging!( - info, - Type::Setup, - "KDE/Plasma detected: Disabled GTK CSD for better titlebar stability." - ); - } -}