From b2cdc8c97eea372d970d6cb02ba581b761d9fd90 Mon Sep 17 00:00:00 2001
From: Benau <Benau@users.noreply.github.com>
Date: Tue, 11 Oct 2016 16:25:22 +0800
Subject: [PATCH] Fix memory leak of unicolor texture

Also try to hold them until the last moment, this may need some
testing.
---
 src/graphics/irr_driver.cpp      |  2 ++
 src/graphics/texture_manager.cpp | 13 +++++++++++--
 src/graphics/texture_manager.hpp |  1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp
index 7538f6bcb..4a527d721 100644
--- a/src/graphics/irr_driver.cpp
+++ b/src/graphics/irr_driver.cpp
@@ -160,6 +160,7 @@ IrrDriver::~IrrDriver()
     }
     assert(m_device != NULL);
 
+    cleanUnicolorTextures();
     m_device->drop();
     m_device = NULL;
     m_modes.clear();
@@ -905,6 +906,7 @@ void IrrDriver::applyResolutionSettings()
     {
         Shaders::destroy();
     }
+    cleanUnicolorTextures();
     initDevice();
 
     font_manager = new FontManager();
diff --git a/src/graphics/texture_manager.cpp b/src/graphics/texture_manager.cpp
index fce9c61f7..7047446cd 100644
--- a/src/graphics/texture_manager.cpp
+++ b/src/graphics/texture_manager.cpp
@@ -59,6 +59,14 @@ static std::map<int, video::ITexture*> unicolor_cache;
 void resetTextureTable()
 {
     AlreadyTransformedTexture.clear();
+}
+
+void cleanUnicolorTextures()
+{
+    for (std::pair<const int, video::ITexture*>& uc : unicolor_cache)
+    {
+        uc.second->drop();
+    }
     unicolor_cache.clear();
 }
 
@@ -228,7 +236,6 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
     std::map<int, video::ITexture*>::iterator it = unicolor_cache.find(c.color);
     if (it != unicolor_cache.end())
     {
-        it->second->grab();
         return it->second;
     }
     else
@@ -240,10 +247,12 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
             c.color
         };
         video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
-        img->grab();
         std::stringstream name;
         name << "color" << c.color;
         video::ITexture* tex = irr_driver->getVideoDriver()->addTexture(name.str().c_str(), img);
+        tex->grab();
+        // Only let our map hold the unicolor texture
+        irr_driver->getVideoDriver()->removeTexture(tex);
         unicolor_cache[c.color] = tex;
         img->drop();
         return tex;
diff --git a/src/graphics/texture_manager.hpp b/src/graphics/texture_manager.hpp
index afa82a4e5..d2e2bd0d7 100644
--- a/src/graphics/texture_manager.hpp
+++ b/src/graphics/texture_manager.hpp
@@ -26,6 +26,7 @@
 GLuint getTextureGLuint(irr::video::ITexture *tex);
 GLuint getDepthTexture(irr::video::ITexture *tex);
 void resetTextureTable();
+void cleanUnicolorTextures();
 void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);
 bool loadCompressedTexture(const std::string& compressed_tex);
 void saveCompressedTexture(const std::string& compressed_tex);