[gtk/wip/on-the-surface-good-fences-can-make-bad-neighbors: 2/2] x11: Avoid thawing surface until frame is drawn



commit 56b36694110dab4db2f540db704e31c8d5934247
Author: Ray Strode <rstrode redhat com>
Date:   Tue Jun 30 14:15:53 2020 -0400

    x11: Avoid thawing surface until frame is drawn
    
    Since commit 972134abe48a4c9c7b6ad41b0723f30f4e7ae16b a frame getting
    drawn has three states (with the vendor nvidia driver at least):
    
    1. drawn by gtk waiting on the GPU
    2. drawn by GPU waiting on the compositor
    3. drawn by compositor
    
    Those three states are encoded in two flags: frame_pending and
    frame_still_painting.
    
    frame_pending means step 1 is done, but step 2 and 3 are still
    in progress.  frame_still_painting means step 2 is still in progress.
    
    After step 1 is finished the surface is frozen until step 3 is finished.
    
    When the compositor notifies gtk it's done with step 3, with a
    _NET_WM_FRAME_DRAWN client message, the toolkit thaws the surface to
    allow the next frame to proceed.
    
    The compositor sometimes sends gtk a _NET_WM_FRAME_DRAWN client message
    between steps 1 and 2.  This message should be ignored because it's not
    a reply to the current frame.
    
    Unfortunately, gtk currently assumes if it gets a _NET_WM_FRAME_DRAWN
    client message while waiting for step 2 that it's actually at step 3,
    and proceeds to draw a new frame while the existing frame is still
    pending, leading to a blown assertion.
    
    This commit addresses the problem by ignoring _NET_WM_FRAME_DRAWN
    client messages from the compositor unless actually expecting one.
    
    Fixes: #2902

 gdk/x11/gdkdisplay-x11.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
---
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 9804d0ea79..ca337066b8 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -1184,7 +1184,7 @@ _gdk_wm_protocols_filter (const XEvent  *xevent,
           if (timings)
             timings->drawn_time = frame_drawn_time;
 
-          if (surface_impl->toplevel->frame_pending)
+          if (!surface_impl->toplevel->frame_still_painting && surface_impl->toplevel->frame_pending)
             {
               surface_impl->toplevel->frame_pending = FALSE;
               gdk_surface_thaw_updates (win);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]