From 6fcf38217e8772b2f90c7a8e7ce6b60071f6d20c Mon Sep 17 00:00:00 2001
From: Steven Bennetts <steve@lindenlab.com>
Date: Tue, 25 Mar 2008 22:50:26 +0000
Subject: [PATCH] merge release@82858 maint-render-2-merge@83010 -> release
 QAR-389

---
 indra/llcommon/llfile.cpp                     |   8 +-
 indra/llcommon/llfile.h                       |   6 +-
 indra/llimagej2coj/llimagej2coj.cpp           |  12 +
 indra/llrender/llfontgl.cpp                   |   6 +
 indra/llrender/llfontgl.h                     |   5 +-
 indra/llrender/llrendertarget.cpp             |  64 ++-
 indra/llrender/llrendertarget.h               |  27 +-
 indra/llwindow/llwindow.cpp                   |   9 +-
 indra/llwindow/llwindow.h                     |   5 +-
 indra/llwindow/llwindowheadless.h             |   2 +
 indra/llwindow/llwindowmacosx.cpp             |  26 +-
 indra/llwindow/llwindowmacosx.h               |  11 +-
 indra/llwindow/llwindowmesaheadless.h         |   2 +
 indra/llwindow/llwindowsdl.cpp                |  40 +-
 indra/llwindow/llwindowsdl.h                  |   5 +-
 indra/llwindow/llwindowwin32.cpp              | 456 +++---------------
 indra/llwindow/llwindowwin32.h                |   5 +-
 indra/newview/app_settings/settings.xml       |  57 ++-
 .../shaders/class1/deferred/diffuseF.glsl     |  16 +
 .../shaders/class1/deferred/diffuseV.glsl     |  22 +
 .../shaders/class1/environment/waterF.glsl    |   2 +-
 .../shaders/class1/environment/waterFogF.glsl |   4 +-
 .../shaders/class1/environment/waterV.glsl    |   5 +-
 .../shaders/class1/lighting/lightF.glsl       |   2 +-
 .../shaders/class1/lighting/lightShinyF.glsl  |   2 +-
 .../class1/lighting/lightShinyWaterF.glsl     |   2 +-
 indra/newview/featuretable.txt                |   1 +
 indra/newview/featuretable_linux.txt          |   1 +
 indra/newview/featuretable_mac.txt            |  59 +--
 indra/newview/featuretable_solaris.txt        |   1 +
 indra/newview/linux_tools/wrapper.sh          |   3 +-
 indra/newview/llappviewer.cpp                 |  21 -
 indra/newview/lldrawpoolwater.cpp             |   3 +
 indra/newview/lldrawpoolwater.h               |   1 +
 indra/newview/llfasttimerview.cpp             |   8 +-
 indra/newview/llfloaterhardwaresettings.cpp   |  23 +-
 indra/newview/llfloaterhardwaresettings.h     |   1 +
 indra/newview/llfloatersnapshot.cpp           | 417 ++++++++++++----
 indra/newview/llfloatersnapshot.h             |  10 +-
 indra/newview/llhudtext.cpp                   |   3 +-
 indra/newview/llhudtext.h                     |   2 +
 indra/newview/lloverlaybar.cpp                |   2 +
 indra/newview/llselectmgr.cpp                 |  30 ++
 indra/newview/llselectmgr.h                   |   1 +
 indra/newview/lltexturefetch.cpp              |  12 +-
 indra/newview/llviewercontrol.cpp             |   1 +
 indra/newview/llviewerdisplay.cpp             |  37 +-
 indra/newview/llviewermenu.cpp                |   3 +
 indra/newview/llviewerpartsource.cpp          |   7 +-
 indra/newview/llviewerwindow.cpp              | 202 ++++++--
 indra/newview/llviewerwindow.h                |   1 +
 indra/newview/llvoavatar.cpp                  | 192 +++++++-
 indra/newview/llvoavatar.h                    |   7 +-
 indra/newview/pipeline.cpp                    | 160 +++---
 indra/newview/pipeline.h                      |   4 +
 55 files changed, 1291 insertions(+), 723 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl

diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c44650009d1..3c590a0d49e 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -266,6 +266,7 @@ void llofstream::open(const char* _Filename,	/* Flawfinder: ignore */
 	}
 	llassert(_Filebuffer==NULL);
 	_Filebuffer = new _Myfb(filep);
+	_ShouldClose = true;
 	_Myios::init(_Filebuffer);
 }
 
@@ -281,7 +282,7 @@ void llofstream::close()
 llofstream::llofstream(const char *_Filename,
 	std::ios_base::openmode _Mode,
 	int _Prot) 
-		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL)
+		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
 {	// construct with named file and specified mode
 	open(_Filename, _Mode , _Prot);	/* Flawfinder: ignore */
 }
@@ -289,7 +290,10 @@ llofstream::llofstream(const char *_Filename,
 llofstream::~llofstream()
 {	
 	// destroy the object
-	close();
+	if (_ShouldClose)
+	{
+		close();
+	}
 	delete _Filebuffer;
 }
 
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 7a1542a6fa9..da1ad6a34e2 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -127,7 +127,7 @@ class	llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
 	typedef std::basic_ios<char,std::char_traits < char > > _Myios;
 
 	llofstream()
-		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL)
+		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
 	{	// construct unopened
 	}
 
@@ -138,7 +138,8 @@ class	llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
 
 	explicit llofstream(_Filet *_File)
 		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),
-			_Filebuffer(new _Myfb(_File))//_File)
+			_Filebuffer(new _Myfb(_File)),//_File)
+			_ShouldClose(false)
 	{	// construct with specified C stream
 	}
 
@@ -157,6 +158,7 @@ class	llofstream	:	public	std::basic_ostream< char , std::char_traits < char > >
 
 private:
 	_Myfb *_Filebuffer;	// the file buffer
+	bool _ShouldClose;
 };
 
 
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index d7be1188759..dfc5d4520b7 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -158,6 +158,18 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
 		return TRUE; // done
 	}
 
+	// sometimes we get bad data out of the cache - check to see if the decode succeeded
+	for (S32 i = 0; i < image->numcomps; i++)
+	{
+		if (image->comps[i].factor != base.getRawDiscardLevel())
+		{
+			// if we didn't get the discard level we're expecting, fail
+			opj_image_destroy(image);
+			base.mDecoding = FALSE;
+			return TRUE;
+		}
+	}
+	
 	// Copy image data into our raw image format (instead of the separate channel format
 
 	S32 img_components = image->numcomps;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 2e767ebb9c1..df9dca3af52 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -47,6 +47,7 @@ F32 LLFontGL::sVertDPI = 96.f;
 F32 LLFontGL::sHorizDPI = 96.f;
 F32 LLFontGL::sScaleX = 1.f;
 F32 LLFontGL::sScaleY = 1.f;
+BOOL LLFontGL::sDisplayFont = TRUE ;
 LLString LLFontGL::sAppDir;
 
 LLFontGL* LLFontGL::sMonospace = NULL;
@@ -557,6 +558,11 @@ S32 LLFontGL::render(const LLWString &wstr,
 					 BOOL use_embedded,
 					 BOOL use_ellipses) const
 {
+	if(!sDisplayFont) //do not display texts
+	{
+		return wstr.length() ;
+	}
+
 	LLGLEnable tex(GL_TEXTURE_2D);
 
 	if (wstr.empty())
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 393d26c6859..b5f018e8f73 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -202,6 +202,8 @@ class LLFontGL : public LLFont
 	static LLString nameFromVAlign(LLFontGL::VAlign align);
 	static LLFontGL::VAlign vAlignFromName(const LLString& name);
 
+	static void setFontDisplay(BOOL flag) { sDisplayFont = flag ; }
+
 protected:
 	struct embedded_data_t
 	{
@@ -220,6 +222,7 @@ class LLFontGL : public LLFont
 	static F32 sHorizDPI;
 	static F32 sScaleX;
 	static F32 sScaleY;
+	static BOOL     sDisplayFont ;
 	static LLString sAppDir;			// For loading fonts
 		
 	static LLFontGL*	sMonospace;		// medium
@@ -244,7 +247,7 @@ class LLFontGL : public LLFont
 protected:
 	/*virtual*/ BOOL addChar(const llwchar wch);
 	static LLString getFontPathLocal();
-	static LLString getFontPathSystem();
+	static LLString getFontPathSystem();	
 
 protected:
 	LLPointer<LLImageRaw>	mRawImageGLp;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index c082b931641..593a5a18e56 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -49,8 +49,9 @@ LLRenderTarget::~LLRenderTarget()
 	release();
 }
 
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL force_fbo)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL use_fbo)
 {
+	stop_glerror();
 	mResX = resx;
 	mResY = resy;
 
@@ -79,32 +80,44 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32
 
 	stop_glerror();
 
-	if (sUseFBO || force_fbo)
+	if (depth)
 	{
-		if (depth)
-		{
-			glGenRenderbuffersEXT(1, (GLuint *) &mDepth);
-			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
-			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,mResX,mResY);
-			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);	
-		}
+		stop_glerror();
+		allocateDepth();
+		stop_glerror();
+	}
 
+	if ((sUseFBO && use_fbo) && gGLManager.mHasFramebufferObject)
+	{
 		glGenFramebuffersEXT(1, (GLuint *) &mFBO);
+
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
 
 		if (mDepth)
 		{
-			glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-											GL_RENDERBUFFER_EXT, mDepth);	
+			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, mUsage, mDepth, 0);
+			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, mUsage, mDepth, 0);
+			stop_glerror();
 		}
+
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 						mUsage, mTex, 0);
-
+		stop_glerror();
 
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+		stop_glerror();
 	}
 }
 
+void LLRenderTarget::allocateDepth()
+{
+	glGenTextures(1, (GLuint *) &mDepth);
+	glBindTexture(mUsage, mDepth);
+	glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
+}
+
 void LLRenderTarget::release()
 {
 	if (mFBO)
@@ -121,7 +134,7 @@ void LLRenderTarget::release()
 
 	if (mDepth)
 	{
-		glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth);
+		glDeleteTextures(1, (GLuint *) &mDepth);
 		mDepth = 0;
 	}
 }
@@ -141,7 +154,7 @@ void LLRenderTarget::clear()
 	U32 mask = GL_COLOR_BUFFER_BIT;
 	if (mUseDepth)
 	{
-		mask |= GL_DEPTH_BUFFER_BIT;
+		mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
 	}
 	if (mFBO)
 	{
@@ -160,13 +173,34 @@ void LLRenderTarget::bindTexture()
 	glBindTexture(mUsage, mTex);
 }
 
-void LLRenderTarget::flush()
+void LLRenderTarget::bindDepth()
+{
+	glBindTexture(mUsage, mDepth);
+}
+
+
+void LLRenderTarget::flush(BOOL fetch_depth)
 {
 	gGL.flush();
 	if (!mFBO)
 	{
 		bindTexture();
 		glCopyTexSubImage2D(mUsage, 0, 0, 0, 0, 0, mResX, mResY);
+
+		if (fetch_depth)
+		{
+			if (!mDepth)
+			{
+				allocateDepth();
+			}
+
+			bindDepth();
+			glCopyTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
+		}
+	}
+	else
+	{
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 	}
 }
 
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 0c0eab2b100..7f9c611c69b 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -37,7 +37,7 @@
 /*
  SAMPLE USAGE:
 
-	LLFBOTarget target;
+	LLRenderTarget target;
 
 	...
 
@@ -46,7 +46,7 @@
 
 	//render to contents of offscreen buffer
 	target.bindTarget();
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	target.clear();
 	... <issue drawing commands> ...
 	target.flush();
 
@@ -71,7 +71,10 @@ class LLRenderTarget
 	//allocate resources for rendering
 	//must be called before use
 	//multiple calls will release previously allocated resources
-	void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL force_fbo = FALSE);
+	void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL use_fbo = TRUE);
+
+	//allocate a depth texture
+	void allocateDepth();
 
 	//free any allocated resources
 	//safe to call redundantly
@@ -80,7 +83,7 @@ class LLRenderTarget
 	//bind target for rendering
 	//applies appropriate viewport
 	void bindTarget();
-
+	
 	//clear render targer, clears depth buffer if present,
 	//uses scissor rect if in copy-to-texture mode
 	void clear();
@@ -88,14 +91,25 @@ class LLRenderTarget
 	//get applied viewport
 	void getViewport(S32* viewport);
 
+	//get X resolution
+	U32 getWidth() const { return mResX; }
+
+	//get Y resolution
+	U32 getHeight() const { return mResY; }
+
 	//bind results of render for sampling
 	void bindTexture();
 
+	//bind results of render for sampling depth buffer
+	void bindDepth();
+
 	//flush rendering operations
 	//must be called when rendering is complete
 	//should be used 1:1 with bindTarget 
 	// call bindTarget once, do all your rendering, call flush once
-	void flush();
+	// if fetch_depth is TRUE, every effort will be made to copy the depth buffer into 
+	// the current depth texture.  A depth texture will be allocated if needed.
+	void flush(BOOL fetch_depth = FALSE);
 
 	//Returns TRUE if target is ready to be rendered into.
 	//That is, if the target has been allocated with at least
@@ -108,8 +122,11 @@ class LLRenderTarget
 	U32 mTex;
 	U32 mFBO;
 	U32 mDepth;
+	U32 mStencil;
 	BOOL mUseDepth;
+	BOOL mRenderDepth;
 	U32 mUsage;
+	
 };
 
 #endif
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 43f3081321a..37f089e8bea 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -440,7 +440,8 @@ LLWindow* LLWindowManager::createWindow(
 	BOOL clearBg,
 	BOOL disable_vsync,
 	BOOL use_gl,
-	BOOL ignore_pixel_depth)
+	BOOL ignore_pixel_depth,
+	U32 fsaa_samples)
 {
 	LLWindow* new_window;
 
@@ -453,15 +454,15 @@ LLWindow* LLWindowManager::createWindow(
 #elif LL_SDL
 		new_window = new LLWindowSDL(
 			title, x, y, width, height, flags, 
-			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
+			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
 #elif LL_WINDOWS
 		new_window = new LLWindowWin32(
 			title, name, x, y, width, height, flags, 
-			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
+			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
 #elif LL_DARWIN
 		new_window = new LLWindowMacOSX(
 			title, name, x, y, width, height, flags, 
-			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
+			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
 #elif LL_LINUX
 		new_window = new LLWindowLinux(
 			title, name, x, y, width, height, flags, 
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index bc444ae8117..b2e9c5b51d8 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -184,6 +184,8 @@ class LLWindow
 	virtual void flashIcon(F32 seconds) = 0;
 	virtual F32 getGamma() = 0;
 	virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma
+	virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples
+	virtual U32	 getFSAASamples() = 0;
 	virtual BOOL restoreGamma() = 0;			// Restore original gamma table (before updating gamma)
 	virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
 	virtual void gatherInput() = 0;
@@ -340,7 +342,8 @@ class LLWindowManager
 		BOOL clearBg = FALSE,
 		BOOL disable_vsync = TRUE,
 		BOOL use_gl = TRUE,
-		BOOL ignore_pixel_depth = FALSE);
+		BOOL ignore_pixel_depth = FALSE,
+		U32 fsaa_samples = 0);
 	static BOOL destroyWindow(LLWindow* window);
 	static BOOL isWindowValid(LLWindow *window);
 };
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 4962cf7bf70..b7e66446749 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -69,6 +69,8 @@ class LLWindowHeadless : public LLWindow
 	/*virtual*/ void flashIcon(F32 seconds) {};
 	/*virtual*/ F32 getGamma() {return 1.0f; };
 	/*virtual*/ BOOL setGamma(const F32 gamma) {return FALSE; }; // Set the gamma
+	/*virtual*/ void setFSAASamples(const U32 fsaa_samples) { }
+	/*virtual*/ U32 getFSAASamples() { return 0; }
 	/*virtual*/ BOOL restoreGamma() {return FALSE; };	// Restore original gamma table (before updating gamma)
 	//virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
 	/*virtual*/ void gatherInput() {};
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index a1d97429e1a..aa4c2c86f72 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -246,7 +246,8 @@ LLWindowMacOSX::LLWindowMacOSX(char *title, char *name, S32 x, S32 y, S32 width,
 							   S32 height, U32 flags,
 							   BOOL fullscreen, BOOL clearBg,
 							   BOOL disable_vsync, BOOL use_gl,
-							   BOOL ignore_pixel_depth)
+							   BOOL ignore_pixel_depth,
+							   U32 fsaa_samples)
 	: LLWindow(fullscreen, flags)
 {
 	// Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
@@ -277,6 +278,8 @@ LLWindowMacOSX::LLWindowMacOSX(char *title, char *name, S32 x, S32 y, S32 width,
 	mTSMScriptCode = 0;
 	mTSMLangCode = 0;
 	mPreeditor = NULL;
+	mFSAASamples = fsaa_samples;
+	mForceRebuild = FALSE;
 	
 	// For reasons that aren't clear to me, LLTimers seem to be created in the "started" state.
 	// Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state.
@@ -558,6 +561,8 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
 					AGL_RGBA,
 						AGL_FULLSCREEN,
 						//			AGL_NO_RECOVERY,	// MBW -- XXX -- Not sure if we want this attribute
+						AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
+						AGL_SAMPLES_ARB, mFSAASamples,
 						AGL_DOUBLEBUFFER,
 						AGL_CLOSEST_POLICY,
 						AGL_ACCELERATED,
@@ -586,6 +591,8 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
 						AGL_DOUBLEBUFFER,
 						AGL_CLOSEST_POLICY,
 						AGL_ACCELERATED,
+						AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
+						AGL_SAMPLES_ARB, mFSAASamples,
 						AGL_RED_SIZE, 8,
 						AGL_GREEN_SIZE, 8,
 						AGL_BLUE_SIZE, 8,
@@ -819,6 +826,9 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
 		}
 	}
 
+	//make sure multisample starts off disabled
+	glDisable(GL_MULTISAMPLE_ARB);
+	
 	// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
 	return TRUE;
 }
@@ -897,8 +907,9 @@ BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL dis
 	}
 
 	stop_glerror();
-	if(needsRebuild)
+	if(needsRebuild || mForceRebuild)
 	{
+		mForceRebuild = FALSE;
 		destroyContext();
 		result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
 		if (result)
@@ -1318,6 +1329,17 @@ F32 LLWindowMacOSX::getGamma()
 	return result;
 }
 
+U32 LLWindowMacOSX::getFSAASamples()
+{
+	return mFSAASamples;
+}
+
+void LLWindowMacOSX::setFSAASamples(const U32 samples)
+{
+	mFSAASamples = samples;
+	mForceRebuild = TRUE;
+}
+
 BOOL LLWindowMacOSX::restoreGamma()
 {
 	CGDisplayRestoreColorSyncSettings();
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 2fdf80ee829..86b88daa3c6 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -78,6 +78,8 @@ class LLWindowMacOSX : public LLWindow
 	/*virtual*/ void flashIcon(F32 seconds);
 	/*virtual*/ F32 getGamma();
 	/*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
+	/*virtual*/ U32 getFSAASamples();
+	/*virtual*/ void setFSAASamples(const U32 fsaa_samples);
 	/*virtual*/ BOOL restoreGamma();			// Restore original gamma table (before updating gamma)
 	/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
 	/*virtual*/ void gatherInput();
@@ -119,7 +121,8 @@ class LLWindowMacOSX : public LLWindow
 	LLWindowMacOSX(
 		char *title, char *name, int x, int y, int width, int height, U32 flags,
 		BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
-		BOOL ignore_pixel_depth);
+		BOOL ignore_pixel_depth,
+		U32 fsaa_samples);
 	~LLWindowMacOSX();
 
 	void	initCursors();
@@ -185,7 +188,9 @@ class LLWindowMacOSX : public LLWindow
 	LLCoordScreen   mNeedsResizeSize;
 	F32			mOverrideAspectRatio;
 	BOOL		mMinimized;
-
+	U32			mFSAASamples;
+	BOOL		mForceRebuild;
+	
 	F32			mBounceTime;
 	NMRec		mBounceRec;
 	LLTimer		mBounceTimer;
@@ -196,7 +201,7 @@ class LLWindowMacOSX : public LLWindow
 	ScriptCode	mTSMScriptCode;
 	LangCode	mTSMLangCode;
 	LLPreeditor*	mPreeditor;
-
+	
 	friend class LLWindowManager;
 };
 
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index fe91a2d2a0f..8de92bbe0e5 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -74,6 +74,8 @@ class LLWindowMesaHeadless : public LLWindow
 	/*virtual*/ F32 getGamma() {return 1.0f; };
 	/*virtual*/ BOOL setGamma(const F32 gamma) {return FALSE; }; // Set the gamma
 	/*virtual*/ BOOL restoreGamma() {return FALSE; };	// Restore original gamma table (before updating gamma)
+	/*virtual*/ void setFSAASamples(const U32 fsaa_samples) { /* FSAA not supported yet on Mesa headless.*/ }
+	/*virtual*/ U32	 getFSAASamples() { return 0; }
 	//virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
 	/*virtual*/ void gatherInput() {};
 	/*virtual*/ void delayInputProcessing() {};
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 686be3385ec..122b57a4976 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -81,7 +81,7 @@ static BOOL was_fullscreen = FALSE;
 
 void maybe_lock_display(void)
 {
-	if (gWindowImplementation) {
+	if (gWindowImplementation && gWindowImplementation->Lock_Display) {
 		gWindowImplementation->Lock_Display();
 	}
 }
@@ -89,7 +89,7 @@ void maybe_lock_display(void)
 
 void maybe_unlock_display(void)
 {
-	if (gWindowImplementation) {
+	if (gWindowImplementation && gWindowImplementation->Unlock_Display) {
 		gWindowImplementation->Unlock_Display();
 	}
 }
@@ -217,7 +217,7 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
 							   S32 height, U32 flags,
 							   BOOL fullscreen, BOOL clearBg,
 							   BOOL disable_vsync, BOOL use_gl,
-							   BOOL ignore_pixel_depth)
+							   BOOL ignore_pixel_depth, U32 fsaa_samples)
 	: LLWindow(fullscreen, flags), mGamma(1.0f)
 {
 	// Initialize the keyboard
@@ -236,6 +236,7 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
 	mReallyCapturedCount = 0;
 	mHaveInputFocus = -1;
 	mIsMinimized = -1;
+	mFSAASamples = fsaa_samples;
 
 #if LL_X11
 	mSDL_XWindowID = None;
@@ -260,7 +261,7 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
 	mWindowTitle = new char[strlen(title) + 1]; /* Flawfinder: ignore */
 	if(mWindowTitle == NULL)
 	{
-		llerrs << "Memory allocation failure" << llendl;
+		llwarns << "Memory allocation failure" << llendl;
 		return;
 	}
 
@@ -535,6 +536,12 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
 
 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
+	if (mFSAASamples > 0)
+	{
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples);
+	}
+	
     	mSDLFlags = sdlflags;
 
 	if (mFullscreen)
@@ -796,7 +803,6 @@ void LLWindowSDL::destroyContext()
 	gGLManager.shutdownGL();
 	llinfos << "SDL_QuitSS/VID begins" << llendl;
 	SDL_QuitSubSystem(SDL_INIT_VIDEO);  // *FIX: this might be risky...
-	//unload_all_glsyms();
 
 	mWindow = NULL;
 }
@@ -922,10 +928,10 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size)
     {
         size->mX = mWindow->w;
         size->mY = mWindow->h;
-		return (TRUE);
+	return (TRUE);
     }
 
-	llerrs << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
+    llwarns << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
     return (FALSE);
 }
 
@@ -935,10 +941,10 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
     {
         size->mX = mWindow->w;
         size->mY = mWindow->h;
-		return (TRUE);
+	return (TRUE);
     }
 
-	llerrs << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
+    llwarns << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
     return (FALSE);
 }
 
@@ -970,6 +976,16 @@ void LLWindowSDL::swapBuffers()
 		SDL_GL_SwapBuffers();
 }
 
+U32 LLWindowSDL::getFSAASamples()
+{
+	return mFSAASamples;
+}
+
+void LLWindowSDL::setFSAASamples(const U32 samples)
+{
+	mFSAASamples = samples;
+}
+
 F32 LLWindowSDL::getGamma()
 {
 	return 1/mGamma;
@@ -1116,8 +1132,10 @@ F32 LLWindowSDL::getPixelAspectRatio()
 	if (getFullscreen())
 	{
 		LLCoordScreen screen_size;
-		getSize(&screen_size);
-		pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
+		if (getSize(&screen_size))
+		{
+			pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
+		}
 	}
 
 	return pixel_aspect;
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 2c411e03fdd..4d4d36e30a7 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -85,6 +85,8 @@ class LLWindowSDL : public LLWindow
 	/*virtual*/ void flashIcon(F32 seconds);
 	/*virtual*/ F32 getGamma();
 	/*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
+	/*virtual*/ U32 getFSAASamples();
+	/*virtual*/ void setFSAASamples(const U32 samples);
 	/*virtual*/ BOOL restoreGamma();			// Restore original gamma table (before updating gamma)
 	/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
 	/*virtual*/ void gatherInput();
@@ -132,7 +134,7 @@ class LLWindowSDL : public LLWindow
 	LLWindowSDL(
 		char *title, int x, int y, int width, int height, U32 flags,
 		BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
-		BOOL ignore_pixel_depth);
+		BOOL ignore_pixel_depth, U32 fsaa_samples);
 	~LLWindowSDL();
 
 	void	initCursors();
@@ -183,6 +185,7 @@ class LLWindowSDL : public LLWindow
 	LLCoordScreen   mNeedsResizeSize;
 	F32			mOverrideAspectRatio;
 	F32		mGamma;
+	U32		mFSAASamples;
 
 	int		mSDLFlags;
 
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index a5367aac8ae..bcbd2d9cc3d 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -371,10 +371,11 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
 							 S32 height, U32 flags, 
 							 BOOL fullscreen, BOOL clearBg,
 							 BOOL disable_vsync, BOOL use_gl,
-							 BOOL ignore_pixel_depth)
+							 BOOL ignore_pixel_depth,
+							 U32 fsaa_samples)
 	: LLWindow(fullscreen, flags)
 {
-	S32 i = 0;
+	mFSAASamples = fsaa_samples;
 	mIconResource = gIconResource;
 	mOverrideAspectRatio = 0.f;
 	mNativeAspectRatio = 0.f;
@@ -389,7 +390,6 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
 	// based on the system's (user's) default settings.
 	allowLanguageTextInput(mPreeditor, FALSE);
 
-	GLuint			pixel_format;
 	WNDCLASS		wc;
 	DWORD			dw_ex_style;
 	DWORD			dw_style;
@@ -651,366 +651,13 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
 	//-----------------------------------------------------------------------
 	// Create GL drawing context
 	//-----------------------------------------------------------------------
-	PIXELFORMATDESCRIPTOR pfd =
+	if (!switchContext(mFullscreen, LLCoordScreen(window_rect.right - window_rect.left,			// width
+												  window_rect.bottom - window_rect.top),			// height
+												  TRUE))
 	{
-		sizeof(PIXELFORMATDESCRIPTOR), 
-			1,
-			pfdflags, 
-			PFD_TYPE_RGBA,
-			BITS_PER_PIXEL,
-			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused
-			8,					// alpha bits
-			0,					// alpha shift
-			0,					// accum bits
-			0, 0, 0, 0,			// accum RGBA
-			24,					// depth bits
-			8,					// stencil bits, avi added for stencil test
-			0,
-			PFD_MAIN_PLANE,
-			0,
-			0, 0, 0
-	};
-
-	if (!(mhDC = GetDC(mWindowHandle)))
-	{
-		close();
-		OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
-		return;
-	}
-
-	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
-	{
-		close();
-		OSMessageBox("Can't find suitable pixel format", "Error", OSMB_OK);
-		return;
-	}
-
-	// Verify what pixel format we actually received.
-	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
-		&pfd))
-	{
-		close();
-		OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
 		return;
 	}
