diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 5e540ad8c58bd2b2ad4b7614329509aa43270a21..5fa28cb90254935db97094f515481b1a2754d0aa 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -1264,6 +1264,7 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
 	mSyncSlave(false),
 	mQueueSounds(false),
 	mPlayedOnce(false),
+	mCorrupted(false),
 	mType(type),
 	mChannelp(NULL),
 	mCurrentDatap(NULL),
@@ -1296,16 +1297,25 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp)
 
 void LLAudioSource::update()
 {
+	if(mCorrupted)
+	{
+		return ; //no need to update
+	}
+
 	if (!getCurrentBuffer())
 	{
 		if (getCurrentData())
 		{
 			// Hack - try and load the sound.  Will do this as a callback
 			// on decode later.
-			if (getCurrentData()->load())
+			if (getCurrentData()->load() && getCurrentData()->getBuffer())
 			{
 				play(getCurrentData()->getID());
-			}			
+			}
+			else
+			{
+				mCorrupted = true ;
+			}
 		}
 	}
 }
@@ -1421,6 +1431,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
 
 bool LLAudioSource::isDone() const
 {
+	if(mCorrupted)
+	{
+		return true ;
+	}
+
 	const F32 MAX_AGE = 60.f;
 	const F32 MAX_UNPLAYED_AGE = 15.f;
 	const F32 MAX_MUTED_AGE = 11.f;
@@ -1736,7 +1751,7 @@ LLAudioData::LLAudioData(const LLUUID &uuid) :
 	}
 }
 
