v3d: missing drm format modifier support on Raspberry Pi 4 required for mpv
System information
- OS: Manjaro ARM Minimal for RPi
- GPU: V3D
- Kernel version: 5.15.82
- Mesa version: 23.0 git
- Compositor: Sway
Describe the issue
I'm working to get HEVC hardware decoding to work with MPV on the Raspberry Pi 4. Recreating my setup to reproduce this issue is difficult because you need a ffmpeg with patches from https://github.com/jc-kynesim/rpi-ffmpeg/ and a mpv with patches I've created to run into this issue. The video file I am using to test is attached. I will try to be as thorough as possible in explaining the issue, and can provide more details using my setup if they are required.
MPV uses eglCreateImageKHR to create mapped surfaces with EGL_LINUX_DMA_BUF_EXT. The problem I'm having is that when it comes time to do this I get EGL_BAD_MATCH because the format modifier isn't supported. When I manually set this modifier to 0 the video plays, but looks like the first screenshot.
The modifier that is trying to be used is DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(1200), which is equal to 0x70000000004b004. If you count the squares from left to right in the first image, you'll see there are 15 of them. 1920/15 is 128, and sure enough if the pitch is set to 128 instead of 1920 then the result is the second screenshot. With that one the first column is perfect, but the rest are still broken.
MPV is seeing DRM_FORMAT_NV12, and translates that to two textures, one DRM_FORMAT_R8 and the other DRM_FORMAT_GR88. I believe this is the core of the issue. Mesa supports SAND128 for NV12, but not these single plane formats, which is how MPV handles things. Using eglQueryDmaBufModifiersEXT I could confirm what modifiers each format supported:
DRM_FORMAT_NV12:
DRM_FORMAT_MOD_BROADCOM_UIF
DRM_FORMAT_INVALID
DRM_FORMAT_MOD_BROADCOM_SAND128
DRM_FORMAT_R8:
DRM_FORMAT_MOD_BROADCOM_UIF
DRM_FORMAT_INVALID
DRM_FORMAT_GR88:
DRM_FORMAT_MOD_BROADCOM_UIF
DRM_FORMAT_MOD_INVALID
I tried the UIF modifier but that only results in the error Attempt to import unsupported winsys offset 102400
(the offset for the GR88 surface is 102400) and EGL_BAD_ALLOC.
This is all just for 8-bit HEVC videos, but I imagine a similar issue will crop up with 10-bit.
Doing a quick grep it looks like the relevant code is in src/gallium/drivers/v3d/v3d_screen.c but I've never looked at the Mesa code before so I could be wildly off with that. If anyone's curious or if it's useful, the relevant code for MPV is in video/out/hwdec/dmabuf_interop_gl.c.
Also I'm not a graphics or multimedia guy, just someone trying to watch videos on a Raspberry Pi, so if any of my terminology is wrong or if this isn't a Mesa issue (already tried opening an issue on libglvnd) then please let me know.