The waylandsink 5 fps cap was two upstream policies colliding -- wlroots hides LINEAR from v3 clients, GStreamer refuses INVALID
scope: device:google-taimen · severity: finding · confidence: proven · subsystem: display
The question — waylandsink delivers 5 fps (35 with sync=false) where GL
sinks do 60 (waylandsink-delivers-5fps-where-other-sinks-do-60). The
handoff’s fork: if wl_buffer.release lags, it is compositor-side; if prompt,
it is inside waylandsink. Which?
The answer — Neither. Releases return in ~3 ms and the sink is idle
~225 ms between commits; the frames never reach the wayland path at speed
because playsink silently inserted a software videoconvert: one spinning
thread (vqueue:src, R in 80/80 wchan samples while every other thread
slept) CPU-converting 1080p at ~4.4 fps. The convert exists because
v4l2h264dec ! waylandsink cannot negotiate dmabuf at all:
- mesa/freedreno on a5xx reports exactly ONE explicit modifier for all 64 formats: LINEAR. wlroots therefore holds {LINEAR, INVALID} per format.
- wlroots’ v3 modifier events collapse exactly that set to INVALID-only — an XWayland workaround (xorg/xserver#1166, still open) applied to every v3 client.
- GStreamer >= 1.24 waylandsink binds v3 (no feedback support even in 1.28.5, hardcoded in gstwldisplay.c) and DROPS INVALID by policy (“we prefer disabling zero-copy over risking a bad output”).
- ∅ dmabuf formats →
drm-format=(int){ }(visible with GST_DEBUG=waylandsink:6) → CPU convert → 4-35 fps, and with sync=true basesink discards the late frames, which is the 5 fps.
The GL sinks never consult the wayland format list — they import dmabufs through EGL, which happily takes implicit modifiers. That is why they were always fine and why the corruption GStreamer fears does not occur here.
The fix — pmaports temp/phoc patch 0003 (pkgrel 51) drops the
workaround branch in the bundled wlroots: the modifier set on this GBM is
explicit-LINEAR-capable, so xserver#1166 (GBM without modifier support) does
not apply. Verified end to end in the unlocked session: every format now
sends 0x0 + INVALID, waylandsink’s display caps list all formats, and
playbin + waylandsink sync=true on the 1080p30 clip runs at 60 panel
vsyncs/s with 0 late-frame drops and vqueue:src asleep in futex_wait —
the converter is gone and the path is zero-copy. The session still flings at
p50 16.6 / p90 18.2 ms on the patched compositor.
Upstream-bound: wlroots should gate the workaround on a GBM that actually
lacks modifier support; GStreamer should bind dmabuf v4 and read the
feedback table.
What this rules out — instrumenting phoc’s buffer releases (prompt); QoS/clock tuning on the sink (symptom); “venus degraded over the day” (118 fps to fakesink at the same moment the sink did 4.4); adding queues or converters (playsink already had one — it IS the problem).
Instrument traps — measured rates for the same pipeline varied 4.4-35 fps with CPU frequency and logging overhead, all of it the speed of the hidden videoconvert, none of it the sink; a busy-spinning streaming thread shows wchan 0/R, so sample stat AND wchan together; the greeter’s compositor (phrog) never maps foreign toplevels, so a pipeline “plays” against it with the panel at 0 vsync/s — panel-on (bl_power=0) plus a vsync delta is the only honest confirmation, and the backlight must be checked, not assumed.