-
+//return false when the audio file is corrupted.
 bool LLAudioData::load()
 {
 	// For now, just assume we're going to use one buffer per audiodata.
@@ -1752,7 +1767,7 @@ bool LLAudioData::load()
 	{
 		// No free buffers, abort.
 		llinfos << "Not able to allocate a new audio buffer, aborting." << llendl;
-		return false;
+		return true;
 	}
 
 	std::string uuid_str;
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 30d24906357a724b2ab7b292c6fddfb2a54805a5..a47ee7ca7ca692053b86f72dec6efee2cd81fa17 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -334,6 +334,7 @@ class LLAudioSource
 	bool			mSyncSlave;
 	bool			mQueueSounds;
 	bool			mPlayedOnce;
+	bool            mCorrupted;
 	S32             mType;
 	LLVector3d		mPositionGlobal;
 	LLVector3		mVelocity;
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 5dee7a3541ee1f4e4a161b15725286ca005d8742..1738c16dea4be7ef1ac72c80a0f4a01e9b3fdf48 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -109,7 +109,7 @@ void LLQueuedThread::shutdown()
 
 // MAIN THREAD
 // virtual
-S32 LLQueuedThread::update(U32 max_time_ms)
+S32 LLQueuedThread::update(F32 max_time_ms)
 {
 	if (!mStarted)
 	{
@@ -122,7 +122,7 @@ S32 LLQueuedThread::update(U32 max_time_ms)
 	return updateQueue(max_time_ms);
 }
 
-S32 LLQueuedThread::updateQueue(U32 max_time_ms)
+S32 LLQueuedThread::updateQueue(F32 max_time_ms)
 {
 	F64 max_time = (F64)max_time_ms * .001;
 	LLTimer timer;
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 499d13a79201126a074feffb8cfef4cd2c26d327..d3704b0fe22ad4e43d509e99901ebb6b215951aa 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -173,8 +173,8 @@ class LL_COMMON_API LLQueuedThread : public LLThread
 public:
 	bool waitForResult(handle_t handle, bool auto_complete = true);
 
-	virtual S32 update(U32 max_time_ms);
-	S32 updateQueue(U32 max_time_ms);
+	virtual S32 update(F32 max_time_ms);
+	S32 updateQueue(F32 max_time_ms);
 	
 	void waitOnPending();
 	void printQueueStats();
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 4988bdf570054e5416d75aab5b50ce2a0d08456a..3d05a30ac2240b2d0b91f01156d7312675faa2a7 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -81,7 +81,7 @@ void LLWorkerThread::clearDeleteList()
 }
 
 // virtual
-S32 LLWorkerThread::update(U32 max_time_ms)
+S32 LLWorkerThread::update(F32 max_time_ms)
 {
 	S32 res = LLQueuedThread::update(max_time_ms);
 	// Delete scheduled workers
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 78a4781d157b3c634f8b5fb458aa9f4ea1b09b19..be46394d6eff2ad9ffd3ae99669afe2f388cd745 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -86,7 +86,7 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread
 	LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
 	~LLWorkerThread();
 
-	/*virtual*/ S32 update(U32 max_time_ms);
+	/*virtual*/ S32 update(F32 max_time_ms);
 	
 	handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
 	
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 28dc3bd313365a58409042d40c9ad4601b0332c5..ad2eb0f69c56e1f9968940707f2b11567765d10f 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -46,7 +46,7 @@ LLImageDecodeThread::~LLImageDecodeThread()
 
 // MAIN THREAD
 // virtual
-S32 LLImageDecodeThread::update(U32 max_time_ms)
+S32 LLImageDecodeThread::update(F32 max_time_ms)
 {
 	LLMutexLock lock(mCreationMutex);
 	for (creation_list_t::iterator iter = mCreationList.begin();
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index c684222fa5f85f10794ed51217b59c35cebf1570..1bfb0ddfd3f28ca36ff3dd1b760a61dd7cff32fa 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -78,7 +78,7 @@ class LLImageDecodeThread : public LLQueuedThread
 	handle_t decodeImage(LLImageFormatted* image,
 						 U32 priority, S32 discard, BOOL needs_aux,
 						 Responder* responder);
-	S32 update(U32 max_time_ms);
+	S32 update(F32 max_time_ms);
 
 	// Used by unit tests to check the consistency of the thread instance
 	S32 tut_size();
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 3c1ae45d6862680e64101f2683756791675ce034..1b11e83b4af369cd4119d19e81d79f486f90014d 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -80,8 +80,8 @@ class LLOctreeNode : public LLTreeNode<T>
 	typedef LLOctreeTraveler<T>									oct_traveler;
 	typedef LLTreeTraveler<T>									tree_traveler;
 	typedef typename std::set<LLPointer<T> >					element_list;
-	typedef typename std::set<LLPointer<T> >::iterator			element_iter;
-	typedef typename std::set<LLPointer<T> >::const_iterator	const_element_iter;
+	typedef typename element_list::iterator						element_iter;
+	typedef typename element_list::const_iterator	const_element_iter;
 	typedef typename std::vector<LLTreeListener<T>*>::iterator	tree_listener_iter;
 	typedef typename std::vector<LLOctreeNode<T>* >				child_list;
 	typedef LLTreeNode<T>		BaseType;
@@ -114,6 +114,8 @@ class LLOctreeNode : public LLTreeNode<T>
 			mOctant = ((oct_node*) mParent)->getOctant(mCenter);
 		}
 
+		mElementCount = 0;
+
 		clearChildren();
 	}
 
@@ -219,11 +221,11 @@ class LLOctreeNode : public LLTreeNode<T>
 	void accept(oct_traveler* visitor)				{ visitor->visit(this); }
 	virtual bool isLeaf() const						{ return mChild.empty(); }
 	
-	U32 getElementCount() const						{ return mData.size(); }
+	U32 getElementCount() const						{ return mElementCount; }
 	element_list& getData()							{ return mData; }
 	const element_list& getData() const				{ return mData; }
 	
-	U32 getChildCount()	const						{ return mChild.size(); }
+	U32 getChildCount()	const						{ return mChildCount; }
 	oct_node* getChild(U32 index)					{ return mChild[index]; }
 	const oct_node* getChild(U32 index) const		{ return mChild[index]; }
 	child_list& getChildren()						{ return mChild; }
@@ -300,17 +302,13 @@ class LLOctreeNode : public LLTreeNode<T>
 			if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
 				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity))) 
 			{ //it belongs here
-#if LL_OCTREE_PARANOIA_CHECK
 				//if this is a redundant insertion, error out (should never happen)
-				if (mData.find(data) != mData.end())
-				{
-					llwarns << "Redundant octree insertion detected. " << data << llendl;
-					return false;
-				}
-#endif
+				llassert(mData.find(data) == mData.end());
 
 				mData.insert(data);
 				BaseType::insert(data);
+
+				mElementCount = mData.size();
 				return true;
 			}
 			else
@@ -346,6 +344,8 @@ class LLOctreeNode : public LLTreeNode<T>
 				{
 					mData.insert(data);
 					BaseType::insert(data);
+
+					mElementCount = mData.size();
 					return true;
 				}
 
@@ -399,6 +399,7 @@ class LLOctreeNode : public LLTreeNode<T>
 		if (mData.find(data) != mData.end())
 		{	//we have data
 			mData.erase(data);
+			mElementCount = mData.size();
 			notifyRemoval(data);
 			checkAlive();
 			return true;
@@ -436,6 +437,7 @@ class LLOctreeNode : public LLTreeNode<T>
         if (mData.find(data) != mData.end())
 		{
 			mData.erase(data);
+			mElementCount = mData.size();
 			notifyRemoval(data);
 			llwarns << "FOUND!" << llendl;
 			checkAlive();
@@ -452,7 +454,7 @@ class LLOctreeNode : public LLTreeNode<T>
 	void clearChildren()
 	{
 		mChild.clear();
-
+		mChildCount = 0;
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 	}
@@ -512,9 +514,10 @@ class LLOctreeNode : public LLTreeNode<T>
 		}
 #endif
 
-		mChildMap[child->getOctant()] = (U8) mChild.size();
+		mChildMap[child->getOctant()] = mChildCount;
 
 		mChild.push_back(child);
+		++mChildCount;
 		child->setParent(this);
 
 		if (!silent)
@@ -534,21 +537,20 @@ class LLOctreeNode : public LLTreeNode<T>
 			oct_listener* listener = getOctListener(i);
 			listener->handleChildRemoval(this, getChild(index));
 		}
