From f01d1ec072cf22899a62fa50dfd086fda14f306d Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Tue, 11 Dec 2018 20:26:33 +0100
Subject: [PATCH] - must merge before continuing...

---
 src/gl/system/gl_framebuffer.cpp |  2 +-
 src/gl/system/gl_framebuffer.h   |  2 +-
 src/textures/hires/hirestex.cpp  | 16 +++++++++-----
 src/textures/hires/hqresize.cpp  | 26 +++++++++++------------
 src/textures/image.h             |  1 +
 src/textures/texture.cpp         | 30 +++++++++++++++++---------
 src/textures/textures.h          | 36 +++++++++++++++++++++++++-------
 src/v_video.h                    |  2 +-
 8 files changed, 75 insertions(+), 40 deletions(-)

diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp
index 58cc8be228..ca2616cfde 100644
--- a/src/gl/system/gl_framebuffer.cpp
+++ b/src/gl/system/gl_framebuffer.cpp
@@ -326,7 +326,7 @@ void OpenGLFrameBuffer::SetTextureFilterMode()
 	if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
 }
 
-IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(FTexture *tex) 
+IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture() 
 { 
 	return new FHardwareTexture(true/*tex->bNoCompress*/);
 }
diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h
index 60929d9473..5ebc586b0d 100644
--- a/src/gl/system/gl_framebuffer.h
+++ b/src/gl/system/gl_framebuffer.h
@@ -33,7 +33,7 @@ public:
 	void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override;
 	sector_t *RenderView(player_t *player) override;
 	void SetTextureFilterMode() override;
-	IHardwareTexture *CreateHardwareTexture(FTexture *tex) override;
+	IHardwareTexture *CreateHardwareTexture() override;
 	void PrecacheMaterial(FMaterial *mat, int translation) override;
 	bool CheckPrecacheMaterial(FMaterial *mat) override;
 	FModelRenderer *CreateModelRenderer(int mli) override;
diff --git a/src/textures/hires/hirestex.cpp b/src/textures/hires/hirestex.cpp
index b2edce48c8..824e61d5e3 100644
--- a/src/textures/hires/hirestex.cpp
+++ b/src/textures/hires/hirestex.cpp
@@ -36,6 +36,7 @@
 #include "gi.h"
 #include "cmdlib.h"
 #include "bitmap.h"
+#include "image.h"
 
 #ifndef _WIN32
 #define _access(a,b) access(a,b)
@@ -357,7 +358,7 @@ int FTexture::CheckExternalFile(bool & hascolorkey)
 //
 //==========================================================================
 
-unsigned char *FTexture::LoadHiresTexture(int *width, int *height)
+bool FTexture::LoadHiresTexture(FTextureBuffer &texbuffer)
 {
 	if (HiresLump == -1)
 	{
@@ -396,10 +397,15 @@ unsigned char *FTexture::LoadHiresTexture(int *width, int *height)
 				if (dwdata[i] == 0xffffff00 || dwdata[i] == 0xffff00ff) dwdata[i] = 0;
 			}
 		}
-		*width = w;
-		*height = h;
-		return buffer;
+		FContentId contentId;
+		contentId.id = 0;
+		contentId.imageID = HiresTexture->GetImage()->GetId();
+		texbuffer.mBuffer = buffer;
+		texbuffer.mWidth = w;
+		texbuffer.mHeight = h;
+		texbuffer.mContentId = contentId.id;
+		return true;
 	}
-	return nullptr;
+	return false;
 }
 
diff --git a/src/textures/hires/hqresize.cpp b/src/textures/hires/hqresize.cpp
index 01f310ed2f..0ba4b247b2 100644
--- a/src/textures/hires/hqresize.cpp
+++ b/src/textures/hires/hqresize.cpp
@@ -348,46 +348,44 @@ static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int
 //  the upsampled buffer.
 //
 //===========================================================================
