diff --git a/doc/contributions.txt b/doc/contributions.txt
index 494e3fe1d75737a3eca6f32a71539f36fddd30ff..be5a5dda83ed6e4eeb5d7d125b9e6b0a212d6bfd 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -9,14 +9,14 @@ blino Nakamura - VWR-17
 Drewan Keats - VWR-28
 Dylan Haskell - VWR-72
 Eddy Stryker - VWR-15, VWR-23
-Hiro Sommambulist - VWR-66
+Hiro Sommambulist - VWR-66, VWR-97, VWR-100, VWR-105, VWR-108, VWR-118
 Joghert LeSabre - VWR-64
 Kage Pixel - VWR-11
 Kunnis Basiat - VWR-82
 Paul Churchill - VWR-20
 Paula Innis - VWR-30
 Peekay Semyorka - VWR-7, VWR-19, VWR-49
-SpacedOut Frye - VWR-57, VWR-123
+SpacedOut Frye - VWR-57, VWR-94, VWR-121, VWR-123
 Strife Onizuka - VWR-74, VWR-85, SVC-9
 Zipherius Turas - VWR-76, VWR-77
 
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index e19604c9f092223f026edabf4b3c8510e984eddb..95d9ae128857388c31454edf05181de66113efb6 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -195,6 +195,10 @@ class LLInventoryItem : public LLInventoryObject
 		II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE		= 0x080000,
 		II_FLAGS_OBJECT_PERM_OVERWRITE_NEXT_OWNER	= 0x100000,
 
+ 		// flag to indicate whether an object that is returned is composed 
+		// of muiltiple items or not.
+		II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS			= 0x200000,
+
 		// wearables use the low order byte of flags to store the
 		// EWearableType enumeration found in newview/llwearable.h
 	};
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 5354de783cf5013ab5de96e1ed94ba4a99d4e7fb..00a192aca8ca8af68a05b91ab697ebfa7206caa9 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2059,7 +2059,7 @@ bool LLVolumeParams::setSkew(const F32 skew_value)
 		{
 			skew = min_skew_mag;
 		}
-		valid = approx_zero(delta);
+		valid = approx_zero(delta, .01f);
 	}
 
 	mPathParams.setSkew(skew);
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 514fb10b4a594ceffe9a58b15fde5a0d93553c86..451fb2e80783ab30e603d9d75243e39c13ca9ba8 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -948,7 +948,7 @@ BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
 					<< (*it).first;
 				llinfos << str.str().c_str() << llendl;
 			}
-			mPotentialLostPackets.erase((*(it++)).first);
+			mPotentialLostPackets.erase(it++);
 		}
 		else
 		{
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 320719072c49283e0a4a13edf57ed2fa593eadcd..1be6c21cc2c562cb25c6dec155a3ccdb1dd1dbbc 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -202,16 +202,15 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
 	{
 		// remove any matching poll file descriptors for this pipe.
 		LLIOPipe::ptr_t pipe_ptr(pipe);
-
-		LLChainInfo::conditionals_t::iterator it = (*mCurrentChain).mDescriptors.begin();
-		LLChainInfo::conditionals_t::iterator end = (*mCurrentChain).mDescriptors.end();
-		while (it != end)
+		LLChainInfo::conditionals_t::iterator it;
+		it = (*mCurrentChain).mDescriptors.begin();
+		while(it != (*mCurrentChain).mDescriptors.end())
 		{
 			LLChainInfo::pipe_conditional_t& value = (*it);
-			if ( pipe_ptr == value.first )
+			if(pipe_ptr == value.first)
 			{
 				ll_delete_apr_pollset_fd_client_data()(value);
-				(*mCurrentChain).mDescriptors.erase(it++);
+				it = (*mCurrentChain).mDescriptors.erase(it);
 				mRebuildPollset = true;
 			}
 			else
@@ -453,7 +452,7 @@ void LLPumpIO::pump()
 //						<< (*run_chain).mChainLinks[0].mPipe
 //						<< " because we reached the end." << llendl;
 #endif
-				mRunningChains.erase(run_chain++);
+				run_chain = mRunningChains.erase(run_chain);
 				continue;
 			}
 		}
@@ -532,7 +531,7 @@ void LLPumpIO::pump()
 				(*run_chain).mDescriptors.begin(),
 				(*run_chain).mDescriptors.end(),
 				ll_delete_apr_pollset_fd_client_data());
-			mRunningChains.erase(run_chain++);
+			run_chain = mRunningChains.erase(run_chain);
 
 			// *NOTE: may not always need to rebuild the pollset.
 			mRebuildPollset = true;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 1fc040c7d6130abf0105bd59cfb301e297b297a7..9a49f32b7d8cdb57fa8f2cbfc7a9829f752e615c 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -285,14 +285,18 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
 		sSansSerifHuge->reset();
 	}
 
-	if (!sSSHugeFallback)
+	if (sSSHugeFallback)
 	{
-		sSSHugeFallback = new LLFontList();
-		 if (!loadFaceFallback(sSSHugeFallback, sanserif_fallback_file, huge_size*ss_fallback_scale))
-		 {
-			 delete sSSHugeFallback;
-			 sSSHugeFallback = NULL;
-		 }
+		delete sSSHugeFallback;
+	}
+	sSSHugeFallback = new LLFontList();
+	if (!loadFaceFallback(
+			sSSHugeFallback,
+			sanserif_fallback_file,
+			huge_size*ss_fallback_scale))
+	{
+		delete sSSHugeFallback;
+		sSSHugeFallback = NULL;
 	}
 
 	failed |= !loadFace(sSansSerifHuge, sansserif_file, huge_size, sSSHugeFallback);
@@ -307,14 +311,18 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
 		sSansSerifBig->reset();
 	}
 
-	if (!sSSBigFallback)
+	if (sSSBigFallback)
 	{
-		sSSBigFallback = new LLFontList();
-		if (!loadFaceFallback(sSSBigFallback, sanserif_fallback_file, big_size*ss_fallback_scale))
-		{
-			delete sSSBigFallback;
-			sSSBigFallback = NULL;
-		}
+		delete sSSBigFallback;
+	}
+	sSSBigFallback = new LLFontList();
+	if (!loadFaceFallback(
+			sSSBigFallback,
+			sanserif_fallback_file,
+			big_size*ss_fallback_scale))
+	{
+		delete sSSBigFallback;
+		sSSBigFallback = NULL;
 	}
 
 	failed |= !loadFace(sSansSerifBig, sansserif_file, big_size, sSSBigFallback);
@@ -329,14 +337,18 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
 		sSansSerif->reset();
 	}
 
-	if (!sSSFallback)
+	if (sSSFallback)
 	{
-		sSSFallback = new LLFontList();
-		if (!loadFaceFallback(sSSFallback, sanserif_fallback_file, medium_size*ss_fallback_scale))
-		{
-			delete sSSFallback;
-			sSSFallback = NULL;
-		}
+		delete sSSFallback;
+	}
+	sSSFallback = new LLFontList();
+	if (!loadFaceFallback(
+			sSSFallback,
+			sanserif_fallback_file,
+			medium_size*ss_fallback_scale))
+	{
+		delete sSSFallback;
+		sSSFallback = NULL;
 	}
 	failed |= !loadFace(sSansSerif, sansserif_file, medium_size, sSSFallback);
 
@@ -350,14 +362,18 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
 		sSansSerifSmall->reset();
 	}
 
-	if (!sSSSmallFallback)
+	if(sSSSmallFallback)
 	{
-		sSSSmallFallback = new LLFontList();
-		if (!loadFaceFallback(sSSSmallFallback, sanserif_fallback_file, small_size*ss_fallback_scale))
-		{
-			delete sSSSmallFallback;
-			sSSSmallFallback = NULL;
-		}
+		delete sSSSmallFallback;
+	}
+	sSSSmallFallback = new LLFontList();
+	if (!loadFaceFallback(
+			sSSSmallFallback,
+			sanserif_fallback_file,
+			small_size*ss_fallback_scale))
+	{
+		delete sSSSmallFallback;
+		sSSSmallFallback = NULL;
 	}
 	failed |= !loadFace(sSansSerifSmall, sansserif_file, small_size, sSSSmallFallback);
 
@@ -374,14 +390,18 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
 		sSansSerifBold->reset();
 	}
 
-	if (!sSSBoldFallback)
+	if (sSSBoldFallback)
 	{
-		sSSBoldFallback = new LLFontList();
-		if (!loadFaceFallback(sSSBoldFallback, sanserif_fallback_file, medium_size*ss_fallback_scale))
-		{
-			delete sSSBoldFallback;
-			sSSBoldFallback = NULL;
-		}
+		delete sSSBoldFallback;
+	}
+	sSSBoldFallback = new LLFontList();
+	if (!loadFaceFallback(
+			sSSBoldFallback,
+			sanserif_fallback_file,
+			medium_size*ss_fallback_scale))
+	{
+		delete sSSBoldFallback;
+		sSSBoldFallback = NULL;
 	}
 	failed |= !loadFace(sSansSerifBold, sansserif_bold_file, medium_size, sSSBoldFallback);
 
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index d5e1e770530cc6275f446cd389df6ac3c884060f..ccc100a861b9032196569940df792ba7e41abd85 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -213,6 +213,10 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags)
 	  mHideCursorPermanent(FALSE),
 	  mFlags(flags)
 {
+	for (U32 i = 0; i < 6; i++)
+	{
+		mJoyAxis[i] = 0;
+	}
 }
 	
 // virtual
@@ -230,6 +234,15 @@ void LLWindow::decBusyCount()
 	}
 }
 
+F32 LLWindow::getJoystickAxis(U32 axis)
+{
+	if (axis < 6)
+	{
+		return mJoyAxis[axis];
+	}
+	return 0.f;
+}
+
 void LLWindow::setCallbacks(LLWindowCallbacks *callbacks)
 {
 	mCallbacks = callbacks;
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index bbe530c9069013d25083fd4bd30df4906313a140..f19178d7f5408b5ed268ba6e575b47a2f4c67ea8 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -181,7 +181,8 @@ class LLWindow
 	virtual F32	getNativeAspectRatio() = 0;
 	virtual F32 getPixelAspectRatio() = 0;
 	virtual void setNativeAspectRatio(F32 aspect) = 0;
-
+	
+	F32 getJoystickAxis(U32 axis);
 	void setCallbacks(LLWindowCallbacks *callbacks);
 
 	virtual void beforeDialog() {};	// prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
@@ -219,6 +220,7 @@ class LLWindow
 	ESwapMethod mSwapMethod;
 	BOOL		mHideCursorPermanent;
 	U32			mFlags;
+	F32			mJoyAxis[6]; 
 	
 	friend class LLWindowManager;
 };
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 4efa173fc430088a6535487b77e6509793294dc5..b8123096e6a17ab3705b1189369dd354f179a09c 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -2796,6 +2796,13 @@ void LLWindowWin32::updateJoystick( )
 	if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js ) ) )
 		return; // The device should have been acquired during the Poll()
 
+	mJoyAxis[0] = js.lX/1000.f;
+	mJoyAxis[1] = js.lY/1000.f;
+	mJoyAxis[2] = js.lZ/1000.f;
+	mJoyAxis[3] = js.lRx/1000.f;
+	mJoyAxis[4] = js.lRy/1000.f;
+	mJoyAxis[5] = js.lRz/1000.f;
+
 	if (js.lX <= -500)
 	{
 		if (!(mJoyStickState & 0x1))
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
index e0e79e95ba063f564c26a7c940cbabbd7e6c981d..11a057b1777f6155f08b37f33fab49de154a1c21 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -132,5 +132,7 @@ void main()
    //apply fog
    applyScatter(color.rgb);
    
+   color.a = spec*0.5+fb.a;
+   
    gl_FragColor = color;
 }
diff --git a/indra/newview/fmod_hidden_symbols.exp b/indra/newview/fmod_hidden_symbols.exp
index c0d5bed859f69f5fed87c55e5568045d1e8aa79f..1e790255bc65f0a58eba47152a17532bbf50eab6 100644
--- a/indra/newview/fmod_hidden_symbols.exp
+++ b/indra/newview/fmod_hidden_symbols.exp
@@ -1,3 +1,5 @@
+_CarbonSndPlayDoubleBuffer
+_ConvertFromIeeeExtended
 __book_maptype1_quantvals
 __book_unquantize
 __float32_pack
@@ -138,3 +140,101 @@ _ov_pcm_seek_page_lap
 _ov_raw_seek_lap
 _ov_time_seek_lap
 _ov_time_seek_page_lap
+_II_step_one
+_II_step_two
+_MyRecComp
+_SampleRates
+_Sinfo
+_ValidStepIndex
+__Z11fmodwrapperv
+__Z11fmodwrapperv.eh
+__floor_P
+__mapping_P
+__residue_P
+__ve_envelope_clear
+__ve_envelope_init
+__ve_envelope_mark
+__ve_envelope_search
+__ve_envelope_shift
+__vi_gpsy_free
+__vi_psy_free
+__vorbis_window_init
+__vp_ampmax_decay
+__vp_couple
+__vp_global_free
+__vp_global_look
+__vp_noise_normalize
+__vp_noise_normalize_sort
+__vp_noisemask
+__vp_offset_and_mix
+__vp_psy_clear
+__vp_psy_init
+__vp_quantize_couple_memo
+__vp_quantize_couple_sort
+__vp_remove_floor
+__vp_tonemask
+_alloc_0
+_alloc_1
+_alloc_2
+_alloc_3
+_alloc_4
+_bandInfo
+_cdcallback
+_cdchannel
+_cdmode
+_cdnumtracks
+_cdstream
+_cdtrack
+_drft_backward
+_drft_clear
+_drft_forward
+_drft_init
+_eatwhite
+_floor0_exportbundle
+_floor1_exportbundle
+_gFreeList
+_gNMRecBusy
+_gNMRecPtr
+_gSilenceOnes
+_gSilenceTwos
+_longLimit
+_mapping0_exportbundle
+_mdct_backward
+_mdct_clear
+_mdct_forward
+_mdct_init
+_muls
+_mystrdup
+_res0_free_info
+_res0_free_look
+_res0_inverse
+_res0_look
+_res0_unpack
+_res1_class
+_res1_inverse
+_res2_inverse
+_residue0_exportbundle
+_residue1_exportbundle
+_residue2_exportbundle
+_scale
+_shortLimit
+_tabsel_123
+_F_Free
+_F_Malloc
+_F_ReAlloc
+_F_memcmp
+_F_memmove
+_F_strcat
+_F_strchr
+_F_strcmp
+_F_strcpy
+_F_stricmp
+_F_strlen
+_F_strncat
+_F_strncmp
+_F_strncpy
+_F_strnicmp
+_F_strstr
+_F_strupr
+_F_tolower
+_F_toupper
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 9ab6c700abcabfb3590b613dda583515f06a3806..b2e727233607ee250f2d117d34c35d9f0b4a99fa 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -43,6 +43,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
 	case POOL_SIMPLE:
 		poolp = new LLDrawPoolSimple();
 		break;
+	case POOL_GLOW:
+		poolp = new LLDrawPoolGlow();
+		break;
 	case POOL_ALPHA:
 		poolp = new LLDrawPoolAlpha();
 		break;
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index f7243f369b71fa3a557fcc5441a9657e5192c535..1a0021f62b07835a895a3d06250920d0db97c0b9 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -38,6 +38,7 @@ class LLDrawPool
 		POOL_BUMP,
 		POOL_AVATAR,
 		POOL_TREE,
+		POOL_GLOW,
 		POOL_ALPHA,
 		POOL_WATER,
 		POOL_ALPHA_POST_WATER,
