From 749bb2bfed739f4d19ae06ced02b4b8463edf1ed Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Jul 2019 11:18:19 +0200 Subject: [PATCH] Refactoring in GLTexture --- src/slic3r/GUI/3DBed.cpp | 4 +- src/slic3r/GUI/GLCanvas3D.cpp | 4 +- src/slic3r/GUI/GLTexture.cpp | 173 +++------------------- src/slic3r/GUI/GLTexture.hpp | 16 +- src/slic3r/GUI/GLToolbar.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 2 +- 6 files changed, 39 insertions(+), 162 deletions(-) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 89ad5a4ad..89b7caedf 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -418,7 +418,7 @@ void Bed3D::render_prusa(GLCanvas3D* canvas, const std::string &key, bool bottom // generate a temporary lower resolution texture to show while no main texture levels have been compressed if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != filename)) { - if (!m_temp_texture.load_from_file(filename, false, false, false, max_tex_size)) + if (!m_temp_texture.load_from_file(filename, false, GLTexture::None, false)) { render_custom(); return; @@ -426,7 +426,7 @@ void Bed3D::render_prusa(GLCanvas3D* canvas, const std::string &key, bool bottom } // starts generating the main texture, compression will run asynchronously - if (!m_texture.load_from_file(filename, true, true, true, max_tex_size)) + if (!m_texture.load_from_file(filename, true, GLTexture::MultiThreaded, true)) { render_custom(); return; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 70544cd37..b4a79c6f0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -302,7 +302,7 @@ void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas if (m_tooltip_texture.get_id() == 0) { std::string filename = resources_dir() + "/icons/variable_layer_height_tooltip.png"; - if (!m_tooltip_texture.load_from_file(filename, false, true)) + if (!m_tooltip_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false)) return; } @@ -334,7 +334,7 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co if (m_reset_texture.get_id() == 0) { std::string filename = resources_dir() + "/icons/variable_layer_height_reset.png"; - if (!m_reset_texture.load_from_file(filename, false, true)) + if (!m_reset_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false)) return; } diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 495a9864c..f3421f150 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -134,7 +134,7 @@ GLTexture::~GLTexture() reset(); } -bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bool compress) +bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy) { reset(); @@ -142,20 +142,7 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bo return false; if (boost::algorithm::iends_with(filename, ".png")) - return load_from_png(filename, use_mipmaps, compress); - else - return false; -} - -bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px) -{ - reset(); - - if (!boost::filesystem::exists(filename)) - return false; - - if (boost::algorithm::iends_with(filename, ".png")) - return load_from_png(filename, use_mipmaps, compress, apply_anisotropy, max_size_px); + return load_from_png(filename, use_mipmaps, compression_type, apply_anisotropy); else return false; } @@ -367,120 +354,9 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, glsafe(::glDisable(GL_BLEND)); } -unsigned int GLTexture::generate_mipmaps(wxImage& image, bool compress) +bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy) { - int w = image.GetWidth(); - int h = image.GetHeight(); - GLint level = 0; - std::vector data(w * h * 4, 0); - - while ((w > 1) || (h > 1)) - { - ++level; - - w = std::max(w / 2, 1); - h = std::max(h / 2, 1); - - int n_pixels = w * h; - - image = image.ResampleBicubic(w, h); - - unsigned char* img_rgb = image.GetData(); - unsigned char* img_alpha = image.GetAlpha(); - - data.resize(n_pixels * 4); - for (int i = 0; i < n_pixels; ++i) - { - int data_id = i * 4; - int img_id = i * 3; - data[data_id + 0] = img_rgb[img_id + 0]; - data[data_id + 1] = img_rgb[img_id + 1]; - data[data_id + 2] = img_rgb[img_id + 2]; - data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255; - } - - if (compress && GLEW_EXT_texture_compression_s3tc) - glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); - else - glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); - } - - return (unsigned int)level; -} - -bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, bool compress) -{ - // Load a PNG with an alpha channel. - wxImage image; - if (!image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG)) - { - reset(); - return false; - } - - m_width = image.GetWidth(); - m_height = image.GetHeight(); - int n_pixels = m_width * m_height; - - if (n_pixels <= 0) - { - reset(); - return false; - } - - // Get RGB & alpha raw data from wxImage, pack them into an array. - unsigned char* img_rgb = image.GetData(); - if (img_rgb == nullptr) - { - reset(); - return false; - } - - unsigned char* img_alpha = image.GetAlpha(); - - std::vector data(n_pixels * 4, 0); - for (int i = 0; i < n_pixels; ++i) - { - int data_id = i * 4; - int img_id = i * 3; - data[data_id + 0] = img_rgb[img_id + 0]; - data[data_id + 1] = img_rgb[img_id + 1]; - data[data_id + 2] = img_rgb[img_id + 2]; - data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255; - } - - // sends data to gpu - glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - glsafe(::glGenTextures(1, &m_id)); - glsafe(::glBindTexture(GL_TEXTURE_2D, m_id)); - if (compress && GLEW_EXT_texture_compression_s3tc) - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); - else - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); - if (use_mipmaps) - { - // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards - unsigned int levels_count = generate_mipmaps(image, compress); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels_count)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); - } - else - { - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); - } - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - - glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); - - m_source = filename; - - return true; -} - -bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px) -{ - bool compression_enabled = compress && GLEW_EXT_texture_compression_s3tc; + bool compression_enabled = (compression_type != None) && GLEW_EXT_texture_compression_s3tc; // Load a PNG with an alpha channel. wxImage image; @@ -493,18 +369,9 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo m_width = image.GetWidth(); m_height = image.GetHeight(); - unsigned int max_size = (unsigned int)std::max(m_width, m_height); bool requires_rescale = false; - if (max_size_px < max_size) - { - float scale = (float)max_size_px / (float)max_size; - m_width = (int)(scale * (float)m_width); - m_height = (int)(scale * (float)m_height); - requires_rescale = true; - } - - if (compression_enabled) + if (compression_enabled && (compression_type == MultiThreaded)) { // the stb_dxt compression library seems to like only texture sizes which are a multiple of 4 int width_rem = m_width % 4; @@ -568,10 +435,15 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo if (compression_enabled) { - // initializes the texture on GPU - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); - // and send the uncompressed data to the compressor - m_compressor.add_level((unsigned int)m_width, (unsigned int)m_height, data); + if (compression_type == SingleThreaded) + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); + else + { + // initializes the texture on GPU + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); + // and send the uncompressed data to the compressor + m_compressor.add_level((unsigned int)m_width, (unsigned int)m_height, data); + } } else glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); @@ -610,10 +482,15 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo if (compression_enabled) { - // initializes the texture on GPU - glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); - // and send the uncompressed data to the compressor - m_compressor.add_level((unsigned int)lod_w, (unsigned int)lod_h, data); + if (compression_type == SingleThreaded) + glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); + else + { + // initializes the texture on GPU + glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); + // and send the uncompressed data to the compressor + m_compressor.add_level((unsigned int)lod_w, (unsigned int)lod_h, data); + } } else glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data())); @@ -637,7 +514,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo m_source = filename; - if (compression_enabled) + if (compression_enabled && (compression_type == MultiThreaded)) // start asynchronous compression m_compressor.start_compressing(); @@ -651,7 +528,6 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f); if (image == nullptr) { -// printf("Could not open SVG image.\n"); reset(); return false; } @@ -686,7 +562,6 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo NSVGrasterizer* rast = nsvgCreateRasterizer(); if (rast == nullptr) { -// printf("Could not init rasterizer.\n"); nsvgDelete(image); reset(); return false; diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 21e01733d..7fc5b8fcf 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -48,6 +48,13 @@ namespace GUI { }; public: + enum ECompressionType : unsigned char + { + None, + SingleThreaded, + MultiThreaded + }; + struct UV { float u; @@ -75,8 +82,7 @@ namespace GUI { GLTexture(); virtual ~GLTexture(); - bool load_from_file(const std::string& filename, bool use_mipmaps, bool compress); - bool load_from_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px); + bool load_from_file(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy); bool load_from_svg_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px); // meanings of states: (std::pair) // first field (int): @@ -102,12 +108,8 @@ namespace GUI { static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top); static void render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const Quad_UVs& uvs); - protected: - unsigned int generate_mipmaps(wxImage& image, bool compress); - private: - bool load_from_png(const std::string& filename, bool use_mipmaps, bool compress); - bool load_from_png(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px); + bool load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy); bool load_from_svg(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px); friend class Compressor; diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 0002eda2d..f4748f680 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -172,7 +172,7 @@ bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture) bool res = false; if (!background_texture.filename.empty()) - res = m_background_texture.texture.load_from_file(path + background_texture.filename, false, true); + res = m_background_texture.texture.load_from_file(path + background_texture.filename, false, GLTexture::SingleThreaded, false); if (res) m_background_texture.metadata = background_texture; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index df53b40aa..1509c1328 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -43,7 +43,7 @@ bool GLGizmosManager::init() if (!m_background_texture.metadata.filename.empty()) { - if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, true)) + if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false)) { reset(); return false;