[Bf-blender-cvs] [721bd5e6cf2] master: Fix invalid swapBuffer calls & outdated window decorations on Wayland

Campbell Barton noreply at git.blender.org
Fri Jan 20 08:12:33 CET 2023


Commit: 721bd5e6cf2328230ae9f7104e5380f21b5e9e7f
Author: Campbell Barton
Date:   Fri Jan 20 17:58:02 2023 +1100
Branches: master
https://developer.blender.org/rB721bd5e6cf2328230ae9f7104e5380f21b5e9e7f

Fix invalid swapBuffer calls & outdated window decorations on Wayland

Swap-buffers was being deferred (to prevent it being called
from the event handling thread) however when it was called the
OpenGL context might not be active (especially with multiple windows).

Moving the cursor between windows made eglSwapBuffers report:
EGL Error (0x300D): EGL_BAD_SURFACE.

Resolve this by removing swapBuffer calls and instead add a
GHOST_kEventWindowUpdateDecor event intended for redrawing
client-side-decoration.

Besides the warning, this results an error with LIBDECOR window frames
not redrawing when a window became inactive.

===================================================================

M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp
M	intern/ghost/intern/GHOST_WindowWayland.h
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 3932bc76af0..e950f9bc679 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -198,6 +198,8 @@ typedef enum {
   GHOST_kEventWindowActivate,
   GHOST_kEventWindowDeactivate,
   GHOST_kEventWindowUpdate,
+  /** Client side window decorations have changed and need to be redrawn. */
+  GHOST_kEventWindowUpdateDecor,
   GHOST_kEventWindowSize,
   GHOST_kEventWindowMove,
   GHOST_kEventWindowDPIHintChanged,
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 9c179a6394f..f486fc319c8 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -311,10 +311,9 @@ enum eGWL_PendingWindowActions {
 #  ifdef GHOST_OPENGL_ALPHA
   PENDING_OPAQUE_SET,
 #  endif
-  PENDING_SWAP_BUFFERS,
   PENDING_SCALE_UPDATE,
 };
-#  define PENDING_NUM (PENDING_SWAP_BUFFERS + 1)
+#  define PENDING_NUM (PENDING_SCALE_UPDATE + 1)
 
 static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
 {
@@ -338,9 +337,6 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
   if (win->pending_actions[PENDING_SCALE_UPDATE].exchange(false)) {
     win->ghost_window->outputs_changed_update_scale();
   }
-  if (win->pending_actions[PENDING_SWAP_BUFFERS].exchange(false)) {
-    win->ghost_window->swapBuffers();
-  }
 }
 
 #endif /* USE_EVENT_BACKGROUND_THREAD */
@@ -356,8 +352,6 @@ static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
 
 #endif
 
-  bool do_redraw = false;
-
   if (win->frame_pending.size[0] != 0 && win->frame_pending.size[1] != 0) {
     if ((win->frame.size[0] != win->frame_pending.size[0]) ||
         (win->frame.size[1] != win->frame_pending.size[1])) {
@@ -365,9 +359,6 @@ static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
     }
   }
 
-  bool is_active_ghost = (win->ghost_window ==
-                          win->ghost_system->getWindowManager()->getActiveWindow());
-
   if (win->frame_pending.is_active) {
     win->ghost_window->activate();
   }
@@ -375,10 +366,6 @@ static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
     win->ghost_window->deactivate();
   }
 
-  if (is_active_ghost != win->frame_pending.is_active) {
-    do_redraw = true;
-  }
-
   win->frame_pending.size[0] = win->frame.size[0];
   win->frame_pending.size[1] = win->frame.size[1];
 
@@ -387,15 +374,6 @@ static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
   /* Signal not to apply the scale unless it's configured. */
   win->frame_pending.size[0] = 0;
   win->frame_pending.size[1] = 0;
