diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index bd594b06cfd5094cd28aa3b1ec56ee59f755a954..675eda2fc580a19be813e0f09c69d492f12ab14e 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -228,6 +228,14 @@ void LLFastTimer::DeclareTimer::updateCachedPointers()
 		// update cached pointer
 		it->mFrameState = &it->mTimer.getFrameState();
 	}
+
+	// also update frame states of timers on stack
+	LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
+	while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)	
+	{
+		cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
+		cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
+	}
 }
 
 //static
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index d9400fb5b325f1cbe05f57fb477def27eab36b86..4063cc730b49e5b470c6f534f19dc49b4e015218 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -323,7 +323,8 @@ LLMutex::LLMutex(apr_pool_t *poolp) :
 LLMutex::~LLMutex()
 {
 #if MUTEX_DEBUG
-	llassert_always(!isLocked()); // better not be locked!
+	//bad assertion, the subclass LLSignal might be "locked", and that's OK
+	//llassert_always(!isLocked()); // better not be locked!
 #endif
 	apr_thread_mutex_destroy(mAPRMutexp);
 	mAPRMutexp = NULL;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7c8b7e3584b6818309a3c5936dc768a3cdb43278..0735842dcd2e625eef829b73e580d70cec4d2128 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -579,11 +579,18 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 
 ////////////////////////////////////////////////////////////////////////////
 
-class LLCurl::Multi
+class LLCurl::Multi : public LLThread
 {
 	LOG_CLASS(Multi);
 public:
-	
+
+	typedef enum
+	{
+		PERFORM_STATE_READY=0,
+		PERFORM_STATE_PERFORMING=1,
+		PERFORM_STATE_COMPLETED=2
+	} ePerformState;
+
 	Multi();
 	~Multi();
 
@@ -593,13 +600,20 @@ class LLCurl::Multi
 	void removeEasy(Easy* easy);
 
 	S32 process();
-	S32 perform();
+	void perform();
 	
+	virtual void run();
+
 	CURLMsg* info_read(S32* msgs_in_queue);
 
 	S32 mQueued;
 	S32 mErrorCount;
 	
+	S32 mPerformState;
+
+	LLCondition* mSignal;
+	bool mQuitting;
+
 private:
 	void easyFree(Easy*);
 	
@@ -614,9 +628,14 @@ class LLCurl::Multi
 };
 
 LLCurl::Multi::Multi()
-	: mQueued(0),
-	  mErrorCount(0)
+	: LLThread("Curl Multi"),
+	  mQueued(0),
+	  mErrorCount(0),
+	  mPerformState(PERFORM_STATE_READY)
 {
+	mQuitting = false;
+	mSignal = new LLCondition(NULL);
+
 	mCurlMultiHandle = curl_multi_init();
 	if (!mCurlMultiHandle)
 	{
@@ -630,6 +649,11 @@ LLCurl::Multi::Multi()
 
 LLCurl::Multi::~Multi()
 {
+	llassert(isStopped());
+
+	delete mSignal;
+	mSignal = NULL;
+
 	// Clean up active
 	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
 		iter != mEasyActiveList.end(); ++iter)
@@ -655,30 +679,50 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
 	return curlmsg;
 }
 
+void LLCurl::Multi::perform()
+{
+	if (mPerformState == PERFORM_STATE_READY)
+	{
+		mSignal->signal();
+	}
+}
 
-S32 LLCurl::Multi::perform()
+void LLCurl::Multi::run()
 {
-	S32 q = 0;
-	for (S32 call_count = 0;
-		 call_count < MULTI_PERFORM_CALL_REPEAT;
-		 call_count += 1)
+	while (!mQuitting)
 	{
-		CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
-		if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+		mSignal->wait();
+		mPerformState = PERFORM_STATE_PERFORMING;
+		if (!mQuitting)
 		{
-			check_curl_multi_code(code);
-			break;
-		}
+			S32 q = 0;
+			for (S32 call_count = 0;
+				 call_count < MULTI_PERFORM_CALL_REPEAT;
+				 call_count += 1)
+			{
+				CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
+				if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
+				{
+					check_curl_multi_code(code);
+					break;
+				}
 	
+			}
+			mQueued = q;
+			mPerformState = PERFORM_STATE_COMPLETED;
+		}
 	}
-	mQueued = q;
-	return q;
 }
 
 S32 LLCurl::Multi::process()
 {
 	perform();
-	
+
+	if (mPerformState != PERFORM_STATE_COMPLETED)
+	{
+		return 0;
+	}
+
 	CURLMsg* msg;
 	int msgs_in_queue;
 
@@ -709,6 +753,8 @@ S32 LLCurl::Multi::process()
 			}
 		}
 	}
+
+	mPerformState = PERFORM_STATE_READY;
 	return processed;
 }
 
@@ -787,6 +833,18 @@ LLCurlRequest::LLCurlRequest() :
 LLCurlRequest::~LLCurlRequest()
 {
 	llassert_always(mThreadID == LLThread::currentID());
+
+	//stop all Multi handle background threads
+	for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
+	{
+		LLCurl::Multi* multi = *iter;
+		multi->mQuitting = true;
+		while (!multi->isStopped())
+		{
+			multi->mSignal->signal();
+			apr_sleep(1000);
+		}
+	}
 	for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
 }
 
@@ -794,6 +852,7 @@ void LLCurlRequest::addMulti()
 {
 	llassert_always(mThreadID == LLThread::currentID());
 	LLCurl::Multi* multi = new LLCurl::Multi();
+	multi->start();
 	mMultiSet.insert(multi);
 	mActiveMulti = multi;
 	mActiveRequestCount = 0;
@@ -923,6 +982,13 @@ S32 LLCurlRequest::process()
 		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
 		{
 			mMultiSet.erase(curiter);
+			multi->mQuitting = true;
+			while (!multi->isStopped())
+			{
+				multi->mSignal->signal();
+				apr_sleep(1000);
+			}
+
 			delete multi;
 		}
 	}
@@ -953,6 +1019,7 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 	  mResultReturned(false)
 {
 	mMulti = new LLCurl::Multi();
+	mMulti->start();
 	mEasy = mMulti->allocEasy();
 	if (mEasy)
 	{
@@ -963,6 +1030,12 @@ LLCurlEasyRequest::LLCurlEasyRequest()
 
 LLCurlEasyRequest::~LLCurlEasyRequest()
 {
+	mMulti->mQuitting = true;
+	while (!mMulti->isStopped())
+	{
+		mMulti->mSignal->signal();
+		apr_sleep(1000);
+	}
 	delete mMulti;
 }
 	
@@ -1059,14 +1132,20 @@ void LLCurlEasyRequest::requestComplete()
 	}
 }
 
-S32 LLCurlEasyRequest::perform()
+void LLCurlEasyRequest::perform()
 {
-	return mMulti->perform();
+	mMulti->perform();
 }
 
 // Usage: Call getRestult until it returns false (no more messages)
 bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
 {
+	if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED)
+	{ //we're busy, try again later
+		return false;
+	}
+	mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY;
+
 	if (!mEasy)
 	{
 		// Special case - we failed to initialize a curl_easy (can happen if too many open files)
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 4ce3fa10780b4c7021432280acd548531e9fc1f9..2f951d6ab8eb0ebd905ac8438e13805c899cd348 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -236,7 +236,7 @@ class LLCurlEasyRequest
 	void slist_append(const char* str);
 	void sendRequest(const std::string& url);
 	void requestComplete();
-	S32 perform();
+	void perform();
 	bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
 	std::string getErrorString();
 
diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp
index 812ef7c151e680ed32dada0949a1269053456b72..e0ca056a5f698afb11ad860f0be48c2e291cc0a4 100644
--- a/indra/llmessage/llfiltersd2xmlrpc.cpp
+++ b/indra/llmessage/llfiltersd2xmlrpc.cpp
@@ -308,6 +308,7 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse()
 }
 
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response");
 // virtual
 LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
 	const LLChannelDescriptors& channels,
@@ -316,6 +317,8 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SD2XMLRPC_RESPONSE);
+
 	PUMP_DEBUG;
 	// This pipe does not work if it does not have everyting. This
 	// could be addressed by making a stream parser for llsd which
@@ -382,6 +385,8 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
 {
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request");
+
 // virtual
 LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
 	const LLChannelDescriptors& channels,
@@ -390,6 +395,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SD2XMLRPC_REQUEST);
 	// This pipe does not work if it does not have everyting. This
 	// could be addressed by making a stream parser for llsd which
 	// handled partial information.
@@ -586,6 +592,8 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD()
 {
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response");
+
 LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
 	const LLChannelDescriptors& channels,
 	buffer_ptr_t& buffer,
@@ -593,6 +601,8 @@ LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_RESPONSE);
+
 	PUMP_DEBUG;
 	if(!eos) return STATUS_BREAK;
 	if(!buffer) return STATUS_ERROR;
@@ -668,6 +678,7 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD()
 {
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request");
 LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
 	const LLChannelDescriptors& channels,
 	buffer_ptr_t& buffer,
@@ -675,6 +686,7 @@ LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST);
 	PUMP_DEBUG;
 	if(!eos) return STATUS_BREAK;
 	if(!buffer) return STATUS_ERROR;
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 3b18a9177cf055e244953b36373016eb05619b6c..73e8a690851800ca5bf7a69314e15ee446bc316e 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -140,6 +140,7 @@ class LLHTTPPipe : public LLIOPipe
 	LLSD mHeaders;
 };
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe");
 LLIOPipe::EStatus LLHTTPPipe::process_impl(
 	const LLChannelDescriptors& channels,
     buffer_ptr_t& buffer,
@@ -147,6 +148,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
     LLSD& context,
     LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_HTTP_PIPE);
 	PUMP_DEBUG;
     lldebugs << "LLSDHTTPServer::process_impl" << llendl;
 
@@ -428,6 +430,9 @@ class LLHTTPResponseHeader : public LLIOPipe
 /**
  * LLHTTPResponseHeader
  */
+
+static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_HEADER("HTTP Header");
+
 // virtual
 LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 	const LLChannelDescriptors& channels,
@@ -436,6 +441,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_HTTP_HEADER);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
 	if(eos)
@@ -630,6 +636,8 @@ void LLHTTPResponder::markBad(
 		<< "</body>\n</html>\n";
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_RESPONDER("HTTP Responder");
+
 // virtual
 LLIOPipe::EStatus LLHTTPResponder::process_impl(
 	const LLChannelDescriptors& channels,
@@ -638,6 +646,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_HTTP_RESPONDER);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
 	LLIOPipe::EStatus status = STATUS_OK;
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 8c752fbe301e74f2767e4203555d6cc4bc7fd868..b717e321bfe9eef182eba707001dc171837c6c03 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -301,6 +301,8 @@ LLIOSocketReader::~LLIOSocketReader()
 	//lldebugs << "Destroying LLIOSocketReader" << llendl;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_READER("Socket Reader");
+
 // virtual
 LLIOPipe::EStatus LLIOSocketReader::process_impl(
 	const LLChannelDescriptors& channels,
@@ -309,6 +311,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SOCKET_READER);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_TCP);
 	if(!mSource) return STATUS_PRECONDITION_NOT_MET;
@@ -401,6 +404,7 @@ LLIOSocketWriter::~LLIOSocketWriter()
 	//lldebugs << "Destroying LLIOSocketWriter" << llendl;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_WRITER("Socket Writer");
 // virtual
 LLIOPipe::EStatus LLIOSocketWriter::process_impl(
 	const LLChannelDescriptors& channels,
@@ -409,6 +413,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SOCKET_WRITER);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_TCP);
 	if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
@@ -555,6 +560,7 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs)
 	mResponseTimeout = timeout_secs;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SERVER_SOCKET("Server Socket");
 // virtual
 LLIOPipe::EStatus LLIOServerSocket::process_impl(
 	const LLChannelDescriptors& channels,
@@ -563,6 +569,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SERVER_SOCKET);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_TCP);
 	if(!pump)
diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp
index 2e6ee59ff2cdfb160e1c820c9a2bd75b75c0abc3..8c50fd50693a1e62ab70d57c8649465d2ebecd21 100644
--- a/indra/llmessage/llioutil.cpp
+++ b/indra/llmessage/llioutil.cpp
@@ -43,6 +43,8 @@ LLIOPipe::EStatus LLIOFlush::process_impl(
 	return STATUS_OK;
 }
 
+
+static LLFastTimer::DeclareTimer FTM_PROCESS_SLEEP("IO Sleep");
 /** 
  * @class LLIOSleep
  */
@@ -53,6 +55,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SLEEP);
 	if(mSeconds > 0.0)
 	{
 		if(pump) pump->sleepChain(mSeconds);
@@ -62,6 +65,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl(
 	return STATUS_DONE;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_ADD_CHAIN("Add Chain");
 /** 
  * @class LLIOAddChain
  */
@@ -72,6 +76,7 @@ LLIOPipe::EStatus LLIOAddChain::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_ADD_CHAIN);
 	pump->addChain(mChain, mTimeout);
 	return STATUS_DONE;
 }
diff --git a/indra/llmessage/llsdrpcclient.cpp b/indra/llmessage/llsdrpcclient.cpp
index 86fe5c79122f026244107999b7a22a2a258441b2..91fd070f0744b6ac24252ee1563cdc3d06f0e545 100644
--- a/indra/llmessage/llsdrpcclient.cpp
+++ b/indra/llmessage/llsdrpcclient.cpp
@@ -82,6 +82,8 @@ bool LLSDRPCResponse::extractResponse(const LLSD& sd)
 	return rv;
 }
 
