Fix hang on startup under Wayland & LIBDECOR with the VULKAN backend

Create a dummy buffer so LIBDECOR initializes the window configuration.
This commit is contained in:
Campbell Barton
2024-01-12 11:28:28 +11:00
parent 16741e735b
commit 3aa3743b6e
3 changed files with 54 additions and 0 deletions

View File

@@ -2086,6 +2086,13 @@ static int memfd_create_sealed(const char *name)
#endif /* !HAVE_MEMFD_CREATE */
}
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_VULKAN_BACKEND)
int memfd_create_sealed_for_vulkan_hack(const char *name)
{
return memfd_create_sealed(name);
}
#endif
enum {
GWL_IOR_READ = 1 << 0,
GWL_IOR_WRITE = 1 << 1,

View File

@@ -88,6 +88,13 @@ bool ghost_wl_dynload_libraries_init();
void ghost_wl_dynload_libraries_exit();
#endif
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_VULKAN_BACKEND)
/**
* Needed for temporary buffer creation.
*/
int memfd_create_sealed_for_vulkan_hack(const char *name);
#endif
struct GWL_Output {
/** Wayland core types. */

View File

@@ -38,6 +38,10 @@
# include <wayland_dynload_libdecor.h>
# endif
# include <libdecor.h>
# ifdef WITH_VULKAN_BACKEND
# include <unistd.h> /* For `ftruncate`. */
# endif
#endif
/* Generated by `wayland-scanner`. */
@@ -1769,11 +1773,47 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
/* NOTE: LIBDECOR requires the window to be created & configured before the state can be set.
* Workaround this by using the underlying `xdg_toplevel` */
# ifdef WITH_VULKAN_BACKEND
/* A dummy buffer is needed for VULKAN & LIBDECOR,
* otherwise `decor.initial_configure_seen` and startup locks up. */
wl_buffer *dummy_buffer = nullptr;
if (window_->ghost_context_type == GHOST_kDrawingContextTypeVulkan) {
const uint32_t format = WL_SHM_FORMAT_ARGB8888;
const int format_size = 4;
const int buffer_size = (window_->frame.size[0] * window_->frame.size[1]) * format_size;
const int fd = memfd_create_sealed_for_vulkan_hack("ghost-wl-dummy-buffer");
ftruncate(fd, buffer_size);
wl_shm *shm = system_->wl_shm_get();
wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer_size);
dummy_buffer = wl_shm_pool_create_buffer(pool,
0,
window_->frame.size[0],
window_->frame.size[1],
window_->frame.size[0] * format_size,
format);
wl_shm_pool_destroy(pool);
wl_surface_attach(window_->wl.surface, dummy_buffer, 0, 0);
wl_surface_damage(window_->wl.surface, 0, 0, window_->frame.size[0], window_->frame.size[1]);
wl_surface_commit(window_->wl.surface);
::close(fd);
}
# endif /* WITH_GHOST_WAYLAND_LIBDECOR */
while (!decor.initial_configure_seen) {
wl_display_flush(system->wl_display_get());
wl_display_dispatch(system->wl_display_get());
}
# ifdef WITH_VULKAN_BACKEND
if (window_->ghost_context_type == GHOST_kDrawingContextTypeVulkan) {
wl_surface_attach(window_->wl.surface, nullptr, 0, 0);
wl_surface_commit(window_->wl.surface);
wl_buffer_destroy(dummy_buffer);
}
# endif /* WITH_GHOST_WAYLAND_LIBDECOR */
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
gwl_window_state_set_for_xdg(toplevel, state, gwl_window_state_get(window_));
}