diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp
index 9dbfeaff3..e768e9689 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp
@@ -426,7 +426,7 @@ void GLCanvas3D::Bed::_render_mk2(float theta) const
     std::string filename = resources_dir() + "/icons/bed/mk2_top.png";
     if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
     {
-        if (!m_top_texture.load_from_file(filename))
+        if (!m_top_texture.load_from_file(filename, true))
         {
             _render_custom();
             return;
@@ -436,7 +436,7 @@ void GLCanvas3D::Bed::_render_mk2(float theta) const
     filename = resources_dir() + "/icons/bed/mk2_bottom.png";
     if ((m_bottom_texture.get_id() == 0) || (m_bottom_texture.get_source() != filename))
     {
-        if (!m_bottom_texture.load_from_file(filename))
+        if (!m_bottom_texture.load_from_file(filename, true))
         {
             _render_custom();
             return;
@@ -451,7 +451,7 @@ void GLCanvas3D::Bed::_render_mk3(float theta) const
     std::string filename = resources_dir() + "/icons/bed/mk3_top.png";
     if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
     {
-        if (!m_top_texture.load_from_file(filename))
+        if (!m_top_texture.load_from_file(filename, true))
         {
             _render_custom();
             return;
@@ -461,7 +461,7 @@ void GLCanvas3D::Bed::_render_mk3(float theta) const
     filename = resources_dir() + "/icons/bed/mk3_bottom.png";
     if ((m_bottom_texture.get_id() == 0) || (m_bottom_texture.get_source() != filename))
     {
-        if (!m_bottom_texture.load_from_file(filename))
+        if (!m_bottom_texture.load_from_file(filename, true))
         {
             _render_custom();
             return;
@@ -911,7 +911,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))
+        if (!m_tooltip_texture.load_from_file(filename, false))
             return;
     }
 
@@ -935,7 +935,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))
+        if (!m_reset_texture.load_from_file(filename, false))
             return;
     }
 
diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp
index d98864931..64df649d4 100644
--- a/xs/src/slic3r/GUI/GLGizmo.cpp
+++ b/xs/src/slic3r/GUI/GLGizmo.cpp
@@ -95,15 +95,15 @@ bool GLGizmoRotate::on_init()
     std::string path = resources_dir() + "/icons/overlay/";
 
     std::string filename = path + "rotate_off.png";
-    if (!m_textures[Off].load_from_file(filename))
+    if (!m_textures[Off].load_from_file(filename, false))
         return false;
 
     filename = path + "rotate_hover.png";
-    if (!m_textures[Hover].load_from_file(filename))
+    if (!m_textures[Hover].load_from_file(filename, false))
         return false;
 
     filename = path + "rotate_on.png";
-    if (!m_textures[On].load_from_file(filename))
+    if (!m_textures[On].load_from_file(filename, false))
         return false;
 
     return true;
@@ -224,15 +224,15 @@ bool GLGizmoScale::on_init()
     std::string path = resources_dir() + "/icons/overlay/";
 
     std::string filename = path + "scale_off.png";
-    if (!m_textures[Off].load_from_file(filename))
+    if (!m_textures[Off].load_from_file(filename, false))
         return false;
 
     filename = path + "scale_hover.png";
-    if (!m_textures[Hover].load_from_file(filename))
+    if (!m_textures[Hover].load_from_file(filename, false))
         return false;
 
     filename = path + "scale_on.png";
-    if (!m_textures[On].load_from_file(filename))
+    if (!m_textures[On].load_from_file(filename, false))
         return false;
 
     return true;
diff --git a/xs/src/slic3r/GUI/GLTexture.cpp b/xs/src/slic3r/GUI/GLTexture.cpp
index b9eb118a9..593362e54 100644
--- a/xs/src/slic3r/GUI/GLTexture.cpp
+++ b/xs/src/slic3r/GUI/GLTexture.cpp
@@ -5,6 +5,7 @@
 #include <wx/image.h>
 
 #include <vector>
+#include <algorithm>
 
 namespace Slic3r {
 namespace GUI {
@@ -22,7 +23,7 @@ GLTexture::~GLTexture()
     reset();
 }
 
-bool GLTexture::load_from_file(const std::string& filename)
+bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmaps)
 {
     reset();
 
@@ -68,10 +69,20 @@ bool GLTexture::load_from_file(const std::string& filename)
     // sends data to gpu
     ::glGenTextures(1, &m_id);
     ::glBindTexture(GL_TEXTURE_2D, m_id);
-    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
     ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
+    if (generate_mipmaps)
+    {
+        // we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
+        _generate_mipmaps(image);
+        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    }
+    else
+    {
+        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+    }
+    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
     ::glBindTexture(GL_TEXTURE_2D, 0);
 
     m_source = filename;
@@ -134,5 +145,41 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo
     ::glEnable(GL_LIGHTING);
 }
 
+void GLTexture::_generate_mipmaps(wxImage& image)
+{
+    int w = image.GetWidth();
+    int h = image.GetHeight();
+    GLint level = 0;
+    std::vector<unsigned char> 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;
+        }
+
+        ::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
+    }
+}
+
 } // namespace GUI
 } // namespace Slic3r
diff --git a/xs/src/slic3r/GUI/GLTexture.hpp b/xs/src/slic3r/GUI/GLTexture.hpp
index 3e3bf83f7..70480c605 100644
--- a/xs/src/slic3r/GUI/GLTexture.hpp
+++ b/xs/src/slic3r/GUI/GLTexture.hpp
@@ -3,10 +3,12 @@
 
 #include <string>
 
+class wxImage;
+
 namespace Slic3r {
 namespace GUI {
 
-    struct GLTexture
+    class GLTexture
     {
     private:
         unsigned int m_id;
@@ -18,7 +20,7 @@ namespace GUI {
         GLTexture();
         ~GLTexture();
 
-        bool load_from_file(const std::string& filename);
+        bool load_from_file(const std::string& filename, bool generate_mipmaps);
         void reset();
 
         unsigned int get_id() const;
@@ -27,6 +29,9 @@ namespace GUI {
         const std::string& get_source() const;
 
         static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
+
+    private:
+        void _generate_mipmaps(wxImage& image);
     };
 
 } // namespace GUI