diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 0bf984b1b..e57196554 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -12,7 +12,7 @@
 // Renders a small sphere in the center of the bounding box of the current selection when no gizmo is active
 #define ENABLE_RENDER_SELECTION_CENTER 0
 // Shows an imgui dialog with render related data
-#define ENABLE_RENDER_STATISTICS 0
+#define ENABLE_RENDER_STATISTICS 1
 
 
 //====================
@@ -47,7 +47,10 @@
 
 
 // Enable saving textures on GPU in compressed format 
-#define ENABLE_COMPRESSED_TEXTURES 0
+#define ENABLE_COMPRESSED_TEXTURES 1
+
+// Enable texture max size to be dependent on detected OpenGL version
+#define ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION 1
 
 // Enable scale object to fit print volume
 #define ENABLE_SCALE_TO_FIT_PRINT_VOLUME 1
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index 8392e534a..2f20a65d9 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -493,6 +493,13 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
 
     std::string model_path = resources_dir() + "/models/" + key;
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    // use anisotropic filter if graphic card allows
+    GLfloat max_anisotropy = GLCanvas3DManager::get_gl_info().get_max_anisotropy();
+
+    // use higher resolution images if graphic card and opengl version allow
+    GLint max_tex_size = GLCanvas3DManager::get_gl_info().get_max_tex_size();
+#else
     // use anisotropic filter if graphic card allows
     GLfloat max_anisotropy = 0.0f;
     if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
@@ -504,6 +511,7 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
 
     // clamp or the texture generation becomes too slow
     max_tex_size = std::min(max_tex_size, 8192);
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
     std::string filename = tex_path + ".svg";
 
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 59480de1c..37e022329 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -2026,7 +2026,11 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
 
 std::string _3DScene::get_gl_info(bool format_as_html, bool extensions)
 {
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    return Slic3r::GUI::GLCanvas3DManager::get_gl_info().to_string(format_as_html, extensions);
+#else
     return s_canvas_mgr.get_gl_info(format_as_html, extensions);
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 }
 
 bool _3DScene::add_canvas(wxGLCanvas* canvas, GUI::Bed3D& bed, GUI::Camera& camera, GUI::GLToolbar& view_toolbar)
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index bac3a3c64..0630e4265 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1714,8 +1714,13 @@ void GLCanvas3D::render()
     ImGui::Separator();
     imgui.text("Textures: ");
     ImGui::SameLine();
-    imgui.text(GLCanvas3DManager::are_compressed_textures_supported() ? "Compressed" : "Uncompressed");
+    imgui.text(GLCanvas3DManager::are_compressed_textures_supported() ? "compressed" : "uncompressed");
 #endif // ENABLE_COMPRESSED_TEXTURES
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    imgui.text("Max texture size: ");
+    ImGui::SameLine();
+    imgui.text(std::to_string(GLCanvas3DManager::get_gl_info().get_max_tex_size()));
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
     imgui.end();
 #endif // ENABLE_RENDER_STATISTICS
 
diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp
index 5f4391a5e..d213990ba 100644
--- a/src/slic3r/GUI/GLCanvas3DManager.cpp
+++ b/src/slic3r/GUI/GLCanvas3DManager.cpp
@@ -15,17 +15,115 @@
 #include <string>
 #include <iostream>
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+#ifdef __APPLE__
+#include "../Utils/MacDarkMode.hpp"
+#endif // __APPLE__
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+
 namespace Slic3r {
 namespace GUI {
 
 GLCanvas3DManager::GLInfo::GLInfo()
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    : m_detected(false)
+    , m_version("")
+    , m_glsl_version("")
+    , m_vendor("")
+    , m_renderer("")
+    , m_max_tex_size(0)
+    , m_max_anisotropy(0.0f)
+#else
     : version("")
     , glsl_version("")
     , vendor("")
     , renderer("")
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 {
 }
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+const std::string& GLCanvas3DManager::GLInfo::get_version() const
+{
+    if (!m_detected)
+        detect();
+
+    return m_version;
+}
+
+const std::string& GLCanvas3DManager::GLInfo::get_glsl_version() const
+{
+    if (!m_detected)
+        detect();
+
+    return m_glsl_version;
+}
+
+const std::string& GLCanvas3DManager::GLInfo::get_vendor() const
+{
+    if (!m_detected)
+        detect();
+
+    return m_vendor;
+}
+
+const std::string& GLCanvas3DManager::GLInfo::get_renderer() const
+{
+    if (!m_detected)
+        detect();
+
+    return m_renderer;
+}
+
+int GLCanvas3DManager::GLInfo::get_max_tex_size() const
+{
+    if (!m_detected)
+        detect();
+
+    // clamp to avoid the texture generation become too slow and use too much GPU memory
+#ifdef __APPLE__
+    // and use smaller texture for non retina systems
+    return (Slic3r::GUI::mac_max_scaling_factor() > 1.0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
+#else
+    // and use smaller texture for older OpenGL versions
+    return is_version_greater_or_equal_to(3, 0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
+#endif // __APPLE__
+}
+
+float GLCanvas3DManager::GLInfo::get_max_anisotropy() const
+{
+    if (!m_detected)
+        detect();
+
+    return m_max_anisotropy;
+}
+
+void GLCanvas3DManager::GLInfo::detect() const
+{
+    const char* data = (const char*)::glGetString(GL_VERSION);
+    if (data != nullptr)
+        m_version = data;
+
+    data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
+    if (data != nullptr)
+        m_glsl_version = data;
+
+    data = (const char*)::glGetString(GL_VENDOR);
+    if (data != nullptr)
+        m_vendor = data;
+
+    data = (const char*)::glGetString(GL_RENDERER);
+    if (data != nullptr)
+        m_renderer = data;
+
+    glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_tex_size));
+    
+    if (GLEW_EXT_texture_filter_anisotropic)
+        glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));
+
+    m_detected = true;
+}
+#else
 void GLCanvas3DManager::GLInfo::detect()
 {
     const char* data = (const char*)::glGetString(GL_VERSION);
@@ -44,7 +142,40 @@ void GLCanvas3DManager::GLInfo::detect()
     if (data != nullptr)
         renderer = data;
 }
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
+{
+    if (!m_detected)
+        detect();
+
+    std::vector<std::string> tokens;
+    boost::split(tokens, m_version, boost::is_any_of(" "), boost::token_compress_on);
+
+    if (tokens.empty())
+        return false;
+
+    std::vector<std::string> numbers;
+    boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
+
+    unsigned int gl_major = 0;
+    unsigned int gl_minor = 0;
+
+    if (numbers.size() > 0)
+        gl_major = ::atoi(numbers[0].c_str());
+
+    if (numbers.size() > 1)
+        gl_minor = ::atoi(numbers[1].c_str());
+
+    if (gl_major < major)
+        return false;
+    else if (gl_major > major)
+        return true;
+    else
+        return gl_minor >= minor;
+}
+#else
 bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
 {
     std::vector<std::string> tokens;
@@ -72,9 +203,15 @@ bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int majo
     else
         return gl_minor >= minor;
 }
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
 std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
 {
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    if (!m_detected)
+        detect();
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+
     std::stringstream out;
 
     std::string h2_start = format_as_html ? "<b>" : "";
@@ -84,10 +221,17 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
     std::string line_end = format_as_html ? "<br>" : "\n";
 
     out << h2_start << "OpenGL installation" << h2_end << line_end;
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    out << b_start << "GL version:   " << b_end << (m_version.empty() ? "N/A" : m_version) << line_end;
+    out << b_start << "Vendor:       " << b_end << (m_vendor.empty() ? "N/A" : m_vendor) << line_end;
+    out << b_start << "Renderer:     " << b_end << (m_renderer.empty() ? "N/A" : m_renderer) << line_end;
+    out << b_start << "GLSL version: " << b_end << (m_glsl_version.empty() ? "N/A" : m_glsl_version) << line_end;
+#else
     out << b_start << "GL version:   " << b_end << (version.empty() ? "N/A" : version) << line_end;
     out << b_start << "Vendor:       " << b_end << (vendor.empty() ? "N/A" : vendor) << line_end;
     out << b_start << "Renderer:     " << b_end << (renderer.empty() ? "N/A" : renderer) << line_end;
     out << b_start << "GLSL version: " << b_end << (glsl_version.empty() ? "N/A" : glsl_version) << line_end;
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
     if (extensions)
     {
@@ -114,6 +258,9 @@ GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas
 #if ENABLE_COMPRESSED_TEXTURES
 bool GLCanvas3DManager::s_compressed_textures_supported = false;
 #endif // ENABLE_COMPRESSED_TEXTURES
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
 GLCanvas3DManager::GLCanvas3DManager()
     : m_context(nullptr)
@@ -193,10 +340,16 @@ void GLCanvas3DManager::init_gl()
     if (!m_gl_initialized)
     {
         glewInit();
+#if !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
         m_gl_info.detect();
+#endif // !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
         const AppConfig* config = GUI::get_app_config();
         m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1");
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+        m_use_VBOs = !m_use_legacy_opengl && s_gl_info.is_version_greater_or_equal_to(2, 0);
+#else
         m_use_VBOs = !m_use_legacy_opengl && m_gl_info.is_version_greater_or_equal_to(2, 0);
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
         m_gl_initialized = true;
 #if ENABLE_COMPRESSED_TEXTURES
         if (GLEW_EXT_texture_compression_s3tc)
@@ -207,10 +360,12 @@ void GLCanvas3DManager::init_gl()
     }
 }
 
+#if !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 std::string GLCanvas3DManager::get_gl_info(bool format_as_html, bool extensions) const
 {
     return m_gl_info.to_string(format_as_html, extensions);
 }
+#endif // !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
 bool GLCanvas3DManager::init(wxGLCanvas* canvas)
 {
diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp
index d391cd60c..3ad30411c 100644
--- a/src/slic3r/GUI/GLCanvas3DManager.hpp
+++ b/src/slic3r/GUI/GLCanvas3DManager.hpp
@@ -29,6 +29,39 @@ struct Camera;
 
 class GLCanvas3DManager
 {
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+public:
+    class GLInfo
+    {
+        mutable bool m_detected;
+
+        mutable std::string m_version;
+        mutable std::string m_glsl_version;
+        mutable std::string m_vendor;
+        mutable std::string m_renderer;
+
+        mutable int m_max_tex_size;
+        mutable float m_max_anisotropy;
+
+    public:
+        GLInfo();
+
+        const std::string& get_version() const;
+        const std::string& get_glsl_version() const;
+        const std::string& get_vendor() const;
+        const std::string& get_renderer() const;
+
+        int get_max_tex_size() const;
+        float get_max_anisotropy() const;
+
+        bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const;
+
+        std::string to_string(bool format_as_html, bool extensions) const;
+
+    private:
+        void detect() const;
+    };
+#else
     struct GLInfo
     {
         std::string version;
@@ -43,7 +76,11 @@ class GLCanvas3DManager
 
         std::string to_string(bool format_as_html, bool extensions) const;
     };
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+private:
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
     enum EMultisampleState : unsigned char
     {
         MS_Unknown,
@@ -55,7 +92,11 @@ class GLCanvas3DManager
 
     CanvasesMap m_canvases;
     wxGLContext* m_context;
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    static GLInfo s_gl_info;
+#else
     GLInfo m_gl_info;
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
     bool m_gl_initialized;
     bool m_use_legacy_opengl;
     bool m_use_VBOs;
@@ -75,7 +116,9 @@ public:
     unsigned int count() const;
 
     void init_gl();
+#if !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
     std::string get_gl_info(bool format_as_html, bool extensions) const;
+#endif // !ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
 
     bool init(wxGLCanvas* canvas);
 
@@ -88,6 +131,10 @@ public:
 
     static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
 
+#if ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+    static const GLInfo& get_gl_info() { return s_gl_info; }
+#endif // ENABLE_TEXTURES_MAXSIZE_DEPENDENT_ON_OPENGL_VERSION
+
 private:
     CanvasesMap::iterator do_get_canvas(wxGLCanvas* canvas);
     CanvasesMap::const_iterator do_get_canvas(wxGLCanvas* canvas) const;
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index f7d2edfe7..2216a14f2 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -18,6 +18,10 @@
 
 #include "libslic3r/Utils.hpp"
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <chrono>
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 namespace Slic3r {
 namespace GUI {
 
@@ -380,6 +384,10 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps)
 
 bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, unsigned int max_size_px)
 {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+    auto start_time = std::chrono::high_resolution_clock::now();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
     if (image == nullptr)
     {
@@ -426,6 +434,11 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
 #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()));
 #endif // ENABLE_COMPRESSED_TEXTURES
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+    auto end_time = std::chrono::high_resolution_clock::now();
+    std::cout << "texture level 0 to GPU in: " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << std::endl;
+    start_time = end_time;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (use_mipmaps)
     {
         // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
@@ -468,6 +481,11 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
     nsvgDeleteRasterizer(rast);
     nsvgDelete(image);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+    end_time = std::chrono::high_resolution_clock::now();
+    std::cout << "mipmaps to GPU in: " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << std::endl;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     return true;
 }