@@ -86,8 +87,8 @@ class LLRenderPass : public LLDrawPool
 	enum
 	{
 		PASS_SIMPLE = NUM_POOL_TYPES,
-		PASS_FULLBRIGHT,
 		PASS_GLOW,
+		PASS_FULLBRIGHT,
 		PASS_INVISIBLE,
 		PASS_SHINY,
 		PASS_BUMP,
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 5cb914c37e73f85eee1245b5017d1fd516f83675..93af95646672a453a67670d61fc04d271db91f5f 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -271,12 +271,20 @@ void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask
 			{
 				gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
 				light_enabled = FALSE;
+				if (LLPipeline::sRenderGlow)
+				{
+					glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+				}
 			}
 		}
 		else if (!light_enabled)
 		{
 			gPipeline.enableLightsDynamic(1.f);
 			light_enabled = TRUE;
+			if (LLPipeline::sRenderGlow)
+			{
+				glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+			}
 		}
 
 		/*if (params.mParticle)
@@ -309,6 +317,11 @@ void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask
 	if (!light_enabled)
 	{
 		gPipeline.enableLightsDynamic(1.f);
+	
+		if (LLPipeline::sRenderGlow)
+		{
+			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+		}
 	}
 
 	/*glPointSize(1.f);
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 6376dd8d33ccf4e173e008a07ebb37953469f4ae..8835535ee7bb918dd5276455328b9bc855958059 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -27,7 +27,7 @@ class LLDrawPoolBump : public LLRenderPass
 
 	LLDrawPoolBump();
 
-	/*virtual*/ void render(S32 pass = 0);
+	virtual void render(S32 pass = 0);
 	/*virtual*/ void beginRenderPass( S32 pass );
 	/*virtual*/ void endRenderPass( S32 pass );
 	/*virtual*/ S32	 getNumPasses();
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 8fc3b9890895f9c6e251bb689e66e613ce006da8..4c09cd4095ccd0646f615ac279f6705390d83161 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -9,43 +9,91 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "lldrawpoolsimple.h"
+#include "lldrawpoolbump.h"
 
+#include "llviewercamera.h"
 #include "llagent.h"
 #include "lldrawable.h"
 #include "llface.h"
 #include "llsky.h"
 #include "pipeline.h"
 
-class LLRenderPassGlow : public LLRenderPass
+class LLRenderShinyGlow : public LLDrawPoolBump
 {
 public:
-	LLRenderPassGlow(): LLRenderPass(LLRenderPass::PASS_GLOW) { }
+	LLRenderShinyGlow() { }
 	
-	enum
+	void render(S32 pass = 0)
 	{
-		VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX |
-							LLVertexBuffer::MAP_TEXCOORD
-	};
-
-	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+		LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
+		if( cube_map )
+		{
+			cube_map->enable(0);
+			cube_map->setMatrix(0);
+			cube_map->bind();
+			glEnableClientState(GL_NORMAL_ARRAY);
+			
+			glColor4f(1,1,1,1);
+
+            U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL;
+			renderStatic(LLRenderPass::PASS_SHINY, mask);
+			renderActive(LLRenderPass::PASS_SHINY, mask);
+
+			glDisableClientState(GL_NORMAL_ARRAY);
+			cube_map->disable();
+			cube_map->restoreMatrix();
+		}
+	}
+};
 
-	virtual void prerender() { }
+void LLDrawPoolGlow::render(S32 pass)
+{
+	LLGLEnable blend(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+	gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
+	renderActive(LLRenderPass::PASS_GLOW, getVertexDataMask());
 
-	void render(S32 pass = 0)
+	if (gSky.mVOSkyp)
 	{
-		LLGLEnable blend(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-		renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
-		renderActive(LLRenderPass::PASS_GLOW, getVertexDataMask());
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		glPushMatrix();
+		LLVector3 origin = gCamera->getOrigin();
+		glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+
+		LLFace* facep = gSky.mVOSkyp->mFace[LLVOSky::FACE_BLOOM];
+
+		if (facep)
+		{
+			LLGLDisable cull(GL_CULL_FACE);
+			facep->getTexture()->bind();
+			glColor4f(1,1,1,1);
+			facep->renderIndexed(getVertexDataMask());
+		}
+
+		glPopMatrix();
 	}
 
-	void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE)
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+	if (LLPipeline::sDynamicReflections)
 	{
-		glColor4ubv(params.mGlowColor.mV);
-		LLRenderPass::pushBatch(params, mask, texture);
+		LLRenderShinyGlow glow;
+		glow.render();
 	}
-};
+
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	
+}
+
+void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+{
+	glColor4ubv(params.mGlowColor.mV);
+	LLRenderPass::pushBatch(params, mask, texture);
+}
+
 
 LLDrawPoolSimple::LLDrawPoolSimple() :
 	LLRenderPass(POOL_SIMPLE)
@@ -97,21 +145,15 @@ void LLDrawPoolSimple::render(S32 pass)
 		renderActive(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
 	}
 
-	{
-		LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW);
-		glDisableClientState(GL_COLOR_ARRAY);
-		LLRenderPassGlow glow;
-		glow.render();
-	}
-
 	{
 		LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE);
 		U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
+		glDisableClientState(GL_COLOR_ARRAY);
 		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 		renderInvisible(invisi_mask);
 		renderActive(LLRenderPass::PASS_INVISIBLE, invisi_mask);
-		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 	}
 }
 
diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h
index f89230d8662fa853ece5a42eae428b3828bb3dad..1eb9b3c6eb3b87c19a97bfec72a2a4cc10f29082 100644
--- a/indra/newview/lldrawpoolsimple.h
+++ b/indra/newview/lldrawpoolsimple.h
@@ -31,4 +31,24 @@ class LLDrawPoolSimple : public LLRenderPass
 
 };
 
+class LLDrawPoolGlow : public LLRenderPass
+{
+public:
+	LLDrawPoolGlow(): LLRenderPass(LLDrawPool::POOL_GLOW) { }
+	
+	enum
+	{
+		VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX |
+							LLVertexBuffer::MAP_TEXCOORD
+	};
+
+	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+	virtual void prerender() { }
+
+	void render(S32 pass = 0);
+	void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE);
+
+};
+
 #endif // LL_LLDRAWPOOLSIMPLE_H
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index db5debc07974338830fb2a7a67822465ff16bf1f..6e372b6f7626d2e4b352544e41afc70e11116d3b 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -33,16 +33,6 @@ const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
 
 static float sTime;
 
-int nhpo2(int v) 
-{
-	int r = 1;
-	while (r < v) {
-		r *= 2;
-	}
-	return r;
-}
-
-static GLuint sScreenTex = 0;
 BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
 
 LLDrawPoolWater::LLDrawPoolWater() :
@@ -69,30 +59,9 @@ LLDrawPoolWater::~LLDrawPoolWater()
 //static
 void LLDrawPoolWater::restoreGL()
 {
-	if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= SHADER_LEVEL_RIPPLE)
-	{
-		//build screen texture
-		glClientActiveTextureARB(GL_TEXTURE0_ARB);
-		glActiveTextureARB(GL_TEXTURE0_ARB);
-		glGenTextures(1, &sScreenTex);
-		LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
-		glBindTexture(GL_TEXTURE_2D, sScreenTex);
-		GLint viewport[4];
-		glGetIntegerv(GL_VIEWPORT, viewport);
-		GLuint resX = nhpo2(viewport[2]);
-		GLuint resY = nhpo2(viewport[3]);
-		
-		gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
-
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	}
+	
 }
 
-
 LLDrawPool *LLDrawPoolWater::instancePool()
 {
 	llerrs << "Should never be calling instancePool on a water pool!" << llendl;
@@ -130,7 +99,7 @@ void LLDrawPoolWater::render(S32 pass)
 
 	std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
 
-	LLGLSPipelineAlpha alphaState;
+	LLGLEnable blend(GL_BLEND);
 
 	if ((mVertexShaderLevel >= SHADER_LEVEL_RIPPLE))
 	{
@@ -324,7 +293,6 @@ void LLDrawPoolWater::render(S32 pass)
 	glDisableClientState(GL_NORMAL_ARRAY);
 	
 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
 }
 
 
@@ -508,50 +476,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
-void bindScreenToTexture() 
-{
-	if (LLDrawPoolWater::sSkipScreenCopy)
-	{
-		glBindTexture(GL_TEXTURE_2D, 0);
-	}
-	else
-	{
-
-		GLint viewport[4];
-		glGetIntegerv(GL_VIEWPORT, viewport);
-		GLuint resX = nhpo2(viewport[2]);
-		GLuint resY = nhpo2(viewport[3]);
-
-		glBindTexture(GL_TEXTURE_2D, sScreenTex);
-		GLint cResX;
-		GLint cResY;
-		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
-		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
-
-		if (cResX != (GLint)resX || cResY != (GLint)resY)
-		{
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
-			gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
-		}
-
-		glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); 
-
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-		float scale[2];
-		scale[0] = (float) viewport[2]/resX;
-		scale[1] = (float) viewport[3]/resY;
-		glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale);
-
-		LLImageGL::sBoundTextureMemory += resX * resY * 3;
-	}
-}
-
 void LLDrawPoolWater::shade()
 {
+	glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
+
 	static LLVector2 d1( 0.5f, -0.17f );
 	static LLVector2 d2( 0.58f, -0.67f );
 	static LLVector2 d3( 0.5f, 0.25f );
@@ -630,8 +558,18 @@ void LLDrawPoolWater::shade()
 
 	gPipeline.mWaterProgram.bind();
 	
-	bindScreenToTexture();
+	if (!sSkipScreenCopy)
+	{
+		gPipeline.bindScreenToTexture();
+	}
+	else
+	{
+		glBindTexture(GL_TEXTURE_2D, 0);
+	}
 	
+	glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, 
+			gPipeline.mScreenScale.mV);
+
 	S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
 	
 	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
@@ -693,6 +631,7 @@ void LLDrawPoolWater::shade()
 	
 	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
 }
 
 void LLDrawPoolWater::renderForSelect()
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index f2981625f79a109a3acfd0687078d61443a092e8..f3821a8b7a3b33d894227c740d33d5e0547cdc5e 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -47,6 +47,7 @@ LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder
 //-----------------------------------------------------------------------------
 LLDynamicTexture::~LLDynamicTexture()
 {
+	releaseGLTexture();
 	for( S32 order = 0; order < ORDER_COUNT; order++ )
 	{
 		LLDynamicTexture::sInstances[order].removeData(this);  // will fail in all but one case.
@@ -54,19 +55,23 @@ LLDynamicTexture::~LLDynamicTexture()
 }
 
 //-----------------------------------------------------------------------------
-// generateGLTexture()
+// releaseGLTexture()
 //-----------------------------------------------------------------------------
-void LLDynamicTexture::generateGLTexture()
+void LLDynamicTexture::releaseGLTexture()
 {
-	if (mComponents < 1 || mComponents > 4)
+	if (mTexture.notNull())
 	{
-		llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl;
+// 		llinfos << "RELEASING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl;
+		mTexture = NULL;
 	}
+}
 
-	LLPointer<LLImageRaw> raw_image = new LLImageRaw(mWidth, mHeight, mComponents);
-	mTexture = new LLImageGL(mWidth, mHeight, mComponents, FALSE);
-	mTexture->createGLTexture(0, raw_image);
-	mTexture->setClamp(mClamp, mClamp);
+//-----------------------------------------------------------------------------
+// generateGLTexture()
+//-----------------------------------------------------------------------------
+void LLDynamicTexture::generateGLTexture()
+{
+	generateGLTexture(-1, 0, 0, FALSE);
 }
 
 void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
@@ -75,10 +80,14 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima
 	{
 		llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl;
 	}
-
+	releaseGLTexture();
 	LLPointer<LLImageRaw> raw_image = new LLImageRaw(mWidth, mHeight, mComponents);
 	mTexture = new LLImageGL(mWidth, mHeight, mComponents, FALSE);
-	mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
+	if (internal_format >= 0)
+	{
+		mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
+	}
+// 	llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl;
 	mTexture->createGLTexture(0, raw_image);
 	mTexture->setClamp(mClamp, mClamp);
 }
diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h
index 75a37aaa297c50756336abbf63c3d987f616ee69..8f6ecb23b44b53c56bf1e0d2d1c49444030125c8 100644
--- a/indra/newview/lldynamictexture.h
+++ b/indra/newview/lldynamictexture.h
@@ -47,6 +47,7 @@ class LLDynamicTexture
 	static void restoreGL();
 
 protected:
+	void releaseGLTexture();
 	void generateGLTexture();
 	void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE);
 
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 6c008749825038da9213510b35890ea5b901af2b..280abcd541965ea97c0ef816eab34a7ecec3951d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -915,7 +915,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	LLVector2 tmin, tmax;
 	
 	const LLTextureEntry *tep = mVObjp->getTE(f);
-	U8  bump_code = tep ? bump_code = tep->getBumpmap() : 0;
+	U8  bump_code = tep ? tep->getBumpmap() : 0;
 
 	if (rebuild_tcoord)
 	{
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index eb5a3de1de123c528ba1bd0fa5330e94bffd9405..622af2b4732875ec2fb4cd1e72056b2dc07e0620 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -128,7 +128,8 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
 	// Compute icon for this item
 	LLUUID icon_id = get_item_icon_uuid(LLAssetType::AT_OBJECT, 
 						 LLInventoryType::IT_OBJECT,
-						 0x0);
+						 0x0, FALSE);
+
 	row["columns"][0]["column"] = "icon";
 	row["columns"][0]["type"] = "icon";
 	row["columns"][0]["value"] = icon_id;
@@ -224,9 +225,16 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
 		LLSD row;
 
 		// Compute icon for this item
+		BOOL item_is_multi = FALSE;
+		if ( inv_item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED )
+		{
+			item_is_multi = TRUE;
+		}
+
 		LLUUID icon_id = get_item_icon_uuid(inv_item->getType(), 
 							 inv_item->getInventoryType(),
-							 inv_item->getFlags());
+							 inv_item->getFlags(),
+							 item_is_multi);
 		row["columns"][0]["column"] = "icon";
 		row["columns"][0]["type"] = "icon";
 		row["columns"][0]["value"] = icon_id;
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index 155d4d6ff7eb318b34d15c778892642e5c067e43..3745de6552f29a19056d871f0850c716f33dddc0 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -195,9 +195,17 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
 
 		// Create the line in the list
 		LLSD row;
+
+		BOOL item_is_multi = FALSE;
+		if ( inv_item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED )
+		{
+			item_is_multi = TRUE;
+		}
+
 		LLUUID icon_id = get_item_icon_uuid(inv_item->getType(), 
 							 inv_item->getInventoryType(),
-							 inv_item->getFlags());
+							 inv_item->getFlags(),
+							 item_is_multi);
 		row["columns"][0]["column"] = "icon";
 		row["columns"][0]["type"] = "icon";
 		row["columns"][0]["value"] = icon_id;
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index 7eaac8887ccdbc23dfb656e3f2801010057a0cb2..ecab84f5d9e32805ea74198b4dde577493e382be 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -218,7 +218,7 @@ class LLSendPostcardResponder : public LLAssetUploadResponder
 	{	
 	}
 	// *TODO define custom uploadFailed here so it's not such a generic message
-	void LLSendPostcardResponder::uploadComplete(const LLSD& content)
+	void uploadComplete(const LLSD& content)
 	{
 		// we don't care about what the server returns from this post, just clean up the UI
 		LLUploadDialog::modalUploadFinished();
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 5f37d756fe6c36db8836a44867cb9cf587002bcf..e9fa4cc1dd2ce3a437e2bcc73aed23d2ec7aef43 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -2524,6 +2524,7 @@ LLFolderView::LLFolderView( const LLString& name, LLViewerImage* root_folder_ico
 	mShowSingleSelection(FALSE),
 	mArrangeGeneration(0),
 	mSelectCallback(NULL),
+	mSelectionChanged(FALSE),
 	mMinWidth(0),
 	mDragAndDropThisFrame(FALSE)
 {
@@ -4408,9 +4409,11 @@ LLInventoryFilter::LLInventoryFilter(const LLString& name) :
 	mFilterGeneration = 0;
 	mMustPassGeneration = S32_MAX;
 	mMinRequiredGeneration = 0;
+	mFilterCount = 0;
 	mNextFilterGeneration = mFilterGeneration + 1;
 
 	mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
+	mFilterBehavior = FILTER_NONE;
 }
 
 LLInventoryFilter::~LLInventoryFilter()
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c3ec9e8f2b28982efc8936cc1755fe18ca4ea4d5..0338e7f02a413b099023a87a56a632ddde2616b8 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -103,6 +103,7 @@ const char* ICON_NAME[ICON_NAME_COUNT] =
 	"inv_item_script.tga",
 	"inv_item_clothing.tga",
 	"inv_item_object.tga",
+	"inv_item_object_multi.tga",
 	"inv_item_notecard.tga",
 	"inv_item_bodypart.tga",
 	"inv_item_snapshot.tga",
@@ -2313,7 +2314,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 
 LLViewerImage* LLScriptBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0);
+	return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
 }
 
 // +=================================================+