-
-	// sanity check pfd returned by Windows
-	if (!ignore_pixel_depth && (pfd.cColorBits < 32))
-	{
-		close();
-		OSMessageBox(
-			"Second Life requires True Color (32-bit) to run in a window.\n"
-			"Please go to Control Panels -> Display -> Settings and\n"
-			"set the screen to 32-bit color.\n"
-			"Alternately, if you choose to run fullscreen, Second Life\n"
-			"will automatically adjust the screen each time it runs.",
-			"Error",
-			OSMB_OK);
-		return;
-	}
-
-	if (!ignore_pixel_depth && (pfd.cAlphaBits < 8))
-	{
-		close();
-		OSMessageBox(
-			"Second Life is unable to run because it can't get an 8 bit alpha\n"
-			"channel.  Usually this is due to video card driver issues.\n"
-			"Please make sure you have the latest video card drivers installed.\n"
-			"Also be sure your monitor is set to True Color (32-bit) in\n"
-			"Control Panels -> Display -> Settings.\n"
-			"If you continue to receive this message, contact customer service.",
-			"Error",
-			OSMB_OK);
-		return;
-	}
-
-	if (!SetPixelFormat(mhDC, pixel_format, &pfd))
-	{
-		close();
-		OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
-		return;
-	}
-
-	if (use_gl)
-	{
-		if (!(mhRC = wglCreateContext(mhDC)))
-		{
-			close();
-			OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
-			return;
-		}
-
-		if (!wglMakeCurrent(mhDC, mhRC))
-		{
-			close();
-			OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
-			return;
-		}
-
-		gGLManager.initWGL();
-
-		if (gGLManager.mHasWGLARBPixelFormat && (wglChoosePixelFormatARB != NULL))
-		{
-			// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
-			// can get exactly what we want.
-			GLint attrib_list[256];
-			S32 cur_attrib = 0;
-
-			attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
-			attrib_list[cur_attrib++] = 24;
-
-			attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
-			attrib_list[cur_attrib++] = 8;
-
-			attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
-			attrib_list[cur_attrib++] = GL_TRUE;
-
-			attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
-			attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
-
-			attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
-			attrib_list[cur_attrib++] = GL_TRUE;
-
-			attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
-			attrib_list[cur_attrib++] = GL_TRUE;
-
-			attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
-			attrib_list[cur_attrib++] = 32;
-
-			attrib_list[cur_attrib++] = WGL_RED_BITS_ARB;
-			attrib_list[cur_attrib++] = 8;
-
-			attrib_list[cur_attrib++] = WGL_GREEN_BITS_ARB;
-			attrib_list[cur_attrib++] = 8;
-
-			attrib_list[cur_attrib++] = WGL_BLUE_BITS_ARB;
-			attrib_list[cur_attrib++] = 8;
-
-			attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
-			attrib_list[cur_attrib++] = 8;
-
-			// End the list
-			attrib_list[cur_attrib++] = 0;
-
-			GLint pixel_formats[256];
-			U32 num_formats = 0;
-
-			// First we try and get a 32 bit depth pixel format
-			BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-			if (!result)
-			{
-				close();
-				show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
-				return;
-			}
-
-			if (!num_formats)
-			{
-				llinfos << "No 32 bit z-buffer, trying 24 bits instead" << llendl;
-				// Try 24-bit format
-				attrib_list[1] = 24;
-				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-				if (!result)
-				{
-					close();
-					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
-					return;
-				}
-
-				if (!num_formats)
-				{
-					llwarns << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << llendl;
-					attrib_list[1] = 16;
-					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-					if (!result || !num_formats)
-					{
-						close();
-						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
-						return;
-					}
-				}
-
-				llinfos << "Choosing pixel formats: " << num_formats << " pixel formats returned" << llendl;
-
-				pixel_format = pixel_formats[0];
-			}
-
-			DestroyWindow(mWindowHandle);
-
-			mWindowHandle = CreateWindowEx(dw_ex_style,
-				mWindowClassName,
-				mWindowTitle,
-				WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
-				x,								// x pos
-				y,								// y pos
-				window_rect.right - window_rect.left,			// width
-				window_rect.bottom - window_rect.top,			// height
-				NULL,
-				NULL,
-				mhInstance,
-				NULL);
-
-			if (!(mhDC = GetDC(mWindowHandle)))
-			{
-				close();
-				OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
-				return;
-			}
-
-			if (!SetPixelFormat(mhDC, pixel_format, &pfd))
-			{
-				close();
-				OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
-				return;
-			}
-
-			int swap_method = 0;
-			GLint swap_query = WGL_SWAP_METHOD_ARB;
-
-			if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
-			{
-				switch (swap_method)
-				{
-				case WGL_SWAP_EXCHANGE_ARB:
-					mSwapMethod = SWAP_METHOD_EXCHANGE;
-					llinfos << "Swap Method: Exchange" << llendl;
-					break;
-				case WGL_SWAP_COPY_ARB:
-					mSwapMethod = SWAP_METHOD_COPY;
-					llinfos << "Swap Method: Copy" << llendl;
-					break;
-				case WGL_SWAP_UNDEFINED_ARB:
-					mSwapMethod = SWAP_METHOD_UNDEFINED;
-					llinfos << "Swap Method: Undefined" << llendl;
-					break;
-				default:
-					mSwapMethod = SWAP_METHOD_UNDEFINED;
-					llinfos << "Swap Method: Unknown" << llendl;
-					break;
-				}
-			}		
-		}
-		else
-		{
-			llwarns << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << llendl;
-		}
-
-		// Verify what pixel format we actually received.
-		if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
-			&pfd))
-		{
-			close();
-			OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
-			return;
-		}
-		llinfos << "GL buffer: Color Bits " << S32(pfd.cColorBits) 
-			<< " Alpha Bits " << S32(pfd.cAlphaBits)
-			<< " Depth Bits " << S32(pfd.cDepthBits) 
-			<< llendl;
-
-		if (pfd.cColorBits < 32)
-		{
-			close();
-			OSMessageBox(
-				"Second Life requires True Color (32-bit) to run in a window.\n"
-				"Please go to Control Panels -> Display -> Settings and\n"
-				"set the screen to 32-bit color.\n"
-				"Alternately, if you choose to run fullscreen, Second Life\n"
-				"will automatically adjust the screen each time it runs.",
-				"Error",
-				OSMB_OK);
-			return;
-		}
-
-		if (pfd.cAlphaBits < 8)
-		{
-			close();
-			OSMessageBox(
-				"Second Life is unable to run because it can't get an 8 bit alpha\n"
-				"channel.  Usually this is due to video card driver issues.\n"
-				"Please make sure you have the latest video card drivers installed.\n"
-				"Also be sure your monitor is set to True Color (32-bit) in\n"
-				"Control Panels -> Display -> Settings.\n"
-				"If you continue to receive this message, contact customer service.",
-				"Error",
-				OSMB_OK);
-			return;
-		}
-
-		if (!(mhRC = wglCreateContext(mhDC)))
-		{
-			close();
-			OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
-			return;
-		}
-
-		if (!wglMakeCurrent(mhDC, mhRC))
-		{
-			close();
-			OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
-			return;
-		}
-
-		if (!gGLManager.initGL())
-		{
-			close();
-			OSMessageBox(
-				"Second Life is unable to run because your video card drivers\n"
-				"are out of date or unsupported. Please make sure you have\n"
-				"the latest video card drivers installed.\n\n"
-				"If you continue to receive this message, contact customer service.",
-				"Error",
-				OSMB_OK);
-			return;
-		}
-
-		// Disable vertical sync for swap
-		if (disable_vsync && wglSwapIntervalEXT)
-		{
-			llinfos << "Disabling vertical sync" << llendl;
-			wglSwapIntervalEXT(0);
-		}
-		else
-		{
-			llinfos << "Keeping vertical sync" << llendl;
-		}
-
-
-		// OK, let's get the current gamma information and store it off.
-		mCurrentGamma = 0.f; // Not set, default;
-		if (!GetDeviceGammaRamp(mhDC, mPrevGammaRamp))
-		{
-			llwarns << "Unable to get device gamma ramp" << llendl;
-		}
-
-		// Calculate what the current gamma is.  From a posting by Garrett T. Bass, Get/SetDeviceGammaRamp Demystified
-		// http://apollo.iwt.uni-bielefeld.de/~ml_robot/OpenGL-04-2000/0058.html
-
-		// We're going to assume that gamma's the same for all 3 channels, because I don't feel like doing it otherwise.
-		// Using the red channel.
-
-		F32 Csum = 0.0; 
-		S32 Ccount = 0; 
-		for (i = 0; i < 256; i++) 
-		{ 
-			if (i != 0 && mPrevGammaRamp[i] != 0 && mPrevGammaRamp[i] != 65536) 
-			{ 
-				F64 B = (i % 256) / 256.0; 
-				F64 A = mPrevGammaRamp[i] / 65536.0; 
-				F32 C = (F32) ( log(A) / log(B) ); 
-				Csum += C; 
-				Ccount++; 
-			} 
-		} 
-		mCurrentGamma = Csum / Ccount; 
-
-		llinfos << "Previous gamma: " << mCurrentGamma << llendl;
-	}
-
-
-	//store this pointer for wndProc callback
-	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
-
+	
 	//start with arrow cursor
 	initCursors();
 	setCursor( UI_CURSOR_ARROW );
@@ -1018,8 +665,6 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,
 	// Initialize (boot strap) the Language text input management,
 	// based on the system's (or user's) default settings.
 	allowLanguageTextInput(NULL, FALSE);
-
-	initInputDevices();
 }
 
 void LLWindowWin32::initInputDevices()
@@ -1558,17 +1203,19 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disa
 		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
 		attrib_list[cur_attrib++] = 24;
 
-		attrib_list[cur_attrib++] = WGL_RED_BITS_ARB;
-		attrib_list[cur_attrib++] = 8;
-
-		attrib_list[cur_attrib++] = WGL_GREEN_BITS_ARB;
+		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
 		attrib_list[cur_attrib++] = 8;
 
-		attrib_list[cur_attrib++] = WGL_BLUE_BITS_ARB;
-		attrib_list[cur_attrib++] = 8;
+		U32 end_attrib = 0;
+		if (mFSAASamples > 0)
+		{
+			end_attrib = cur_attrib;
+			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
+			attrib_list[cur_attrib++] = GL_TRUE;
 
-		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
-		attrib_list[cur_attrib++] = 8;
+			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
+			attrib_list[cur_attrib++] = mFSAASamples;
+		}
 
 		// End the list
 		attrib_list[cur_attrib++] = 0;
@@ -1587,36 +1234,67 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disa
 
 		if (!num_formats)
 		{
-			llinfos << "No 32 bit z-buffer, trying 24 bits instead" << llendl;
-			// Try 24-bit format
-			attrib_list[1] = 24;
-			BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-			if (!result)
+			if (end_attrib > 0)
 			{
-				close();
-				show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
-				return FALSE;
+				llinfos << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << llendl;
+				attrib_list[end_attrib] = 0;
+
+				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+				if (!result)
+				{
+					close();
+					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
+					return FALSE;
+				}
 			}
 
 			if (!num_formats)
 			{
-				llwarns << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << llendl;
-				attrib_list[1] = 16;
+				llinfos << "No 32 bit z-buffer, trying 24 bits instead" << llendl;
+				// Try 24-bit format
+				attrib_list[1] = 24;
 				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-				if (!result || !num_formats)
+				if (!result)
 				{
 					close();
-					show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
+					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
 					return FALSE;
 				}
+
+				if (!num_formats)
+				{
+					llwarns << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << llendl;
+					attrib_list[1] = 16;
+					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+					if (!result || !num_formats)
+					{
+						close();
+						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
+						return FALSE;
+					}
+				}
 			}
 
 			llinfos << "Choosing pixel formats: " << num_formats << " pixel formats returned" << llendl;
+		}
+
+		pixel_format = pixel_formats[0];
+
+		if (mhDC != 0)											// Does The Window Have A Device Context?
+		{
+			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero
+			if (mhRC != 0)										// Does The Window Have A Rendering Context?
+			{
+				wglDeleteContext (mhRC);							// Release The Rendering Context
+				mhRC = 0;										// Zero The Rendering Context
 
-			pixel_format = pixel_formats[0];
+			}
+			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context
+			mhDC = 0;											// Zero The Device Context
 		}
+		DestroyWindow (mWindowHandle);									// Destroy The Window
+		
 
-		DestroyWindow(mWindowHandle);
 		mWindowHandle = CreateWindowEx(dw_ex_style,
 			mWindowClassName,
 			mWindowTitle,
@@ -2985,6 +2663,16 @@ BOOL LLWindowWin32::setGamma(const F32 gamma)
 	return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
 }
 
+void LLWindowWin32::setFSAASamples(const U32 fsaa_samples)
+{
+	mFSAASamples = fsaa_samples;
+}
+
+U32 LLWindowWin32::getFSAASamples()
+{
+	return mFSAASamples;
+}
+
 LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions)
 {
 	if (!mSupportedResolutions)
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index b21df8981e1..e8eed55aee2 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -78,6 +78,8 @@ class LLWindowWin32 : public LLWindow
 	/*virtual*/ void flashIcon(F32 seconds);
 	/*virtual*/ F32 getGamma();
 	/*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
+	/*virtual*/ void setFSAASamples(const U32 fsaa_samples);
+	/*virtual*/ U32 getFSAASamples();
 	/*virtual*/ BOOL restoreGamma();			// Restore original gamma table (before updating gamma)
 	/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
 	/*virtual*/ void gatherInput();
@@ -118,7 +120,7 @@ class LLWindowWin32 : public LLWindow
 	LLWindowWin32(
 		char *title, char *name, int x, int y, int width, int height, U32 flags, 
 		BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
-		BOOL ignore_pixel_depth);
+		BOOL ignore_pixel_depth, U32 fsaa_samples);
 	~LLWindowWin32();
 
 	void	initCursors();
@@ -184,6 +186,7 @@ class LLWindowWin32 : public LLWindow
 	static BOOL sIsClassRegistered; // has the window class been registered?
 
 	F32			mCurrentGamma;
+	U32			mFSAASamples;
 	WORD		mPrevGammaRamp[256*3];
 	WORD		mCurrentGammaRamp[256*3];
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 9cc61b48272..16b278c01c2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5632,7 +5632,7 @@
         <key>Type</key>
             <string>Boolean</string>
         <key>Value</key>
-            <integer>0</integer>
+            <integer>1</integer>
         </map>
     <key>RenderUseFarClip</key>
         <map>
@@ -9600,5 +9600,60 @@
 		<key>Value</key>
 			<integer>1</integer>
 		</map>
+    <key>RenderDeferred</key>
+		<map>
+		<key>Comment</key>
+			<string>Use deferred rendering pipeline.</string>
+		<key>Persist</key>
+			<integer>1</integer>
+		<key>Type</key>
+			<string>Boolean</string>
+		<key>Value</key>
+			<integer>0</integer>
+		</map>
+    <key>RenderFSAASamples</key>
+		<map>
+		<key>Comment</key>
+			<string>Number of samples to use for FSAA (0 = no AA).</string>
+		<key>Persist</key>
+			<integer>1</integer>
+		<key>Type</key>
+			<string>U32</string>
+		<key>Value</key>
+			<integer>0</integer>
+		</map>
+    <key>RenderTextureMemoryMultiple</key>
+		<map>
+		<key>Comment</key>
+			<string>Multiple of texture memory value to use (should fit: 0 &lt; value &lt;= 1.0)</string>
+		<key>Persist</key>
+			<integer>1</integer>
+		<key>Type</key>
+			<string>F32</string>
+		<key>Value</key>
+			<real>1.0</real>
+		</map>
+    <key>Disregard128DefaultDrawDistance</key>
+		<map>
+		<key>Comment</key>
+			<string>Whether to use the auto default to 128 draw distance</string>
+		<key>Persist</key>
+			<integer>1</integer>
+		<key>Type</key>
+			<string>Boolean</string>
+		<key>Value</key>
+			<real>1</real>
+		</map>
+    <key>Disregard96DefaultDrawDistance</key>
+		<map>
+		<key>Comment</key>
+			<string>Whether to use the auto default to 96 draw distance</string>
+		<key>Persist</key>
+			<integer>1</integer>
+		<key>Type</key>
+			<string>Boolean</string>
+		<key>Value</key>
+			<real>1</real>
+		</map>
     </map>
 </llsd>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
