ENH:optimize mem usage of imgui fonts loading

Change-Id: Icdd88b119c4406c407a955240698da5187f8efd8
This commit is contained in:
liz.li 2022-12-05 09:45:48 +08:00 committed by Lane.Wei
parent 41fcf8eb1e
commit 316ca3f5f5
4 changed files with 84 additions and 41 deletions

View file

@ -138,7 +138,7 @@ void GLGizmoText::pop_combo_style()
// BBS // BBS
void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
{ {
static std::vector<std::string> m_avail_font_names = wxGetApp().imgui()->get_fonts_names(); std::vector<std::string> m_avail_font_names = wxGetApp().imgui()->get_fonts_names();
const float win_h = ImGui::GetWindowHeight(); const float win_h = ImGui::GetWindowHeight();
y = std::min(y, bottom_limit - win_h); y = std::min(y, bottom_limit - win_h);

View file

@ -1484,6 +1484,9 @@ bool GLGizmosManager::activate_gizmo(EType type)
GLGizmoBase* new_gizmo = type == Undefined ? nullptr : m_gizmos[type].get(); GLGizmoBase* new_gizmo = type == Undefined ? nullptr : m_gizmos[type].get();
if (old_gizmo) { if (old_gizmo) {
if (m_current == Text) {
wxGetApp().imgui()->destroy_fonts_texture();
}
old_gizmo->set_state(GLGizmoBase::Off); old_gizmo->set_state(GLGizmoBase::Off);
if (old_gizmo->get_state() != GLGizmoBase::Off) if (old_gizmo->get_state() != GLGizmoBase::Off)
return false; // gizmo refused to be turned off, do nothing. return false; // gizmo refused to be turned off, do nothing.
@ -1503,8 +1506,12 @@ bool GLGizmosManager::activate_gizmo(EType type)
m_current = type; m_current = type;
if (new_gizmo) if (new_gizmo) {
if (m_current == Text) {
wxGetApp().imgui()->load_fonts_texture();
}
new_gizmo->set_state(GLGizmoBase::On); new_gizmo->set_state(GLGizmoBase::On);
}
return true; return true;
} }

View file

@ -304,6 +304,7 @@ ImGuiWrapper::ImGuiWrapper()
ImGuiWrapper::~ImGuiWrapper() ImGuiWrapper::~ImGuiWrapper()
{ {
destroy_fonts_texture();
destroy_font(); destroy_font();
ImGui::DestroyContext(); ImGui::DestroyContext();
} }
@ -381,6 +382,7 @@ void ImGuiWrapper::set_language(const std::string &language)
if (ranges != m_glyph_ranges) { if (ranges != m_glyph_ranges) {
m_glyph_ranges = ranges; m_glyph_ranges = ranges;
destroy_fonts_texture();
destroy_font(); destroy_font();
} }
@ -408,6 +410,7 @@ void ImGuiWrapper::set_scaling(float font_size, float scale_style, float scale_b
ImGui::GetStyle().ScaleAllSizes(scale_style / m_style_scaling); ImGui::GetStyle().ScaleAllSizes(scale_style / m_style_scaling);
m_style_scaling = scale_style; m_style_scaling = scale_style;
destroy_fonts_texture();
destroy_font(); destroy_font();
} }
@ -1908,29 +1911,6 @@ void ImGuiWrapper::init_font(bool compress)
if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); } if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); }
} }
// Add System Font
builder.Clear();
builder.AddRanges(m_glyph_basic_ranges);
builder.BuildRanges(&basic_ranges);
std::map<std::string, std::string> sys_fonts_map = get_occt_fonts_maps(); //map<font name, font path>
im_fonts_map.clear(); //map<font name, ImFont*>
BOOST_LOG_TRIVIAL(info) << "init_im_font start";
for (auto sys_font : sys_fonts_map) {
boost::filesystem::path font_path(sys_font.second);
if (!boost::filesystem::exists(font_path)) {
BOOST_LOG_TRIVIAL(trace) << "load font = " << sys_font.first << ", path = " << font_path << " is not exists";
continue;
}
ImFont* im_font = io.Fonts->AddFontFromFileTTF(sys_font.second.c_str(), m_font_size, &cfg, basic_ranges.Data);
if (im_font == nullptr) {
BOOST_LOG_TRIVIAL(trace) << "load font = " << sys_font.first << " failed, path = " << font_path << " is not exists";
continue;
}
im_fonts_map.insert({ sys_font.first, im_font });
}
BOOST_LOG_TRIVIAL(info) << "init_im_font end";
#ifdef __APPLE__ #ifdef __APPLE__
ImFontConfig config; ImFontConfig config;
config.MergeMode = true; config.MergeMode = true;
@ -1957,7 +1937,7 @@ void ImGuiWrapper::init_font(bool compress)
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
BOOST_LOG_TRIVIAL(trace) << "Build texture done. width: " << width << ", height: " << height; BOOST_LOG_TRIVIAL(trace) << "Build default font texture done. width: " << width << ", height: " << height;
// Fill rectangles from the SVG-icons // Fill rectangles from the SVG-icons
for (auto icon : font_icons) { for (auto icon : font_icons) {
@ -2007,21 +1987,6 @@ void ImGuiWrapper::init_font(bool compress)
rect_id++; rect_id++;
} }
if (m_fonts_names.size() == 0) {
std::vector<std::string> to_delete_fonts;
for (auto im_font : im_fonts_map) {
if (im_font.second->Glyphs.Size < 4) {
to_delete_fonts.push_back(im_font.first);
}
}
for (auto to_delete_font : to_delete_fonts) {
sys_fonts_map.erase(to_delete_font);
im_fonts_map.erase(to_delete_font);
}
for (auto im_font : im_fonts_map)
m_fonts_names.push_back(im_font.first);
}
// Upload texture to graphics system // Upload texture to graphics system
GLint last_texture; GLint last_texture;
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
@ -2042,6 +2007,66 @@ void ImGuiWrapper::init_font(bool compress)
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture)); glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
} }
void ImGuiWrapper::load_fonts_texture()
{
if (m_font_another_texture == 0) {
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
ImFontConfig cfg = ImFontConfig();
cfg.OversampleH = cfg.OversampleV = 1;
std::map<std::string, std::string> sys_fonts_map = get_occt_fonts_maps(); // map<font name, font path>
im_fonts_map.clear(); // map<font name, ImFont*>
BOOST_LOG_TRIVIAL(info) << "init_im_font start";
for (auto sys_font : sys_fonts_map) {
boost::filesystem::path font_path(sys_font.second);
if (!boost::filesystem::exists(font_path)) {
BOOST_LOG_TRIVIAL(trace) << "load font = " << sys_font.first << ", path = " << font_path << " is not exists";
continue;
}
ImFont* im_font = io.Fonts->AddFontFromFileTTF(sys_font.second.c_str(), m_font_size, &cfg, ImGui::GetIO().Fonts->GetGlyphRangesBasic());
if (im_font == nullptr) {
BOOST_LOG_TRIVIAL(trace) << "load font = " << sys_font.first << " failed, path = " << font_path << " is not exists";
continue;
}
im_fonts_map.insert({ sys_font.first, im_font });
}
BOOST_LOG_TRIVIAL(info) << "init_im_font end";
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
BOOST_LOG_TRIVIAL(trace) << "Build system fonts texture done. width: " << width << ", height: " << height;
if (m_fonts_names.size() == 0) {
std::vector<std::string> to_delete_fonts;
for (auto im_font : im_fonts_map) {
if (im_font.second->Glyphs.Size < 4) { to_delete_fonts.push_back(im_font.first); }
}
for (auto to_delete_font : to_delete_fonts) {
sys_fonts_map.erase(to_delete_font);
im_fonts_map.erase(to_delete_font);
}
for (auto im_font : im_fonts_map) m_fonts_names.push_back(im_font.first);
}
GLint last_texture;
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
glsafe(::glGenTextures(1, &(m_font_another_texture)));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_font_another_texture));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)m_font_another_texture;
// Restore state
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
}
}
void ImGuiWrapper::init_input() void ImGuiWrapper::init_input()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -2248,6 +2273,14 @@ void ImGuiWrapper::destroy_font()
} }
} }
void ImGuiWrapper::destroy_fonts_texture() {
if (m_font_another_texture != 0) {
init_font(true);
glsafe(::glDeleteTextures(1, &m_font_another_texture));
m_font_another_texture = 0;
}
}
const char* ImGuiWrapper::clipboard_get(void* user_data) const char* ImGuiWrapper::clipboard_get(void* user_data)
{ {
ImGuiWrapper *self = reinterpret_cast<ImGuiWrapper*>(user_data); ImGuiWrapper *self = reinterpret_cast<ImGuiWrapper*>(user_data);

View file

@ -50,6 +50,7 @@ class ImGuiWrapper
bool m_font_cjk{ false }; bool m_font_cjk{ false };
float m_font_size{ 18.0 }; float m_font_size{ 18.0 };
unsigned m_font_texture{ 0 }; unsigned m_font_texture{ 0 };
unsigned m_font_another_texture{ 0 };
float m_style_scaling{ 1.0 }; float m_style_scaling{ 1.0 };
unsigned m_mouse_buttons{ 0 }; unsigned m_mouse_buttons{ 0 };
bool m_disabled{ false }; bool m_disabled{ false };
@ -160,6 +161,8 @@ public:
const std::vector<std::string> get_fonts_names() const { return m_fonts_names; } const std::vector<std::string> get_fonts_names() const { return m_fonts_names; }
bool push_font_by_name(std::string font_name); bool push_font_by_name(std::string font_name);
bool pop_font_by_name(std::string font_name); bool pop_font_by_name(std::string font_name);
void load_fonts_texture();
void destroy_fonts_texture();
void disabled_begin(bool disabled); void disabled_begin(bool disabled);
void disabled_end(); void disabled_end();