From 837a2e1e5fef788cf108e036c27d092cedb3982f Mon Sep 17 00:00:00 2001
From: Aaron Suen <warr1024@gmail.com>
Date: Sat, 21 Mar 2015 09:59:06 -0400
Subject: [PATCH] Fix composite textures with texture_min_size. Moved upscaling
 of textures to later in the process, when images are converted to textures,
 instead of right after image load, so the original image is unmodified for
 generateImagePart.

---
 src/client/tile.cpp | 76 ++++++++++++++++++++++++++-------------------
 1 file changed, 44 insertions(+), 32 deletions(-)

diff --git a/src/client/tile.cpp b/src/client/tile.cpp
index 078e62741..7b326c152 100644
--- a/src/client/tile.cpp
+++ b/src/client/tile.cpp
@@ -182,6 +182,42 @@ struct TextureInfo
 	}
 };
 
+/* Upscale textures to user's requested minimum size.  This is a trick to make
+ * filters look as good on low-res textures as on high-res ones, by making
+ * low-res textures BECOME high-res ones.  This is helpful for worlds that
+ * mix high- and low-res textures, or for mods with least-common-denominator
+ * textures that don't have the resources to offer high-res alternatives.
+ */
+video::IImage *textureMinSizeUpscale(video::IVideoDriver *driver, video::IImage *orig) {
+	if(orig == NULL)
+		return orig;
+	s32 scaleto = g_settings->getS32("texture_min_size");
+	if (scaleto > 0) {
+
+		/* Calculate scaling needed to make the shortest texture dimension
+		 * equal to the target minimum.  If e.g. this is a vertical frames
+		 * animation, the short dimension will be the real size.
+		 */
+		const core::dimension2d<u32> dim = orig->getDimension();
+		u32 xscale = scaleto / dim.Width;
+		u32 yscale = scaleto / dim.Height;
+		u32 scale = (xscale > yscale) ? xscale : yscale;
+
+		// Never downscale; only scale up by 2x or more.
+		if (scale > 1) {
+			u32 w = scale * dim.Width;
+			u32 h = scale * dim.Height;
+			const core::dimension2d<u32> newdim = core::dimension2d<u32>(w, h);
+			video::IImage *newimg = driver->createImage(
+					orig->getColorFormat(), newdim);
+			orig->copyToScaling(newimg);
+			return newimg;
+		}
+	}
+
+	return orig;
+}
+
 /*
 	SourceImageCache: A cache used for storing source images.
 */
@@ -276,36 +312,6 @@ class SourceImageCache
 			}
 		}
 
-		/* Upscale textures to user's requested minimum size.  This is a trick to make
-		 * filters look as good on low-res textures as on high-res ones, by making
-		 * low-res textures BECOME high-res ones.  This is helpful for worlds that
-		 * mix high- and low-res textures, or for mods with least-common-denominator
-		 * textures that don't have the resources to offer high-res alternatives.
-		 */
-		s32 scaleto = g_settings->getS32("texture_min_size");
-		if (scaleto > 0) {
-
-			/* Calculate scaling needed to make the shortest texture dimension
-			 * equal to the target minimum.  If e.g. this is a vertical frames
-			 * animation, the short dimension will be the real size.
-			 */
-			const core::dimension2d<u32> dim = toadd->getDimension();
-			u32 xscale = scaleto / dim.Width;
-			u32 yscale = scaleto / dim.Height;
-			u32 scale = (xscale > yscale) ? xscale : yscale;
-
-			// Never downscale; only scale up by 2x or more.
-			if (scale > 1) {
-				u32 w = scale * dim.Width;
-				u32 h = scale * dim.Height;
-				const core::dimension2d<u32> newdim = core::dimension2d<u32>(w, h);
-				video::IImage *newimg = driver->createImage(
-						toadd->getColorFormat(), newdim);
-				toadd->copyToScaling(newimg);
-				toadd = newimg;
-			}
-		}
-
 		if (need_to_grab)
 			toadd->grab();
 		m_images[name] = toadd;
@@ -682,7 +688,8 @@ u32 TextureSource::generateTexture(const std::string &name)
 	video::IVideoDriver *driver = m_device->getVideoDriver();
 	sanity_check(driver);
 
-	video::IImage *img = generateImage(name);
+	video::IImage *origimg = generateImage(name);
+	video::IImage *img = textureMinSizeUpscale(driver, origimg);
 
 	video::ITexture *tex = NULL;
 
@@ -693,6 +700,8 @@ u32 TextureSource::generateTexture(const std::string &name)
 		// Create texture from resulting image
 		tex = driver->addTexture(name.c_str(), img);
 		img->drop();
+		if((origimg != NULL) && (img != origimg))
+			origimg->drop();
 	}
 
 	/*
@@ -783,7 +792,8 @@ void TextureSource::rebuildImagesAndTextures()
 	// Recreate textures
 	for (u32 i=0; i<m_textureinfo_cache.size(); i++){
 		TextureInfo *ti = &m_textureinfo_cache[i];
-		video::IImage *img = generateImage(ti->name);
+		video::IImage *origimg = generateImage(ti->name);
+		video::IImage *img = textureMinSizeUpscale(driver, origimg);
 #ifdef __ANDROID__
 		img = Align2Npot2(img, driver);
 		sanity_check(img->getDimension().Height == npot2(img->getDimension().Height));
@@ -794,6 +804,8 @@ void TextureSource::rebuildImagesAndTextures()
 		if (img) {
 			t = driver->addTexture(ti->name.c_str(), img);
 			img->drop();
+			if(origimg && (origimg != img))
+				origimg->drop();
 		}
 		video::ITexture *t_old = ti->texture;
 		// Replace texture
-- 
GitLab