-unsigned char *FTexture::CreateUpsampledTextureBuffer (unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight, bool hasAlpha )
+void FTexture::CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha)
 {
 	// [BB] Make sure that outWidth and outHeight denote the size of
 	// the returned buffer even if we don't upsample the input buffer.
-	outWidth = inWidth;
-	outHeight = inHeight;
+	int outWidth = texbuffer.mWidth;
+	int outHeight = texbuffer.mHeight;
 
 	// [BB] Don't resample if the width or height of the input texture is bigger than gl_texture_hqresize_maxinputsize.
-	if ( ( inWidth > gl_texture_hqresize_maxinputsize ) || ( inHeight > gl_texture_hqresize_maxinputsize ) )
-		return inputBuffer;
+	if ( ( outWidth > gl_texture_hqresize_maxinputsize ) || ( outHeight > gl_texture_hqresize_maxinputsize ) )
+		return;
 
-	// [BB] Don't try to upsample textures based off FCanvasTexture.
+	// [BB] Don't try to upsample textures based off FCanvasTexture. (This should never get here in the first place!)
 	if ( bHasCanvas )
-		return inputBuffer;
+		return;
 
 	// already scaled?
 	if (Scale.X >= 2 && Scale.Y >= 2)
-		return inputBuffer;
+		return;
 
 	switch (UseType)
 	{
 	case ETextureType::Sprite:
 	case ETextureType::SkinSprite:
-		if (!(gl_texture_hqresize_targets & 2)) return inputBuffer;
+		if (!(gl_texture_hqresize_targets & 2)) return;
 		break;
 
 	case ETextureType::FontChar:
-		if (!(gl_texture_hqresize_targets & 4)) return inputBuffer;
+		if (!(gl_texture_hqresize_targets & 4)) return;
 		break;
 
 	default:
-		if (!(gl_texture_hqresize_targets & 1)) return inputBuffer;
+		if (!(gl_texture_hqresize_targets & 1)) return;
 		break;
 	}
 
-	if (inputBuffer)
+	if (texbuffer.mBuffer)
 	{
 		int type = gl_texture_hqresize;
-		outWidth = inWidth;
-		outHeight = inHeight;
 #ifdef HAVE_MMX
 		// hqNx MMX does not preserve the alpha channel so fall back to C-version for such textures
 		if (hasAlpha && type > 6 && type <= 9)
diff --git a/src/textures/image.h b/src/textures/image.h
index e53fc20354..7e0db353fe 100644
--- a/src/textures/image.h
+++ b/src/textures/image.h
@@ -64,6 +64,7 @@ public:
 	bool bMasked = true;						// Image (might) have holes (Assume true unless proven otherwise!)
 	int8_t bTranslucent = -1;					// Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check)
 
+	int GetId() const { return ImageID; }
 	
 	// 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture.
 
diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp
index f91f7acc99..538ece45c2 100644
--- a/src/textures/texture.cpp
+++ b/src/textures/texture.cpp
@@ -661,23 +661,22 @@ bool FTexture::ProcessData(unsigned char * buffer, int w, int h, bool ispatch)
 //
 //===========================================================================
 
-unsigned char * FTexture::CreateTexBuffer(int translation, int & w, int & h, int flags)
+FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
 {
+	FTextureBuffer result;
+
 	unsigned char * buffer = nullptr;
 	int W, H;
 	int isTransparent = -1;
 
 	if (flags & CTF_CheckHires)
 	{
-		buffer = LoadHiresTexture(&w, &h);
-		if (buffer != nullptr)
-			return buffer;
+		if (LoadHiresTexture(result)) return result;
 	}
-
 	int exx = !!(flags & CTF_Expand);
 
-	W = w = GetWidth() + 2 * exx;
-	H = h = GetHeight() + 2 * exx;
+	W = GetWidth() + 2 * exx;
+	H = GetHeight() + 2 * exx;
 
 	buffer = new unsigned char[W*(H + 1) * 4];
 	memset(buffer, 0, W * (H + 1) * 4);
@@ -700,13 +699,24 @@ unsigned char * FTexture::CreateTexBuffer(int translation, int & w, int & h, int
 		// A translated image is not conclusive for setting the texture's transparency info.
 	}
 
+	FContentId builder;
+	builder.id = 0;
+	builder.imageID = GetImage()->GetId();
+	builder.translation = MAX(0, translation);
+	builder.expand = exx;
+
+	result.mBuffer = buffer;
+	result.mWidth = W;
+	result.mHeight = H;
+	result.mContentId = builder.id;
+
 	if (flags & CTF_ProcessData) 
 	{
-		buffer = CreateUpsampledTextureBuffer(buffer, W, H, w, h, !!isTransparent);
-		ProcessData(buffer, w, h, false);
+		CreateUpsampledTextureBuffer(result, !!isTransparent);
+		ProcessData(result.mBuffer, result.mWidth, result.mHeight, false);
 	}
 
-	return buffer;
+	return result;
 }
 
 //===========================================================================
diff --git a/src/textures/textures.h b/src/textures/textures.h
index 52cf9b97a7..47e4da28f8 100644
--- a/src/textures/textures.h
+++ b/src/textures/textures.h
@@ -226,6 +226,31 @@ namespace OpenGLRenderer
 	class FHardwareTexture;
 }
 
+union FContentId
+{
+	uint64_t id;
+	struct
+	{
+		unsigned imageID : 24;
+		unsigned translation : 16;
+		unsigned expand : 1;
+		unsigned scaler : 4;
+		unsigned scalefactor : 4;
+	};
+};
+
+struct FTextureBuffer
+{
+	uint8_t *mBuffer = nullptr;
+	int mWidth = 0;
+	int mHeight = 0;
+	uint64_t mContentId = 0;	// unique content identifier. (Two images created from the same image source with the same settings will return the same value.)
+
+	FTextureBuffer()
+	{
+		if (mBuffer) delete[] mBuffer;
+	}
+};
 
 // Base texture class
 class FTexture
@@ -258,12 +283,7 @@ public:
 	virtual ~FTexture ();
 	virtual FImageSource *GetImage() const { return nullptr; }
 	void AddAutoMaterials();
-	unsigned char *CreateUpsampledTextureBuffer(unsigned char *inputBuffer, const int inWidth, const int inHeight, int &outWidth, int &outHeight, bool hasAlpha);
-
-	// These should only be used in places where the texture scaling must be ignored and absolutely nowhere else!
-	// Preferably all code depending on the physical texture size should be rewritten, unless it is part of the software rasterizer.
-	//int GetPixelWidth() { return GetWidth(); }
-	//int GetPixelHeight() { return GetHeight(); }
+	void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha);
 
 	// These are mainly meant for 2D code which only needs logical information about the texture to position it properly.
 	int GetDisplayWidth() { return GetScaledWidth(); }
