From 0612e0df6e104a5b76b8c95c2f40805198d81f2a Mon Sep 17 00:00:00 2001 From: hujianwei Date: Sun, 23 Oct 2022 08:47:27 +0000 Subject: [PATCH] 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. --- subcompositor.c | 13 +++++++------ xdg_surface.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/subcompositor.c b/subcompositor.c index 21d9c7d..7737b16 100644 --- a/subcompositor.c +++ b/subcompositor.c @@ -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; diff --git a/xdg_surface.c b/xdg_surface.c index 18ec0f3..6084501 100644 --- a/xdg_surface.c +++ b/xdg_surface.c @@ -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);