phase0 closed — root cause isolated to mpv vo_dmabuf_wayland plane-semantics

Eight directed A/B tests on ohm ruled out every layer that doesn't
matter (libva, decoder content, color tags, kwin-fourier 0001 patch,
Mesa 26.0.6 vs 26.0.5, Wayland generally, kernel 6.19.10 vs 7.0,
KWin Vulkan vs OpenGL backend). WAYLAND_DEBUG=1 capture surfaced the
real bug at the protocol-message layer:

  add(fd 41, plane=0, offset=0,        stride=1920, mod=0,0)
  add(fd 42, plane=1, offset=2088960,  stride=1920, mod=0,0)

mpv mixes per-plane fds (V4L2 MPLANE export semantics) with
single-allocation offset for plane 1 (single-fd export semantics).
KWin reads UV from past-EOF on the UV-plane fd → all-zero NV12 →
dark green render (Y=U=V=0 in BT.601/709 ≈ RGB(0,70,0)).

Filed at marfrit/dmabuf-modifier-triage#1 with full diagnosis +
suggested fix path. Iter1 fix work is blocked on libva-multiplanar
iter9 (need clean libva path to verify which producer is at fault
or whether mpv VO is the sole bug). Working interim path is
mpv --hwdec=v4l2request --vo=gpu (correct picture, slow shader path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 14:30:00 +00:00
parent dfabeddf93
commit d13ad847a4
+56 -2
View File
@@ -2,7 +2,61 @@
**Locked 2026-05-08.** Iter1 phase 0 substrate. **Locked 2026-05-08.** Iter1 phase 0 substrate.
## Locked research question > **PHASE 0 CLOSED 2026-05-08** — root cause isolated within hours of opening, faster than expected. See "Phase 0 conclusion" below. The original deliverables list (modifier captures, A/B tests) is preserved as historical record; the elimination ladder went deeper than the planned items but landed at a clear answer.
## Phase 0 conclusion
**Root cause:** mpv's `vo_dmabuf_wayland.c` constructs the `zwp_linux_buffer_params_v1` protocol message with **internally inconsistent plane semantics** — different fds per plane (V4L2 MPLANE export semantics) combined with single-allocation offset for plane 1 (single-fd export semantics). KWin imports plane 1 from the wrong byte address, reads zeros for the UV chroma plane, and the all-zero NV12 buffer renders as dark green. Filed at [marfrit/dmabuf-modifier-triage#1](https://git.reauktion.de/marfrit/dmabuf-modifier-triage/issues/1).
**Trace (one buffer cycle, abbreviated):**
```
create_params #54
add(fd 41, plane=0, offset=0, stride=1920, modifier=0,0) ← Y plane
add(fd 42, plane=1, offset=2088960, stride=1920, modifier=0,0) ← UV plane
create_immed(wl_buffer#56, 1920, 1080, NV12, flags=0)
```
`1920×1088 = 2088960` is the size of the Y plane (height-aligned 1080→1088). Correct offset for "both planes in one allocation"; wrong when plane 1 is in its own fd.
**Color analysis** — why all-zero NV12 = dark green specifically: Y=0 + U=0 + V=0 in BT.601/709 → RGB ≈ (0, 70, 0), which is the dark green the user reported.
**Layers ruled out via directed A/B (in order):**
| Layer | Verdict | Test |
|---|---|---|
| libva | not the cause | `--hwdec=v4l2request` (libva-bypassed) also greens |
| Decoder content | correct | `--vo=gpu --hwdec=v4l2request` shows real picture |
| Color tagging / HDR PQ | not the cause | `--target-colorspace-hint=no` + explicit BT.709 SDR triple no effect |
| kwin-fourier 0001 (`watchDmaBuf` bypass) | exonerated | stock arch `kwin` also greens |
| Mesa 26.0.6 vs 26.0.5 | exonerated | downgrade to 26.0.5 still greens |
| Wayland / KWin generally | exonerated | `--vo=wlshm` shows correct picture |
| Kernel besser-7.0 vs pinetab2-6.19.10 | exonerated | boot.scr swap + reboot, both kernels green |
| KWin Vulkan vs OpenGL backend | exonerated | qdbus6 confirms KWin runs OpenGL + Mesa-panfrost (same path mpv's vo=gpu uses successfully) |
**Why the layer-strip works the way it does:**
- mpv's `vo=gpu` is fine because it imports the dmabuf via libva's `vaExportSurfaceHandle` / ffmpeg's `av_hwframe_transfer_data` directly into mpv's own EGL context — those APIs return *correct* per-plane structure.
- mpv's `vo=dmabuf-wayland` is the unique broken path because it constructs the wl_dmabuf protocol message itself, mishandling the producer's plane semantics.
- mpv's `vo=wlshm` is fine because it goes through CPU memcpy, bypassing the dmabuf protocol entirely.
**Deferred verifier (gates iter1's actual fix):**
Re-run the WAYLAND_DEBUG capture with `--hwdec=vaapi` (libva path) once `libva-v4l2-request-fourier#1` is fixed and the cap_pool/REQBUFS cascade stops blocking libva playback. If both paths produce the same wrong `.add()` pattern → bug is purely in mpv VO. If only one does → that path's producer (libva or ffmpeg V4L2 hwaccel respectively) is the bug.
This means iter1's fix work cannot start until libva-multiplanar iter9 lands. dmabuf-modifier-triage iter1 is **blocked-on**: libva-multiplanar/iter9.
**Working ohm HW-decode workflow until fix lands:**
```bash
mpv --hwdec=v4l2request --vo=gpu fourier-test/bbb_1080p30_h264.mp4
```
Correct picture, slow due to GPU shader path on Mali-G52. Documented as the campaign's interim recommended path.
---
## Locked research question (original — superseded by Phase 0 conclusion above)
> Identify the layer responsible for the dmabuf-wayland green on ohm — > Identify the layer responsible for the dmabuf-wayland green on ohm —
> libva (`vaExportSurfaceHandle` modifier reporting), ffmpeg V4L2 request > libva (`vaExportSurfaceHandle` modifier reporting), ffmpeg V4L2 request
@@ -11,7 +65,7 @@
> hantro driver (buffer attribute reporting). File upstream where > hantro driver (buffer attribute reporting). File upstream where
> appropriate; fix what's locally in scope. > appropriate; fix what's locally in scope.
Bug tracker: [marfrit/libva-multiplanar#1](https://git.reauktion.de/marfrit/libva-multiplanar/issues/1). Bug tracker: [marfrit/libva-multiplanar#1](https://git.reauktion.de/marfrit/libva-multiplanar/issues/1) (user-visible symptom). Root-cause issue: [marfrit/dmabuf-modifier-triage#1](https://git.reauktion.de/marfrit/dmabuf-modifier-triage/issues/1) (mpv vo_dmabuf_wayland plane-semantics).
## Reproduction (verbatim from issue tracker) ## Reproduction (verbatim from issue tracker)