+static LLFastTimer::DeclareTimer FTM_SDRPC_RESPONSE("SDRPC Response");
+
 // virtual
 LLIOPipe::EStatus LLSDRPCResponse::process_impl(
 	const LLChannelDescriptors& channels,
@@ -90,6 +92,7 @@ LLIOPipe::EStatus LLSDRPCResponse::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_SDRPC_RESPONSE);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
 	if(mIsError)
@@ -178,6 +181,8 @@ bool LLSDRPCClient::call(
 	return true;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_CLIENT("SDRPC Client");
+
 // virtual
 LLIOPipe::EStatus LLSDRPCClient::process_impl(
 	const LLChannelDescriptors& channels,
@@ -186,6 +191,7 @@ LLIOPipe::EStatus LLSDRPCClient::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SDRPC_CLIENT);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
 	if((STATE_NONE == mState) || (!pump))
diff --git a/indra/llmessage/llsdrpcserver.cpp b/indra/llmessage/llsdrpcserver.cpp
index f87c418fb152c5aece31c7e3c0ce73245a18ebba..9f776aca72a252220fbf4b9f659d376a88a18125 100644
--- a/indra/llmessage/llsdrpcserver.cpp
+++ b/indra/llmessage/llsdrpcserver.cpp
@@ -97,6 +97,8 @@ void LLSDRPCServer::clearLock()
 	}
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_SERVER("SDRPC Server");
+
 // virtual
 LLIOPipe::EStatus LLSDRPCServer::process_impl(
 	const LLChannelDescriptors& channels,
@@ -105,6 +107,7 @@ LLIOPipe::EStatus LLSDRPCServer::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_SDRPC_SERVER);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
 //	lldebugs << "LLSDRPCServer::process_impl" << llendl;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 28bd09fc4cb10615f60d1f224411b2249fa1770a..e8e35d00a21aa5808c6e5b35047e007751fc66f1 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -270,6 +270,8 @@ LLIOPipe::EStatus LLURLRequest::handleError(
 	return status;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request");
+
 // virtual
 LLIOPipe::EStatus LLURLRequest::process_impl(
 	const LLChannelDescriptors& channels,
@@ -278,6 +280,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_URL_REQUEST);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	//llinfos << "LLURLRequest::process_impl()" << llendl;
@@ -288,6 +291,8 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	const S32 MIN_ACCUMULATION = 100000;
 	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
 	{
+		static LLFastTimer::DeclareTimer FTM_URL_ADJUST_TIMEOUT("Adjust Timeout");
+		LLFastTimer t(FTM_URL_ADJUST_TIMEOUT);
 		 // This is a pretty sloppy calculation, but this
 		 // tries to make the gross assumption that if data
 		 // is coming in at 56kb/s, then this transfer will
@@ -335,16 +340,30 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	{
 		PUMP_DEBUG;
 		LLIOPipe::EStatus status = STATUS_BREAK;
-		mDetail->mCurlRequest->perform();
+		static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform");
+		{
+			LLFastTimer t(FTM_URL_PERFORM);
+			mDetail->mCurlRequest->perform();
+		}
+
 		while(1)
 		{
 			CURLcode result;
-			bool newmsg = mDetail->mCurlRequest->getResult(&result);
+
+			static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
+
+			bool newmsg = false;
+			{
+				LLFastTimer t(FTM_PROCESS_URL_REQUEST_GET_RESULT);
+				newmsg = mDetail->mCurlRequest->getResult(&result);
+			}
+		
 			if(!newmsg)
 			{
 				// keep processing
 				break;
 			}
+		
 
 			mState = STATE_HAVE_RESPONSE;
 			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
@@ -370,7 +389,11 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 						link.mChannels = LLBufferArray::makeChannelConsumer(
 							channels);
 						chain.push_back(link);
-						pump->respond(chain, buffer, context);
+						static LLFastTimer::DeclareTimer FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond");
+						{
+							LLFastTimer t(FTM_PROCESS_URL_PUMP_RESPOND);
+							pump->respond(chain, buffer, context);
+						}
 						mCompletionCallback = NULL;
 					}
 					break;
@@ -422,8 +445,11 @@ void LLURLRequest::initialize()
 	mResponseTransferedBytes = 0;
 }
 
+static LLFastTimer::DeclareTimer FTM_URL_REQUEST_CONFIGURE("URL Configure");
 bool LLURLRequest::configure()
 {
+	LLFastTimer t(FTM_URL_REQUEST_CONFIGURE);
+	
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	bool rv = false;
 	S32 bytes = mDetail->mResponseBuffer->countAfter(
@@ -624,6 +650,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
 	return header_len;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_URL_EXTRACTOR("URL Extractor");
 /**
  * LLContextURLExtractor
  */
@@ -635,6 +662,7 @@ LLIOPipe::EStatus LLContextURLExtractor::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_URL_EXTRACTOR);
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	// The destination host is in the context.
@@ -713,6 +741,7 @@ void LLURLRequestComplete::responseStatus(LLIOPipe::EStatus status)
 	mRequestStatus = status;
 }
 
+static LLFastTimer::DeclareTimer FTM_PROCESS_URL_COMPLETE("URL Complete");
 // virtual
 LLIOPipe::EStatus LLURLRequestComplete::process_impl(
 	const LLChannelDescriptors& channels,
@@ -721,6 +750,7 @@ LLIOPipe::EStatus LLURLRequestComplete::process_impl(
 	LLSD& context,
 	LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_PROCESS_URL_COMPLETE);
 	PUMP_DEBUG;
 	complete(channels, buffer);
 	return STATUS_OK;
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index fb22d7f1f581dbf3ea70ae301ff4a83bc8ca0fab..1b10354c22919e597b2ee67d0660cf579d6c30fb 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -259,7 +259,7 @@ void LLCubeMap::setMatrix(S32 stage)
 	
 	if (mMatrixStage < 0) return;
 	
-	if (stage > 0)
+	//if (stage > 0)
 	{
 		gGL.getTexUnit(stage)->activate();
 	}
@@ -278,17 +278,17 @@ void LLCubeMap::setMatrix(S32 stage)
 	glLoadMatrixf((F32 *)trans.mMatrix);
 	glMatrixMode(GL_MODELVIEW);
 	
-	if (stage > 0)
+	/*if (stage > 0)
 	{
 		gGL.getTexUnit(0)->activate();
-	}
+	}*/
 }
 
 void LLCubeMap::restoreMatrix()
 {
 	if (mMatrixStage < 0) return;
 
-	if (mMatrixStage > 0)
+	//if (mMatrixStage > 0)
 	{
 		gGL.getTexUnit(mMatrixStage)->activate();
 	}
@@ -296,10 +296,10 @@ void LLCubeMap::restoreMatrix()
 	glPopMatrix();
 	glMatrixMode(GL_MODELVIEW);
 	
-	if (mMatrixStage > 0)
+	/*if (mMatrixStage > 0)
 	{
 		gGL.getTexUnit(0)->activate();
-	}
+	}*/
 }
 
 void LLCubeMap::setReflection (void)
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c224ab0e9bb20a8c6aefb7517315e1c9cf1a6180..89377262091d981cf80ba0cba2a3c16b3e4d68b6 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -128,9 +128,21 @@ PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB = NULL;
 PFNGLGETBUFFERPOINTERVARBPROC		glGetBufferPointervARB = NULL;
 
 // GL_ARB_map_buffer_range
-PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
-
+PFNGLMAPBUFFERRANGEPROC			glMapBufferRange = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange = NULL;
+
+// GL_ARB_sync
+PFNGLFENCESYNCPROC				glFenceSync = NULL;
+PFNGLISSYNCPROC					glIsSync = NULL;
+PFNGLDELETESYNCPROC				glDeleteSync = NULL;
+PFNGLCLIENTWAITSYNCPROC			glClientWaitSync = NULL;
+PFNGLWAITSYNCPROC				glWaitSync = NULL;
+PFNGLGETINTEGER64VPROC			glGetInteger64v = NULL;
+PFNGLGETSYNCIVPROC				glGetSynciv = NULL;
+
+// GL_APPLE_flush_buffer_range
+PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL;
 
 // vertex object prototypes
 PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI = NULL;
@@ -334,9 +346,10 @@ LLGLManager::LLGLManager() :
 	mHasFramebufferObject(FALSE),
 	mMaxSamples(0),
 	mHasBlendFuncSeparate(FALSE),
-
+	mHasSync(FALSE),
 	mHasVertexBufferObject(FALSE),
 	mHasMapBufferRange(FALSE),
+	mHasFlushBufferRange(FALSE),
 	mHasPBuffer(FALSE),
 	mHasShaderObjects(FALSE),
 	mHasVertexShader(FALSE),
@@ -774,7 +787,9 @@ void LLGLManager::initExtensions()
 	mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
 	mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
 	mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
+	mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
 	mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
+	mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
 	mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
 	// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
 #ifdef GL_ARB_framebuffer_object
@@ -969,6 +984,16 @@ void LLGLManager::initExtensions()
 			mHasVertexBufferObject = FALSE;
 		}
 	}
+	if (mHasSync)
+	{
+		glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
+		glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync");
+		glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync");
+		glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync");
+		glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync");
+		glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v");
+		glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv");
+	}
 	if (mHasMapBufferRange)
 	{
 		glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
@@ -1354,6 +1379,8 @@ void LLGLState::checkStates(const std::string& msg)
 	glGetIntegerv(GL_BLEND_SRC, &src);
 	glGetIntegerv(GL_BLEND_DST, &dst);
 	
+	stop_glerror();
+
 	BOOL error = FALSE;
 
 	if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
@@ -1374,7 +1401,9 @@ void LLGLState::checkStates(const std::string& msg)
 	{
 		LLGLenum state = iter->first;
 		LLGLboolean cur_state = iter->second;
+		stop_glerror();
 		LLGLboolean gl_state = glIsEnabled(state);
+		stop_glerror();
 		if(cur_state != gl_state)
 		{
 			dumpStates();
@@ -1399,11 +1428,11 @@ void LLGLState::checkStates(const std::string& msg)
 
 void LLGLState::checkTextureChannels(const std::string& msg)
 {
+#if 0
 	if (!gDebugGL)
 	{
 		return;
 	}
-
 	stop_glerror();
 
 	GLint activeTexture;
@@ -1569,6 +1598,7 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 			LL_GL_ERRS << "GL texture state corruption detected.  " << msg << LL_ENDL;
 		}
 	}
+#endif
 }
 
 void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
@@ -1685,7 +1715,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
 		}
 	}
 
-	if (glIsEnabled(GL_TEXTURE_2D))
+	/*if (glIsEnabled(GL_TEXTURE_2D))
 	{
 		if (!(data_mask & 0x0008))
 		{
@@ -1708,7 +1738,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
 				gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl;
 			}
 		}
-	}
+	}*/
 
 	glClientActiveTextureARB(GL_TEXTURE0_ARB);
 	gGL.getTexUnit(0)->activate();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index d1bee001617b33f0c3447b6571c50cefeff5949b..d736133f3ffc14ba21ec732be273c5338bcf0e76 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -88,7 +88,9 @@ class LLGLManager
 		
 	// ARB Extensions
 	BOOL mHasVertexBufferObject;
+	BOOL mHasSync;
 	BOOL mHasMapBufferRange;
+	BOOL mHasFlushBufferRange;
 	BOOL mHasPBuffer;
 	BOOL mHasShaderObjects;
 	BOOL mHasVertexShader;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index f35f329f002488b8b8ce61cd2149f462b253be47..851a75629e184e60767390c843360156d7d8515a 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -68,6 +68,19 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC				glFenceSync;
+extern PFNGLISSYNCPROC					glIsSync;
+extern PFNGLDELETESYNCPROC				glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC			glClientWaitSync;
+extern PFNGLWAITSYNCPROC				glWaitSync;
+extern PFNGLGETINTEGER64VPROC			glGetInteger64v;
+extern PFNGLGETSYNCIVPROC				glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
 // GL_ARB_map_buffer_range
 extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
 extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
@@ -310,6 +323,19 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC				glFenceSync;
+extern PFNGLISSYNCPROC					glIsSync;
+extern PFNGLDELETESYNCPROC				glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC			glClientWaitSync;
+extern PFNGLWAITSYNCPROC				glWaitSync;
+extern PFNGLGETINTEGER64VPROC			glGetInteger64v;
+extern PFNGLGETSYNCIVPROC				glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
 // GL_ARB_map_buffer_range
 extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
 extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
@@ -519,6 +545,19 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
 extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
 extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
 
+// GL_ARB_sync
+extern PFNGLFENCESYNCPROC				glFenceSync;
+extern PFNGLISSYNCPROC					glIsSync;
+extern PFNGLDELETESYNCPROC				glDeleteSync;
+extern PFNGLCLIENTWAITSYNCPROC			glClientWaitSync;
+extern PFNGLWAITSYNCPROC				glWaitSync;
+extern PFNGLGETINTEGER64VPROC			glGetInteger64v;
+extern PFNGLGETSYNCIVPROC				glGetSynciv;
+
+// GL_APPLE_flush_buffer_range
+extern PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
+
 // GL_ARB_map_buffer_range
 extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
 extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index ad2c662dfcacf784d89fa681003cb956d4bd3d6d..80c93bb0d2335ba015f7d7b663b03347c7e6773d 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -49,6 +49,11 @@ using std::make_pair;
 using std::string;
 
 GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+bool LLGLSLShader::sNoFixedFunction = false;
