xwayland/present: Handle clearing damage after flip in xwl_present_execute

Due to DamageReportNonEmpty, damage_report doesn't get called if the
damage region was already non-empty before the flip. In which case it
didn't get called before the first draw after the flip either.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1627
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1314>
This commit is contained in:
Michel Dänzer 2024-02-28 10:52:03 +01:00 committed by Michel Dänzer
parent 6b290fa5d9
commit 64341c479c
4 changed files with 15 additions and 13 deletions

View File

@ -35,6 +35,7 @@
#include "xwayland-screen.h"
#include "xwayland-shm.h"
#include "xwayland-window.h"
#include "xwayland-window-buffers.h"
#include "xwayland-pixmap.h"
#include "tearing-control-v1-client-protocol.h"
@ -833,7 +834,6 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
}
wl_display_flush(xwl_window->xwl_screen->display);
xwl_window->present_flipped = TRUE;
return TRUE;
}
@ -890,6 +890,8 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
if (xwl_present_flip(vblank, damage)) {
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window);
struct xwl_window *xwl_window = xwl_window_from_window(window);
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
/* Replace window pixmap with flip pixmap */
@ -906,10 +908,19 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
vblank->pixmap->refcnt++;
dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
/* Report damage */
/* Report damage, let damage_report ignore it though */
xwl_screen->ignore_damage = TRUE;
DamageDamageRegion(&vblank->window->drawable, damage);
xwl_screen->ignore_damage = FALSE;
RegionDestroy(damage);
/* Clear damage region, to ensure damage_report is called before
* any drawing to the window
*/
xwl_window_buffer_add_damage_region(xwl_window);
RegionEmpty(xwl_window_get_damage_region(xwl_window));
xorg_list_del(&xwl_window->link_damage);
/* Put pending flip at the flip queue head */
xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue);

View File

@ -90,6 +90,7 @@ struct xwl_screen {
struct xorg_list seat_list;
struct xorg_list damage_window_list;
struct xorg_list window_list;
Bool ignore_damage;
int wayland_fd;
struct wl_display *display;

View File

@ -194,17 +194,8 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
return;
xwl_screen = xwl_window->xwl_screen;
if (xwl_window->present_flipped) {
/* This damage is from a Present flip, which already committed a new
* buffer for the surface, so we don't need to do anything in response
*/
xwl_window_buffer_add_damage_region(xwl_window);
RegionEmpty(DamageRegion(pDamage));
xorg_list_del(&xwl_window->link_damage);
xwl_window->present_flipped = FALSE;
if (xwl_screen->ignore_damage)
return;
}
if (xorg_list_is_empty(&xwl_window->link_damage))
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);

View File

@ -111,7 +111,6 @@ struct xwl_window {
struct wl_output *wl_output;
struct wl_output *wl_output_fullscreen;
struct xorg_list frame_callback_list;
Bool present_flipped;
#ifdef XWL_HAS_LIBDECOR
struct libdecor_frame *libdecor_frame;
#endif