From 6dcde6469d03b96260b1d00c22a90d76357a28ae Mon Sep 17 00:00:00 2001
From: ruslantproductengine <ruslantproductengine@lindenlab.com>
Date: Tue, 6 Jun 2017 15:30:03 +0300
Subject: [PATCH] [SL-711] - Eliminate some overheads in texturecache.

- Eliminate memory overhead when need duplicated scaled image.
- Small improvement in LLImageBase::getCodecFromExtension()
---
 indra/llimage/llimage.cpp         | 60 ++++++++++++++++++++++++++++---
 indra/llimage/llimage.h           |  3 +-
 indra/newview/lltexturecache.cpp  |  4 +--
 indra/newview/llviewertexture.cpp |  6 ++--
 4 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index a07ea146212..ad765b64153 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1436,7 +1436,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
 bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
 {
     S32 components = getComponents();
-	if (! ((1 == components) || (3 == components) || (4 == components) ))
+    if (components != 1 && components != 3 && components != 4)
     {
         LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
         return false;
@@ -1512,6 +1512,55 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
 	return true ;
 }
 
+LLPointer<LLImageRaw> LLImageRaw::scaled(S32 new_width, S32 new_height)
+{
+    LLPointer<LLImageRaw> result;
+
+    S32 components = getComponents();
+    if (components != 1 && components != 3 && components != 4)
+    {
+        LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+        return result;
+    }
+
+    if (isBufferInvalid())
+    {
+        LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+        return result;
+    }
+
+    S32 old_width = getWidth();
+    S32 old_height = getHeight();
+
+    if ((old_width == new_width) && (old_height == new_height))
+    {
+        result = new LLImageRaw(old_width, old_height, components);
+        if (!result)
+        {
+            LL_WARNS() << "Failed to allocate new image" << LL_ENDL;
+            return result;
+        }
+        memcpy(result->getData(), getData(), getDataSize());
+    }
+    else
+    {
+        S32 new_data_size = new_width * new_height * components;
+
+        if (new_data_size > 0)
+        {
+            result = new LLImageRaw(new_width, new_height, components);
+            if (!result)
+            {
+                LL_WARNS() << "Failed to allocate new image" << LL_ENDL;
+                return result;
+            }
+            bilinear_scale(getData(), old_width, old_height, components, old_width*components, result->getData(), new_width, new_height, components, new_width*components);
+        }
+    }
+
+    return result;
+}
+
 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
 {
 	const S32 components = getComponents();
@@ -1785,10 +1834,13 @@ static std::string find_file(std::string &name, S8 *codec)
 #endif
 EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
 {
-	for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
+	if (!exten.empty())
 	{
-		if (exten == file_extensions[i].exten)
-			return file_extensions[i].codec;
+		for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++)
+		{
+			if (exten == file_extensions[i].exten)
+				return file_extensions[i].codec;
+		}
 	}
 	return IMG_CODEC_INVALID;
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index d0bd4a2aefe..958c9fad3d1 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -215,7 +215,8 @@ class LLImageRaw : public LLImageBase
 	void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
 	void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
 	void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
-	bool scale( S32 new_width, S32 new_height, bool scale_image = true );
+	bool scale(S32 new_width, S32 new_height, bool scale_image = true);
+    LLPointer<LLImageRaw> scaled(S32 new_width, S32 new_height);
 	
 	// Fill the buffer with a constant color
 	void fill( const LLColor4U& color );
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e8b3842ae56..f0c28041d14 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1987,15 +1987,13 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis
 		if(w * h *c > 0) //valid
 		{
 			//make a duplicate to keep the original raw image untouched.
-			raw = raw->duplicate();
+			raw = raw->scaled(w, h);
 			if (raw->isBufferInvalid())
 			{
 				LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL;
 				return false;
 			}
 
-			raw->scale(w, h) ;
-			
 			discardlevel += i ;
 		}
 	}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5de7df7b910..e5a1bed48cb 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1396,8 +1396,7 @@ void LLViewerFetchedTexture::addToCreateTexture()
 
 						{
 							//make a duplicate in case somebody else is using this raw image
-							mRawImage = mRawImage->duplicate(); 
-							mRawImage->scale(w >> i, h >> i) ;					
+							mRawImage = mRawImage->scaled(w >> i, h >> i);
 						}
 					}
 				}
@@ -2913,8 +2912,7 @@ void LLViewerFetchedTexture::setCachedRawImage()
 			
 			{
 				//make a duplicate in case somebody else is using this raw image
-				mRawImage = mRawImage->duplicate(); 
-				mRawImage->scale(w >> i, h >> i) ;
+				mRawImage = mRawImage->scaled(w >> i, h >> i);
 			}
 		}
 		mCachedRawImage = mRawImage;
-- 
GitLab