@@ -2325,7 +2326,7 @@ LLString LLTextureBridge::sPrefix("Texture: ");
 
 LLViewerImage* LLTextureBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0);
+	return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
 }
 	
 void open_texture(const LLUUID& item_id, 
@@ -2375,7 +2376,7 @@ LLString LLSoundBridge::sPrefix("Sound: ");
 
 LLViewerImage* LLSoundBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0);
+	return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
 }
 
 void LLSoundBridge::openItem()
@@ -2470,7 +2471,7 @@ LLString LLLandmarkBridge::sPrefix("Landmark:  ");
 
 LLViewerImage* LLLandmarkBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited);
+	return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
 }
 
 void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
@@ -2631,7 +2632,7 @@ LLViewerImage* LLCallingCardBridge::getIcon() const
 	{
 		online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
 	}
-	return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online);
+	return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
 }
 
 LLString LLCallingCardBridge::getLabelSuffix() const
@@ -2779,7 +2780,7 @@ LLString LLNotecardBridge::sPrefix("Note: ");
 
 LLViewerImage* LLNotecardBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0);
+	return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
 }
 
 void open_notecard(const LLUUID& item_id, 
@@ -2851,7 +2852,7 @@ LLString LLGestureBridge::sPrefix("Gesture: ");
 
 LLViewerImage* LLGestureBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0);
+	return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
 }
 
 LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
@@ -2984,7 +2985,7 @@ LLString LLAnimationBridge::sPrefix("Animation: ");
 
 LLViewerImage* LLAnimationBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0);
+	return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
 }
 
 void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
@@ -3102,7 +3103,7 @@ BOOL LLObjectBridge::isItemRemovable()
 
 LLViewerImage* LLObjectBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt);
+	return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
 }
 
 void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
@@ -3357,7 +3358,7 @@ LLString LLLSLTextBridge::sPrefix("Script: ");
 
 LLViewerImage* LLLSLTextBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0);
+	return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
 }
 
 void LLLSLTextBridge::openItem()
@@ -4120,7 +4121,7 @@ LLString LLWearableBridge::getLabelSuffix() const
 
 LLViewerImage* LLWearableBridge::getIcon() const
 {
-	return get_item_icon(mAssetType, mInvType, mWearableType);
+	return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
 }
 
 // virtual
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 11573741a29b90b95defbeefab5f38ba57fccfd8..ddfc4fe791fbd39368254f2660bd008d12b20f19 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -22,6 +22,7 @@ enum EInventoryIcon
 	SCRIPT_ICON_NAME,
 	CLOTHING_ICON_NAME,
 	OBJECT_ICON_NAME,
+	OBJECT_MULTI_ICON_NAME,
 	NOTECARD_ICON_NAME,
 	BODYPART_ICON_NAME,
 	SNAPSHOT_ICON_NAME,
@@ -509,6 +510,8 @@ class LLObjectBridge : public LLItemBridge
 		LLItemBridge(inventory, uuid), mInvType(type)
 	{
 		mAttachPt = (flags & 0xff); // low bye of inventory flags
+
+		mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ?  TRUE: FALSE;
 	}
 
 protected:
@@ -516,7 +519,7 @@ class LLObjectBridge : public LLItemBridge
 	static LLUUID	sContextMenuItemID;  // Only valid while the context menu is open.
 	LLInventoryType::EType mInvType;
 	U32 mAttachPt;
-
+	BOOL mIsMultiObject;
 };
 
 
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 9e26d951bc4ae6bf5090adf07a9d2404f3ff3b1f..6171971c163a8eae4f6577880e93a15d2ea401b9 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1678,7 +1678,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
 			LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
 		}
 
-		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 	}
 
 	glPushMatrix();
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index e1ab8bf371effd1bcfa369878f7d10861176d601..b03747c68b5d822b0637be06a61af2f3c696cd5f 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -304,9 +304,16 @@ void LLPanelGroupNotices::setItem(LLPointer<LLInventoryItem> inv_item)
 {
 	mInventoryItem = inv_item;
 
+	BOOL item_is_multi = FALSE;
+	if ( inv_item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
+	{
+		item_is_multi = TRUE;
+	};
+
 	LLViewerImage* item_icon = get_item_icon(inv_item->getType(),
 										inv_item->getInventoryType(),
-										inv_item->getFlags());
+										inv_item->getFlags(),
+										item_is_multi );
 
 	mCreateInventoryIcon->setImage(item_icon->getID());
 	mCreateInventoryIcon->setVisible(TRUE);
@@ -463,7 +470,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
 		{
 			LLUUID icon_id = get_item_icon_uuid(
 						(LLAssetType::EType)asset_type,
-						LLInventoryType::IT_NONE,FALSE);
+						LLInventoryType::IT_NONE,FALSE, FALSE);
 			row["columns"][0]["type"] = "icon";
 			row["columns"][0]["value"] = icon_id;
 		}
@@ -531,7 +538,7 @@ void LLPanelGroupNotices::showNotice(const char* subject,
 
 		LLViewerImage* item_icon = get_item_icon(mInventoryOffer->mType,
 												LLInventoryType::IT_TEXTURE,
-												0);
+												0, FALSE);
 
 		mViewInventoryIcon->setImage(item_icon->getID());
 		mViewInventoryIcon->setVisible(TRUE);
diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index 4c4c15a9e287c35d87edd947c612ca881858a836..c49fee6d4afb6949fbe36b503236dd9980303cf8 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -321,7 +321,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName )
 		}
 
 		U8 rotationOrder;
-		numRead = fread(&rotationOrder, 1, 1, fp);
+		numRead = fread(&rotationOrder, sizeof(U8), 1, fp);
 
 		if (numRead != 1)
 		{
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 38c4f72fc9b79f19e2bc884f34682ca4bd81034e..98b4c4ef42aecef43e0032c41fcde778f82ebe9a 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1076,7 +1076,7 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
 			
 	if (drawablep->getPositionGroup().magVecSquared() > MAX_MAG)
 	{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
+#if 0 //ndef LL_RELEASE_FOR_DOWNLOAD
 		llwarns << "LLSpatialPartition::put Object out of range!" << llendl;
 		llinfos << drawablep->getPositionGroup() << llendl;
 
@@ -1726,8 +1726,9 @@ void LLSpatialPartition::processImagery(LLCamera* camera)
 				gPipeline.mCubeBuffer->initGL();
 			}
 
+			S32 res = gSavedSettings.getS32("RenderReflectionRes");
 			gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128);
-			gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, 64);
+			gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, res);
 			group->mReflectionMap = cube_map;
 			group->setState(LLSpatialGroup::GEOM_DIRTY);
 			gPipeline.markRebuild(group);
@@ -2203,7 +2204,7 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera)
 
 	glFlush();
 
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 }
 
 class LLOctreeGet : public LLSpatialGroup::OctreeTraveler
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 33e191cc9cde096b5a8215e6374a933f76918a39..fcabdc84509b80039cf0c3bb68ca33583f9a3787 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -36,8 +36,6 @@
 
 // SJB: We really always want to use the GL cache;
 // let GL page textures in and out of video RAM instead of trying to do so by hand.
-// const U32 USE_AVATAR_GL_CACHE_THRESHOLD = 1024 * 1024 * 35; // 35 MB
-BOOL gUseAvatarGLCache = TRUE; //FALSE;
 
 LLGradientPaletteList gGradientPaletteList;
 
@@ -218,8 +216,6 @@ BOOL LLTexLayerSetBuffer::render()
 {
 	U8* baked_bump_data = NULL;
 
-// 	gUseAvatarGLCache = ( gImageList.getMaxResidentTexMem() > USE_AVATAR_GL_CACHE_THRESHOLD );
-
 	// do we need to upload, and do we have sufficient data to create an uploadable composite?
 	// When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
 	BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
@@ -754,7 +750,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
 		glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
 		glBlendFunc( GL_ONE, GL_ZERO );
 
-		if( gUseAvatarGLCache )
 		{
 			LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE );
 			if( image_gl )
@@ -768,29 +763,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
 				success = FALSE;
 			}
 		}
-		else
-		{
-			LLImageRaw* image_raw = gTexStaticImageList.getImageRaw( getInfo()->mStaticAlphaFileName );
-			if( image_raw )
-			{
-				GLenum format = GL_ALPHA;
-				if( mAvatar->bindScratchTexture(format) )
-				{
-					glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, image_raw->getWidth(), image_raw->getHeight(), format, GL_UNSIGNED_BYTE, image_raw->getData() );
-					stop_glerror();
-
-					gl_rect_2d_simple_tex( width, height );
-				}
-				else
-				{
-					success = FALSE;
-				}
-			}
-			else
-			{
-				success = FALSE;
-			}
-		}
 		LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
 
 		glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
@@ -1267,23 +1239,6 @@ BOOL LLTexLayer::parseData( LLXmlTreeNode* node )
 //-----------------------------------------------------------------------------
 
 
-BOOL LLTexLayer::loadStaticImageRaw()
-{
-	if( mStaticImageRaw.isNull() && !mStaticImageInvalid)
-	{
-		mStaticImageRaw = gTexStaticImageList.getImageRaw( getInfo()->mStaticImageFileName );  
-		// We now have something in one of our caches
-		LLTexLayerSet::sHasCaches |= mStaticImageRaw.notNull() ? TRUE : FALSE;
-		if( mStaticImageRaw.isNull() )
-		{
-			llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl;
-			mStaticImageInvalid = TRUE; // don't try again.
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
 void LLTexLayer::deleteCaches()
 {
 	for( alpha_list_t::iterator iter = mParamAlphaList.begin();
@@ -1356,7 +1311,6 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
 
 	if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
 	{
-		if( gUseAvatarGLCache )
 		{
 			LLImageGL* image_gl = NULL;
 			if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
@@ -1382,29 +1336,10 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
 				success = FALSE;
 			}
 		}
-		else
-		{
-			LLPointer<LLImageRaw> image_raw = new LLImageRaw;
-			if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) )
-			{
-				success &= renderImageRaw( image_raw->getData(),
-										   image_raw->getWidth(),
-										   image_raw->getHeight(),
-										   image_raw->getComponents(), 
-										   width, 
-										   height, 
-										   FALSE );
-			}
-			else
-			{
-				success = FALSE;
-			}
-		}
 	}
 
 	if( !getInfo()->mStaticImageFileName.empty() )
 	{
-		if( gUseAvatarGLCache )
 		{
 			LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
 			if( image_gl )
@@ -1418,26 +1353,6 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
 				success = FALSE;
 			}
 		}
-		else
-		{
-			// Don't load the image file until we actually need it the first time.  Like now.
-			if (!loadStaticImageRaw())
-			{
-				success = FALSE;
-			}
-			if( mStaticImageRaw.notNull() )
-			{
-				success &= renderImageRaw( 
-					mStaticImageRaw->getData(),
-					mStaticImageRaw->getWidth(),
-					mStaticImageRaw->getHeight(),
-					mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask );
-			}
-			else
-			{
-				success = FALSE;
-			}
-		}
 	}
 
 	if( ((-1 == getInfo()->mLocalTexture) ||
@@ -1591,7 +1506,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 	// Accumulate the alpha component of the texture
 	if( getInfo()->mLocalTexture != -1 )
 	{
-		if( gUseAvatarGLCache )
 		{
 			LLImageGL* image_gl = NULL;
 			if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
@@ -1616,30 +1530,10 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 				success = FALSE;
 			}
 		}
-		else
-		{
-			LLPointer<LLImageRaw> image_raw = new LLImageRaw;
-			if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture,  image_raw ) )
-			{
-				if(image_raw->getComponents() == 4)
-				{
-					success &= renderImageRaw( 
-						image_raw->getData(),
-						image_raw->getWidth(),
-						image_raw->getHeight(),
-						image_raw->getComponents(), width, height, FALSE );
-				}
-			}
-			else
-			{
-				success = FALSE;
-			}
-		}
 	}
 
 	if( !getInfo()->mStaticImageFileName.empty() )
 	{
-		if( gUseAvatarGLCache )
 		{
 			LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
 			if( image_gl )
@@ -1658,31 +1552,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 				success = FALSE;
 			}
 		}
-		else
-		{
-			// Don't load the image file until we actually need it the first time.  Like now.
-			if (!loadStaticImageRaw())
-			{
-				success = FALSE;
-			}
-
-			if( mStaticImageRaw.notNull() )
-			{
-				if(	(mStaticImageRaw->getComponents() == 4) ||
-					( (mStaticImageRaw->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
-				{
-					success &= renderImageRaw( 
-						mStaticImageRaw->getData(),
-						mStaticImageRaw->getWidth(),
-						mStaticImageRaw->getHeight(),
-						mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask );
-				}
-			}
-			else
-			{
-				success = FALSE;
-			}
-		}
 	}
 
 	// Draw a rectangle with the layer color to multiply the alpha by that color's alpha.
@@ -2087,8 +1956,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
 		if(	!mCachedProcessedImageGL ||
 			(mCachedProcessedImageGL->getWidth() != image_tga_width) ||
 			(mCachedProcessedImageGL->getHeight() != image_tga_height) ||
-			(weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) ||
-			(!gUseAvatarGLCache) )
+			(weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) )
 		{
 //			llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
 			mCachedEffectiveWeight = effective_weight;
@@ -2130,7 +1998,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
 
 		if( mCachedProcessedImageGL )
 		{
-			if( gUseAvatarGLCache ) // 64 MB
 			{
 				if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
 				{
@@ -2168,94 +2035,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
 				}
 				stop_glerror();
 			}
-			else
-			{
-				if( (mCachedProcessedImageGL->getWidth() != VOAVATAR_SCRATCH_TEX_WIDTH) ||
-					(mCachedProcessedImageGL->getHeight() != VOAVATAR_SCRATCH_TEX_HEIGHT) )
-				{
-					if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
-					{
-						mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
-						
-						LLGLSNoAlphaTest gls_no_alpha_test;
-						
-						mCachedProcessedImageGL->bind();
-						mCachedProcessedImageGL->setClamp(TRUE, TRUE);
-
-						gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
-						gl_rect_2d_simple_tex( width, height );
-						LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-						mCachedProcessedImageGL->destroyGLTexture();
-					}
-					else
-					{
-						// Create the GL texture, bind it and draw a rect, and then immediately destroy it.
-						mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
-
-						LLGLSNoAlphaTest gls_no_alpha_test;
-						
-						mCachedProcessedImageGL->bind();
-						mCachedProcessedImageGL->setClamp(TRUE, TRUE);
-
-						gl_rect_2d_simple_tex( width, height );
-
-						LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-
-						mCachedProcessedImageGL->destroyGLTexture();
-					}
-					stop_glerror();
-				}
-				else
-				{
-					if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))
-					{
-						// Write into a pre-existing GL Image, and then bind and render that.
-						// Faster than creating a new GL Image and then destroying it.
-						if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_COLOR_INDEX ) )
-						{
-							glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
-								mCachedProcessedImageGL->getWidth(),
-								mCachedProcessedImageGL->getHeight(),
-								GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
-								mStaticImageRaw->getData() );
-							stop_glerror();
-
-							LLGLSNoAlphaTest gls_no_alpha_test;
-							gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight );
-							gl_rect_2d_simple_tex( width, height );
-
-							LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-						}
-						else
-						{
-							success = FALSE;
-						}
-					}
-					else
-					{
-						// Write into a pre-existing GL Image, and then bind and render that.
-						// Faster than creating a new GL Image and then destroying it.
-						if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_ALPHA ) )
-						{
-							glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
-								mCachedProcessedImageGL->getWidth(),
-								mCachedProcessedImageGL->getHeight(),
-								GL_ALPHA, GL_UNSIGNED_BYTE,
-								mStaticImageRaw->getData() );
-							stop_glerror();
-
-							LLGLSNoAlphaTest gls_no_alpha_test;
-							gl_rect_2d_simple_tex( width, height );
-
-							LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
-						}
-						else
-						{
-							success = FALSE;
-						}
-					}
-				}
-			}
 		}
 
 		// Don't keep the cache for other people's avatars