-
 		
-
 		if (destroy)
 		{
 			mChild[index]->destroy();
 			delete mChild[index];
 		}
 		mChild.erase(mChild.begin() + index);
+		--mChildCount;
 
 		//rebuild child map
 		U32* foo = (U32*) mChildMap;
 		foo[0] = foo[1] = 0xFFFFFFFF;
 
-		for (U32 i = 0; i < mChild.size(); ++i)
+		for (U32 i = 0; i < mChildCount; ++i)
 		{
 			mChildMap[mChild[i]->getOctant()] = i;
 		}
@@ -601,8 +603,10 @@ class LLOctreeNode : public LLTreeNode<T>
 
 	child_list mChild;
 	U8 mChildMap[8];
+	U32 mChildCount;
 
 	element_list mData;
+	U32 mElementCount;
 		
 }; 
 
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index da0fa329633ebc4b3a1bf2825ec7c2b1902ab05a..0c6cf1dfae107e0cb32cb347bd4a2d60742d1c76 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -4617,18 +4617,83 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en
 				genBinormals(i);
 			}
 
-			if (!face.mOctree)
-			{
-				face.createOctree();
-			}
-			
-			//LLVector4a* p = (LLVector4a*) face.mPositions;
+			if (isUnique())
+			{ //don't bother with an octree for flexi volumes
+				U32 tri_count = face.mNumIndices/3;
+
+				for (U32 j = 0; j < tri_count; ++j)
+				{
+					U16 idx0 = face.mIndices[j*3+0];
+					U16 idx1 = face.mIndices[j*3+1];
+					U16 idx2 = face.mIndices[j*3+2];
 
-			LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
-			intersect.traverse(face.mOctree);
-			if (intersect.mHitFace)
+					const LLVector4a& v0 = face.mPositions[idx0];
+					const LLVector4a& v1 = face.mPositions[idx1];
+					const LLVector4a& v2 = face.mPositions[idx2];
+				
+					F32 a,b,t;
+
+					if (LLTriangleRayIntersect(v0, v1, v2,
+							start, dir, a, b, t))
+					{
+						if ((t >= 0.f) &&      // if hit is after start
+							(t <= 1.f) &&      // and before end
+							(t < closest_t))   // and this hit is closer
+						{
+							closest_t = t;
+							hit_face = i;
+
+							if (intersection != NULL)
+							{
+								LLVector4a intersect = dir;
+								intersect.mul(closest_t);
+								intersect.add(start);
+								intersection->set(intersect.getF32ptr());
+							}
+
+
+							if (tex_coord != NULL)
+							{
+								LLVector2* tc = (LLVector2*) face.mTexCoords;
+								*tex_coord = ((1.f - a - b)  * tc[idx0] +
+									a              * tc[idx1] +
+									b              * tc[idx2]);
+
+							}
+
+							if (normal!= NULL)
+							{
+								LLVector4* norm = (LLVector4*) face.mNormals;
+
+								*normal		= ((1.f - a - b)  * LLVector3(norm[idx0]) + 
+									a              * LLVector3(norm[idx1]) +
+									b              * LLVector3(norm[idx2]));
+							}
+
+							if (bi_normal != NULL)
+							{
+								LLVector4* binormal = (LLVector4*) face.mBinormals;
+								*bi_normal = ((1.f - a - b)  * LLVector3(binormal[idx0]) + 
+										a              * LLVector3(binormal[idx1]) +
+										b              * LLVector3(binormal[idx2]));
+							}
+						}
+					}
+				}
+			}
+			else
 			{
-				hit_face = i;
+				if (!face.mOctree)
+				{
+					face.createOctree();
+				}
+			
+				LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
+				intersect.traverse(face.mOctree);
+				if (intersect.mHitFace)
+				{
+					hit_face = i;
+				}
 			}
 		}		
 	}
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index f56963076687524bbce9e6f82d8f8eb75c9fd6c4..e17380fdf5e14b542540398468eebd767d5dc576 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -675,6 +675,10 @@ bool LLCurl::Multi::doPerform()
 				call_count++)
 		{
 			LLMutexLock lock(mMutexp) ;
+
+			//WARNING: curl_multi_perform will block for many hundreds of milliseconds
+			// NEVER call this from the main thread, and NEVER allow the main thread to 
+			// wait on a mutex held by this thread while curl_multi_perform is executing
 			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
 			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
 			{
@@ -873,7 +877,7 @@ LLCurlThread::~LLCurlThread()
 	LLCurl::Multi::sMultiInitMutexp = NULL ;
 }
 
-S32 LLCurlThread::update(U32 max_time_ms)
+S32 LLCurlThread::update(F32 max_time_ms)
 {	
 	return LLQueuedThread::update(max_time_ms);
 }
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 705cdcbbcc5c0cfb722fb01c7c6c5c1db57dd194..9c2c215c7a6478ffd5163162c020db8c522ae190 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -349,7 +349,7 @@ class LLCurlThread : public LLQueuedThread
 	LLCurlThread(bool threaded = true) ;
 	virtual ~LLCurlThread() ;
 
-	S32 update(U32 max_time_ms);
+	S32 update(F32 max_time_ms);
 
 	void addMulti(LLCurl::Multi* multi) ;
 	void killMulti(LLCurl::Multi* multi) ;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index a3a2b2b1b8c2db8d8b10863eff3eb6718885a7f0..261e57e79e4d4d94b539b32bb5c37a5e3d3818c1 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -64,7 +64,7 @@ class LLURLRequestDetail
 	~LLURLRequestDetail();
 	std::string mURL;
 	LLCurlEasyRequest* mCurlRequest;
-	LLBufferArray* mResponseBuffer;
+	LLIOPipe::buffer_ptr_t mResponseBuffer;
 	LLChannelDescriptors mChannels;
 	U8* mLastRead;
 	U32 mBodyLimit;
@@ -75,7 +75,6 @@ class LLURLRequestDetail
 
 LLURLRequestDetail::LLURLRequestDetail() :
 	mCurlRequest(NULL),
-	mResponseBuffer(NULL),
 	mLastRead(NULL),
 	mBodyLimit(0),
 	mByteAccumulator(0),
@@ -90,7 +89,6 @@ LLURLRequestDetail::~LLURLRequestDetail()
 {
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	delete mCurlRequest;
-	mResponseBuffer = NULL;
 	mLastRead = NULL;
 }
 
@@ -326,7 +324,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 
 		// *FIX: bit of a hack, but it should work. The configure and
 		// callback method expect this information to be ready.
-		mDetail->mResponseBuffer = buffer.get();
+		mDetail->mResponseBuffer = buffer;
 		mDetail->mChannels = channels;
 		if(!configure())
 		{
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 5a6f3d8292c2daf5db8599e28590faa52ca8becb..6b2852670a42c56c4bfae5eaf2c84229c2082191 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -66,7 +66,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 LLShaderFeatures::LLShaderFeatures()
 : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
 hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
+hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
 hasAlphaMask(false)
 {
 }
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 2a6c050eac9bbe18dd6f22d4fc48a746e4fe9bf9..00b4b0dbd4097c07e56ffab9ec014ad7dae000fb 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -36,6 +36,7 @@ class LLShaderFeatures
 	bool calculatesLighting;
 	bool calculatesAtmospherics;
 	bool hasLighting; // implies no transport (it's possible to have neither though)
+	bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
 	bool isShiny;
 	bool isFullbright; // implies no lighting
 	bool isSpecular;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 1aa12614ea1415d257f94b6fcda1a53616b8c0f5..ef2a7395dad3d1d9545176485133180ed0bfd544 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -457,7 +457,8 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
 	gGL.flush();
 	if (!source.mFBO || !mFBO)
 	{
-		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+		llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+		return;
 	}
 
 	
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index ac9dc9544d5790ab595816cffeca2e64ffdfa52d..1a03aeebb7d218fe8f90ec213a3faa0bdcb0089b 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -107,10 +107,13 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				return FALSE;
 			}
-			
-			if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+		
+			if (!features->isAlphaLighting)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+				{
+					return FALSE;
+				}
 			}
 			
 			if (!shader->attachObject("lighting/lightSpecularV.glsl"))