+
+//UI shader -- declared here so llui_libtest will link properly
+LLGLSLShader	gUIProgram;
+LLGLSLShader	gSolidColorProgram;
 
 BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 {
@@ -376,6 +381,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
 
 void LLGLSLShader::bind()
 {
+	gGL.flush();
 	if (gGLManager.mHasShaderObjects)
 	{
 		glUseProgramObjectARB(mProgramObject);
@@ -390,6 +396,7 @@ void LLGLSLShader::bind()
 
 void LLGLSLShader::unbind()
 {
+	gGL.flush();
 	if (gGLManager.mHasShaderObjects)
 	{
 		stop_glerror();
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 4922eb6d6725bd0eee38177a2d776231c9e27ed1..621e0b82eeabb98a5e9b50927922bb02d9dbe350 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -67,6 +67,7 @@ class LLGLSLShader
 	LLGLSLShader();
 
 	static GLhandleARB sCurBoundShader;
+	static bool sNoFixedFunction;
 
 	void unload();
 	BOOL createShader(std::vector<std::string> * attributes,
@@ -141,4 +142,10 @@ class LLGLSLShader
 	std::string mName;
 };
 
+//UI shader (declared here so llui_libtest will link properly)
+extern LLGLSLShader			gUIProgram;
+//output vec4(color.rgb,color.a*tex0[tc0].a)
+extern LLGLSLShader			gSolidColorProgram;
+
+
 #endif
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 60a5962234054aa34b64ea9d543759f54113beb6..9ca3a23d52cd4665e76c792b8c3158d65c45a1e5 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1414,6 +1414,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
 
 void LLImageGL::deleteDeadTextures()
 {
+	bool reset = false;
+
 	while (!sDeadTextureList.empty())
 	{
 		GLuint tex = sDeadTextureList.front();
@@ -1426,12 +1428,22 @@ void LLImageGL::deleteDeadTextures()
 			{
 				tex_unit->unbind(tex_unit->getCurrType());
 				stop_glerror();
+
+				if (i > 0)
+				{
+					reset = true;
+				}
 			}
 		}
 		
 		glDeleteTextures(1, &tex);
 		stop_glerror();
 	}
+
+	if (reset)
+	{
+		gGL.getTexUnit(0)->activate();
+	}
 }
 		
 void LLImageGL::destroyGLTexture()
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 1d82dda30f6b4e3b289a15c8bd108c7885184613..70df1dd1d184522b5f716509c8ed9600c20fbb01 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -46,6 +46,7 @@ S32	gGLViewport[4];
 
 U32 LLRender::sUICalls = 0;
 U32 LLRender::sUIVerts = 0;
+U32 LLTexUnit::sWhiteTexture = 0;
 
 static const U32 LL_NUM_TEXTURE_LAYERS = 32; 
 static const U32 LL_NUM_LIGHT_UNITS = 8;
@@ -126,7 +127,8 @@ void LLTexUnit::refreshState(void)
 	// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
 	// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
 	//
-	bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+	bool enableDisable = !LLGLSLShader::sNoFixedFunction && 
+		(mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
 		
 	if (mCurrTexType != TT_NONE)
 	{
@@ -184,7 +186,8 @@ void LLTexUnit::enable(eTextureType type)
 		mCurrTexType = type;
 
 		gGL.flush();
-		if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+		if (!LLGLSLShader::sNoFixedFunction && 
+			type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
 			mIndex < gGLManager.mNumTextureUnits)
 		{
 			glEnable(sGLTextureType[type]);
@@ -201,7 +204,8 @@ void LLTexUnit::disable(void)
 		activate();
 		unbind(mCurrTexType);
 		gGL.flush();
-		if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+		if (!LLGLSLShader::sNoFixedFunction &&
+			mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
 			mIndex < gGLManager.mNumTextureUnits)
 		{
 			glDisable(sGLTextureType[mCurrTexType]);
@@ -403,7 +407,14 @@ void LLTexUnit::unbind(eTextureType type)
 
 		activate();
 		mCurrTexture = 0;
-		glBindTexture(sGLTextureType[type], 0);
+		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
+		{
+			glBindTexture(sGLTextureType[type], sWhiteTexture);
+		}
+		else
+		{
+			glBindTexture(sGLTextureType[type], 0);
+		}
 		stop_glerror();
 	}
 }
@@ -474,6 +485,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
 
 void LLTexUnit::setTextureBlendType(eTextureBlendType type)
 {
+	if (LLGLSLShader::sNoFixedFunction)
+	{ //texture blend type means nothing when using shaders
+		return;
+	}
+
 	if (mIndex < 0) return;
 
 	// Do nothing if it's already correctly set.
@@ -594,6 +610,11 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
 
 void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha)
 {
+	if (LLGLSLShader::sNoFixedFunction)
+	{ //register combiners do nothing when not using fixed function
+		return;
+	}	
+
 	if (mIndex < 0) return;
 
 	activate();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 41e7b35341d17f27b77ccd761d44bca95463e399..9eedebe2ce08efb9d74d45871c70466b5883da86 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -52,6 +52,8 @@ class LLTexUnit
 {
 	friend class LLRender;
 public:
+	static U32 sWhiteTexture;
+
 	typedef enum
 	{
 		TT_TEXTURE = 0,			// Standard 2D Texture
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index b6463309e111f81db4805915fe472577ec435f20..8c0d3592df9fde28330dbc706d6a70bdf5d5595a 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -72,11 +72,11 @@ LLRenderTarget::~LLRenderTarget()
 	release();
 }
 
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
+bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
 {
 	stop_glerror();
-	
 	release();
+	stop_glerror();
 
 	mResX = resx;
 	mResY = resy;
@@ -103,9 +103,11 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
 	{
 		if (depth)
 		{
-			stop_glerror();
-			allocateDepth();
-			stop_glerror();
+			if (!allocateDepth())
+			{
+				llwarns << "Failed to allocate depth buffer for render target." << llendl;
+				return false;
+			}
 		}
 
 		glGenFramebuffers(1, (GLuint *) &mFBO);
@@ -131,14 +133,14 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
 		stop_glerror();
 	}
 
-	addColorAttachment(color_fmt);
+	return addColorAttachment(color_fmt);
 }
 
-void LLRenderTarget::addColorAttachment(U32 color_fmt)
+bool LLRenderTarget::addColorAttachment(U32 color_fmt)
 {
 	if (color_fmt == 0)
 	{
-		return;
+		return true;
 	}
 
 	U32 offset = mTex.size();
@@ -158,14 +160,26 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
 #ifdef GL_ARB_texture_multisample
 	if (mSamples > 1)
 	{
+		clear_glerror();
 		glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
+		if (glGetError() != GL_NO_ERROR)
+		{
+			llwarns << "Could not allocate multisample color buffer for render target." << llendl;
+			return false;
+		}
 	}
 	else
 #else
 	llassert_always(mSamples <= 1);
 #endif
 	{
+		clear_glerror();
 		LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+		if (glGetError() != GL_NO_ERROR)
+		{
+			llwarns << "Could not allocate color buffer for render target." << llendl;
+			return false;
+		}
 	}
 	
 	stop_glerror();
@@ -217,15 +231,18 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
 		flush();
 	}
 
+	return true;
 }
 
-void LLRenderTarget::allocateDepth()
+bool LLRenderTarget::allocateDepth()
 {
 	if (mStencil)
 	{
 		//use render buffers where stencil buffers are in play
 		glGenRenderbuffers(1, (GLuint *) &mDepth);
 		glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
+		stop_glerror();
+		clear_glerror();
 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY);
 		glBindRenderbuffer(GL_RENDERBUFFER, 0);
 	}
@@ -237,17 +254,29 @@ void LLRenderTarget::allocateDepth()
 		{
 			U32 internal_type = LLTexUnit::getInternalType(mUsage);
 			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+			stop_glerror();
+			clear_glerror();
 			LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
 		}
 #ifdef GL_ARB_texture_multisample
 		else
 		{
+			stop_glerror();
+			clear_glerror();
 			glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
 		}
 #else
 		llassert_always(mSamples <= 1);
 #endif
 	}
+
+	if (glGetError() != GL_NO_ERROR)
+	{
+		llwarns << "Unable to allocate depth buffer for render target." << llendl;
+		return false;
+	}
+
+	return true;
 }
 
 void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 094b58b562cabcab805cbfc7415c7805714d9940..dea1de12d80953a2f519e337a62b4805bb1fc068 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -66,30 +66,30 @@ class LLRenderTarget
 	static bool sUseFBO; 
 
 	LLRenderTarget();
-	virtual ~LLRenderTarget();
+	~LLRenderTarget();
 
 	//allocate resources for rendering
 	//must be called before use
 	//multiple calls will release previously allocated resources
-	void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
+	bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
 
 	//add color buffer attachment
 	//limit of 4 color attachments per render target
-	virtual void addColorAttachment(U32 color_fmt);
+	bool addColorAttachment(U32 color_fmt);
 
 	//allocate a depth texture
-	virtual void allocateDepth();
+	bool allocateDepth();
 
 	//share depth buffer with provided render target
-	virtual void shareDepthBuffer(LLRenderTarget& target);
+	void shareDepthBuffer(LLRenderTarget& target);
 
 	//free any allocated resources
 	//safe to call redundantly
-	virtual void release();
+	void release();
 
 	//bind target for rendering
 	//applies appropriate viewport
-	virtual void bindTarget();
+	void bindTarget();
 
 	//unbind target for rendering
 	static void unbindTarget();
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 4a0b964e616bb06644ed4bbe6b5f011ca2fdb021..1180afa6313758f760a643c10f078e69ba5f8a52 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -35,6 +35,8 @@
 #include "llmemtype.h"
 #include "llrender.h"
 #include "llvector4a.h"
+#include "llglslshader.h"
+
 
 //============================================================================
 
@@ -65,6 +67,60 @@ S32	LLVertexBuffer::sWeight4Loc = -1;
 std::vector<U32> LLVertexBuffer::sDeleteList;
 
 
+const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000;  //1 ms
+
+class LLGLSyncFence : public LLGLFence
+{
+public:
+#ifdef GL_ARB_sync
+	GLsync mSync;
+#endif
+	
+	LLGLSyncFence()
+	{
+#ifdef GL_ARB_sync
+		mSync = 0;
+#endif
+	}
+
+	~LLGLSyncFence()
+	{
+#ifdef GL_ARB_sync
+		if (mSync)
+		{
+			glDeleteSync(mSync);
+		}
+#endif
+	}
+
+	void placeFence()
+	{
+#ifdef GL_ARB_sync
+		if (mSync)
+		{
+			glDeleteSync(mSync);
+		}
+		mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+#endif
+	}
+
+	void wait()
+	{
+#ifdef GL_ARB_sync
+		if (mSync)
+		{
+			while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
+			{ //track the number of times we've waited here
+				static S32 waits = 0;
+				waits++;
+			}
+		}
+#endif
+	}
+
+
+};
+
 S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
 {
 	sizeof(LLVector4), // TYPE_VERTEX,
@@ -309,6 +365,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
 	glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, 
 		idx);
 	stop_glerror();
+	placeFence();
 }
 
 void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
@@ -340,6 +397,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 	glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
 		((U16*) getIndicesPointer()) + indices_offset);
 	stop_glerror();
+	placeFence();
 }
 
 void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
@@ -365,6 +423,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 	stop_glerror();
 	glDrawArrays(sGLMode[mode], first, count);
 	stop_glerror();
+	placeFence();
 }
 
 //static
@@ -444,9 +503,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 	mFilthy(FALSE),
 	mEmpty(TRUE),
 	mResized(FALSE),
-	mDynamicSize(FALSE)
+	mDynamicSize(FALSE),
+	mFence(NULL)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
+	mFence = NULL;
 	if (!sEnableVBOs)
 	{
 		mUsage = 0 ; 
@@ -527,9 +588,40 @@ LLVertexBuffer::~LLVertexBuffer()
 	destroyGLIndices();
 	sCount--;
 
+	if (mFence)
+	{
+		delete mFence;
+	}
+	
+	mFence = NULL;
+
 	llassert_always(!mMappedData && !mMappedIndexData) ;
 };
 
+void LLVertexBuffer::placeFence() const
+{
+	/*if (!mFence && useVBOs())
+	{
+		if (gGLManager.mHasSync)
+		{
+			mFence = new LLGLSyncFence();
+		}
+	}
+
+	if (mFence)
+	{
+		mFence->placeFence();
+	}*/
+}
+
+void LLVertexBuffer::waitFence() const
+{
+	/*if (mFence)
+	{
+		mFence->wait();
+	}*/
+}
+
 //----------------------------------------------------------------------------
 
 void LLVertexBuffer::genBuffer()
@@ -892,17 +984,11 @@ BOOL LLVertexBuffer::useVBOs() const
 {
 	//it's generally ineffective to use VBO for things that are streaming on apple
 		
-#if LL_DARWIN
-	if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
-	{
-		return FALSE;
-	}
-#else
 	if (!mUsage)
 	{
 		return FALSE;
 	}
-#endif
+
 	return TRUE;
 }
 
@@ -967,8 +1053,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 		
 	if (useVBOs())
 	{
-
-		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 		{
 			if (count == -1)
 			{
@@ -1008,6 +1093,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
 			setBuffer(0, type);
 			mVertexLocked = TRUE;
+			sMappedCount++;
 			stop_glerror();	
 
 			if(sDisableVBOMapping)
@@ -1018,29 +1104,50 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 			else
 			{
 				U8* src = NULL;
-#ifdef GL_ARB_map_buffer_range
+				waitFence();
 				if (gGLManager.mHasMapBufferRange)
 				{
 					if (map_range)
 					{
+#ifdef GL_ARB_map_buffer_range
 						S32 offset = mOffsets[type] + sTypeSize[type]*index;
 						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
-						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, 
+							GL_MAP_WRITE_BIT | 
+							GL_MAP_FLUSH_EXPLICIT_BIT | 
+							GL_MAP_INVALIDATE_RANGE_BIT);
+#endif
 					}
 					else
 					{
-						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+#ifdef GL_ARB_map_buffer_range
+						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, 
+							GL_MAP_WRITE_BIT | 
+							GL_MAP_FLUSH_EXPLICIT_BIT);
+#endif
+					}
+				}
+				else if (gGLManager.mHasFlushBufferRange)
+				{
+					if (map_range)
+					{
+						glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
+						glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+						src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+					}
+					else
+					{
+						src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 					}
 				}
 				else
-#else
-				llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
 				{
 					map_range = false;
 					src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 				}
 
+				llassert(src != NULL);
+
 				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedOffset = mMappedData - src;
 			
@@ -1082,7 +1189,6 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 					llerrs << "memory allocation for vertex data failed." << llendl ;
 				}
 			}
-			sMappedCount++;
 		}
 	}
 	else
@@ -1090,7 +1196,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 		map_range = false;
 	}
 	
-	if (map_range && !sDisableVBOMapping)
+	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
 	{
 		return mMappedData;
 	}
@@ -1114,7 +1220,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 
 	if (useVBOs())
 	{
-		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 		{
 			if (count == -1)
 			{
@@ -1152,6 +1258,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 
 			setBuffer(0, TYPE_INDEX);
 			mIndexLocked = TRUE;
+			sMappedCount++;
 			stop_glerror();	
 
 			if(sDisableVBOMapping)
@@ -1162,29 +1269,51 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 			else
 			{
 				U8* src = NULL;
-#ifdef GL_ARB_map_buffer_range
+				waitFence();
 				if (gGLManager.mHasMapBufferRange)
 				{
 					if (map_range)
 					{
+#ifdef GL_ARB_map_buffer_range
 						S32 offset = sizeof(U16)*index;
 						S32 length = sizeof(U16)*count;
-						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, 
+							GL_MAP_WRITE_BIT | 
+							GL_MAP_FLUSH_EXPLICIT_BIT | 
+							GL_MAP_INVALIDATE_RANGE_BIT);
+#endif
+					}
+					else
+					{
+#ifdef GL_ARB_map_buffer_range
+						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, 
+							GL_MAP_WRITE_BIT | 
+							GL_MAP_FLUSH_EXPLICIT_BIT);
+#endif
+					}
+				}
+				else if (gGLManager.mHasFlushBufferRange)
+				{
+					if (map_range)
+					{
+						glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
+						glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+						src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 					}
 					else
 					{
-						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+						src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 					}
 				}
 				else
-#else
-				llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
 				{
 					map_range = false;
 					src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 				}
 
+				llassert(src != NULL);
+
+
 				mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedIndexOffset = mMappedIndexData - src;
 				stop_glerror();
@@ -1211,15 +1340,13 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 				llerrs << "memory allocation for Index data failed. " << llendl ;
 			}
 		}
-
-		sMappedCount++;
 	}
 	else
 	{
 		map_range = false;
 	}
 
-	if (map_range && !sDisableVBOMapping)
+	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
 	{
 		return mMappedIndexData;
 	}
@@ -1268,8 +1395,7 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 		}
 		else
 		{
-#ifdef GL_ARB_map_buffer_range
-			if (gGLManager.mHasMapBufferRange)
+			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 			{
 				if (!mMappedVertexRegions.empty())
 				{
@@ -1279,16 +1405,22 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 						const MappedRegion& region = mMappedVertexRegions[i];
 						S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
 						S32 length = sTypeSize[region.mType]*region.mCount;
-						glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+						if (gGLManager.mHasMapBufferRange)
+						{
+#ifdef GL_ARB_map_buffer_range
+							glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+#endif
+						}
+						else if (gGLManager.mHasFlushBufferRange)
+						{
+							glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
+						}
 						stop_glerror();
 					}
 
 					mMappedVertexRegions.clear();
 				}
 			}
-#else
-			llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
 			stop_glerror();
 			glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
 			stop_glerror();
@@ -1326,8 +1458,7 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 		}
 		else
 		{
-#ifdef GL_ARB_map_buffer_range
-			if (gGLManager.mHasMapBufferRange)
+			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
 			{
 				if (!mMappedIndexRegions.empty())
 				{
@@ -1336,16 +1467,24 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 						const MappedRegion& region = mMappedIndexRegions[i];
 						S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
 						S32 length = sizeof(U16)*region.mCount;
-						glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+						if (gGLManager.mHasMapBufferRange)
+						{
+#ifdef GL_ARB_map_buffer_range
+							glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+#endif
+						}
+						else if (gGLManager.mHasFlushBufferRange)
+						{
+#ifdef GL_APPLE_flush_buffer_range
+							glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+#endif
+						}
 						stop_glerror();
 					}
 
 					mMappedIndexRegions.clear();
 				}
 			}
-#else
-			llassert_always(!gGLManager.mHasMapBufferRange);
-#endif
 			stop_glerror();
 			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
 			stop_glerror();
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index aa5df305a66f0eda5bf8b31caa304311f454e4d1..cc5d11e1c29018ff1ec085da20c4e7045d33600d 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -70,6 +70,12 @@ class LLVBOPool : public LLGLNamePool
 	}
 };
 
+class LLGLFence
+{
+public:
+	virtual void placeFence() = 0;
+	virtual void wait() = 0;
+};
 
 //============================================================================
 // base class 
@@ -270,6 +276,12 @@ class LLVertexBuffer : public LLRefCount
 	std::vector<MappedRegion> mMappedVertexRegions;
 	std::vector<MappedRegion> mMappedIndexRegions;
 
+	mutable LLGLFence* mFence;
+
+	void placeFence() const;
+	void waitFence() const;
+
+
 public:
 	static S32 sCount;
 	static S32 sGLCount;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 8020ca802bd2df162653bc2acd89318fd088c58a..28d7e0a5ba6cc93486895b31778f3b6447bdf196 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -95,7 +95,6 @@ static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("
 // register other widgets which otherwise may not be linked in
 static LLDefaultChildRegistry::Register<LLLoadingIndicator> register_loading_indicator("loading_indicator");
 
-
 //
 // Functions
 //
@@ -524,8 +523,15 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
 	
 	if (solid_color)
 	{
-		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
-		gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gSolidColorProgram.bind();
+		}
+		else
+		{
+			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
+			gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
+		}
 	}
 
 	gGL.getTexUnit(0)->bind(image);
@@ -699,7 +705,14 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
 
 	if (solid_color)
 	{
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+		else
+		{
+			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		}
 	}
 }
 
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index c583d58d5a5076645fc797bf4bc556eb36879deb..a04b232a28190dd7569582eb2462a3cdc8cf9e5b 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -33,6 +33,7 @@
 #include "llrect.h"
 #include "llcontrol.h"
 #include "llcoord.h"
+#include "llglslshader.h"
 #include "llinitparam.h"
 #include "llregistry.h"
 #include "lluicolor.h"
@@ -47,6 +48,7 @@
 // for initparam specialization
 #include "llfontgl.h"
 
+
 class LLColor4; 
 class LLVector3;
 class LLVector2;
@@ -484,4 +486,7 @@ namespace LLInitParam
 	};
 }
 
+extern LLGLSLShader gSolidColorProgram;
+extern LLGLSLShader gUIProgram;
+
 #endif
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 9f4e89691f1ba3dc5628c63dcbce4a028983d77c..ae72dee9002f13939ae85e7e919eb40a7749c614 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -44,7 +44,6 @@
 						<array>
 							<!-- sample entry for debugging a specific item	-->
 <!--						<string>Voice</string>							-->
-              <string>Capabilities</string>
 						</array>
 				</map>
 			</array>
diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3827c72f4cdd5df65393f15aedaa834482d95032
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl
@@ -0,0 +1,17 @@
+/** 
+ * @file customalphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+uniform sampler2D diffuseMap;
+
+uniform float custom_alpha;
+
+void main() 
+{
+	vec4 color = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy);
+	color.a *= custom_alpha;
+	gl_FragColor = color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..04bfff22c1298a7dd592e5d9ded26f7b2d24fde8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl
@@ -0,0 +1,16 @@
+/** 
+ * @file customalphaV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_FrontColor = gl_Color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..a60fb1eaa7d54edbf4bbb4c3a7af51393f6f6c5e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
@@ -0,0 +1,17 @@
+/** 
+ * @file glowcombineF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2D glowMap;
+uniform sampler2DRect screenMap;
+
+void main() 
+{
+	gl_FragColor = texture2D(glowMap, gl_TexCoord[0].xy) +
+					texture2DRect(screenMap, gl_TexCoord[1].xy);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ce183ec15421c999aa0913b6f8cdebc143ea574b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl
@@ -0,0 +1,15 @@
+/** 
+ * @file glowcombineV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_TexCoord[1] = gl_MultiTexCoord1;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b140712f181ff1d0b0a6666f65d85aa37a5694c1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl
@@ -0,0 +1,11 @@
+/** 
+ * @file occlusionF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+void main() 
+{
+	gl_FragColor = vec4(1,1,1,1);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..5a5d0ec506bd1b9f231b659f2fe43cc34d2b79aa
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl
@@ -0,0 +1,12 @@
+/** 
+ * @file uiV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ae943cc438d4a62b87147bd73e16e9692a335f08
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl
@@ -0,0 +1,15 @@
+/** 
+ * @file twotextureaddF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+uniform sampler2D tex0;
+
+void main() 
+{
+	float alpha = texture2D(tex0, gl_TexCoord[0].xy).a;
+
+	gl_FragColor = vec4(gl_Color.rgb, alpha);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..5a854b4e02c752ba0ea38ea7fa8adfa590dad6b0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl
@@ -0,0 +1,15 @@
+/** 
+ * @file solidcolorV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..d81b56fdb9856ef52419bd67042d09fb9491d970
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl
@@ -0,0 +1,14 @@
+/** 
+ * @file twotextureaddF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+uniform sampler2D tex0;
+uniform sampler2D tex1;
+
+void main() 
+{
+	gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy)+texture2D(tex1, gl_TexCoord[1].xy);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..f685b112b4517394932db079809b66678e170f20
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl
@@ -0,0 +1,16 @@
+/** 
+ * @file twotextureaddV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_TexCoord[1] = gl_MultiTexCoord1;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/uiF.glsl b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9dec7a56ba78141f456fc12da420494dffac85e8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl
@@ -0,0 +1,13 @@
+/** 
+ * @file uiF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+uniform sampler2D diffuseMap;
+
+void main() 
+{
+	gl_FragColor = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/uiV.glsl b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9ca6cae5c5f78586532b46afc9069c67c7b83423
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl
@@ -0,0 +1,16 @@
+/** 
+ * @file uiV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+
+void main()
+{
+	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_FrontColor = gl_Color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..587ab93a80e20a25532451268df65485d4b8179c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl
@@ -0,0 +1,17 @@
+/** 
+ * @file bumpF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+uniform sampler2D texture0;
+uniform sampler2D texture1;
+
+void main() 
+{
+	float tex0 = texture2D(texture0, gl_TexCoord[0].xy).a;
+	float tex1 = texture2D(texture1, gl_TexCoord[1].xy).a;
+
+	gl_FragColor = vec4(tex0+(1.0-tex1)-0.5);
+}
diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..056d1a9582e3694c343ec6e9cc0d7fb80a645b9e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
@@ -0,0 +1,16 @@
+/** 
+ * @file bumpV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+ 
+
+void main()
+{
+	//transform vertex
+	gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+	gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
+	gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index b49aaa5d3270a7d3933df103a76f4b682249cdf4..1f9dc6e4e5113bb0bd57a0fd1364c707bfc3d382 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 30
+version 32
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences 
 // Should be combined into one table
@@ -244,10 +244,10 @@ RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
 //
-// No GL_ARB_map_buffer_range
+// GL_ARB_map_buffer_range exists
 //
-list NoMapBufferRange
-RenderVBOMappingDisable		1	0
+list MapBufferRange
+RenderVBOMappingDisable		1	1
 
 
 //
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 649f5ebd186838cdf8c1d43a4c2b45e123a5a2ca..6e962f3c567e2063b1dc4e4710d27dd2a0edcae9 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 25
+version 27
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -242,10 +242,10 @@ RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
 //
-// No GL_ARB_map_buffer_range
+// GL_ARB_map_buffer_range exists
 //
-list NoMapBufferRange
-RenderVBOMappingDisable		1	0
+list MapBufferRange
+RenderVBOMappingDisable		1	1
 
 
 
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index ee08e78af5a2b475e3d71705ed8a5086810687d2..fa67ee547c6daaf21d97b5a9faf1788bf77c2044 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 26
+version 29
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -47,8 +47,8 @@ RenderTerrainLODFactor			1	2.0
 RenderTransparentWater			1	1
 RenderTreeLODFactor				1	1.0
 RenderUseImpostors				1	1
-RenderVBOEnable					1	1
-RenderVBOMappingDisable		1	1
+RenderVBOEnable					1	0
+RenderVBOMappingDisable		1	0
 RenderVolumeLODFactor			1	2.0
 UseStartScreen				1	1
 UseOcclusion					1	1
@@ -63,7 +63,7 @@ RenderDeferred				1	1
 RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
 WatchdogDisabled				1	1
-RenderUseStreamVBO			1	1
+RenderUseStreamVBO			1	0
 RenderFSAASamples			1	16
 
 //
@@ -243,13 +243,6 @@ RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
-//
-// No GL_ARB_map_buffer_range
-//
-list NoMapBufferRange
-RenderVBOMappingDisable		1	0
-
-
 //
 // "Default" setups for safe, low, medium, high
 //
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index ba74f9a6c24b9ec6f5b72faf254f64137557906b..a0245f5369070dd5ed6fee3f49f594584a6065b6 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -1,4 +1,4 @@
-version 30
+version 31
 
 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
 // Should be combined into one table
@@ -244,10 +244,10 @@ RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
 
 //
-// No GL_ARB_map_buffer_range
+// GL_ARB_map_buffer_range exists
 //
-list NoMapBufferRange
-RenderVBOMappingDisable		1	0
+list MapBufferRange
+RenderVBOMappingDisable		1	1
 
 
 //
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 862fc49c0e6c2f78df34ab69b285f2da6b0ee297..b65933f8a1d1866c3f953bf038031453df713d45 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4003,6 +4003,8 @@ class LLFrameStatsTimer : public LLFrameTimer
 
 static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio");
 static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup");
+static LLFastTimer::DeclareTimer FTM_CLEANUP_DRAWABLES("Drawables");
+static LLFastTimer::DeclareTimer FTM_CLEANUP_OBJECTS("Objects");
 static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks");
 static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD");
 static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist");
@@ -4279,8 +4281,14 @@ void LLAppViewer::idle()
 
 	{
 		LLFastTimer t(FTM_CLEANUP);
-		gObjectList.cleanDeadObjects();
-		LLDrawable::cleanupDeadDrawables();
+		{
+			LLFastTimer t(FTM_CLEANUP_OBJECTS);
+			gObjectList.cleanDeadObjects();
+		}
+		{
+			LLFastTimer t(FTM_CLEANUP_DRAWABLES);
+			LLDrawable::cleanupDeadDrawables();
+		}
 	}
 	
 	//
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index fa7d6e2a40fd237ab548af78265f8f61b80027ff..286284f828e13af883bce36d6ce5dba52da5fd27 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -190,15 +190,16 @@ void LLDrawPool::renderPostDeferred(S32 pass)
 //virtual
 void LLDrawPool::endRenderPass( S32 pass )
 {
-	for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+	/*for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
 	{ //dummy cleanup of any currently bound textures
 		if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
 		{
 			gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
 			gGL.getTexUnit(i)->disable();
 		}
-	}
+	}*/
 
