Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
761 changes: 761 additions & 0 deletions deps/wxWidgets/0002-fix-wayland-egl-subsurface.patch

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion deps/wxWidgets/wxWidgets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif ()
set(_wx_toolkit "-DwxBUILD_TOOLKIT=gtk${_gtk_ver}")
set(_wx_private_font "-DwxUSE_PRIVATE_FONTS=1")
set(_wx_egl "-DwxUSE_GLCANVAS_EGL=OFF")
set(_wx_egl "-DwxUSE_GLCANVAS_EGL=ON")
else ()
set(_wx_egl "")
endif()
Expand All @@ -23,9 +23,19 @@ endif ()
# set(_patch_cmd test -f WXWIDGETS_PATCHED || ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/0001-wxWidget-fix.patch && touch WXWIDGETS_PATCHED)
# endif ()

if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Fix blank wxGLCanvas on native Wayland: reposition the EGL subsurface
# after layout and keep eglSwapBuffers() from blocking on frame callbacks
# (backport of the corresponding wxWidgets 3.2 behavior).
set(_patch_cmd PATCH_COMMAND sh -c "test -f WXWIDGETS_PATCHED || git apply --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0002-fix-wayland-egl-subsurface.patch && touch WXWIDGETS_PATCHED")
else ()
set(_patch_cmd "")
endif ()

bambustudio_add_cmake_project(wxWidgets
GIT_REPOSITORY "https://github.com/bambulab/wxWidgets"
GIT_TAG master
${_patch_cmd}
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${TIFF_PKG} ${JPEG_PKG}
CMAKE_ARGS
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
Expand Down
3 changes: 3 additions & 0 deletions linux.d/debian
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ REQUIRED_DEV_PACKAGES=(
libudev-dev
libmspack-dev
libgl1-mesa-dev
libegl-dev
libgtk-3-dev
libwayland-dev
wayland-protocols
libxkbcommon-dev
libtool
libunwind-dev
Expand Down
15 changes: 11 additions & 4 deletions src/BambuStudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1495,13 +1495,20 @@ int CLI::run(int argc, char **argv)
save_main_thread_id();

#ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on
// startup if gtk3 is used. This env var has to be set explicitly to
// instruct the window manager to fall back to X server mode.
::setenv("GDK_BACKEND", "x11", /* replace */ true);
// On Linux, default to the X11 backend (XWayland on Wayland sessions)
// for stability, but honor a user-provided GDK_BACKEND so that
// GDK_BACKEND=wayland opts into native Wayland, which the EGL-enabled
// wxWidgets build supports.
::setenv("GDK_BACKEND", "x11", /* replace */ false);

::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false);

// WebKitGTK >= 2.40 renders blank/garbled webviews with its dmabuf
// renderer on some Wayland setups (notably NVIDIA and VMs); disable it
// there unless the user overrides.
if (::getenv("WAYLAND_DISPLAY") != nullptr)
::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", /* replace */ false);

// Also on Linux, we need to tell Xlib that we will be using threads,
// lest we crash when we fire up GStreamer.
XInitThreads();
Expand Down
8 changes: 7 additions & 1 deletion src/slic3r/GUI/GCodeViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,13 @@ namespace Slic3r {
const bool b_dirty = m_b_advanced_gcode_viewer_enabled != b_advanced_gcode_viewer_enabled;
if (!m_p_renderer || b_dirty) {
if (p_ogl_manager) {
if (p_ogl_manager->init_gl()) {
// Do not force GL initialization here: this accessor can run
// during startup before the canvas GL context has ever been
// made current (e.g. on Wayland), which would compile all
// shaders into whatever foreign context is current. GL init
// is performed by the render path with the proper context
// current; until then, defer creating the renderer.
if (p_ogl_manager->is_gl_initialized()) {
const auto& gl_version = p_ogl_manager->get_gl_info().get_formated_gl_version();
if (b_advanced_gcode_viewer_enabled && gl_version >= 31) {
m_p_renderer = std::make_shared<gcode::AdvancedRenderer>();
Expand Down
8 changes: 8 additions & 0 deletions src/slic3r/GUI/GLCanvas3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,14 @@ bool GLCanvas3D::init()
// wxGetApp().plater()->enable_wireframe(false);
m_initialized = true;

// If model objects were loaded while OpenGL initialization was still
// deferred (possible on Wayland, where the GL context only becomes
// usable once the canvas is mapped), the reload_scene() calls made
// during that load were no-ops. Rebuild the scene now so those objects
// get their GLVolumes. Deferred refresh: init() runs inside render().
if (m_canvas_type != ECanvasType::CanvasPreview && m_model != nullptr && !m_model->objects.empty())
reload_scene(false, true);

return true;
}

Expand Down
9 changes: 9 additions & 0 deletions src/slic3r/GUI/GUI_App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,15 @@ void GUI_App::post_init()
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "Found glcontext not ready, postpone the init";
// The eager init above could not run, so rendering must stay
// enabled: the render path performs the same initialization
// lazily once the canvas is actually visible. Leaving it
// disabled here would keep the viewport blank for the whole
// session (on Wayland the canvas is never "shown on screen"
// during post_init, because its wl_subsurface only exists
// after the widget is mapped, which cannot happen within the
// current event-loop turn).
plater_->canvas3D()->enable_render(true);
}
//#endif
if (is_editor())
Expand Down
7 changes: 7 additions & 0 deletions src/slic3r/GUI/OpenGLManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,13 @@ bool OpenGLManager::init_gl(bool popup_error)
if (!m_gl_initialized) {
glewExperimental = GL_TRUE;
GLenum result = glewInit();
#ifdef GLEW_ERROR_NO_GLX_DISPLAY
// GLX-built GLEW reports this when there is no GLX display (native
// Wayland/EGL, or the CLI's OSMesa context). Only GLX extension entry
// points are missing; core GL is already resolved, so continue.
if (result == GLEW_ERROR_NO_GLX_DISPLAY)
result = GLEW_OK;
#endif
if (result != GLEW_OK) {
BOOST_LOG_TRIVIAL(error) << "Unable to init glew library";
return false;
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/OpenGLManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class OpenGLManager
~OpenGLManager();

bool init_gl(bool popup_error = true);
bool is_gl_initialized() const { return m_gl_initialized; }
wxGLContext* init_glcontext(wxGLCanvas& canvas);

const std::shared_ptr<GLShaderProgram>& get_shader(const std::string& shader_name) const { return m_shaders_manager.get_shader(shader_name); }
Expand Down
7 changes: 7 additions & 0 deletions src/slic3r/GUI/TextureImportDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,13 @@ void TexturePreviewCanvas::ensure_gl_ready()

glewExperimental = GL_TRUE;
GLenum err = glewInit();
#ifdef GLEW_ERROR_NO_GLX_DISPLAY
// GLX-built GLEW reports this when there is no GLX display (native
// Wayland/EGL). Only GLX extension entry points are missing; core GL is
// already resolved, so continue.
if (err == GLEW_ERROR_NO_GLX_DISPLAY)
err = GLEW_OK;
#endif
if (err != GLEW_OK) {
BOOST_LOG_TRIVIAL(error) << "TexturePreviewCanvas: glewInit failed: "
<< glewGetErrorString(err);
Expand Down