@@ -125,9 +128,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 				return FALSE;
 			}
 			
-			if (!shader->attachObject("lighting/sumLightsV.glsl"))
+			if (!features->isAlphaLighting)
 			{
-				return FALSE;
+				if (!shader->attachObject("lighting/sumLightsV.glsl"))
+				{
+					return FALSE;
+				}
 			}
 			
 			if (!shader->attachObject("lighting/lightV.glsl"))
@@ -296,7 +302,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 				}
 				shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
 			}
-		}		
+		}
 	}
 	
 	// NOTE order of shader object attaching is VERY IMPORTANT!!!
@@ -579,7 +585,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		text[count++] = strdup("#define ATTRIBUTE attribute\n");
 		text[count++] = strdup("#define VARYING varying\n");
 	}
-	else if (version < 3.f)
+	else if (version < 3.3f)
 	{
 		//set version to 1.20
 		text[count++] = strdup("#version 120\n");
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index b09441f7eb92e27222fa46f7647f7e42c2ff339f..0170ad4b55f939eb4e347cb85f75b1df4cb76ecd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -30,7 +30,6 @@ ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getObjectSkinnedTransform();
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -38,8 +37,6 @@ float calcDirectionalLight(vec3 n, vec3 l);
 
 vec3 atmosAmbient(vec3 light);
 vec3 atmosAffectDirectionalLight(float lightIntensity);
-vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
 
 VARYING vec3 vary_position;
 VARYING vec3 vary_ambient;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index 88fe3c3dee3132665ddb2d82beaeb0d13b0a8e56..e612efba61ffd5a570d1218b2099886a18ca7b29 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -57,7 +57,7 @@ float getDepth(vec2 pos_screen)
 
 float calc_cof(float depth)
 {
-	float sc = abs(depth-focal_distance)/-depth*blur_constant;
+	float sc = (depth-focal_distance)/-depth*blur_constant;
 		
 	sc /= magnification;
 	
@@ -79,9 +79,10 @@ void main()
 	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
 	
 	float sc = calc_cof(depth);
-	sc = min(abs(sc), max_cof);
+	sc = min(sc, max_cof);
+	sc = max(sc, -max_cof);
 	
 	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
 	gl_FragColor.rgb = diff.rgb + bloom.rgb;
-	gl_FragColor.a = sc/max_cof;
+	gl_FragColor.a = sc/max_cof*0.5+0.5;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
index 21453aefaa995e409fa02002e24abd7a5af68b75..01e3505359f98ccb6c11bb76fd91d61392b7bdf6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
@@ -48,7 +48,7 @@ void main()
 	
 	vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy);
 
-	float a = min(diff.a * max_cof*res_scale*res_scale, 1.0);
+	float a = min(abs(diff.a*2.0-1.0) * max_cof*res_scale*res_scale, 1.0);
 
 	if (a > 0.25 && a < 0.75)
 	{ //help out the transition a bit
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 4603d99c5e5bf15de9537e8eca3def917ce45229..18d451bf878068e1a74c7d77f9f3767148c4c6bd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -42,7 +42,7 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
 {
 	vec4 s = texture2DRect(diffuseRect, tc);
 
-	float sc = s.a*max_cof;
+	float sc = abs(s.a*2.0-1.0)*max_cof;
 
 	if (sc > min_sc) //sampled pixel is more "out of focus" than current sample radius
 	{
@@ -57,6 +57,20 @@ void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc)
 	}
 }
 
+void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc)
+{
+	vec4 s = texture2DRect(diffuseRect, tc);
+
+	float wg = 0.25;
+
+	// de-weight dull areas to make highlights 'pop'
+	wg += s.r+s.g+s.b;
+
+	diff += wg*s;
+		
+	w += wg;
+}
+
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
@@ -66,12 +80,30 @@ void main()
 	{ 
 		float w = 1.0;
 		
-		float sc = diff.a*max_cof;
-				
+		float sc = (diff.a*2.0-1.0)*max_cof;
+			
 		float PI = 3.14159265358979323846264;
 
 		// sample quite uniformly spaced points within a circle, for a circular 'bokeh'		
+		if (sc > 0.5)
+		{
+			while (sc > 0.5)
+			{
+				int its = int(max(1.0,(sc*3.7)));
+				for (int i=0; i<its; ++i)
+				{
+					float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
+					float samp_x = sc*sin(ang);
+					float samp_y = sc*cos(ang);
+					// you could test sample coords against an interesting non-circular aperture shape here, if desired.
+					dofSampleNear(diff, w, sc, vary_fragcoord.xy + vec2(samp_x,samp_y));
+				}
+				sc -= 1.0;
+			}
+		}
+		else if (sc < -0.5)
 		{
+			sc = abs(sc);
 			while (sc > 0.5)
 			{
 				int its = int(max(1.0,(sc*3.7)));
@@ -86,7 +118,7 @@ void main()
 				sc -= 1.0;
 			}
 		}
-		
+
 		diff /= w;
 	}
 		
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0861fe85a84475ad45f3a32e6baa7a97c5d07e76..40136adbc9fa6c243a8c77fc3b5c0e7400d6eaa8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1346,17 +1346,19 @@ bool LLAppViewer::mainLoop()
 				{
 					S32 work_pending = 0;
 					S32 io_pending = 0;
+					F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
+
 					{
 						LLFastTimer ftm(FTM_TEXTURE_CACHE);
- 						work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+ 						work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
 					}
 					{
 						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+	 					work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
 					}
 					{
 						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+	 					work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
 					}
 
 					{
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
old mode 100644
new mode 100755
index 42e7decec188e4cbf76e94d4ef6771ebd11fc045..b539ac38ed82eedf7dc83e2cd98af50e86a4d317
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -75,6 +75,9 @@ void LLAvatarIconIDCache::load	()
 		LLUUID icon_id;
 		LLDate date;
 
+		if (line.length()<=uuid_len*2)
+			continue; // short line, bail out to prevent substr calls throwing exception.
+
 		std::string avatar_id_str = line.substr(0,uuid_len);
 		std::string icon_id_str = line.substr(uuid_len,uuid_len);
 		
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index b696b90d847b418c8ca153ed518b21b8534619d5..b58efe62ab6dc4f2af0b4740391ebc73ca6cf5dd 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -1036,51 +1036,48 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
 	llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
 
 	LLViewerTexture* bump = NULL;
-	const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
-	if( src_image->getMaxVirtualSize() > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
-	{
-		bump_image_map_t* entries_list = NULL;
-		void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
+	
+	bump_image_map_t* entries_list = NULL;
+	void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
 
-		switch( bump_code )
-		{
-		case BE_BRIGHTNESS:
-			entries_list = &mBrightnessEntries;
-			callback_func = LLBumpImageList::onSourceBrightnessLoaded;
-			break;
-		case BE_DARKNESS:
-			entries_list = &mDarknessEntries;
-			callback_func = LLBumpImageList::onSourceDarknessLoaded;
-			break;
-		default:
-			llassert(0);
-			return NULL;
-		}
+	switch( bump_code )
+	{
+	case BE_BRIGHTNESS:
+		entries_list = &mBrightnessEntries;
+		callback_func = LLBumpImageList::onSourceBrightnessLoaded;
+		break;
+	case BE_DARKNESS:
+		entries_list = &mDarknessEntries;
+		callback_func = LLBumpImageList::onSourceDarknessLoaded;
+		break;
+	default:
+		llassert(0);
+		return NULL;
+	}
 
-		bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
-		if (iter != entries_list->end() && iter->second.notNull())
-		{
-			bump = iter->second;
-		}
-		else
-		{
-			LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
-			raw->clear(0x77, 0x77, 0xFF, 0xFF);
+	bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
+	if (iter != entries_list->end() && iter->second.notNull())
+	{
+		bump = iter->second;
+	}
+	else
+	{
+		LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
+		raw->clear(0x77, 0x77, 0xFF, 0xFF);
 
-			(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
-			bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
-		}
+		(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
+		bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
+	}
 
-		if (!src_image->hasCallbacks())
-		{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
-			if (src_image->getWidth() != bump->getWidth() ||
-				src_image->getHeight() != bump->getHeight())// ||
-				//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
-			{
-				src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
-				src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
-				src_image->forceToSaveRawImage(0) ;
-			}
+	if (!src_image->hasCallbacks())
+	{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
+		if (src_image->getWidth() != bump->getWidth() ||
+			src_image->getHeight() != bump->getHeight())// ||
+			//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
+		{
+			src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
+			src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
+			src_image->forceToSaveRawImage(0) ;
 		}
 	}
 
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 3e16ccf3dacbf5a9f67c4e31b586af7896e0f4a7..900f126049cdd8011fa086904e50cff26b46181b 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -28,6 +28,10 @@
 
 #include "llspatialpartition.h"
 
+#include "llappviewer.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "llimageworker.h"
 #include "llviewerwindow.h"
 #include "llviewerobjectlist.h"
 #include "llvovolume.h"
@@ -1221,6 +1225,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
 	for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
 	{
 		mOcclusionQuery[i] = 0;
+		mOcclusionIssued[i] = 0;
 		mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
 		mVisible[i] = 0;
 	}
@@ -1543,6 +1548,8 @@ BOOL LLSpatialGroup::rebound()
 }
 
 static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
+static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait");
+
 void LLSpatialGroup::checkOcclusion()
 {
 	if (LLPipeline::sUseOcclusion > 1)
@@ -1560,6 +1567,22 @@ void LLSpatialGroup::checkOcclusion()
 			if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
 			{
 				glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+
+				if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)
+				{ //query was issued last frame, wait until it's available
+					S32 max_loop = 1024;
+					LLFastTimer t(FTM_OCCLUSION_WAIT);
+					while (!available && max_loop-- > 0)
+					{
+						F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
+						//do some usefu work while we wait
+						LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
+						LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
+						LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
+						
+						glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+					}
+				}
 			}
 			else
 			{
@@ -1679,6 +1702,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
 					{
 						LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
 						
+						//store which frame this query was issued on
+						mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount;
+
 						{
 							LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY);
 							glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);					
@@ -3749,11 +3775,7 @@ void renderRaycast(LLDrawable* drawablep)
 				for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
 				{
 					const LLVolumeFace& face = volume->getVolumeFace(i);
-					if (!face.mOctree)
-					{
-						((LLVolumeFace*) &face)->createOctree(); 
-					}
-
+					
 					gGL.pushMatrix();
 					gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);					
 					gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix);
@@ -3776,9 +3798,6 @@ void renderRaycast(LLDrawable* drawablep)
 					LLVector4a dir;
 					dir.setSub(enda, starta);
 
-					F32 t = 1.f;
-
-					LLRenderOctreeRaycast render(starta, dir, &t);
 					gGL.flush();
 					glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);				
 
@@ -3790,8 +3809,21 @@ void renderRaycast(LLDrawable* drawablep)
 						gGL.syncMatrices();
 						glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
 					}
-						
-					render.traverse(face.mOctree);
+					
+					if (!volume->isUnique())
+					{
+						F32 t = 1.f;
+
+						if (!face.mOctree)
+						{
+							((LLVolumeFace*) &face)->createOctree(); 
+						}
+
+						LLRenderOctreeRaycast render(starta, dir, &t);
+					
+						render.traverse(face.mOctree);
+					}
+
 					gGL.popMatrix();		
 					glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 				}
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index f0c8a372ee3224c8f2b11f5ba99b8e5a05bb72b1..899547ae4d29a858cffa47b516b2e464462574d7 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -396,6 +396,8 @@ class LLSpatialGroup : public LLOctreeListener<LLDrawable>
 
 	U32 mState;
 	U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
+	U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS];
+
 	S32 mLODHash;
 	static S32 sLODSeed;
 
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e7a176f4f9fffbdc1b62fec273b5f475015f879d..8632890bbbdc7ad0c2aaac46fd38f0c888d566e0 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -760,7 +760,7 @@ LLTextureCache::~LLTextureCache()
 //////////////////////////////////////////////////////////////////////////////
 
 //virtual
-S32 LLTextureCache::update(U32 max_time_ms)
+S32 LLTextureCache::update(F32 max_time_ms)
 {
 	static LLFrameTimer timer ;
 	static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds.
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 64e3a2658c38565f1b8f32253fdb50621ed90773..dd0cc9b4bd6147b519ab416ed3180508b22a7c95 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -101,7 +101,7 @@ class LLTextureCache : public LLWorkerThread
 	LLTextureCache(bool threaded);
 	~LLTextureCache();
 
-	/*virtual*/ S32 update(U32 max_time_ms);	
+	/*virtual*/ S32 update(F32 max_time_ms);	
 	
 	void purgeCache(ELLPath location);
 	void setReadOnly(BOOL read_only) ;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 56dfb61c4f8b2ae13ece3a423ebb0f870a0d9e5d..f18aa8b4e61b05cefaf821af67165f368855ec08 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2204,7 +2204,7 @@ void LLTextureFetch::commonUpdate()
 
 // MAIN THREAD
 //virtual
-S32 LLTextureFetch::update(U32 max_time_ms)
+S32 LLTextureFetch::update(F32 max_time_ms)
 {
 	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS");
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index d101da1f4be1697e6221825a3c6cd72d8a7ca150..35df7d816f20b91e28b319c40c9767e1a428c7b6 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -55,7 +55,7 @@ class LLTextureFetch : public LLWorkerThread
 
 	class TFRequest;
 	
-	/*virtual*/ S32 update(U32 max_time_ms);	
+	/*virtual*/ S32 update(F32 max_time_ms);	
 	void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down.
 	void shutDownImageDecodeThread() ;  //called in the main thread after the ImageDecodeThread shuts down.
 
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index bddc07b395cf676525f34be9e33d698c18139f84..5de363e03ccf373b87c091cd0b2f69858993c25c 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -1103,11 +1103,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
 		gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
-		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1235,6 +1236,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1398,6 +1400,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index f4bbc2b067237e5f808763db1bacbddbc72e3b82..61236edc86e0e46ed4ef4c7ca2ebc0484c760a32 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -417,11 +417,24 @@ const S32 min_non_tex_system_mem = (128<<20); // 128 MB
 F32 texmem_lower_bound_scale = 0.85f;
 F32 texmem_middle_bound_scale = 0.925f;
 
+static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check");
+
 //static 
 bool LLViewerTexture::isMemoryForTextureLow()
 {
-	const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
-	const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB
+	const F32 WAIT_TIME = 1.0f ; //second
+	static LLFrameTimer timer ;
+
+	if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second.
+	{
+		return false;
+	}
+	timer.reset() ;
+
+	LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
+
+	const S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
+	const S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB	
 
 	bool low_mem = false ;
 	if (gGLManager.mHasATIMemInfo)
@@ -433,6 +446,15 @@ bool LLViewerTexture::isMemoryForTextureLow()
 		{
 			low_mem = true ;
 		}
+
+		if(!low_mem) //check main memory, only works for windows.
+		{
+			LLMemory::updateMemoryInfo() ;
+			if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
+			{
+				low_mem = true ;
+			}
+		}
 	}
 #if 0  //ignore nVidia cards
 	else if (gGLManager.mHasNVXMemInfo)
@@ -445,20 +467,14 @@ bool LLViewerTexture::isMemoryForTextureLow()
 			low_mem = true ;
 		}
 	}
-#endif
-
-	if(!low_mem) //check main memory, only works for windows.
-	{
-		LLMemory::updateMemoryInfo() ;
-		if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
-		{
-			low_mem = true ;
-		}
-	}
+#endif	
 
 	return low_mem ;
 }
 
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_MEDIA("Media");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_TEST("Test");
+
 //static
 void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
 {
@@ -467,9 +483,14 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
 	LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
 	if (tester)
 	{
+		LLFastTimer t(FTM_TEXTURE_UPDATE_TEST);
 		tester->update() ;
 	}
-	LLViewerMediaTexture::updateClass() ;
+
+	{
+		LLFastTimer t(FTM_TEXTURE_UPDATE_MEDIA);
+		LLViewerMediaTexture::updateClass() ;
+	}
 
 	sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
 	sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
@@ -3142,8 +3163,13 @@ void LLViewerLODTexture::processTextureStats()
 		S32 current_discard = getDiscardLevel();
 		if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0)
 		{
+			if(desired_discard_bias_max <= sDesiredDiscardBias && !mForceToSaveRawImage)
+			{
+				//needs to release texture memory urgently
+				scaleDown() ;
+			}
 			// Limit the amount of GL memory bound each frame
-			if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
+			else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
 				(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
 			{
 				scaleDown() ;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index cddf7dcfea9d1daf7c436541e35998b98104ed82..089f45ca899ae58eea2c7f36a0b4f81bd8d351ed 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -534,6 +534,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 	S32 count = mImageList.erase(image) ;
 	if(count != 1) 
 	{
+		llinfos << image->getID() << llendl ;
 		llerrs << "Error happens when remove image from mImageList: " << count << llendl ;
 	}
       
@@ -919,6 +920,8 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
 		image_list.push_back(imagep);
 		imagep->setInImageList(FALSE) ;
 	}
+
+	llassert_always(image_list.size() == mImageList.size()) ;
 	mImageList.clear();
 	for (std::vector<LLPointer<LLViewerFetchedTexture> >::iterator iter = image_list.begin();
 		 iter != image_list.end(); ++iter)
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 657cdc0e07b295a16d475ffe0401513c93e98e0c..8449e74fb6e0d96ee53f6482a314ec83b6859e73 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6333,17 +6333,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 	}
 
-	U32 res_mod = RenderResolutionDivisor;
-
 	LLVector2 tc1(0,0);
 	LLVector2 tc2((F32) mScreen.getWidth()*2,
 				  (F32) mScreen.getHeight()*2);
 
-	if (res_mod > 1)
-	{
-		tc2 /= (F32) res_mod;
-	}
-
 	LLFastTimer ftm(FTM_RENDER_BLOOM);
 	gGL.color4f(1,1,1,1);
 	LLGLDepthTest depth(GL_FALSE);
@@ -6807,7 +6800,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 				mFXAABuffer.bindTexture(0, channel);
 				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 			}
-						
+			
+			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+			gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+			gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+			gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+			glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
 			F32 scale_x = (F32) width/mFXAABuffer.getWidth();
 			F32 scale_y = (F32) height/mFXAABuffer.getHeight();
 			shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
@@ -6827,11 +6826,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 	}
 	else
 	{
-		if (res_mod > 1)
-		{
-			tc2 /= (F32) res_mod;
-		}
-
 		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
 		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
 		buff->allocateBuffer(3,0,TRUE);
@@ -7458,8 +7452,7 @@ void LLPipeline::renderDeferredLighting()
 					F32 s = volume->getLightRadius()*1.5f;
 
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					if (col.magVecSquared() < 0.001f)
 					{
 						continue;
@@ -7572,8 +7565,7 @@ void LLPipeline::renderDeferredLighting()
 					setupSpotLight(gDeferredSpotLightProgram, drawablep);
 					
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					//vertex positions are encoded so the 3 bits of their vertex index 
 					//correspond to their axis facing, with bit position 3,2,1 matching
 					//axis facing x,y,z, bit set meaning positive facing, bit clear 
@@ -7682,8 +7674,7 @@ void LLPipeline::renderDeferredLighting()
 					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
 
 					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
+					
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
 					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);