+	//make sure channel 0 is active channel
 	gGL.getTexUnit(0)->activate();
 }
 
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index ad7e3ad59352c33b4cb4db805e24ddad83aca306..ddcf42e5233e19e9e4ae872e36d6dfa12dd1350d 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -138,6 +138,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
 		gPipeline.mDeferredDepth.bindTarget();
 		simple_shader = NULL;
 		fullbright_shader = NULL;
+		gObjectFullbrightProgram.bind();
 	}
 
 	deferred_render = TRUE;
@@ -156,6 +157,7 @@ void LLDrawPoolAlpha::endPostDeferredPass(S32 pass)
 	{
 		gPipeline.mDeferredDepth.flush();
 		gPipeline.mScreen.bindTarget();
+		gObjectFullbrightProgram.unbind();
 	}
 
 	deferred_render = FALSE;
@@ -238,7 +240,7 @@ void LLDrawPoolAlpha::render(S32 pass)
 				fullbright_shader->bind();
 			}
 			pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
-			LLGLSLShader::bindNoShader();
+			//LLGLSLShader::bindNoShader();
 		}
 		else
 		{
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 813b3820ee8948c05e566754853c8531af581281..d801f6df18a6518b1beac2f4cf6e1f20e8c50f36 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -464,11 +464,15 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
 			}
 		}
 	}
-	gGL.getTexUnit(diffuse_channel)->disable();
-	gGL.getTexUnit(cube_channel)->disable();
 
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		gGL.getTexUnit(diffuse_channel)->disable();
+		gGL.getTexUnit(cube_channel)->disable();
+
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	}
 }
 
 void LLDrawPoolBump::endShiny(bool invisible)
@@ -583,19 +587,19 @@ void LLDrawPoolBump::endFullbrightShiny()
 		cube_map->disable();
 		cube_map->restoreMatrix();
 
-		if (diffuse_channel != 0)
+		/*if (diffuse_channel != 0)
 		{
 			shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 		}
 		gGL.getTexUnit(0)->activate();
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);*/
 
 		shader->unbind();
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 	}
 	
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	//gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 
 	diffuse_channel = -1;
 	cube_channel = 0;
@@ -706,36 +710,44 @@ void LLDrawPoolBump::beginBump(U32 pass)
 	// Optional second pass: emboss bump map
 	stop_glerror();
 
-	// TEXTURE UNIT 0
-	// Output.rgb = texture at texture coord 0
-	gGL.getTexUnit(0)->activate();
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gObjectBumpProgram.bind();
+	}
+	else
+	{
+		// TEXTURE UNIT 0
+		// Output.rgb = texture at texture coord 0
+		gGL.getTexUnit(0)->activate();
 
-	gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
-	gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
+		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
+		gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
 
-	// TEXTURE UNIT 1
-	gGL.getTexUnit(1)->activate();
+		// TEXTURE UNIT 1
+		gGL.getTexUnit(1)->activate();
  
-	gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
+		gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
+
+		gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA);
+		gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
 
-	gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA);
-	gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA);
+		// src	= tex0 + (1 - tex1) - 0.5
+		//		= (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
+		//		= (1 + bump0 - bump1) / 2
 
-	// src	= tex0 + (1 - tex1) - 0.5
-	//		= (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
-	//		= (1 + bump0 - bump1) / 2
 
+		// Blend: src * dst + dst * src
+		//		= 2 * src * dst
+		//		= 2 * ((1 + bump0 - bump1) / 2) * dst   [0 - 2 * dst]
+		//		= (1 + bump0 - bump1) * dst.rgb
+		//		= dst.rgb + dst.rgb * (bump0 - bump1)
+
+		gGL.getTexUnit(0)->activate();
+		gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+	}
 
-	// Blend: src * dst + dst * src
-	//		= 2 * src * dst
-	//		= 2 * ((1 + bump0 - bump1) / 2) * dst   [0 - 2 * dst]
-	//		= (1 + bump0 - bump1) * dst.rgb
-	//		= dst.rgb + dst.rgb * (bump0 - bump1)
 	gGL.setSceneBlendType(LLRender::BT_MULT_X2);
-	gGL.getTexUnit(0)->activate();
 	stop_glerror();
-
-	gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
 }
 
 //static
@@ -765,14 +777,21 @@ void LLDrawPoolBump::endBump(U32 pass)
 		return;
 	}
 
-	// Disable texture unit 1
-	gGL.getTexUnit(1)->activate();
-	gGL.getTexUnit(1)->disable();
-	gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gObjectBumpProgram.unbind();
+	}
+	else
+	{
+		// Disable texture blending on unit 1
+		gGL.getTexUnit(1)->activate();
+		//gGL.getTexUnit(1)->disable();
+		gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
 
-	// Disable texture unit 0
-	gGL.getTexUnit(0)->activate();
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		// Disable texture blending on unit 0
+		gGL.getTexUnit(0)->activate();
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	}
 	
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
 }
@@ -1407,6 +1426,11 @@ void LLDrawPoolInvisible::render(S32 pass)
 { //render invisiprims
 	LLFastTimer t(FTM_RENDER_INVISIBLE);
   
+	if (gPipeline.canUseVertexShaders())
+	{
+		gOcclusionProgram.bind();
+	}
+
 	U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
 	glStencilMask(0);
 	gGL.setColorMask(false, false);
@@ -1414,6 +1438,11 @@ void LLDrawPoolInvisible::render(S32 pass)
 	gGL.setColorMask(true, false);
 	glStencilMask(0xFFFFFFFF);
 
+	if (gPipeline.canUseVertexShaders())
+	{
+		gOcclusionProgram.unbind();
+	}
+
 	if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
 	{
 		beginShiny(true);
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 5dbb27cabb84e174b0dcb0b9a7f4c82daa266ec6..224f149c6bdf8d51b5903104006f664174fc7cad 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -49,6 +49,8 @@ void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
 	gDeferredFullbrightProgram.bind();
 }
 
+static LLFastTimer::DeclareTimer FTM_RENDER_GLOW_PUSH("Glow Push");
+
 void LLDrawPoolGlow::renderPostDeferred(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_GLOW);
@@ -62,7 +64,11 @@ void LLDrawPoolGlow::renderPostDeferred(S32 pass)
 	
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 	gGL.setColorMask(false, true);
-	pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+
+	{
+		LLFastTimer t(FTM_RENDER_GLOW_PUSH);
+		pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+	}
 	
 	gGL.setColorMask(true, false);
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);	
@@ -374,10 +380,14 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
 	LLFastTimer t(FTM_RENDER_FULLBRIGHT);
 	LLRenderPass::endRenderPass(pass);
 
+	stop_glerror();
+
 	if (mVertexShaderLevel > 0)
 	{
 		fullbright_shader->unbind();
 	}
+
+	stop_glerror();
 }
 
 void LLDrawPoolFullbright::render(S32 pass)
@@ -385,6 +395,8 @@ void LLDrawPoolFullbright::render(S32 pass)
 	LLFastTimer t(FTM_RENDER_FULLBRIGHT);
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
 
+	stop_glerror();
+
 	if (mVertexShaderLevel > 0)
 	{
 		fullbright_shader->bind();
@@ -398,6 +410,8 @@ void LLDrawPoolFullbright::render(S32 pass)
 		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
 		renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
 	}
+
+	stop_glerror();
 }
 
 S32 LLDrawPoolFullbright::getNumPasses()
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 030d6e11107369865b0699351e70bbf4d530c512..efffb2df9e705ab96682a8c6c7c8ea3f8abe4288 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -82,6 +82,10 @@ void LLDrawPoolSky::render(S32 pass)
 		mShader = &gObjectFullbrightWaterProgram;
 		mShader->bind();
 	}
+	else if (LLGLSLShader::sNoFixedFunction)
+	{ //just use the UI shader (generic single texture no lighting)
+		gUIProgram.bind();
+	}
 	else
 	{
 		// don't use shaders!
@@ -139,6 +143,7 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side)
 
 	if (LLSkyTex::doInterpolate())
 	{
+		
 		LLGLEnable blend(GL_BLEND);
 		mSkyTex[side].bindTexture(FALSE);
 		glColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 81c796b14630f19aea34b1fcdaac174baf95688b..429e06b22786d9933c9f09e1e3143d3f3830aace 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -73,7 +73,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass)
 		shader = &gObjectSimpleNonIndexedProgram;
 	}
 
-	if (gPipeline.canUseWindLightShadersOnObjects())
+	if (gPipeline.canUseVertexShaders())
 	{
 		shader->bind();
 	}
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index bf79c2100c40e125ff64f2ad01cbba509b9fd053..f9fd50107230cd6e34008dfea1c4dad6fd420a4c 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -189,16 +189,31 @@ void LLDrawPoolWLSky::renderStars(void) const
 	glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
 	// gl_FragColor.rgb = gl_Color.rgb;
 	// gl_FragColor.a = gl_Color.a * star_alpha.a;
-	gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR);
-	gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA);
-	glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV);
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gCustomAlphaProgram.bind();
+		gCustomAlphaProgram.uniform1f("custom_alpha", star_alpha.mV[3]);
+	}
+	else
+	{
+		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR);
+		gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA);
+		glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV);
+	}
 
 	gSky.mVOWLSkyp->drawStars();
 
 	gGL.popMatrix();
-	
-	// and disable the combiner states
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gCustomAlphaProgram.unbind();
+	}
+	else
+	{
+		// and disable the combiner states
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	}
 }
 
 void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
@@ -242,6 +257,10 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
 
 	if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount())
 	{
+		if (gPipeline.canUseVertexShaders())
+		{
+			gUIProgram.bind();
+		}
 		// *NOTE: even though we already bound this texture above for the
 		// stars register combiners, we bind again here for defensive reasons,
 		// since LLImageGL::bind detects that it's a noop, and optimizes it out.
@@ -257,6 +276,11 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
 		
 		LLFacePool::LLOverrideFaceColor color_override(this, color);
 		face->renderIndexed();
+
+		if (gPipeline.canUseVertexShaders())
+		{
+			gUIProgram.unbind();
+		}
 	}
 }
 
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index b6566fcbd094da1b4c887f89ac667fafd942b1ba..432e61f6d8479c593e6b3025529d155a56308a84 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1051,6 +1051,13 @@ bool LLFace::canRenderAsMask()
 
 
 static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TEXTURE("Texture");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");
