forked from 12to11/12to11
Fix race condition between ConfigureNotify and PresentCompleteNotify
* compositor.h: Update prototypes. * frame_clock.c (struct _FrameClock): New fields for keeping track of configure events. (FreezeForValue): If the freeze is outdated, bring the counter up to date now. (XLFrameClockHandleFrameEvent): Set the number of configure events that should have been considered by the frame clock upon processing. (XLFrameClockNoteConfigure): New function. * picture_renderer.c (SwapBackBuffers): Remove outdated comment. * xdg_surface.c (NoteConfigure, XLXdgRoleReconstrain): * xdg_toplevel.c (NoteWindowResized): Note frame clock configure.
This commit is contained in:
parent
da212fe729
commit
743d363ad2
5 changed files with 61 additions and 3 deletions
|
@ -1288,6 +1288,7 @@ extern void XLFrameClockDisablePredictRefresh (FrameClock *);
|
|||
extern void XLFrameClockSetFreezeCallback (FrameClock *, void (*) (void *),
|
||||
void *);
|
||||
extern uint64_t XLFrameClockGetFrameTime (FrameClock *);
|
||||
extern void XLFrameClockNoteConfigure (FrameClock *);
|
||||
extern void *XLAddCursorClockCallback (void (*) (void *, struct timespec),
|
||||
void *);
|
||||
extern void XLStopCursorClockCallback (void *);
|
||||
|
|
|
@ -109,6 +109,11 @@ struct _FrameClock
|
|||
/* The delay between the start of vblank and the redraw point. */
|
||||
uint32_t frame_delay;
|
||||
|
||||
/* The number of configure events received affecting freeze, and the
|
||||
number of configure events that should be received after a freeze
|
||||
is put in place. */
|
||||
uint32_t got_configure_count, pending_configure_count;
|
||||
|
||||
/* Whether or not configury is in progress, and whether or not this
|
||||
is frozen, and whether or not the frame shouldn't actually be
|
||||
unfrozen until EndFrame. */
|
||||
|
@ -239,18 +244,31 @@ HandleEndFrame (Timer *timer, void *data, struct timespec time)
|
|||
EndFrame (clock);
|
||||
}
|
||||
|
||||
/* Forward declaration. */
|
||||
/* Forward declarations. */
|
||||
|
||||
static void RunFrameCallbacks (FrameClock *);
|
||||
static Bool StartFrame (FrameClock *, Bool, Bool);
|
||||
|
||||
static void
|
||||
FreezeForValue (FrameClock *clock, uint64_t counter_value)
|
||||
{
|
||||
Bool need_empty_frame;
|
||||
|
||||
/* If it took too long (1 second at 60fps) to obtain the counter
|
||||
value, and said value is now out of date, don't do anything. */
|
||||
|
||||
if (clock->next_frame_id > counter_value)
|
||||
return;
|
||||
|
||||
need_empty_frame = False;
|
||||
|
||||
/* If ending a frame waits for PresentCompleteNotify, then the
|
||||
configure event after this freeze may have been put into effect
|
||||
by the time the freeze itself. Start a new frame to bring up to
|
||||
date contents to the display. */
|
||||
if (clock->pending_configure_count <= clock->got_configure_count)
|
||||
need_empty_frame = True;
|
||||
|
||||
/* The frame clock is now frozen, and we will have to wait for a
|
||||
client to ack_configure and then commit something. */
|
||||
|
||||
|
@ -278,7 +296,20 @@ FreezeForValue (FrameClock *clock, uint64_t counter_value)
|
|||
clock->in_frame = False;
|
||||
clock->need_configure = True;
|
||||
clock->configure_id = counter_value;
|
||||
clock->frozen = True;
|
||||
|
||||
if (need_empty_frame)
|
||||
{
|
||||
/* Request a new frame and don't allow starting frames until it
|
||||
finishes. See above for why. clock->in_frame is False for
|
||||
now to really force the frame to happen. */
|
||||
|
||||
StartFrame (clock, True, False);
|
||||
EndFrame (clock);
|
||||
}
|
||||
else
|
||||
clock->frozen = True;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -408,6 +439,10 @@ StartFrame (FrameClock *clock, Bool urgent, Bool predict)
|
|||
{
|
||||
clock->next_frame_id = clock->configure_id;
|
||||
clock->finished_frame_id = 0;
|
||||
|
||||
/* Don't start the end frame timer if this frame is being drawn
|
||||
in response to configury. */
|
||||
predict = True;
|
||||
}
|
||||
|
||||
clock->in_frame = True;
|
||||
|
@ -700,6 +735,11 @@ XLFrameClockHandleFrameEvent (FrameClock *clock, XEvent *event)
|
|||
if (value % 2)
|
||||
value += 1;
|
||||
|
||||
/* Set the number of configure events that should be received by
|
||||
the time the freeze is put into effect. */
|
||||
clock->pending_configure_count
|
||||
= clock->got_configure_count + 1;
|
||||
|
||||
/* If a frame is in progress, postpone this frame
|
||||
synchronization message. */
|
||||
if (clock->in_frame && !clock->end_frame_called)
|
||||
|
@ -861,6 +901,13 @@ XLFrameClockGetFrameTime (FrameClock *clock)
|
|||
return clock->last_frame_time;
|
||||
}
|
||||
|
||||
void
|
||||
XLFrameClockNoteConfigure (FrameClock *clock)
|
||||
{
|
||||
/* This value is to track resize event validity. */
|
||||
clock->got_configure_count += 1;
|
||||
}
|
||||
|
||||
|
||||
/* Cursor animation clock-related functions. */
|
||||
|
||||
|
|
|
@ -804,7 +804,6 @@ SwapBackBuffers (PictureTarget *target, pixman_region32_t *damage)
|
|||
if (!present_serial)
|
||||
present_serial++;
|
||||
|
||||
/* TODO: handle completion correctly. */
|
||||
XPresentPixmap (compositor.display, target->window,
|
||||
back_buffer->pixmap, present_serial,
|
||||
None, region, 0, 0, None, None, fence,
|
||||
|
|
|
@ -1064,6 +1064,11 @@ NoteConfigure (XdgRole *role, XEvent *event)
|
|||
event->xconfigure.y);
|
||||
}
|
||||
|
||||
/* Tell the frame clock how many WM-generated configure events have
|
||||
arrived. */
|
||||
XLFrameClockNoteConfigure (role->clock);
|
||||
|
||||
/* Run reconstrain callbacks. */
|
||||
RunReconstrainCallbacksForXEvent (role, event);
|
||||
}
|
||||
|
||||
|
@ -1956,6 +1961,10 @@ XLXdgRoleReconstrain (Role *role, XEvent *event)
|
|||
|
||||
xdg_role = XdgRoleFromRole (role);
|
||||
RunReconstrainCallbacksForXEvent (xdg_role, event);
|
||||
|
||||
/* If event is a configure event, tell the frame clock about it. */
|
||||
if (event->type == ConfigureNotify)
|
||||
XLFrameClockNoteConfigure (xdg_role->clock);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1660,6 +1660,8 @@ NoteWindowResized (Role *role, XdgRoleImplementation *impl,
|
|||
|
||||
if (event.xconfigure.send_event)
|
||||
XLXdgRoleNoteConfigure (toplevel->role, &event);
|
||||
else
|
||||
XLXdgRoleReconstrain (toplevel->role, &event);
|
||||
|
||||
RecordStateSize (toplevel);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue