Skip to content

Fix randomly high latency with the Nvidia Xorg driver

Daniel van Vugt requested to merge vanvugt/mutter:sync-delay-edge-cases into master

The documentation for clutter_stage_skip_sync_delay where it said "drawn as quickly as possible" had led to a literal interpretation that was ignoring the display's refresh rate and overfilling the SwapBuffers queue. This overfilling led to visible lag between the hardware cursor and the screen contents as clutter_stage_cogl_schedule_update would repeatedly schedule new frames faster than the refresh rate here:

if (sync_delay < 0)
  {   
    stage_cogl->update_time = now;
    return;
  }   

But nobody noticed this earlier because:

  • The offending code path is only used on Xorg.

  • It's only a problem on Xorg drivers (Nvidia since 3.34, !602 (merged)) that don't implement last_presentation_time so don't get a value above zero for pending_swaps to forcefully throttle updates to the refresh rate:

    clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window)
    {   
      ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
    
      if (stage_cogl->pending_swaps)
        return -1; /* in the future, indefinite */

    Which is also documented in the original design:

    If a redraw is scheduled for time T, and we’re still waiting for the previous swap to complete at time T, redraw immediately when the swap completes.

    https://blog.fishsoup.net/2012/11/28/avoiding-jitter-in-composited-frame-display/

Now we correct both the implementation and the documentation to only skip the sync delay and not skip throttling to the refresh rate. As intended by the original design. And now we don't get runaway lag from repeated overscheduling when using the Nvidia Xorg driver.

Fixes: https://bugs.launchpad.net/bugs/1880086

Edited by Daniel van Vugt

Merge request reports