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); 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 there's nothing to do, return. */
if (!start) if (!start)
@ -2455,12 +2462,6 @@ SubcompositorUpdate (Subcompositor *subcompositor)
this case, because the surface should now be unmapped. */ this case, because the surface should now be unmapped. */
goto complete; 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. */ /* Now update all views from start onwards. */
list = start->link; list = start->link;

View file

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