diff options
author | Sultan Alsawaf <sultan@kerneltoast.com> | 2023-01-22 22:16:58 -0800 |
---|---|---|
committer | Sultan Alsawaf <sultan@kerneltoast.com> | 2023-02-28 22:43:37 -0800 |
commit | d4bd39f1a5db2c5ee5ff251f1982bbe6aa5c0f7f (patch) | |
tree | d3efbafe0e9e839f372ebe83cf8cd8b6dec59329 | |
parent | 53b02054f36a49bd45e954f0eef1029152af78b7 (diff) | |
download | xserver-d4bd39f1a5db2c5ee5ff251f1982bbe6aa5c0f7f.tar.gz |
present: Prevent double vblank enqueue on error when TearFree is used
It's possible for present_execute_copy to enqueue a vblank even when
TearFree is used, specifically when the present_queue_vblank in
present_scmd_pixmap fails and the subsequent vblank enqueue in
present_execute_copy somehow doesn't. This could happen if the DRM event
queue is exhausted when present_queue_vblank is called, but is no longer
exhausted by the time present_execute_copy is reached.
This exceedingly unlikely chain of events can lead to a vblank getting
enqueued a second time by the TearFree machinery in present_execute, which
is not good.
Although this scenario is very unlikely, prevent it by first checking that
the vblank wasn't enqueued by present_execute_copy before attempting to
enqueue it for TearFree.
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Acked-by: Martin Roukala <martin.roukala@mupuf.org>
-rw-r--r-- | present/present_scmd.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/present/present_scmd.c b/present/present_scmd.c index 200ded348..59feb001b 100644 --- a/present/present_scmd.c +++ b/present/present_scmd.c @@ -554,7 +554,6 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) WindowPtr window = vblank->window; ScreenPtr screen = window->drawable.pScreen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); - uint64_t completion_msc; if (vblank && vblank->crtc) { screen_priv=present_screen_priv(vblank->crtc->pScreen); } @@ -652,23 +651,26 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) * If TearFree is already flipping then the presentation will be visible * at the *next* next vblank. */ - completion_msc = crtc_msc + 1; - switch (vblank->reason) { - case PRESENT_FLIP_REASON_DRIVER_TEARFREE_FLIPPING: - if (vblank->exec_msc < crtc_msc) - completion_msc++; - case PRESENT_FLIP_REASON_DRIVER_TEARFREE: - if (Success == screen_priv->queue_vblank(screen, - window, - vblank->crtc, - vblank->event_id, - completion_msc)) { - /* Ensure present_execute_post() runs at the next MSC */ - vblank->exec_msc = vblank->target_msc; - vblank->queued = TRUE; + if (!vblank->queued) { + uint64_t completion_msc = crtc_msc + 1; + + switch (vblank->reason) { + case PRESENT_FLIP_REASON_DRIVER_TEARFREE_FLIPPING: + if (vblank->exec_msc < crtc_msc) + completion_msc++; + case PRESENT_FLIP_REASON_DRIVER_TEARFREE: + if (Success == screen_priv->queue_vblank(screen, + window, + vblank->crtc, + vblank->event_id, + completion_msc)) { + /* Ensure present_execute_post() runs at the next MSC */ + vblank->exec_msc = vblank->target_msc; + vblank->queued = TRUE; + } + default: + break; } - default: - break; } if (vblank->queued) { |