# 显卡切换与驱动安装设计方案 ## 背景 当前插件已实现 GPU 检测、温度/使用率监控、主副显标识和 GPU 模式检测。 本文档描述后续两个功能的架构方案:**显卡切换** 和 **驱动安装**。 --- ## 一、显卡切换(PRIME Render Offload) ### 1.1 原理 Linux 双 GPU 笔记本(核显+独显)通过 PRIME Render Offload 实现按需渲染: - 核显(AMD/Intel)负责日常显示输出 - 独显(NVIDIA)按需渲染 3D 应用 - 通过环境变量控制渲染 GPU: - `__NV_PRIME_RENDER_OFFLOAD=1` - 启用 NVIDIA offload - `__GLX_VENDOR_LIBRARY_NAME=nvidia` - 指定 OpenGL 实现为 NVIDIA ### 1.2 系统现状 | 检测项 | 当前状态 | |--------|---------| | PRIME 配置文件 | `/usr/share/X11/xorg.conf.d/nvidia-drm-outputclass.conf` 存在 | | prime-select 工具 | 不存在 | | nvidia-prime 包 | 未安装 | | boot_vga | AMD=1(主显),NVIDIA=0(副显) | | 当前渲染器 | AMD Radeon(核显主渲染) | ### 1.3 方案设计 #### 方案 A:全局开关(推荐先实现) **原理**:通过 `~/.config/environment.d/` 设置全局环境变量,重新登录后生效。 **实现**: - 插件弹窗中添加 PRIME 开关按钮 - 开启时写入 `~/.config/environment.d/nvidia-prime.conf`: ```ini __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia ``` - 关闭时删除该文件 - 不需要 root 权限 - 需要重新登录生效,UI 上提示用户 **优点**:不需要 root,实现简单,全局生效 **缺点**:需要重新登录 #### 方案 B:按应用启动 **原理**:提供快捷方式,设置环境变量后启动指定应用。 **实现**: - 任务栏右键菜单添加"用独显启动"选项 - 弹出应用选择器或输入命令 - 执行 `__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia ` - 即时生效,不影响全局 **优点**:即时生效,不影响全局 **缺点**:需要手动选择应用 #### 方案 C:两者结合(最终目标) 同时提供全局开关和按应用启动,用户可选择使用方式。 ### 1.4 实现计划 1. C++ 后端新增 `primeEnabled` 属性和 `togglePrime(bool)` 方法 2. C++ 后端读写 `~/.config/environment.d/nvidia-prime.conf` 3. QML 弹窗中添加 PRIME 开关控件 4. 开关状态变更后提示"需要重新登录生效" 5. (后续)右键菜单添加"用独显启动应用" ### 1.5 数据接口 ```cpp // 新增属性 Q_PROPERTY(bool primeEnabled READ primeEnabled NOTIFY primeEnabledChanged) // 新增方法 Q_INVOKABLE void togglePrime(bool enabled); // primeEnabled 获取逻辑 // 1. 检查 ~/.config/environment.d/nvidia-prime.conf 是否存在 // 2. 检查文件内容是否包含 __NV_PRIME_RENDER_OFFLOAD=1 ``` --- ## 二、驱动安装 ### 2.1 原理 驱动安装需要 root 权限执行 `apt install/remove`,核心问题是如何从任务栏插件(普通用户)安全地获取特权。 ### 2.2 系统现状 | 检测项 | 当前状态 | |--------|---------| | deepin-graphics-driver-manager | 未安装 | | D-Bus 驱动管理服务 | 不存在 | | pkexec | 可用 (`/usr/bin/pkexec`) | | polkit apt 策略 | `com.deepin.pkexec.aptInstallDepend.policy` 存在 | | nvidia-driver 包 | 已安装,版本 580.119.02 | ### 2.3 方案对比 | 方案 | 实现 | 优点 | 缺点 | |------|------|------|------| | **A. pkexec + apt(推荐)** | pkexec 弹授权框执行 apt | 简单直接,无需额外服务 | 每次操作需授权 | | **B. D-Bus 系统服务** | 创建 systemd 服务暴露接口 | 规范,可记住授权 | 工作量大,需额外包 | | **C. 复用 deepin-graphics-driver-manager** | 安装该包调用其接口 | 功能最全 | V25 兼容性未知 | ### 2.4 推荐方案:pkexec + apt #### 流程 ``` 用户点击"安装驱动" ↓ 插件检测可安装的驱动包列表 (apt list nvidia-driver*) ↓ 用户选择驱动版本 ↓ pkexec apt install -y nvidia-driver-xxx ↓ polkit 弹出密码授权框 ↓ 用户输入密码 ↓ apt 执行安装 ↓ 插件显示安装结果 ``` #### 实现细节 1. **驱动状态检测**: - 已安装:读取 `/sys/module/nvidia/version` 或 `/proc/driver/nvidia/version` - 可用版本:`apt list nvidia-driver* 2>/dev/null` - 加载状态:`lsmod | grep nvidia` 2. **安装/卸载**: - 创建 helper 脚本 `/usr/share/dde-shell/org.deepin.ds.graphics-driver/scripts/install-driver.sh` - 脚本接收包名参数,执行 apt install/remove - 插件通过 `pkexec` 调用该脚本 - 利用系统已有的 `com.deepin.pkexec.aptInstallDepend.policy` polkit 策略 3. **进度显示**: - pkexec 执行期间显示"安装中..."状态 - QProcess 监听 pkexec 进程退出码判断成功/失败 ### 2.5 数据接口 ```cpp // 新增属性 Q_PROPERTY(QStringList availableDrivers READ availableDrivers NOTIFY availableDriversChanged) Q_PROPERTY(bool driverInstalling READ driverInstalling NOTIFY driverInstallingChanged) // 新增方法 Q_INVOKABLE void installDriver(const QString &packageName); Q_INVOKABLE void uninstallDriver(const QString &packageName); // availableDrivers 获取逻辑 // 执行 apt list nvidia-driver*,解析输出 ``` ### 2.6 安全考虑 - helper 脚本放置在 `/usr/share/` 下,需要 root 权限修改 - 脚本中硬编码允许的包名前缀(如 `nvidia-driver`),防止注入 - 不直接传递用户输入给 apt,只传递预定义的包名 - polkit 策略限制只有本插件可以调用 --- ## 三、实现优先级 | 优先级 | 功能 | 难度 | 预计工作量 | |--------|------|------|-----------| | P0 | PRIME 全局开关(方案A) | 低 | 0.5 天 | | P1 | 驱动安装 pkexec 方案 | 中 | 1-2 天 | | P2 | 按应用启动独显(方案B) | 中 | 1 天 | | P3 | D-Bus 系统服务(可选) | 高 | 2-3 天 | ## 四、参考资源 - [NVIDIA PRIME Render Offload 官方文档](https://download.nvidia.com/XFree86/Linux-x86_64/580.119.02/README/primerenderoffload.html) - [deepin-graphics-driver-manager 源码](http://git.jokul.space/Jokul/deepin-graphics-driver-manager) - [Polkit 设计文档](https://www.freedesktop.org/software/polkit/docs/latest/) - [systemd environment.d 说明](https://systemd.io/ENVIRONMENT/)