@@ -2606,7 +2385,6 @@ LLStringTable LLTexStaticImageList::sImageNames(16384);
 
 LLTexStaticImageList::LLTexStaticImageList()
 	:
-	mRawBytes( 0 ),
 	mGLBytes( 0 ),
 	mTGABytes( 0 )
 {}
@@ -2619,36 +2397,31 @@ LLTexStaticImageList::~LLTexStaticImageList()
 void LLTexStaticImageList::dumpByteCount()
 {
 	llinfos << "Avatar Static Textures " <<
-		" Raw:" << (mRawBytes / 1024) <<
 		"KB GL:" << (mGLBytes / 1024) <<
 		"KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
 }
 
 void LLTexStaticImageList::deleteCachedImages()
 {
-	if( mRawBytes || mGLBytes || mTGABytes )
+	if( mGLBytes || mTGABytes )
 	{
 		llinfos << "Clearing Static Textures " <<
-			" Raw:" << (mRawBytes / 1024) <<
 			"KB GL:" << (mGLBytes / 1024) <<
 			"KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
 
 		//mStaticImageLists uses LLPointers, clear() will cause deletion
 		
-		mStaticImageListRaw.clear();
 		mStaticImageListTGA.clear();
 		mStaticImageListGL.clear();
 		
-		mRawBytes = 0;
 		mGLBytes = 0;
 		mTGABytes = 0;
 	}
 }
 
-// Note: in general, for a given image image we'll call either getImageTga(), getImageRaw() or getImageGL().
+// Note: in general, for a given image image we'll call either getImageTga() or getImageGL().
 // We call getImageTga() if the image is used as an alpha gradient.
-// Otherwise, we call getImageRaw() if we have 32 MB or less of video RAM or less and getImageGL() if we have
-// more video RAM than that.
+// Otherwise, we call getImageGL()
 
 // Returns an LLImageTGA that contains the encoded data from a tga file named file_name.
 // Caches the result to speed identical subsequent requests.
@@ -2680,34 +2453,6 @@ LLImageTGA* LLTexStaticImageList::getImageTGA(const LLString& file_name)
 
 
 
-// Returns an LLImageRaw that contains the decoded data from a tga file named file_name.
-// Caches the result to speed identical subsequent requests.
-LLImageRaw* LLTexStaticImageList::getImageRaw(const LLString& file_name)
-{
-	LLPointer<LLImageRaw> image_raw;
-	const char *namekey = sImageNames.addString(file_name);
-	image_raw_map_t::iterator iter = mStaticImageListRaw.find(namekey);
-	if( iter != mStaticImageListRaw.end() )
-	{
-		image_raw = iter->second;
-	}
-	else
-	{
-		image_raw = new LLImageRaw();
-		if( loadImageRaw( file_name, image_raw ) )
-		{
-			mStaticImageListRaw[ namekey ] = image_raw;
-			mRawBytes += image_raw->getDataSize();
-		}
-		else
-		{
-			image_raw = NULL;
-		}
-	}
-
-	return image_raw;
-}
-
 // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name.
 // Caches the result to speed identical subsequent requests.
 LLImageGL* LLTexStaticImageList::getImageGL(const LLString& file_name, BOOL is_mask )
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 5c1a11cdf10c0a958ccbe99b657501b3294f9735..bda865eb2e3adc816fc492541857925262ead21e 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -321,9 +321,6 @@ class LLTexLayer
 	BOOL					renderAlphaMasks(  S32 x, S32 y, S32 width, S32 height, LLColor4* colorp );
 	BOOL					hasAlphaParams() { return (!mParamAlphaList.empty());}
 
-protected:
-	BOOL					loadStaticImageRaw();
-
 protected:
 	LLTexLayerSet*			mTexLayerSet;
 	LLPointer<LLImageRaw>	mStaticImageRaw;
@@ -498,15 +495,12 @@ class LLTexStaticImageList
 private:
 	static LLStringTable sImageNames;
 
-	typedef std::map< const char *, LLPointer<LLImageRaw> > image_raw_map_t;
 	typedef std::map< const char *, LLPointer<LLImageGL> > image_gl_map_t;
 	typedef std::map< const char *, LLPointer<LLImageTGA> > image_tga_map_t;
-	image_raw_map_t mStaticImageListRaw;
 	image_gl_map_t mStaticImageListGL;
 	image_tga_map_t mStaticImageListTGA;
 
 public:
-	S32 mRawBytes;
 	S32 mGLBytes;
 	S32 mTGABytes;
 };
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index cb846a43fe64b380a763e9ef93788ee2d85eb09b..1a3fe79551c245cdcab5baa7663cadd8224bb4ab 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -671,7 +671,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)
 			mWriteData = NULL; // we never owned data
 			mDataSize = 0;
 		}
-		mResponder->completed(success);
+		mCache->addCompleted(mResponder, success);
 	}
 }
 
@@ -705,6 +705,7 @@ LLTextureCache::LLTextureCache(bool threaded)
 	: LLWorkerThread("TextureCache", threaded),
 	  mWorkersMutex(getAPRPool()),
 	  mHeaderMutex(getAPRPool()),
+	  mListMutex(getAPRPool()),
 	  mFileAPRPool(NULL),
 	  mReadOnly(FALSE),
 	  mTexturesSizeTotal(0),
@@ -726,9 +727,17 @@ S32 LLTextureCache::update(U32 max_time_ms)
 	S32 res;
 	res = LLWorkerThread::update(max_time_ms);
 
+	mListMutex.lock();
+	handle_list_t priorty_list = mPrioritizeWriteList; // copy list
+	mPrioritizeWriteList.clear();
+	responder_list_t completed_list = mCompletedList; // copy list
+	mCompletedList.clear();
+	mListMutex.unlock();
+	
 	lockWorkers();
-	for (std::vector<handle_t>::iterator iter1 = mPrioritizeWriteList.begin();
-		 iter1 != mPrioritizeWriteList.end(); ++iter1)
+	
+	for (handle_list_t::iterator iter1 = priorty_list.begin();
+		 iter1 != priorty_list.end(); ++iter1)
 	{
 		handle_t handle = *iter1;
 		handle_map_t::iterator iter2 = mWriters.find(handle);
@@ -738,8 +747,17 @@ S32 LLTextureCache::update(U32 max_time_ms)
 			worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
 		}
 	}
-	mPrioritizeWriteList.clear();
+
+	for (responder_list_t::iterator iter1 = completed_list.begin();
+		 iter1 != completed_list.end(); ++iter1)
+	{
+		Responder *responder = iter1->first;
+		bool success = iter1->second;
+		responder->completed(success);
+	}
+	
 	unlockWorkers();
+	
 	return res;
 }
 
@@ -1294,9 +1312,16 @@ void LLTextureCache::prioritizeWrite(handle_t handle)
 {
 	// Don't prioritize yet, we might be working on this now
 	//   which could create a deadlock
+	LLMutexLock lock(&mListMutex);	
 	mPrioritizeWriteList.push_back(handle);
 }
 
+void LLTextureCache::addCompleted(Responder* responder, bool success)
+{
+	LLMutexLock lock(&mListMutex);
+	mCompletedList.push_back(std::make_pair(responder,success));
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 // Called from MAIN thread (endWork())
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index f9eb8cb177770c2b192811e18cdb539d2cb9e96d..f0f2ef47a8b6d379288622912abdbfa5e249aa62 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -84,6 +84,7 @@ class LLTextureCache : public LLWorkerThread
 	bool appendToTextureEntryList(const LLUUID& id, S32 size);
 	std::string getLocalFileName(const LLUUID& id);
 	std::string getTextureFileName(const LLUUID& id);
+	void addCompleted(Responder* responder, bool success);
 	
 private:
 	void setDirNames(ELLPath location);
@@ -99,12 +100,18 @@ class LLTextureCache : public LLWorkerThread
 	// Internal
 	LLMutex mWorkersMutex;
 	LLMutex mHeaderMutex;
+	LLMutex mListMutex;
 	apr_pool_t* mFileAPRPool;
 	
 	typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
 	handle_map_t mReaders;
 	handle_map_t mWriters;
-	std::vector<handle_t> mPrioritizeWriteList;
+
+	typedef std::vector<handle_t> handle_list_t;
+	handle_list_t mPrioritizeWriteList;
+
+	typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t;
+	responder_list_t mCompletedList;
 	
 	BOOL mReadOnly;
 	
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 4c90c3624b77b3ea3b62dbe15eb0a757003b9748..a9f660a0f5842deed43fc8222cef25371bc2bb5f 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -220,7 +220,6 @@ class LLTextureFetchWorker : public LLWorkerClass
 	U32 calcWorkPriority();
 	void removeFromCache();
 	bool processSimulatorPackets();
-	void startDecode();
 	bool decodeImage();
 	bool writeToCacheComplete();
 	
@@ -235,7 +234,7 @@ class LLTextureFetchWorker : public LLWorkerClass
 	void callbackDecoded(bool success);
 	
 private:
-	enum e_state
+	enum e_state // mState
 	{
 		// NOTE: Affects LLTextureBar::draw in lltextureview.cpp (debug hack)
 		INVALID = 0,
@@ -252,6 +251,14 @@ class LLTextureFetchWorker : public LLWorkerClass
 		WAIT_ON_WRITE,
 		DONE
 	};
+	enum e_request_state // mSentRequest
+	{
+		UNSENT = 0,
+		QUEUED = 1,
+		SENT_SIM = 2,
+		SENT_URL = 3,
+		SENT_HTTP = 4
+	};
 	static const char* sStateDescs[];
 	e_state mState;
 	LLTextureFetch* mFetcher;
@@ -261,6 +268,7 @@ class LLTextureFetchWorker : public LLWorkerClass
 	LLPointer<LLImageRaw> mAuxImage;
 	LLUUID mID;
 	LLHost mHost;
+	U8 mType;
 	F32 mImagePriority;
 	U32 mWorkPriority;
 	F32 mRequestedPriority;
@@ -270,7 +278,7 @@ class LLTextureFetchWorker : public LLWorkerClass
 	S32 mLoadedDiscard;
 	S32 mDecodedDiscard;
 	LLFrameTimer mRequestedTimer;
-	LLFrameTimer mIdleTimer;
+	LLFrameTimer mFetchTimer;
 	LLTextureCache::handle_t mCacheReadHandle;
 	LLTextureCache::handle_t mCacheWriteHandle;
 	U8* mBuffer;
@@ -280,12 +288,11 @@ class LLTextureFetchWorker : public LLWorkerClass
 	S32 mFileSize;
 	S32 mCachedSize;
 	BOOL mLoaded;
-	BOOL mRequested;
+	e_request_state mSentRequest;
 	BOOL mDecoded;
 	BOOL mWritten;
 	BOOL mNeedsAux;
 	BOOL mHaveAllData;
-	BOOL mUseHTTPGet;
 	BOOL mInLocalCache;
 	S32 mRetryAttempt;
 	std::string mURL;
@@ -306,7 +313,6 @@ class LLTextureFetchWorker : public LLWorkerClass
 	S32 mLastPacket;
 	U16 mTotalPackets;
 	U8 mImageCodec;
-	LLFrameTimer mFetchTimer; // debug
 };
 
 //static
@@ -357,12 +363,11 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mFileSize(0),
 	  mCachedSize(0),
 	  mLoaded(FALSE),
-	  mRequested(FALSE),
+	  mSentRequest(UNSENT),
 	  mDecoded(FALSE),
 	  mWritten(FALSE),
 	  mNeedsAux(FALSE),
 	  mHaveAllData(FALSE),
-	  mUseHTTPGet(FALSE),
 	  mInLocalCache(FALSE),
 	  mRetryAttempt(0),
 	  mActiveCount(0),
@@ -373,10 +378,10 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mImageCodec(IMG_CODEC_INVALID)
 {
 	calcWorkPriority();
-	if ((gSavedSettings.getBOOL("ImagePipelineUseHTTP")) &&
-		(host == LLHost::invalid))
+	mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
+	if (host == LLHost::invalid)
 	{
-		mUseHTTPGet = TRUE;
+		mHost = gAgent.getRegionHost();
 	}
 	if (!mFetcher->mDebugPause)
 	{
@@ -423,8 +428,10 @@ U32 LLTextureFetchWorker::calcWorkPriority()
 	return mWorkPriority;
 }
 
+// mWorkMutex is locked
 void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
 {
+	bool prioritize = false;
 	if (mDesiredDiscard != discard)
 	{
 		if (!haveWork())
@@ -438,8 +445,7 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
 		}
 		else if (mDesiredDiscard < discard)
 		{
-			U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
-			setPriority(work_priority);
+			prioritize = true;
 		}
 		mDesiredDiscard = discard;
 		mDesiredSize = size;
@@ -447,6 +453,10 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
 	else if (size > mDesiredSize)
 	{
 		mDesiredSize = size;
+		prioritize = true;
+	}
+	if (prioritize && mState == INIT)
+	{
 		U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH;
 		setPriority(work_priority);
 	}
@@ -490,9 +500,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 {
 	LLMutexLock lock(&mWorkMutex);
 
-	e_state old_state = mState;
-	mFetchTimer.reset();
-
 	if (mFetcher->mDebugPause)
 	{
 		return false; // debug: don't do any work
@@ -502,6 +509,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		mFetcher->mDebugCount++; // for setting breakpoints
 	}
 
+	if (mState != DONE)
+	{
+		mFetchTimer.reset();
+	}
+	
 	if (mState == INIT)
 	{
 		mRequestedDiscard = -1;
@@ -511,7 +523,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		mFileSize = 0;
 		mCachedSize = 0;
 		mLoaded = FALSE;
-		mRequested = FALSE;
+		mSentRequest = UNSENT;
 		mDecoded  = FALSE;
 		mWritten  = FALSE;
 		delete[] mBuffer;
@@ -587,21 +599,18 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 	if (mState == LOAD_FROM_NETWORK)
 	{
-		if (mFormattedImage.isNull())
-		{
-			mFormattedImage = new LLImageJ2C;
-		}
-		mState = mUseHTTPGet ? LOAD_FROM_HTTP_GET_URL : LOAD_FROM_SIMULATOR;
-		return false;
-	}
-	
-	if (mState == LOAD_FROM_SIMULATOR)
-	{
-		if (!mRequested)
+		if (mSentRequest == UNSENT)
 		{
+			if (mFormattedImage.isNull())
+			{
+				mFormattedImage = new LLImageJ2C;
+			}
+			// Add this to the network queue and sit here.
+			// LLTextureFetch::update() will send off a request which will change our state
 			S32 data_size = mFormattedImage->getDataSize();
 			if (data_size > 0)
 			{
+				// Only used for simulator requests
 				mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1;
 				if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size)
 				{
@@ -616,13 +625,19 @@ bool LLTextureFetchWorker::doWork(S32 param)
 					mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1;
 				}
 			}
-			mRequested = TRUE;
 			mRequestedSize = mDesiredSize;
 			mRequestedDiscard = mDesiredDiscard;
+			mSentRequest = QUEUED;
 			mFetcher->lockQueue();
 			mFetcher->addToNetworkQueue(this);
 			mFetcher->unlockQueue();
+			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 		}
+		return false;
+	}
+	
+	if (mState == LOAD_FROM_SIMULATOR)
+	{
 		if (processSimulatorPackets())
 		{
 			mFetcher->lockQueue();
@@ -644,11 +659,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		return false;
 	}
 	
+#if 0
 	if (mState == LOAD_FROM_HTTP_GET_URL)
 	{
-		if (!mRequested)
+		if (!mSentRequest)
 		{
-			mRequested = TRUE;
+			mSentRequest = TRUE;
 			mLoaded = FALSE;
 			std::string url;
 			LLViewerRegion* region = gAgent.getRegion();
@@ -660,14 +676,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			{
 				LLSD sd;
 				sd = mID.asString();
+				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 				LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID));
-//*TODO:uncomment 				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 				return false;
 			}
 			else
 			{
 				llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl;
-				mRequested = FALSE;
+				mSentRequest = FALSE;
 				mState = LOAD_FROM_SIMULATOR;
 				return false;
 			}
@@ -679,13 +695,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				if (!mURL.empty())
 				{
 					mState = LOAD_FROM_HTTP_GET_DATA;
-					mRequested = FALSE; // reset
+					mSentRequest = FALSE; // reset
 					mLoaded = FALSE; // reset
 				}
 				else
 				{
 					llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl;
-					mRequested = FALSE;
+					mSentRequest = FALSE;
 					mState = LOAD_FROM_SIMULATOR;
 					return false;
 				}
@@ -696,9 +712,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
 	
 	if (mState == LOAD_FROM_HTTP_GET_DATA)
 	{
-		if (!mRequested)
+		if (!mSentRequest)
 		{
-			mRequested = TRUE;
+			mSentRequest = TRUE;
 			S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have
 			mRequestedSize = mDesiredSize;
 			mRequestedDiscard = mDesiredDiscard;
@@ -724,9 +740,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			}
 			mLoaded = FALSE;
 // 			llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl;
+			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 			LLCurl::getByteRange(url, offset, mRequestedSize,
 								 new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority
-//*TODO:uncomment	setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 			return false; // not done
 		}
 
@@ -747,30 +763,23 @@ bool LLTextureFetchWorker::doWork(S32 param)
 					return false; // use what we have
 				}
 			}
-			llassert(mBufferSize == cur_size + mRequestedSize);
+			llassert_always(mBufferSize == cur_size + mRequestedSize);
 			if (mHaveAllData)
 			{
 				mFileSize = mBufferSize;
 			}
-			if (mRequestedSize > 0)
-			{
-				U8* buffer = new U8[mBufferSize];
-				if (cur_size > 0)
-				{
-					memcpy(buffer, mFormattedImage->getData(), cur_size);
-				}
-				memcpy(buffer + cur_size, mBuffer, mRequestedSize); // append
-				// NOTE: setData releases current data and owns new data (buffer)
-				mFormattedImage->setData(buffer, mBufferSize);
-				// delete temp data
-				delete[] mBuffer; // Note: not 'buffer' (assigned in setData())
-				mBuffer = NULL;
-				mBufferSize = 0;
-			}
-			else
+			U8* buffer = new U8[mBufferSize];
+			if (cur_size > 0)
 			{
-				llassert_always(cur_size);
+				memcpy(buffer, mFormattedImage->getData(), cur_size);
 			}
+			memcpy(buffer + cur_size, mBuffer, mRequestedSize); // append
+			// NOTE: setData releases current data and owns new data (buffer)
+			mFormattedImage->setData(buffer, mBufferSize);
+			// delete temp data
+			delete[] mBuffer; // Note: not 'buffer' (assigned in setData())
+			mBuffer = NULL;
+			mBufferSize = 0;
 			mLoadedDiscard = mRequestedDiscard;
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 			mState = DECODE_IMAGE;
@@ -781,13 +790,21 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 		return false;
 	}
-
+#endif
+	
 	if (mState == DECODE_IMAGE)
 	{
 		llassert_always(mFormattedImage->getDataSize() > 0);
 		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
-		startDecode();
+		mRawImage = NULL;
+		mAuxImage = NULL;
+		llassert_always(mImageWorker == NULL);
+		llassert_always(mFormattedImage.notNull());
+		S32 discard = mHaveAllData ? 0 : mLoadedDiscard;
+		U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
+		mDecoded  = FALSE;
 		mState = DECODE_IMAGE_UPDATE;
+		mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this));
 		// fall though (need to call requestDecodedData() to start work)
 	}
 	