new file mode 100644
index 00000000000..14e6361f83f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -0,0 +1,16 @@
+/** 
+ * @file diffuseF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2D diffuseMap;
+
+varying vec3 vary_normal;
+
+void main() 
+{
+	gl_FragColor = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+	gl_FragColor.rgb = vary_normal*0.5+0.5;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
new file mode 100644
index 00000000000..8e9069368ae
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -0,0 +1,22 @@
+/** 
+ * @file diffuseV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec3 vary_normal;
+varying vec3 vary_position;
+
+void main()
+{
+	//transform vertex
+	gl_Position = ftransform(); 
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	
+	vary_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
+	
+	vary_normal = normalize(gl_NormalMatrix * gl_Normal);
+
+	gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index 1c14381df94..7b9e4ff828d 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -86,7 +86,7 @@ void main()
 	color.rgb = mix(mix(fogCol.rgb, fb.rgb, fogCol.a), refcol.rgb, df);
 	color.rgb += spec * specular;
 	
-	color.rgb = atmosTransport(color.rgb);
+	color.rgb = applyWaterFog(color);//atmosTransport(color.rgb);
 	color.rgb = scaleSoftClip(color.rgb);
 	color.a = spec * sunAngle2;
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index 59e44fa871e..7ee41998e2b 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -8,11 +8,11 @@
 vec4 applyWaterFog(vec4 color)
 {
 	// GL_EXP2 Fog
-	float fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);
+	//float fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);
 	// GL_EXP Fog
 	// float fog = exp(-gl_Fog.density * gl_FogFragCoord);
 	// GL_LINEAR Fog
-	// float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
+	float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
 	fog = clamp(fog, 0.0, 1.0);
 	color.rgb = mix(gl_Fog.color.rgb, color.rgb, fog);
 	return color;
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index d3327981030..48ac87ef073 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -63,9 +63,8 @@ void main()
 	//pass wave parameters to pixel shader
 	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + d1 * time * 0.055;
 	//get two normal map (detail map) texture coordinates
-	littleWave.xy = (v.xy) * vec2(0.6, 1.2)   + d2 * time * 0.05;
-	// littleWave.zw = (v.xy) * vec2(0.07, 0.15) - d1 * time * 0.043;
-	littleWave.zw = (v.xy) * vec2(0.3, 0.6) + d1 * time * 0.1;
+	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + d2 * time * 0.13;
+	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
 	view.w = bigWave.y;
 	refCoord.w = bigWave.x;
 	
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
index 9ab986be6d1..071489bca88 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
@@ -9,7 +9,7 @@ uniform sampler2D diffuseMap;
 
 void default_lighting() 
 {
-	color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
 	gl_FragColor = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
index c6f7f8b81bf..89785c45cb9 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
@@ -11,7 +11,7 @@ uniform samplerCube environmentMap;
 
 void shiny_lighting() 
 {
-	color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
 	gl_FragColor = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
index 75f61ccdf19..7ac3c359bf4 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
@@ -11,7 +11,7 @@ uniform samplerCube environmentMap;
 
 void shiny_lighting_water() 
 {
-	color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+	vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
 	gl_FragColor = color;
 }
 
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 898751d3f1c..2fcec67c0e9 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -51,6 +51,7 @@ WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 Disregard128DefaultDrawDistance	1	1
 Disregard96DefaultDrawDistance	1	1
+RenderTextureMemoryMultiple		1	1.0
 
 //
 // Low Graphics Settings
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index d7921ffb59f..40aa05d0c63 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -51,6 +51,7 @@ WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 Disregard128DefaultDrawDistance	1	1
 Disregard96DefaultDrawDistance	1	1
+RenderTextureMemoryMultiple		1	1.0
 
 //
 // Low Graphics Settings
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 9645ff8abfb..c17ca7fcad6 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -23,33 +23,36 @@ version 15
 // NOTE: All settings are set to the MIN of applied values, including 'all'!
 //
 list all
-RenderAnisotropic			1	0
-RenderAvatarCloth			0	0
-RenderAvatarLODFactor		1	1.0
-RenderAvatarVP				1	0
-RenderCubeMap				1	1
-RenderFarClip				1	256
-RenderFlexTimeFactor		1	1.0
-RenderFogRatio				1	4.0
-RenderGamma					1	0
-RenderGlowResolutionPow		1	9
-RenderLightingDetail		1	1
-RenderMaxPartCount			1	8192
-RenderNightBrightness		1	1.0
-RenderObjectBump			1	1
-RenderReflectionDetail		1	3
-RenderTerrainDetail			1	1
-RenderTerrainLODFactor		1	2.0
-RenderTreeLODFactor			1	1.0
-RenderUseImpostors			1	1
-RenderVBOEnable				1	1
-RenderVolumeLODFactor		1	2.0
-RenderWaterReflections		1	1
-UseOcclusion				1	1
-VertexShaderEnable			1	1
-WindLightUseAtmosShaders	1	1
-WLSkyDetail					1	128
-RenderUseCleverUI			1	1
+RenderAnisotropic				1	0
+RenderAvatarCloth				0	0
+RenderAvatarLODFactor			1	1.0
+RenderAvatarVP					1	0
+RenderCubeMap					1	1
+RenderFarClip					1	256
+RenderFlexTimeFactor			1	1.0
+RenderFogRatio					1	4.0
+RenderGamma						1	0
+RenderGlowResolutionPow			1	9
+RenderLightingDetail			1	1
+RenderMaxPartCount				1	8192
+RenderNightBrightness			1	1.0
+RenderObjectBump				1	1
+RenderReflectionDetail			1	3
+RenderTerrainDetail				1	1
+RenderTerrainLODFactor			1	2.0
+RenderTreeLODFactor				1	1.0
+RenderUseImpostors				1	1
+RenderVBOEnable					1	1
+RenderVolumeLODFactor			1	2.0
+RenderWaterReflections			1	1
+UseOcclusion					1	1
+VertexShaderEnable				1	1
+WindLightUseAtmosShaders		1	1
+WLSkyDetail						1	128
+RenderUseCleverUI				1	1
+Disregard128DefaultDrawDistance	1	1
+Disregard96DefaultDrawDistance	1	1
+RenderTextureMemoryMultiple		1	0.5
 Disregard128DefaultDrawDistance	1	1
 Disregard96DefaultDrawDistance	1	1
 
@@ -337,6 +340,8 @@ VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 Disregard96DefaultDrawDistance	1	0
 
+list NVIDIA_GeForce_8600
+RenderTextureMemoryMultiple			1	0.375	
 
 /// tweaked ATI to 96 Draw distance
 
diff --git a/indra/newview/featuretable_solaris.txt b/indra/newview/featuretable_solaris.txt
index 7dd7c22cdf0..2a514eaab1f 100644
--- a/indra/newview/featuretable_solaris.txt
+++ b/indra/newview/featuretable_solaris.txt
@@ -34,6 +34,7 @@ RenderParticleCount	1	4096
 RenderRippleWater	1	1
 RenderTerrainDetail	1	2
 VertexShaderEnable	1	1
+RenderTextureMemoryMultiple		1	1.0
 
 //
 // Class 0 Hardware (Unknown or just old)
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index 070d45a5bb5..1b7d6b809ec 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -17,8 +17,7 @@
 ##   on some hardware.  Disabling this option may cause BETTER PERFORMANCE but
 ##   may also cause CRASHES and hangs on some unstable combinations of drivers
 ##   and hardware.
-## NOTE: This is 'off' for WindLight to help testing.  Hopefully it's not
-##   really needed any more anyway.
+## NOTE: This is now disabled by default.
 #export LL_GL_BASICEXT=x
 
 ## - Avoids *all* optional OpenGL extensions.  This is the safest and least-
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0e2d28400de..0a611c9bfa3 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3169,27 +3169,6 @@ void LLAppViewer::idle()
 	}
 	stop_glerror();
 	
-	//////////////////////////////////////
-	//
-	// Update images, using the image stats generated during object update/culling
-	//
-	// Can put objects onto the retextured list.
-	//
-	gFrameStats.start(LLFrameStats::IMAGE_UPDATE);
-
-	{
-		LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE);
-		
-		LLViewerImage::updateClass(gCamera->getVelocityStat()->getMean(),
-									gCamera->getAngularVelocityStat()->getMean());
-
-		gBumpImageList.updateImages();  // must be called before gImageList version so that it's textures are thrown out first.
-
-		const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame)
-		gImageList.updateImages(max_image_decode_time);
-		stop_glerror();
-	}
-
 	//////////////////////////////////////
 	//
 	// Sort and cull in the new renderer are moved to pipeline.cpp
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index ca2f5ebb863..4dfe725731d 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -59,6 +59,7 @@ static float sTime;
 
 BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
 BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
+BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
 LLColor4 LLDrawPoolWater::sWaterFogColor = LLColor4(0.2f, 0.5f, 0.5f, 0.f);
 LLVector3 LLDrawPoolWater::sLightDir;
 
@@ -546,6 +547,7 @@ void LLDrawPoolWater::shade()
 			
 			if (water->getUseTexture())
 			{
+				sNeedsDistortionUpdate = TRUE;
 				face->renderIndexed();
 			}
 			else
@@ -557,6 +559,7 @@ void LLDrawPoolWater::shade()
 				}
 				else
 				{
+					sNeedsDistortionUpdate = TRUE;
 					face->renderIndexed();
 				}
 			}
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index d9b91db85cf..a1b09a5e494 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -50,6 +50,7 @@ class LLDrawPoolWater: public LLFacePool
 public:
 	static BOOL sSkipScreenCopy;
 	static BOOL sNeedsReflectionUpdate;
+	static BOOL sNeedsDistortionUpdate;
 	static LLVector3 sLightDir;
 
 	static LLColor4 sWaterFogColor;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index c1194fa99ee..f0ac46b7d61 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -113,10 +113,6 @@ static struct ft_display_info ft_display_table[] =
 	{ LLFastTimer::FTM_PIPELINE,			"     Pipeline",	&LLColor4::magenta4, 0 },
 	{ LLFastTimer::FTM_CLEANUP,				"  Cleanup",		&LLColor4::cyan3, 0 },
 	{ LLFastTimer::FTM_AUDIO_UPDATE,		"  Audio Update",	&LLColor4::yellow3, 0 },
-	{ LLFastTimer::FTM_IMAGE_UPDATE,		"  Image Update",	&LLColor4::yellow4, 1 },
-	{ LLFastTimer::FTM_IMAGE_CREATE,		"   Image CreateGL",&LLColor4::yellow5, 0 },
-	{ LLFastTimer::FTM_IMAGE_DECODE,		"   Image Decode",	&LLColor4::yellow6, 0 },
-	{ LLFastTimer::FTM_IMAGE_MARK_DIRTY,	"   Dirty Textures",&LLColor4::red1, 0 },
 	{ LLFastTimer::FTM_VFILE_WAIT,			"  VFile Wait",		&LLColor4::cyan6, 0 },
 //	{ LLFastTimer::FTM_IDLE_CB,				"  Callbacks",		&LLColor4::pink1, 0 },
 	{ LLFastTimer::FTM_RENDER,				" Render",			&green0, 1 },
@@ -146,6 +142,10 @@ static struct ft_display_info ft_display_table[] =
     { LLFastTimer::FTM_CULL_REBOUND,		"   Rebound",		&LLColor4::blue3, 0 },
 	{ LLFastTimer::FTM_FRUSTUM_CULL,		"   Frustum Cull",	&LLColor4::blue4, 0 },
 	{ LLFastTimer::FTM_OCCLUSION_READBACK,	"   Occlusion Read", &LLColor4::red2, 0 },
+	{ LLFastTimer::FTM_IMAGE_UPDATE,		"  Image Update",	&LLColor4::yellow4, 1 },
+	{ LLFastTimer::FTM_IMAGE_CREATE,		"   Image CreateGL",&LLColor4::yellow5, 0 },
+	{ LLFastTimer::FTM_IMAGE_DECODE,		"   Image Decode",	&LLColor4::yellow6, 0 },
+	{ LLFastTimer::FTM_IMAGE_MARK_DIRTY,	"   Dirty Textures",&LLColor4::red1, 0 },
 	{ LLFastTimer::FTM_STATESORT,			"  State Sort",	&LLColor4::orange1, 1 },
 	{ LLFastTimer::FTM_STATESORT_DRAWABLE,	"   Drawable",		&LLColor4::orange2, 0 },
 	{ LLFastTimer::FTM_STATESORT_POSTSORT,	"   Post Sort",	&LLColor4::orange3, 0 },
diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp
index 00dcf674538..a3c3acd3bbc 100644
--- a/indra/newview/llfloaterhardwaresettings.cpp
+++ b/indra/newview/llfloaterhardwaresettings.cpp
@@ -77,11 +77,13 @@ void LLFloaterHardwareSettings::refresh()
 
 	mUseVBO = gSavedSettings.getBOOL("RenderVBOEnable");
 	mUseAniso = gSavedSettings.getBOOL("RenderAnisotropic");
+	mFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
 	mGamma = gSavedSettings.getF32("RenderGamma");
 	mVideoCardMem = gSavedSettings.getS32("TextureMemory");
 	mFogRatio = gSavedSettings.getF32("RenderFogRatio");
 	mProbeHardwareOnStartup = gSavedSettings.getBOOL("ProbeHardwareOnStartup");
 
+	childSetValue("fsaa", (LLSD::Integer) mFSAASamples);
 	refreshEnabledState();
 }
 
@@ -175,9 +177,25 @@ void LLFloaterHardwareSettings::apply()
 	// Anisotropic rendering
 	BOOL old_anisotropic = LLImageGL::sGlobalUseAnisotropic;
 	LLImageGL::sGlobalUseAnisotropic = childGetValue("ani");
-	if (old_anisotropic != LLImageGL::sGlobalUseAnisotropic)
+
+	U32 fsaa = (U32) childGetValue("fsaa").asInteger();
+	U32 old_fsaa = gSavedSettings.getU32("RenderFSAASamples");
+
+	BOOL logged_in = (LLStartUp::getStartupState() >= STATE_STARTED);
+
+	if (old_fsaa != fsaa)
+	{
+		gSavedSettings.setU32("RenderFSAASamples", fsaa);
+		LLWindow* window = gViewerWindow->getWindow();
+		LLCoordScreen size;
+		window->getSize(&size);
+		gViewerWindow->changeDisplaySettings(window->getFullscreen(), 
+														size,
+														gSavedSettings.getBOOL("DisableVerticalSync"),
+														logged_in);
+	}
+	else if (old_anisotropic != LLImageGL::sGlobalUseAnisotropic)
 	{
-		BOOL logged_in = (LLStartUp::getStartupState() >= STATE_STARTED);
 		gViewerWindow->restartDisplay(logged_in);
 	}
 
@@ -189,6 +207,7 @@ void LLFloaterHardwareSettings::cancel()
 {
 	gSavedSettings.setBOOL("RenderVBOEnable", mUseVBO);
 	gSavedSettings.setBOOL("RenderAnisotropic", mUseAniso);
+	gSavedSettings.setU32("RenderFSAASamples", mFSAASamples);
 	gSavedSettings.setF32("RenderGamma", mGamma);
 	gSavedSettings.setS32("TextureMemory", mVideoCardMem);
 	gSavedSettings.setF32("RenderFogRatio", mFogRatio);
diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h
index 0f5f2fee054..2012a0aa2f8 100644
--- a/indra/newview/llfloaterhardwaresettings.h
+++ b/indra/newview/llfloaterhardwaresettings.h
@@ -88,6 +88,7 @@ class LLFloaterHardwareSettings : public LLFloater
 
 	BOOL mUseVBO;
 	BOOL mUseAniso;
+	U32 mFSAASamples;
 	F32 mGamma;
 	S32 mVideoCardMem;
 	F32 mFogRatio;
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index d9694a7b3f8..1af6683218f 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -75,10 +75,14 @@
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
 ///----------------------------------------------------------------------------
+S32 LLFloaterSnapshot::sUIWinHeightLong = 526 ;
+S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 230 ;
+S32 LLFloaterSnapshot::sUIWinWidth = 215 ;
 
 LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
 
 LLFloaterSnapshot* LLFloaterSnapshot::sInstance = NULL;
+
 const F32 SNAPSHOT_TIME_DELAY = 1.f;
 
 F32 SHINE_TIME = 0.5f;
@@ -88,7 +92,7 @@ F32 FALL_TIME = 0.6f;
 S32 BORDER_WIDTH = 6;
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
-#define MAX_TEXTURE_SIZE 512 //max upload texture size 512 * 512
+const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
 ///----------------------------------------------------------------------------
 /// Class LLSnapshotLivePreview 
 ///----------------------------------------------------------------------------
@@ -120,19 +124,30 @@ class LLSnapshotLivePreview : public LLView
 	ESnapshotType getSnapshotType() const { return mSnapshotType; }
 	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
 	BOOL isSnapshotActive() { return mSnapshotActive; }
+	LLImageGL* getThumbnailImage() const { return mThumbnailImage ; }
+	S32  getThumbnailWidth() const { return mThumbnailWidth ; }
+	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
+	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
+	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
 	LLImageGL* getCurrentImage();
 	F32 getImageAspect();
+	F32 getAspect() ;
 	LLRect getImageRect();
 	BOOL isImageScaled();
 	
 	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
 	void setSnapshotQuality(S32 quality);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
-	void updateSnapshot(BOOL new_snapshot);
+	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE);
 	LLFloaterPostcard* savePostcard();
 	void saveTexture();
 	BOOL saveLocal();
 
+	BOOL setThumbnailImageSize() ;
+	void generateThumbnailImage(BOOL force_update = FALSE) ;
+	void resetThumbnailImage() { mThumbnailImage = NULL ; }
+	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
+
 	static void onIdle( void* snapshot_preview );
 
 protected:
@@ -144,6 +159,14 @@ class LLSnapshotLivePreview : public LLView
 	BOOL						mImageScaled[2];
 	S32                         mMaxImageSize ;
 	
+	//thumbnail image
+	LLPointer<LLImageGL>		mThumbnailImage ;
+	S32                         mThumbnailWidth ;
+	S32                         mThumbnailHeight ;
+	LLRect                      mPreviewRect ;
+	BOOL                        mThumbnailUpdateLock ;
+	BOOL                        mThumbnailUpToDate ;
+
 	S32							mCurImageIndex;
 	LLPointer<LLImageRaw>		mRawImage;
 	LLPointer<LLImageRaw>		mRawImageEncoded;
@@ -170,12 +193,12 @@ class LLSnapshotLivePreview : public LLView
 };
 
 std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
-
 LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : 
 	LLView("snapshot_live_preview", rect, FALSE), 
 	mColor(1.f, 0.f, 0.f, 0.5f), 
 	mCurImageIndex(0),
 	mRawImage(NULL),
+	mThumbnailImage(NULL) ,
 	mRawImageEncoded(NULL),
 	mJPEGImage(NULL),
 	mShineCountdown(0),
@@ -204,6 +227,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) :
 
 	mMaxImageSize = MAX_IMAGE_SIZE ;
 	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
+	mThumbnailUpdateLock = FALSE ;
+	mThumbnailUpToDate   = FALSE ;
 }
 
 LLSnapshotLivePreview::~LLSnapshotLivePreview()
@@ -234,13 +259,8 @@ LLImageGL* LLSnapshotLivePreview::getCurrentImage()
 	return mViewerImage[mCurImageIndex];
 }
 
-F32 LLSnapshotLivePreview::getImageAspect()
+F32 LLSnapshotLivePreview::getAspect()
 {
-	if (!mViewerImage[mCurImageIndex])
-	{
-		return 0.f;
-	}
-
 	F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]);
 	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
 
@@ -254,6 +274,16 @@ F32 LLSnapshotLivePreview::getImageAspect()
 	}
 }
 
+F32 LLSnapshotLivePreview::getImageAspect()
+{
+	if (!mViewerImage[mCurImageIndex])
+	{
+		return 0.f;
+	}
+
+	return getAspect() ;	
+}
+
 LLRect LLSnapshotLivePreview::getImageRect()
 {
 	return mImageRect[mCurImageIndex];
@@ -264,7 +294,7 @@ BOOL LLSnapshotLivePreview::isImageScaled()
 	return mImageScaled[mCurImageIndex];
 }
 
-void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot) 
+void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail) 
 { 
 	if (mSnapshotUpToDate)
 	{
@@ -272,15 +302,9 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot)
 		mCurImageIndex = (mCurImageIndex + 1) % 2; 
 		mWidth[mCurImageIndex] = mWidth[old_image_index];
 		mHeight[mCurImageIndex] = mHeight[old_image_index];
-		mFallAnimTimer.start();
-	}
-	mSnapshotUpToDate = FALSE; 
-	mShineAnimTimer.stop();
-	if (new_snapshot)
-	{
-		mSnapshotDelayTimer.start();
-		mSnapshotDelayTimer.setTimerExpirySec(SNAPSHOT_TIME_DELAY);
+		mFallAnimTimer.start();		
 	}
+	mSnapshotUpToDate = FALSE; 		
 
 	LLRect& rect = mImageRect[mCurImageIndex];
 	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
@@ -305,6 +329,21 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot)
 			rect.mRight -= (getRect().getWidth() - new_width) / 2;
 		}
 	}
+
+	mShineAnimTimer.stop();
+	if (new_snapshot)
+	{
+		mSnapshotDelayTimer.start();
+		mSnapshotDelayTimer.setTimerExpirySec(SNAPSHOT_TIME_DELAY);
+	}
+	else if(new_thumbnail)
+	{
+		mThumbnailUpToDate = FALSE ;
+	}
+	else
+	{
+		setThumbnailImageSize() ;
+	}
 }
 
 void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
@@ -326,6 +365,45 @@ LLString LLSnapshotLivePreview::getWidgetTag() const
 	return LL_SNAPSHOT_LIVE_PREVIEW_TAG;
 }
 
+void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
+{
+	F32 line_width ; 
+	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
+	glLineWidth(2.0f * line_width) ;
+	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
+	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
+		        mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
+	glLineWidth(line_width) ;
+
+	//draw four alpha rectangles to cover areas outside of the snapshot image
+	if(!mKeepAspectRatio)
+	{
+		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
+		S32 dwl = 0, dwr = 0 ;
+		if(mThumbnailWidth > mPreviewRect.getWidth())
+		{
+			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
+			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
+
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
+		        mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
+		        mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+		}
+
+		if(mThumbnailHeight > mPreviewRect.getHeight())
+		{
+			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
+		        mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
+
+			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
+			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
+		        mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
+		}
+	}
+}
+
 void LLSnapshotLivePreview::draw()
 {
 	if(getVisible()) 
@@ -519,14 +597,137 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
 	LLView::reshape(width, height, called_from_parent);
 	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
 	{
-		updateSnapshot(getSnapshotUpToDate());
+		updateSnapshot(FALSE, TRUE);
+	}
+}
+
+BOOL LLSnapshotLivePreview::setThumbnailImageSize()
+{
+	if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
+	{
+		return FALSE ;
+	}
+	S32 window_width = gViewerWindow->getWindowDisplayWidth() ;
+	S32 window_height = gViewerWindow->getWindowDisplayHeight() ;
+
+	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
+
+	// UI size for thumbnail
+	S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20;
+	S32 max_height = 90;
+
+	if (window_aspect_ratio > (F32)max_width / max_height)
+	{
+		// image too wide, shrink to width
+		mThumbnailWidth = max_width;
+		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
+	}
+	else
+	{
+		// image too tall, shrink to height
+		mThumbnailHeight = max_height;
+		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
+	}
+	
+	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
+	{
+		return FALSE ;//if the window is too small, ignore thumbnail updating.
+	}
+
+	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
+	if(!mKeepAspectRatio)
+	{
+		F32 ratio_x = (F32)mWidth[mCurImageIndex] / window_width ;
+		F32 ratio_y = (F32)mHeight[mCurImageIndex] / window_height ;
+
+		//if(mWidth[mCurImageIndex] > window_width ||
+		//	mHeight[mCurImageIndex] > window_height )
+		{
+			if(ratio_x > ratio_y)
+			{
+				top = (S32)(top * ratio_y / ratio_x) ;
+			}
+			else
+			{
+				right = (S32)(right * ratio_x / ratio_y) ;
+			}			
+		}
+		//else
+		//{
+		//	right = (S32)(right * ratio_x) ;
+		//	top = (S32)(top * ratio_y) ;
+		//}
+		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
+		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
+		top += bottom ;
+		right += left ;
+	}
+	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
+
+	return TRUE ;
+}
+
+void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
+{	
+	if(mThumbnailUpdateLock) //in the process of updating
+	{
+		return ;
+	}
+	if(mThumbnailUpToDate && !force_update)//already updated
+	{
+		return ;
+	}
+	if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10)
+	{
+		return ;
+	}
+
+	////lock updating
+	mThumbnailUpdateLock = TRUE ;
+
+	if(!setThumbnailImageSize())
+	{
+		mThumbnailUpdateLock = FALSE ;
+		mThumbnailUpToDate = TRUE ;
+		return ;
+	}
+
+	if(mThumbnailImage)
+	{
+		resetThumbnailImage() ;
+	}		
+
+	LLPointer<LLImageRaw> raw = NULL ;
+	S32 w , h ;
+	w = get_nearest_power_two(mThumbnailWidth, 512) * 2 ;
+	h = get_nearest_power_two(mThumbnailHeight, 512) * 2 ;
+
+	{
+		raw = new LLImageRaw ;
+		if(!gViewerWindow->thumbnailSnapshot(raw,
+								w, h,
+								gSavedSettings.getBOOL("RenderUIInSnapshot"),
+								FALSE,
+								mSnapshotBufferType) )								
+		{
+			raw = NULL ;
+		}
+	}
+
+	if(raw)
+	{
+		mThumbnailImage = new LLImageGL(raw, FALSE); 		
+		mThumbnailUpToDate = TRUE ;
 	}
+
+	//unlock updating
+	mThumbnailUpdateLock = FALSE ;		
 }
 
 //static 
 void LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 {
-	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;	
 
 	LLVector3 new_camera_pos = gCamera->getOrigin();
 	LLQuaternion new_camera_rot = gCamera->getQuaternion();
@@ -637,6 +838,7 @@ void LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 			previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE);
 
 			previewp->mSnapshotUpToDate = TRUE;
+			previewp->generateThumbnailImage(TRUE) ;
 
 			previewp->mPosTakenGlobal = gAgent.getCameraPositionGlobal();
 			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
@@ -647,6 +849,10 @@ void LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		previewp->mSnapshotDelayTimer.stop();
 		previewp->mSnapshotActive = FALSE;
 	}
+	if(!previewp->getThumbnailUpToDate())
+	{
+		previewp->generateThumbnailImage() ;
+	}
 }
 
 void LLSnapshotLivePreview::setSize(S32 w, S32 h)
@@ -759,7 +965,8 @@ class LLFloaterSnapshot::Impl
 	static void onCommitLayerTypes(LLUICtrl* ctrl, void*data);
 	static void onCommitSnapshotType(LLUICtrl* ctrl, void* data);
 	static void onCommitCustomResolution(LLUICtrl *ctrl, void* data);
-	static void checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
+	static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ;
+	static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value);
 
 	static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
 	static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname);
@@ -773,7 +980,7 @@ class LLFloaterSnapshot::Impl
 	static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater);
 	static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater);
 	static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname);
-	static void checkAutoSnapshot(LLSnapshotLivePreview* floater);
+	static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE);
 	static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ;
 
 public:
@@ -840,7 +1047,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 {
 	LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
 
-	S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : -230 ;
+	S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ;
 
 	LLComboBox* combo;
 	if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution
@@ -869,7 +1076,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 		floaterp->getParent()->setMouseOpaque(TRUE);
 		
 		// shrink to smaller layout
-		floaterp->reshape(floaterp->getRect().getWidth(), 526 + delta_height);
+		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height);
 
 		// can see and interact with fullscreen preview now
 		if (previewp)
@@ -902,7 +1109,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 	else // turning off freeze frame mode
 	{
 		floaterp->getParent()->setMouseOpaque(FALSE);
-		floaterp->reshape(floaterp->getRect().getWidth(), 526 + delta_height);
+		floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height);
 		if (previewp)
 		{
 			previewp->setVisible(FALSE);
@@ -1051,11 +1258,11 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 }
 
 // static
-void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp)
+void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, BOOL update_thumbnail)
 {
 	if (previewp)
 	{		
-		previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"));
+		previewp->updateSnapshot(gSavedSettings.getBOOL("AutoSnapshot"), update_thumbnail);
 	}
 }
 
@@ -1143,16 +1350,13 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
 
 void LLFloaterSnapshot::Impl::onClickMore(void* data)
 {
-	//floater->childSetVisible("more_btn", FALSE);
-	//floater->childSetVisible("less_btn", TRUE);
-
 	gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE );
 	
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		
 	if (view)
 	{
-		view->translate( 0, -230 );
-		view->reshape(view->getRect().getWidth(), 526);
+		view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() );
+		view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong());
 
 		updateControls(view) ;
 		updateLayout(view) ;
@@ -1160,40 +1364,24 @@ void LLFloaterSnapshot::Impl::onClickMore(void* data)
 }
 void LLFloaterSnapshot::Impl::onClickLess(void* data)
 {
-	//floater->childSetVisible("less_btn", FALSE);
-	//floater->childSetVisible("more_btn", TRUE);
-
 	gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE );
 	
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		
 	if (view)
 	{
-		view->translate( 0, 230 );
-		view->reshape(view->getRect().getWidth(), 294);
+		view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() );
+		view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort());
 
 		updateControls(view) ;
 		updateLayout(view) ;
+
+		if(getPreviewView(view))
+		{
+			getPreviewView(view)->setThumbnailImageSize() ;
+		}
 	}
 }
 
-//void LLFloaterSnapshot::Impl::onClickAdvanceSnap(LLUICtrl *ctrl, void* data)
-//{
-//	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
-//	gSavedSettings.setBOOL( "AdvanceSnapshot", check->get() );
-//	
-//	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		
-//	if (view)
-//	{
-//		S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : -230 ;
-//
-//		view->translate( 0, delta_height ? 230 : -230 );
-//		view->reshape(view->getRect().getWidth(), 526 + delta_height);
-//
-//		updateControls(view) ;
-//		updateLayout(view) ;
-//	}
-//}
-
 // static
 void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
 {
@@ -1203,7 +1391,7 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
 	if (view)
 	{
-		checkAutoSnapshot(getPreviewView(view));
+		checkAutoSnapshot(getPreviewView(view), TRUE);
 	}
 }
 
@@ -1216,7 +1404,7 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data)
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
 	if (view)
 	{
-		checkAutoSnapshot(getPreviewView(view));
+		checkAutoSnapshot(getPreviewView(view), TRUE);
 	}
 }
 
@@ -1244,23 +1432,14 @@ void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data)
 
 			S32 w, h ;
 			previewp->getSize(w, h) ;
-			checkImageSize(previewp, w, h, TRUE, previewp->getMaxImageSize()) ;
-			previewp->setSize(w, h) ;
-
-			//update textbox
-			LLSpinCtrl *sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_width") ;
-			if(sctrl)
+			if(checkImageSize(previewp, w, h, TRUE, previewp->getMaxImageSize()))
 			{
-				sctrl->setValue(w) ;
+				resetSnapshotSizeOnUI(view, w, h) ;
 			}
 
-			sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_height") ;
-			if(sctrl)
-			{
-				sctrl->setValue(h) ;
-			}
+			previewp->setSize(w, h) ;
 
-			checkAutoSnapshot(previewp);
+			checkAutoSnapshot(previewp, TRUE);
 		}
 	}
 }
@@ -1276,7 +1455,7 @@ void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data)
 	{
 		previewp->setSnapshotQuality(quality_val);
 	}
-	checkAutoSnapshot(previewp);
+	checkAutoSnapshot(previewp, TRUE);
 }
 
 // static
@@ -1300,6 +1479,12 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
 {
 	LLSnapshotLivePreview *previewp = getPreviewView(view) ;
 	
+	if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getTypeIndex(view))
+	{
+		previewp->mKeepAspectRatio = FALSE ;
+		return ;
+	}
+
 	if(!index) //current window size
 	{
 		sAspectRatioCheckOff = TRUE ;
@@ -1385,13 +1570,17 @@ void LLFloaterSnapshot::Impl::onCommitResolution(LLUICtrl* ctrl, void* data)
 		checkAspectRatio(view, width) ;
 
 		previewp->getSize(width, height);
-		checkImageSize(previewp, width, height, TRUE, previewp->getMaxImageSize()) ;
+	
+		if(checkImageSize(previewp, width, height, TRUE, previewp->getMaxImageSize()))
+		{
+			resetSnapshotSizeOnUI(view, width, height) ;
+		}
 		previewp->setSize(width, height);
 
 		view->childSetValue("snapshot_width", width);
 		view->childSetValue("snapshot_height", height);
 		// hide old preview as the aspect ratio could be wrong
-		checkAutoSnapshot(previewp);
+		checkAutoSnapshot(previewp, FALSE);
 	}
 }
 
@@ -1409,7 +1598,7 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)
 		{
 			previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex());
 		}
-		checkAutoSnapshot(previewp);
+		checkAutoSnapshot(previewp, TRUE);
 	}
 }
 
@@ -1440,8 +1629,11 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s
 
 
 //static
-void LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
+BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value)
 {
+	S32 w = width ;
+	S32 h = height ;
+
 	//if texture, ignore aspect ratio setting, round image size to power of 2.
 	if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == gSavedSettings.getS32("LastSnapshotType"))
 	{
@@ -1457,15 +1649,12 @@ void LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3
 		//round to nearest power of 2
 		width = get_nearest_power_two(width, MAX_TEXTURE_SIZE) ;
 		height = get_nearest_power_two(height, MAX_TEXTURE_SIZE) ;
-
-		return ;
 	}
-
-	if(previewp && previewp->mKeepAspectRatio)
+	else if(previewp && previewp->mKeepAspectRatio)
 	{
 		if(gViewerWindow->getWindowDisplayWidth() < 1 || gViewerWindow->getWindowDisplayHeight() < 1)
 		{
-			return ;
+			return FALSE ;
 		}
 
 		//aspect ratio of the current window
@@ -1499,7 +1688,27 @@ void LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3
 	else
 	{
 	}
-	return ;
+
+	return (w != width || h != height) ;
+}
+
+//static
+void LLFloaterSnapshot::Impl::resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height)
+{
+	LLSpinCtrl *sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_width") ;
+	if(sctrl)
+	{
+		sctrl->setValue(width) ;
+	}
+
+	sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_height") ;
+	if(sctrl)
+	{
+		sctrl->setValue(height) ;
+	}
+
+	gSavedSettings.setS32("LastSnapshotWidth", width);
+	gSavedSettings.setS32("LastSnapshotHeight", height);
 }
 
 //static
@@ -1522,35 +1731,14 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat
 			
 			if (w != curw || h != curh)
 			{
-				S32 width = w ;
-				S32 height = h ;
-				
 				previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ;
-				checkImageSize(previewp, width, height, width != curw, previewp->getMaxImageSize()) ;
-
-				if(width != w || height != h)
+				if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()))
 				{
-					LLSpinCtrl *sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_width") ;
-					if(sctrl)
-					{
-						sctrl->setValue(width) ;
-					}
-
-					sctrl = LLViewerUICtrlFactory::getSpinnerByName(view, "snapshot_height") ;
-					if(sctrl)
-					{
-						sctrl->setValue(height) ;
-					}
-
-					w = width ;
-					h = height ;
-
-					gSavedSettings.setS32("LastSnapshotWidth", w);
-					gSavedSettings.setS32("LastSnapshotHeight", h);
+					resetSnapshotSizeOnUI(view, w, h) ;
 				}
 
 				previewp->setSize(w,h);
-				checkAutoSnapshot(previewp);
+				checkAutoSnapshot(previewp, FALSE);
 				comboSetCustom(view, "postcard_size_combo");
 				comboSetCustom(view, "texture_size_combo");
 				comboSetCustom(view, "local_size_combo");
@@ -1664,7 +1852,7 @@ void LLFloaterSnapshot::draw()
 {
 	LLSnapshotLivePreview* previewp = impl.getPreviewView(this);
 
-	if (previewp && previewp->isSnapshotActive())
+	if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
 	{
 		// don't render snapshot window in snapshot, even if "show ui" is turned on
 		return;
@@ -1720,7 +1908,7 @@ void LLFloaterSnapshot::draw()
 	LLFloater::draw();
 
 	// draw snapshot thumbnail if not in fullscreen preview mode
-	if (/*!gSavedSettings.getBOOL("UseFreezeFrame") &&*/ previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate())
+	/*if (previewp && previewp->getCurrentImage() && previewp->getSnapshotUpToDate())
 	{
 		F32 aspect = previewp->getImageAspect();
 		// UI size for thumbnail
@@ -1757,6 +1945,21 @@ void LLFloaterSnapshot::draw()
 		glMatrixMode(GL_TEXTURE);
 		glPopMatrix();
 		glMatrixMode(GL_MODELVIEW);
+	}*/
+	if (previewp)
+	{		
+		if(previewp->getThumbnailImage())
+		{
+			S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ;
+			S32 offset_y = getRect().getHeight() - 205 + (90 - previewp->getThumbnailHeight()) / 2 ;
+
+			glMatrixMode(GL_MODELVIEW);
+			gl_draw_scaled_image(offset_x, offset_y, 
+					previewp->getThumbnailWidth(), previewp->getThumbnailHeight(), 
+					previewp->getThumbnailImage(), LLColor4::white);	
+
+			previewp->drawPreviewRect(offset_x, offset_y) ;
+		}
 	}
 }
 
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index cf1e6bd8f80..fecc3f0fd58 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -50,14 +50,20 @@ class LLFloaterSnapshot : public LLFloater
 
 	static void show(void*);
 	static void hide(void*);
