diff --git a/README.md b/README.md index 68c08c7..a003637 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,100 @@ -# 显卡切换任务栏插件 +# GPU 显卡驱动管理任务栏插件 -Deepin显卡驱动管理任务栏插件,集成到DDE Shell任务栏中,提供显卡设备检测、驱动安装和切换功能。 +Deepin V25 DDE Shell 任务栏插件,实时检测 GPU 设备、显示驱动信息和温度/使用率监控。 ## 功能特性 -- 自动检测系统显卡设备 -- 显示当前安装的驱动版本 -- 列出可用的驱动版本 -- 一键切换显卡驱动 -- 实时显示安装进度 -- 安装完成后提示重启 +- **GPU 设备检测** - 通过 `lspci` + `sysfs` 检测所有显卡(NVIDIA/AMD/Intel) +- **驱动信息显示** - 驱动模块名 + 版本号(NVIDIA 用 nvidia-smi/proc,AMD 用内核版本) +- **实时温度监控** - NVIDIA 用 `nvidia-smi`,AMD 用 `hwmon`,2 秒自动刷新 +- **GPU 使用率** - 进度条显示,NVIDIA 用 `nvidia-smi`,AMD 用 `gpu_busy_percent` +- **显存使用** - 已用/总量 (MB),带使用率百分比 +- **主副显标识** - 通过 `boot_vga` 区分主显卡(绿色"主显"标签) +- **GPU 切换模式检测** - 自动识别 PRIME / Bumblebee / Solo / Hybrid 模式 +- **国际化** - 支持简体中文、繁体中文、英文 + +## 截图 + +``` +┌─────────────────────────────────────┐ +│ GPU 显卡驱动管理 │ +│─────────────────────────────────────│ +│ 当前驱动: nvidia, amdgpu [PRIME] │ +│─────────────────────────────────────│ +│ ┌─────────────────────────────────┐ │ +│ │ NV NVIDIA GeForce RTX 3060 主显│ │ +│ │ nvidia 580.119.02 │ │ +│ │ 54°C 108/6144 MB │ │ +│ │ GPU ████░░░░░░ 36% │ │ +│ └─────────────────────────────────┘ │ +│ ┌─────────────────────────────────┐ │ +│ │ AMD AMD Radeon Vega │ │ +│ │ amdgpu Linux 6.18.36 │ │ +│ │ 90°C 471/512 MB │ │ +│ │ GPU ████████░░ 71% │ │ +│ └─────────────────────────────────┘ │ +│ [ 刷新 ] │ +└─────────────────────────────────────┘ +``` ## 依赖项 -- Qt6 >= 6.0 -- Dtk6 Core -- deepin-graphics-driver-manager(运行时依赖) +### 构建依赖 + +``` +cmake (>= 3.16) +g++ +qt6-base-dev +qt6-l10n-tools # lrelease 翻译编译 +libdde-shell-dev # DDE Shell 插件头文件 +libdtk6core-dev # DTK6 Core +``` + +### 运行时依赖 + +``` +dde-shell # 任务栏宿主 +lspci # GPU 检测(pciutils 包) +nvidia-smi # NVIDIA 监控(可选,nvidia-driver 包自带) +``` ## 构建 ```bash # 安装构建依赖 -sudo apt install -y cmake g++ qt6-base-dev qt6-tools-dev libdtk6core-dev +sudo apt install -y cmake g++ qt6-base-dev qt6-l10n-tools libdde-shell-dev libdtk6core-dev -# 构建项目 +# 构建 cmake -Bbuild cmake --build build ``` ## 安装 -```bash -# 安装插件到系统(deepin v25需关闭磐石) -sudo cmake --install build +### 方式一:一键脚本 -# 重启任务栏加载插件 +```bash +bash install.sh +``` + +### 方式二:手动安装 + +```bash +sudo cmake --install build systemctl --user restart dde-shell@DDE ``` -或者注销并重新登录。 +### 方式三:deb 包 + +```bash +bash build-deb.sh --install +``` ## 卸载 ```bash -# 卸载插件 -sudo rm -f /usr/lib/x86_64-linux-gnu/dde-shell/libdde-graphics-driver.so -sudo rm -rf /usr/lib/x86_64-linux-gnu/dde-shell/org.deepin.ds.graphics-driver - -# 重启任务栏 +sudo rm -f /usr/lib/x86_64-linux-gnu/dde-shell/org.deepin.ds.graphics-driver.so +sudo rm -rf /usr/share/dde-shell/org.deepin.ds.graphics-driver systemctl --user restart dde-shell@DDE ``` @@ -55,73 +102,90 @@ systemctl --user restart dde-shell@DDE ``` ├── package/ -│ ├── metadata.json # 插件元数据 -│ └── driverview.qml # QML界面 -├── graphicsdriverapplet.h # 主插件类头文件 -├── graphicsdriverapplet.cpp # 主插件类实现 -├── gpuindicator.h # GPU指示器类头文件 -├── gpuindicator.cpp # GPU指示器类实现 -├── debian/ # Debian打包文件 -├── CMakeLists.txt # 构建配置 -└── README.md # 项目说明 +│ ├── metadata.json # 插件元数据(ID、父插件、dockOrder) +│ └── driverview.qml # QML 界面(弹窗、卡片、tooltip) +├── translations/ +│ ├── *_zh_CN.ts # 简体中文翻译 +│ └── *_zh_TW.ts # 繁体中文翻译 +├── graphicsdriverapplet.h # C++ 插件类头文件 +├── graphicsdriverapplet.cpp # C++ 插件类实现 +├── debian/ # Debian 打包配置 +├── docs/ # 设计文档 +│ └── GPU_SWITCH_AND_DRIVER_INSTALL.md +├── CMakeLists.txt # 构建配置 +├── install.sh # 一键构建安装脚本 +├── build-deb.sh # 一键 deb 打包脚本 +└── README.md ``` ## 技术实现 -### 架构设计 +### 架构 ``` -┌─────────────────────────────────────────────────────────┐ -│ DDE Shell Taskbar │ -├─────────────────────────────────────────────────────────┤ -│ dde-graphics-driver-applet │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ GPU检测模块 │ │ 驱动管理 │ │ UI界面 │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -├─────────────────────────────────────────────────────────┤ -│ D-Bus Interface │ -│ com.deepin.daemon.GraphicsDriver │ -├─────────────────────────────────────────────────────────┤ -│ deepin-graphics-driver-manager │ -│ (现有的驱动管理服务,无需修改) │ -└─────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────┐ +│ DDE Shell Taskbar │ +├──────────────────────────────────────────────┤ +│ org.deepin.ds.graphics-driver │ +│ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ +│ │ GPU 检测 │ │ 实时监控 │ │ QML UI │ │ +│ │ lspci │ │ nvidia-smi│ │ 卡片 │ │ +│ │ sysfs │ │ hwmon │ │ tooltip │ │ +│ │ boot_vga │ │ drm │ │ 进度条 │ │ +│ └──────────┘ └──────────┘ └───────────┘ │ +└──────────────────────────────────────────────┘ ``` -### D-Bus接口 +### 数据采集方式 -插件通过D-Bus与deepin-graphics-driver-manager服务通信: +| 数据 | NVIDIA | AMD/Intel | +|------|--------|-----------| +| GPU 检测 | `lspci -mm` | `lspci -mm` | +| 驱动名 | `/sys/bus/pci/.../driver` symlink | 同左 | +| 驱动版本 | `/proc/driver/nvidia/version` | `/proc/sys/kernel/osrelease` | +| 温度 | `nvidia-smi` | `/sys/class/hwmon/hwmonN/temp1_input` | +| GPU 使用率 | `nvidia-smi` | `/sys/class/drm/cardN/device/gpu_busy_percent` | +| 显存 | `nvidia-smi` | `/sys/class/drm/cardN/device/mem_info_vram_*` | +| 主副显 | `/sys/bus/pci/.../boot_vga` | 同左 | +| 切换模式 | `nvidia-drm-outputclass.conf` 检测 | - | -- `GetDevice()` - 获取显卡设备信息 -- `GetCurrDriverName()` - 获取当前驱动名称 -- `GetNewDriverName()` - 获取推荐驱动名称 -- `PrepareInstall(name, language)` - 准备安装驱动 -- `TestInstall()` - 测试安装 -- `RealInstall()` - 实际安装 -- `CancelInstall()` - 取消安装 +### QML 属性接口 -### 信号 - -- `ReportProgress(ratio)` - 安装进度报告 -- `Cancel()` - 安装取消通知 +| 属性 | 类型 | 说明 | +|------|------|------| +| `applet.ready` | bool | GPU 检测完成 | +| `applet.deviceInfo` | QString | GPU 信息(每行一个) | +| `applet.currentDriver` | QString | 当前驱动列表 | +| `applet.gpuSummary` | QString | GPU 摘要 | +| `applet.gpuStats` | QStringList | 实时统计(temp\|gpu\|mem\|used\|total) | +| `applet.gpuMode` | QString | 切换模式(PRIME/Bumblebee/Solo/Hybrid) | +| `applet.gpuPrimary` | QStringList | 主副显标识(true/false) | +| `applet.refreshStats()` | void | 刷新实时统计 | +| `applet.refreshDeviceInfo()` | void | 重新检测 GPU | ## 使用说明 -1. 插件安装后会自动加载到任务栏 -2. 点击任务栏图标打开驱动管理界面 -3. 查看当前显卡设备和驱动信息 -4. 选择要切换的驱动版本 -5. 确认后开始安装过程 -6. 安装完成后选择重启系统 +1. 插件安装后自动加载到任务栏右侧 +2. **悬停**任务栏图标 - 显示 GPU 温度和使用率摘要 +3. **点击**图标 - 打开弹窗,查看详细 GPU 信息 +4. 弹窗内数据每 2 秒自动刷新 +5. **悬停**卡片 - 显示该 GPU 的驱动详情 tooltip +6. **点击刷新** - 重新检测 GPU 设备 + +## 开发计划 + +- [x] GPU 检测与驱动信息显示 +- [x] 温度/使用率/显存实时监控 +- [x] 主副显标识与 GPU 模式检测 +- [ ] PRIME 显卡切换(全局开关) +- [ ] 驱动安装(pkexec + apt) + +详见 [设计方案文档](docs/GPU_SWITCH_AND_DRIVER_INSTALL.md) ## 许可证 GPL-3.0-or-later -## 贡献 - -欢迎提交Issue和Pull Request。 - ## 相关项目 -- [dde-shell](https://github.com/linuxdeepin/dde-shell) - Deepin Shell插件系统 -- [deepin-graphics-driver-manager](https://github.com/linuxdeepin/deepin-graphics-driver-manager) - 显卡驱动管理器 +- [dde-shell](https://github.com/linuxdeepin/dde-shell) - Deepin Shell 插件系统 diff --git a/docs/GPU_SWITCH_AND_DRIVER_INSTALL.md b/docs/GPU_SWITCH_AND_DRIVER_INSTALL.md new file mode 100644 index 0000000..88ce633 --- /dev/null +++ b/docs/GPU_SWITCH_AND_DRIVER_INSTALL.md @@ -0,0 +1,194 @@ +# 显卡切换与驱动安装设计方案 + +## 背景 + +当前插件已实现 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/)