Fix display of deferred frames

* subcompositor.c (SubcompositorUpdate): Always call note frame
callback.
* xdg_surface.c (MaybeRunLateFrame): New function.
(AfterFrame, NoteFrame): Potentially run late frames.
This commit is contained in:
hujianwei 2022-10-23 08:47:27 +00:00
parent 76e40a1a74
commit 0612e0df6e
2 changed files with 43 additions and 10 deletions

View file

@ -2448,6 +2448,13 @@ SubcompositorUpdate (Subcompositor *subcompositor)
StorePreviousDamage (subcompositor, NULL);
}
/* Increase the frame count and announce the new frame number. This
must be done even if no graphics changes were committed. */
if (subcompositor->note_frame)
subcompositor->note_frame (ModeStarted,
++subcompositor->frame_counter,
subcompositor->note_frame_data);
/* If there's nothing to do, return. */
if (!start)
@ -2455,12 +2462,6 @@ SubcompositorUpdate (Subcompositor *subcompositor)
this case, because the surface should now be unmapped. */
goto complete;
/* Increase the frame count and announce the new frame number. */
if (subcompositor->note_frame)
subcompositor->note_frame (ModeStarted,
++subcompositor->frame_counter,
subcompositor->note_frame_data);
/* Now update all views from start onwards. */
list = start->link;

View file

@ -940,6 +940,30 @@ HandleResourceDestroy (struct wl_resource *resource)
ReleaseBacking (role);
}
static Bool
MaybeRunLateFrame (XdgRole *role)
{
/* If there is a late frame, run it now. Return whether or not a
late frame was run. */
if (role->state & StateLateFrame)
{
/* Clear the late frame flag. */
role->state &= ~StateLateFrame;
if (role->state & StateLateFrameAcked)
XLFrameClockUnfreeze (role->clock);
/* Now apply the state in the late frame. */
SubcompositorUpdate (role->subcompositor);
/* Return True, as a new update has started. */
return True;
}
return False;
}
static void
AfterFrame (FrameClock *clock, void *data)
{
@ -947,6 +971,10 @@ AfterFrame (FrameClock *clock, void *data)
role = data;
/* Run any late frame. */
if (MaybeRunLateFrame (role))
return;
/* If all pending frames have been drawn, run frame callbacks.
Unless some buffers have not yet been released, in which case the
callbacks will be run when they are. */
@ -1267,15 +1295,20 @@ NoteFrame (FrameMode mode, uint64_t id, void *data)
/* End the frame. */
XLFrameClockEndFrame (role->clock);
/* Clear the frame completed flag. */
role->state &= ~StateFrameStarted;
/* No frame was started clock-side for this frame. That
means programs waiting for frame callbacks will not get
any, so the frame callbacks must be run by hand. */
if (!(role->state & StateFrameStarted)
|| !IsRoleMapped (role))
RunFrameCallbacksConditionally (role);
{
if (MaybeRunLateFrame (role))
return;
/* Clear the frame completed flag. */
role->state &= ~StateFrameStarted;
RunFrameCallbacksConditionally (role);
}
if (mode == ModePresented
&& renderer_flags & SupportsDirectPresent)
@ -1574,7 +1607,6 @@ XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
role->subcompositor = MakeSubcompositor ();
role->clock = XLMakeFrameClockForWindow (role->window);
XLFrameClockSetFreezeCallback (role->clock, HandleFreeze, role);
SubcompositorSetTarget (role->subcompositor, &role->target);