Repository navigation
plymouth: boot splash for KMS devices, with a ucode theme engine and a demo theme - #164
Merged
Merged
Conversation
The package builds xkeyboard-config-2.pc and a compatibility symlink to it, but installs neither into the staging directory, so anything asking pkg-config for xkeyboard-config fails to configure. plymouth does, for the xkb_base path. Install both names; the symlink alone leaves a dangling link. Signed-off-by: Daniel Golle <[email protected]>
Formality Check: FailedWe checked this pull request against the contribution guidelines. Here is what needs your attention: 🛑 CRITICAL ERRORS
Tip Do not close this pull request to make corrections. Instead, modify your existing commits (e.g. Something broken? Consider reporting an issue. |
dangowrt
force-pushed
the
plymouth-splash
branch
2 times, most recently
from
September 25, 2026 23:17
60446f8 to
bc3d758
Compare
Plymouth draws a boot splash straight onto a DRM device and holds the display until whatever follows it takes over, so nothing of the boot is visible between reset and the user interface. On a board with no framebuffer console that is the only way to put anything on screen early. Built without the framebuffer backend, without systemd and upstart integration, and without gtk, pango and freetype, so the runtime needs only libpng and libdrm. msgfmt is needed at build time, for the themes that are built and then not installed. Neither binary answers to --version, so the CI version probe is answered by test-version.sh instead. No theme is installed and none is named in the daemon configuration: a theme is a package of its own and selects itself when it is installed. Four patches are carried. Two are build fixes for musl, which has neither rpmatch() nor execinfo.h. The other two are bugs, both submitted upstream. The drm renderer drops master immediately after opening the device, so every connector probe runs as a client that is not drm master; the kernel declines it a forced probe and returns a cached status of "unknown", and the renderer gives up with "Could not initialize heads", which leaves the splash able to light only a display something else has already probed. The escape key tears the splash down for a text view, guarded only on a VT existing, so on a kernel with CONFIG_VT but no framebuffer console the dummy driver is bound, the text goes nowhere and the screen turns black. Signed-off-by: Daniel Golle <[email protected]>
Plymouth's own script plugin has its own little language and draws by compositing prepared images, which means a theme arrives as a few hundred PNGs. This plugin makes a theme one ucode program instead, with a plutovg canvas over plymouth's pixel buffer, so a theme is source and its artwork is SVG. A theme returns setup, frame, paint and event. frame advances state and declares what changed, paint draws one damaged rectangle, and nothing reaches the screen that the theme did not ask for, which keeps a busy scene at a couple of milliseconds a frame rather than repainting everything. Themes are written against the contract in files/README.md and can be measured offscreen, on any target, with the included plymouth-theme-bench, which reports the package version it was built from. The plugin connects to ubus and passes events through, along with the objects that already existed when it connected, so a theme can show what the system is actually doing rather than animating a guess. It starts the splash from a preinit hook, before the overlay is mounted, and keeps it up through sysupgrade. Signed-off-by: Daniel Golle <[email protected]>
A worked example of what the ucode splash plugin can do, and the default theme once it is installed: nothing here is meant to be the last word on how an OpenWrt boot should look. The scene is a network graph, laid out afresh on every boot, drawn from one ucode program and one SVG with no rendered frames anywhere. It has two phases because the splash does. Before ubusd exists there is nothing true to report, so the graph simply grows, a node every second or so, for however long preinit takes. Once the bus is up the rest of the graph completes at once, the row of pictograms is built from /etc/rc.d/S*, and the packets that move afterwards are driven by real ubus activity rather than a timer. A stage is shown only for a service that is actually enabled and has a pictogram, dark until the service's own ubus object appears, so a box without blockd never shows storage. sysntpd has no object and reports its sync through /etc/hotplug.d/ntp instead, which is the general way for a service with a hook but no object to light its stage. Shutdown, reboot and sysupgrade take the graph apart rather than building it. About 5 ms a frame at any resolution from 640x480 to 3840x2160 on a Rock 5B, against 33 ms at the default frame rate. Signed-off-by: Daniel Golle <[email protected]>
dangowrt
force-pushed
the
plymouth-splash
branch
from
September 25, 2026 23:44
bc3d758 to
2a1fe10
Compare
dangowrt
marked this pull request as ready for review
September 26, 2026 09:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A boot splash for boards that have a KMS device and no framebuffer console, in three parts: the plymouth daemon, a splash plugin that makes a theme a ucode program, and a demo theme that shows what the plugin can do.
plymouth
Built for DRM only: no framebuffer backend, no systemd or upstart integration, no gtk, pango or freetype, so the runtime needs libpng and libdrm and nothing else. The package installs no theme and names none in
plymouthd.conf; a theme is a package of its own and selects itself when it is installed.Four patches. Two are build fixes for musl, which has neither
rpmatch()norexecinfo.h. The other two are bugs found while getting this working on an rk3588 board, both submitted upstream:drmDropMaster()immediately after opening the device and only takes master back inactivate(), so every connector probe inquery_device()runs as a client that is not DRM master. The kernel declines a forced probe from such a client and returns the cached connection status, which on a connector nothing has probed yet isunknown. No output counts as connected, no controller is assigned, and the renderer gives up withCould not initialize heads. The splash could therefore only light a display that something else had already probed, which with fbdev emulation gone never happens.CONFIG_VTis enabled on targets with no framebuffer console at all, so the VT is real but the only console driver bound to it is the dummy one and the details view is written where nobody can read it. The screen simply goes black until escape is pressed again.plymouth-plugin-ucode
Plymouth's own script plugin has its own small language and composites prepared images, so a theme arrives as a few hundred PNGs. This plugin makes a theme one ucode program with a plutovg canvas over plymouth's pixel buffer: a theme is source, and its artwork is SVG.
A theme returns
setup,frame,paintandevent.frameadvances state and declares what changed,paintdraws one damaged rectangle, and nothing reaches the screen that the theme did not ask for, which is what keeps a busy scene at a couple of milliseconds a frame instead of repainting everything. The contract is documented infiles/README.md, andplymouth-theme-benchmeasures any theme offscreen on any target, so themes can be compared without a display.The plugin connects to ubus and passes events through, together with the objects that already existed when it connected, so a theme can show what the system is actually doing rather than animating a guess. It starts the splash from a preinit hook, before the overlay is mounted, and keeps it up through sysupgrade.
plymouth-theme-openwrt-demo
A worked example, and the default theme once installed. It is explicitly a demo: people with a better eye will do nicer things, and the point here is to show the mechanism end to end.
The scene is a network graph laid out afresh on every boot, drawn from one ucode program and one SVG with no rendered frames anywhere. It has two phases because the splash does. Before ubusd exists there is nothing true to report, so the graph just grows, a node every second or so, for however long preinit takes. Once the bus is up the rest of the graph completes at once, the row of pictograms is built from
/etc/rc.d/S*, and the packets that move afterwards are driven by real ubus activity rather than by a timer.A stage appears only for a service that is actually enabled and has a pictogram, drawn dark until that service's own ubus object shows up, so a box without blockd never shows a storage icon rather than showing one that stays dark all boot.
sysntpdregisters no object at all and reports its sync through/etc/hotplug.d/ntp, which is the general escape hatch for a service with a hook but no object. Shutdown, reboot and sysupgrade take the graph apart instead of building it.Roughly 5 ms a frame at every resolution from 640x480 to 3840x2160 on a Rock 5B, against a 33 ms budget at the default frame rate.
The xkeyboard-config commit
Not cosmetic and not optional: plymouth's
meson.builddoesdependency('xkeyboard-config'), which cannot resolve unless that package stages its pkg-config file. Without it plymouth does not configure. It is first in the series and kept separate because it is a different package; happy to split it into its own PR if preferred.Testing
Build tested for rockchip/armv8 (aarch64, musl) and run tested on a Radxa ROCK 5B driving an HDMI television, from power-on through the handover to the application that takes the display afterwards. The
Theme=line written by the demo theme'spostinstwas verified in a freshly built rootfs, not just at runtime.