Linux Host Driver - notro/gud GitHub Wiki

The Linux host driver is available in mainline since v5.13: drivers/gpu/drm/gud

5.10 backport: https://github.com/notro/gud/discussions/21#discussioncomment-7667439

Development tree: https://cgit.freedesktop.org/drm/drm-misc/tree/drivers/gpu/drm/gud (maintainers entry)

Asynchronous flushing

When the host driver receives a notification that the framebuffer has changed it stores the info about which area that has changed, wakes up a kernel thread, and notifies the caller that the flush has happened (DRM_IOCTL_MODE_PAGE_FLIP, DRM_IOCTL_MODE_DIRTYFB or DRM_IOCTL_MODE_ATOMIC with optional damage property).

The kernel thread copies the changed area from the framebuffer into a temporary buffer, compresses it if supported and then sends the buffer to the device.

This can lead to tearing since userspace might be writing to the buffer that is being copied by the kernel thread. If this turns out to be a problem in real life, one solution might be to copy the buffer during the commit/flip and do the USB transfer asynchronously.

This also means that userspace doesn't know when the update has happened, to userspace it looks like the GUD device is blazingly fast (and thus modetest -v will give bogus fps numbers).

The reason for doing it like that is because some Desktop Environments runs all displays in the same rendering loop and the slowest one sets the pace. This would really hamper performance on that 60/120Hz primary display.

Linux v5.15 got a module parameter async_flush that can control this behaviour. In Linux v6.3 the default was changed to synchronous flushing (ref).

Split transfers

If the gadget sets max_buffer_size and an update exceeds that, the update is split up in order to fit the device buffer. A device which supports lz4 decompression and has very little memory might do that.

The host might also trigger a split because it couldn't allocate a big enough compression buffer (fixed in Linux v5.15: drm/gud: Use scatter-gather USB bulk transfer).

A split transfer will most likely cause tearing since there will be a delay between the partial transfers. When showing a movie this causes a constant tearing line where the split is.

XRGB8888 emulation

If the gadget does not support XRGB8888 the driver will advertise XRGB8888 and convert to the first format the device returns. This is because some userspace only supports this format.

DRM Properties

The GUD protocol supports several DRM connector properties and one plane property (rotation). The downside is that these properties are poorly supported in userspace applications and libraries.

The connector margin properties and rotation can be set on the kernel commandline.

Backlight

The GUD_PROPERTY_BACKLIGHT_BRIGHTNESS protocol property is presented to userspace as a backlight device.

fbdev emulation

The driver provides fbdev support through the DRM fbdev emulation layer. Going through fbdev incurs the overhead of an extra buffer copy.

PRIME Buffer Sharing

The GUD driver is only a display driver. Userspace can use a GPU to do the rendering and then let GUD display the resulting framebuffer. To do this the display driver and GPU driver have to share a buffer.

There are two ways to do this:

  • Userspace creates a GPU buffer and imports this into the display driver

  • Userspace creates a dumb buffer in the display driver and imports this into the GPU driver

Which strategi is used can be deduced by turning on PRIME debug output to the kernel log: echo 0x08 > /sys/module/drm/parameters/debug

Refs:

Other issues

  • systemd or GNOME/mutter does not close the DRM file descriptor when the device is unplugged. This results in buffers not being freed. This will be fixed in Linux v5.15: drm/gud: Free buffers on device removal

  • The Pi4 has two hdmi ports and I was asked if the driver supports driving both at the same time, and I've concluded that it would be too much work to implement at this point. It is possible to extend the protocol and implement it later.