@@ -466,13 +486,13 @@ protected:
 
 
 public:
-	unsigned char * CreateTexBuffer(int translation, int & w, int & h, int flags = 0);
+	FTextureBuffer CreateTexBuffer(int translation, int flags = 0);
 	bool GetTranslucency();
 
 private:
 	int CheckDDPK3();
 	int CheckExternalFile(bool & hascolorkey);
-	unsigned char *LoadHiresTexture(int *width, int *height);
+	bool LoadHiresTexture(FTextureBuffer &texbuffer);
 
 	bool bSWSkyColorDone = false;
 	PalEntry FloorSkyColor;
diff --git a/src/v_video.h b/src/v_video.h
index bdf556edd3..bbbcb71f96 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -424,7 +424,7 @@ public:
 	// Delete any resources that need to be deleted after restarting with a different IWAD
 	virtual void CleanForRestart() {}
 	virtual void SetTextureFilterMode() {}
-	virtual IHardwareTexture *CreateHardwareTexture(FTexture *tex) { return nullptr; }
+	virtual IHardwareTexture *CreateHardwareTexture() { return nullptr; }
 	virtual bool CheckPrecacheMaterial(FMaterial *mat) { return true; }
 	virtual void PrecacheMaterial(FMaterial *mat, int translation) {}
 	virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; }