+static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");
 
 BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							   const S32 &f,
@@ -1064,6 +1071,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	S32 num_vertices = (S32)vf.mNumVertices;
 	S32 num_indices = (S32) vf.mNumIndices;
 	
+	bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
+
 	if (mVertexBuffer.notNull())
 	{
 		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
@@ -1182,7 +1191,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	// INDICES
 	if (full_rebuild)
 	{
-		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_INDEX);
+		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range);
 
 		__m128i* dst = (__m128i*) indicesp.get();
 		__m128i* src = (__m128i*) vf.mIndices;
@@ -1201,7 +1211,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			indicesp[i] = vf.mIndices[i]+index_offset;
 		}
 
-		mVertexBuffer->setBuffer(0);
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 	
 	LLMatrix4a mat_normal;
@@ -1215,6 +1228,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 	if (rebuild_tcoord)
 	{
+		LLFastTimer t(FTM_FACE_GEOM_TEXTURE);
 		bool do_xform;
 			
 		if (tep)
@@ -1422,11 +1436,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				}
 			}
 
-			mVertexBuffer->setBuffer(0);
+			if (map_range)
+			{
+				mVertexBuffer->setBuffer(0);
+			}
 		}
 		else
 		{ //either bump mapped or in atlas, just do the whole expensive loop
-			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, true);
+			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);
 
 			std::vector<LLVector2> bump_tc;
 		
@@ -1566,12 +1583,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				}
 			}
 
-			mVertexBuffer->setBuffer(0);
-
+			if (map_range)
+			{
+				mVertexBuffer->setBuffer(0);
+			}
 
 			if (do_bump)
 			{
-				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, true);
+				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range);
 		
 				for (S32 i = 0; i < num_vertices; i++)
 				{
@@ -1601,14 +1620,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					*tex_coords2++ = tc;
 				}
 
-				mVertexBuffer->setBuffer(0);
+				if (map_range)
+				{
+					mVertexBuffer->setBuffer(0);
+				}
 			}
 		}
 	}
 
 	if (rebuild_pos)
 	{
-		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_POSITION);
+		llassert(num_vertices > 0);
+		
+		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range);
 		vertices = (LLVector4a*) vert.get();
 	
 		LLMatrix4a mat_vert;
@@ -1636,13 +1661,25 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			index_dst += 4;
 		}
 		while (index_dst < index_end);
-
-		mVertexBuffer->setBuffer(0);
+		
+		S32 aligned_pad_vertices = mGeomCount - num_vertices;
+		LLVector4a* last_vec = end - 1;
+		while (aligned_pad_vertices > 0)
+		{
+			--aligned_pad_vertices;
+			*dst++ = *last_vec;
+		}
+		
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 		
 	if (rebuild_normal)
 	{
-		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_NORMAL);
+		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
 		normals = (LLVector4a*) norm.get();
 	
 		for (S32 i = 0; i < num_vertices; i++)
@@ -1653,12 +1690,16 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			normals[i] = normal;
 		}
 
-		mVertexBuffer->setBuffer(0);
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 		
 	if (rebuild_binormal)
 	{
-		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
+		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);
 		binormals = (LLVector4a*) binorm.get();
 		
 		for (S32 i = 0; i < num_vertices; i++)
@@ -1669,20 +1710,28 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			binormals[i] = binormal;
 		}
 
-		mVertexBuffer->setBuffer(0);
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 	
 	if (rebuild_weights && vf.mWeights)
 	{
-		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS);
+		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range);
 		weights = (LLVector4a*) wght.get();
 		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
-		mVertexBuffer->setBuffer(0);
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 
 	if (rebuild_color)
 	{
-		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, true);
+		LLFastTimer t(FTM_FACE_GEOM_COLOR);
+		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range);
 
 		LLVector4a src;
 
@@ -1703,7 +1752,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			dst[i] = src;
 		}
 
-		mVertexBuffer->setBuffer(0);
+		if (map_range)
+		{
+			mVertexBuffer->setBuffer(0);
+		}
 	}
 
 	if (rebuild_tcoord)
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 83844048d1d2c14f3877b4131a6354bcc6ddc4ab..0ea0e41dfae9fbff54752eb5ee30f9802fec1f67 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -769,6 +769,10 @@ void LLFeatureManager::applyBaseMasks()
 	{
 		maskFeatures("TexUnit8orLess");
 	}
+	if (gGLManager.mHasMapBufferRange)
+	{
+		maskFeatures("MapBufferRange");
+	}
 
 	// now mask by gpu string
 	// Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 82e1f2dfb5ed2ae947e830ef714171ce498686df..482294c8a614bf2aec9ba73251aefadd607cc684 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -477,7 +477,7 @@ void LLHUDNameTag::renderText(BOOL for_select)
 		
 	// Render label
 	{
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 
 		for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
 			segment_iter != mLabelSegments.end(); ++segment_iter )
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index f99afa923b9a4275f02eb9651b84fb1e3f4a6a58..e23b431457470e1a3ef5fc699a8019b1486a9b55 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -47,6 +47,7 @@
 #include "llvoavatar.h"
 #include "llvolumemgr.h"
 #include "lltextureatlas.h"
+#include "llglslshader.h"
 
 static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
 static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
@@ -3176,6 +3177,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
 				glColor4fv(line_color.mV);
 				LLVertexBuffer::unbind();
 
+				llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0);
+
 				glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints);
 				glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
 				
@@ -3257,7 +3260,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
 		if (phys_volume->mHullPoints && phys_volume->mHullIndices)
 		{
 			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-			
+			llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0);
 			LLVertexBuffer::unbind();
 			glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints);
 			glColor4fv(line_color.mV);
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index bd41aa64f0a6df82afab3b367e54d6218a2b7398..e8abee2fb76c07d55ef61f92ca5642f3792d6010 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -45,6 +45,7 @@
 #include "llagentwearables.h"
 #include "llwearable.h"
 #include "llviewercontrol.h"
+#include "llviewershadermgr.h"
 #include "llviewervisualparam.h"
 
 //#include "../tools/imdebug/imdebug.h"
@@ -294,11 +295,17 @@ BOOL LLTexLayerSetBuffer::render()
 	
 	BOOL success = TRUE;
 
+	//hack to use fixed function when updating tex layer sets
+	bool no_ff = LLGLSLShader::sNoFixedFunction;
+	LLGLSLShader::sNoFixedFunction = false;
+	
 	// Composite the color data
 	LLGLSUIDefault gls_ui;
 	success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight );
 	gGL.flush();
 
+	LLGLSLShader::sNoFixedFunction = no_ff;
+	
 	if(upload_now)
 	{
 		if (!success)
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 911fc8e1ed56ebcd5d660b054db753ed92c498ca..39053fe9e4b2889545f93311b363666c6add65b2 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -616,6 +616,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 				&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
 				&& gSavedSettings.getBOOL("UseOcclusion") 
 				&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
+		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 
 		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
 		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
@@ -709,6 +710,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 		}
 
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
 		//if (!for_snapshot)
 		{
 			LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
@@ -717,6 +721,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			gPipeline.generateHighlight(*LLViewerCamera::getInstance());
 		}
 
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
 		//////////////////////////////////////
 		//
 		// Update images, using the image stats generated during object update/culling
@@ -743,6 +750,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			LLImageGL::deleteDeadTextures();
 			stop_glerror();
 		}
+
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
 		///////////////////////////////////
 		//
 		// StateSort
@@ -770,6 +781,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			}
 		}
 
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
 		LLPipeline::sUseOcclusion = occlusion;
 
 		{
@@ -828,6 +842,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
 		LLPipeline::refreshRenderDeferred();
 		
+		LLGLState::checkStates();
+		LLGLState::checkClientArrays();
+
 		stop_glerror();
 
 		if (to_texture)
@@ -878,6 +895,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			stop_glerror();
 		}
 
+		for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+		{ //dummy cleanup of any currently bound textures
+			if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
+			{
+				gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
+				gGL.getTexUnit(i)->disable();
+			}
+		}
 		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");		
 		
 		if (to_texture)
@@ -1339,7 +1364,7 @@ void render_ui_2d()
 	}
 
 	stop_glerror();
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+	//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 
 	// render outline for HUD
 	if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 9f882ee73276baadc9bba275194bb7089b5409cc..48ccc7d0354d078f902ddfcdd05f7be19f3fd230 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1339,18 +1339,29 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
 
 	S32 num_removed = 0;
 	LLViewerObject *objectp;
-	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); )
+	
+	vobj_list_t::reverse_iterator target = mObjects.rbegin();
+
+	vobj_list_t::iterator iter = mObjects.begin();
+	for ( ; iter != mObjects.end(); )
 	{
-		// Scan for all of the dead objects and remove any "global" references to them.
+		// Scan for all of the dead objects and put them all on the end of the list with no ref count ops
 		objectp = *iter;
+		if (objectp == NULL)
+		{ //we caught up to the dead tail
+			break;
+		}
+
 		if (objectp->isDead())
 		{
-			iter = mObjects.erase(iter);
+			LLPointer<LLViewerObject>::swap(*iter, *target);
+			*target = NULL;
+			++target;
 			num_removed++;
 
-			if (num_removed == mNumDeadObjects)
+			if (num_removed == mNumDeadObjects || iter->isNull())
 			{
-				// We've cleaned up all of the dead objects.
+				// We've cleaned up all of the dead objects or caught up to the dead tail
 				break;
 			}
 		}
@@ -1360,6 +1371,11 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
 		}
 	}
 
+	llassert(num_removed == mNumDeadObjects);
+
+	//erase as a block
+	mObjects.erase(mObjects.begin()+(mObjects.size()-mNumDeadObjects), mObjects.end());
+
 	// We've cleaned the global object list, now let's do some paranoia testing on objects
 	// before blowing away the dead list.
 	mDeadObjects.clear();
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index e473901609c0b1d9fc70e78cc89949a33bf82d58..62d83b516fb820be71eb7e275b0423aff5631a4a 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -61,6 +61,12 @@ BOOL				LLViewerShaderMgr::sInitialized = FALSE;
 
 LLVector4			gShinyOrigin;
 
+//utility shaders
+LLGLSLShader	gOcclusionProgram;
+LLGLSLShader	gCustomAlphaProgram;
+LLGLSLShader	gGlowCombineProgram;
+LLGLSLShader	gTwoTextureAddProgram;
+
 //object shaders
 LLGLSLShader		gObjectSimpleProgram;
 LLGLSLShader		gObjectSimpleWaterProgram;
@@ -70,6 +76,7 @@ LLGLSLShader		gObjectFullbrightShinyProgram;
 LLGLSLShader		gObjectFullbrightShinyWaterProgram;
 LLGLSLShader		gObjectShinyProgram;
 LLGLSLShader		gObjectShinyWaterProgram;
+LLGLSLShader		gObjectBumpProgram;
 
 LLGLSLShader		gObjectSimpleNonIndexedProgram;
 LLGLSLShader		gObjectSimpleNonIndexedWaterProgram;
@@ -166,14 +173,24 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gWLCloudProgram);
 	mShaderList.push_back(&gAvatarProgram);
 	mShaderList.push_back(&gObjectShinyProgram);
+	mShaderList.push_back(&gObjectShinyNonIndexedProgram);
 	mShaderList.push_back(&gWaterProgram);
 	mShaderList.push_back(&gAvatarEyeballProgram); 
 	mShaderList.push_back(&gObjectSimpleProgram);
+	mShaderList.push_back(&gObjectBumpProgram);
+	mShaderList.push_back(&gUIProgram);
+	mShaderList.push_back(&gCustomAlphaProgram);
+	mShaderList.push_back(&gGlowCombineProgram);
+	mShaderList.push_back(&gTwoTextureAddProgram);
+	mShaderList.push_back(&gSolidColorProgram);
+	mShaderList.push_back(&gOcclusionProgram);
 	mShaderList.push_back(&gObjectFullbrightProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyWaterProgram);
 	mShaderList.push_back(&gObjectSimpleNonIndexedProgram);
+	mShaderList.push_back(&gObjectSimpleNonIndexedWaterProgram);
 	mShaderList.push_back(&gObjectFullbrightNonIndexedProgram);
+	mShaderList.push_back(&gObjectFullbrightNonIndexedWaterProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram);
 	mShaderList.push_back(&gObjectFullbrightShinyNonIndexedWaterProgram);
 	mShaderList.push_back(&gSkinnedObjectSimpleProgram);
@@ -190,6 +207,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gObjectFullbrightWaterProgram);
 	mShaderList.push_back(&gAvatarWaterProgram);
 	mShaderList.push_back(&gObjectShinyWaterProgram);
+	mShaderList.push_back(&gObjectShinyNonIndexedWaterProgram);
 	mShaderList.push_back(&gUnderWaterProgram);
 	mShaderList.push_back(&gDeferredSunProgram);
 	mShaderList.push_back(&gDeferredBlurLightProgram);
@@ -410,9 +428,13 @@ void LLViewerShaderMgr::setShaders()
 	}
 	mMaxAvatarShaderLevel = 0;
 
