mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-09 11:07:34 +00:00
* Add runtime display backend detection for Wayland support Add LinuxDisplayBackend utility to detect X11 vs Wayland at runtime using GDK_IS_X11_DISPLAY / GDK_IS_WAYLAND_DISPLAY macros. This is the foundation for removing the forced GDK_BACKEND=x11 and enabling native Wayland support. - New files: LinuxDisplayBackend.hpp/.cpp with get_linux_display_backend(), is_running_on_wayland(), and is_running_on_x11() - Propagate wxHAVE_GDK_X11 / wxHAVE_GDK_WAYLAND from FindGTK3.cmake as compile definitions to libslic3r_gui - No-op on non-Linux platforms (returns Unknown / false) * Fix Phase 1 code quality: pragma once, source ordering, static cache * Make X11 initialization conditional for Wayland support Remove the unconditional GDK_BACKEND=x11 force that blocked native Wayland. Replace with conditional logic: - EGL safety fallback: re-force X11 only when wxUSE_GLCANVAS_EGL is off and WAYLAND_DISPLAY is set, with a warning log - XInitThreads() only called when DISPLAY is set (X11 in use) - __GLX_VENDOR_LIBRARY_NAME only set when DISPLAY is present (GLX-specific) - WEBKIT_DISABLE_COMPOSITING_MODE only set under XWayland (both DISPLAY and WAYLAND_DISPLAY present) - Guard X11/Xlib.h include with __has_include for robustness - Restore display validation to accept either DISPLAY or WAYLAND_DISPLAY This is Phase 2 of the Wayland support plan. * Fix Phase 2: safer EGL macro check, add clarifying comments * Add GLAD2 library and replace GLEW linkage in build system Set up GLAD2 as a static library to replace GLEW for OpenGL loading. GLAD2 supports both GLX and EGL, which is required for Wayland support. - Create src/glad/ with pre-generated GLAD2 sources (GL 4.6 compat) - Add src/glad/CMakeLists.txt building glad as a static library - Wire glad into src/CMakeLists.txt before libvgcode - Modify libvgcode to use shared glad for GL path (keeps local copy only for GLES2/Emscripten) to avoid duplicate symbol conflicts - Replace GLEW::GLEW with glad in libslic3r_gui link libraries Note: GLEW is kept in deps for OpenCSG. Code migration from GL/glew.h to glad/gl.h headers will follow in Phase 3B+3C. * Fix Phase 3A+3D: libvgcode GLAD include, dead files, dlopen dep, OpenGL link var * Migrate from GLEW to GLAD: replace headers and API calls across codebase Replace all #include <GL/glew.h> with <glad/gl.h> across 49 source files. Migrate GLEW API calls to GLAD equivalents: - glewInit/glewExperimental -> gladLoaderLoadGL() - GLEW_EXT_* / GLEW_ARB_* extension checks -> GLAD_GL_EXT_* / GLAD_GL_ARB_* - Remove GLEW-specific EGL/GLX mismatch #error guards (not needed with GLAD) - Replace unavailable EXT symbols with core GL equivalents in GLCanvas3D.cpp (GL_MAX_SAMPLES, glRenderbufferStorageMultisample, glBlitFramebuffer, GL_READ/DRAW_FRAMEBUFFER) - Update log messages from glewInit to gladLoadGL * Fix Phase 3B+3C: remove GLEW find, clean EXT symbols, update attribution - Remove find_package(GLEW) block from root CMakeLists.txt since GLEW is no longer linked by any main application code - Remove "glew" from SLIC3R_STATIC option description - Replace all remaining EXT framebuffer symbols with core equivalents in render_thumbnail_framebuffer_ext and _rectangular_selection_picking_pass - Update AboutDialog credits from GLEW to GLAD * Enable EGL in wxWidgets and add runtime GLX/EGL selection for Wayland - Set wxUSE_GLCANVAS_EGL=ON in wxWidgets build and Flatpak manifest - Add PreferGLX() call on X11 sessions for driver compatibility - Remove Phase 2 safety fallback (EGL is now always compiled in) - Guard SwapBuffers against hidden canvases to prevent Wayland stalls * Fix Phase 4: move PreferGLX to app startup, fix FPS counter guard Move wxGLCanvas::PreferGLX() from OpenGLManager::create_wxglcanvas() (static initializer) to GUI_App::on_init_inner() before any wxGLCanvas is constructed. This prevents a race where SkipPartCanvas could trigger wxGLBackend::Init() before the GLX preference is set. The new location also adds explicit is_running_on_wayland() detection with a warning for unknown backends. Move increment_fps_counter() inside the IsShownOnScreen() guard so FPS is only counted when a frame is actually swapped. * Update GLFW from 3.3.7 to 3.4 for runtime Wayland/X11 backend selection Replace the compile-time GLFW_USE_WAYLAND flag (which locked to a single backend) with GLFW 3.4's GLFW_BUILD_WAYLAND + GLFW_BUILD_X11 flags that build both backends and auto-select at runtime based on the available display server. This enables the CLI thumbnail renderer to work on both Wayland and X11 sessions without separate builds. * wayland: Fix UI call sites that rely on global screen coordinates On Wayland, wxGetMousePosition() returns (0,0) and SetPosition() is a no-op for top-level windows. Fix the highest-impact call sites: - GLCanvas3D: Use cached m_mouse.position from event handlers instead of wxGetMousePosition() + ScreenToClient() in get_local_mouse_position() - Plater: Use event-relative coords via ClientToScreen(e.GetPosition()) instead of wxGetMousePosition() in 3 leave-window handlers - BBLTopbar: Use event.GetPosition() and FindToolByPosition() directly in mouse handlers instead of wxGetMousePosition()/FindToolByCurrentPosition() - Search: Use focus-based dismiss logic on Wayland instead of wxGetMousePosition()-based rect checks in SearchDialog and SearchObjectDialog - GUI_App: Skip SetPosition() in window_pos_restore() on Wayland where it is a no-op; still restore size and maximize state - Button: Position tooltip relative to button widget via ClientToScreen instead of wxGetMousePosition() * Fix SearchDialog Wayland dismiss: guard against search_line focus * flatpak: Add Wayland socket permission for native Wayland support * spec * Fix crash on Wayland when wxWidgets lacks EGL support Restore the safety fallback that forces GDK_BACKEND=x11 when wxWidgets was not built with wxUSE_GLCANVAS_EGL=ON. Without this, the GLX backend tries to access a non-existent X11 display on native Wayland, crashing in wxGLCanvas::IsDisplaySupported() with SIGSEGV at offset 0xe4. Also add a defense-in-depth guard in detect_multisample() that skips the IsDisplaySupported call entirely on Wayland without EGL. Root cause: deps/wxWidgets must be rebuilt after enabling EGL. The compile-time check in OrcaSlicer.cpp detects the mismatch and falls back safely. * Fix EGL detection: use wxHAS_EGL instead of wxUSE_GLCANVAS_EGL wxUSE_GLCANVAS_EGL is a CMake build option, NOT a C++ preprocessor macro. The actual macro defined in wxWidgets setup.h is wxHAS_EGL. All compile-time EGL checks were using the wrong macro, causing the safety fallback to always trigger even with a properly built EGL-enabled wxWidgets. * Fix GL function pointers invalidated on Wayland/EGL gladLoaderLoadGL() dlopen's libGL.so.1 to resolve GL function pointers via dlsym, then immediately dlclose's the handle. On X11/GLX this is fine because the GLX context keeps libGL.so mapped. On Wayland/EGL, nothing else holds libGL.so open, so dlclose unmaps it and all function pointers become dangling — causing SIGSEGV on the first GL call. Fix: on Wayland, use gladLoadGL(eglGetProcAddress) which resolves function pointers through the EGL loader without opening/closing libGL.so. * fix crash on start and various rendering issues * fix crash on close * small refactor * move GPU selection to desktop file * clean up a bit * clean up more * fix appimage error
322 lines
11 KiB
C++
322 lines
11 KiB
C++
#ifndef slic3r_EmbossStyleManager_hpp_
|
|
#define slic3r_EmbossStyleManager_hpp_
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <functional>
|
|
#include <imgui/imgui.h>
|
|
#include <wx/font.h>
|
|
#include <glad/gl.h>
|
|
#include <libslic3r/BoundingBox.hpp>
|
|
#include <libslic3r/Emboss.hpp>
|
|
#include <libslic3r/TextConfiguration.hpp>
|
|
#include <libslic3r/EmbossShape.hpp>
|
|
#include <libslic3r/AppConfig.hpp>
|
|
|
|
namespace Slic3r::GUI::Emboss {
|
|
/// <summary>
|
|
/// Manage Emboss text styles
|
|
/// Cache actual state of style
|
|
/// + imgui font
|
|
/// + wx font
|
|
/// </summary>
|
|
class StyleManager
|
|
{
|
|
friend class CreateFontStyleImagesJob; // access to StyleImagesData
|
|
public:
|
|
/// <param name="language_glyph_range">Character to load for imgui when initialize imgui font</param>
|
|
/// <param name="create_default_styles">Function to create default styles</param>
|
|
StyleManager(const ImWchar *language_glyph_range, const std::function<EmbossStyles()>& create_default_styles);
|
|
|
|
/// <summary>
|
|
/// Release imgui font and style images from GPU
|
|
/// </summary>
|
|
~StyleManager();
|
|
|
|
/// <summary>
|
|
/// Load font style list from config
|
|
/// Also select actual activ font
|
|
/// </summary>
|
|
/// <param name="app_config">Application configuration loaded from file "PrusaSlicer.ini"
|
|
/// + cfg is stored to privat variable</param>
|
|
void init(AppConfig *app_config);
|
|
|
|
/// <summary>
|
|
/// Write font list into AppConfig
|
|
/// </summary>
|
|
/// <param name="item_to_store">Configuration</param>
|
|
/// <param name="use_modification">When true cache state will be used for store</param>
|
|
/// <param name="use_modification">When true store activ index into configuration</param>
|
|
/// <returns>True on succes otherwise False.</returns>
|
|
bool store_styles_to_app_config(bool use_modification = true, bool store_active_index = true);
|
|
|
|
/// <summary>
|
|
/// Append actual style to style list
|
|
/// </summary>
|
|
/// <param name="name">New name for style</param>
|
|
void add_style(const std::string& name);
|
|
|
|
/// <summary>
|
|
/// Change order of style item in m_styles.
|
|
/// Fix selected font index when (i1 || i2) == m_font_selected
|
|
/// </summary>
|
|
/// <param name="i1">First index to m_styles</param>
|
|
/// <param name="i2">Second index to m_styles</param>
|
|
void swap(size_t i1, size_t i2);
|
|
|
|
/// <summary>
|
|
/// Discard changes in activ style
|
|
/// When no activ style use last used OR first loadable
|
|
/// </summary>
|
|
void discard_style_changes();
|
|
|
|
/// <summary>
|
|
/// Remove style from m_styles.
|
|
/// Fix selected font index when index is under m_font_selected
|
|
/// </summary>
|
|
/// <param name="index">Index of style to be removed</param>
|
|
void erase(size_t index);
|
|
|
|
/// <summary>
|
|
/// Rename actual selected font item
|
|
/// </summary>
|
|
/// <param name="name">New name</param>
|
|
void rename(const std::string &name);
|
|
|
|
/// <summary>
|
|
/// load some valid style
|
|
/// </summary>
|
|
void load_valid_style();
|
|
|
|
/// <summary>
|
|
/// Change active font
|
|
/// When font not loaded roll back activ font
|
|
/// </summary>
|
|
/// <param name="font_index">New font index(from m_styles range)</param>
|
|
/// <returns>True on succes. False on fail load font</returns>
|
|
bool load_style(size_t font_index);
|
|
// load font style not stored in list
|
|
struct Style;
|
|
bool load_style(const Style &style);
|
|
// fastering load font on index by wxFont, ignore type and descriptor
|
|
bool load_style(const Style &style, const wxFont &font);
|
|
|
|
// clear actual selected glyphs cache
|
|
void clear_glyphs_cache();
|
|
|
|
// remove cached imgui font for actual selected font
|
|
void clear_imgui_font();
|
|
|
|
// getters for private data
|
|
const Style *get_stored_style() const;
|
|
|
|
const Style &get_style() const { return m_style_cache.style; }
|
|
Style &get_style() { return m_style_cache.style; }
|
|
size_t get_style_index() const { return m_style_cache.style_index; }
|
|
std::string &get_truncated_name() { return m_style_cache.truncated_name; }
|
|
const ImFontAtlas &get_atlas() const { return m_style_cache.atlas; }
|
|
const FontProp &get_font_prop() const { return get_style().prop; }
|
|
FontProp &get_font_prop() { return get_style().prop; }
|
|
const wxFont &get_wx_font() const { return m_style_cache.wx_font; }
|
|
const wxFont &get_stored_wx_font() const { return m_style_cache.stored_wx_font; }
|
|
Slic3r::Emboss::FontFileWithCache &get_font_file_with_cache() { return m_style_cache.font_file; }
|
|
bool has_collections() const { return m_style_cache.font_file.font_file != nullptr &&
|
|
m_style_cache.font_file.font_file->infos.size() > 1; }
|
|
|
|
// True when activ style has same name as some of stored style
|
|
bool exist_stored_style() const { return m_style_cache.style_index != std::numeric_limits<size_t>::max(); }
|
|
|
|
/// <summary>
|
|
/// check whether current style differ to selected
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
bool is_font_changed() const;
|
|
|
|
bool is_unique_style_name(const std::string &name) const;
|
|
|
|
/// <summary>
|
|
/// Setter on wx_font when changed
|
|
/// </summary>
|
|
/// <param name="wx_font">new wx font</param>
|
|
/// <returns>True on success set otherwise FALSE</returns>
|
|
bool set_wx_font(const wxFont &wx_font);
|
|
|
|
/// <summary>
|
|
/// Faster way of set wx_font when font file is known(do not load font file twice)
|
|
/// When you not sure that wx_font is made by font_file use only set_wx_font(wx_font)
|
|
/// </summary>
|
|
/// <param name="wx_font">Must be source of font file</param>
|
|
/// <param name="font_file">font file created by WxFontUtils::create_font_file(wx_font)</param>
|
|
/// <returns>True on success otherwise false</returns>
|
|
bool set_wx_font(const wxFont &wx_font, std::unique_ptr<Slic3r::Emboss::FontFile> font_file);
|
|
|
|
// Getter on acitve font pointer for imgui
|
|
// Initialize imgui font(generate texture) when doesn't exist yet.
|
|
// Extend font atlas when not in glyph range
|
|
ImFont *get_imgui_font();
|
|
// initialize font range by unique symbols in text
|
|
ImFont *create_imgui_font(const std::string& text, double scale);
|
|
|
|
// init truncated names of styles
|
|
void init_trunc_names(float max_width);
|
|
|
|
/// <summary>
|
|
/// Initialization texture with rendered font style
|
|
/// </summary>
|
|
/// <param name="max_size">Maximal width and height of one style texture</param>
|
|
/// <param name="text">Text to render by style</param>
|
|
void init_style_images(const Vec2i32& max_size, const std::string &text);
|
|
void free_style_images();
|
|
|
|
// access to all managed font styles
|
|
const std::vector<Style> &get_styles() const;
|
|
|
|
/// <summary>
|
|
/// Describe image in GPU to show settings of style
|
|
/// </summary>
|
|
struct StyleImage
|
|
{
|
|
void* texture_id = nullptr; // GLuint
|
|
BoundingBox bounding_box;
|
|
ImVec2 tex_size;
|
|
ImVec2 uv0;
|
|
ImVec2 uv1;
|
|
Point offset = Point(0, 0);
|
|
};
|
|
|
|
/// <summary>
|
|
/// All connected with one style
|
|
/// keep temporary data and caches for style
|
|
/// </summary>
|
|
struct Style : public EmbossStyle
|
|
{
|
|
// Define how to emboss shape
|
|
EmbossProjection projection;
|
|
|
|
// distance from surface point
|
|
// used for move over model surface
|
|
// When not set value is zero and is not stored
|
|
std::optional<float> distance; // [in mm]
|
|
|
|
// Angle of rotation around emboss direction (Z axis)
|
|
// It is calculate on the fly from volume world transformation
|
|
// only StyleManager keep actual value for comparision with style
|
|
// When not set value is zero and is not stored
|
|
std::optional<float> angle; // [in radians] form -Pi to Pi
|
|
|
|
bool operator==(const Style &other) const
|
|
{
|
|
return EmbossStyle::operator==(other) &&
|
|
projection == other.projection &&
|
|
distance == other.distance &&
|
|
angle == other.angle;
|
|
}
|
|
|
|
// cache for view font name with maximal width in imgui
|
|
std::string truncated_name;
|
|
|
|
// visualization of style
|
|
std::optional<StyleImage> image;
|
|
};
|
|
using Styles = std::vector<Style>;
|
|
|
|
// check if exist selected font style in manager
|
|
bool is_active_font();
|
|
|
|
// Limits for imgui loaded font size
|
|
// Value out of limits is crop
|
|
static float min_imgui_font_size;
|
|
static float max_imgui_font_size;
|
|
static float get_imgui_font_size(const FontProp &prop, const Slic3r::Emboss::FontFile &file, double scale);
|
|
|
|
private:
|
|
// function to create default style list
|
|
std::function<EmbossStyles()> m_create_default_styles;
|
|
// keep language dependent glyph range
|
|
const ImWchar *m_imgui_init_glyph_range;
|
|
|
|
/// <summary>
|
|
/// Cache data from style to reduce amount of:
|
|
/// 1) loading font from file
|
|
/// 2) Create atlas of symbols for imgui
|
|
/// 3) Keep loaded(and modified by style) glyphs from font
|
|
/// </summary>
|
|
struct StyleCache
|
|
{
|
|
// share font file data with emboss job thread
|
|
Slic3r::Emboss::FontFileWithCache font_file = {};
|
|
|
|
// must live same as imgui_font inside of atlas
|
|
ImVector<ImWchar> ranges = {};
|
|
|
|
// Keep only actual style in atlas
|
|
ImFontAtlas atlas = {};
|
|
|
|
// wx widget font
|
|
wxFont wx_font = {};
|
|
|
|
// cache for view font name with maximal width in imgui
|
|
std::string truncated_name;
|
|
|
|
// actual used font item
|
|
Style style = {};
|
|
|
|
// cache for stored wx font to not create every frame
|
|
wxFont stored_wx_font = {};
|
|
|
|
// index into m_styles
|
|
size_t style_index = std::numeric_limits<size_t>::max();
|
|
|
|
} m_style_cache;
|
|
|
|
// Privat member
|
|
Styles m_styles;
|
|
AppConfig *m_app_config = nullptr;
|
|
size_t m_last_style_index = std::numeric_limits<size_t>::max();
|
|
|
|
/// <summary>
|
|
/// Keep data needed to create Font Style Images in Job
|
|
/// </summary>
|
|
struct StyleImagesData
|
|
{
|
|
struct Item
|
|
{
|
|
Slic3r::Emboss::FontFileWithCache font;
|
|
std::string text;
|
|
FontProp prop;
|
|
};
|
|
using Items = std::vector<Item>;
|
|
|
|
// Keep styles to render
|
|
Items styles;
|
|
// Maximal width and height in pixels of image
|
|
Vec2i32 max_size;
|
|
// Text to render
|
|
std::string text;
|
|
|
|
/// <summary>
|
|
/// Result of job
|
|
/// </summary>
|
|
struct StyleImages
|
|
{
|
|
// vector of inputs
|
|
StyleImagesData::Items styles;
|
|
// job output
|
|
std::vector<StyleImage> images;
|
|
};
|
|
|
|
// place to store result in main thread in Finalize
|
|
std::shared_ptr<StyleImages> result;
|
|
|
|
// pixel per milimeter (scaled DPI)
|
|
double ppm;
|
|
};
|
|
std::shared_ptr<StyleImagesData::StyleImages> m_temp_style_images = nullptr;
|
|
bool m_exist_style_images = false;
|
|
};
|
|
|
|
} // namespace Slic3r
|
|
|
|
#endif // slic3r_EmbossStyleManager_hpp_
|