wlroots does DRM output layers only through libliftoff
scope: generic · severity: finding · confidence: proven · subsystem: display
The question — my compositor wants to put a client’s buffer on a hardware
overlay plane. nm says the wlr_output_layer_* symbols are right there in the
binary, /sys/kernel/debug/dri/0/state says seven planes are idle, the backend
is atomic, and every layer still comes back accepted = false. Why?
The answer — because the symbols are not the implementation. wlr_output_layer
and wlr_output_state_set_layers() live in generic types/output/, so they are
in every wlroots build. The DRM backend implements them only in
backend/drm/libliftoff.c. backend/drm/atomic.c contains no reference to
layers at all, and drm.c has:
static bool drm_connector_set_pending_layer_fbs(...) { ... if (!crtc->liftoff) { return true; // libliftoff is disabled }which returns success having done nothing, so every layer stays unaccepted and the compositor silently composites everything on the GPU forever.
Two things are needed, and neither is the default:
- build with libliftoff —
meson.optionsdeclares ittype: 'feature', value: 'auto', so a build host without the library disables it silently. Pass it explicitly (-Dwlroots:libliftoff=enabledfor an embedded wlroots) so a missing library fails the build instead of shipping an inert one. - select the interface at runtime with
WLR_DRM_FORCE_LIBLIFTOFF=1. Without itdrm_backend_init()picksatomic_iface, which has no layers.env_parse_bool()reads"0"as false, so that value is the off switch.
What this rules out — “the symbols are present, so the feature is present”.
Also “the compositor must be computing the wrong geometry”, “the DPU must be
refusing the format”, and “the kernel is rejecting the atomic commit”: with the
atomic interface the kernel is never asked about a layer in the first place, and
drm.debug=0x10 shows the commit carrying [NOFB] on every overlay plane with
no failure line anywhere.
How it was established — read in wlroots 0.20.x, then confirmed on a
Pixel 2 XL (msm8998, mainline 7.2). Enabling the option put
depend = so:libliftoff.so.0 in the phoc apk, which is the cheap check that the
auto feature actually resolved; forcing the interface then modeset cleanly at
1440x2880 and put a client surface on plane-7. What would overturn it: a
wlroots release that teaches atomic.c to program overlay planes directly, at
which point the forced interface becomes unnecessary rather than wrong.