+	LLGLSLShader::sNoFixedFunction = false;
 	if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") 
 		&& gSavedSettings.getBOOL("VertexShaderEnable"))
 	{
+		//using shaders, disable fixed function
+		LLGLSLShader::sNoFixedFunction = true;
+
 		S32 light_class = 2;
 		S32 env_class = 2;
 		S32 obj_class = 2;
@@ -554,6 +576,7 @@ void LLViewerShaderMgr::setShaders()
 		}
 		else
 		{
+			LLGLSLShader::sNoFixedFunction = false;
 			gPipeline.mVertexShadersEnabled = FALSE;
 			gPipeline.mVertexShadersLoaded = 0;
 			mVertexShaderLevel[SHADER_LIGHTING] = 0;
@@ -568,6 +591,7 @@ void LLViewerShaderMgr::setShaders()
 	}
 	else
 	{
+		LLGLSLShader::sNoFixedFunction = false;
 		gPipeline.mVertexShadersEnabled = FALSE;
 		gPipeline.mVertexShadersLoaded = 0;
 		mVertexShaderLevel[SHADER_LIGHTING] = 0;
@@ -591,7 +615,15 @@ void LLViewerShaderMgr::setShaders()
 
 void LLViewerShaderMgr::unloadShaders()
 {
+	gOcclusionProgram.unload();
+	gUIProgram.unload();
+	gCustomAlphaProgram.unload();
+	gGlowCombineProgram.unload();
+	gTwoTextureAddProgram.unload();
+	gSolidColorProgram.unload();
+
 	gObjectSimpleProgram.unload();
+	gObjectBumpProgram.unload();
 	gObjectSimpleWaterProgram.unload();
 	gObjectFullbrightProgram.unload();
 	gObjectFullbrightWaterProgram.unload();
@@ -1581,6 +1613,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyWaterProgram.unload();
 		gObjectShinyWaterProgram.unload();
 		gObjectSimpleProgram.unload();
+		gObjectBumpProgram.unload();
 		gObjectSimpleWaterProgram.unload();
 		gObjectFullbrightProgram.unload();
 		gObjectFullbrightWaterProgram.unload();
@@ -1751,6 +1784,22 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		success = gObjectSimpleProgram.createShader(NULL, NULL);
 	}
 	
+	if (success)
+	{
+		gObjectBumpProgram.mName = "Bump Shader";
+		/*gObjectBumpProgram.mFeatures.calculatesLighting = true;
+		gObjectBumpProgram.mFeatures.calculatesAtmospherics = true;
+		gObjectBumpProgram.mFeatures.hasGamma = true;
+		gObjectBumpProgram.mFeatures.hasAtmospherics = true;
+		gObjectBumpProgram.mFeatures.hasLighting = true;
+		gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/
+		gObjectBumpProgram.mShaderFiles.clear();
+		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB));
+		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		success = gObjectBumpProgram.createShader(NULL, NULL);
+	}
+	
 	if (success)
 	{
 		gObjectSimpleWaterProgram.mName = "Simple Water Shader";
@@ -2135,6 +2184,85 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		success = gHighlightProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gUIProgram.mName = "UI Shader";
+		gUIProgram.mShaderFiles.clear();
+		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB));
+		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gUIProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gCustomAlphaProgram.mName = "Custom Alpha Shader";
+		gCustomAlphaProgram.mShaderFiles.clear();
+		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB));
+		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gCustomAlphaProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gGlowCombineProgram.mName = "Glow Combine Shader";
+		gGlowCombineProgram.mShaderFiles.clear();
+		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB));
+		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gGlowCombineProgram.createShader(NULL, NULL);
+		if (success)
+		{
+			gGlowCombineProgram.bind();
+			gGlowCombineProgram.uniform1i("glowMap", 0);
+			gGlowCombineProgram.uniform1i("screenMap", 1);
+			gGlowCombineProgram.unbind();
+		}
+	}
+
+	if (success)
+	{
+		gTwoTextureAddProgram.mName = "Two Texture Add Shader";
+		gTwoTextureAddProgram.mShaderFiles.clear();
+		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB));
+		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gTwoTextureAddProgram.createShader(NULL, NULL);
+		if (success)
+		{
+			gTwoTextureAddProgram.bind();
+			gTwoTextureAddProgram.uniform1i("tex0", 0);
+			gTwoTextureAddProgram.uniform1i("tex1", 1);
+		}
+	}
+
+	if (success)
+	{
+		gSolidColorProgram.mName = "Solid Color Shader";
+		gSolidColorProgram.mShaderFiles.clear();
+		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB));
+		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gSolidColorProgram.createShader(NULL, NULL);
+		if (success)
+		{
+			gSolidColorProgram.bind();
+			gSolidColorProgram.uniform1i("tex0", 0);
+			gSolidColorProgram.unbind();
+		}
+	}
+
+	if (success)
+	{
+		gOcclusionProgram.mName = "Occlusion Shader";
+		gOcclusionProgram.mShaderFiles.clear();
+		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB));
+		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gOcclusionProgram.createShader(NULL, NULL);
+	}
+
 	if( !success )
 	{
 		mVertexShaderLevel[SHADER_INTERFACE] = 0;
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index efef9ec5b272a20ac52f374742e11e7d6c3b2293..93a0ecc4f04307cc4aad5fc5d0f197692142e3b1 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -287,6 +287,14 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade
 
 extern LLVector4			gShinyOrigin;
 
+//utility shaders
+extern LLGLSLShader			gOcclusionProgram;
+extern LLGLSLShader			gCustomAlphaProgram;
+extern LLGLSLShader			gGlowCombineProgram;
+
+//output tex0[tc0] + tex1[tc1]
+extern LLGLSLShader			gTwoTextureAddProgram;
+								
 //object shaders
 extern LLGLSLShader			gObjectSimpleProgram;
 extern LLGLSLShader			gObjectSimpleWaterProgram;
@@ -296,6 +304,7 @@ extern LLGLSLShader			gObjectFullbrightProgram;
 extern LLGLSLShader			gObjectFullbrightWaterProgram;
 extern LLGLSLShader			gObjectFullbrightNonIndexedProgram;
 extern LLGLSLShader			gObjectFullbrightNonIndexedWaterProgram;
+extern LLGLSLShader			gObjectBumpProgram;
 
 extern LLGLSLShader			gObjectSimpleLODProgram;
 extern LLGLSLShader			gObjectFullbrightLODProgram;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 4da0f80a00281beff887a3fd191d8ebf6cb14942..5fcc57bc91dc82841a5710e390a8516e64f57fd9 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -599,7 +599,7 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
 	}
 	if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep))
 	{
-		res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ;
+		res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep);
 	}
 	if (!res)
 	{
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index d24174adeae4552368b4c70da3c55d687fb02234..30ef8b8a292b23b3a89022e68b425e93e8847d24 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -115,7 +115,7 @@ void LLViewerTextureList::doPreloadImages()
 	
 	// Set the "white" image
 	LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
-	
+	LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 	LLUIImageList* image_list = LLUIImageList::getInstance();
 
 	image_list->initFromFile();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c31e1c3ba9a64e340aa753d851adcf5fe4833118..988c4ed1a234f4600152a45d5f8d3572cd3900e7 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2302,6 +2302,11 @@ void LLViewerWindow::draw()
 	// Draw all nested UI views.
 	// No translation needed, this view is glued to 0,0
 
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+
 	gGL.pushMatrix();
 	LLUI::pushMatrix();
 	{
@@ -2376,6 +2381,11 @@ void LLViewerWindow::draw()
 	LLUI::popMatrix();
 	gGL.popMatrix();
 
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.unbind();
+	}
+
 //#if LL_DEBUG
 	LLView::sIsDrawing = FALSE;
 //#endif
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index cd2bbad620951b4d2ec0121b958e0a3b40755562..0db0010688369ee1f21417d407b42888b99148c1 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -7049,6 +7049,8 @@ LLVivoxProtocolParser::~LLVivoxProtocolParser()
 		XML_ParserFree(parser);
 }
 
+static LLFastTimer::DeclareTimer FTM_VIVOX_PROCESS("Vivox Process");
+
 // virtual
 LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
 													  const LLChannelDescriptors& channels,
@@ -7057,6 +7059,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
 													  LLSD& context,
 													  LLPumpIO* pump)
 {
+	LLFastTimer t(FTM_VIVOX_PROCESS);
 	LLBufferStream istr(channels, buffer.get());
 	std::ostringstream ostr;
 	while (istr.good())
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 3c7fe708e61e5537d342c72f269567777e426914..890861df71fa2bfe79afc48848dc47bf7ea0d822 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -51,6 +51,7 @@
 #include "llspatialpartition.h"
 #include "llnotificationsutil.h"
 #include "raytrace.h"
+#include "llglslshader.h"
 
 extern LLPipeline gPipeline;
 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e6da8eb89d8ec90617d1f70d354adff65008b19e..4c137d339479ef2906916846f5e699777d9d50c9 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3743,6 +3743,11 @@ bool can_batch_texture(LLFace* facep)
 		return false;
 	}
 
+	if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA)
+	{ //can't batch invisiprims
+		return false;
+	}
+
 	if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
 	{ //texture animation breaks batches
 		return false;
@@ -4361,6 +4366,8 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 
 		group->mBuilt = 1.f;
 		
+		std::set<LLVertexBuffer*> mapped_buffers;
+
 		for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
 		{
 			LLFastTimer t(FTM_VOLUME_GEOM_PARTIAL);
@@ -4375,35 +4382,31 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
 				{
 					LLFace* face = drawablep->getFace(i);
-					if (face && face->getVertexBuffer())
+					if (face)
 					{
-						face->getGeometryVolume(*volume, face->getTEOffset(), 
-							vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
+						LLVertexBuffer* buff = face->getVertexBuffer();
+						if (buff)
+						{
+							face->getGeometryVolume(*volume, face->getTEOffset(), 
+								vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
+
+							if (buff->isLocked())
+							{
+								mapped_buffers.insert(buff);
+							}
+						}
 					}
 				}
-
+				
 				drawablep->clearState(LLDrawable::REBUILD_ALL);
 			}
 		}
 		
-		//unmap all the buffers
-		for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
+		for (std::set<LLVertexBuffer*>::iterator iter = mapped_buffers.begin(); iter != mapped_buffers.end(); ++iter)
 		{
-			LLSpatialGroup::buffer_texture_map_t& map = i->second;
-			for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j)
-			{
-				LLSpatialGroup::buffer_list_t& list = j->second;
-				for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k)
-				{
-					LLVertexBuffer* buffer = *k;
-					if (buffer->isLocked())
-					{
-						buffer->setBuffer(0);
-					}
-				}
-			}
+			(*iter)->setBuffer(0);
 		}
-		
+
 		// don't forget alpha
 		if(group != NULL && 
 		   !group->mVertexBuffer.isNull() && 
@@ -4713,6 +4716,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			}
 
 			const LLTextureEntry* te = facep->getTextureEntry();
+			tex = facep->getTexture();
 
 			BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
 		
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 69ebad61ac49cb1fd7d8a85b04e953efb7fbac39..e70ac0a2e747600e753a26b59617e02cd6b0886a 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -282,6 +282,11 @@ void LLVOWater::updateSpatialExtents(LLVector4a &newMin, LLVector4a& newMax)
 
 U32 LLVOWater::getPartitionType() const
 { 
+	if (mIsEdgePatch)
+	{
+		return LLViewerRegion::PARTITION_VOIDWATER;
+	}
+
 	return LLViewerRegion::PARTITION_WATER; 
 }
 
@@ -300,6 +305,7 @@ LLWaterPartition::LLWaterPartition()
 
 LLVoidWaterPartition::LLVoidWaterPartition()
 {
+	mOcclusionEnabled = FALSE;
 	mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER;
 	mPartitionType = LLViewerRegion::PARTITION_VOIDWATER;
 }
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 257884d921ba1f887e45a4034c9eb1fa08429524..bd1d2ed7a7b7e325eb625a50048afcefc6239eee 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -394,16 +394,18 @@ bool LLXMLRPCTransaction::Impl::process()
 		}
 	}
 	
-	const F32 MAX_PROCESSING_TIME = 0.05f;
-	LLTimer timer;
+	//const F32 MAX_PROCESSING_TIME = 0.05f;
+	//LLTimer timer;
 
-	while (mCurlRequest->perform() > 0)
+	mCurlRequest->perform();
+
+	/*while (mCurlRequest->perform() > 0)
 	{
 		if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME)
 		{
 			return false;
 		}
-	}
+	}*/
 
 	while(1)
 	{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e74bf2a6203d46a7ab7470744806d761902e2d47..dfcc7396ba6695f83996ca8930712a9a7400f93d 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -336,10 +336,10 @@ static const U32 gl_cube_face[] =
 void validate_framebuffer_object();
 
 
-void addDeferredAttachments(LLRenderTarget& target)
+bool addDeferredAttachments(LLRenderTarget& target)
 {
-	target.addColorAttachment(GL_RGBA); //specular
-	target.addColorAttachment(GL_RGBA); //normal+z	
+	return target.addColorAttachment(GL_RGBA) && //specular
+			target.addColorAttachment(GL_RGBA); //normal+z	
 }
 
 LLPipeline::LLPipeline() :
@@ -586,18 +586,61 @@ void LLPipeline::allocatePhysicsBuffer()
 
 void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 {
-	// remember these dimensions
-	mScreenWidth = resX;
-	mScreenHeight = resY;
-	
-	//cap samples at 4 for render targets to avoid out of memory errors
 	U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
 
 	if (gGLManager.mIsATI)
-	{ //disable multisampling of render targets where ATI is involved
+	{ //ATI doesn't like the way we use multisample texture
 		samples = 0;
 	}
 
+	//try to allocate screen buffers at requested resolution and samples
+	// - on failure, shrink number of samples and try again
+	// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
+	// Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state
+
+	if (!allocateScreenBuffer(resX, resY, samples))
+	{
+		releaseScreenBuffers();
+		//reduce number of samples 
+		while (samples > 0)
+		{
+			samples /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{ //success
+				return;
+			}
+			releaseScreenBuffers();
+		}
+
+		//reduce resolution
+		while (resY > 0 && resX > 0)
+		{
+			resY /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{
+				return;
+			}
+			releaseScreenBuffers();
+
+			resX /= 2;
+			if (allocateScreenBuffer(resX, resY, samples))
+			{
+				return;
+			}
+			releaseScreenBuffers();
+		}
+
+		llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
+	}
+}
+
+
+bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
+{
+	// remember these dimensions
+	mScreenWidth = resX;
+	mScreenHeight = resY;
+	
 	U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
 
 	if (res_mod > 1 && res_mod < resX && res_mod < resY)
@@ -608,7 +651,10 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 	if (gSavedSettings.getBOOL("RenderUIBuffer"))
 	{
-		mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+		{
+			return false;
+		}
 	}	
 
 	if (LLPipeline::sRenderDeferred)
@@ -618,22 +664,22 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		bool gi = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED);
 
 		//allocate deferred rendering color buffers
-		mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
-		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
-		addDeferredAttachments(mDeferredScreen);
+		if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!addDeferredAttachments(mDeferredScreen)) return false;
 	
-		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);		
+		if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		
 #if LL_DARWIN
 		// As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
-		mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		if (!mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
 #else
-		mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		if (!mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
 #endif
 
 		if (shadow_detail > 0 || ssao)
 		{ //only need mDeferredLight[0] for shadows OR ssao
-			mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+			if (!mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
 		}
 		else
 		{
@@ -642,7 +688,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		if (ssao)
 		{ //only need mDeferredLight[1] for ssao
-			mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
+			if (!mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false)) return false;
 		}
 		else
 		{
@@ -651,14 +697,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		if (gi)
 		{ //only need mDeferredLight[2] and mGIMapPost for gi
-			mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
+			if (!mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false)) return false;
 			for (U32 i = 0; i < 2; i++)
 			{
 #if LL_DARWIN
 				// As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
-				mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+				if (!mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
 #else
-				mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+				if (!mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
 #endif
 			}
 		}
@@ -685,7 +731,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		{ //allocate 4 sun shadow maps
 			for (U32 i = 0; i < 4; i++)
 			{
-				mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+				if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
 			}
 		}
 		else
@@ -703,7 +749,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		{ //allocate two spot shadow maps
 			for (U32 i = 4; i < 6; i++)
 			{
-				mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE);
+				if (!mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE)) return false;
 			}
 		}
 		else
@@ -716,7 +762,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		width = nhpo2(resX)/2;
 		height = nhpo2(resY)/2;
-		mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE);
+		if (!mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE)) return false;
 	}
 	else
 	{
@@ -738,7 +784,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		mEdgeMap.release();
 		mLuminanceMap.release();
 		
-		mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
+		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
 	}
 	
 	if (LLPipeline::sRenderDeferred)
@@ -750,6 +796,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 	stop_glerror();
 
+	return true;
 }
 
 //static
@@ -800,9 +847,23 @@ void LLPipeline::releaseGLBuffers()
 
 	mWaterRef.release();
 	mWaterDis.release();
+	
+	for (U32 i = 0; i < 3; i++)
+	{
+		mGlow[i].release();
+	}
+
+	releaseScreenBuffers();
+
+	gBumpImageList.destroyGL();
+	LLVOAvatar::resetImpostors();
+}
+
+void LLPipeline::releaseScreenBuffers()
+{
+	mUIScreen.release();
 	mScreen.release();
 	mPhysicsDisplay.release();
-	mUIScreen.release();
 	mDeferredScreen.release();
 	mDeferredDepth.release();
 	for (U32 i = 0; i < 3; i++)
@@ -821,16 +882,9 @@ void LLPipeline::releaseGLBuffers()
 	{
 		mShadow[i].release();
 	}
-
-	for (U32 i = 0; i < 3; i++)
-	{
-		mGlow[i].release();
-	}
-
-	gBumpImageList.destroyGL();
-	LLVOAvatar::resetImpostors();
 }
 
