Skip to content

fix(linux): recover the DMA-BUF plane size the producer leaves at zero - #319

Merged
EtienneLescot merged 2 commits into
mainfrom
fix/dmabuf-import-maxsize
Aug 8, 2026
Merged

fix(linux): recover the DMA-BUF plane size the producer leaves at zero#319
EtienneLescot merged 2 commits into
mainfrom
fix/dmabuf-import-maxsize

Conversation

@EtienneLescot

@EtienneLescotEtienneLescot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #299, whose import half turns out never to have run.

How this was found

#299 fixed the negotiation half — advertising SPA_FORMAT_VIDEO_modifier — and that half is well covered offline by enum_format_survives_a_dmabuf_only_producer. The import half had no coverage, so I tried to exercise it locally.

It cannot be reached by any compositor available here:

CompositorResult
mutter (GNOME)uses_dmabuf=0, dataType: MemFd — even after #299
sway 1.9 via xdg-desktop-portal-wlruses_dmabuf=0, dataType: MemFd

That is correct behaviour, not a bug: the helper publishes shm first and DMA-BUF second, and pw_stream treats the array as a preference list, so any producer able to do shm wins params[0]. It also means the DMA-BUF branch is unreachable outside the compositor of #287.

The bug

Forcing the dmabuf object (OPENSCREEN_PIPEWIRE_FORCE_DMABUF, added here) gets DMA-BUF negotiated — and the import fails on the first buffer:

[osc-dmabuf] negotiated 1280x720 uses_dmabuf=1 modifier=0x0
[osc-dmabuf] refused before mmap: fd=23 len=0 lseek_size=3686400

wlroots reports maxsize = 0. That is legitimate — the size of a dmabuf is a property of the exporting buffer, not of the SPA descriptor — but osc_map_dmabuf refused on it and returned NULL before calling mmap. The user then saw:

dmabuf mmap failed: this driver does not allow CPU mapping of the capture buffer

The driver was blamed for a refusal it was never asked for. That message is what a bug report from a niri user would have contained, pointing whoever picked it up at the GPU.

The fix, measured

3686400 is exactly 1280×720×4 — the size is right there on the fd. Seeking it and retrying:

[osc-dmabuf] maxsize=0, recovered 3686400 bytes via lseek
[osc-dmabuf] mmap fd=23 len=3686400 ok (all four buffers)

AMD Mendocino / amdgpu, sway 1.9, xdg-desktop-portal-wlr 0.7.1. So CPU mapping does work on this driver; the size was the whole obstacle.

Also in here

  • The resolved length is stored.dmabuf_maps[].len used to take the producer's 0, leaving every later bounds check and the munmap pointed at an empty mapping.
  • The failure reason is carried up rather than assumed, so "no fd", "size unknown" and "driver refused" stop reading as the same thing.
  • OPENSCREEN_PIPEWIRE_DEBUG traces the negotiated modifier and every mapping. Without it a capture reports identical success whichever path it took, which is why this went unnoticed.
  • OPENSCREEN_PIPEWIRE_FORCE_DMABUF drops the shm object. Test-only, and the only way to exercise any of this without niri — worth keeping for the same reason it was needed today.
  • A comment correction.fix(linux): negotiate DMA-BUF so capture works on niri and other wlroots compositors #299 states that every Smithay/wlroots compositor lacks a memfd path. sway 1.9 has one and uses it.

What this does not settle

56 crate tests pass.

🤖 Generated with Claude Code

The DMA-BUF import path #299 added has never run: mutter and sway both offer
shared memory, so params[0] wins and the memfd branch is taken. Forcing the
dmabuf object (new OPENSCREEN_PIPEWIRE_FORCE_DMABUF, see below) shows the
import fails on the very first buffer.
wlroots hands out planes with maxsize = 0 — legitimate, since the size of a
dmabuf belongs to the exporting buffer and not to the SPA descriptor.
osc_map_dmabuf refused on that and returned NULL *before calling mmap*, and
the failure was reported as "this driver does not allow CPU mapping of the
capture buffer". The GPU was blamed for a refusal it was never asked for.
Measured on AMD Mendocino / amdgpu, sway 1.9 via xdg-desktop-portal-wlr:
[osc-dmabuf] refused before mmap: fd=23 len=0 lseek_size=3686400
[osc-dmabuf] maxsize=0, recovered 3686400 bytes via lseek
[osc-dmabuf] mmap fd=23 len=3686400 ok
3686400 is exactly 1280x720x4. The size is recoverable by seeking the fd,
which is the documented way, and the mmap then succeeds.
Also here:
- The resolved length is stored in dmabuf_maps[].len. It used to store the
producer's 0, leaving every later bounds check and the munmap on an empty
mapping.
- The failure reason is carried up instead of assumed, so "no fd", "size
unknown" and "driver refused" no longer read as the same thing.
- OPENSCREEN_PIPEWIRE_DEBUG traces the negotiated modifier and each mapping.
Without it there is no way to tell whether a capture used this path at all.
- OPENSCREEN_PIPEWIRE_FORCE_DMABUF drops the shm object so a compositor that
offers both is forced onto DMA-BUF. Test-only, and the only way to exercise
any of this without the compositor from #287.
- Corrects the claim that every Smithay/wlroots compositor lacks a memfd path.
sway 1.9 has one and takes it.
56 crate tests pass, enum_format_survives_a_dmabuf_only_producer included.
Not verified: whether niri reports maxsize = 0 as wlroots does, so this may
not be the whole of #287. And no frames are encoded under nested sway — an
empty desktop generates almost no damage — so osc_read_frame's dmabuf arm is
still unexercised beyond the mapping itself.
@coderabbitai

coderabbitaiBot commented Aug 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@EtienneLescot, you've reached your PR review limit, so we couldn't start this review.

Next review available in:43 seconds

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e49b169d-c7ca-4de0-97e4-52762b96bc6e

📥 Commits

Reviewing files that changed from the base of the PR and between 686f239 and 5490dd5.

📒 Files selected for processing (1)
  • electron/native/pipewire-capture/csrc/pw_shim.c

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@EtienneLescot
EtienneLescot merged commit 6afd393 into mainAug 8, 2026
19 checks passed
@EtienneLescot
EtienneLescot deleted the fix/dmabuf-import-maxsize branch August 8, 2026 22:22
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@EtienneLescot