From 873472b747eb13721154ec6fc3dd2a83d31ec1e0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 20 Feb 2024 14:09:49 +0100 Subject: [PATCH 1/2] Linux: Improve headless EGL initialization messages When it succeeds, don't print an error message. When it fails, print errors for both display and headless attempts. Pull Request: https://projects.blender.org/blender/blender/pulls/118530 --- intern/ghost/intern/GHOST_ContextEGL.cc | 75 ++++++++++++++++--------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextEGL.cc b/intern/ghost/intern/GHOST_ContextEGL.cc index a68e91e185b..5239ee49541 100644 --- a/intern/ghost/intern/GHOST_ContextEGL.cc +++ b/intern/ghost/intern/GHOST_ContextEGL.cc @@ -111,6 +111,19 @@ static const char *get_egl_error_message_string(EGLint error) } } +static void egl_print_error(const char *message, const EGLint error) +{ + const char *code = get_egl_error_enum_string(error); + const char *msg = get_egl_error_message_string(error); + + fprintf(stderr, + "%sEGL Error (0x%04X): %s: %s\n", + message, + uint(error), + code ? code : "", + msg ? msg : ""); +} + static bool egl_chk(bool result, const char *file = nullptr, int line = 0, @@ -132,11 +145,7 @@ static bool egl_chk(bool result, code ? code : "", msg ? msg : ""); #else - fprintf(stderr, - "EGL Error (0x%04X): %s: %s\n", - uint(error), - code ? code : "", - msg ? msg : ""); + egl_print_error("", error); (void)(file); (void)(line); (void)(text); @@ -343,33 +352,43 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext() goto error; } - if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)) || - (egl_major == 0 && egl_minor == 0)) { - /* We failed to create a regular render window, retry and see if we can create a headless - * render context. */ - ::eglTerminate(m_display); + const EGLBoolean init_display_result = ::eglInitialize(m_display, &egl_major, &egl_minor); + const EGLint init_display_error = (init_display_result) ? 0 : eglGetError(); - const char *egl_extension_st = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); - assert(egl_extension_st != nullptr); - assert(egl_extension_st == nullptr || - strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") != nullptr); - if (egl_extension_st == nullptr || - strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") == nullptr) - { - goto error; + if (!init_display_result || (egl_major == 0 && egl_minor == 0)) { + /* We failed to create a regular render window, retry and see if we can create a headless + * render context. */ + ::eglTerminate(m_display); + + const char *egl_extension_st = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + assert(egl_extension_st != nullptr); + assert(egl_extension_st == nullptr || + strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") != nullptr); + if (egl_extension_st == nullptr || + strstr(egl_extension_st, "EGL_MESA_platform_surfaceless") == nullptr) + { + egl_print_error("Failed to create display GPU context: ", init_display_error); + fprintf( + stderr, + "Failed to create headless GPU context: No EGL_MESA_platform_surfaceless extension"); + goto error; + } + + m_display = eglGetPlatformDisplayEXT( + EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, nullptr); + + const EGLBoolean headless_result = ::eglInitialize(m_display, &egl_major, &egl_minor); + const EGLint init_headless_error = (headless_result) ? 0 : eglGetError(); + + if (!headless_result) { + egl_print_error("Failed to create display GPU context: ", init_display_error); + egl_print_error("Failed to create headless GPU context: ", init_headless_error); + goto error; + } } - - m_display = eglGetPlatformDisplayEXT( - EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, nullptr); - - if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor))) { - goto error; - } - /* Because the first eglInitialize will print an error to the terminal, print a "success" - * message here to let the user know that we successfully recovered from the error. */ - fprintf(stderr, "\nManaged to successfully fallback to surfaceless EGL rendering!\n\n"); } + #ifdef WITH_GHOST_DEBUG fprintf(stderr, "EGL Version %d.%d\n", egl_major, egl_minor); #endif From 4c708a8c3e8af55c7e623516ae0d2046e5fecd43 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 20 Feb 2024 20:11:16 +0100 Subject: [PATCH 2/2] Linux: Avoid XDG_RUNTIME_DIR warnings running headless Blender Pull Request: https://projects.blender.org/blender/blender/pulls/118530 --- intern/ghost/intern/GHOST_SystemWayland.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 4f3b71bdb2f..fb8963d130d 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -1780,6 +1780,8 @@ static void ghost_wayland_log_handler(const char *msg, va_list arg) __attribute__((format(printf, 1, 0))); #endif +static bool ghost_wayland_log_handler_is_background = false; + /** * Callback for WAYLAND to run when there is an error. * @@ -1788,6 +1790,15 @@ static void ghost_wayland_log_handler(const char *msg, va_list arg) */ static void ghost_wayland_log_handler(const char *msg, va_list arg) { + /* This is fine in background mode, we will try to fall back to headless GPU context. + * Happens when render farm process runs without user login session. */ + if (ghost_wayland_log_handler_is_background && + (strstr(msg, "error: XDG_RUNTIME_DIR not set in the environment") || + strstr(msg, "error: XDG_RUNTIME_DIR is invalid or not set in the environment"))) + { + return; + } + fprintf(stderr, "GHOST/Wayland: "); vfprintf(stderr, msg, arg); /* Includes newline. */ @@ -6872,6 +6883,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background) #endif display_(new GWL_Display) { + ghost_wayland_log_handler_is_background = background; wl_log_set_handler_client(ghost_wayland_log_handler); display_->system = this;