-
 	static void update();
-	
+
+	static S32  getUIWinHeightLong()  {return sUIWinHeightLong ;}
+	static S32  getUIWinHeightShort() {return sUIWinHeightShort ;}
+	static S32  getUIWinWidth()       {return sUIWinWidth ;}
+
 private:
 	class Impl;
 	Impl& impl;
 
 	static LLFloaterSnapshot* sInstance;
+	static S32    sUIWinHeightLong ;
+	static S32    sUIWinHeightShort ;
+	static S32    sUIWinWidth ;
 };
 
 class LLSnapshotFloaterView : public LLFloaterView
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 0468ae5a1ad..e04a62167c7 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -76,6 +76,7 @@ const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
 std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
 std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
 std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleHUDTextObjects;
+BOOL LLHUDText::sDisplayText = TRUE ;
 
 bool lltextobject_further_away::operator()(const LLPointer<LLHUDText>& lhs, const LLPointer<LLHUDText>& rhs) const
 {
@@ -120,7 +121,7 @@ LLHUDText::~LLHUDText()
 
 void LLHUDText::render()
 {
-	if (!mOnHUDAttachment)
+	if (!mOnHUDAttachment && sDisplayText)
 	{
 		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
 		renderText(FALSE);
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index 75dc43cd6ad..bb96c356bb2 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -124,6 +124,7 @@ class LLHUDText : public LLHUDObject
 	static void renderAllHUD();
 	static void addPickable(std::set<LLViewerObject*> &pick_list);
 	static void reshape();
+	static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
 protected:
 	LLHUDText(const U8 type);
 
@@ -170,6 +171,7 @@ class LLHUDText : public LLHUDObject
 	S32				mLOD;
 	BOOL			mHidden;
 
+	static BOOL    sDisplayText ;
 	static std::set<LLPointer<LLHUDText> > sTextObjects;
 	static std::vector<LLPointer<LLHUDText> > sVisibleTextObjects;
 	static std::vector<LLPointer<LLHUDText> > sVisibleHUDTextObjects;
diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp
index 237826cb7a8..89f2e6239a3 100644
--- a/indra/newview/lloverlaybar.cpp
+++ b/indra/newview/lloverlaybar.cpp
@@ -61,6 +61,7 @@
 #include "llvoavatar.h"
 #include "llvoiceremotectrl.h"
 #include "llwebbrowserctrl.h"
+#include "llselectmgr.h"
 
 //
 // Globals
@@ -325,6 +326,7 @@ void LLOverlayBar::onClickMouselook(void*)
 //static
 void LLOverlayBar::onClickStandUp(void*)
 {
+	gSelectMgr->deselectAllForStandingUp();
 	gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
 }
 
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index f6556ffbd5e..f468ce97acf 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3343,6 +3343,36 @@ void LLSelectMgr::deselectAll()
 	updatePointAt();
 }
 
+void LLSelectMgr::deselectAllForStandingUp()
+{
+	/*
+	This function is similar deselectAll() except for the first if statement
+	which was removed. This is needed as a workaround for DEV-2854
+	*/
+
+	// Zap the angular velocity, as the sim will set it to zero
+	for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
+		 iter != mSelectedObjects->end(); iter++ )
+	{
+		LLViewerObject *objectp = (*iter)->getObject();
+		objectp->setAngularVelocity( 0,0,0 );
+		objectp->setVelocity( 0,0,0 );
+	}
+
+	sendListToRegions(
+		"ObjectDeselect",
+		packAgentAndSessionID,
+		packObjectLocalID,
+		NULL,
+		SEND_INDIVIDUALS);
+
+	removeAll();
+	
+	mLastSentSelectionCenterGlobal.clearVec();
+
+	updatePointAt();
+}
+
 void LLSelectMgr::deselectUnused()
 {
 	// no more outstanding references to this selection
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 68c1d4d9f82..570bcef79a1 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -419,6 +419,7 @@ class LLSelectMgr : public LLEditMenuHandler
 
 	// Send deselect messages to simulator, then clear the list
 	void deselectAll();
+	void deselectAllForStandingUp();
 
 	// deselect only if nothing else currently referencing the selection
 	void deselectUnused();
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 008eaccdc4a..acd64220d97 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -474,7 +474,7 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
 		mDesiredDiscard = discard;
 		mDesiredSize = size;
 	}
-	else if (size > mDesiredSize)
+	else if (size > mDesiredSize || size == 0)
 	{
 		mDesiredSize = size;
 		prioritize = true;
@@ -571,7 +571,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			U32 cache_priority = mWorkPriority;
 			S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
 			S32 size = mDesiredSize - offset;
-			if (size <= 0)
+
+			if(mDesiredSize != 0 && size <= 0)
 			{
 				mState = CACHE_POST;
 				return false;
@@ -1304,6 +1305,13 @@ bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 pri
 		// we really do get it.)
 		desired_size = worker->mFileSize;
 	}
+	else if ((discard == 0) && worker == NULL)
+	{
+		// if we want the entire image, but we don't know its size, then send
+		// a sentinel value of zero to request the entire contents of the cache.
+		// patch supplied by resident Sheet Spotter for VWR-2404
+		desired_size = 0;
+	}
 	else if (w*h*c > 0)
 	{
 		// If the requester knows the dimentions of the image,
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 7733ef5ae17..0df04fccfa1 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -470,6 +470,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("RenderUseImpostors")->getSignal()->connect(boost::bind(&handleRenderUseImpostorsChanged, _1));
 	gSavedSettings.getControl("RenderUseCleverUI")->getSignal()->connect(boost::bind(&handleRenderUseCleverUIChanged, _1));
 	gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _1));
+	gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
 	gSavedSettings.getControl("AvatarCompositeLimit")->getSignal()->connect(boost::bind(&handleCompositeLimitChanged, _1));
 	gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _1));
 	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _1));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index a75544d5287..41a936ca49e 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -75,6 +75,7 @@
 #include "llcubemap.h"
 #include "llviewerregion.h"
 #include "lldrawpoolwater.h"