@@ -828,7 +845,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 	if (mState == WRITE_TO_CACHE)
 	{
-		if (mInLocalCache || !mFileSize || !mRequested)
+		if (mInLocalCache || !mFileSize || mSentRequest == UNSENT)
 		{
 			// If we're in a local cache or we didn't actually receive any new data, skip
 			mState = DONE;
@@ -839,11 +856,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
 		U32 cache_priority = mWorkPriority;
 		mWritten = FALSE;
+		mState = WAIT_ON_WRITE;
 		CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
 		mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
 																  mFormattedImage->getData(), datasize,
 																  mFileSize, responder);
-		mState = WAIT_ON_WRITE;
 		// fall through
 	}
 	
@@ -876,10 +893,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 			return false;
 		}
-		if (old_state != DONE)
-		{
-			mIdleTimer.reset();
-		}
 		return true;
 	}
 	
@@ -942,12 +955,16 @@ bool LLTextureFetchWorker::deleteOK()
 			delete_ok = false;
 		}
 	}
-	// Don't delete while waiting for network requests *TODO: Need LLCurl::abort()
-	// Don't delete while waiting on writes
-	if ((mState >= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_URL &&
-		 mState <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA) ||
-		(mState >= LLTextureFetchWorker::WRITE_TO_CACHE &&
-		 mState <= LLTextureFetchWorker::WAIT_ON_WRITE))
+
+	const F32 MAX_IDLE_TIME = 5.f;
+	if ((mFetchTimer.getElapsedTimeF32() < MAX_IDLE_TIME))
+	{
+		delete_ok = false;
+	}
+	else if ((haveWork() &&
+			  // not ok to delete from these states
+			  ((mState >= LOAD_FROM_HTTP_GET_URL && mState <= LOAD_FROM_HTTP_GET_DATA) ||
+			   (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE))))
 	{
 		delete_ok = false;
 	}
@@ -1014,21 +1031,35 @@ bool LLTextureFetchWorker::processSimulatorPackets()
 
 void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success)
 {
+#if 0
 	LLMutexLock lock(&mWorkMutex);
+	if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_URL)
+	{
+		llwarns << "callbackURLReceived for unrequested fetch worker, req="
+				<< mSentRequest << " state= " << mState << llendl;
+		return;
+	}
 	if (success)
 	{
 		mURL = data.asString();
 	}
 	mLoaded = TRUE;
 	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+#endif
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
 void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block)
 {
+#if 0
 	LLMutexLock lock(&mWorkMutex);
-	llassert_always(mRequested);
+	if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_DATA)
+	{
+		llwarns << "callbackHttpGet for unrequested fetch worker, req="
+				<< mSentRequest << " state= " << mState << llendl;
+		return;
+	}
 // 	llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl;
 	if (mLoaded)
 	{
@@ -1070,6 +1101,7 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl
 	}
 	mLoaded = TRUE;
 	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+#endif
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1078,6 +1110,11 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima
 											 S32 imagesize, BOOL islocal)
 {
 	LLMutexLock lock(&mWorkMutex);
+	if (mState != LOAD_FROM_TEXTURE_CACHE)
+	{
+		llwarns << "Read callback for " << mID << " with state = " << mState << llendl;
+		return;
+	}
 	if (success)
 	{
 		llassert_always(imagesize > 0);
@@ -1097,6 +1134,11 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima
 void LLTextureFetchWorker::callbackCacheWrite(bool success)
 {
 	LLMutexLock lock(&mWorkMutex);
+	if (mState != WAIT_ON_WRITE)
+	{
+		llwarns << "Write callback for " << mID << " with state = " << mState << llendl;
+		return;
+	}
 	mWritten = TRUE;
 	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 }
@@ -1105,26 +1147,17 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success)
 
 void LLTextureFetchWorker::callbackDecoded(bool success)
 {
+	if (mState != DECODE_IMAGE_UPDATE)
+	{
+		llwarns << "Decode callback for " << mID << " with state = " << mState << llendl;
+		return;
+	}
 // 	llinfos << mID << " : DECODE COMPLETE " << llendl;
 	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-void LLTextureFetchWorker::startDecode()
-{
-	mRawImage = NULL;
-	mAuxImage = NULL;
-	llassert_always(mImageWorker == NULL);
-	llassert_always(mFormattedImage.notNull());
-	S32 discard = mHaveAllData ? 0 : mLoadedDiscard;
-	U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
-// 	llinfos << mID << " : DECODE STARTED : " << discard
-// 			<< " Pri: " << priority
-// 			<< " Components:" << (S32)mFormattedImage->getComponents() << llendl;
-	mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this));
-}
-
 bool LLTextureFetchWorker::decodeImage()
 {
 	llassert_always(mImageWorker);
@@ -1165,12 +1198,6 @@ bool LLTextureFetchWorker::decodeImage()
 		mImageWorker->scheduleDelete();
 		mImageWorker = NULL;
 	}
-	else
-	{
-		U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
-		mImageWorker->setPriority(image_priority);
-		//llinfos << worker->mID << " : DECODE PRIORITY : " << priority << llendl;
-	}
 	return res;
 }
 
@@ -1225,10 +1252,13 @@ bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 pri
 	if (iter != mRequestMap.end())
 	{
 		worker = iter->second;
-		if (worker->mHost != host)
+		LLHost host2 = host;
+		if (host2 == LLHost::invalid) host2 = gAgent.getRegionHost();	
+		if (worker->mHost != host2)
 		{
- 			llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts" << llendl;
-			removeRequest(worker, false);
+// 			llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts: "
+//					<< host << " != " << host2 << llendl;
+			removeRequest(worker, true);
 			worker = NULL;
 		}
 	}
@@ -1287,6 +1317,7 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
 		// i.e. a delete has not been requested
 		mNetworkQueue.insert(worker->mID);
 	}
+	mCancelQueue[worker->mHost].erase(worker->mID);
 }
 
 // call lockQueue() first!
@@ -1401,42 +1432,6 @@ S32 LLTextureFetch::update(U32 max_time_ms)
 		mNetworkTimer.reset();
 		sendRequestListToSimulators();
 	}
-
-#if 0 // Currently this logic is handled in LLViewer
-	{
-		LLMutexLock lock(&mQueueMutex);
-		const F32 MIN_IDLE_TIME = 1.f * 60.f; // 1 minute
-		const F32 MAX_IDLE_TIME = 5.f * 60.f; // 5 minutes
-		const S32 MIN_IDLE_COUNT = 16; // always keep last 16 idle requests
-		const F32 MAX_IDLE_COUNT = 1024; // max number of idle requests
-		// Remove any old requests (releasing their raw data)
-		typedef std::pair<F32, LLTextureFetchWorker*> idle_pair;
-		typedef std::set<idle_pair, compare_pair_greater<F32,LLTextureFetchWorker*> > idle_set;
-		idle_set remove_set;
-		for (map_t::iterator iter = mRequestMap.begin(); iter != mRequestMap.end(); ++iter)
-		{
-			LLTextureFetchWorker* worker = iter->second;
-			if (worker->mActiveCount > 0)
-				continue;
-			if (worker->haveWork())
-				continue;
-			F32 idletime = worker->mIdleTimer.getElapsedTimeF32();
-			if (idletime < MIN_IDLE_TIME)
-				continue;
-			remove_set.insert(std::make_pair(idletime, worker));
-		}
-		S32 num_left = remove_set.size();
-		for (idle_set::iterator iter = remove_set.begin(); iter != remove_set.end(); ++iter)
-		{
-			if (num_left <= MIN_IDLE_COUNT)
-				break;
-			if (iter->first < MAX_IDLE_TIME &&
-				num_left < MAX_IDLE_COUNT)
-				break;
-			num_left--;
-		}
-	}
-#endif
 	
 	return res;
 }
@@ -1466,7 +1461,7 @@ void LLTextureFetch::sendRequestListToSimulators()
 		if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1)
 		{
 			// We have all the packets... make sure this is high priority
-			req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
+// 			req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
 			continue;
 		}
 		F32 elapsed = req->mRequestedTimer.getElapsedTimeF32();
@@ -1478,58 +1473,79 @@ void LLTextureFetch::sendRequestListToSimulators()
 			requests[req->mHost].insert(req);
 		}
 	}
+
+	std::string http_url;
+#if 0
+	if (gSavedSettings.getBOOL("ImagePipelineUseHTTP"))
+	{
+		LLViewerRegion* region = gAgent.getRegion();
+		if (region)
+		{
+			http_url = region->getCapability("RequestTextureDownload");
+		}
+	}
+#endif
+	
 	for (work_request_map_t::iterator iter1 = requests.begin();
 		 iter1 != requests.end(); ++iter1)
 	{
+		bool use_http = http_url.empty() ? false : true;
 		LLHost host = iter1->first;
 		// invalid host = use agent host
-		if (host == LLHost::invalid)
+		if (host != gAgent.getRegionHost())
 		{
-			host = gAgent.getRegionHost();
+			use_http = false;
 		}
 
-		S32 request_count = 0;
-		for (request_list_t::iterator iter2 = iter1->second.begin();
-			 iter2 != iter1->second.end(); ++iter2)
+		if (use_http)
 		{
-			LLTextureFetchWorker* req = *iter2;
-			if (0 == request_count)
+		}
+		else
+		{
+			S32 request_count = 0;
+			for (request_list_t::iterator iter2 = iter1->second.begin();
+				 iter2 != iter1->second.end(); ++iter2)
 			{
-				gMessageSystem->newMessageFast(_PREHASH_RequestImage);
-				gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-				gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-				gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+				LLTextureFetchWorker* req = *iter2;
+				req->mSentRequest = LLTextureFetchWorker::SENT_SIM;
+				if (0 == request_count)
+				{
+					gMessageSystem->newMessageFast(_PREHASH_RequestImage);
+					gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+					gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+					gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+				}
+				S32 packet = req->mLastPacket + 1;
+				gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
+				gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
+				gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard);
+				gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
+				gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
+				U8 type = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
+				gMessageSystem->addU8Fast(_PREHASH_Type, type);
+// 				llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
+// 						<< " Packet: " << packet << " Priority: " << req->mImagePriority << llendl;
+
+				req->lockWorkData();
+				req->mSimRequestedDiscard = req->mDesiredDiscard;
+				req->mRequestedPriority = req->mImagePriority;
+				req->mRequestedTimer.reset();
+				req->unlockWorkData();
+				request_count++;
+				if (request_count >= IMAGES_PER_REQUEST)
+				{
+// 					llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+					gMessageSystem->sendSemiReliable(host, NULL, NULL);
+					request_count = 0;
+				}
 			}
-			S32 packet = req->mLastPacket + 1;
-			gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
-			gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
-			gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard);
-			gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
-			gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
-			U8 type = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
-			gMessageSystem->addU8Fast(_PREHASH_Type, type);
-// 			llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
-// 					<< " Packet: " << packet << " Priority: " << req->mImagePriority << llendl;
-
-			req->lockWorkData();
-			req->mSimRequestedDiscard = req->mDesiredDiscard;
-			req->mRequestedPriority = req->mImagePriority;
-			req->mRequestedTimer.reset();
-			req->unlockWorkData();
-			request_count++;
-			if (request_count >= IMAGES_PER_REQUEST)
+			if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
 			{
 // 				llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
 				gMessageSystem->sendSemiReliable(host, NULL, NULL);
 				request_count = 0;
-				break; // only send the top requests
 			}
 		}
-		if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
-		{
-// 			llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
-			gMessageSystem->sendSemiReliable(host, NULL, NULL);
-		}
 	}
 	
 	// Send cancelations
