Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/03-boot-timing-splash-to-lock.md
Fimeg 8578e654d2 tasks: rewrite 03 (boot timing, source-verified faults), add 17 (keyboard/dictation)
03: today's deep boot investigation — the splash-to-splash flicker is a
DRM-master handoff race on a panel with supportsAsyncCommit:false (56
EBUSY commits); the Hyprland splash text is killed (disable_splash_rendering);
the corner box is an unidentified top-right toast (NOT the error overlay,
which stays); the recovery-mode wedge is documented. The EBUSY handoff
fix is the one real remaining timing bug.

17: stevia OSK + mic key + dictation shipped this session; layout/UX
polish and TTS wiring remain.
2026-07-21 11:37:16 -04:00

6.2 KiB

TASK 03 — Boot timing: fade splash → lock, no extra fixes

Status: open, deeply diagnosed 2026-07-21. Casey's framing: "the dang boot video is more than long enough if things were being timed right such that we didn't need all these extra fixes." The boot is visually ugly even on a successful boot — splash-to-splash flicker, a stray corner box, and the desktop assembling in the open before the lock covers it. Three of the faults are now root-caused to source; two fixes landed today.

Goal

One clean boot timeline: boot video (splash) plays, fades directly onto the lockscreen. No flicker, no error box, no gap that shows the desktop.

The desired timeline

kernel quiet ─ splash starts ─ DRM probes ─ splash animating
            ─ greetd initial session (souveraine-session)
            ─ souveraine-splash --wayland holder maps (act two)
            ─ sessiond acquires ext-session-lock, renders glance (TASK-02)
            ─ quickshell starts, BootBloom maps, holder crossfades to it
            ─ sessiond hands off the lock, shell lockscreen visible
splash → holder → bloom → lock, one continuous bloom ─ done

Root-caused faults (2026-07-21, source-verified)

The visible mess is THREE distinct problems, not one. Read the live boot log: journalctl -b -o short-monotonic and the Hyprland instance log at /run/user/1000/hypr/<sig>/hyprland.log (grep -v the GL_ extension dumps).

  1. The splash-to-splash flicker = a DRM-master handoff race on a panel that can't async-commit. aquamarine logs drm: drmProps.supportsAsyncCommit: false for DSI-1, then Clearing stale page-flip state for DSI-1 (pending for 598ms), then 56 consecutive atomic drm request: failed to commit: Device or resource busy. The C splash leaves a page-flip pending when it drops DRM master; Hyprland grabs the CRTC and, unable to queue behind the stale flip (no async commit on this panel), spins EBUSY until it retires. Source: hyprwm/aquamarine src/backend/drm/DRM.cpp (CDRMOutput::commitState retries as blocking modeset, sets commitTainted on fail — no per-frame backoff before that).

    • Escape hatch (blunt): env = AQ_NO_ATOMIC,1 forces legacy KMS ("heavily not recommended" upstream, but real). NOT applied.
    • Proper fix (UNDONE): tighten souveraine-session's handoff so the C splash fully drains its last page-flip and drops master BEFORE Hyprland modesets — no overlapping pending flip. This is the real TASK-03 work item.
  2. The "Hyprland :)" splash TEXT — FIXED 2026-07-21. disable_hyprland_logo (already set) only kills the mascot background; the handwritten splash text is a SEPARATE option, misc.disable_splash_rendering, which defaulted on. Now = true in overlays/hypr/hyprland.lua (Pixel3Arch 488139b), live-confirmed set:true.

  3. The small upper-right corner box during the flashes — NOT yet pinned to a specific trigger. It is one of Hyprland's top-right toasts (src/notification/NotificationOverlay.cpp) — startup callers in Compositor.cpp fire for: non-"Hyprland" XDG_CURRENT_DESKTOP, missing hyprland-dialog, failed render assets (m_failedAssetsNo > 0, red), no watchdog fd — and PluginSystem.cpp toasts a failed plugin load (hyprgrass is loaded via hyprpm reload at boot step 2). Most likely suspects here: failed-assets or a hyprgrass API-version toast. NEXT: catch it live (it is transient; a boot screen-record or reading hyprctl notifications/asset-fail count right after boot names it). This is NOT the CHyprError overlay (src/errorOverlay/) — Casey explicitly does NOT want that touched; leave error reporting intact.

Separately: the desktop-visible ~12s gap. Splash releases ~20.8s but sessiond doesn't confirm the shell's lock until ~33s. The bloom holder (souveraine-splash --wayland, added 2026-07-21, Pixel3Arch 20e72c5) is meant to cover this whole window; on Casey's eyes it still leaks Hyprland through. Verify the holder actually maps first and stays up until BootBloom pokes it — a gap here is a holder-timing bug, not a new surface.

Worse, separate: recovery-mode wedge

If hyprland.lua fails to load, Hyprland falls to recoverycfg.lua (autogenerated), whose boot exec chain never runs the real step 0-4 wiring AND which grabs the ext-session-lock itself, showing the built-in "Oopsie daisy… lockscreen app died" screen. Then sessiond/shell can never take the lock (lock denied/revoked — another locker owns the session) because Hyprland owns it and Wayland only lets the locking client unlock. Observed 2026-07-21 after a shell restart landed on a prior recovery instance. Recovery is: at the device, drop Hyprland's lock (the fallback screen prints the commands) or cold boot. Watch for it: hyprctl binds | grep -c dispatcher returns ~3 in recovery vs ~48 on the real config; ls /run/user/1000/hypr/<sig>/recoverycfg.lua present is a tell but not proof (Hyprland writes it as a fallback artifact even on good boots).

Context

  • Pixel3Arch/bootsplash/ — the C DRM splash (main.c) + the new --wayland holder (wayland.c) + splash-signal.c (pokes both the /run and $XDG_RUNTIME_DIR sockets). Builds native on the phone.
  • Pixel3Arch/overlays/greetd/souveraine-session — greetd initial session; pokes the DRM splash and waits for socket vanish before exec start-hyprland. This is where fault #1's handoff fix goes.
  • Pixel3Arch/overlays/hypr/hyprland.lua — boot step 0 launches the holder, step 3 restarts souveraine-shell.service.
  • SouveraineOS/docs/LOCK-DPMS-LESSONS.md §5 — lock arch, ~1.05s handoff gap, lockdead_screen_delay = 4000.
  • Panel fact: DSI-1, 1080x2160@60, supportsAsyncCommit:false, freedreno/FD630 — the async-commit limit is hardware, not config.

Acceptance

A cold boot shows: boot video → one continuous bloom → lockscreen. No splash-to-splash flicker (no EBUSY storm, or it's hidden). No Hyprland splash text (done). No stray corner toast. No desktop visible before the lock. One lock surface, ever.

Connects to

TASK-02 (the glance the bloom fades onto), TASK-10 (mkinitcpio initramfs text before the splash), TASK-11 (souveraine-secrets must not prompt at boot). The EBUSY handoff fix (#1) is the last load-bearing timing bug.