+#include "lldrawpoolbump.h"
 #include "llwlparammanager.h"
 #include "llwaterparammanager.h"
 #include "llpostprocess.h"
@@ -82,6 +83,7 @@
 extern LLPointer<LLImageGL> gStartImageGL;
 extern BOOL gDisplaySwapBuffers;
 
+
 LLPointer<LLImageGL> gDisconnectedImagep = NULL;
 
 // used to toggle renderer back on after teleport
@@ -509,7 +511,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		
 		gFrameStats.start(LLFrameStats::UPDATE_CULL);
 		S32 water_clip = 0;
-		if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT) > 1)
+		if ((LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+			 gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
 		{
 			if (gCamera->cameraUnderWater())
 			{
@@ -571,7 +574,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 				
 				glh::matrix4f proj = glh_get_current_projection();
 				glh::matrix4f mod = glh_get_current_modelview();
-				glViewport(0,0,128,256);
+				glViewport(0,0,512,512);
+				LLVOAvatar::updateFreezeCounter() ;
 				LLVOAvatar::updateImpostors();
 				glh_set_current_projection(proj);
 				glh_set_current_modelview(mod);
@@ -590,6 +594,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			gPipeline.generateWaterReflection(*gCamera);
 		}
 
+		//////////////////////////////////////
+		//
+		// Update images, using the image stats generated during object update/culling
+		//
+		// Can put objects onto the retextured list.
+		//
+		// Doing this here gives hardware occlusion queries extra time to complete
+		gFrameStats.start(LLFrameStats::IMAGE_UPDATE);
+
+		{
+			LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE);
+			
+			LLViewerImage::updateClass(gCamera->getVelocityStat()->getMean(),
+										gCamera->getAngularVelocityStat()->getMean());
+
+			gBumpImageList.updateImages();  // must be called before gImageList version so that it's textures are thrown out first.
+
+			const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame)
+			gImageList.updateImages(max_image_decode_time);
+			stop_glerror();
+		}
+
 		///////////////////////////////////
 		//
 		// StateSort
@@ -692,8 +718,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			}
 			stop_glerror();
 		}
-	
-		render_hud_attachments();
 		
 		if (to_texture)
 		{
@@ -764,13 +788,13 @@ void render_hud_attachments()
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_GLOW);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
 		
 		gPipeline.stateSort(hud_cam, result);
 
 		gPipeline.renderGeom(hud_cam);
 
+		render_hud_elements();
 		//restore type mask
 		gPipeline.setRenderTypeMask(mask);
 		if (has_ui)
@@ -874,6 +898,9 @@ void render_ui_and_swap()
 		{
 			gPipeline.renderBloom(gSnapshot);
 		}
+
+		render_hud_elements();
+		render_hud_attachments();
 	}
 
 	LLGLSDefault gls_default;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ac52b8d05fd..77cfd63847f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1359,6 +1359,9 @@ void init_debug_rendering_menu(LLMenuGL* menu)
 	sub_menu->append(new LLMenuItemCheckGL("Texture Priority",	&LLPipeline::toggleRenderDebug, NULL,
 													&LLPipeline::toggleRenderDebugControl,
 													(void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY));
+	sub_menu->append(new LLMenuItemCheckGL("Avatar Rendering Cost",	&LLPipeline::toggleRenderDebug, NULL,
+													&LLPipeline::toggleRenderDebugControl,
+													(void*)LLPipeline::RENDER_DEBUG_SHAME));
 	sub_menu->append(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
 													&LLPipeline::toggleRenderDebugControl,
 													(void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA));
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index d81b688abf8..db356064d45 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -84,7 +84,10 @@ LLUUID LLViewerPartSource::getImageUUID() const
 }
 void LLViewerPartSource::setStart()
 {
-	mDelay = 99 ;
+	//cancel delaying to start a new added particle source, because some particle source just emits for a short time.
+	//however, canceling this might cause overall particle emmitting fluctuate for a while because the new added source jumps to 
+	//the current particle emmitting settings instantly. -->bao
+	mDelay = 0 ; //99
 }
 
 LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
@@ -263,7 +266,7 @@ void LLViewerPartSourceScript::update(const F32 dt)
 		}
 		
 		if(mDelay)
-		{
+		{			
 			limited_rate = llmax(limited_rate, 0.01f * mDelay--) ;
 		}
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 900fd6fc8bb..d48e3cc4f3d 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1522,7 +1522,8 @@ LLViewerWindow::LLViewerWindow(
 		gNoRender,
 		gSavedSettings.getBOOL("DisableVerticalSync"),
 		!gNoRender,
-		ignore_pixel_depth);
+		ignore_pixel_depth,
+		gSavedSettings.getU32("RenderFSAASamples"));
 #if LL_WINDOWS
 	if (!LLWinDebug::setupExceptionHandler())
 	{
@@ -4242,14 +4243,145 @@ void LLViewerWindow::playSnapshotAnimAndSound()
 	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
 }
 
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+{
+	if ((!gWorldPointer) || (!raw) || preview_width < 10 || preview_height < 10)
+	{
+		return FALSE;
+	}
+
+	if(gResizeScreenTexture) //the window is resizing
+	{
+		return FALSE ;
+	}
+
+	setCursor(UI_CURSOR_WAIT);
+
+	// Hide all the UI widgets first and draw a frame
+	BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+
+	if ( prev_draw_ui != show_ui)
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = FALSE;
+	}
+
+	S32 render_name = gSavedSettings.getS32("RenderName");
+	gSavedSettings.setS32("RenderName", 0);
+	LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame
+	
+	S32 w = preview_width ;
+	S32 h = preview_height ;	
+	LLVector2 display_scale = mDisplayScale ;
+	mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ;
+	LLRect window_rect = mWindowRect;
+	mWindowRect.set(0, h, w, 0);
+	
+	gDisplaySwapBuffers = FALSE;	
+	glClearColor(0.f, 0.f, 0.f, 0.f);
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	setup3DRender();
+	setupViewport();
+
+	LLFontGL::setFontDisplay(FALSE) ;
+	LLHUDText::setDisplayText(FALSE) ;
+	if (type == SNAPSHOT_TYPE_OBJECT_ID)
+	{
+		gPickTransparent = FALSE;
+		gObjectList.renderObjectsForSelect(*gCamera, FALSE, FALSE);
+	}
+	else
+	{
+		display(do_rebuild, 1.0f, 0, TRUE);
+		render_ui_and_swap();
+	}
+
+	S32 glformat, gltype, glpixel_length ;
+	if(SNAPSHOT_TYPE_DEPTH == type)
+	{
+		glpixel_length = 4 ;
+		glformat = GL_DEPTH_COMPONENT ; 
+		gltype = GL_FLOAT ;
+	}
+	else
+	{
+		glpixel_length = 3 ;
+		glformat = GL_RGB ;
+		gltype = GL_UNSIGNED_BYTE ;
+	}
+
+	raw->resize(w, h, glpixel_length);	
+	glReadPixels(0, 0, w, h, glformat, gltype, raw->getData());
+
+	if(SNAPSHOT_TYPE_DEPTH == type)
+	{
+		F32 depth_conversion_factor_1 = (gCamera->getFar() + gCamera->getNear()) / (2.f * gCamera->getFar() * gCamera->getNear());
+		F32 depth_conversion_factor_2 = (gCamera->getFar() - gCamera->getNear()) / (2.f * gCamera->getFar() * gCamera->getNear());
+
+		//calculate the depth 
+		for (S32 y = 0 ; y < h ; y++)
+		{
+			for(S32 x = 0 ; x < w ; x++)
+			{
+				S32 i = (w * y + x) << 2 ;
+				
+				F32 depth_float_i = *(F32*)(raw->getData() + i);
+				
+				F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2));
+				U8 depth_byte = F32_to_U8(linear_depth_float, gCamera->getNear(), gCamera->getFar());
+				*(raw->getData() + i + 0) = depth_byte;
+				*(raw->getData() + i + 1) = depth_byte;
+				*(raw->getData() + i + 2) = depth_byte;
+				*(raw->getData() + i + 3) = 255;
+			}
+		}		
+	}
+
+	LLFontGL::setFontDisplay(TRUE) ;
+	LLHUDText::setDisplayText(TRUE) ;
+	mDisplayScale.setVec(display_scale) ;
+	mWindowRect = window_rect;	
+	setup3DRender();
+	setupViewport();
+	gDisplaySwapBuffers = FALSE;
+
+	// POST SNAPSHOT
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = TRUE;
+	}
+
+	setCursor(UI_CURSOR_ARROW);
+
+	if (do_rebuild)
+	{
+		// If we had to do a rebuild, that means that the lists of drawables to be rendered
+		// was empty before we started.
+		// Need to reset these, otherwise we call state sort on it again when render gets called the next time
+		// and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
+		// objects on them.
+		gPipeline.resetDrawOrders();
+	}
+	
+	gSavedSettings.setS32("RenderName", render_name);	
+	
+	return TRUE;
+}
 
 // Saves the image from the screen to the specified filename and path.
 BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
 								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
 {
-	//F32 image_aspect_ratio = ((F32)image_width) / ((F32)image_height);
-	//F32 window_aspect_ratio = ((F32)getWindowWidth()) / ((F32)getWindowHeight());
-
 	if ((!gWorldPointer) ||
 		(!raw))
 	{
@@ -4282,43 +4414,30 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 	// from window
 	S32 snapshot_width = mWindowRect.getWidth();
 	S32 snapshot_height =  mWindowRect.getHeight();
+	// SNAPSHOT
+	S32 window_width = mWindowRect.getWidth();
+	S32 window_height = mWindowRect.getHeight();	
+	LLRect window_rect = mWindowRect;
+	BOOL use_fbo = FALSE;
+
 	F32 scale_factor = 1.0f ;
-	if (keep_window_aspect || is_texture) //map the entire window to snapshot
-	{
-	}
-	else //scale or crop
+	if(!keep_window_aspect) //image cropping
 	{
-		if(snapshot_width > image_width) //crop
-		{
-			snapshot_width = image_width ;
-		}
-		if(snapshot_height > image_height)//crop
-		{
-			snapshot_height = image_height ;
-		}
-
-		//if (image_aspect_ratio > window_aspect_ratio)
+		//if(snapshot_width > image_width && snapshot_height > image_height) //crop
 		//{
-		//	snapshot_height  = llround((F32)snapshot_width / image_aspect_ratio);
-		//}
-		//else if (image_aspect_ratio < window_aspect_ratio)
-		//{
-		//	snapshot_width = llround((F32)snapshot_height  * image_aspect_ratio);
+		//	snapshot_width = image_width ;
+		//	snapshot_height = image_height ;
 		//}
+		//else //crop and enlarge
+		{
+			F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+			snapshot_width = (S32)(ratio * image_width) ;
+			snapshot_height = (S32)(ratio * image_height) ;
+			scale_factor = llmax(1.0f, 1.0f / ratio) ;
+		}
 	}
 
 	LLRenderTarget target;
-	
-	scale_factor = llmax(1.f, (F32)image_width / snapshot_width, (F32)image_height / snapshot_height); 
-	
-	// SNAPSHOT
-	S32 window_width = mWindowRect.getWidth();
-	S32 window_height = mWindowRect.getHeight();
-	
-	LLRect window_rect = mWindowRect;
-
-	BOOL use_fbo = FALSE;
-	
 	if (gGLManager.mHasFramebufferObject && 
 		(image_width > window_width ||
 		image_height > window_height) &&
@@ -4339,9 +4458,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 			window_height = snapshot_height;
 			scale_factor = 1.f;
 			mWindowRect.set(0, 0, snapshot_width, snapshot_height);
-			target.bindTarget();
-
-			
+			target.bindTarget();			
 		}
 	}
 	
@@ -4954,6 +5071,8 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 		return TRUE;	// a lie..., because we'll get to it later
 	}
 
+	U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
+	U32 old_fsaa = mWindow->getFSAASamples();
 	// going from windowed to windowed
 	if (!old_fullscreen && !fullscreen)
 	{
@@ -4962,7 +5081,11 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 		{
 			mWindow->setSize(size);
 		}
-		return TRUE;
+
+		if (fsaa == old_fsaa)
+		{
+			return TRUE;
+		}
 	}
 
 	// Close floaters that don't handle settings change
@@ -4988,10 +5111,13 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
 		gSavedSettings.setS32("WindowY", old_pos.mY);
 	}
 	
+	mWindow->setFSAASamples(fsaa);
+
 	result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync);
 	if (!result_first_try)
 	{
 		// try to switch back
+		mWindow->setFSAASamples(old_fsaa);
 		result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync);
 
 		if (!result_second_try)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 09ad3fc270f..ef3b5146e2a 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -219,6 +219,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	BOOL			saveSnapshot(const LLString&  filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
 	BOOL			rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
 								BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_IMAGE_SIZE );
+	BOOL            thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
 	BOOL		    saveImageNumbered(LLImageRaw *raw, const LLString& extension = LLString());
 
 	void			playSnapshotAnimAndSound();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 575f9c424ce..68c5eec9a4d 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -138,6 +138,7 @@ LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL;
 LLVOAvatarInfo* 		LLVOAvatar::sAvatarInfo = NULL;
 
 BOOL gDebugAvatarRotation = FALSE;
+S32 LLVOAvatar::sFreezeCounter = 0 ;
 
 //extern BOOL gVelocityInterpolate;
 
@@ -2378,7 +2379,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 {
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
 	LLFastTimer t(LLFastTimer::FTM_AVATAR_UPDATE);
-	
+
 	if (isDead())
 	{
 		llinfos << "Warning!  Idle on dead avatar" << llendl;
@@ -2606,7 +2607,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 			F32 old_angle = mImpostorAngle.mV[i];
 			F32 angle_diff = fabsf(cur_angle-old_angle);
 		
-			if (angle_diff > 3.14159f/16.f)
+			if (angle_diff > 3.14159f/512.f*distance)
 			{
 				mNeedsImpostorUpdate = TRUE;
 			}
@@ -3069,6 +3070,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 		sNumVisibleChatBubbles--;
 	}
 
+	shame();
+
 	//--------------------------------------------------------------------
 	// draw tractor beam when editing objects
 	//--------------------------------------------------------------------
@@ -3166,6 +3169,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 {
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
 	// update screen joint size
+
 	if (mScreenp)
 	{
 		F32 aspect = gCamera->getAspect();
@@ -3235,10 +3239,15 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 	// the rest should only be done occasionally for far away avatars
 	//--------------------------------------------------------------------
 
-	if (!mIsSelf && sUseImpostors && !mNeedsAnimUpdate)
+	if (!mIsSelf && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
 	{
 		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
-		if (visible && mPixelArea <= impostor_area)
+		if (gMuteListp && gMuteListp->isMuted(getID()))
+		{
+			mUpdatePeriod = 16;
+			visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE;
+		}
+		else if (visible && mPixelArea <= impostor_area)
 		{
 			mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mPixelArea), 2, 8);
 
@@ -3897,7 +3906,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 			{
 				mEyeLashLOD.updateGeometry();
 				mHeadLOD.updateGeometry();
-				mHairLOD.updateGeometry();
+				mHairLOD.updateGeometry();				
 			}
 			mNeedsSkin = FALSE;
 			
@@ -4119,8 +4128,13 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
 	}
 
 	LLVector3 pos(getRenderPosition()+mImpostorOffset);
-	LLVector3 left = gCamera->getLeftAxis()*mImpostorDim.mV[0];
-	LLVector3 up = gCamera->getUpAxis()*mImpostorDim.mV[1];
+	LLVector3 at = (pos-gCamera->getOrigin());
+	at.normVec();
+	LLVector3 left = gCamera->getUpAxis() % at;
+	LLVector3 up = at%left;
+
+	left *= mImpostorDim.mV[0];
+	up *= mImpostorDim.mV[1];
 
 	LLGLEnable test(GL_ALPHA_TEST);
 	glAlphaFunc(GL_GREATER, 0.f);
@@ -5650,6 +5664,8 @@ BOOL LLVOAvatar::updateJointLODs()
 	F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE));
 	F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f);
 	F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);
+	F32 area_scale = 0.16f;
+
 	{
 		if (mIsSelf)
 		{
@@ -5659,7 +5675,7 @@ BOOL LLVOAvatar::updateJointLODs()
 			}
 			else
 			{
-				mAdjustedPixelArea = mPixelArea;
+				mAdjustedPixelArea = mPixelArea*area_scale;
 			}
 		}
 		else if (mIsDummy)
@@ -5669,7 +5685,7 @@ BOOL LLVOAvatar::updateJointLODs()
 		else
 		{
 			// reported avatar pixel area is dependent on avatar render load, based on number of visible avatars
-			mAdjustedPixelArea = (F32)mPixelArea * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor;
+			mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor;
 		}
 
 		// now select meshes to render based on adjusted pixel area
@@ -9440,6 +9456,23 @@ LLHost LLVOAvatar::getObjectHost() const
 	}
 }
 
