mirror of
https://github.com/yshui/picom.git
synced 2025-04-14 17:53:25 -04:00
vblank: alternative invalid present event recovery
I found sometimes, when we receive an invalid PresentCompleteNotify, keep requesting new present notifys using `last_msc + 1` doesn't really help us recover. Instead X just keeps sending us bad PresentCompleteNotifys, and we stuck in a loop. (This is more likely to happen during screen resolution change. Also this did not seem to be possible previously, when we were still handling resolution changes inside the X critical section.) This commit tries to test out a different approach. The hypothesis is, maybe doing something to the screen (e.g. render and present a new frame) helps change the internal state of the X server, thus kicks us out of the loop. So whenever we get an invalid notify, we fake a vblank event so rendering can happen. And we keeps doing this until we are (hopefully) fine. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
1c57ba85b7
commit
532784149e
1 changed files with 11 additions and 10 deletions
21
src/vblank.c
21
src/vblank.c
|
@ -401,6 +401,10 @@ static void handle_present_complete_notify(struct present_vblank_scheduler *self
|
|||
|
||||
assert(self->base.vblank_event_requested);
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
auto now_us = (unsigned long)(now.tv_sec * 1000000L + now.tv_nsec / 1000);
|
||||
|
||||
// X sometimes sends duplicate/bogus MSC events, when screen has just been turned
|
||||
// off. Don't use the msc value in these events. We treat this as not receiving a
|
||||
// vblank event at all, and try to get a new one.
|
||||
|
@ -409,18 +413,15 @@ static void handle_present_complete_notify(struct present_vblank_scheduler *self
|
|||
// https://gitlab.freedesktop.org/xorg/xserver/-/issues/1418
|
||||
bool event_is_invalid = cne->msc <= self->last_msc || cne->ust == 0;
|
||||
if (event_is_invalid) {
|
||||
log_debug("Invalid PresentCompleteNotify event, %" PRIu64 " %" PRIu64,
|
||||
log_debug("Invalid PresentCompleteNotify event, %" PRIu64 " %" PRIu64
|
||||
". Trying to recover, reporting a fake vblank.",
|
||||
cne->msc, cne->ust);
|
||||
x_request_vblank_event(self->base.c, cne->window, self->last_msc + 1);
|
||||
return;
|
||||
self->last_ust = now_us;
|
||||
self->last_msc += 1;
|
||||
} else {
|
||||
self->last_ust = cne->ust;
|
||||
self->last_msc = cne->msc;
|
||||
}
|
||||
|
||||
self->last_ust = cne->ust;
|
||||
self->last_msc = cne->msc;
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
auto now_us = (unsigned long)(now.tv_sec * 1000000L + now.tv_nsec / 1000);
|
||||
double delay_sec = 0.0;
|
||||
if (now_us < cne->ust) {
|
||||
log_trace("The end of this vblank is %" PRIu64 " us into the "
|
||||
|
|
Loading…
Add table
Reference in a new issue