xwayland: correctly report PresentCompleteModeCopy

After executing a PresentPixmap request using the copy path, Xwayland
will clear the vblank's pixmap field and re-queue it for the next msc so
that on the next frame a PresentCompleteNotify event will be delivered
to the client by present_execute_post.

While this does work, since the pixmap field of the vblank will be NULL
when present_execute_post is called, the mode reported in the event will
always be PresentCompleteModeSkip, even if the request *was* actually
executed with a copy.

To fix this, we introduce a new "copy_executed" flag in the
xwl_present_event struct. If xwl_present_execute sees that this flag is
set, it will fall straight through to present_execute_post like it does
if the window or pixmap is NULL. So, after executing a request with
present_execute_copy, instead of clearing the pixmap field we will set
the copy_executed flag to true. This will cause present_execute_post to
report the correct completion mode to the client when the
PresentCompleteNotify event is delivered on the next frame.

Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1254>
This commit is contained in:
Erik Kurzinger 2024-01-25 15:14:20 -08:00 committed by Marge Bot
parent b335a0fa20
commit a0717e5f03
2 changed files with 8 additions and 4 deletions

View File

@ -852,6 +852,7 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
WindowPtr window = vblank->window;
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
struct xwl_present_event *event = xwl_present_event_from_vblank(vblank);
xorg_list_del(&vblank->event_queue);
@ -868,7 +869,7 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
vblank->queued = FALSE;
if (vblank->pixmap && vblank->window) {
if (vblank->pixmap && vblank->window && !event->copy_executed) {
ScreenPtr screen = window->drawable.pScreen;
if (vblank->flip) {
@ -943,9 +944,8 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
present_execute_copy(vblank, crtc_msc);
assert(!vblank->queued);
/* Clear the pixmap field, so this will fall through to present_execute_post next time */
dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
vblank->pixmap = NULL;
/* Set the copy_executed field, so this will fall through to present_execute_post next time */
event->copy_executed = TRUE;
if (xwl_present_queue_vblank(screen, window, vblank->crtc,
vblank->event_id, crtc_msc + 1)
@ -1022,6 +1022,9 @@ xwl_present_pixmap(WindowPtr window,
if (vblank->target_msc != target_msc)
continue;
if (xwl_present_event_from_vblank(vblank)->copy_executed)
continue;
present_vblank_scrap(vblank);
if (vblank->flip_ready)
xwl_present_re_execute(vblank);

View File

@ -59,6 +59,7 @@ struct xwl_present_event {
PixmapPtr pixmap;
Bool async_may_tear;
Bool copy_executed;
};
Bool xwl_present_entered_for_each_frame_callback(void);