From 5e7ad1ad70ded29a3e3d2221d91e1617443b708a Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Thu, 16 Jul 2026 11:02:55 +0800 Subject: [PATCH] Fix OpenGL framebuffer object support on macOS (#14769) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix OpenGL framebuffer object support on macOS this enables the outline on macOS * Revert "Fix OpenGL framebuffer object support on macOS" This reverts commit 9872708954e785a86209613bbab7cc770d636b7a. * Enable ARB framebuffer if OpenGL >= 3.0 (OrcaSlicer/OrcaSlicer#14770) * FIX: plater toolbar image update jira: STUDIO-12457 Change-Id: Ia855b4bd9bec884d52202f5d8f5cfad9efce0f2f (cherry picked from commit 474691813b497654ef701fe7073992db366e81a9) * FIX: thumbinal regen jira: STUDIO-16732 Change-Id: I4cc4e76b36caf1a41793c1f84ee5e88a44ebdd42 (cherry picked from commit 53f33b7db260005e477842d6459b1b28aa8aa0d8) * FIX: force update thumbinal once dirty jira: STUDIO-13041 Change-Id: I770743b53c51351cb3b8a7133140974c75c05364 (cherry picked from commit 96198a12712f21d2b4521b6e3d1caff50bed21ff) * FIX:thumbnail update jira: STUDIO-13041 / STUDIO-13304 Change-Id: I9dec25f12454fc8485195cf5dc3feb421b6347c4 (cherry picked from commit cf778dc90f805d3f46e28f8f1d1d5814d3fb4d51) --------- Co-authored-by: jun.zhang --- resources/shaders/110/imgui.fs | 4 ++-- resources/shaders/140/imgui.fs | 4 ++-- src/slic3r/GUI/GLCanvas3D.cpp | 35 +++++++++++++++++------------- src/slic3r/GUI/GLCanvas3D.hpp | 1 - src/slic3r/GUI/IMToolbar.cpp | 2 -- src/slic3r/GUI/IMToolbar.hpp | 1 - src/slic3r/GUI/ImGuiWrapper.cpp | 4 ++++ src/slic3r/GUI/Jobs/FillBedJob.cpp | 2 ++ src/slic3r/GUI/OpenGLManager.cpp | 7 +++++- src/slic3r/GUI/PartPlate.cpp | 11 ++++++++++ src/slic3r/GUI/Plater.cpp | 32 ++++++++++++++++++++------- src/slic3r/GUI/Plater.hpp | 5 +++++ 12 files changed, 76 insertions(+), 32 deletions(-) diff --git a/resources/shaders/110/imgui.fs b/resources/shaders/110/imgui.fs index 4b0e27ce9d..3af9c82653 100644 --- a/resources/shaders/110/imgui.fs +++ b/resources/shaders/110/imgui.fs @@ -1,11 +1,11 @@ #version 110 -uniform sampler2D Texture; +uniform sampler2D s_texture; varying vec2 Frag_UV; varying vec4 Frag_Color; void main() { - gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st); + gl_FragColor = Frag_Color * texture2D(s_texture, Frag_UV.st); } \ No newline at end of file diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs index 1666c814eb..daebb189de 100644 --- a/resources/shaders/140/imgui.fs +++ b/resources/shaders/140/imgui.fs @@ -1,6 +1,6 @@ #version 140 -uniform sampler2D Texture; +uniform sampler2D s_texture; in vec2 Frag_UV; in vec4 Frag_Color; @@ -9,5 +9,5 @@ out vec4 out_color; void main() { - out_color = Frag_Color * texture(Texture, Frag_UV.st); + out_color = Frag_Color * texture(s_texture, Frag_UV.st); } \ No newline at end of file diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2789d0b21b..ceb09426a3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2338,11 +2338,6 @@ void GLCanvas3D::remove_curr_plate_all() m_dirty = true; } -void GLCanvas3D::update_plate_thumbnails() -{ - _update_imgui_select_plate_toolbar(); -} - void GLCanvas3D::select_all() { if (!m_gizmos.is_allow_select_all()) { @@ -3223,7 +3218,6 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) // BBS //m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state(); - _update_imgui_select_plate_toolbar(); bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); m_dirty |= mouse3d_controller_applied; m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this); @@ -4833,11 +4827,6 @@ void GLCanvas3D::force_set_focus() { void GLCanvas3D::on_set_focus(wxFocusEvent& evt) { m_tooltip_enabled = false; - if (m_canvas_type == ECanvasType::CanvasPreview) { - // update thumbnails and update plate toolbar - wxGetApp().plater()->update_all_plate_thumbnails(); - _update_imgui_select_plate_toolbar(); - } _refresh_if_shown_on_screen(); m_tooltip_enabled = true; m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style"); @@ -6920,13 +6909,28 @@ void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) { bool GLCanvas3D::_update_imgui_select_plate_toolbar() { bool result = true; - if (!m_sel_plate_toolbar.is_enabled() || m_sel_plate_toolbar.is_render_finish) return false; + if (!m_sel_plate_toolbar.is_enabled()) { + return false; + } + + const auto& p_plater = wxGetApp().plater(); + if (!p_plater) { + return false; + } + + if (!p_plater->is_plate_toolbar_image_dirty()) { + return false; + } + + if (!p_plater->is_gcode_3mf()) { + p_plater->update_all_plate_thumbnails(true); + } _update_select_plate_toolbar_stats_item(); m_sel_plate_toolbar.del_all_item(); - PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list(); + PartPlateList& plate_list = p_plater->get_partplate_list(); for (int i = 0; i < plate_list.get_plate_count(); i++) { IMToolbarItem* item = new IMToolbarItem(); PartPlate* plate = plate_list.get_plate(i); @@ -6939,7 +6943,7 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar() } m_sel_plate_toolbar.m_items.push_back(item); } - + p_plater->clear_plate_toolbar_image_dirty(); m_sel_plate_toolbar.is_display_scrollbar = false; return result; } @@ -8797,6 +8801,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() return; } + _update_imgui_select_plate_toolbar(); + IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item; PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list(); @@ -9213,7 +9219,6 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() m_sel_plate_toolbar.is_display_scrollbar = is_win_hovered; imgui.end(); - m_sel_plate_toolbar.is_render_finish = true; } //BBS: GUI refactor: GLToolbar adjust diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 4c2402c546..55e118fa4c 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -997,7 +997,6 @@ public: void select_curr_plate_all(); void select_object_from_idx(std::vector& object_idxs); void remove_curr_plate_all(); - void update_plate_thumbnails(); void select_all(); void deselect_all(); diff --git a/src/slic3r/GUI/IMToolbar.cpp b/src/slic3r/GUI/IMToolbar.cpp index 733683366f..2a569c960b 100644 --- a/src/slic3r/GUI/IMToolbar.cpp +++ b/src/slic3r/GUI/IMToolbar.cpp @@ -61,8 +61,6 @@ void IMToolbar::del_stats_item() void IMToolbar::set_enabled(bool enable) { m_enabled = enable; - if (!m_enabled) - is_render_finish = false; } bool IMReturnToolbar::init() diff --git a/src/slic3r/GUI/IMToolbar.hpp b/src/slic3r/GUI/IMToolbar.hpp index 24152f20ee..bf5bf70756 100644 --- a/src/slic3r/GUI/IMToolbar.hpp +++ b/src/slic3r/GUI/IMToolbar.hpp @@ -51,7 +51,6 @@ public: float icon_height; bool is_display_scrollbar; bool show_stats_item{ false }; - bool is_render_finish{false}; IMToolbar() { icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH; icon_height = DEFAULT_TOOLBAR_BUTTON_HEIGHT; diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index c7609be5ef..8974a169d1 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -3158,6 +3158,9 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) shader->set_uniform("Texture", 0); shader->set_uniform("ProjMtx", ortho_projection); + const uint8_t stage = 0; + shader->set_uniform("s_texture", stage); + // Will project scissor/clipping rectangles into framebuffer space const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) @@ -3222,6 +3225,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); // Bind texture, Draw + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); } diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index 711228c0bc..a9a66cb96f 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -348,6 +348,8 @@ void FillBedJob::finalize(bool canceled, std::exception_ptr &eptr) } m_plater->update(); } + + m_plater->mark_plate_toolbar_image_dirty(); } }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 2b5ebcd086..382a9176b9 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -266,7 +266,12 @@ bool OpenGLManager::init_gl(bool popup_error) else s_compressed_textures_supported = false; - if (GLAD_GL_ARB_framebuffer_object) { + if (s_gl_info.is_version_greater_or_equal_to(3, 0)) { + // ARB framebuffer became a mandatory part of core OpenGL 3.0 + s_framebuffers_type = EFramebufferType::Arb; + BOOST_LOG_TRIVIAL(info) << "Opengl version >= 30, FrameBuffer Type ARB." << std::endl; + } + else if (GLAD_GL_ARB_framebuffer_object) { s_framebuffers_type = EFramebufferType::Arb; BOOST_LOG_TRIVIAL(info) << "Found Framebuffer Type ARB."<< std::endl; } diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 1f0454c778..415e1ea0f5 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2433,6 +2433,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height m_depth = depth; m_height = height; + if (with_instance_move && m_plater) + m_plater->mark_plate_toolbar_image_dirty(); + return; } @@ -2780,6 +2783,8 @@ int PartPlate::add_instance(int obj_id, int instance_id, bool move_position, Bou } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , m_ready_for_slice changes to %2%") % m_plate_index %m_ready_for_slice; + if (m_plater) + m_plater->mark_plate_toolbar_image_dirty(); return 0; } @@ -5344,6 +5349,9 @@ int PartPlateList::notify_instance_removed(int obj_id, int instance_id) unprintable_plate.update_object_index(obj_id, m_model->objects.size()); } + if (m_plater) + m_plater->mark_plate_toolbar_image_dirty(); + return 0; } @@ -6265,6 +6273,9 @@ int PartPlateList::rebuild_plates_after_arrangement(bool recycle_plates, bool ex } #endif + if (m_plater) + m_plater->mark_plate_toolbar_image_dirty(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":after rebuild, plates count %1%") % m_plate_list.size(); return ret; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 45c3098d36..ffa4bbc5b3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -277,6 +277,21 @@ void Plater::show_illegal_characters_warning(wxWindow* parent) show_error(parent, _L("Invalid name, the following characters are not allowed:") + " <>:/\\|?*\""); } +void Plater::mark_plate_toolbar_image_dirty() +{ + m_b_plate_toolbar_image_dirty = true; +} + +bool Plater::is_plate_toolbar_image_dirty() const +{ + return m_b_plate_toolbar_image_dirty; +} + +void Plater::clear_plate_toolbar_image_dirty() +{ + m_b_plate_toolbar_image_dirty = false; +} + static std::map bed_type_thumbnails = { {BedType::btPC, "bed_cool" }, {BedType::btEP, "bed_engineering" }, @@ -6326,10 +6341,8 @@ void Plater::priv::update(unsigned int flags) //BBS assemble view this->assemble_view->reload_scene(false, flags); - if (current_panel && is_preview_shown()) { - q->force_update_all_plate_thumbnails(); - //update_fff_scene_only_shells(true); - } + // todo: better to mark thumbnail dirty here + q->mark_plate_toolbar_image_dirty(); if (force_background_processing_restart) this->restart_background_process(update_status); @@ -7884,6 +7897,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } q->schedule_background_process(true); + q->mark_plate_toolbar_image_dirty(); return obj_idxs; } @@ -8263,6 +8277,8 @@ void Plater::priv::object_list_changed() main_frame->update_slice_print_status(MainFrame::eEventObjectUpdate, can_slice); wxGetApp().params_panel()->notify_object_config_changed(); + + q->mark_plate_toolbar_image_dirty(); } void Plater::priv::select_curr_plate_all() @@ -9166,6 +9182,8 @@ void Plater::priv::update_fff_scene() view3D->reload_scene(true); //BBS: add assemble view related logic assemble_view->reload_scene(true); + + q->mark_plate_toolbar_image_dirty(); } //BBS: add print project related logic @@ -10074,9 +10092,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) preview->get_canvas3d()->enable_select_plate_toolbar(true); } } - else { - preview->get_canvas3d()->enable_select_plate_toolbar(false); - } if (current_panel == panel) { @@ -10935,6 +10950,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":finished, reload print soon"); m_is_slicing = false; this->preview->reload_print(false); + q->mark_plate_toolbar_image_dirty(); /* BBS if in publishing progress */ if (m_is_publishing) { if (m_publish_dlg && !m_publish_dlg->was_cancelled()) { @@ -14651,6 +14667,7 @@ void Plater::invalid_all_plate_thumbnails() plate->thumbnail_data.reset(); plate->no_light_thumbnail_data.reset(); } + mark_plate_toolbar_image_dirty(); } void Plater::force_update_all_plate_thumbnails() @@ -14661,7 +14678,6 @@ void Plater::force_update_all_plate_thumbnails() invalid_all_plate_thumbnails(); update_all_plate_thumbnails(true); } - get_preview_canvas3D()->update_plate_thumbnails(); } // BBS: backup diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 1730bd2705..fdba3496e0 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -936,6 +936,10 @@ public: bool is_loading_project() const { return m_loading_project; } + void mark_plate_toolbar_image_dirty(); + bool is_plate_toolbar_image_dirty() const; + void clear_plate_toolbar_image_dirty(); + private: struct priv; std::unique_ptr p; @@ -956,6 +960,7 @@ private: std::string m_preview_only_filename; int m_valid_plates_count { 0 }; int m_check_status = 0; // 0 not check, 1 check success, 2 check failed + bool m_b_plate_toolbar_image_dirty{ true }; void suppress_snapshots(); void allow_snapshots();