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.
This commit is contained in:
parent
bbc35fef25
commit
721bd5e6cf
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue