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:
- 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.
- 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.
The expected behavior from
DRM_EVENT_FLIP_COMPLETEis 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,
evdifires vblank immediately after the user-space driver (i.e.,displaylink) calledDRM_EVDI_GRABPIXto obtain a sampled buffer, meaning that the minimum time between commit and vblank is the time it takesevdi_painterto perform amemcpy. 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, causingdisplaylinkto 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
displaylinkdriver (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:
evdiqueue the pageflip event on a timer set to the display refresh rate. New commits should be rejected withEBUSYuntil it fires.displaylinkthrottle calls toDRM_EVDI_GRABPIXaccording to the display refresh rate. This could also be extended to haveDRM_EVDI_GRABPIXbe 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.