-
-  if (do_redraw) {
-#ifdef USE_EVENT_BACKGROUND_THREAD
-    /* Could swap buffers, use pending to a redundant call in some cases. */
-    gwl_window_pending_actions_tag(win, PENDING_SWAP_BUFFERS);
-#else
-    win->ghost_window->swapBuffers();
-#endif
-  }
 }
 
 static void gwl_window_frame_update_from_pending(GWL_Window *win)
@@ -621,12 +599,11 @@ static void frame_handle_commit(struct libdecor_frame * /*frame*/, void *data)
 {
   CLOG_INFO(LOG, 2, "commit");
 
+#  if 0
   GWL_Window *win = static_cast<GWL_Window *>(data);
-
-#  ifdef USE_EVENT_BACKGROUND_THREAD
-  gwl_window_pending_actions_tag(win, PENDING_SWAP_BUFFERS);
+  win->ghost_window->notify_decor_redraw();
 #  else
-  win->ghost_window->swapBuffers();
+  (void)data;
 #  endif
 }
 
@@ -1321,8 +1298,17 @@ GHOST_TSuccess GHOST_WindowWayland::activate()
       return GHOST_kFailure;
     }
   }
-  return system_->pushEvent_maybe_pending(
+  const GHOST_TSuccess success = system_->pushEvent_maybe_pending(
       new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowActivate, this));
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  if (success == GHOST_kSuccess) {
+    if (use_libdecor) {
+      /* Ensure there is a swap-buffers, needed for the updated window borders to refresh. */
+      notify_decor_redraw();
+    }
+  }
+#endif
+  return success;
 }
 
 GHOST_TSuccess GHOST_WindowWayland::deactivate()
@@ -1335,8 +1321,17 @@ GHOST_TSuccess GHOST_WindowWayland::deactivate()
   {
     system_->getWindowManager()->setWindowInactive(this);
   }
-  return system_->pushEvent_maybe_pending(
+  const GHOST_TSuccess success = system_->pushEvent_maybe_pending(
       new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowDeactivate, this));
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  if (success == GHOST_kSuccess) {
+    if (use_libdecor) {
+      /* Ensure there is a swap-buffers, needed for the updated window borders to refresh. */
+      notify_decor_redraw();
+    }
+  }
+#endif
+  return success;
 }
 
 GHOST_TSuccess GHOST_WindowWayland::notify_size()
@@ -1358,6 +1353,14 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size()
       new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowSize, this));
 }
 
+GHOST_TSuccess GHOST_WindowWayland::notify_decor_redraw()
+{
+  /* NOTE: we want to `swapBuffers`, however this may run from a thread and
+   * when this windows OpenGL context is not active, so send and update event instead. */
+  return system_->pushEvent_maybe_pending(
+      new GHOST_Event(system_->getMilliSeconds(), GHOST_kEventWindowUpdateDecor, this));
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index 326c1d5e994..c5554f70200 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -150,6 +150,7 @@ class GHOST_WindowWayland : public GHOST_Window {
   GHOST_TSuccess activate();
   GHOST_TSuccess deactivate();
   GHOST_TSuccess notify_size();
+  GHOST_TSuccess notify_decor_redraw();
 
   /* WAYLAND utility functions. */
 
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 0077c8e2259..2e5e370ae06 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1229,6 +1229,22 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
 
         break;
       }
+      case GHOST_kEventWindowUpdateDecor: {
+        if (G.debug & G_DEBUG_EVENTS) {
+          printf("%s: ghost redraw decor %d\n", __func__, win->winid);
+        }
+
+        wm_window_make_drawable(wm, win);
+#if 0
+        /* NOTE(@campbellbarton): Ideally we could swap-buffers to avoid a full redraw.
+         * however this causes window flickering on resize with LIBDECOR under WAYLAND. */
+        wm_window_swap_buffers(win);
+#else
+        WM_event_add_notifier(C, NC_WINDOW, NULL);
+#endif
+
+        break;
+      }
       case GHOST_kEventWindowSize:
       case GHOST_kEventWindowMove: {
         GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);



More information about the Bf-blender-cvs mailing list