Add plan to migrate to DRM
build-prod.yml / update-and-build (push) Canceled after 0s

This commit is contained in:
NeilClack
2026-08-17 10:44:36 -05:00
parent 240be2540f
commit 06c2a7cd0a
+159
View File
@@ -0,0 +1,159 @@
# DRM/KMS Direct Mode — Deferred to Post-Launch
**Status:** Deferred (too much risk before launch)
**Created:** 2026-08-17
---
## Goal
Remove Cage (Wayland compositor) from -dev kiosk variants and run RadiantWave
directly on DRM/KMS via SDL3's built-in `SDL_VIDEODRIVER=drm` backend. This
simplifies the stack, removes compositor overhead, and is better suited for
embedded/hardware kiosks.
**Decision:** Deferring until after the current launch. Cage works, and the
transition touches every variant's boot pipeline.
---
## What Cage Currently Provides
| Feature | How Cage Does It | DRM/KMS Replacement |
|---------|------------------|---------------------|
| Display mode setting | Opens `/dev/dri/card*` via libseat, selects connector/CRTC/mode | SDL3 DRM backend opens DRM devices directly |
| Fullscreen surface | Creates Wayland surface, manages lifecycle | SDL3 creates DRM framebuffer surface |
| Page flipping / VSync | Handles `drmHandlePageFlip()` | SDL3 DRM backend handles page flip |
| Input devices | Opens `/dev/input/*` via libseat, generates Wayland events | SDL3 DRM backend reads evdev directly |
| Keyboard mapping | XKB keymap loading, key repeat | SDL3 handles keymap translation |
| Seat management | Connects to seatd via libseat | Not needed — group permissions (`video`, `input`) suffice |
---
## What Stays Safe Without Cage
| Concern | Why It's Safe |
|---------|---------------|
| **Audio** | PipeWire/ALSA works independently of the compositor. App uses SDL3_mixer -> ALSA. Audio init service still runs before launch. |
| **WiFi** | NetworkManager uses system bus (`sd_bus_open_system()` in `network_manager.cpp`). No session bus needed. `networkmanager` group handles D-Bus access. |
| **Keyboard/input** | SDL3's DRM backend reads `/dev/input/*` evdev directly. `input` group grants access. |
| **DRM/display** | SDL3's DRM backend opens `/dev/dri/card*` directly. `video` group grants access. |
| **Plymouth** | `sudo -n plymouth quit --wait` still works — Plymouth runs as root on DRM/KMS. |
| **Auto-login** | getty autologin still works on tty1. |
| **Health check** | `pgrep -f '.radiantwave-unwrapped'` still works — no wrapper changes. |
| **Backup service** | Runs as kiosk user, rsyncs `~/.local/radiantwave`. No compositor dependency. |
---
## Implementation Plan — 4 Phases
All changes are in **kioskconfig only**. The radiantwave app needs no code
changes — SDL3 handles DRM/KMS internally when `SDL_VIDEODRIVER=drm` is set.
The NixOS system already provides Mesa/EGL/GBM via `hardware.graphics.enable = true`.
Only **-dev** variants are modified. Production configs stay on Cage.
### New module: `kiosk-drm.nix`
A NixOS module that overrides the Wayland/cage setup:
- `environment.systemPackages = mkForce [...]` — same list as `configuration.nix`
but **without `pkgs.cage`**
- `environment.loginShellInit = mkForce ''...` — same script but:
- Sets `SDL_VIDEODRIVER=drm` instead of `wayland`
- Removes `WLR_RENDERER`, `WLR_NO_HARDWARE_CURSORS`, `QT_QPA_PLATFORM`,
`XDG_SESSION_TYPE`, `GODEBUG`
- Launches `exec /run/current-system/sw/bin/radiantwave` directly
(no `dbus-run-session cage --`)
- Keeps: network wait, audio init, Plymouth quit
- `services.seatd.enable = mkForce false` — nothing uses libseat anymore
---
### Phase 1: `radiantwavekiosk-dev` (Intel NUC)
**Files:**
- Create `kiosk-drm.nix`
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
`radiantwavekiosk-dev`
- `dev-iso.nix` already targets `radiantwavekiosk-dev` — no change needed
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-dev.config.system.build.toplevel`
---
### Phase 2: `radiantwavekiosk-commercial-dev` (commercial HW)
**Files:**
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
`radiantwavekiosk-commercial-dev`
- Create `commercial-dev-iso.nix` (same pattern as `dev-iso.nix`, targeting
`radiantwavekiosk-commercial-dev`)
- Add `commercial-dev-iso` config to `flake.nix`
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-commercial-dev.config.system.build.toplevel`
---
### Phase 3: `radiantwavekiosk-android-dev` (rotated display)
**Files:**
- Create `radiantwavekiosk-android-dev` in `flake.nix` (currently only
production `radiantwavekiosk-android` exists)
- Create `android-kiosk-drm.nix` — DRM/KMS mode + display rotation
**Challenge:** `rotated_display.nix` uses `wlr-randr` (Wayland tool) for
90-degree rotation. Without Cage/Wayland, this won't work. Alternatives:
- Option A: Use `modetest` from `libdrm` to set DRM rotation property
- Option B: Handle rotation in the app (query display orientation, render rotated)
- Option C: Kernel DRM rotation via modprobe params or udev rule
This is the hardest phase — needs investigation.
**Verify:** `nix build .#nixosConfigurations.radiantwavekiosk-android-dev.config.system.build.toplevel`
---
### Phase 4: `radiantwavekiosk-rpi-dev` (RPi 5)
**Files:**
- Modify `flake.nix`: add `./kiosk-drm.nix` to `extraModules` for
`radiantwavekiosk-rpi-dev`
- Modify `build-rpi.sh`: update to build `radiantwavekiosk-rpi-dev` instead of
`radiantwavekiosk-rpi`
RPi 5 uses VC4/V3D GPU driver — `hardware.graphics.enable = true` +
`nixos-raspberrypi.nixosModules.raspberry-pi-5.display-vc4` already handles this.
**Verify:** `./build-rpi.sh` (builds SD card image)
---
## Risks and Unknowns
1. **SDL3 DRM backend maturity** — Less commonly used than the Wayland backend.
Needs testing on NUC (Intel i915) and RPi 5 (VC4/V3D) hardware.
2. **Android rotation** — `wlr-randr` won't work without Wayland. Needs an
alternative rotation strategy.
3. **Input device permissions** — SDL3's DRM backend reads `/dev/input/*`
directly. Need to verify `input` group is sufficient and udev rules don't
block access.
4. **Multi-GPU/multi-output** — DRM/KMS needs to select the right connector.
SDL3 handles this, but edge cases exist (e.g., multiple monitors).
5. **Plymouth -> app handoff** — Plymouth runs on DRM/KMS too. The handoff
should work, but timing might differ without a Wayland compositor in between.
---
## radiantwave Repo — No Changes Needed
The app doesn't directly use DRM/KMS APIs. SDL3 handles the DRM backend
internally when `SDL_VIDEODRIVER=drm` is set. The Nix package doesn't need
changes — SDL3 dynamically loads DRM libraries at runtime.
The only change is the environment variable in the kiosk startup script
(`SDL_VIDEODRIVER=drm` vs `wayland`), which lives in kioskconfig.