Pick a renderer from the GPU and fall back to software rendering
This commit is contained in:
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
# blob:summary=Detect whether a DRM device with an accelerated driver is present.
|
||||
|
||||
drm_path="${BLOB_DRM_PATH:-/sys/class/drm}"
|
||||
|
||||
accelerated_drivers=(
|
||||
amdgpu
|
||||
i915
|
||||
nouveau
|
||||
nvidia
|
||||
nvidia-drm
|
||||
radeon
|
||||
xe
|
||||
)
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for card in "$drm_path"/card[0-9]*; do
|
||||
[[ -L $card/device/driver ]] || continue
|
||||
driver=$(basename "$(readlink -f "$card/device/driver")")
|
||||
|
||||
for accelerated in "${accelerated_drivers[@]}"; do
|
||||
[[ $driver == "$accelerated" ]] && exit 0
|
||||
done
|
||||
done
|
||||
|
||||
exit 1
|
||||
@@ -37,6 +37,7 @@ hl.env("PATH", table.concat(kept, ":"))
|
||||
|
||||
-- Hardware-specific environment.
|
||||
require("default.hypr.nvidia")
|
||||
require("default.hypr.renderer")
|
||||
|
||||
hl.config({
|
||||
xwayland = {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
local paths = require("default.hypr.paths")
|
||||
|
||||
local accelerated = paths.blob_path .. "/bin/blob-hw-gpu-accelerated"
|
||||
|
||||
if not o.shell_succeeds(o.shell_quote(accelerated)) then
|
||||
hl.env("LIBGL_ALWAYS_SOFTWARE", "1")
|
||||
hl.env("WLR_NO_HARDWARE_CURSORS", "1")
|
||||
|
||||
hl.config({
|
||||
cursor = {
|
||||
no_hardware_cursors = true,
|
||||
},
|
||||
})
|
||||
end
|
||||
@@ -1,6 +1,31 @@
|
||||
-- Hyprland config for the SDDM Wayland greeter. SDDM starts the greeter itself
|
||||
-- once the compositor is up, so nothing here launches anything.
|
||||
-- The greeter runs as SDDM's own user, with no BLOB_PATH and no read access to
|
||||
-- the checkout, so it calls the copy install.sh puts in /usr/local/bin rather
|
||||
-- than loading the Lua modules the session uses. A detector that is not there
|
||||
-- yet reads as no acceleration, which is the fallback that always draws.
|
||||
local function gpu_is_accelerated()
|
||||
local pipe = io.popen("/usr/local/bin/blob-hw-gpu-accelerated >/dev/null 2>&1 && echo OK")
|
||||
if not pipe then
|
||||
return false
|
||||
end
|
||||
|
||||
local output = pipe:read("*a") or ""
|
||||
pipe:close()
|
||||
|
||||
return output:match("OK") ~= nil
|
||||
end
|
||||
|
||||
if not gpu_is_accelerated() then
|
||||
hl.env("LIBGL_ALWAYS_SOFTWARE", "1")
|
||||
hl.env("WLR_NO_HARDWARE_CURSORS", "1")
|
||||
end
|
||||
|
||||
hl.config({
|
||||
cursor = {
|
||||
no_hardware_cursors = true,
|
||||
},
|
||||
|
||||
misc = {
|
||||
disable_hyprland_logo = true,
|
||||
disable_splash_rendering = true,
|
||||
|
||||
@@ -206,6 +206,7 @@ of the `blob` listing.
|
||||
| `blob-hw-display` | Print the most likely display backlight device. | - |
|
||||
| `blob-hw-external` | Returns true when an external monitor is physically connected. | - |
|
||||
| `blob-hw-fingerprint` | Returns true when a fingerprint reader is present (hidden) | - |
|
||||
| `blob-hw-gpu-accelerated` | Detect whether a DRM device with an accelerated driver is present. | - |
|
||||
| `blob-hw-hybrid-gpu` | Detect whether the system has an active hybrid GPU configuration | - |
|
||||
| `blob-hw-laptop` | Returns true when running on a laptop (has a lid or laptop chassis). | - |
|
||||
| `blob-hw-laptop-closed` | Returns true when the laptop lid is closed (hidden) | - |
|
||||
|
||||
+51
-1
@@ -86,10 +86,14 @@ with `--check`.
|
||||
| `/usr/local/share/wayland-sessions/blob.desktop` | the session SDDM offers |
|
||||
| `/etc/sddm.conf.d/zz-blob.conf` | Wayland greeter, run on Hyprland, stock theme, remember the last session |
|
||||
| `/etc/sddm/hyprland-greeter.lua` | the greeter's own tiny Hyprland config |
|
||||
| `/usr/local/bin/blob-hw-gpu-accelerated` | the renderer check that config runs, where SDDM's user can read it |
|
||||
|
||||
The greeter config matters more than it looks: SDDM's stock Wayland greeter
|
||||
runs on `weston`, which Blob does not install, so a default SDDM would fail
|
||||
to draw anything. That greeter config has to be Lua: Hyprland dropped the old
|
||||
to draw anything. The installer checks that the `CompositorCommand` named in
|
||||
`zz-blob.conf` is actually installed and warns when it is not, because SDDM
|
||||
with a compositor command it cannot run starts, fails, and leaves the machine
|
||||
sitting at a text console with no explanation. That greeter config has to be Lua: Hyprland dropped the old
|
||||
hyprlang format, and a config it cannot parse leaves the greeter with no
|
||||
compositor and the screen black. `sddm.service` is enabled and the default
|
||||
systemd target is set to `graphical.target`, which an Arch install without a
|
||||
@@ -131,6 +135,52 @@ with `--check`.
|
||||
| `--autologin` | skip the SDDM prompt for this user |
|
||||
| `--no-launch` | leave the login screen for the next reboot |
|
||||
|
||||
## Choosing a renderer
|
||||
|
||||
Hyprland renders through Mesa, and on an adapter Mesa has no driver for it exits
|
||||
with `failed to create dri2 screen` instead of drawing. The greeter is Hyprland
|
||||
too, so that is a black screen at boot and a second one after login, which is
|
||||
how a machine with no real GPU behind its display arrives.
|
||||
|
||||
`blob-hw-gpu-accelerated` decides which way to go. It reads the kernel driver of
|
||||
each `/sys/class/drm/card*` from sysfs, not from `lspci`, which reads PCI config
|
||||
space and resumes runtime-suspended GPUs. A card driven by `amdgpu`, `i915`,
|
||||
`nouveau`, `nvidia`, `nvidia-drm`, `radeon` or `xe` is a real integrated or
|
||||
dedicated GPU and hardware rendering is left alone. Everything else - `vmwgfx`,
|
||||
`vboxvideo`, `qxl`, `bochs-drm`, `cirrus`, `simpledrm`, `vkms`, `virtio_gpu` -
|
||||
is virtual or framebuffer-only, and two settings are applied:
|
||||
|
||||
| Setting | Effect |
|
||||
| --- | --- |
|
||||
| `LIBGL_ALWAYS_SOFTWARE=1` | Mesa uses llvmpipe, which renders on the CPU |
|
||||
| `WLR_NO_HARDWARE_CURSORS=1`, `cursor:no_hardware_cursors` | the cursor is drawn by the compositor, since there is no plane to put it on |
|
||||
|
||||
llvmpipe is slow and it draws. A machine with a real GPU never touches it.
|
||||
|
||||
Two places read the detector, because they run as different users:
|
||||
|
||||
| Where | How |
|
||||
| --- | --- |
|
||||
| the session | `default/hypr/renderer.lua`, required from `envs.lua` beside `nvidia.lua`, through `$BLOB_PATH/bin` |
|
||||
| the greeter | `default/sddm/hyprland-greeter.lua`, through `/usr/local/bin/blob-hw-gpu-accelerated` |
|
||||
|
||||
The greeter runs as SDDM's own user, with no `BLOB_PATH` and no read access to
|
||||
your home directory, so `install.sh` copies the detector to `/usr/local/bin`.
|
||||
A detector that is not there yet reads as no acceleration, which is the fallback
|
||||
that always draws.
|
||||
|
||||
To add a driver to the accelerated list, edit `accelerated_drivers` in
|
||||
`bin/blob-hw-gpu-accelerated` and rerun `./install.sh` so the greeter's copy
|
||||
follows. `virtio_gpu` is deliberately not on it: QEMU only accelerates it when
|
||||
the host enables virgl, and Mesa fails the same way when it does not.
|
||||
|
||||
To see the difference by hand, from a console:
|
||||
|
||||
```bash
|
||||
Hyprland # fails with the dri2 error
|
||||
LIBGL_ALWAYS_SOFTWARE=1 Hyprland # starts
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
`./uninstall.sh` removes the config, the user units, the `/etc` drop-ins, the
|
||||
|
||||
@@ -81,6 +81,7 @@ install_login_config
|
||||
install_session_entry
|
||||
install_autologin
|
||||
enable_display_manager
|
||||
report_greeter_compositor
|
||||
report_login_conflicts
|
||||
report_desktop_essentials
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ greeter_compositor_config=/etc/sddm/hyprland-greeter.lua
|
||||
# ISO, or a previous desktop left behind.
|
||||
blob_greeter_conf="$greeter_config_dir/zz-blob.conf"
|
||||
blob_autologin_conf="$greeter_config_dir/zzz-blob-autologin.conf"
|
||||
greeter_gpu_detector=/usr/local/bin/blob-hw-gpu-accelerated
|
||||
|
||||
# SDDM's stock Wayland greeter runs on weston, which Blob does not install.
|
||||
# Point it at Hyprland with a greeter-only config instead. That config is Lua:
|
||||
@@ -18,6 +19,8 @@ install_login_config() {
|
||||
"$greeter_compositor_config" "sddm/hyprland-greeter.lua"
|
||||
install_root_file "$repo_dir/default/sddm/zz-blob.conf" \
|
||||
"$blob_greeter_conf" "sddm.conf.d/zz-blob.conf"
|
||||
install_root_file "$repo_dir/bin/blob-hw-gpu-accelerated" \
|
||||
"$greeter_gpu_detector" "blob-hw-gpu-accelerated" 0755
|
||||
}
|
||||
|
||||
install_session_entry() {
|
||||
@@ -54,6 +57,22 @@ setting_value() {
|
||||
sed -n "s/^[[:space:]]*$key[[:space:]]*=[[:space:]]*//p" "$file" | tail -1
|
||||
}
|
||||
|
||||
# SDDM runs CompositorCommand to get a Wayland greeter on screen. When that
|
||||
# binary is not installed SDDM fails with no greeter at all, which reads as a
|
||||
# machine that boots to a console for no reason, so name it here instead.
|
||||
report_greeter_compositor() {
|
||||
local command_line binary
|
||||
|
||||
command_line="$(setting_value "$repo_dir/default/sddm/zz-blob.conf" CompositorCommand)"
|
||||
binary="${command_line%% *}"
|
||||
|
||||
[[ -n $binary ]] || return 0
|
||||
command -v "$binary" &>/dev/null && return 0
|
||||
|
||||
say "WARN the greeter's compositor command '$binary' is not installed"
|
||||
say " SDDM cannot draw a greeter without it; it is set in $blob_greeter_conf"
|
||||
}
|
||||
|
||||
# zz-blob.conf blanks Theme and Autologin, so a leftover drop-in cannot point the
|
||||
# greeter at a theme that was uninstalled or autolog into a session that no
|
||||
# longer exists. Either one leaves SDDM on a black screen it never falls back
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
# Compositor and shell
|
||||
hyprland
|
||||
mesa
|
||||
quickshell
|
||||
uwsm
|
||||
sddm
|
||||
|
||||
@@ -8,6 +8,7 @@ session_entry="/usr/local/share/wayland-sessions/blob.desktop"
|
||||
|
||||
root_files=(
|
||||
/etc/profile.d/blob.sh
|
||||
/usr/local/bin/blob-hw-gpu-accelerated
|
||||
/etc/sddm.conf.d/zz-blob.conf
|
||||
/etc/sddm.conf.d/zzz-blob-autologin.conf
|
||||
/etc/sddm/hyprland-greeter.conf
|
||||
|
||||
Reference in New Issue
Block a user