evdi_painter: vblank timing incorrect · Issue #512 · DisplayLink/evdi · GitHub
Skip to content

evdi_painter: vblank timing incorrect #512

Open

Description

@kennylevinsen

The expected behavior from DRM_EVENT_FLIP_COMPLETE is that it fires once the new content is presented, and will naturally be throttled to happen at an interval no shorter than the configured display refresh rate.

Currently, evdi fires vblank immediately after the user-space driver (i.e., displaylink) called DRM_EVDI_GRABPIX to obtain a sampled buffer, meaning that the minimum time between commit and vblank is the time it takes evdi_painter to perform a memcpy. This in turn will generally result in the drm master immediately starting to render a new frame, thinking the display is fast enough to want it, which in turn leads to new update ready events, causing displaylink to request the new frame leading to yet another immediate vblank event...

The result is wasted CPU/GPU on useless frames that get thrown away anyway, and as this event also drives the user-space visible vblank signals (e.g., Wayland's frame callbacks), it also causes user-space applications to run far too fast, wasting resources.

This also seems to lead to tearing, with the displaylink driver (or hardware) not performing appropriate double-buffering.

On top of this, if multiple commits are issued, the previous vblank event will fire immediately.

This could be fixed a few ways:

  1. Have evdi queue the pageflip event on a timer set to the display refresh rate. New commits should be rejected with EBUSY until it fires.
  2. Have displaylink throttle calls to DRM_EVDI_GRABPIX according to the display refresh rate. This could also be extended to have DRM_EVDI_GRABPIX be a blocking call that first fires any past vblank events, and then blocks on a condition that is raised when a new commit completes that can be copied, such that a vblank event correctly portrays that the user-space driver is ready to accept the next frame.

Activity

  1. synaptics-lspintzyk commented on Mar 28, 2025

    @synaptics-lspintzyk
    Contributor

    Hi @kennylevinsen,
    Thank you for your comments.

    Userspace displaylink driver is using double buffering and the reason it sends vblank right after memcpy in DRM_EVDI_GRABPIX is to allow compositor to prepare next frame when previous is in its internal render pipeline. Perhaps triggering vblank on timer rether than on grab would save some power. I agree this could be done better.

    I was analyzing that behaviour recently with Gnome/mutter wayland implementation and evdi driver never gets new commit until vblank event was sent for the last one. Also it was sending commits in a expected pace of the set refresh rate.

    Did you saw mentioned multiple commits issue in other than Gnome/mutter implementations? Can you say something more about the setup you see that problems?

  2. kennylevinsen commented on Mar 28, 2025

    @kennylevinsen
    Author

    Userspace displaylink driver is using double buffering and the reason it sends vblank right after memcpy in DRM_EVDI_GRABPIX is to allow compositor to prepare next frame when previous is in its internal render pipeline.

    This is not how the flip event is meant to fire, and will cause different problems based on display server rendering strategy.

    DRM_EVENT_FLIP_COMPLETED is used to:

    1. Throttle rendering so it happens no faster than the display can update content
    2. Time presentation to estimate the timing of the next presentation, synchronizing render timing as close to the calculated upcoming presentation as possible to minimize perceived latency
    3. Provide presentation timings required to correctly time audio and video frames in multimedia content

    If hardware feedback is not present in the displaylink platform (even within the black box driver), two of these use-cases are out the window and a timer is the only real option.

    When rendering full-screen content this fast, tearing artifacts occur. Given that evdi had synchronization issues reported in another thread, and given that the displaylink driver and its hardware is a black box, I'm not sure where the issue lies. Rendering this fast certainly isn't helping.

    Did you saw mentioned multiple commits issue in other than Gnome/mutter implementations? Can you say something more about the setup you see that problems?

    I tested both sway (I made wlroots work with displaylink some time back) and niri (where support for render-less display devices like displaylink is currently being prototyped) with weston-simple-egl as test client, powering a 4k@30Hz display using some bogus Dell DisplayLink dock I have laying around for test purposes.

    Due to evdi firing vblank immediately after DRM_EVDI_GRABPIX, sway and niri were both driving their render loops at around 120fps instead of 30fps, and also telling weston-simple-egl to render that fast. At this speed, the display was visibly tearing in a somewhat unusual way, with wide rows of interchangeably old and new content - niri devs reproduced this with different test hardware.

    I'd expect every display server with standard frame pacing to have this issue, and servers with smart frame pacing will do undefined things as they're trying to calculate the time between pageflip events and pick a point as close to the estimated next page flip event as possible to render.

    I don't use mutter, maybe it's running its own synthetic frame pacing timer with some special handling of invalid frame timings?

  3. synaptics-lspintzyk commented on Mar 28, 2025

    @synaptics-lspintzyk
    Contributor

    I can confirm I can see it on Weston with westin-simple-egl.
    On mutter it is fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions