evdi_painter: Access to scanout FB, vblank event, dirty rects racy · Issue #511 · DisplayLink/evdi · GitHub
Skip to content

evdi_painter: Access to scanout FB, vblank event, dirty rects racy #511

Open

Description

@kennylevinsen

When an atomic commit is being processed through the atomic commit helpers, the details of the coming frame is recorded on the evdi_painter through individual calls to evdi_painter_set_vblank, evdi_painter_set_scanout_buffer, evdi_painter_mark_dirty, etc.

Each of these functions take the evdi_painter's mutex through painter_lock, perform cleanup if needed, record the new value, and release the lock again. Once a user-space driver comes along and calls DRM_EVDI_GRABPIX, the painter lock is taken and all the values are observed.

The problem is that the values are recorded under individually held locks, meaning that there is no guarantee that the whole set of values are logically consistent. The caller may observe the dirty rect from the previous commit, but the scanout buffer from the current commit.

New values must be applied atomically. The simplest way to do this would be to accumulate values in a pending struct, and at the end of the atomic commit do something like:

struct evdi_painter_state old;

painter_lock(painter);
old = *painter->current;
*painter->current = *painter->pending;
evdi_painter_state_init(painter->pending);
painter_unlock(painter);

evdi_painter_state_finish(&old);

Activity

  1. synaptics-lspintzyk commented on Mar 28, 2025

    @synaptics-lspintzyk
    Contributor

    Hi
    @kennylevinsen, you are right that evdi_painter should care for consistency of the data that userspace driver reads.
    However I am not sure that we have problem at the moment with dirty rects. evdi_painter role is to accumulate dirty rects and keep pointer to last framebuffer, so that userspace driver will not miss any dirty rects. Here we have assumption that framebuffer content is valid and latest in the areas outside of the dirty rects region! Please let me know I am wrong here.

    I understand that you are raising concerns about design or code quality. Thank you for that.
    We can consider that improvements if this would fix some issues you see. Can you elaborate on that? E.g. what is your desktop environment or steps to reproduce issue?

  2. kennylevinsen commented on Mar 28, 2025

    @kennylevinsen
    Author
    1. If DRM_EVDI_GRABPIX is called after the buffer is recorded but before the commit flushes, vblank will not yet be stored and will therefore not be fired by evdi_painter_grabpix_ioctl. Without a pageflip event, no further commits will occur and the fallback fire in evdi_painter_set_vblank will also not fire. Later calls to evdi_painter_grabpix_ioctl will fail early due to there being no dirty regions. This would stall rendering for that output.

    2. If a newer damage clip could end up used with an older buffer, issues would occur where content new content does not end up copied as the old buffer was used as source, and later buffers while containing the new content does not damage the area.

    3. If an older damage clip is used with a new buffer, the output will show stale and/or partial content until the output changes again.

    Maybe other things could happen. It's definitely broken, and it doesn't feel like it would be that much work to fix. I discovered the issue while looking at why displaylink was tearing despite running under a strictly double-buffering display server.

  3. synaptics-lspintzyk commented on Mar 28, 2025

    @synaptics-lspintzyk
    Contributor

    Thanks @kennylevinsen
    Can you describe steps to reproduce that problems?
    e.g.
    What distro you have?
    What primary gpu (e.g. amdgpu has some known tearing issues to me. maybe they are related)?
    What compositor you have? How it is configured. Is it installed from sources of from packages.
    Any relevant informations.

    Thanks for rising that.

  4. kennylevinsen commented on Mar 28, 2025

    @kennylevinsen
    Author

    The tearing was observed with AMDGPU yes. It could be an implicit sync issue, made worse by the very high display refresh evdi is driving.

    1. I connected a displaylink device to a 4k monitor, which it could only drive at 30Hz.
    2. I launched sway (master branch with WLR_RENDERER=vulkan set) or niri (the development branch linked in the other issue
    3. I launched weston-simple-egl
    4. I saw tearing and absurd refresh rates

    There's some details about the discovery here and in the other issue about vblank. This issue was just about the race conditions I found when glancing at evdi.

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