@@ -1539,11 +1555,6 @@ void LLTextureFetch::sendRequestListToSimulators()
 			 iter1 != mCancelQueue.end(); ++iter1)
 		{
 			LLHost host = iter1->first;
-			// invalid host = use agent host
-			if (host == LLHost::invalid)
-			{
-				host = gAgent.getRegionHost();
-			}
 			S32 request_count = 0;
 			for (queue_t::iterator iter2 = iter1->second.begin();
 				 iter2 != iter1->second.end(); ++iter2)
@@ -1586,12 +1597,12 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 	mRequestedTimer.reset();
 	if (index >= mTotalPackets)
 	{
-		llwarns << "Received Image Packet " << index << " > max: " << mTotalPackets << " Skipping. " << llendl;
+// 		llwarns << "Received Image Packet " << index << " > max: " << mTotalPackets << " for image: " << mID << llendl;
 		return false;
 	}
 	if (index > 0 && index < mTotalPackets-1 && size != MAX_IMG_PACKET_SIZE)
 	{
-		llwarns << "Received bad sized packet: " << index << ", " << size << " != " << MAX_IMG_PACKET_SIZE << " Skipping. " << llendl;
+// 		llwarns << "Received bad sized packet: " << index << ", " << size << " != " << MAX_IMG_PACKET_SIZE << " for image: " << mID << llendl;
 		return false;
 	}
 	
@@ -1601,7 +1612,7 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 	}
 	else if (mPackets[index] != NULL)
 	{
-// 		llwarns << "LLTextureFetchWorker::insertPacket called for duplicate packet: " << index << llendl;
+// 		llwarns << "Received duplicate packet: " << index << " for image: " << mID << llendl;
 		return false;
 	}
 
@@ -1613,20 +1624,49 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
 	return true;
 }
 
-bool LLTextureFetch::receiveImageHeader(const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
+bool LLTextureFetch::receiveImageHeader(const LLHost& host_in, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
 										U16 data_size, U8* data)
 {
 	LLMutexLock lock(&mQueueMutex);
 	LLTextureFetchWorker* worker = getWorker(id);
+	LLHost host = (host_in == LLHost::invalid) ? gAgent.getRegionHost() : host_in;
+	bool res = true;
+
+	++mPacketCount;
+	
 	if (!worker)
 	{
-// 		llwarns << "receiveImageHeader for non active worker: " << id << llendl;
-		return false;
+// 		llwarns << "Received header for non active worker: " << id << llendl;
+		res = false;
+	}
+	else if (host != worker->mHost)
+	{
+// 		llwarns << "Received header from wrong host for: " << id << llendl;
+		res = false;
+	}
+	else if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK ||
+			 worker->mSentRequest != LLTextureFetchWorker::SENT_SIM)
+	{
+ 		llwarns << "receiveImageHeader for worker: " << id
+				<< " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState]
+				<< " sent: " << worker->mSentRequest << llendl;
+		res = false;
 	}
-	// check to see if we've gotten this packet before
-	if (worker->mLastPacket != -1)
+	else if (worker->mLastPacket != -1)
 	{
-// 		llwarns << "Img: " << id << ":" << " Duplicate Image Header" << llendl;
+		// check to see if we've gotten this packet before
+// 		llwarns << "Received duplicate header for: " << id << llendl;
+		res = false;
+	}
+	else if (!data_size)
+	{
+		llwarns << "Img: " << id << ":" << " Empty Image Header" << llendl;
+		res = false;
+	}
+	if (!res)
+	{
+		++mBadPacketCount;
+		mCancelQueue[host].insert(id);
 		return false;
 	}
 
@@ -1637,40 +1677,68 @@ bool LLTextureFetch::receiveImageHeader(const LLUUID& id, U8 codec, U16 packets,
 	worker->mTotalPackets = packets;
 	worker->mFileSize = (S32)totalbytes;	
 	llassert_always(totalbytes > 0);
-	bool res = false;
-	if (data_size)
-	{
-		llassert(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);
-		res = worker->insertPacket(0, data, data_size);
-		worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
-	}
+	llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);
+	res = worker->insertPacket(0, data, data_size);
+	worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
+	worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR;
 	worker->unlockWorkData();
 	return res;
 }
 
-bool LLTextureFetch::receiveImagePacket(const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
+bool LLTextureFetch::receiveImagePacket(const LLHost& host_in, const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
 {
 	LLMutexLock lock(&mQueueMutex);
 	LLTextureFetchWorker* worker = getWorker(id);
+	LLHost host = (host_in == LLHost::invalid) ? gAgent.getRegionHost() : host_in;
+	bool res = true;
+
+	++mPacketCount;
+	
 	if (!worker)
 	{
-// 		llwarns << "receiveImagePacket " << packet_num << " for non active worker: " << id << llendl;
-		return false;
+// 		llwarns << "Received packet " << packet_num << " for non active worker: " << id << llendl;
+		res = false;
+	}
+	else if (host != worker->mHost)
+	{
+// 		llwarns << "Received packet from wrong host for: " << id << llendl;
+		res = false;
 	}
-	if (worker->mLastPacket == -1)
+	else if (worker->mLastPacket == -1)
 	{
-// 		llwarns << "Img: " << id << ":" << " Image Packet " << packet_num << " received before header" << llendl;
+// 		llwarns << "Received packet " << packet_num << " before header for: " << id << llendl;
+		res = false;
+	}
+	else if (!data_size)
+	{
+		llwarns << "Img: " << id << ":" << " Empty Image Header" << llendl;
+		res = false;
+	}
+	if (!res)
+	{
+		++mBadPacketCount;
+		mCancelQueue[host].insert(id);
 		return false;
 	}
 
-	bool res = false;
-	if (data_size)
+	worker->lockWorkData();
+	
+	res = worker->insertPacket(packet_num, data, data_size);
+	
+	if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) ||
+		(worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK))
 	{
-		worker->lockWorkData();
-		res = worker->insertPacket(packet_num, data, data_size);
 		worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
-		worker->unlockWorkData();
+		worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR;
 	}
+	else
+	{
+// 		llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id
+// 			<< " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl;
+	}
+	
+	worker->unlockWorkData();
+
 	return res;
 }
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 7cf7cb45f22898cdc5ef1a9c91aef367b3ad0fda..e4e94c048eec0ba965ed2f0d107832257d455210 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -37,8 +37,8 @@ class LLTextureFetch : public LLWorkerThread
 							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
 	bool updateRequestPriority(const LLUUID& id, F32 priority);
 
-	bool receiveImageHeader(const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
-	bool receiveImagePacket(const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
+	bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
+	bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
 
 	// Debug
 	S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
@@ -63,6 +63,8 @@ class LLTextureFetch : public LLWorkerThread
 	LLUUID mDebugID;
 	S32 mDebugCount;
 	BOOL mDebugPause;
+	S32 mPacketCount;
+	S32 mBadPacketCount;
 	
 private:
 	LLMutex mQueueMutex;
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index f051236fbac965390238174dcc6a5b3fb8895c40..b75e379755f7156276b3bcc32d9cf5fe9944d1b0 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -131,9 +131,7 @@ void LLTextureBar::draw()
 	{
 		S32 idx = llclamp(mHilite,1,4);
 		if (idx==1) color = LLColor4::yellow;
-		if (idx==2) color = LLColor4::cyan;
-		if (idx==3) color = LLColor4::magenta;
-		if (idx==4) color = LLColor4::blue;
+		else color = LLColor4::orange;
 	}
 	else if (mImagep->getBoostLevel())
 	{
@@ -331,7 +329,7 @@ void LLTextureBar::draw()
 
 BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	if (mask & MASK_ALT)
+	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == MASK_ALT)
 	{
 		gTextureFetch->mDebugID = mImagep->getID();
 		return TRUE;
@@ -453,9 +451,10 @@ void LLGLTexMemBar::draw()
 
 	LLGLEnable tex(GL_TEXTURE_2D);
 	
-	text = llformat("Textures: Count: %d Fetch: %d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d",
+	text = llformat("Textures: Count: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d",
 					gImageList.getNumImages(),
 					gTextureFetch->getNumRequests(), gTextureFetch->getNumDeletes(),
+					gTextureFetch->mPacketCount, gTextureFetch->mBadPacketCount, 
 					gTextureCache->getNumReads(), gTextureCache->getNumWrites(),
 					LLLFSThread::sLocal->getPending(),
 					LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(),
@@ -513,13 +512,14 @@ LLRect LLGLTexMemBar::getRequiredRect()
 ////////////////////////////////////////////////////////////////////////////
 
 LLTextureView::LLTextureView(const std::string& name, const LLRect& rect)
-:	LLContainerView(name, rect)
+	:	LLContainerView(name, rect),
+		mFreezeView(FALSE),
+		mOrderFetch(FALSE),
+		mPrintList(FALSE),
+		mNumTextureBars(0)
 {
 	setVisible(FALSE);
-	mFreezeView = FALSE;
-	mOrderFetch = FALSE;
 	
-	mNumTextureBars = 0;
 	setDisplayChildren(TRUE);
 	mGLTexMemBar = 0;
 }
@@ -567,10 +567,28 @@ void LLTextureView::draw()
 		typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t;
 		display_list_t display_image_list;
 	
+		if (mPrintList)
+		{
+			llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl;
+		}
+	
 		for (LLViewerImageList::image_priority_list_t::iterator iter = gImageList.mImageList.begin();
 			 iter != gImageList.mImageList.end(); )
 		{
 			LLPointer<LLViewerImage> imagep = *iter++;
+
+			if (mPrintList)
+			{
+				llinfos << imagep->getID()
+						<< "\t" <<  imagep->mTextureMemory
+						<< "\t" << imagep->getBoostLevel()
+						<< "\t" << imagep->getDecodePriority()
+						<< "\t" << imagep->getWidth()
+						<< "\t" << imagep->getHeight()
+						<< "\t" << imagep->getDiscardLevel()
+						<< llendl;
+			}
+		
 #if 0
 			if (imagep->getDontDiscard())
 			{
@@ -661,7 +679,12 @@ void LLTextureView::draw()
 				display_image_list.insert(std::make_pair(pri, imagep));
 			}
 		}
-
+		
+		if (mPrintList)
+		{
+			mPrintList = FALSE;
+		}
+		
 		static S32 max_count = 50;
 		S32 count = 0;
 		for (display_list_t::iterator iter = display_image_list.begin();
@@ -687,7 +710,7 @@ void LLTextureView::draw()
 			sortChildren(LLTextureBar::sort_fetch());
 		else
 			sortChildren(LLTextureBar::sort());
-	
+
 		mGLTexMemBar = new LLGLTexMemBar("gl texmem bar", this);
 		addChild(mGLTexMemBar);
 	
@@ -737,7 +760,12 @@ BOOL LLTextureView::addBar(LLViewerImage *imagep, S32 hilite)
 
 BOOL LLTextureView::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	if ((mask & MASK_CONTROL) && (mask & MASK_SHIFT))
+	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_ALT|MASK_SHIFT))
+	{
+		mPrintList = TRUE;
+		return TRUE;
+	}
+	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_CONTROL|MASK_SHIFT))
 	{
 		gTextureFetch->mDebugPause = !gTextureFetch->mDebugPause;
 		return TRUE;
diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h
index 691438c64ea9ae2c5f5c0bd3524c7e2ea8c22af1..4392b382a8880b118610acc6899a8b6a0e7ed057 100644
--- a/indra/newview/lltextureview.h
+++ b/indra/newview/lltextureview.h
@@ -18,6 +18,8 @@ class LLGLTexMemBar;
 
 class LLTextureView : public LLContainerView
 {
+	friend class LLTextureBar;
+	friend class LLGLTexMemBar;
 public:
 	LLTextureView(const std::string& name, const LLRect& rect);
 	~LLTextureView();
@@ -38,11 +40,11 @@ class LLTextureView : public LLContainerView
 	BOOL addBar(LLViewerImage *image, BOOL hilight = FALSE);
 	void removeAllBars();
 
-public:
+private:
 	BOOL mFreezeView;
 	BOOL mOrderFetch;
+	BOOL mPrintList;
 	
-private:
 	LLTextBox *mInfoTextp;
 
 	std::vector<LLTextureBar*> mTextureBars;
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index 0ab1fd1cbf660e2ffdb111d7ec1b2fbf59ec5b16..8efed010182826af481ffee423dceac6271465ca 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -253,7 +253,7 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass )
 					triangle_count += drawShape( pixelArea, FALSE );
 				}
 				// third past respects z buffer and writes color
-				glColorMask(TRUE, TRUE, TRUE, TRUE);
+				glColorMask(TRUE, TRUE, TRUE, FALSE);
 				{
 					LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
 					triangle_count += drawShape( pixelArea, FALSE );
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index cbbc2ac6cd883741d7e34358c92c4e58b7ec3744..9a437291952fcd8ea0c673fe433fe4c684d67022 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -422,6 +422,8 @@ void handle_dump_image_list(void*);
 void handle_fullscreen_debug(void*);
 void handle_crash(void*);
 void handle_dump_followcam(void*);
+void handle_toggle_flycam(void*);
+BOOL check_flycam(void*);
 void handle_viewer_enable_message_log(void*);
 void handle_viewer_disable_message_log(void*);
 void handle_send_postcard(void*);
@@ -884,6 +886,9 @@ void init_client_menu(LLMenuGL* menu)
 	menu->append(new LLMenuItemToggleGL("Disable Camera Constraints", 
 		&LLViewerCamera::sDisableCameraConstraints));
 
+	menu->append(new LLMenuItemCheckGL("Joystick Flycam", 
+		&handle_toggle_flycam,NULL,&check_flycam,NULL));
+		
 	menu->append(new LLMenuItemCheckGL("Mouse Smoothing",
 										&menu_toggle_control,
 										NULL,
@@ -1158,6 +1163,9 @@ void init_debug_rendering_menu(LLMenuGL* menu)
 	sub_menu->append(new LLMenuItemCheckGL("LightTrace",&LLPipeline::toggleRenderDebug, NULL,
 													&LLPipeline::toggleRenderDebugControl,
 													(void*)LLPipeline::RENDER_DEBUG_LIGHT_TRACE));
+	sub_menu->append(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, NULL,
+													&LLPipeline::toggleRenderDebugControl,
+													(void*)LLPipeline::RENDER_DEBUG_GLOW));
 	
 	sub_menu->append(new LLMenuItemCheckGL("Show Depth Buffer",
 										   &menu_toggle_control,
@@ -6321,6 +6329,20 @@ void handle_dump_followcam(void*)
 	LLFollowCamMgr::dump();
 }
 
+BOOL check_flycam(void*)
+{
+	return LLPipeline::sOverrideAgentCamera;
+}
+
+void handle_toggle_flycam(void*)
+{
+	LLPipeline::sOverrideAgentCamera = !LLPipeline::sOverrideAgentCamera;
+	if (LLPipeline::sOverrideAgentCamera)
+	{
+		LLFloaterJoystick::show(NULL);
+	}
+}
+
 void handle_viewer_enable_message_log(void*)
 {
 	gMessageSystem->startLogging();
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 259fa0930986b44be955af3dac0abf8953e259a8..f9e74f31e66978f849dbd7812df7c039445ff369 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -323,7 +323,16 @@ void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font )
 			}
 			break;
 		  case LLAssetType::AT_CLOTHING:		img_name = "inv_item_clothing.tga";	break;
-		  case LLAssetType::AT_OBJECT:			img_name = "inv_item_object.tga";	break;
+		  case LLAssetType::AT_OBJECT:			
+			if (item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
+			{
+				img_name = "inv_item_object_multi.tga";	
+			}
+			else
+			{
+				img_name = "inv_item_object.tga";	
+			}
+			break;
 		  case LLAssetType::AT_NOTECARD:		img_name = "inv_item_notecard.tga";	break;
 		  case LLAssetType::AT_LSL_TEXT:		img_name = "inv_item_script.tga";	break;
 		  case LLAssetType::AT_BODYPART:		img_name = "inv_item_bodypart.tga";	break;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a2dadcc438dfa0f84109eca8b428ff0ac2109e6d..41f937efd5ad50721382a30b97c219ad2f2d9f29 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -3007,7 +3007,7 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask
 	glViewport(scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4);
 	stop_glerror();
 
-	glClearColor(0.f, 0.f, 0.f, 1.f);
+	glClearColor(0.f, 0.f, 0.f, 0.f);
 	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
 	// Draw the objects so the user can select them.
@@ -3098,7 +3098,7 @@ void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*
 	glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4);
 	stop_glerror();
 
-	glClearColor(0.f, 0.f, 0.f, 1.f);
+	glClearColor(0.f, 0.f, 0.f, 0.f);
 	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 
 	// Draw the objects so the user can select them.
@@ -3974,7 +3974,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 			gDisplaySwapBuffers = FALSE;
 			if (type == SNAPSHOT_TYPE_OBJECT_ID)
 			{
-				glClearColor(0.f, 0.f, 0.f, 1.f);
+				glClearColor(0.f, 0.f, 0.f, 0.f);
 				glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
 				gCamera->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f9ee5064a1fef04bba9a978007a1df568c96c37c..5db295874c015855cf00644852d77cb4a369ac45 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1725,6 +1725,9 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info)
 		mScreenp = new LLViewerJoint("mScreen", NULL);
 		// for now, put screen at origin, as it is only used during special
 		// HUD rendering mode
+		F32 aspect = gCamera->getAspect();
+		LLVector3 scale(1.f, aspect, 1.f);
+		mScreenp->setScale(scale);
 		mScreenp->setWorldPosition(LLVector3::zero);
 	}
 
@@ -3005,12 +3008,9 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
 	{
 		F32 aspect = gCamera->getAspect();
 		LLVector3 scale(1.f, aspect, 1.f);
-		if (mScreenp->getScale() != scale)
-		{
-			mScreenp->setScale(scale);
-			mScreenp->updateWorldMatrixChildren();
-			resetHUDAttachments();
-		}
+		mScreenp->setScale(scale);
+		mScreenp->updateWorldMatrixChildren();
+		resetHUDAttachments();
 	}
 
 	// clear debug text
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index eb62f8ceb09f9e2cdf83c86613c44cb8e31c1544..987d2ac7cbfede92087d76a4560c0cdb344296b5 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -443,7 +443,7 @@ void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt)
 			}
 			
 			U32* pix = (U32*)(data + offset);
-			LLColor4 temp = LLColor4(col);
+			LLColor4 temp = LLColor4(col, 0);
 			LLColor4U temp1 = LLColor4U(temp);
 			*pix = temp1.mAll;
 		}
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index c705c3951e59b31cc3b63d022620f84562bac3f7..0ded91bb809e96cc30c3bf4efbea464885bad850 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -671,6 +671,7 @@ class LLVOSky : public LLStaticViewerObject
 
 public:
 	static F32 sNighttimeBrightness; // [0,2] default = 1.0
+	LLFace				*mFace[FACE_COUNT];
 
 protected:
 	LLPointer<LLViewerImage> mSunTexturep;
@@ -700,8 +701,7 @@ class LLVOSky : public LLStaticViewerObject
 	BOOL				mWeatherChange;
 	F32					mCloudDensity;
 	F32					mWind;
-	LLFace				*mFace[FACE_COUNT];
-
+	
 	BOOL				mInitialized;
 	BOOL				mForceUpdate;				//flag to force instantaneous update of cubemap
 	LLVector3			mLastLightingDirection;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 66195319536d345f4f841c5870e1a0dbfb40eb50..b5b9e06831326b731dba729939f0c639a7a63e1f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1768,7 +1768,8 @@ F32 LLVOVolume::getBinRadius()
 	
 	BOOL shrink_wrap = mDrawable->isAnimating();
 	BOOL alpha_wrap = FALSE;
-	//if (!shrink_wrap)
+
+	if (!isHUDAttachment())
 	{
 		for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
 		{
@@ -1779,6 +1780,10 @@ F32 LLVOVolume::getBinRadius()
 			}
 		}
 	}
+	else
+	{
+		shrink_wrap = FALSE;
+	}
 
 	if (alpha_wrap)
 	{
@@ -1959,12 +1964,15 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		draw_info->mVSize = facep->getVirtualSize();
 		draw_vec.push_back(draw_info);
 		LLVOVolume* volume = (LLVOVolume*) facep->getViewerObject();
-		LLColor3 col = volume->getLightColor();
+		BOOL is_light = volume->mDrawable->isLight();
+
+		U8 alpha = is_light ? 196 : 160;
+		LLColor3 col = is_light ? volume->getLightColor() : LLColor3(0,0,0);
 		LLColor4 col2 = facep->getRenderColor();
 		draw_info->mGlowColor.setVec((U8) (col.mV[0]*col2.mV[0]*255),
 									(U8) (col.mV[1]*col2.mV[1]*255),
 									(U8) (col.mV[2]*col2.mV[2]*255),
-									196);					
+									alpha);					
 		draw_info->mTextureMatrix = tex_mat;
 		validate_draw_info(*draw_info);
 	}
@@ -2269,7 +2277,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					registerFace(group, facep, LLRenderPass::PASS_BUMP);
 				}
 
-				if (vobj->getIsLight())
+				if (vobj->getIsLight() ||
+					(LLPipeline::sRenderGlow && facep->isState(LLFace::FULLBRIGHT)))
 				{
 					registerFace(group, facep, LLRenderPass::PASS_GLOW);
 				}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c7ecb225fb362e20146861c24b66a3dc811f7bfd..6b7f60457d244d3173707c5d1b12089ff25fb9dc 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -25,7 +25,7 @@
 #include "material_codes.h"
 #include "timing.h"
 #include "v3color.h"
-#include "llui.h"
+#include "llui.h" 
 #include "llglheaders.h"
 
 // newview includes
@@ -70,6 +70,7 @@
 #include "llworld.h"
 #include "viewer.h"
 #include "llcubemap.h"
+#include "lldebugmessagebox.h"
 
 #ifdef _DEBUG
 // Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -157,6 +158,13 @@ const char* LLPipeline::sTerrainUniforms[] =
 
 U32 LLPipeline::sTerrainUniformCount = sizeof(LLPipeline::sTerrainUniforms)/sizeof(char*);
 
+const char* LLPipeline::sGlowUniforms[] =
+{
+	"delta"
+};
+
+U32 LLPipeline::sGlowUniformCount = sizeof(LLPipeline::sGlowUniforms)/sizeof(char*);
+
 const char* LLPipeline::sShinyUniforms[] = 
 {
 	"origin"
@@ -196,6 +204,14 @@ void stamp(F32 x, F32 y, F32 xs, F32 ys)
 	glEnd();
 }
 
+U32 nhpo2(U32 v) 
+{
+	U32 r = 1;
+	while (r < v) {
+		r *= 2;
+	}
+	return r;
+}
 
 
 //----------------------------------------
@@ -210,10 +226,14 @@ BOOL	LLPipeline::sRenderSoundBeacons = FALSE;
 BOOL	LLPipeline::sUseOcclusion = FALSE;
 BOOL	LLPipeline::sSkipUpdate = FALSE;
 BOOL	LLPipeline::sDynamicReflections = FALSE;
+BOOL	LLPipeline::sRenderGlow = FALSE;
+BOOL	LLPipeline::sOverrideAgentCamera = FALSE;
 
 LLPipeline::LLPipeline() :
+	mScreenTex(0),
 	mCubeBuffer(NULL),
-	mCubeList(0),
+	mGlowMap(0),
+	mGlowBuffer(0),
 	mVertexShadersEnabled(FALSE),
 	mVertexShadersLoaded(0),
 	mLastRebuildPool(NULL),
@@ -225,11 +245,14 @@ LLPipeline::LLPipeline() :
 	mWaterPool(NULL),
 	mGroundPool(NULL),
 	mSimplePool(NULL),
+	mGlowPool(NULL),
 	mBumpPool(NULL),
 	mLightMask(0),
 	mLightMovingMask(0)
 {
-
+	mFramebuffer[0] = mFramebuffer[1] = 0;
+	mCubeFrameBuffer = 0;
+	mCubeDepth = 0;
 }
 
 void LLPipeline::init()
@@ -256,6 +279,7 @@ void LLPipeline::init()
 	getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
 	getPool(LLDrawPool::POOL_SIMPLE);
 	getPool(LLDrawPool::POOL_BUMP);
+	getPool(LLDrawPool::POOL_GLOW);
 
 	mTrianglesDrawnStat.reset();
 	resetFrameStats();
@@ -339,20 +363,12 @@ void LLPipeline::cleanup()
 	mGroundPool = NULL;
 	delete mSimplePool;
 	mSimplePool = NULL;
+	delete mGlowPool;
+	mGlowPool = NULL;
 	delete mBumpPool;
 	mBumpPool = NULL;
 
-	if (mCubeBuffer)
-	{
-		delete mCubeBuffer;
-		mCubeBuffer = NULL;
-	}
-
-	if (mCubeList)
-	{
-		glDeleteLists(mCubeList, 1);
-		mCubeList = 0;
-	}
+	releaseGLBuffers();
 
 	mBloomImagep = NULL;
 	mBloomImage2p = NULL;
@@ -395,16 +411,46 @@ void LLPipeline::destroyGL()
 	clearRenderMap();
 	resetVertexBuffers();
 
+	releaseGLBuffers();
+}
+
+void LLPipeline::releaseGLBuffers()
+{
+	if (mGlowMap)
+	{
+		glDeleteTextures(1, &mGlowMap);
+		mGlowMap = 0;
+	}
+
+	if (mGlowBuffer)
+	{
+		glDeleteTextures(1, &mGlowBuffer);
+		mGlowBuffer = 0;
+	}
+
+	if (mScreenTex)
+	{
+		glDeleteTextures(1, &mScreenTex);
+		mScreenTex = 0;
+	}
+
 	if (mCubeBuffer)
 	{
 		delete mCubeBuffer;
 		mCubeBuffer = NULL;
 	}
 
-	if (mCubeList)
+	if (mCubeFrameBuffer)
+	{
+		glDeleteFramebuffersEXT(1, &mCubeFrameBuffer);
+		glDeleteRenderbuffersEXT(1, &mCubeDepth);
+		mCubeDepth = mCubeFrameBuffer = 0;
+	}
+
+	if (mFramebuffer[0])
 	{
-		glDeleteLists(mCubeList, 1);
-		mCubeList = 0;
+		glDeleteFramebuffersEXT(2, mFramebuffer);
+		mFramebuffer[0] = mFramebuffer[1] = 0;
 	}
 }
 
@@ -665,8 +711,16 @@ BOOL LLPipeline::validateProgramObject(GLhandleARB obj)
 
 void LLPipeline::setShaders()
 {
-	sDynamicReflections = gSavedSettings.getBOOL("RenderDynamicReflections");
-
+	if (gGLManager.mHasFramebufferObject)
+	{
+		sDynamicReflections = gSavedSettings.getBOOL("RenderDynamicReflections");
+		sRenderGlow = gSavedSettings.getBOOL("RenderGlow");
+	}
+	else
+	{
+		sDynamicReflections = sRenderGlow = FALSE;
+	}
+	
 	//hack to reset buffers that change behavior with shaders
 	resetVertexBuffers();
 
@@ -788,6 +842,7 @@ void LLPipeline::unloadShaders()
 	mObjectAlphaProgram.unload();
 	mWaterProgram.unload();
 	mTerrainProgram.unload();
+	mGlowProgram.unload();
 	mGroundProgram.unload();
 	mAvatarProgram.unload();
 	mAvatarEyeballProgram.unload();
@@ -913,6 +968,7 @@ BOOL LLPipeline::loadShadersEnvironment()
 		mWaterProgram.unload();
 		mGroundProgram.unload();
 		mTerrainProgram.unload();
+		mGlowProgram.unload();
 		return FALSE;
 	}
 	
@@ -977,6 +1033,26 @@ BOOL LLPipeline::loadShadersEnvironment()
 		}
 	}
 
+	if (success)
+	{
+		//load glow shader
+		std::string glowvertex = "environment/glowV.glsl";
+		std::string glowfragment = "environment/glowF.glsl";
+		mGlowProgram.mProgramObject = glCreateProgramObjectARB();
+		mGlowProgram.attachObjects(baseObjects, baseCount);
+		mGlowProgram.attachObject(loadShader(glowvertex, SHADER_ENVIRONMENT, GL_VERTEX_SHADER_ARB));
+		mGlowProgram.attachObject(loadShader(glowfragment, SHADER_ENVIRONMENT, GL_FRAGMENT_SHADER_ARB));
+		success = mGlowProgram.mapAttributes();
+		if (success)
+		{
+			success = mGlowProgram.mapUniforms(sGlowUniforms, sGlowUniformCount);
+		}
+		if (!success)
+		{
+			llwarns << "Failed to load " << glowvertex << llendl;
+		}
+	}
+
 	if( !success )
 	{
 		mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
@@ -1356,6 +1432,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
 		poolp = mSimplePool;
 		break;
 
+	case LLDrawPool::POOL_GLOW:
+		poolp = mGlowPool;
+		break;
+
 	case LLDrawPool::POOL_TREE:
 		poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
 		break;
@@ -2777,8 +2857,8 @@ void LLPipeline::renderGeom(LLCamera& camera)
 	else
 	{
 		LLFastTimer t(LLFastTimer::FTM_POOLS);
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
 		calcNearbyLights();
-
 		pool_set_t::iterator iter1 = mPools.begin();
 		while ( iter1 != mPools.end() )
 		{
@@ -2851,12 +2931,13 @@ void LLPipeline::renderGeom(LLCamera& camera)
 			iter1 = iter2;
 			stop_glerror();
 		}
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 	}
 
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
 #endif
 
 	if (occlude)
@@ -2886,6 +2967,38 @@ void LLPipeline::renderGeom(LLCamera& camera)
 	// Contains a list of the faces of objects that are physical or
 	// have touch-handlers.
 	mHighlightFaces.clear();
+
+	if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
+		!LLDrawPoolWater::sSkipScreenCopy &&
+		sRenderGlow &&
+		gGLManager.mHasFramebufferObject)
+	{
+		const U32 glow_res = nhpo2(gSavedSettings.getS32("RenderGlowResolution"));
+		if (mGlowMap == 0)
+		{
+			glGenTextures(1, &mGlowMap);
+			glBindTexture(GL_TEXTURE_2D, mGlowMap);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		}
+
+		if (mGlowBuffer == 0)
+		{
+			glGenTextures(1, &mGlowBuffer);
+			glBindTexture(GL_TEXTURE_2D, mGlowBuffer);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glow_res, glow_res, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		}
+
+		bindScreenToTexture();
+		renderBloom(mScreenTex, mGlowMap, mGlowBuffer, glow_res, LLVector2(0,0), mScreenScale);
+	}
 }
 
 void LLPipeline::processGeometry(LLCamera& camera)
@@ -3257,6 +3370,18 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
 		}
 		break;
 
+	case LLDrawPool::POOL_GLOW:
+		if (mGlowPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate glow pool." << llendl;
+		}
+		else
+		{
+			mGlowPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
 	case LLDrawPool::POOL_TREE:
 		mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
 		break;
@@ -3376,6 +3501,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
 		mSimplePool = NULL;
 		break;
 
+	case LLDrawPool::POOL_GLOW:
+		llassert(mGlowPool == poolp);
+		mGlowPool = NULL;
+		break;
+
 	case LLDrawPool::POOL_TREE:
 		#ifdef _DEBUG
 			{
@@ -4445,8 +4575,6 @@ BOOL LLGLSLShader::mapUniforms(const char** uniform_names,  S32 count)
 	mUniform.resize(count + LLPipeline::sReservedUniformCount, -1);
 	mTexture.resize(count + LLPipeline::sReservedUniformCount, -1);
 	
-
-
 	bind();
 
 	//get the number of active uniforms
@@ -4663,6 +4791,14 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 		glGenTextures(1, &blur_tex);
 	}
 
+	BOOL reattach = FALSE;
+	if (mCubeFrameBuffer == 0)
+	{
+		glGenFramebuffersEXT(1, &mCubeFrameBuffer);
+		glGenRenderbuffersEXT(1, &mCubeDepth);
+		reattach = TRUE;
+	}
+
 	BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
 	if (toggle_ui)
 	{
@@ -4679,6 +4815,7 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 					(1 << LLPipeline::RENDER_TYPE_CLOUDS) |
 					//(1 << LLPipeline::RENDER_TYPE_STARS) |
 					//(1 << LLPipeline::RENDER_TYPE_AVATAR) |
+					(1 << LLPipeline::RENDER_TYPE_GLOW) |
 					(1 << LLPipeline::RENDER_TYPE_GRASS) |
 					(1 << LLPipeline::RENDER_TYPE_VOLUME) |
 					(1 << LLPipeline::RENDER_TYPE_TERRAIN) |
@@ -4712,9 +4849,43 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 
 	gPipeline.calcNearbyLights();
 
+	cube_map->bind();
 	for (S32 i = 0; i < 6; i++)
 	{
+		GLint res_x, res_y;
+		glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_WIDTH, &res_x);
+		glGetTexLevelParameteriv(cube_face[i], 0, GL_TEXTURE_HEIGHT, &res_y);
+
+		if (res_x != res || res_y != res)
+		{
+			glTexImage2D(cube_face[i],0,GL_RGBA,res,res,0,GL_RGBA,GL_FLOAT,NULL);
+			reattach = TRUE;
+		}
+	}
+	cube_map->disable();
+
+	if (reattach)
+	{
+		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth);
+		GLint res_x, res_y;
+		glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &res_x);
+		glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &res_y);
+
+		if (res_x != res || res_y != res)
+		{
+			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,res,res);
+		}
 		
+		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+	}
+
+	for (S32 i = 0; i < 6; i++)
+	{
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
+		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+									cube_face[i], cube_map->getGLName(), 0);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+										GL_RENDERBUFFER_EXT, mCubeDepth);		
 		glMatrixMode(GL_PROJECTION);
 		glLoadIdentity();
 		gluPerspective(90.f, 1.f, 0.1f, 1024.f);
@@ -4723,7 +4894,6 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 		
 		apply_cube_face_rotation(i);
 
-		
 		glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
 		cube_cam.setOrigin(origin);
 		LLViewerCamera::updateFrustumPlanes(cube_cam);
@@ -4731,15 +4901,12 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 		gPipeline.updateCull(cube_cam);
 		gPipeline.stateSort(cube_cam);
 		
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 		gPipeline.renderGeom(cube_cam);
-
-		cube_map->enable(0);
-		cube_map->bind();
-		glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, 0, res, res, 0);
-		cube_map->disable();
 	}
 
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
 	cube_cam.setOrigin(origin);
 	gPipeline.resetDrawOrders();
 	gPipeline.mShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
@@ -4756,14 +4923,12 @@ void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam,
 	{
 		gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
 	}
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	LLDrawPoolWater::sSkipScreenCopy = FALSE;
 }
 
 //send cube map vertices and texture coordinates
 void render_cube_map()
 {
-	
 	U32 idx[36];
 
 	idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
@@ -4810,7 +4975,7 @@ void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32
 {
 	LLGLEnable cube(GL_TEXTURE_CUBE_MAP_ARB);
 	LLGLDepthTest depth(GL_FALSE);
-
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 	glMatrixMode(GL_PROJECTION);
 	glPushMatrix();
 	glLoadIdentity();
@@ -4823,9 +4988,9 @@ void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32
 	
 	S32 kernel = 2;
 	F32 step = 90.f/res;
-	F32 alpha = 1.f/((kernel*2+1));
+	F32 alpha = 1.f/((kernel*2)+1);
 
-	glColor4f(1,1,1,alpha);
+	glColor4f(alpha,alpha,alpha,alpha*1.25f);
 
 	S32 x = 0;
 
@@ -4847,7 +5012,7 @@ void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32
 	};
 
 	
-	glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
+	glBlendFunc(GL_ONE, GL_ONE);
 	//3-axis blur
 	for (U32 j = 0; j < 3; j++)
 	{
@@ -4879,7 +5044,7 @@ void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32
 		}
 		for (U32 i = 0; i < 6; i++)
 		{
-			glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, i*res, res, res, 0);
+			glCopyTexImage2D(cube_face[i], 0, GL_RGBA, 0, i*res, res, res, 0);
 		}
 	}
 	
@@ -4889,6 +5054,273 @@ void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32
 	glPopMatrix();
 
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void LLPipeline::bindScreenToTexture() 
+{
+	LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
+
+	if (mScreenTex == 0)
+	{
+		glGenTextures(1, &mScreenTex);
+		glBindTexture(GL_TEXTURE_2D, mScreenTex);
+		GLint viewport[4];
+		glGetIntegerv(GL_VIEWPORT, viewport);
+		GLuint resX = nhpo2(viewport[2]);
+		GLuint resY = nhpo2(viewport[3]);
+		
+		gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, resX, resY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	}
+
+	GLint viewport[4];
+	glGetIntegerv(GL_VIEWPORT, viewport);
+	GLuint resX = nhpo2(viewport[2]);
+	GLuint resY = nhpo2(viewport[3]);
+
+	glBindTexture(GL_TEXTURE_2D, mScreenTex);
+	GLint cResX;
+	GLint cResY;
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
+
+	if (cResX != (GLint)resX || cResY != (GLint)resY)
+	{
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
+		gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+	}
+
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); 
+
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+	
+	mScreenScale.mV[0] = (float) viewport[2]/resX;
+	mScreenScale.mV[1] = (float) viewport[3]/resY;
+	
+	LLImageGL::sBoundTextureMemory += resX * resY * 3;
 }
 
+void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, LLVector2 tc1, LLVector2 tc2)
+{
+	mGlowProgram.bind();
+
+	if (!gGLManager.mHasFramebufferObject)
+	{
+		llerrs << "WTF?" << llendl;
+	}
+
+	LLGLEnable tex(GL_TEXTURE_2D);
+	LLGLDepthTest depth(GL_FALSE);
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable cull(GL_CULL_FACE);
+
+	if (mFramebuffer[0] == 0)
+	{
+		glGenFramebuffersEXT(2, mFramebuffer);
+	}
+
+	GLint viewport[4];
+	glGetIntegerv(GL_VIEWPORT, viewport);
+	glViewport(0,0,res,res);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+
+	glBindTexture(GL_TEXTURE_2D, source);
+	
+	S32 kernel = gSavedSettings.getS32("RenderGlowSize")*2;
+	
+	LLGLDisable test(GL_ALPHA_TEST);
+
+	F32 delta = 1.f/(res*gSavedSettings.getF32("RenderGlowStrength"));
+
+	for (S32 i = 0; i < kernel; i++)
+	{
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer[i%2]);
+		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
+								GL_COLOR_ATTACHMENT0_EXT,
+								GL_TEXTURE_2D, 
+								i%2 == 0 ? buffer : dest, 0);
+		
+		glBindTexture(GL_TEXTURE_2D, i == 0 ? source : 
+									i%2==0 ? dest :
+									buffer);
+		
+		glUniform1fARB(mGlowProgram.mUniform[LLPipeline::GLSL_GLOW_DELTA],delta);					
 
+		glBegin(GL_TRIANGLE_STRIP);
+		glTexCoord2f(tc1.mV[0], tc1.mV[1]);
+		glVertex2f(-1,-1);
+		
+		glTexCoord2f(tc1.mV[0], tc2.mV[1]);
+		glVertex2f(-1,1);
+		
+		glTexCoord2f(tc2.mV[0], tc1.mV[1]);
+		glVertex2f(1,-1);
+		
+		glTexCoord2f(tc2.mV[0], tc2.mV[1]);
+		glVertex2f(1,1);
+		glEnd();
+	
+		tc1.setVec(0,0);
+		tc2.setVec(1,1);
+		
+	}
+
+	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+	mGlowProgram.unbind();
+
+	glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW))
+	{
+		glClear(GL_COLOR_BUFFER_BIT);
+	}
+
+	glBindTexture(GL_TEXTURE_2D, dest);
+	{
+		LLGLEnable blend(GL_BLEND);
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+		glBegin(GL_TRIANGLE_STRIP);
+		glColor4f(1,1,1,1);
+		glTexCoord2f(tc1.mV[0], tc1.mV[1]);
+		glVertex2f(-1,-1);
+		
+		glTexCoord2f(tc1.mV[0], tc2.mV[1]);
+		glVertex2f(-1,1);
+		
+		glTexCoord2f(tc2.mV[0], tc1.mV[1]);
+		glVertex2f(1,-1);
+		
+		glTexCoord2f(tc2.mV[0], tc2.mV[1]);
+		glVertex2f(1,1);
+		glEnd();
+
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+}
+
+void LLPipeline::updateCamera()
+{
+	LLWindow* window = gViewerWindow->getWindow();
+
+	F32 time = gFrameIntervalSeconds;
+
+	S32 axis[] = 
+	{
+		gSavedSettings.getS32("JoystickAxis0"),
+		gSavedSettings.getS32("JoystickAxis1"),
+		gSavedSettings.getS32("JoystickAxis2"),
+		gSavedSettings.getS32("JoystickAxis3"),
+		gSavedSettings.getS32("JoystickAxis4"),
+		gSavedSettings.getS32("JoystickAxis5")
+	};
+
+	F32 axis_scale[] =
+	{
+		gSavedSettings.getF32("JoystickAxisScale0"),
+		gSavedSettings.getF32("JoystickAxisScale1"),
+		gSavedSettings.getF32("JoystickAxisScale2"),
+		gSavedSettings.getF32("JoystickAxisScale3"),
+		gSavedSettings.getF32("JoystickAxisScale4"),
+		gSavedSettings.getF32("JoystickAxisScale5")
+	};
+
+	F32 dead_zone[] =
+	{
+		gSavedSettings.getF32("JoystickAxisDeadZone0"),
+		gSavedSettings.getF32("JoystickAxisDeadZone1"),
+		gSavedSettings.getF32("JoystickAxisDeadZone2"),
+		gSavedSettings.getF32("JoystickAxisDeadZone3"),
+		gSavedSettings.getF32("JoystickAxisDeadZone4"),
+		gSavedSettings.getF32("JoystickAxisDeadZone5")
+	};
+
+	F32 cur_delta[6];
+	static F32 last_delta[] = {0,0,0,0,0,0};
+	static F32 delta[] = { 0,0,0,0,0,0 };
+
+	F32 feather = gSavedSettings.getF32("FlycamFeathering");
+	BOOL absolute = gSavedSettings.getBOOL("FlycamAbsolute");
+
+	for (U32 i = 0; i < 6; i++)
+	{
+		cur_delta[i] = window->getJoystickAxis(axis[i]);	
+		F32 tmp = cur_delta[i];
+		if (absolute)
+		{
+			cur_delta[i] = cur_delta[i] - last_delta[i];
+		}
+		last_delta[i] = tmp;
+
+		if (cur_delta[i] > 0)
+		{
+			cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f);
+		}
+		else
+		{
+			cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f);
+		}
+		cur_delta[i] *= axis_scale[i];
+		
+		if (!absolute)
+		{
+			cur_delta[i] *= time;
+		}
+
+		delta[i] = delta[i] + (cur_delta[i]-delta[i])*time*feather;
+	}
+	
+	mFlyCamPosition += LLVector3(delta) * mFlyCamRotation;
+
+	LLMatrix3 rot_mat(delta[3],
+					  delta[4],
+					  delta[5]);
+	
+	mFlyCamRotation = LLQuaternion(rot_mat)*mFlyCamRotation;
+
+	if (gSavedSettings.getBOOL("FlycamAutoLeveling"))
+	{
+		LLMatrix3 level(mFlyCamRotation);
+
+		LLVector3 x = LLVector3(level.mMatrix[0]);
+		LLVector3 y = LLVector3(level.mMatrix[1]);
+		LLVector3 z = LLVector3(level.mMatrix[2]);
+
+		y.mV[2] = 0.f;
+		y.normVec();
+
+		level.setRows(x,y,z);
+		level.orthogonalize();
+				
+		LLQuaternion quat = LLQuaternion(level);
+		mFlyCamRotation = nlerp(llmin(feather*time,1.f), mFlyCamRotation, quat);
+	}
+
+	LLMatrix3 mat(mFlyCamRotation);
+
+	gCamera->setOrigin(mFlyCamPosition);
+	gCamera->mXAxis = LLVector3(mat.mMatrix[0]);
+	gCamera->mYAxis = LLVector3(mat.mMatrix[1]);
+	gCamera->mZAxis = LLVector3(mat.mMatrix[2]);
+}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 5061ef742c5663bf428ad7dbc01978abd2f13f48..4d89b65c90c05ae691d6252c7e0e83c29a262e29 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -87,10 +87,13 @@ class LLPipeline
 	void destroyGL();
 	void restoreGL();
 	void resetVertexBuffers();
+	void releaseGLBuffers();
 	void resetVertexBuffers(LLDrawable* drawable);
 	void setUseVBO(BOOL use_vbo);
 	void generateReflectionMap(LLCubeMap* cube_map, LLCamera& camera, GLsizei res);
 	void blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res);
+	void bindScreenToTexture();
+	void renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, LLVector2 tc1, LLVector2 tc2);
 
 	void init();
 	void cleanup();
@@ -281,6 +284,8 @@ class LLPipeline
 		RENDER_TYPE_TREE		= LLDrawPool::POOL_TREE,
 		RENDER_TYPE_WATER		= LLDrawPool::POOL_WATER,
  		RENDER_TYPE_ALPHA		= LLDrawPool::POOL_ALPHA,
+		RENDER_TYPE_GLOW		= LLDrawPool::POOL_GLOW,
+
 		// Following are object types (only used in drawable mRenderType)
 		RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES,
 		RENDER_TYPE_VOLUME,
@@ -327,7 +332,8 @@ class LLPipeline
 		RENDER_DEBUG_TEXTURE_AREA		= 0x08000,
 		RENDER_DEBUG_FACE_AREA			= 0x10000,
 		RENDER_DEBUG_PARTICLES			= 0x20000,
-		RENDER_DEBUG_TEXTURE_ANIM		= 0x40000,
+		RENDER_DEBUG_GLOW				= 0x40000,
+		RENDER_DEBUG_TEXTURE_ANIM		= 0x80000,
 	};
 
 	LLPointer<LLViewerImage>	mAlphaSizzleImagep;
@@ -355,6 +361,11 @@ class LLPipeline
 	LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj);
 	LLSpatialPartition* getSpatialPartition(U32 index);
 
+	void updateCamera();
+	
+	LLVector3				mFlyCamPosition;
+	LLQuaternion			mFlyCamRotation;
+
 	BOOL					 mBackfaceCull;
 	S32						 mTrianglesDrawn;
 	LLStat                   mTrianglesDrawnStat;
@@ -378,10 +389,28 @@ class LLPipeline
 	static BOOL				sUseOcclusion;
 	static BOOL				sSkipUpdate; //skip lod updates
 	static BOOL				sDynamicReflections;
+	static BOOL				sRenderGlow;
+	static BOOL				sOverrideAgentCamera;
+
+	//screen texture
+	GLuint					mScreenTex;
+	LLVector2				mScreenScale;
+
+	//texture for making the glow
+	GLuint					mGlowMap;
+	GLuint					mGlowBuffer;
+
+	//framebuffer objects for off-screen scratch space
+	GLuint					mFramebuffer[2];
 
-	//cube map for anti-aliasing reflections
+	//dynamic cube map scratch space
 	LLCubeMap*				mCubeBuffer;
-	GLuint					mCubeList;
+
+	//frambuffer object for rendering dynamic cube maps
+	GLuint					mCubeFrameBuffer;
+	
+	//depth buffer object for rendering dynamic cube maps
+	GLuint					mCubeDepth;
 
 	class LLScatterShader
 	{
@@ -465,8 +494,18 @@ class LLPipeline
 		GLSL_TERRAIN_ALPHARAMP
 	} eTerrainUniforms;
 
+	//glow parameters
+	static const char* sGlowUniforms[];
+	static U32 sGlowUniformCount;
+
+	typedef enum
+	{
+		GLSL_GLOW_DELTA = GLSL_END_RESERVED_UNIFORMS
+	} eGlowUniforms;
+
 	//environment shaders
 	LLGLSLShader			mTerrainProgram;
+	LLGLSLShader			mGlowProgram;
 	LLGLSLShader			mGroundProgram;
 	LLGLSLShader			mWaterProgram;
 
@@ -627,6 +666,7 @@ class LLPipeline
 	LLDrawPool*					mWaterPool;
 	LLDrawPool*					mGroundPool;
 	LLRenderPass*				mSimplePool;
+	LLDrawPool*					mGlowPool;
 	LLDrawPool*					mBumpPool;
 	// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar