From c5756c3f0f024c7d95cd7766573f8191befc7427 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 9 Apr 2010 00:09:12 -0600
Subject: merged from viewer-trunk, fix for EXT-6780: to make
 LLImageBase::allocateData() thread-safe. Also include some debug code for
 EXT-6567: crash at LLImageBase::allocateData().

---
 indra/llimage/llimage.cpp          | 30 +++++++++++++++++++++---------
 indra/llimage/llimage.h            | 14 ++++++--------
 indra/newview/llviewermenufile.cpp |  5 ++---
 3 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 7d0de18c7c..0874f574c5 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -93,9 +93,10 @@ LLImageBase::LLImageBase()
 	  mWidth(0),
 	  mHeight(0),
 	  mComponents(0),
+	  mBadBufferAllocation(false),
+	  mAllowOverSize(false),
 	  mMemType(LLMemType::MTYPE_IMAGEBASE)
 {
-	mBadBufferAllocation = FALSE ;
 }
 
 // virtual
@@ -134,8 +135,6 @@ void LLImageBase::sanityCheck()
 	}
 }
 
-BOOL LLImageBase::sSizeOverride = FALSE;
-
 // virtual
 void LLImageBase::deleteData()
 {
@@ -157,23 +156,32 @@ U8* LLImageBase::allocateData(S32 size)
 			llerrs << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
 		}
 	}
-	if (size < 1 || (size > 4096*4096*16 && sSizeOverride == FALSE))
+	
+	//make this function thread-safe.
+	static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16 ; //256 MB
+	if (size < 1 || size > MAX_BUFFER_SIZE) 
 	{
 		llinfos << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << llendl ;
+		if(mAllowOverSize)
+		{
+			llinfos << "Oversize: " << size << llendl ;
+		}
+		else
+		{
 		llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
 	}
-	
+	}
 	if (!mData || size != mDataSize)
 	{
 		deleteData(); // virtual
-		mBadBufferAllocation = FALSE ;
+		mBadBufferAllocation = false ;
 		mData = new U8[size];
 		if (!mData)
 		{
 			llwarns << "allocate image data: " << size << llendl;
 			size = 0 ;
 			mWidth = mHeight = 0 ;
-			mBadBufferAllocation = TRUE ;
+			mBadBufferAllocation = true ;
 		}
 		mDataSize = size;
 	}
@@ -222,7 +230,7 @@ U8* LLImageBase::getData()
 	return mData; 
 }
 
-BOOL LLImageBase::isBufferInvalid()
+bool LLImageBase::isBufferInvalid()
 {
 	return mBadBufferAllocation || mData == NULL ;
 }
@@ -258,7 +266,11 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
 	: LLImageBase()
 {
 	mMemType = LLMemType::MTYPE_IMAGERAW;
-	llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
+	//llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
+	if(S32(width) * S32(height) * S32(components) > MAX_IMAGE_DATA_SIZE)
+	{
+		llwarns << "over size: width: " << (S32)width << " height: " << (S32)height << " components: " << (S32)components << llendl ;
+	}
 	allocateDataSize(width, height, components);
 	++sRawImageCount;
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 686f583886..10444e7f89 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -48,7 +48,7 @@ const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
 const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE;
 const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
 const S32 MAX_IMAGE_COMPONENTS = 8;
-const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS;
+const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 * 2048 * 8 = 16 MB
 
 // Note!  These CANNOT be changed without modifying simulator code
 // *TODO: change both to 1024 when SIM texture fetching is deprecated
@@ -124,10 +124,12 @@ public:
 
 	const U8 *getData() const	;
 	U8 *getData()				;
-	BOOL isBufferInvalid() ;
+	bool isBufferInvalid() ;
 
 	void setSize(S32 width, S32 height, S32 ncomponents);
 	U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData()
+	void enableOverSize() {mAllowOverSize = true ;}
+	void disableOverSize() {mAllowOverSize = false; }
 
 protected:
 	// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
@@ -140,8 +142,6 @@ public:
 	// <= 0 priority means that there's no need for more data.
 	static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent);
 
-	static void setSizeOverride(BOOL enabled) { sSizeOverride = enabled; }
-
 	static EImageCodec getCodecFromExtension(const std::string& exten);
 	
 private:
@@ -153,12 +153,10 @@ private:
 
 	S8 mComponents;
 
-	BOOL mBadBufferAllocation ;
-
+	bool mBadBufferAllocation ;
+	bool mAllowOverSize ;
 public:
 	LLMemType::DeclareMemType& mMemType; // debug
-	
-	static BOOL sSizeOverride;
 };
 
 // Raw representation of an image (used for textures, and other uncompressed formats
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index dfde9a9d1d..a5bc5d0634 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -411,7 +411,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
 		{
 			gViewerWindow->playSnapshotAnimAndSound();
 			
-			LLImageBase::setSizeOverride(TRUE);
 			LLPointer<LLImageFormatted> formatted;
 			switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat")))
 			{
@@ -426,12 +425,12 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
 				break;
 			  default: 
 				llwarns << "Unknown Local Snapshot format" << llendl;
-				LLImageBase::setSizeOverride(FALSE);
 				return true;
 			}
 
+			formatted->enableOverSize() ;
 			formatted->encode(raw, 0);
-			LLImageBase::setSizeOverride(FALSE);
+			formatted->disableOverSize() ;
 			gViewerWindow->saveImageNumbered(formatted);
 		}
 		return true;
-- 
cgit v1.2.3