+
 void LLPipeline::createGLBuffers()
 {
 	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
@@ -1983,6 +2037,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 
+	bool bound_shader = false;
+	if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0)
+	{ //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
+		// (shadow render uses a special shader that clamps to clip planes)
+		bound_shader = true;
+		gOcclusionProgram.bind();
+	}
+	
 	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
 			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 	{
@@ -2010,6 +2072,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		}
 	}
 
+	if (bound_shader)
+	{
+		gOcclusionProgram.unbind();
+	}
+
 	camera.disableUserClipPlane();
 
 	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
@@ -2133,7 +2200,21 @@ void LLPipeline::doOcclusion(LLCamera& camera)
 		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 
 		LLGLDisable cull(GL_CULL_FACE);
+
 		
+		bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0;
+		if (bind_shader)
+		{
+			if (LLPipeline::sShadowRender)
+			{
+				gDeferredShadowProgram.bind();
+			}
+			else
+			{
+				gOcclusionProgram.bind();
+			}
+		}
+
 		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
 		{
 			LLSpatialGroup* group = *iter;
@@ -2141,6 +2222,18 @@ void LLPipeline::doOcclusion(LLCamera& camera)
 			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
 		}
 	
+		if (bind_shader)
+		{
+			if (LLPipeline::sShadowRender)
+			{
+				gDeferredShadowProgram.unbind();
+			}
+			else
+			{
+				gOcclusionProgram.unbind();
+			}
+		}
+
 		gGL.setColorMask(true, false);
 	}
 }
@@ -3249,6 +3342,11 @@ void render_hud_elements()
 	gGL.color4f(1,1,1,1);
 	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
 	{
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+
 		LLGLEnable multisample(gSavedSettings.getU32("RenderFSAASamples") > 0 ? GL_MULTISAMPLE_ARB : 0);
 		gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
 	
@@ -3262,6 +3360,10 @@ void render_hud_elements()
 	
 		// Render name tags.
 		LLHUDObject::renderAll();
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.unbind();
+		}
 	}
 	else if (gForceRenderLandFence)
 	{
@@ -3599,8 +3701,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 						check_stack_depth(stack_depth);
 						std::string msg = llformat("pass %d", i);
 						LLGLState::checkStates(msg);
-						LLGLState::checkTextureChannels(msg);
-						LLGLState::checkClientArrays(msg);
+						//LLGLState::checkTextureChannels(msg);
+						//LLGLState::checkClientArrays(msg);
 					}
 				}
 			}
@@ -3638,16 +3740,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 
 	LLVertexBuffer::unbind();
 	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	
-
-	stop_glerror();
-		
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
 
 	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
 
@@ -3701,8 +3793,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 	LLVertexBuffer::unbind();
 
 	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
+//	LLGLState::checkTextureChannels();
+//	LLGLState::checkClientArrays();
 }
 
 void LLPipeline::renderGeomDeferred(LLCamera& camera)
@@ -3785,8 +3877,6 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 						llerrs << "GL matrix stack corrupted!" << llendl;
 					}
 					LLGLState::checkStates();
-					LLGLState::checkTextureChannels();
-					LLGLState::checkClientArrays();
 				}
 			}
 		}
@@ -3879,8 +3969,6 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
 						llerrs << "GL matrix stack corrupted!" << llendl;
 					}
 					LLGLState::checkStates();
-					LLGLState::checkTextureChannels();
-					LLGLState::checkClientArrays();
 				}
 			}
 		}
@@ -3955,8 +4043,6 @@ void LLPipeline::renderGeomShadow(LLCamera& camera)
 				LLVertexBuffer::unbind();
 
 				LLGLState::checkStates();
-				LLGLState::checkTextureChannels();
-				LLGLState::checkClientArrays();
 			}
 		}
 		else
@@ -6449,30 +6535,39 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 		LLGLDisable blend(GL_BLEND);
 
-		//tex unit 0
-		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
-	
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		gGL.getTexUnit(1)->activate();
-		gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
-
-		//tex unit 1
-		gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gGlowCombineProgram.bind();
+		}
+		else
+		{
+			//tex unit 0
+			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+			//tex unit 1
+			gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
+		}
 		
+		gGL.getTexUnit(0)->bind(&mGlow[1]);
 		gGL.getTexUnit(1)->bind(&mScreen);
-		gGL.getTexUnit(1)->activate();
 		
 		LLGLEnable multisample(gSavedSettings.getU32("RenderFSAASamples") > 0 ? GL_MULTISAMPLE_ARB : 0);
 		
 		buff->setBuffer(mask);
 		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
 		
-		gGL.getTexUnit(1)->disable();
-		gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gGlowCombineProgram.unbind();
+		}
+		else
+		{
+			gGL.getTexUnit(1)->disable();
+			gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
 
-		gGL.getTexUnit(0)->activate();
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+			gGL.getTexUnit(0)->activate();
+			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+		}
+		
 	}
 
 	if (LLRenderTarget::sUseFBO)
@@ -6485,6 +6580,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
 	{
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.bind();
+		}
+
 		gGL.setColorMask(true, false);
 
 		LLVector2 tc1(0,0);
@@ -6508,6 +6608,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		
 		gGL.end();
 		gGL.flush();
+
+		if (LLGLSLShader::sNoFixedFunction)
+		{
+			gUIProgram.unbind();
+		}
+
 	}
 
 	glMatrixMode(GL_PROJECTION);
@@ -7923,7 +8029,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
 			static LLCullResult ref_result;
 
-			if (LLDrawPoolWater::sNeedsDistortionUpdate)
+			if (LLDrawPoolWater::sNeedsReflectionUpdate)
 			{
 				//initial sky pass (no user clip plane)
 				{ //mask out everything but the sky
@@ -8063,8 +8169,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 		LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
 		
 		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
 
 		if (!skip_avatar_update)
 		{
@@ -8197,6 +8301,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	LLVertexBuffer::unbind();
 
 	{
+		if (!use_shader)
+		{ //occlusion program is general purpose depth-only no-textures
+			gOcclusionProgram.bind();
+		}
 		LLFastTimer ftm(FTM_SHADOW_SIMPLE);
 		LLGLDisable test(GL_ALPHA_TEST);
 		gGL.getTexUnit(0)->disable();
@@ -8205,6 +8313,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 			renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
 		}
 		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+		if (!use_shader)
+		{
+			gOcclusionProgram.unbind();
+		}
 	}
 	
 	if (use_shader)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index e9da25e544b93e9d686e5c90300be610b6021a83..28e6526acd960dc761e6cc3644798f736e6945d0 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -113,9 +113,11 @@ class LLPipeline
 	void resetVertexBuffers();
 	void resizeScreenTexture();
 	void releaseGLBuffers();
+	void releaseScreenBuffers();
 	void createGLBuffers();
 
 	void allocateScreenBuffer(U32 resX, U32 resY);
+	bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
 	void allocatePhysicsBuffer();
 	
 	void resetVertexBuffers(LLDrawable* drawable);
diff --git a/shining-fixes_rev18977.patch b/shining-fixes_rev18977.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b711da870a951304979f5d0045253f82d0765185
--- /dev/null
+++ b/shining-fixes_rev18977.patch
@@ -0,0 +1,41 @@
+# HG changeset patch
+# User Dave Parks <davep@lindenlab.com>
+# Date 1308673064 18000
+# Node ID 95c5639a3f80920e8dc54703d894517dd7694edf
+# Parent  6af10678de4736222b2c3f7e010e984fb5b327de
+SH-208 Disable VBO on all intel graphics chips (stability improvement).
+
+diff -r 6af10678de47 -r 95c5639a3f80 indra/newview/featuretable.txt
+--- a/indra/newview/featuretable.txt	Mon Jun 20 16:42:31 2011 -0700
++++ b/indra/newview/featuretable.txt	Tue Jun 21 11:17:44 2011 -0500
+@@ -1,4 +1,4 @@
+-version 29
++version 30
+ 
+ // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
+ // Should be combined into one table
+@@ -297,6 +297,7 @@
+ 
+ list Intel
+ RenderAnisotropic			1	0
++RenderVBOEnable				1	0
+ 
+ list GeForce2
+ RenderAnisotropic			1	0
+diff -r 6af10678de47 -r 95c5639a3f80 indra/newview/featuretable_xp.txt
+--- a/indra/newview/featuretable_xp.txt	Mon Jun 20 16:42:31 2011 -0700
++++ b/indra/newview/featuretable_xp.txt	Tue Jun 21 11:17:44 2011 -0500
+@@ -1,4 +1,4 @@
+-version 29
++version 30
+ 
+ // NOTE: This is mostly identical to featuretable_mac.txt with a few differences
+ // Should be combined into one table
+@@ -295,6 +295,7 @@
+ 
+ list Intel
+ RenderAnisotropic			1	0
++RenderVBOEnable				1	0
+ 
+ list GeForce2
+ RenderAnisotropic			1	0