+//static
+void LLVOAvatar::updateFreezeCounter(S32 counter)
+{
+	if(counter)
+	{
+		sFreezeCounter = counter ;
+	}
+	else if(sFreezeCounter > 0)
+	{
+		sFreezeCounter-- ;
+	}
+	else
+	{
+		sFreezeCounter = 0 ;
+	}
+}
+
 BOOL LLVOAvatar::updateLOD()
 {
 	BOOL res = updateJointLODs();
@@ -9493,7 +9526,7 @@ BOOL LLVOAvatar::isImpostor() const
 
 BOOL LLVOAvatar::needsImpostorUpdate() const
 {
-	return mNeedsImpostorUpdate;
+	return mNeedsImpostorUpdate ;
 }
 
 const LLVector3& LLVOAvatar::getImpostorOffset() const
@@ -9524,8 +9557,141 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di
 
 	LLVector3 at = gCamera->getOrigin()-(getRenderPosition()+mImpostorOffset);
 	distance = at.normVec();
-	angle.mV[0] = acosf(at.mV[0]);
-	angle.mV[1] = acosf(at.mV[1]);
-	angle.mV[2] = acosf(at.mV[2]);
+	F32 da = 1.f - (at*gCamera->getAtAxis());
+	angle.mV[0] = gCamera->getYaw()*da;
+	angle.mV[1] = gCamera->getPitch()*da;
+	angle.mV[2] = da;
+}
+
+U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
+{
+	if (!volume)
+	{
+		return 0;
+	}
+
+	U32 shame = 0;
+
+	U32 invisi = 0;
+	U32 shiny = 0;
+	U32 glow = 0;
+	U32 alpha = 0;
+	U32 flexi = 0;
+	U32 animtex = 0;
+	U32 particles = 0;
+	U32 scale = 0;
+	U32 bump = 0;
+	U32 planar = 0;
+	
+	if (volume->isFlexible())
+	{
+		flexi = 1;
+	}
+	if (volume->isParticleSource())
+	{
+		particles = 1;
+	}
+
+	const LLVector3& sc = volume->getScale();
+	scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
+
+	LLDrawable* drawablep = volume->mDrawable;
+
+	if (volume->isSculpted())
+	{
+		LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+		LLUUID sculpt_id = sculpt_params->getSculptTexture();
+		textures.insert(sculpt_id);
+	}
+
+	for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+	{
+		LLFace* face = drawablep->getFace(i);
+		const LLTextureEntry* te = face->getTextureEntry();
+		LLViewerImage* img = face->getTexture();
+
+		textures.insert(img->getID());
+
+		if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
+		{
+			alpha++;
+		}
+		else if (img->getPrimaryFormat() == GL_ALPHA)
+		{
+			invisi = 1;
+		}
+
+		if (te->getBumpmap())
+		{
+			bump = 1;
+		}
+		if (te->getShiny())
+		{
+			shiny = 1;
+		}
+		if (te->getGlow() > 0.f)
+		{
+			glow = 1;
+		}
+		if (face->mTextureMatrix != NULL)
+		{
+			animtex++;
+		}
+		if (te->getTexGen())
+		{
+			planar++;
+		}
+	}
+
+	shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar;
+
+	for (U32 i = 0; i < drawablep->getChildCount(); ++i)
+	{
+		shame += calc_shame(drawablep->getChild(i)->getVOVolume(), textures);
+	}
+
+	return shame;
 }
 
+void LLVOAvatar::shame()
+{
+	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
+	{
+		return;
+	}
+
+	U32 shame = 1;
+
+	std::set<LLUUID> textures;
+
+	attachment_map_t::const_iterator iter;
+	for (iter = mAttachmentPoints.begin(); 
+		iter != mAttachmentPoints.end();
+		++iter)
+	{
+		LLViewerJointAttachment* attachment = iter->second;
+		LLViewerObject* object = attachment->getObject();
+		if (object && !object->isHUDAttachment())
+		{
+			LLDrawable* drawable = object->mDrawable;
+			if (drawable)
+			{
+				shame += 10;
+				LLVOVolume* volume = drawable->getVOVolume();
+				if (volume)
+				{
+					shame += calc_shame(volume, textures);
+				}
+			}
+		}
+	}	
+
+	shame += textures.size() * 5;
+
+	setDebugText(llformat("%d", shame));
+	F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
+	F32 red = llmin((F32) shame/1024.f, 1.f);
+	mText->setColor(LLColor4(red,green,0,1));
+}
+
+
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index ae0656f3ea7..a6731c3e312 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -984,6 +984,7 @@ class LLVOAvatar :
 	LLHost			getObjectHost() const;
 	S32				getLocalDiscardLevel( S32 index);
 	
+	void			shame();  //generate shame metric
 //Ventrella
 	//-----------------------------------------------------------------------------------------------
 	// the Voice Visualizer is responsible for detecting the user's voice signal, and when the
@@ -993,7 +994,11 @@ class LLVOAvatar :
 	LLVoiceVisualizer * mVoiceVisualizer;
 	int					mCurrentGesticulationLevel;
 //End Ventrella
-	
+
+private:
+	static  S32 sFreezeCounter ;
+public:
+	static void updateFreezeCounter(S32 counter = 0 ) ;
 };
 
 #endif // LL_VO_AVATAR_H
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index f42ec51b5d6..448bda1857e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -99,7 +99,7 @@
 #include "llwlparammanager.h"
 #include "llwaterparammanager.h"
 #include "llspatialpartition.h"
-
+#include "llmutelist.h"
 
 #ifdef _DEBUG
 // Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -1252,6 +1252,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		mScreen.flush();
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 	}
+	else if (LLPipeline::sUseOcclusion > 1)
+	{
+		glFlush();
+	}
 }
 
 void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
@@ -1339,6 +1343,7 @@ void LLPipeline::doOcclusion(LLCamera& camera)
 	}
 
 	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+	glFlush();
 }
 	
 BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
@@ -2124,8 +2129,6 @@ void render_hud_elements()
 	LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
 	gPipeline.disableLights();		
 	
-	gPipeline.renderDebug();
-
 	LLGLDisable fog(GL_FOG);
 	LLGLSUIDefault gls_ui;
 
@@ -2289,15 +2292,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 
 	LLVertexBuffer::startRender();
 	
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
-		{
-			poolp->prerender();
-		}
-	}
-
 	//by bao
 	//fake vertex buffer updating
 	//to guaranttee at least updating one VBO buffer every frame
@@ -2314,7 +2308,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	glMatrixMode(GL_MODELVIEW);
 
 	LLGLSPipeline gls_pipeline;
-	
+	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
 	LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
 				
 	// Toggle backface culling for debugging
@@ -2346,8 +2341,22 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	{
 		gObjectList.renderObjectsForSelect(camera);
 	}
+	else if (gSavedSettings.getBOOL("RenderDeferred"))
+	{
+		renderGeomDeferred();
+	}
 	else
 	{
+		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+		{
+			LLDrawPool *poolp = *iter;
+			if (hasRenderType(poolp->getType()))
+			{
+				poolp->prerender();
+			}
+		}
+
+
 		LLFastTimer t(LLFastTimer::FTM_POOLS);
 		calcNearbyLights(camera);
 		setupHWLights(NULL);
@@ -2456,7 +2465,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	// have touch-handlers.
 	mHighlightFaces.clear();
 
-	render_hud_elements();
+	renderDebug();
 
 	LLVertexBuffer::stopRender();
 	LLVertexBuffer::unbind();
@@ -2479,6 +2488,19 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 #endif
 }
 
+void LLPipeline::renderGeomDeferred()
+{
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+	gDeferredDiffuseProgram.bind();
+	gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE);
+	gDeferredDiffuseProgram.unbind();
+	glDisableClientState(GL_COLOR_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
 void LLPipeline::addTrianglesDrawn(S32 count)
 {
 	assertInitialized();
@@ -4814,6 +4836,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
 		
 		mScreen.bindTexture();
 		
+		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 		
 		glDisable(GL_TEXTURE_RECTANGLE_ARB);
@@ -4948,13 +4971,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 				mRenderTypeMask = tmp;
 			}
 
-			if (LLDrawPoolWater::sNeedsReflectionUpdate)
+			if (LLDrawPoolWater::sNeedsDistortionUpdate)
 			{
 				mRenderTypeMask &=	~((1<<LLPipeline::RENDER_TYPE_WATER) |
 									  (1<<LLPipeline::RENDER_TYPE_GROUND) |
 									  (1<<LLPipeline::RENDER_TYPE_SKY) |
-									  (1<<LLPipeline::RENDER_TYPE_CLOUDS) |
-									  (1<<LLPipeline::RENDER_TYPE_WL_SKY));	
+									  (1<<LLPipeline::RENDER_TYPE_CLOUDS));	
 
 				if (gSavedSettings.getBOOL("RenderWaterReflections"))
 				{ //mask out selected geometry based on reflection detail
@@ -5034,7 +5056,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			LLPipeline::sUnderWaterRender = FALSE;
 			mWaterDis.flush();
 		}
-		last_update = LLDrawPoolWater::sNeedsReflectionUpdate;
+		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
 
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 		LLPipeline::sReflectionRender = FALSE;
@@ -5048,6 +5070,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 		gViewerWindow->setupViewport();
 		mRenderTypeMask = type_mask;
 		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
+		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
 		gCamera->setUserClipPlane(LLPlane(-pnorm, -pd));
 		LLPipeline::sUseOcclusion = occlusion;
 	}
@@ -5075,10 +5098,6 @@ LLCubeMap* LLPipeline::findReflectionMap(const LLVector3& location)
 
 void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
 {
-#if !LL_RELEASE_FOR_DOWNLOAD
-	LLGLState::checkClientArrays(mask);
-#endif
-
 	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
 	{
 		LLSpatialGroup* group = *i;
@@ -5105,22 +5124,23 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	assertInitialized();
 
-	if (!avatar->mImpostor.isComplete())
+	U32 mask;
+	BOOL muted = gMuteListp && gMuteListp->isMuted(avatar->getID());
+
+	if (muted)
 	{
-		avatar->mImpostor.allocate(128,256,GL_RGBA,TRUE);
-		avatar->mImpostor.bindTexture();
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+		mask  = 1 << LLPipeline::RENDER_TYPE_AVATAR;
 	}
-
-	U32 mask = (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+	else
+	{
+		mask  = (1<<LLPipeline::RENDER_TYPE_VOLUME) |
 				(1<<LLPipeline::RENDER_TYPE_AVATAR) |
 				(1<<LLPipeline::RENDER_TYPE_BUMP) |
 				(1<<LLPipeline::RENDER_TYPE_GRASS) |
 				(1<<LLPipeline::RENDER_TYPE_SIMPLE) |
 				(1<<LLPipeline::RENDER_TYPE_ALPHA) | 
 				(1<<LLPipeline::RENDER_TYPE_INVISIBLE);
+	}
 	
 	mask = mask & gPipeline.getRenderTypeMask();
 	U32 saved_mask = gPipeline.mRenderTypeMask;
@@ -5148,24 +5168,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	stateSort(*gCamera, result);
 	
-	glClearColor(0.0f,0.0f,0.0f,0.0f);
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	glStencilMask(0xFFFFFFFF);
-	glClearStencil(0);
-
-	{
-		LLGLEnable scissor(GL_SCISSOR_TEST);
-		glScissor(0, 0, 128, 256);
-		avatar->mImpostor.bindTarget();
-		avatar->mImpostor.getViewport(gGLViewport);
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-	}
-	
-	LLGLEnable stencil(GL_STENCIL_TEST);
-
-	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
 	const LLVector3* ext = avatar->mDrawable->getSpatialExtents();
 	LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
 
@@ -5190,9 +5192,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 
 	glMatrixMode(GL_PROJECTION);
 	glPushMatrix();
-	glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0);
-	glh_set_current_projection(ortho);
-	glLoadMatrixf(ortho.m);
+	//glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0);
+	F32 distance = (pos-camera.getOrigin()).magVec();
+	F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
+	F32 aspect = tdim.mV[0]/tdim.mV[1]; //128.f/256.f;
+	glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
+	glh_set_current_projection(persp);
+	glLoadMatrixf(persp.m);
 
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix();
@@ -5204,24 +5210,68 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 	glLoadMatrixf(mat.m);
 	glh_set_current_modelview(mat);
 
+	glClearColor(0.0f,0.0f,0.0f,0.0f);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glStencilMask(0xFFFFFFFF);
+	glClearStencil(0);
+
+	// get the number of pixels per angle
+	F32 pa = gViewerWindow->getWindowDisplayHeight()/(RAD_TO_DEG*gCamera->getView());
+
+	//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
+	U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
+	U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
+
+	if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
+		resY != avatar->mImpostor.getHeight())
+	{
+		avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE);
+		avatar->mImpostor.bindTexture();
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+	}
+
+	{
+		LLGLEnable scissor(GL_SCISSOR_TEST);
+		glScissor(0, 0, resX, resY);
+		avatar->mImpostor.bindTarget();
+		avatar->mImpostor.getViewport(gGLViewport);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	}
+	
+	LLGLEnable stencil(GL_STENCIL_TEST);
+
+	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
 	renderGeom(camera);
 	
 	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 	glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
 
 	{
-		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 		LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
 		LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
 
-		LLGLEnable blend(GL_BLEND);
+		LLGLEnable blend(muted ? 0 : GL_BLEND);
+
+		if (muted)
+		{
+			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		}
+		else
+		{
+			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+		}
+		
 		gGL.blendFunc(GL_ONE, GL_ONE);
 		LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 
 		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
 
 		gGL.start();
-		gGL.color4ub(0,0,0,1);
+		gGL.color4ub(64,64,64,1);
 		gGL.begin(GL_QUADS);
 		gGL.vertex3fv((pos+left-up).mV);
 		gGL.vertex3fv((pos-left-up).mV);
@@ -5230,9 +5280,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 		gGL.end();
 		gGL.stop();
 
+
 		gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	}
 
+
 	avatar->mImpostor.flush();
 
 	avatar->setImpostorDim(tdim);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 2054492b721..9c64ccdbe3f 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -72,6 +72,7 @@ void glh_set_current_modelview(glh::matrix4f& mat);
 glh::matrix4f glh_get_current_projection();
 void glh_set_current_projection(glh::matrix4f& mat);
 glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);
+glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
 
 class LLPipeline
 {
@@ -179,6 +180,8 @@ class LLPipeline
 	void grabReferences(LLCullResult& result);
 
 	void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE);
+	void renderGeomDeferred();
+
 	void processImagery(LLCamera& camera);
 	void generateWaterReflection(LLCamera& camera);
 	void renderHighlights();
@@ -328,6 +331,7 @@ class LLPipeline
 		RENDER_DEBUG_TEXTURE_ANIM		= 0x080000,
 		RENDER_DEBUG_LIGHTS				= 0x100000,
 		RENDER_DEBUG_BATCH_SIZE			= 0x200000,
+		RENDER_DEBUG_SHAME				= 0x400000,
 	};
 
 	LLPointer<LLViewerImage>	mAlphaSizzleImagep;
-- 
GitLab