diff --git a/.hgtags b/.hgtags
old mode 100644
new mode 100755
index a86e9eafa8f46806c23aef4f53aacb0cc8e67c8a..fce3d9abc1ca06750f3e71b50688e9fd8fedf849
--- a/.hgtags
+++ b/.hgtags
@@ -352,6 +352,7 @@ ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5
 a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182
 1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1
 81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
+78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
 cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
 9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
 e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193
diff --git a/autobuild.xml b/autobuild.xml
index 0ff952be5b207d53caf3820168aaaf5846251c12..5093e136b5ced6505442305da013d31ca573b1d7 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1062,9 +1062,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d91e1f483209cd3eba04135c6a59e829</string>
+              <string>a5b2dff0d97b643227a58473e5c57906</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/221672/arch/Darwin/installer/kdu-6.4.1-darwin-20110218.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/256978/arch/Darwin/installer/kdu-7.0.0-darwin-20120515.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1086,9 +1086,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>6cd9f36465ef73a3df34bf2b3bba2ced</string>
+              <string>6d80d35524e1c0c32d3385014d02d48c</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/221672/arch/CYGWIN/installer/kdu-6.4.1-windows-20110218.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/256978/arch/CYGWIN/installer/kdu-7.0.0-windows-20120515.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 6775b005f4f179e8beb94b57fd876ca6a81c26f7..e6b838c5b260ce93da7f0753aaaa0314ccd3027f 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -292,11 +292,16 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
 	++sRawImageCount;
 }
 
-LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
+LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
 	: LLImageBase()
 {
 	mMemType = LLMemType::MTYPE_IMAGERAW;
-	if(allocateDataSize(width, height, components))
+
+	if(no_copy)
+	{
+		setDataAndSize(data, width, height, components);
+	}
+	else if(allocateDataSize(width, height, components))
 	{
 		memcpy(getData(), data, width*height*components);
 	}
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 46e6d1a901315fb622382dd20f0461c5a1116516..99023351c2b0646cffcaab6d45a56c8f1837ab3c 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -189,7 +189,7 @@ class LLImageRaw : public LLImageBase
 public:
 	LLImageRaw();
 	LLImageRaw(U16 width, U16 height, S8 components);
-	LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
+	LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
 	// Construct using createFromFile (used by tools)
 	//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
 
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
old mode 100644
new mode 100755
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index cf88de12b49ab8ff05512ccc98cd31fb592536dc..0c0a844b739f30abdf4431f34f3b1b4fe2046cef 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -1179,7 +1179,7 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
 			llassert(mDims == comp_dims); // Safety check; the caller has ensured this
 		}
 		bool use_shorts = (mComps[c].get_bit_depth(true) <= 16);
-		mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts);
+		mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts,0,0);
 		if (res.which() == 0) // No DWT levels used
 		{
 			mEngines[c] = kdu_decoder(res.access_subband(LL_BAND),&mAllocator,use_shorts);
@@ -1223,7 +1223,7 @@ separation between consecutive rows in the real buffer. */
 	{
 		for (c = 0; c < mNumComponents; c++)
 		{
-			mEngines[c].pull(mLines[c],true);
+			mEngines[c].pull(mLines[c]);
 		}
 		if ((mNumComponents >= 3) && mUseYCC)
 		{
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
index 9ab0b9e4a7bcfe9402ebb81956c3cb9b8e50a83a..fb1f6535bac58b87d27f6ccfb3fe70caabc5df44 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -32,6 +32,7 @@
 //
 // KDU core header files
 //
+#define KDU_NO_THREADS
 #include "kdu_elementary.h"
 #include "kdu_messaging.h"
 #include "kdu_params.h"
diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h
index 9d923fc3674b2a7cfdb5ab0cf527270e4efae136..dbdf88b2d92b36825ae56775244b1f484e053a4c 100644
--- a/indra/llkdu/llkdumem.h
+++ b/indra/llkdu/llkdumem.h
@@ -28,6 +28,7 @@
 #define LL_LLKDUMEM_H
 
 // Support classes for reading and writing from memory buffers in KDU
+#define KDU_NO_THREADS
 #include "kdu_image.h"
 #include "kdu_elementary.h"
 #include "kdu_messaging.h"
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
old mode 100644
new mode 100755
index beee99a522967af6159b9241c898b076dad827a5..b675153b2ede472fed851b75dc37f79f9c6a4da3
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -127,7 +127,6 @@ kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; }
 void kdu_resolution::get_dims(kdu_dims& ) { }
 int kdu_resolution::which() { return 0; }
 int kdu_resolution::get_valid_band_indices(int &) { return 1; }
-kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
 kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
 kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
 kdu_params::~kdu_params() { }
@@ -153,7 +152,6 @@ void kdu_codestream::destroy() { }
 void kdu_codestream::collect_timing_stats(int ) { }
 void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
 void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
-void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long ) { }
 void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { }
 void kdu_codestream::apply_input_restrictions( int, int, int, int, kdu_dims*, kdu_component_access_mode ) { }
 void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
@@ -175,7 +173,7 @@ kdu_block* kdu_subband::open_block(kdu_coords, int*, kdu_thread_env*) { return N
 bool kdu_codestream_comment::put_text(const char*) { return false; }
 void kdu_customize_warnings(kdu_message*) { }
 void kdu_customize_errors(kdu_message*) { }
-void kdu_convert_ycc_to_rgb(kdu_line_buf&, kdu_line_buf&, kdu_line_buf&, int) { }
+
 kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, bool, kdu_roi_image*, bool, int, kdu_thread_env*, kdu_thread_queue*, bool ) { kdu_long a = 0; return a; }
 siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
 void siz_params::finalize(bool ) { }
@@ -184,6 +182,21 @@ int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0;
 bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }
 bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; }
 
+#ifdef LL_LINUX
+// Linux use the old pre KDU v7.0.0
+// *TODO: Supress this legacy stubbs once Linux migrates to v7.0.0
+kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
+void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long ) { }
+void kdu_convert_ycc_to_rgb(kdu_line_buf&, kdu_line_buf&, kdu_line_buf&, int) { }
+#else
+kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*, int) { }
+void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long, kdu_thread_env* ) { }
+void (*kdu_convert_ycc_to_rgb_rev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
+void (*kdu_convert_ycc_to_rgb_irrev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
+void (*kdu_convert_ycc_to_rgb_rev32)(kdu_int32*,kdu_int32*,kdu_int32*,int);
+void (*kdu_convert_ycc_to_rgb_irrev32)(float*,float*,float*,int);
+#endif
+
 // -------------------------------------------------------------------------------------------
 // TUT
 // -------------------------------------------------------------------------------------------
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 97f279268647a1e5a247fd558eba5344c803fafa..fbc3cc6de2933445722e646e7fa96e78bf366127 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -87,6 +87,9 @@ namespace LLAvatarNameCache
     /// Time when unrefreshed cached names were checked last
     static F64 sLastExpireCheck;
 
+	/// Time-to-live for a temp cache entry.
+	const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
+
 	//-----------------------------------------------------------------------
 	// Internal methods
 	//-----------------------------------------------------------------------
@@ -274,7 +277,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
     {
         // there is no existing cache entry, so make a temporary name from legacy
         LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent "
-                                << agent_id << LL_ENDL;
+								<< agent_id << LL_ENDL;
         gCacheName->get(agent_id, false,  // legacy compatibility
                         boost::bind(&LLAvatarNameCache::legacyNameCallback,
                                     _1, _2, _3));
@@ -287,13 +290,14 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
         // Clear this agent from the pending list
         LLAvatarNameCache::sPendingQueue.erase(agent_id);
 
-        const LLAvatarName& av_name = existing->second;
+        LLAvatarName& av_name = existing->second;
         LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent "
                                  << agent_id 
                                  << "user '" << av_name.mUsername << "' "
                                  << "display '" << av_name.mDisplayName << "' "
                                  << "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
                                  << LL_ENDL;
+		av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest.
     }
 }
 
@@ -402,10 +406,12 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
 							 << LL_ENDL;
 	buildLegacyName(full_name, &av_name);
 
-	// Don't add to cache, the data already exists in the legacy name system
-	// cache and we don't want or need duplicate storage, because keeping the
-	// two copies in sync is complex.
-	processName(agent_id, av_name, false);
+	// Add to cache, because if we don't we'll keep rerequesting the
+	// same record forever.  buildLegacyName should always guarantee
+	// that these records expire reasonably soon
+	// (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due
+	// to something temporary we will eventually request and get the right data.
+	processName(agent_id, av_name, true);
 }
 
 void LLAvatarNameCache::requestNamesViaLegacy()
@@ -583,7 +589,7 @@ void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
 	av_name->mDisplayName = full_name;
 	av_name->mIsDisplayNameDefault = true;
 	av_name->mIsTemporaryName = true;
-	av_name->mExpires = F64_MAX; // not used because these are not cached
+	av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME;
 	LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName "
 							 << full_name
 							 << LL_ENDL;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 5ea9b58300fe68e53fd8f21b02cceaa847f8535c..b4ac984d57f7eb57212a9d43a2ec0e5d8f3da1f0 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -935,8 +935,8 @@ bool LLCurlThread::CurlRequest::processRequest()
 
 		if(!completed)
 		{
-		setPriority(LLQueuedThread::PRIORITY_LOW) ;
-	}
+			setPriority(LLQueuedThread::PRIORITY_LOW) ;
+		}
 	}
 
 	return completed ;
@@ -946,7 +946,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)
 {
 	if(mMulti->isDead())
 	{
-	mCurlThread->deleteMulti(mMulti) ;
+		mCurlThread->deleteMulti(mMulti) ;
 	}
 	else
 	{
@@ -990,6 +990,7 @@ void LLCurlThread::killMulti(LLCurl::Multi* multi)
 		return ;
 	}
 
+
 	multi->markDead() ;
 }
 
@@ -1095,7 +1096,9 @@ void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
 {
 	getByteRange(url, headers_t(), 0, -1, responder);
 }
-	
+
+// Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
+// the remainder of the file if not.
 bool LLCurlRequest::getByteRange(const std::string& url,
 								 const headers_t& headers,
 								 S32 offset, S32 length,
@@ -1113,6 +1116,11 @@ bool LLCurlRequest::getByteRange(const std::string& url,
 		std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1);
 		easy->slist_append(range.c_str());
 	}
+	else if (offset > 0)
+	{
+		std::string range = llformat("Range: bytes=%d-", offset);
+		easy->slist_append(range.c_str());
+	}
 	easy->setHeaders();
 	bool res = addEasy(easy);
 	return res;
@@ -1238,6 +1246,208 @@ S32 LLCurlRequest::getQueued()
 	return queued;
 }
 
+LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) : 
+	LLCurlRequest(), 
+	mConcurrency(concurrency),
+	mInQueue(0),
+	mMutex(NULL),
+	mHandleCounter(1),
+	mTotalIssuedRequests(0),
+	mTotalReceivedBits(0)
+{
+	mGlobalTimer.reset();
+}
+
+LLCurlTextureRequest::~LLCurlTextureRequest()
+{
+	mRequestMap.clear();
+
+	for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
+	{
+		delete *iter;
+	}
+	mCachedRequests.clear();
+}
+
+//return 0: success
+// > 0: cached handle
+U32 LLCurlTextureRequest::getByteRange(const std::string& url,
+								 const headers_t& headers,
+								 S32 offset, S32 length, U32 pri,
+								 LLCurl::ResponderPtr responder, F32 delay_time)
+{
+	U32 ret_val = 0;
+	bool success = false;	
+
+	if(mInQueue < mConcurrency && delay_time < 0.f)
+	{
+		success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);		
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	if(success)
+	{
+		mInQueue++;
+		mTotalIssuedRequests++;
+	}
+	else
+	{
+		request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
+		if(delay_time > 0.f)
+		{
+			request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
+		}
+
+		mCachedRequests.insert(request);
+		mRequestMap[mHandleCounter] = request;
+		ret_val = mHandleCounter;
+		mHandleCounter++;
+
+		if(!mHandleCounter)
+		{
+			mHandleCounter = 1;
+		}
+	}
+
+	return ret_val;
+}
+
+void LLCurlTextureRequest::completeRequest(S32 received_bytes)
+{
+	LLMutexLock lock(&mMutex);
+
+	llassert_always(mInQueue > 0);
+
+	mInQueue--;
+	mTotalReceivedBits += received_bytes * 8;
+}
+
+void LLCurlTextureRequest::nextRequests()
+{
+	if(mCachedRequests.empty() || mInQueue >= mConcurrency)
+	{
+		return;
+	}
+
+	F32 cur_time = mGlobalTimer.getElapsedTimeF32();
+
+	req_queue_t::iterator iter;	
+	{
+		LLMutexLock lock(&mMutex);
+		iter = mCachedRequests.begin();
+	}
+	while(1)
+	{
+		request_t* request = *iter;
+		if(request->mStartTime < cur_time)
+		{
+			if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
+			{
+				break;
+			}
+
+			LLMutexLock lock(&mMutex);
+			++iter;
+			mInQueue++;
+			mTotalIssuedRequests++;
+			mCachedRequests.erase(request);
+			mRequestMap.erase(request->mHandle);
+			delete request;
+
+			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+			{
+				break;
+			}
+		}
+		else
+		{
+			LLMutexLock lock(&mMutex);
+			++iter;
+			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+			{
+				break;
+			}
+		}
+	}
+
+	return;
+}
+
+void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
+{
+	if(!handle)
+	{
+		return;
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+	if(iter != mRequestMap.end())
+	{
+		request_t* req = iter->second;
+		
+		if(req->mPriority != pri)
+		{
+			mCachedRequests.erase(req);
+			req->mPriority = pri;
+			mCachedRequests.insert(req);
+		}
+	}
+}
+
+void LLCurlTextureRequest::removeRequest(U32 handle)
+{
+	if(!handle)
+	{
+		return;
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+	if(iter != mRequestMap.end())
+	{
+		request_t* req = iter->second;
+		mRequestMap.erase(iter);
+		mCachedRequests.erase(req);
+		delete req;
+	}
+}
+
+bool LLCurlTextureRequest::isWaiting(U32 handle)
+{
+	if(!handle)
+	{
+		return false;
+	}
+
+	LLMutexLock lock(&mMutex);
+	return mRequestMap.find(handle) != mRequestMap.end();
+}
+
+U32 LLCurlTextureRequest::getTotalReceivedBits()
+{
+	LLMutexLock lock(&mMutex);
+
+	U32 bits = mTotalReceivedBits;
+	mTotalReceivedBits = 0;
+	return bits;
+}
+
+U32 LLCurlTextureRequest::getTotalIssuedRequests()
+{
+	LLMutexLock lock(&mMutex);
+	return mTotalIssuedRequests;
+}
+
+S32 LLCurlTextureRequest::getNumRequests()
+{
+	LLMutexLock lock(&mMutex);
+	return mInQueue;
+}
+
 ////////////////////////////////////////////////////////////////////////////
 // For generating one easy request
 // associated with a single multi request
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index d6a7714d4c850251d846d19cbd6811f8c72682ac..20ebd86c067138c2f4d56fcb76fda0f688bb29f4 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -414,6 +414,71 @@ class LLCurlRequest
 	BOOL mProcessing;
 };
 
+//for texture fetch only
+class LLCurlTextureRequest : public LLCurlRequest
+{
+public:
+	LLCurlTextureRequest(S32 concurrency);
+	~LLCurlTextureRequest();
+
+	U32 getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder, F32 delay_time = -1.f);
+	void nextRequests();
+	void completeRequest(S32 received_bytes);
+
+	void updatePriority(U32 handle, U32 pri);
+	void removeRequest(U32 handle);
+
+	U32 getTotalReceivedBits();
+	U32 getTotalIssuedRequests();
+	S32 getNumRequests();
+	bool isWaiting(U32 handle);
+	
+private:
+	LLMutex mMutex;
+	S32 mConcurrency;
+	S32 mInQueue; //request currently in queue.
+	U32 mHandleCounter;
+	U32 mTotalIssuedRequests;
+	U32 mTotalReceivedBits;
+
+	typedef struct _request_t
+	{
+		_request_t(U32 handle, const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder) :
+				mHandle(handle), mUrl(url), mHeaders(headers), mOffset(offset), mLength(length), mPriority(pri), mResponder(responder), mStartTime(0.f)
+				{}
+
+		U32  mHandle;
+		std::string mUrl;
+		LLCurlRequest::headers_t mHeaders;
+		S32 mOffset;
+		S32 mLength;
+		LLCurl::ResponderPtr mResponder;
+		U32 mPriority;
+		F32 mStartTime; //start time to issue this request
+	} request_t;
+
+	struct request_compare
+	{
+		bool operator()(const request_t* lhs, const request_t* rhs) const
+		{
+			if(lhs->mPriority != rhs->mPriority)
+			{
+				return lhs->mPriority > rhs->mPriority; // higher priority in front of queue (set)
+			}
+			else
+			{
+				return (U32)lhs < (U32)rhs;
+			}
+		}
+	};
+
+	typedef std::set<request_t*, request_compare> req_queue_t;
+	req_queue_t mCachedRequests;
+	std::map<S32, request_t*> mRequestMap;
+
+	LLFrameTimer mGlobalTimer;
+};
+
 class LLCurlEasyRequest
 {
 public:
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
old mode 100644
new mode 100755
index 30532247ac1f0b8af71c4aeddbea5076b013ccfc..6dee1927838f1d7e54ca0d3212963644f8410552
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -149,7 +149,8 @@ bool LLPrimitive::cleanupVolumeManager()
 LLPrimitive::LLPrimitive()
 :	mTextureList(),
 	mNumTEs(0),
-	mMiscFlags(0)
+	mMiscFlags(0),
+	mNumBumpmapTEs(0)
 {
 	mPrimitiveCode = 0;
 
@@ -237,7 +238,10 @@ void  LLPrimitive::setAllTETextures(const LLUUID &tex_id)
 //===============================================================
 void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te)
 {
-	mTextureList.copyTexture(index, te);
+	if(mTextureList.copyTexture(index, te) != TEM_CHANGE_NONE && te.getBumpmap() > 0)
+	{
+		mNumBumpmapTEs++;
+	}
 }
 
 S32  LLPrimitive::setTETexture(const U8 index, const LLUUID &id)
@@ -316,6 +320,7 @@ S32  LLPrimitive::setTERotation(const U8 index, const F32 r)
 //===============================================================
 S32  LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump)
 {
+	updateNumBumpmap(index, bump);
 	return mTextureList.setBumpShinyFullbright(index, bump);
 }
 
@@ -326,11 +331,13 @@ S32  LLPrimitive::setTEMediaTexGen(const U8 index, const U8 media)
 
 S32  LLPrimitive::setTEBumpmap(const U8 index, const U8 bump)
 {
+	updateNumBumpmap(index, bump);
 	return mTextureList.setBumpMap(index, bump);
 }
 
 S32  LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny)
 {
+	updateNumBumpmap(index, bump_shiny);
 	return mTextureList.setBumpShiny(index, bump_shiny);
 }
 
@@ -1445,6 +1452,26 @@ void LLPrimitive::takeTextureList(LLPrimTextureList& other_list)
 	mTextureList.take(other_list);
 }
 
+void LLPrimitive::updateNumBumpmap(const U8 index, const U8 bump)
+{
+	LLTextureEntry* te = getTE(index);
+	if(!te)
+	{
+		return;
+	}
+
+	U8 old_bump = te->getBumpmap();	
+	if(old_bump > 0)
+	{
+		mNumBumpmapTEs--;
+	}
+	if((bump & TEM_BUMP_MASK) > 0)
+	{
+		mNumBumpmapTEs++;
+	}
+
+	return;
+}
 //============================================================================
 
 // Moved from llselectmgr.cpp
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 998016f8f6a4fd56ead0b31df6c703b1804ffa00..8dcaa8c740b58c47f742e0c340c099de627a79eb 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -421,7 +421,8 @@ class LLPrimitive : public LLXform
 	inline BOOL	isAvatar() const;
 	inline BOOL	isSittingAvatar() const;
 	inline BOOL	isSittingAvatarOnGround() const;
-
+	inline bool hasBumpmap() const  { return mNumBumpmapTEs > 0;}
+	
 	void setFlags(U32 flags) { mMiscFlags = flags; }
 	void addFlags(U32 flags) { mMiscFlags |= flags; }
 	void removeFlags(U32 flags) { mMiscFlags &= ~flags; }
@@ -435,6 +436,9 @@ class LLPrimitive : public LLXform
 	inline static BOOL isPrimitive(const LLPCode pcode);
 	inline static BOOL isApp(const LLPCode pcode);
 
+private:
+	void updateNumBumpmap(const U8 index, const U8 bump);
+
 protected:
 	LLPCode				mPrimitiveCode;		// Primitive code
 	LLVector3			mVelocity;			// how fast are we moving?
@@ -444,6 +448,7 @@ class LLPrimitive : public LLXform
 	LLPrimTextureList	mTextureList;		// list of texture GUIDs, scales, offsets
 	U8					mMaterial;			// Material code
 	U8					mNumTEs;			// # of faces on the primitve	
+	U8                  mNumBumpmapTEs;     // number of bumpmap TEs.
 	U32 				mMiscFlags;			// home for misc bools
 
 public:
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
old mode 100644
new mode 100755
index a84221176435912164d8a0cb63df23664011ad1b..a4d7872ec25e0091152a4da7de8e60f2df09e5ed
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -478,7 +478,7 @@ bool LLImageGL::checkSize(S32 width, S32 height)
 	return check_power_of_two(width) && check_power_of_two(height);
 }
 
-void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
+void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
 {
 	if (width != mWidth || height != mHeight || ncomponents != mComponents)
 	{
@@ -511,6 +511,11 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
 				width >>= 1;
 				height >>= 1;
 			}
+
+			if(discard_level > 0)
+			{
+				mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
+			}
 		}
 		else
 		{
@@ -860,14 +865,13 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
 		llassert(mCurrentDiscardLevel >= 0);
 		discard_level = mCurrentDiscardLevel;
 	}
-	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
-
+	
 	// Actual image width/height = raw image width/height * 2^discard_level
 	S32 w = raw_image->getWidth() << discard_level;
 	S32 h = raw_image->getHeight() << discard_level;
 
 	// setSize may call destroyGLTexture if the size does not match
-	setSize(w, h, raw_image->getComponents());
+	setSize(w, h, raw_image->getComponents(), discard_level);
 
 	if( !mHasExplicitFormat )
 	{
@@ -1264,8 +1268,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
 		llassert(mCurrentDiscardLevel >= 0);
 		discard_level = mCurrentDiscardLevel;
 	}
-	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
-
+	
 	// Actual image width/height = raw image width/height * 2^discard_level
 	S32 raw_w = imageraw->getWidth() ;
 	S32 raw_h = imageraw->getHeight() ;
@@ -1273,7 +1276,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
 	S32 h = raw_h << discard_level;
 
 	// setSize may call destroyGLTexture if the size does not match
-	setSize(w, h, imageraw->getComponents());
+	setSize(w, h, imageraw->getComponents(), discard_level);
 
 	if( !mHasExplicitFormat )
 	{
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
old mode 100644
new mode 100755
index e118c28c1ba2e4a9d26ad2920399f1e9e6a43f4e..cf3c484c79df58a4bbeb17e2b84dd2ffab4a7e4d
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -100,7 +100,7 @@ class LLImageGL : public LLRefCount
 public:
 	virtual void dump();	// debugging info to llinfos
 	
-	void setSize(S32 width, S32 height, S32 ncomponents);
+	void setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
 	void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
 	void setAllowCompression(bool allow) { mAllowCompression = allow; }
 
diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
old mode 100644
new mode 100755
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
old mode 100644
new mode 100755
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
old mode 100644
new mode 100755
index adfab91cd2d9dedf1687412af117205f4763d634..5e42fc29f79769d94397f78347d81edada7e912f
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3269,6 +3269,17 @@
         <string>Boolean</string>
         <key>Value</key>
         <integer>0</integer>
+    </map>
+    <key>FastCacheFetchEnabled</key>
+    <map>
+      <key>Comment</key>
+      <string>Enable texture fast cache fetching if set</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <string>1</string>
     </map>
 	<key>FeatureManagerHTTPTable</key>
       <map>
@@ -10789,6 +10800,83 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>TextureFetchSource</key>
+    <map>
+      <key>Comment</key>
+      <string>Debug use: Source to fetch textures</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>TextureFetchUpdateHighPriority</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of high priority textures to update per frame</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>32</integer>
+    </map>
+    <key>TextureFetchUpdateMaxMediumPriority</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of medium priority textures to update per frame</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>256</integer>
+    </map>
+    <key>TextureFetchUpdateMinMediumPriority</key>
+    <map>
+      <key>Comment</key>
+      <string>Minimum number of medium priority textures to update per frame</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>32</integer>
+    </map>
+    <key>TextureFetchUpdatePriorityThreshold</key>
+    <map>
+      <key>Comment</key>
+      <string>Threshold under which textures will be considered too low priority and skipped for update</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <integer>0.0</integer>
+    </map>
+    <key>TextureFetchUpdateSkipLowPriority</key>
+    <map>
+      <key>Comment</key>
+      <string>Flag indicating if we want to skip textures with too low of a priority</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>TextureFetchUpdatePriorities</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of priority texture to update per frame</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>32</integer>
+    </map>
     <key>TextureLoadFullRes</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f5de4fe3446fb4502f80376193703dd94ad14e83..c9458857d14e8cf46df6a0639cae1526f9978883 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4356,6 +4356,10 @@ void LLAppViewer::idle()
     {
 		return;
     }
+	if (gTeleportDisplay)
+    {
+		return;
+    }
 
 	gViewerWindow->updateUI();
 
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 8d0664770b7167a535b5e1e897e7236e70c883ff..4a0c94df33fa40d789f41c70656774e0901cd19e 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -2167,6 +2167,12 @@ BOOL LLFace::hasMedia() const
 const F32 LEAST_IMPORTANCE = 0.05f ;
 const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
 
+void LLFace::resetVirtualSize()
+{
+	setVirtualSize(0.f);
+	mImportanceToCamera = 0.f;
+}
+
 F32 LLFace::getTextureVirtualSize()
 {
 	F32 radius;
@@ -2232,8 +2238,17 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 	LLVector4a t;
 	t.load3(camera->getOrigin().mV);
 	lookAt.setSub(center, t);
+	
 	F32 dist = lookAt.getLength3().getF32();
-	dist = llmax(dist-size.getLength3().getF32(), 0.f);
+	dist = llmax(dist-size.getLength3().getF32(), 0.001f);
+	//ramp down distance for nearby objects
+	if (dist < 16.f)
+	{
+		dist /= 16.f;
+		dist *= dist;
+		dist *= 16.f;
+	}
+
 	lookAt.normalize3fast() ;	
 
 	//get area of circle around node
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index efc3424858c371891282b14990f988335a6efa83..de4d03351ce39ad319f01bb4ba932065e778ff10 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -218,6 +218,7 @@ class LLFace
 
 	F32         getTextureVirtualSize() ;
 	F32         getImportanceToCamera()const {return mImportanceToCamera ;}
+	void        resetVirtualSize();
 
 	void        setHasMedia(bool has_media)  { mHasMedia = has_media ;}
 	BOOL        hasMedia() const ;
diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp
index 2b34b720557148beb70c7c214cf96a3f9f62f790..91573891877b26dc49cdfad8be8c353e604f714f 100644
--- a/indra/newview/llfloatertexturefetchdebugger.cpp
+++ b/indra/newview/llfloatertexturefetchdebugger.cpp
@@ -59,12 +59,15 @@ LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
 
 	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this));
 	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this));
+	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllCache",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllCache, this));
+	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllHTTP",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP, this));
 }
 //----------------------------------------------
 
 BOOL LLFloaterTextureFetchDebugger::postBuild(void) 
 {	
 	mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger();
+	mStartStatus = (S32)LLTextureFetchDebugger::IDLE;
 
 	//set states for buttons
 	mButtonStateMap["start_btn"] = true;
@@ -76,8 +79,10 @@ BOOL LLFloaterTextureFetchDebugger::postBuild(void)
 	mButtonStateMap["decode_btn"] = false;
 	mButtonStateMap["gl_btn"] = false;
 
-	mButtonStateMap["refetchviscache_btn"] = true;
-	mButtonStateMap["refetchvishttp_btn"] = true;
+	mButtonStateMap["refetchviscache_btn"] = false;
+	mButtonStateMap["refetchvishttp_btn"] = false;
+	mButtonStateMap["refetchallcache_btn"] = false;
+	mButtonStateMap["refetchallhttp_btn"] = false;
 
 	updateButtons();
 
@@ -89,7 +94,7 @@ BOOL LLFloaterTextureFetchDebugger::postBuild(void)
 LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger()
 {
 	//stop everything
-	mDebugger->stopDebug();
+	mDebugger->setStopDebug();
 }
 
 void LLFloaterTextureFetchDebugger::updateButtons()
@@ -118,47 +123,81 @@ void LLFloaterTextureFetchDebugger::disableButtons()
 	childDisable("gl_btn");
 	childDisable("refetchviscache_btn");
 	childDisable("refetchvishttp_btn");
+	childDisable("refetchallcache_btn");
+	childDisable("refetchallhttp_btn");
+}
+void LLFloaterTextureFetchDebugger::setStartStatus(S32 status)
+{
+	llassert_always(LLTextureFetchDebugger::IDLE == (LLTextureFetchDebugger::e_debug_state)mStartStatus) ;
+	mStartStatus = status;
+}
+	
+bool LLFloaterTextureFetchDebugger::idleStart()
+{
+	if(mStartStatus != (S32)LLTextureFetchDebugger::IDLE)
+	{
+		mDebugger->startWork((LLTextureFetchDebugger::e_debug_state)mStartStatus);
+		mStartStatus = (S32)LLTextureFetchDebugger::IDLE;
+		return true;
+	}
+
+	return false;
 }
 
 void LLFloaterTextureFetchDebugger::idle()
 {	
-	LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();
-	
-	if(mDebugger->update())
+	if(idleStart())
+	{
+		return;
+	}
+
+	const F32 max_time = 0.005f; //5ms
+	LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();	
+	if(mDebugger->update(max_time))
 	{
 		switch(state)
 		{
 		case LLTextureFetchDebugger::IDLE:
 			break;
-		case LLTextureFetchDebugger::READ_CACHE:
-			mButtonStateMap["cachewrite_btn"] = true;
-			mButtonStateMap["decode_btn"] = true;
-			updateButtons();
+		case LLTextureFetchDebugger::START_DEBUG:
+			mButtonStateMap["cacheread_btn"] = true;
+			mButtonStateMap["http_btn"] = true;
+			mButtonStateMap["refetchviscache_btn"] = true;
+			mButtonStateMap["refetchvishttp_btn"] = true;
+			mButtonStateMap["refetchallcache_btn"] = true;
+			mButtonStateMap["refetchallhttp_btn"] = true;
 			break;
-		case LLTextureFetchDebugger::WRITE_CACHE:
-			updateButtons();
+		case LLTextureFetchDebugger::READ_CACHE:			
+			mButtonStateMap["decode_btn"] = true;			
+			break;
+		case LLTextureFetchDebugger::WRITE_CACHE:			
 			break;
 		case LLTextureFetchDebugger::DECODING:
-			mButtonStateMap["gl_btn"] = true;
-			updateButtons();
+			mButtonStateMap["gl_btn"] = true;			
 			break;
 		case LLTextureFetchDebugger::HTTP_FETCHING:
 			mButtonStateMap["cacheread_btn"] = true;
 			mButtonStateMap["cachewrite_btn"] = true;
-			mButtonStateMap["decode_btn"] = true;
-			updateButtons();
+			mButtonStateMap["decode_btn"] = true;			
 			break;
-		case LLTextureFetchDebugger::GL_TEX:
-			updateButtons();
+		case LLTextureFetchDebugger::GL_TEX:			
 			break;
-		case LLTextureFetchDebugger::REFETCH_VIS_CACHE:
-			updateButtons();
-		case LLTextureFetchDebugger::REFETCH_VIS_HTTP:
-			updateButtons();
+		case LLTextureFetchDebugger::REFETCH_VIS_CACHE:			
+			break;
+		case LLTextureFetchDebugger::REFETCH_VIS_HTTP:			
+			break;
+		case LLTextureFetchDebugger::REFETCH_ALL_CACHE:			
+			break;
+		case LLTextureFetchDebugger::REFETCH_ALL_HTTP:
 			break;
 		default:
 			break;
 		}
+
+		if(state != LLTextureFetchDebugger::IDLE)
+		{
+			updateButtons();
+		}
 	}
 }
 
@@ -172,11 +211,10 @@ void LLFloaterTextureFetchDebugger::onClickStart()
 {
 	disableButtons();
 
-	mDebugger->startDebug();
+	setStartStatus((S32)LLTextureFetchDebugger::START_DEBUG);	
 
 	mButtonStateMap["start_btn"] = false;
-	mButtonStateMap["cacheread_btn"] = true;
-	mButtonStateMap["http_btn"] = true;
+
 	updateButtons();
 }
 
@@ -185,7 +223,9 @@ void LLFloaterTextureFetchDebugger::onClickClose()
 	setVisible(FALSE);
 	
 	//stop everything
-	mDebugger->stopDebug();
+	mDebugger->setStopDebug();
+
+	delete this;
 }
 
 void LLFloaterTextureFetchDebugger::onClickClear()
@@ -203,7 +243,7 @@ void LLFloaterTextureFetchDebugger::onClickClear()
 	updateButtons();
 
 	//stop everything
-	mDebugger->stopDebug();
+	mDebugger->setStopDebug();
 	mDebugger->clearHistory();
 }
 
@@ -211,49 +251,63 @@ void LLFloaterTextureFetchDebugger::onClickCacheRead()
 {
 	disableButtons();
 
-	mDebugger->debugCacheRead();
+	setStartStatus((S32)LLTextureFetchDebugger::READ_CACHE);
 }
 
 void LLFloaterTextureFetchDebugger::onClickCacheWrite()
 {
 	disableButtons();
 
-	mDebugger->debugCacheWrite();
+	setStartStatus((S32)LLTextureFetchDebugger::WRITE_CACHE);
 }
 
 void LLFloaterTextureFetchDebugger::onClickHTTPLoad()
 {
 	disableButtons();
 
-	mDebugger->debugHTTP();
+	setStartStatus((S32)LLTextureFetchDebugger::HTTP_FETCHING);
 }
 
 void LLFloaterTextureFetchDebugger::onClickDecode()
 {
 	disableButtons();
 
-	mDebugger->debugDecoder();
+	setStartStatus((S32)LLTextureFetchDebugger::DECODING);
 }
 
 void LLFloaterTextureFetchDebugger::onClickGLTexture()
 {
 	disableButtons();
 
-	mDebugger->debugGLTextureCreation();
+	setStartStatus((S32)LLTextureFetchDebugger::GL_TEX);	
 }
 
 void LLFloaterTextureFetchDebugger::onClickRefetchVisCache()
 {
 	disableButtons();
 
-	mDebugger->debugRefetchVisibleFromCache();
+	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_CACHE);
 }
 
 void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP()
 {
 	disableButtons();
 
-	mDebugger->debugRefetchVisibleFromHTTP();
+	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_HTTP);	
+}
+
+void LLFloaterTextureFetchDebugger::onClickRefetchAllCache()
+{
+	disableButtons();
+
+	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_CACHE);
+}
+
+void LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP()
+{
+	disableButtons();
+
+	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_HTTP);	
 }
 
 void LLFloaterTextureFetchDebugger::draw()
@@ -368,8 +422,22 @@ void LLFloaterTextureFetchDebugger::draw()
 	else
 	{
 		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime()));
-		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10));
-		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f));
+		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10));
+		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f));
+	}
+
+	//total time on refetching all textures from cache
+	if(mDebugger->getRefetchAllCacheTime() < 0.f)
+	{
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", std::string("----"));
+	}
+	else
+	{
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllCacheTime()));
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10));
+		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f));
 	}
 
 	//total time on refetching visible textures from http
@@ -382,8 +450,22 @@ void LLFloaterTextureFetchDebugger::draw()
 	else
 	{
 		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime()));
-		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedData() >> 10));
-		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedPixels() / 1000000.f));
+		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10));
+		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f));
+	}
+
+	//total time on refetching all textures from http
+	if(mDebugger->getRefetchAllHTTPTime() < 0.f)
+	{
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", std::string("----"));
+	}
+	else
+	{
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllHTTPTime()));
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10));
+		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f));
 	}
 
 	LLFloater::draw();
diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h
index 33012c6a3dcf67978bd3e49df7fc6173df2ae04c..096ad88e07e5c1520f5fd28e5b1e5526937806ee 100644
--- a/indra/newview/llfloatertexturefetchdebugger.h
+++ b/indra/newview/llfloatertexturefetchdebugger.h
@@ -53,6 +53,8 @@ class LLFloaterTextureFetchDebugger : public LLFloater
 
 	void onClickRefetchVisCache();
 	void onClickRefetchVisHTTP();
+	void onClickRefetchAllCache();
+	void onClickRefetchAllHTTP();
 public:
 	void idle() ;
 
@@ -63,9 +65,12 @@ class LLFloaterTextureFetchDebugger : public LLFloater
 	void updateButtons();
 	void disableButtons();
 
+	void setStartStatus(S32 status);
+	bool idleStart();
 private:	
 	LLTextureFetchDebugger* mDebugger;
 	std::map<std::string, bool> mButtonStateMap;
+	S32 mStartStatus;
 };
 
 #endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
old mode 100644
new mode 100755
index b27eef6464236c766aaa795f1a60d6ed28c52aed..42648b82c2df2c8aa3f64f535f0b5222590a05f9
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -362,6 +362,15 @@ bool idle_startup()
 
 	if ( STATE_FIRST == LLStartUp::getStartupState() )
 	{
+		static bool first_call = true;
+		if (first_call)
+		{
+			// Other phases get handled when startup state changes,
+			// need to capture the initial state as well.
+			LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString());
+			first_call = false;
+		}
+
 		gViewerWindow->showCursor(); 
 		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
 
@@ -2720,9 +2729,10 @@ void LLStartUp::setStartupState( EStartupState state )
 		getStartupStateString() << " to " <<  
 		startupStateToString(state) << LL_ENDL;
 
-	sPhases->stopPhase(getStartupStateString());
+	getPhases().stopPhase(getStartupStateString());
 	gStartupState = state;
-	sPhases->startPhase(getStartupStateString());
+	getPhases().startPhase(getStartupStateString());
+
 	postStartupState();
 }
 
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
old mode 100644
new mode 100755
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 8632890bbbdc7ad0c2aaac46fd38f0c888d566e0..a61e2d5c869fa067ee78d1589fc187c4c0e61c3d 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -50,6 +50,8 @@
 const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE;//1024;
 const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
 const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
+const S32 TEXTURE_FAST_CACHE_ENTRY_OVERHEAD = sizeof(S32) * 4; //w, h, c, level
+const S32 TEXTURE_FAST_CACHE_ENTRY_SIZE = 16 * 16 * 4 + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD;
 
 class LLTextureCacheWorker : public LLWorkerClass
 {
@@ -283,9 +285,12 @@ class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
 	LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
 						 U8* data, S32 datasize, S32 offset,
 						 S32 imagesize, // for writes
+						 LLPointer<LLImageRaw> raw, S32 discardlevel,
 						 LLTextureCache::Responder* responder) 
 			: LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder),
-			mState(INIT)
+			mState(INIT),
+			mRawImage(raw),
+			mRawDiscardLevel(discardlevel)
 	{
 	}
 
@@ -303,6 +308,8 @@ class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
 	};
 
 	e_state mState;
+	LLPointer<LLImageRaw> mRawImage;
+	S32 mRawDiscardLevel;
 };
 
 
@@ -559,6 +566,11 @@ bool LLTextureCacheRemoteWorker::doWrite()
 		if(idx < 0)
 		{
 			idx = mCache->setHeaderCacheEntry(mID, entry, mImageSize, mDataSize); // create the new entry.
+			if(idx >= 0)
+			{
+				//write to the fast cache.
+				llassert_always(mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel));
+			}
 		}
 		else
 		{
@@ -658,6 +670,7 @@ bool LLTextureCacheRemoteWorker::doWrite()
 		// Nothing else to do at that point...
 		done = true;
 	}
+	mRawImage = NULL;
 
 	// Clean up and exit
 	return done;
@@ -744,10 +757,14 @@ LLTextureCache::LLTextureCache(bool threaded)
 	  mWorkersMutex(NULL),
 	  mHeaderMutex(NULL),
 	  mListMutex(NULL),
+	  mFastCacheMutex(NULL),
 	  mHeaderAPRFile(NULL),
 	  mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
 	  mTexturesSizeTotal(0),
-	  mDoPurge(FALSE)
+	  mDoPurge(FALSE),
+	  mFastCachep(NULL),
+	  mFastCachePoolp(NULL),
+	  mFastCachePadBuffer(NULL)
 {
 }
 
@@ -755,6 +772,9 @@ LLTextureCache::~LLTextureCache()
 {
 	clearDeleteList() ;
 	writeUpdatedEntries() ;
+	delete mFastCachep;
+	delete mFastCachePoolp;
+	FREE_MEM(LLImageBase::getPrivatePool(), mFastCachePadBuffer);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -879,15 +899,15 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id)
 //////////////////////////////////////////////////////////////////////////////
 
 //static
-const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
-F32 LLTextureCache::sHeaderCacheVersion = 1.4f;
-U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
+F32 LLTextureCache::sHeaderCacheVersion = 1.7f;
+U32 LLTextureCache::sCacheMaxEntries = 1024 * 1024; //~1 million textures.
 S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
 const char* entries_filename = "texture.entries";
 const char* cache_filename = "texture.cache";
 const char* old_textures_dirname = "textures";
 //change the location of the texture cache to prevent from being deleted by old version viewers.
 const char* textures_dirname = "texturecache";
+const char* fast_cache_filename = "FastCache.cache";
 
 void LLTextureCache::setDirNames(ELLPath location)
 {
@@ -896,6 +916,7 @@ void LLTextureCache::setDirNames(ELLPath location)
 	mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename);
 	mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename);
 	mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
+	mFastCacheFileName =  gDirUtilp->getExpandedFilename(location, textures_dirname, fast_cache_filename);
 }
 
 void LLTextureCache::purgeCache(ELLPath location)
@@ -938,8 +959,8 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
 {
 	llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
 
-	S64 header_size = (max_size * 2) / 10;
-	S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
+	S64 header_size = (max_size / 100) * 36; //0.36 * max_size
+	S64 max_entries = header_size / (TEXTURE_CACHE_ENTRY_SIZE + TEXTURE_FAST_CACHE_ENTRY_SIZE);
 	sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
 	header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE;
 	max_size -= header_size;
@@ -981,6 +1002,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
 	purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
 
 	llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
+	openFastCache(true);
 
 	return max_size; // unused cache space
 }
@@ -1751,7 +1773,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri
 	LLMutexLock lock(&mWorkersMutex);
 	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
 																  NULL, size, offset,
-																  0, responder);
+																  0, NULL, 0, responder);
 	handle_t handle = worker->read();
 	mReaders[handle] = worker;
 	return handle;
@@ -1789,6 +1811,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
 
 LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
 													  U8* data, S32 datasize, S32 imagesize,
+													  LLPointer<LLImageRaw> rawimage, S32 discardlevel,
 													  WriteResponder* responder)
 {
 	if (mReadOnly)
@@ -1807,12 +1830,159 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
 	LLMutexLock lock(&mWorkersMutex);
 	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
 																  data, datasize, 0,
-																  imagesize, responder);
+																  imagesize, rawimage, discardlevel, responder);
 	handle_t handle = worker->write();
 	mWriters[handle] = worker;
 	return handle;
 }
 
+//called in the main thread
+LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& discardlevel)
+{
+	U32 offset;
+	{
+		LLMutexLock lock(&mHeaderMutex);
+		id_map_t::const_iterator iter = mHeaderIDMap.find(id);
+		if(iter == mHeaderIDMap.end())
+		{
+			return NULL; //not in the cache
+		}
+
+		offset = iter->second;
+	}
+	offset *= TEXTURE_FAST_CACHE_ENTRY_SIZE;
+
+	U8* data;
+	S32 head[4];
+	{
+		LLMutexLock lock(&mFastCacheMutex);
+
+		openFastCache();
+
+		mFastCachep->seek(APR_SET, offset);		
+	
+		llassert_always(mFastCachep->read(head, TEXTURE_FAST_CACHE_ENTRY_OVERHEAD) == TEXTURE_FAST_CACHE_ENTRY_OVERHEAD);
+		
+		S32 image_size = head[0] * head[1] * head[2];
+		if(!image_size) //invalid
+		{
+			closeFastCache();
+			return NULL;
+		}
+		discardlevel = head[3];
+		
+		data =  (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), image_size);
+		llassert_always(mFastCachep->read(data, image_size) == image_size);
+		closeFastCache();
+	}
+	LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true);
+
+	return raw;
+}
+
+//return the fast cache location
+bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)
+{
+	//rescale image if needed
+	S32 w, h, c;
+	w = raw->getWidth();
+	h = raw->getHeight();
+	c = raw->getComponents();
+	S32 i = 0 ;
+	
+	while(((w >> i) * (h >> i) * c) > TEXTURE_FAST_CACHE_ENTRY_SIZE - TEXTURE_FAST_CACHE_ENTRY_OVERHEAD)
+	{
+		++i ;
+	}
+		
+	if(i)
+	{
+		w >>= i;
+		h >>= i;
+		if(w * h *c > 0) //valid
+		{
+			LLPointer<LLImageRaw> newraw = new LLImageRaw(raw->getData(), raw->getWidth(), raw->getHeight(), raw->getComponents());
+			newraw->scale(w, h) ;
+			raw = newraw;
+
+			discardlevel += i ;
+		}
+	}
+	
+	//copy data
+	memcpy(mFastCachePadBuffer, &w, sizeof(S32));
+	memcpy(mFastCachePadBuffer + sizeof(S32), &h, sizeof(S32));
+	memcpy(mFastCachePadBuffer + sizeof(S32) * 2, &c, sizeof(S32));
+	memcpy(mFastCachePadBuffer + sizeof(S32) * 3, &discardlevel, sizeof(S32));
+	if(w * h * c > 0) //valid
+	{
+		memcpy(mFastCachePadBuffer + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD, raw->getData(), w * h * c);
+	}
+	S32 offset = id * TEXTURE_FAST_CACHE_ENTRY_SIZE;
+
+	{
+		LLMutexLock lock(&mFastCacheMutex);
+
+		openFastCache();
+
+		mFastCachep->seek(APR_SET, offset);	
+		llassert_always(mFastCachep->write(mFastCachePadBuffer, TEXTURE_FAST_CACHE_ENTRY_SIZE) == TEXTURE_FAST_CACHE_ENTRY_SIZE);
+
+		closeFastCache(true);
+	}
+
+	return true;
+}
+
+void LLTextureCache::openFastCache(bool first_time)
+{
+	if(!mFastCachep)
+	{
+		if(first_time)
+		{
+			if(!mFastCachePadBuffer)
+			{
+				mFastCachePadBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_FAST_CACHE_ENTRY_SIZE);
+			}
+			mFastCachePoolp = new LLVolatileAPRPool();
+			if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp))
+			{
+				mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;				
+			}
+			else
+			{
+				mFastCachep = new LLAPRFile(mFastCacheFileName, APR_CREATE|APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
+			}
+		}
+		else
+		{
+			mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
+		}
+
+		mFastCacheTimer.reset();
+	}
+	return;
+}
+	
+void LLTextureCache::closeFastCache(bool forced)
+{	
+	static const F32 timeout = 10.f ; //seconds
+
+	if(!mFastCachep)
+	{
+		return ;
+	}
+
+	if(!forced && mFastCacheTimer.getElapsedTimeF32() < timeout)
+	{
+		return ;
+	}
+
+	delete mFastCachep;
+	mFastCachep = NULL;
+	return;
+}
+	
 bool LLTextureCache::writeComplete(handle_t handle, bool abort)
 {
 	lockWorkers();
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index dd0cc9b4bd6147b519ab416ed3180508b22a7c95..e3fc957fd264b65651c0ce0fbf9ba65b01b45d1a 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -36,6 +36,7 @@
 
 class LLImageFormatted;
 class LLTextureCacheWorker;
+class LLImageRaw;
 
 class LLTextureCache : public LLWorkerThread
 {
@@ -113,8 +114,9 @@ class LLTextureCache : public LLWorkerThread
 	handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
 						   ReadResponder* responder);
 	bool readComplete(handle_t handle, bool abort);
-	handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize,
+	handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
 						  WriteResponder* responder);
+	LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);
 	bool writeComplete(handle_t handle, bool abort = false);
 	void prioritizeWrite(handle_t handle);
 
@@ -171,12 +173,18 @@ class LLTextureCache : public LLWorkerThread
 	void lockHeaders() { mHeaderMutex.lock(); }
 	void unlockHeaders() { mHeaderMutex.unlock(); }
 	
+	void openFastCache(bool first_time = false);
+	void closeFastCache(bool forced = false);
+	bool writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel);	
+
 private:
 	// Internal
 	LLMutex mWorkersMutex;
 	LLMutex mHeaderMutex;
 	LLMutex mListMutex;
+	LLMutex mFastCacheMutex;
 	LLAPRFile* mHeaderAPRFile;
+	LLVolatileAPRPool* mFastCachePoolp;
 	
 	typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
 	handle_map_t mReaders;
@@ -193,12 +201,17 @@ class LLTextureCache : public LLWorkerThread
 	// HEADERS (Include first mip)
 	std::string mHeaderEntriesFileName;
 	std::string mHeaderDataFileName;
+	std::string mFastCacheFileName;
 	EntriesInfo mHeaderEntriesInfo;
 	std::set<S32> mFreeList; // deleted entries
 	std::set<LLUUID> mLRU;
-	typedef std::map<LLUUID,S32> id_map_t;
+	typedef std::map<LLUUID, S32> id_map_t;
 	id_map_t mHeaderIDMap;
 
+	LLAPRFile*   mFastCachep;
+	LLFrameTimer mFastCacheTimer;
+	U8*          mFastCachePadBuffer;
+
 	// BODIES (TEXTURES minus headers)
 	std::string mTexturesDirName;
 	typedef std::map<LLUUID,S32> size_map_t;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 2ed7488b856015f3d2a4acebc6ca69d2b5d8bb8b..7adf5212c280826476972313a21859dd1836f5f6 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -151,7 +151,7 @@ class LLTextureFetchWorker : public LLWorkerClass
 	/*virtual*/ bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
 	/*virtual*/ void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
 	/*virtual*/ bool deleteOK(); // called from update() (WORK THREAD)
-
+	
 	~LLTextureFetchWorker();
 	// void relese() { --mActiveCount; }
 
@@ -196,6 +196,8 @@ class LLTextureFetchWorker : public LLWorkerClass
 	bool processSimulatorPackets();
 	bool writeToCacheComplete();
 	
+	void removeFromHTTPQueue();
+
 	void lockWorkMutex() { mWorkMutex.lock(); }
 	void unlockWorkMutex() { mWorkMutex.unlock(); }
 
@@ -275,6 +277,8 @@ class LLTextureFetchWorker : public LLWorkerClass
 	S32 mRetryAttempt;
 	S32 mActiveCount;
 	U32 mGetStatus;
+	U32 mHTTPHandle;
+	F32 mDelay;
 	std::string mGetReason;
 	
 	// Work Data
@@ -328,6 +332,7 @@ class HTTPGetResponder : public LLCurl::Responder
 			mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
 		}
 
+		S32 data_size = 0;
 		lldebugs << "HTTP COMPLETE: " << mID << llendl;
 		LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
 		if (worker)
@@ -349,7 +354,7 @@ class HTTPGetResponder : public LLCurl::Responder
 // 				llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
 			}
 			
-			S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success);
+			data_size = worker->callbackHttpGet(channels, buffer, partial, success);
 			
 			if(log_texture_traffic && data_size > 0)
 			{
@@ -359,9 +364,7 @@ class HTTPGetResponder : public LLCurl::Responder
 					gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ;
 				}
 			}
-
-			mFetcher->removeFromHTTPQueue(mID, data_size);
-
+		
 			if (worker->mMetricsStartTime)
 			{
 				LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE,
@@ -376,9 +379,10 @@ class HTTPGetResponder : public LLCurl::Responder
 		}
 		else
 		{
-			mFetcher->removeFromHTTPQueue(mID);
- 			llwarns << "Worker not found: " << mID << llendl;
+			llwarns << "Worker not found: " << mID << llendl;
 		}
+
+		mFetcher->getCurlRequest().completeRequest(data_size);
 	}
 
 	virtual bool followRedir()
@@ -692,10 +696,12 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
 	  mLastPacket(-1),
 	  mTotalPackets(0),
 	  mImageCodec(IMG_CODEC_INVALID),
-	  mMetricsStartTime(0)
+	  mMetricsStartTime(0),
+	  mHTTPHandle(0),
+	  mDelay(-1.f)
 {
 	mCanUseNET = mUrl.empty() ;
-
+	
 	calcWorkPriority();
 	mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;
 // 	llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << llendl;
@@ -726,7 +732,19 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
 	mFormattedImage = NULL;
 	clearPackets();
 	unlockWorkMutex();
-	mFetcher->removeFromHTTPQueue(mID);
+	
+	removeFromHTTPQueue();
+}
+
+void LLTextureFetchWorker::removeFromHTTPQueue()
+{
+	if(mHTTPHandle > 0)
+	{
+		llassert_always(mState == WAIT_HTTP_REQ);
+
+		mFetcher->getCurlRequest().removeRequest(mHTTPHandle);
+		mHTTPHandle = 0;
+	}
 }
 
 void LLTextureFetchWorker::clearPackets()
@@ -824,6 +842,7 @@ void LLTextureFetchWorker::setImagePriority(F32 priority)
 		mImagePriority = priority;
 		calcWorkPriority();
 		U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS);
+		mFetcher->getCurlRequest().updatePriority(mHTTPHandle, mWorkPriority);
 		setPriority(work_priority);
 	}
 }
@@ -851,8 +870,6 @@ void LLTextureFetchWorker::startWork(S32 param)
 // Called from LLWorkerThread::processRequest()
 bool LLTextureFetchWorker::doWork(S32 param)
 {
-	static const F32 FETCHING_TIMEOUT = 120.f;//seconds
-
 	LLMutexLock lock(&mWorkMutex);
 
 	if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED)))
@@ -912,6 +929,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		mCacheWriteHandle = LLTextureCache::nullHandle();
 		mState = LOAD_FROM_TEXTURE_CACHE;
 		mInCache = FALSE;
+		mDelay = -1.f;
 		mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE
 		LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)
 							 << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
@@ -927,7 +945,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			S32 size = mDesiredSize - offset;
 			if (size <= 0)
 			{
-				mState = CACHE_POST;
+				mState = CACHE_POST; //have enough data, will fall to decode
 				return false;
 			}
 			mFileSize = 0;
@@ -944,7 +962,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 																		  offset, size, responder);
 				mCacheReadTimer.reset();
 			}
-			else if (mUrl.empty())
+			else if (mUrl.empty() && mFetcher->canLoadFromCache())
 			{
 				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
 
@@ -953,7 +971,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 																		  offset, size, responder);
 				mCacheReadTimer.reset();
 			}
-			else if(mCanUseHTTP)
+			else if(!mUrl.empty() && mCanUseHTTP)
 			{
 				if (!(mUrl.compare(0, 7, "http://") == 0))
 				{
@@ -981,6 +999,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
 			}
 			else
 			{
+				//
+				//This should never happen
+				//
 				return false;
 			}
 		}
@@ -1020,6 +1041,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL;
 				mState = LOAD_FROM_NETWORK;
 			}
+			
 			// fall through
 			LLTextureFetch::sCacheHitRate.addValue(0.f);
 		}
@@ -1060,7 +1082,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		}
 		if (mCanUseHTTP && !mUrl.empty())
 		{
-			mState = LLTextureFetchWorker::SEND_HTTP_REQ;
+			mState = SEND_HTTP_REQ;
 			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 			if(mWriteToCacheState != NOT_WRITE)
 			{
@@ -1156,17 +1178,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 	{
 		if(mCanUseHTTP)
 		{
-			//NOTE:
-			//control the number of the http requests issued for:
-			//1, not openning too many file descriptors at the same time;
-			//2, control the traffic of http so udp gets bandwidth.
-			//
-			static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 8 ;
-			if(mFetcher->getNumHTTPRequests() > MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE)
-			{
-				return false ; //wait.
-			}
-
 			mFetcher->removeFromNetworkQueue(this, false);
 			
 			S32 cur_size = 0;
@@ -1179,6 +1190,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 					{
 						// We already have all the data, just decode it
 						mLoadedDiscard = mFormattedImage->getDiscardLevel();
+						setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 						mState = DECODE_IMAGE;
 						return false;
 					}
@@ -1209,7 +1221,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 				mState = WAIT_HTTP_REQ;	
 
-				mFetcher->addToHTTPQueue(mID);
 				if (! mMetricsStartTime)
 				{
 					mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
@@ -1221,8 +1232,16 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				// Will call callbackHttpGet when curl request completes
 				std::vector<std::string> headers;
 				headers.push_back("Accept: image/x-j2c");
-				res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize,
-															  new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true));
+				// If we try to fetch the whole file, we set the size to 0 so that we generate the correct curl range request
+				// Note: it looks a bit hacky but we need to limit this (size==0) to mean "whole file" to HTTP only as it messes up UDP fetching
+				if ((offset+mRequestedSize) == MAX_IMAGE_DATA_SIZE)
+				{
+					mRequestedSize = 0;
+				}
+				mHTTPHandle = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, mWorkPriority,
+															  new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset, true), mDelay);
+				mDelay = -1.f; //reset
+				res = true;
 			}
 			if (!res)
 			{
@@ -1263,6 +1282,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 					{
 						mState = INIT ;
 						mCanUseHTTP = false ;
+						mUrl.clear();
 						setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 						return false ;
 					}
@@ -1275,12 +1295,15 @@ bool LLTextureFetchWorker::doWork(S32 param)
 					++mHTTPFailCount;
 					max_attempts = mHTTPFailCount+1; // Keep retrying
 					LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
+					mDelay = 2.0f; //delay 2 second to re-issue the http request
 				}
 				else
 				{
 					const S32 HTTP_MAX_RETRY_COUNT = 3;
 					max_attempts = HTTP_MAX_RETRY_COUNT + 1;
 					++mHTTPFailCount;
+					mDelay = 2.0f; //delay 2 second to re-issue the http request
+
 					llinfos << "HTTP GET failed for: " << mUrl
 							<< " Status: " << mGetStatus << " Reason: '" << mGetReason << "'"
 							<< " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl;
@@ -1288,10 +1311,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 				if (mHTTPFailCount >= max_attempts)
 				{
+					mUrl.clear();
 					if (cur_size > 0)
 					{
 						// Use available data
 						mLoadedDiscard = mFormattedImage->getDiscardLevel();
+						setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 						mState = DECODE_IMAGE;
 						return false; 
 					}
@@ -1304,11 +1329,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
 				}
 				else
 				{
+					setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 					mState = SEND_HTTP_REQ;
 					return false; // retry
 				}
 			}
 			
+			// Clear the url since we're done with the fetch
+			// Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch
+			// next time the texture is requested, even if the data have already been fetched.
+			if(mWriteToCacheState != NOT_WRITE)
+			{
+				mUrl.clear();
+			}
+
 			llassert_always(mBufferSize == cur_size + mRequestedSize);
 			if(!mBufferSize)//no data received.
 			{
@@ -1363,13 +1397,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		}
 		else
 		{
-			if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32())
-			{
-				//timeout, abort.
-				mState = DONE;
-				return true;
-			}
-
+			//
+			//No need to timeout, the responder should be triggered automatically.
+			//
 			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
 			return false;
 		}
@@ -1501,7 +1531,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 		CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
 		mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
 																  mFormattedImage->getData(), datasize,
-																  mFileSize, responder);
+																  mFileSize, mRawImage, mDecodedDiscard, responder);
 		// fall through
 	}
 	
@@ -1689,7 +1719,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
 	S32 data_size = 0 ;
 
 	LLMutexLock lock(&mWorkMutex);
-
+	mHTTPHandle = 0;
 	if (mState != WAIT_HTTP_REQ)
 	{
 		llwarns << "callbackHttpGet for unrequested fetch worker: " << mID
@@ -1713,7 +1743,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
 			mBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size);
 			buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
 			mBufferSize += data_size;
-			if (data_size < mRequestedSize && mRequestedDiscard == 0)
+			if (mRequestedSize == 0)
 			{
 				mHaveAllData = TRUE;
 			}
@@ -1739,6 +1769,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
 	{
 		mRequestedSize = -1; // error
 	}
+	
 	mLoaded = TRUE;
 	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
 
@@ -1862,11 +1893,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mTextureCache(cache),
 	  mImageDecodeThread(imagedecodethread),
 	  mTextureBandwidth(0),
-	  mHTTPTextureBits(0),
-	  mTotalHTTPRequests(0),
 	  mCurlGetRequest(NULL),
 	  mQAMode(qa_mode),
 	  mFetchDebugger(NULL),
+	  mFetchSource(LLTextureFetch::FROM_ALL),
+	  mOriginFetchSource(LLTextureFetch::FROM_ALL),
 	  mFetcherLocked(FALSE)
 {
 	mCurlPOSTRequestCount = 0;
@@ -1877,6 +1908,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	if(LLTextureFetchDebugger::isEnabled())
 	{
 		mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ;
+		mFetchSource = (e_tex_source)gSavedSettings.getS32("TextureFetchSource");
+		if(mFetchSource < 0 && mFetchSource >= INVALID_SOURCE)
+		{
+			mFetchSource = LLTextureFetch::FROM_ALL;
+			gSavedSettings.setS32("TextureFetchSource", 0);
+		}
+		mOriginFetchSource = mFetchSource;
 	}
 }
 
@@ -1946,6 +1984,8 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
 	}
 	else
 	{
+		// If the requester knows nothing about the file, we fetch the smallest
+		// amount of data at the lowest resolution (highest discard level) possible.
 		desired_size = TEXTURE_CACHE_ENTRY_SIZE;
 		desired_discard = MAX_DISCARD_LEVEL;
 	}
@@ -2024,45 +2064,22 @@ void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool c
 	}
 }
 
-// protected
-void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
-{
-	LLMutexLock lock(&mNetworkQueueMutex);
-	mHTTPTextureQueue.insert(id);
-	mTotalHTTPRequests++;
-}
-
-void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size)
-{
-	LLMutexLock lock(&mNetworkQueueMutex);
-	mHTTPTextureQueue.erase(id);
-	mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits	
-}
-
 void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
 {
 	lockQueue() ;
 	LLTextureFetchWorker* worker = getWorkerAfterLock(id);
-	if (worker)
-	{		
-		size_t erased_1 = mRequestMap.erase(worker->mID);
-		unlockQueue() ;
-
-		llassert_always(erased_1 > 0) ;
-
-		removeFromNetworkQueue(worker, cancel);
-		llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
+	unlockQueue() ;
 
-		worker->scheduleDelete();	
-	}
-	else
-	{
-		unlockQueue() ;
-	}
+	removeRequest(worker, cancel);
 }
 
 void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
 {
+	if(!worker)
+	{
+		return;
+	}
+
 	lockQueue() ;
 	size_t erased_1 = mRequestMap.erase(worker->mID);
 	unlockQueue() ;
@@ -2071,9 +2088,28 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
 	removeFromNetworkQueue(worker, cancel);
 	llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
 
+	worker->removeFromHTTPQueue();
 	worker->scheduleDelete();	
 }
 
+void LLTextureFetch::deleteAllRequests()
+{
+	while(1)
+	{
+		lockQueue();
+		if(mRequestMap.empty())
+		{
+			unlockQueue() ;
+			break;
+		}
+
+		LLTextureFetchWorker* worker = mRequestMap.begin()->second;
+		unlockQueue() ;
+
+		removeRequest(worker, true);
+	}
+}
+
 S32 LLTextureFetch::getNumRequests() 
 { 
 	lockQueue() ;
@@ -2083,24 +2119,6 @@ S32 LLTextureFetch::getNumRequests()
 	return size ;
 }
 
-S32 LLTextureFetch::getNumHTTPRequests() 
-{ 
-	mNetworkQueueMutex.lock() ;
-	S32 size = (S32)mHTTPTextureQueue.size(); 
-	mNetworkQueueMutex.unlock() ;
-
-	return size ;
-}
-
-U32 LLTextureFetch::getTotalNumHTTPRequests()
-{
-	mNetworkQueueMutex.lock() ;
-	U32 size = mTotalHTTPRequests ;
-	mNetworkQueueMutex.unlock() ;
-
-	return size ;
-}
-
 // call lockQueue() first!
 LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
 {
@@ -2186,7 +2204,7 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
 	{
 		worker->lockWorkMutex();
 		worker->setImagePriority(priority);
-		worker->unlockWorkMutex();
+		worker->unlockWorkMutex();		
 		res = true;
 	}
 	return res;
@@ -2268,15 +2286,7 @@ S32 LLTextureFetch::update(F32 max_time_ms)
 {
 	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS");
 
-	{
-		mNetworkQueueMutex.lock() ;
-		mMaxBandwidth = band_width ;
-
-		gTextureList.sTextureBits += mHTTPTextureBits ;
-		mHTTPTextureBits = 0 ;
-
-		mNetworkQueueMutex.unlock() ;
-	}
+	mMaxBandwidth = band_width ;
 
 	S32 res = LLWorkerThread::update(max_time_ms);
 	
@@ -2287,13 +2297,28 @@ S32 LLTextureFetch::update(F32 max_time_ms)
 		// won't work so don't bother trying
 		if (LLStartUp::getStartupState() > STATE_AGENT_SEND)
 		{
-			sendRequestListToSimulators();
+			sendRequestListToSimulators();			
 		}
 	}
 
 	if (!mThreaded)
 	{
 		commonUpdate();
+		
+		if(mCurlGetRequest)
+		{
+			mCurlGetRequest->nextRequests();
+		}
+	}
+
+	if(mCurlGetRequest)
+	{
+		gTextureList.sTextureBits += mCurlGetRequest->getTotalReceivedBits();
+	}
+
+	if(mFetchDebugger)
+	{
+		mFetchDebugger->tryToStopDebug(); //check if need to stop debugger.
 	}
 
 	return res;
@@ -2323,7 +2348,7 @@ void LLTextureFetch::shutDownImageDecodeThread()
 void LLTextureFetch::startThread()
 {
 	// Construct mCurlGetRequest from Worker Thread
-	mCurlGetRequest = new LLCurlRequest();
+	mCurlGetRequest = new LLCurlTextureRequest(8);
 	
 	if(mFetchDebugger)
 	{
@@ -2348,6 +2373,8 @@ void LLTextureFetch::threadedUpdate()
 {
 	llassert_always(mCurlGetRequest);
 	
+	mCurlGetRequest->nextRequests();
+
 	// Limit update frequency
 	const F32 PROCESS_TIME = 0.05f; 
 	static LLFrameTimer process_timer;
@@ -3160,6 +3187,7 @@ class LLDebuggerHTTPResponder : public LLCurl::Responder
 			llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl;
 		}
 		mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success);
+		mDebugger->getCurlGetRequest()->completeRequest(0);
 	}
 	virtual bool followRedir()
 	{
@@ -3182,7 +3210,8 @@ LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextur
 LLTextureFetchDebugger::~LLTextureFetchDebugger()
 {
 	mFetchingHistory.clear();
-	stopDebug();
+	mStopDebug = TRUE;
+	tryToStopDebug();
 }
 
 void LLTextureFetchDebugger::init()
@@ -3197,6 +3226,8 @@ void LLTextureFetchDebugger::init()
 	mTotalFetchingTime = 0.f;
 	mRefetchVisCacheTime = -1.f;
 	mRefetchVisHTTPTime = -1.f;
+	mRefetchAllCacheTime = -1.f;
+	mRefetchAllHTTPTime = -1.f;
 
 	mNumFetchedTextures = 0;
 	mNumCacheHits = 0;
@@ -3210,10 +3241,56 @@ void LLTextureFetchDebugger::init()
 	mRenderedDecodedData = 0;
 	mFetchedPixels = 0;
 	mRenderedPixels = 0;
-	mRefetchedData = 0;
-	mRefetchedPixels = 0;
+	mRefetchedVisData = 0;
+	mRefetchedVisPixels = 0;
+	mRefetchedAllData = 0;
+	mRefetchedAllPixels = 0;
 
 	mFreezeHistory = FALSE;
+	mStopDebug = FALSE;
+	mClearHistory = FALSE;
+}
+
+void LLTextureFetchDebugger::startWork(e_debug_state state)
+{
+	switch(state)
+	{
+		case IDLE:
+			break;
+		case START_DEBUG:
+			startDebug();
+			break;
+		case READ_CACHE:			
+			debugCacheRead();
+			break;
+		case WRITE_CACHE:
+			debugCacheWrite();
+			break;
+		case DECODING:
+			debugDecoder();
+			break;
+		case HTTP_FETCHING:
+			debugHTTP();
+			break;
+		case GL_TEX:
+			debugGLTextureCreation();
+			break;
+		case REFETCH_VIS_CACHE:
+			debugRefetchVisibleFromCache();
+			break;
+		case REFETCH_VIS_HTTP:
+			debugRefetchVisibleFromHTTP();
+			break;
+		case REFETCH_ALL_CACHE:
+			debugRefetchAllFromCache();
+			break;
+		case REFETCH_ALL_HTTP:
+			debugRefetchAllFromHTTP();
+			break;
+		default:
+			break;
+	}
+	return;
 }
 
 void LLTextureFetchDebugger::startDebug()
@@ -3221,10 +3298,18 @@ void LLTextureFetchDebugger::startDebug()
 	//lock the fetcher
 	mFetcher->lockFetcher(true);
 	mFreezeHistory = TRUE;
+	mFetcher->resetLoadSource();
 
 	//clear the current fetching queue
 	gTextureList.clearFetchingRequests();
 
+	mState = START_DEBUG;
+}
+
+bool LLTextureFetchDebugger::processStartDebug(F32 max_time)
+{
+	mTimer.reset();
+
 	//wait for all works to be done
 	while(1)
 	{
@@ -3236,6 +3321,11 @@ void LLTextureFetchDebugger::startDebug()
 		{
 			break;
 		}
+
+		if(mTimer.getElapsedTimeF32() > max_time)
+		{
+			return false;
+		}
 	}
 
 	//collect statistics
@@ -3274,10 +3364,17 @@ void LLTextureFetchDebugger::startDebug()
 	}
 
 	mNumFetchedTextures = fetched_textures.size();
+
+	return true;
 }
 
-void LLTextureFetchDebugger::stopDebug()
+void LLTextureFetchDebugger::tryToStopDebug()
 {
+	if(!mStopDebug)
+	{
+		return;
+	}
+
 	//clear the current debug work
 	S32 size = mFetchingHistory.size();
 	switch(mState)
@@ -3306,37 +3403,71 @@ void LLTextureFetchDebugger::stopDebug()
 		break;
 	case GL_TEX:
 		break;
+	case REFETCH_VIS_CACHE:
+		break;
+	case REFETCH_VIS_HTTP:
+		break;
+	case REFETCH_ALL_CACHE:
+		mRefetchList.clear();
+		break;
+	case REFETCH_ALL_HTTP:
+		mRefetchList.clear();
+		break;
 	default:
 		break;
 	}
 
-	while(1)
+	if(update(0.005f))
 	{
-		if(update())
+		//unlock the fetcher
+		mFetcher->lockFetcher(false);
+		mFetcher->resetLoadSource();
+		mFreezeHistory = FALSE;		
+		mStopDebug = FALSE;
+
+		if(mClearHistory)
 		{
-			break;
+			mFetchingHistory.clear();
+			init();	
+			mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset
 		}
 	}
-
-	//unlock the fetcher
-	mFetcher->lockFetcher(false);
-	mFreezeHistory = FALSE;
-	mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32(); //reset
 }
 
 //called in the main thread and when the fetching queue is empty
 void LLTextureFetchDebugger::clearHistory()
 {
-	mFetchingHistory.clear();
-	init();
+	mClearHistory = TRUE;	
 }
 
 void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 {
+	if(worker->mRawImage.isNull() || worker->mFormattedImage.isNull())
+	{
+		return;
+	}
+
 	if(mFreezeHistory)
 	{
-		mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
-		mRefetchedData += worker->mFormattedImage->getDataSize();
+		if(mState == REFETCH_VIS_CACHE || mState == REFETCH_VIS_HTTP)
+		{
+			mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
+			mRefetchedVisData += worker->mFormattedImage->getDataSize();
+		}
+		else
+		{
+			mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
+			mRefetchedAllData += worker->mFormattedImage->getDataSize();
+
+			LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID);
+			if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end())
+			{
+				if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel)
+				{
+					mRefetchList[tex].erase(mRefetchList[tex].begin());
+				}
+			}
+		}
 		return;
 	}
 
@@ -3348,9 +3479,8 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 	mDecodedData += worker->mRawImage->getDataSize();
 	mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
 
-	mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
-	//mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(),
-		//worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
+	mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, 
+		worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
 }
 
 void LLTextureFetchDebugger::lockCache()
@@ -3367,6 +3497,7 @@ void LLTextureFetchDebugger::debugCacheRead()
 	llassert_always(mState == IDLE);
 	mTimer.reset();
 	mState = READ_CACHE;
+	mCacheReadTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
@@ -3402,6 +3533,7 @@ void LLTextureFetchDebugger::debugCacheWrite()
 	llassert_always(mState == IDLE);
 	mTimer.reset();
 	mState = WRITE_CACHE;
+	mCacheWriteTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
@@ -3411,7 +3543,7 @@ void LLTextureFetchDebugger::debugCacheWrite()
 			mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 
 				mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize,
 				mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1, 
-				new LLDebuggerCacheWriteResponder(this, i));					
+				NULL, 0, new LLDebuggerCacheWriteResponder(this, i));					
 		}
 	}
 }
@@ -3430,6 +3562,7 @@ void LLTextureFetchDebugger::debugDecoder()
 	llassert_always(mState == IDLE);
 	mTimer.reset();
 	mState = DECODING;
+	mDecodingTime = -1.f;
 
 	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
@@ -3465,6 +3598,7 @@ void LLTextureFetchDebugger::debugHTTP()
 	
 	mTimer.reset();
 	mState = HTTP_FETCHING;
+	mHTTPTime = -1.f;
 	
 	S32 size = mFetchingHistory.size();
 	for (S32 i = 0 ; i < size ; i++)
@@ -3481,14 +3615,28 @@ void LLTextureFetchDebugger::debugHTTP()
 
 S32 LLTextureFetchDebugger::fillCurlQueue()
 {
-	if (mNbCurlRequests == 24)
-		return mNbCurlRequests;
-	
+	if(mStopDebug) //stop
+	{
+		mNbCurlCompleted = mFetchingHistory.size();
+		return 0;
+	}
 	S32 size = mFetchingHistory.size();
+
+	if (mNbCurlRequests == size) //all issued
+	{
+		return 0;
+	}	
+	
+	S32 counter = 8;
+	mNbCurlRequests = 0;
 	for (S32 i = 0 ; i < size ; i++)
 	{		
+		mNbCurlRequests++;
+
 		if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE)
+		{
 			continue;
+		}
 		std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str();
 		S32 requestedSize = mFetchingHistory[i].mRequestedSize;
 		// We request the whole file if the size was not set.
@@ -3497,16 +3645,11 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
 		requestedSize = (requestedSize == 33554432 ? 0 : requestedSize);
 		std::vector<std::string> headers;
 		headers.push_back("Accept: image/x-j2c");
-		bool res = mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, new LLDebuggerHTTPResponder(this, i));
-		if (res)
-		{
-			mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
-			mNbCurlRequests++;
-			// Hack
-			if (mNbCurlRequests == 24)
-				break;
-		}
-		else 
+		mCurlGetRequest->getByteRange(texture_url, headers, 0, requestedSize, 0x10000, new LLDebuggerHTTPResponder(this, i));
+		
+		mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
+		counter--;
+		if(counter < 1)
 		{
 			break;
 		}
@@ -3519,7 +3662,7 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
 {
 	llassert_always(mState == IDLE);
 	mState = GL_TEX;
-	std::vector<LLViewerFetchedTexture*> tex_list;
+	mTempTexList.clear();
 
 	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
@@ -3530,28 +3673,54 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
 			if(tex && !tex->isForSculptOnly())
 			{
 				tex->destroyGLTexture() ;
-				tex_list.push_back(tex);
+				mTempTexList.push_back(tex);
 			}
 		}
 	}
+	
+	mGLCreationTime = -1.f;
+	mTempIndex = 0;
+	mHistoryListIndex = 0;
+	
+	return;
+}
 
+bool LLTextureFetchDebugger::processGLCreation(F32 max_time)
+{
 	mTimer.reset();
-	S32 j = 0 ;
-	S32 size1 = tex_list.size();
-	for(S32 i = 0 ; i < size && j < size1; i++)
+
+	bool done = true;
+	S32 size = mFetchingHistory.size();
+	S32 size1 = mTempTexList.size();
+	for(; mHistoryListIndex < size && mTempIndex < size1; mHistoryListIndex++)
 	{
-		if(mFetchingHistory[i].mRawImage.notNull())
+		if(mFetchingHistory[mHistoryListIndex].mRawImage.notNull())
 		{
-			if(mFetchingHistory[i].mID == tex_list[j]->getID())
+			if(mFetchingHistory[mHistoryListIndex].mID == mTempTexList[mTempIndex]->getID())
 			{
-				tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel());
-				j++;
+				mTempTexList[mTempIndex]->createGLTexture(mFetchingHistory[mHistoryListIndex].mDecodedLevel, 
+					mFetchingHistory[mHistoryListIndex].mRawImage, 0, TRUE, mTempTexList[mTempIndex]->getBoostLevel());
+				mTempIndex++;
 			}
 		}
+
+		if(mTimer.getElapsedTimeF32() > max_time)
+		{
+			done = false;
+			break;
+		}
 	}
 
-	mGLCreationTime = mTimer.getElapsedTimeF32() ;
-	return;
+	if(mGLCreationTime < 0.f)
+	{
+		mGLCreationTime = mTimer.getElapsedTimeF32() ;
+	}
+	else
+	{
+		mGLCreationTime += mTimer.getElapsedTimeF32() ;
+	}
+
+	return done;
 }
 
 //clear fetching results of all textures.
@@ -3568,15 +3737,62 @@ void LLTextureFetchDebugger::clearTextures()
 	}
 }
 
+void LLTextureFetchDebugger::makeRefetchList()
+{
+	mRefetchList.clear();
+	S32 size = mFetchingHistory.size();
+	for(S32 i = 0 ; i < size; i++)
+	{		
+		LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(mFetchingHistory[i].mID);
+		if(tex && tex->isJustBound()) //visible
+		{
+			continue; //the texture fetch pipeline will take care of visible textures.
+		}
+
+		mRefetchList[tex].push_back(i); 		
+	}
+}
+
+void LLTextureFetchDebugger::scanRefetchList()
+{
+	if(mStopDebug)
+	{
+		return;
+	}
+	if(!mRefetchNonVis)
+	{
+		return;
+	}
+
+	for(std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> >::iterator iter = mRefetchList.begin();
+		iter != mRefetchList.end(); )
+	{
+		if(iter->second.empty())
+		{
+			gTextureList.setDebugFetching(iter->first, -1);
+			mRefetchList.erase(iter++);		// This is the correct method to "erase and move on" in an std::map
+		}
+		else
+		{
+			gTextureList.setDebugFetching(iter->first, mFetchingHistory[iter->second[0]].mDecodedLevel);
+			++iter;
+		}
+	}
+}
+
 void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
 {
 	llassert_always(mState == IDLE);
 	mState = REFETCH_VIS_CACHE;
 
 	clearTextures();
-
+	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
+	
 	mTimer.reset();
 	mFetcher->lockFetcher(false);
+	mRefetchVisCacheTime = -1.f;
+	mRefetchedVisData = 0;
+	mRefetchedVisPixels = 0;
 }
 
 void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
@@ -3584,17 +3800,60 @@ void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
 	llassert_always(mState == IDLE);
 	mState = REFETCH_VIS_HTTP;
 
-	clearCache();
 	clearTextures();
+	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
+
+	mTimer.reset();
+	mFetcher->lockFetcher(false);
+	mRefetchVisHTTPTime = -1.f;
+	mRefetchedVisData = 0;
+	mRefetchedVisPixels = 0;
+}
+
+void LLTextureFetchDebugger::debugRefetchAllFromCache()
+{
+	llassert_always(mState == IDLE);
+	mState = REFETCH_ALL_CACHE;
+
+	clearTextures();
+	makeRefetchList();
+	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL);
+
+	mTimer.reset();
+	mFetcher->lockFetcher(false);
+	mRefetchAllCacheTime = -1.f;
+	mRefetchedAllData = 0;
+	mRefetchedAllPixels = 0;
+	mRefetchNonVis = FALSE;
+}
+
+void LLTextureFetchDebugger::debugRefetchAllFromHTTP()
+{
+	llassert_always(mState == IDLE);
+	mState = REFETCH_ALL_HTTP;
+
+	clearTextures();
+	makeRefetchList();
+	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY);
 
 	mTimer.reset();
 	mFetcher->lockFetcher(false);
+	mRefetchAllHTTPTime = -1.f;
+	mRefetchedAllData = 0;
+	mRefetchedAllPixels = 0;
+	mRefetchNonVis = TRUE;
 }
 
-bool LLTextureFetchDebugger::update()
+bool LLTextureFetchDebugger::update(F32 max_time)
 {
 	switch(mState)
 	{
+	case START_DEBUG:
+		if(processStartDebug(max_time))
+		{
+			mState = IDLE;
+		}
+		break;
 	case READ_CACHE:
 		if(!mTextureCache->update(1))
 		{
@@ -3621,6 +3880,7 @@ bool LLTextureFetchDebugger::update()
 		break;
 	case HTTP_FETCHING:
 		mCurlGetRequest->process();
+		mCurlGetRequest->nextRequests();
 		LLCurl::getCurlThread()->update(1);
 		if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
 		{
@@ -3629,22 +3889,59 @@ bool LLTextureFetchDebugger::update()
 		}
 		break;
 	case GL_TEX:
-		mState = IDLE;
+		if(processGLCreation(max_time))
+		{
+			mState = IDLE;
+			mTempTexList.clear();
+		}
 		break;
 	case REFETCH_VIS_CACHE:
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
-			mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+			mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ;
 			mState = IDLE;
 			mFetcher->lockFetcher(true);
+			mFetcher->resetLoadSource();
 		}
 		break;
 	case REFETCH_VIS_HTTP:
 		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
 		{
-			mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+			mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ;
+			mState = IDLE;
+			mFetcher->lockFetcher(true);
+			mFetcher->resetLoadSource();
+		}
+		break;
+	case REFETCH_ALL_CACHE:
+		scanRefetchList();
+		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+		{
+			if(!mRefetchNonVis)
+			{
+				mRefetchNonVis = TRUE; //start to fetch non-vis
+				scanRefetchList();
+				break;
+			}
+
+			mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ;
+			mState = IDLE; 
+			mFetcher->lockFetcher(true);
+			mFetcher->resetLoadSource();
+			mRefetchList.clear();
+			mRefetchNonVis = FALSE;
+		}
+		break;
+	case REFETCH_ALL_HTTP:
+		scanRefetchList();
+		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+		{
+			mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ;
 			mState = IDLE;
 			mFetcher->lockFetcher(true);
+			mFetcher->resetLoadSource();
+			mRefetchList.clear();
+			mRefetchNonVis = FALSE;
 		}
 		break;
 	default:
@@ -3685,7 +3982,6 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
 										  const LLIOPipe::buffer_ptr_t& buffer, 
 										  bool partial, bool success)
 {
-	mNbCurlRequests--;
 	if (success)
 	{
 		mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
@@ -3699,7 +3995,7 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
 			U8* d_buffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), data_size);
 			buffer->readAfter(channels.in(), NULL, d_buffer, data_size);
 			
-			llassert_always(mFetchingHistory[id].mFormattedImage.isNull());
+			mFetchingHistory[id].mFormattedImage = NULL;
 			{
 				// For now, create formatted image based on extension
 				std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str();
@@ -3721,6 +4017,7 @@ void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& ch
 		{
 			// Fetch will have to be redone
 			mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE;
+			mNbCurlRequests--;	
 		}
 		else //skip
 		{
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 107e1623b0167dafe7eff655a5fb95b8cfba66f8..f5072a79f16dc9ef566bfd9608f0615b0fb5215a 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -65,6 +65,7 @@ class LLTextureFetch : public LLWorkerThread
 	bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
 					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
 	void deleteRequest(const LLUUID& id, bool cancel);
+	void deleteAllRequests();
 	bool getRequestFinished(const LLUUID& id, S32& discard_level,
 							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
 	bool updateRequestPriority(const LLUUID& id, F32 priority);
@@ -81,8 +82,6 @@ class LLTextureFetch : public LLWorkerThread
 					  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http);
 	void dump();
 	S32 getNumRequests() ;
-	S32 getNumHTTPRequests() ;
-	U32 getTotalNumHTTPRequests() ;
 	
 	// Public for access by callbacks
     S32 getPending();
@@ -101,7 +100,7 @@ class LLTextureFetch : public LLWorkerThread
 							LLViewerAssetStats * main_stats);
 	void commandDataBreak();
 
-	LLCurlRequest & getCurlRequest()	{ return *mCurlGetRequest; }
+	LLCurlTextureRequest & getCurlRequest()	{ return *mCurlGetRequest; }
 
 	bool isQAMode() const				{ return mQAMode; }
 
@@ -113,7 +112,6 @@ class LLTextureFetch : public LLWorkerThread
 	void addToNetworkQueue(LLTextureFetchWorker* worker);
 	void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
 	void addToHTTPQueue(const LLUUID& id);
-	void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0);
 	void removeRequest(LLTextureFetchWorker* worker, bool cancel);
 
 	// Overrides from the LLThread tree
@@ -172,8 +170,8 @@ class LLTextureFetch : public LLWorkerThread
 
 	LLTextureCache* mTextureCache;
 	LLImageDecodeThread* mImageDecodeThread;
-	LLCurlRequest* mCurlGetRequest;
-	
+	LLCurlTextureRequest* mCurlGetRequest;
+
 	// Map of all requests by UUID
 	typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
 	map_t mRequestMap;
@@ -188,11 +186,6 @@ class LLTextureFetch : public LLWorkerThread
 	F32 mMaxBandwidth;
 	LLTextureInfo mTextureInfo;
 
-	U32 mHTTPTextureBits;
-
-	//debug use
-	U32 mTotalHTTPRequests ;
-
 	// Out-of-band cross-thread command queue.  This command queue
 	// is logically tied to LLQueuedThread's list of
 	// QueuedRequest instances and so must be covered by the
@@ -216,18 +209,34 @@ class LLTextureFetch : public LLWorkerThread
 	// reporting due to either startup or a problem POSTing data.
 	static volatile bool svMetricsDataBreak;
 
+public:
+	//debug use
+	enum e_tex_source
+	{
+		FROM_ALL = 0,
+		FROM_HTTP_ONLY,
+		INVALID_SOURCE
+	};
 private:
 	//debug use
 	LLTextureFetchDebugger* mFetchDebugger;
 	bool mFetcherLocked;
+	
+	e_tex_source mFetchSource;
+	e_tex_source mOriginFetchSource;
 
 public:
 	//debug use
 	LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
 	void lockFetcher(bool lock) { mFetcherLocked = lock;}
+
+	void setLoadSource(e_tex_source source) {mFetchSource = source;}
+	void resetLoadSource() {mFetchSource = mOriginFetchSource;}
+	bool canLoadFromCache() { return mFetchSource != FROM_HTTP_ONLY;}
 };
 
 //debug use
+class LLViewerFetchedTexture;
 class LLTextureFetchDebugger
 {
 	friend class LLTextureFetch;
@@ -239,6 +248,7 @@ class LLTextureFetchDebugger
 	enum e_debug_state
 	{
 		IDLE = 0,
+		START_DEBUG,
 		READ_CACHE,
 		WRITE_CACHE,
 		DECODING,
@@ -301,13 +311,15 @@ class LLTextureFetchDebugger
 	F32 mTotalFetchingTime;
 	F32 mRefetchVisCacheTime;
 	F32 mRefetchVisHTTPTime;
+	F32 mRefetchAllCacheTime;
+	F32 mRefetchAllHTTPTime;
 
 	LLTimer mTimer;
 	
 	LLTextureFetch* mFetcher;
 	LLTextureCache* mTextureCache;
 	LLImageDecodeThread* mImageDecodeThread;
-	LLCurlRequest* mCurlGetRequest;
+	LLCurlTextureRequest* mCurlGetRequest;
 	
 	S32 mNumFetchedTextures;
 	S32 mNumCacheHits;
@@ -321,34 +333,39 @@ class LLTextureFetchDebugger
 	U32 mRenderedDecodedData;
 	U32 mFetchedPixels;
 	U32 mRenderedPixels;
-	U32 mRefetchedData;
-	U32 mRefetchedPixels;
+	U32 mRefetchedVisData;
+	U32 mRefetchedVisPixels;
+	U32 mRefetchedAllData;
+	U32 mRefetchedAllPixels;
 
 	BOOL mFreezeHistory;
+	BOOL mStopDebug;
+	BOOL mClearHistory;
+	BOOL mRefetchNonVis;
 
 	std::string mHTTPUrl;
 	S32 mNbCurlRequests;
 	S32 mNbCurlCompleted;
 
+	std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList;
+	std::vector< LLPointer<LLViewerFetchedTexture> > mTempTexList;
+	S32 mTempIndex;
+	S32 mHistoryListIndex;
+
 public:
-	bool update(); //called in the main thread once per frame
+	bool update(F32 max_time); //called in the main thread once per frame
 
 	//fetching history
 	void clearHistory();
 	void addHistoryEntry(LLTextureFetchWorker* worker);
 	
-	void setCurlGetRequest(LLCurlRequest* request) { mCurlGetRequest = request;}
-	
-	void startDebug();
-	void stopDebug(); //stop everything
-	void debugCacheRead();
-	void debugCacheWrite();	
-	void debugHTTP();
-	void debugDecoder();
-	void debugGLTextureCreation();
-	void debugRefetchVisibleFromCache();
-	void debugRefetchVisibleFromHTTP();
+	void setCurlGetRequest(LLCurlTextureRequest* request) { mCurlGetRequest = request;}
+	LLCurlTextureRequest* getCurlGetRequest() { return mCurlGetRequest;}
 
+	void startWork(e_debug_state state);
+	void setStopDebug() {mStopDebug = TRUE;}
+	void tryToStopDebug(); //stop everything
+	
 	void callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
 						   S32 imagesize, BOOL islocal);
 	void callbackCacheWrite(S32 id, bool success);
@@ -372,8 +389,10 @@ class LLTextureFetchDebugger
 	U32  getRenderedDecodedData()        {return mRenderedDecodedData;}
 	U32  getFetchedPixels()              {return mFetchedPixels;}
 	U32  getRenderedPixels()             {return mRenderedPixels;}
-	U32  getRefetchedData()              {return mRefetchedData;}
-	U32  getRefetchedPixels()            {return mRefetchedPixels;}
+	U32  getRefetchedVisData()              {return mRefetchedVisData;}
+	U32  getRefetchedVisPixels()            {return mRefetchedVisPixels;}
+	U32  getRefetchedAllData()              {return mRefetchedAllData;}
+	U32  getRefetchedAllPixels()            {return mRefetchedAllPixels;}
 
 	F32  getCacheReadTime()     {return mCacheReadTime;}
 	F32  getCacheWriteTime()    {return mCacheWriteTime;}
@@ -383,11 +402,15 @@ class LLTextureFetchDebugger
 	F32  getTotalFetchingTime() {return mTotalFetchingTime;}
 	F32  getRefetchVisCacheTime() {return mRefetchVisCacheTime;}
 	F32  getRefetchVisHTTPTime()  {return mRefetchVisHTTPTime;}
+	F32  getRefetchAllCacheTime() {return mRefetchAllCacheTime;}
+	F32  getRefetchAllHTTPTime()  {return mRefetchAllHTTPTime;}
 
 private:
 	void init();
 	void clearTextures();//clear fetching results of all textures.
 	void clearCache();
+	void makeRefetchList();
+	void scanRefetchList();
 
 	void lockFetcher();
 	void unlockFetcher();
@@ -400,6 +423,20 @@ class LLTextureFetchDebugger
 	
 	S32 fillCurlQueue();
 
+	void startDebug();
+	void debugCacheRead();
+	void debugCacheWrite();	
+	void debugHTTP();
+	void debugDecoder();
+	void debugGLTextureCreation();
+	void debugRefetchVisibleFromCache();
+	void debugRefetchVisibleFromHTTP();
+	void debugRefetchAllFromCache();
+	void debugRefetchAllFromHTTP();
+
+	bool processStartDebug(F32 max_time);
+	bool processGLCreation(F32 max_time);
+
 private:
 	static bool sDebuggerEnabled;
 public:
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
old mode 100644
new mode 100755
index 52d085dd2cf946231e48226413909e593d6d7e37..c60b4155a0c44e0c6d7d3307eb3334a200c74e5e
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -514,7 +514,7 @@ void LLGLTexMemBar::draw()
 	S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
 	F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
 	F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
-	U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
+	U32 total_http_requests = LLAppViewer::getTextureFetch()->getCurlRequest().getTotalIssuedRequests() ;
 	//----------------------------------------------------------------------------
 	LLGLSUIDefault gls_ui;
 	LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
@@ -552,7 +552,7 @@ void LLGLTexMemBar::draw()
 					LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
 					LLLFSThread::sLocal->getPending(),
 					LLImageRaw::sRawImageCount,
-					LLAppViewer::getTextureFetch()->getNumHTTPRequests(),
+					LLAppViewer::getTextureFetch()->getCurlRequest().getNumRequests(),
 					LLAppViewer::getImageDecodeThread()->getPending(), 
 					gTextureList.mCreateTextureList.size());
 
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
old mode 100644
new mode 100755
index 8fef13a6bc0cd10d9b72c023ea7adfe3b81de516..d1c6b7ea7913419608a6e1696e1c796b78dd1d17
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -949,15 +949,8 @@ LLSD LLViewerStats::PhaseMap::dumpPhases()
 	for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter)
 	{
 		const std::string& phase_name = iter->first;
-		result[phase_name]["completed"] = !(iter->second.getStarted());
+		result[phase_name]["completed"] = LLSD::Integer(!(iter->second.getStarted()));
 		result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32();
-#if 0 // global stats for each phase seem like overkill here
-		phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name);
-		if (stats_iter != sPhaseStats.end())
-		{
-			result[phase_name]["stats"] = stats_iter->second.getData();
-		}
-#endif
 	}
 	return result;
 }
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e1eb54bd240c216fe60e1a83acd170caae11251a..8eb8717de2d49edc3947a4e2f4cec190a68aa04f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -62,6 +62,7 @@
 #include "llmediaentry.h"
 #include "llvovolume.h"
 #include "llviewermedia.h"
+#include "lltexturecache.h"
 ///////////////////////////////////////////////////////////////////////////////
 
 // statics
@@ -409,7 +410,11 @@ void LLViewerTextureManager::cleanup()
 void LLViewerTexture::initClass()
 {
 	LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
-	sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
+	
+	if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"))
+	{
+		sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
+	}
 }
 
 // static
@@ -1236,7 +1241,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mIsMissingAsset = FALSE;
 
 	mLoadedCallbackDesiredDiscardLevel = S8_MAX;
-	mPauseLoadedCallBacks = TRUE ;
+	mPauseLoadedCallBacks = FALSE ;
 
 	mNeedsCreateTexture = FALSE;
 	
@@ -1253,6 +1258,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mRequestDeltaTime = 0.f;
 	mForSculpt = FALSE ;
 	mIsFetched = FALSE ;
+	mInFastCacheList = FALSE;
 
 	mCachedRawImage = NULL ;
 	mCachedRawDiscardLevel = -1 ;
@@ -1266,6 +1272,8 @@ void LLViewerFetchedTexture::init(bool firstinit)
 	mLastReferencedSavedRawImageTime = 0.0f ;
 	mKeptSavedRawImageTime = 0.f ;
 	mLastCallBackActiveTime = 0.f;
+
+	mInDebug = FALSE;
 }
 
 LLViewerFetchedTexture::~LLViewerFetchedTexture()
@@ -1310,14 +1318,47 @@ void LLViewerFetchedTexture::cleanup()
 	mSavedRawDiscardLevel = -1;
 }
 
+//access the fast cache
+void LLViewerFetchedTexture::loadFromFastCache()
+{
+	if(!mInFastCacheList)
+	{
+		return; //no need to access the fast cache.
+	}
+	mInFastCacheList = FALSE;
+
+	mRawImage = LLAppViewer::getTextureCache()->readFromFastCache(getID(), mRawDiscardLevel) ;
+	if(mRawImage.notNull())
+	{
+		mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
+		mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
+		setTexelsPerImage();
+
+		if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
+		{ 
+			//discard all oversized textures.
+			destroyRawImage();
+			setIsMissingAsset();
+			mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
+		}
+		else
+		{
+			mRequestedDiscardLevel = mDesiredDiscardLevel + 1;
+			mIsRawImageValid = TRUE;			
+			addToCreateTexture() ;
+		}
+	}
+}
+
 void LLViewerFetchedTexture::setForSculpt()
 {
 	static const S32 MAX_INTERVAL = 8 ; //frames
 
 	mForSculpt = TRUE ;
-	if(isForSculptOnly() && !getBoundRecently())
+	if(isForSculptOnly() && hasGLTexture() && !getBoundRecently())
 	{
 		destroyGLTexture() ; //sculpt image does not need gl texture.
+		mTextureState = ACTIVE;
 	}
 	checkCachedRawSculptImage() ;
 	setMaxVirtualSizeResetInterval(MAX_INTERVAL) ;
@@ -1735,7 +1776,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
 		S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
 		ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
 		priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
-		setAdditionalDecodePriority(1.0f) ;//boost the textures without any data so far.
+		setAdditionalDecodePriority(0.1f) ;//boost the textures without any data so far.
 	}
 	else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
 	{
@@ -1836,8 +1877,6 @@ F32 LLViewerFetchedTexture::maxDecodePriority()
 
 void LLViewerFetchedTexture::setDecodePriority(F32 priority)
 {
-	llassert(!mInImageList); 
-    
 	mDecodePriority = priority;
 
 	if(mDecodePriority < F_ALMOST_ZERO)
@@ -1898,6 +1937,20 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
 	return current_discard ;
 }
 
+bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level)
+{
+	if(debug_level < 0)
+	{
+		mInDebug = FALSE;
+		return false;
+	}
+	mInDebug = TRUE;
+
+	mDesiredDiscardLevel = debug_level;	
+
+	return true;
+}
+
 bool LLViewerFetchedTexture::updateFetch()
 {
 	static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
@@ -1935,6 +1988,10 @@ bool LLViewerFetchedTexture::updateFetch()
 	{
 		return false; // process any raw image data in callbacks before replacing
 	}
+	if(mInFastCacheList)
+	{
+		return false;
+	}
 	
 	S32 current_discard = getCurrentDiscardLevelForFetching() ;
 	S32 desired_discard = getDesiredDiscardLevel();
@@ -2052,6 +2109,10 @@ bool LLViewerFetchedTexture::updateFetch()
 	{
 		make_request = false;
 	}
+	else if(mDesiredDiscardLevel > getMaxDiscardLevel())
+	{
+		make_request = false;
+	}
 	else if (mNeedsCreateTexture || mIsMissingAsset)
 	{
 		make_request = false;
@@ -2060,6 +2121,11 @@ bool LLViewerFetchedTexture::updateFetch()
 	{
 		make_request = false;
 	}
+	else if(mCachedRawImage.notNull() && (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
+	{
+		make_request = false;
+		switchToCachedImage() ; //use the cached raw data first
+	}
 	//else if (!isJustBound() && mCachedRawImageReady)
 	//{
 	//	make_request = false;
@@ -2152,7 +2218,10 @@ bool LLViewerFetchedTexture::updateFetch()
 
 void LLViewerFetchedTexture::clearFetchedResults()
 {
-	llassert_always(!mNeedsCreateTexture && !mIsFetching);
+	if(mNeedsCreateTexture || mIsFetching)
+	{
+		return ;
+	}
 	
 	cleanup();
 	destroyGLTexture();
@@ -2167,11 +2236,13 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
 {
 	if (mHasFetcher)
 	{
-		LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
 		mHasFetcher = FALSE;
 		mIsFetching = FALSE ;
-		resetTextureStats();
 	}
+		
+	resetTextureStats();
+
+	mDesiredDiscardLevel = getMaxDiscardLevel() + 1;
 }
 
 void LLViewerFetchedTexture::setIsMissingAsset()
@@ -2215,10 +2286,18 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
 		mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ;
 	}
 
-	if(mPauseLoadedCallBacks && !pause)
+	if(mPauseLoadedCallBacks)
+	{
+		if(!pause)
+		{
+			unpauseLoadedCallbacks(src_callback_list) ;
+		}
+	}
+	else if(pause)
 	{
-		unpauseLoadedCallbacks(src_callback_list) ;
+		pauseLoadedCallbacks(src_callback_list) ;
 	}
+
 	LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause);
 	mLoadedCallbackList.push_back(entryp);	
 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
old mode 100644
new mode 100755
index f1105c3705e652294581a7391e3dae0d82a29aa9..2ea9a07e9a1acff51c8d7406d6294859ad5bf021
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -436,6 +436,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	void setMinDiscardLevel(S32 discard) 	{ mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
 
 	bool updateFetch();
+	bool setDebugFetching(S32 debug_level);
+	bool isInDebug() {return mInDebug;}
 	
 	void clearFetchedResults(); //clear all fetched results, for debug use.
 
@@ -498,6 +500,9 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	void        setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}
 
 	void        forceToDeleteRequest();
+	void        loadFromFastCache();
+	void        setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }
+	bool        isInFastCacheList() { return mInFastCacheList; }
 protected:
 	/*virtual*/ void switchToCachedImage();
 	S32 getCurrentDiscardLevelForFetching() ;
@@ -516,6 +521,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 
 private:
 	BOOL  mFullyLoaded;
+	BOOL  mInDebug;
+	BOOL  mInFastCacheList;
 
 protected:		
 	std::string mLocalFileName;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 9a6c0569a996056846df55a8769e6263f7edfcd4..e4669cde345f0b89a34c0d32679181a386fb9467 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -58,7 +58,7 @@
 #include "pipeline.h"
 #include "llappviewer.h"
 #include "llxuiparser.h"
-#include "llagent.h"
+#include "llviewerdisplay.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -276,6 +276,7 @@ void LLViewerTextureList::shutdown()
 	// Flush all of the references
 	mLoadingStreamList.clear();
 	mCreateTextureList.clear();
+	mFastCacheList.clear();
 	
 	mUUIDMap.clear();
 	
@@ -453,6 +454,8 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 												   LLGLenum primary_format,
 												   LLHost request_from_host)
 {
+	static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled");
+
 	LLPointer<LLViewerFetchedTexture> imagep ;
 	switch(texture_type)
 	{
@@ -490,6 +493,11 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
 		imagep->forceActive() ;
 	}
 
+	if(fast_cache_fetching_enabled)
+	{
+		mFastCacheList.insert(imagep);
+		imagep->setInFastCacheList(true);
+	}
 	return imagep ;
 }
 
@@ -503,6 +511,7 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id)
 
 void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
 {
+	assert_main_thread();
 	llassert_always(mInitialized) ;
 	llassert(image);
 	if (image->isInImageList())
@@ -519,6 +528,7 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
 
 void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 {
+	assert_main_thread();
 	llassert_always(mInitialized) ;
 	llassert(image);
 	if (!image->isInImageList())
@@ -593,16 +603,24 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images");
 static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_PRIORITIES("Prioritize");
 static LLFastTimer::DeclareTimer FTM_IMAGE_CALLBACKS("Callbacks");
 static LLFastTimer::DeclareTimer FTM_IMAGE_FETCH("Fetch");
+static LLFastTimer::DeclareTimer FTM_FAST_CACHE_IMAGE_FETCH("Fast Cache Fetch");
 static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create");
 static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats");
 
 void LLViewerTextureList::updateImages(F32 max_time)
 {
-	if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
+	static BOOL cleared = FALSE;
+	if(gTeleportDisplay)
 	{
-		clearFetchingRequests();
+		if(!cleared)
+		{
+			clearFetchingRequests();
+			gPipeline.clearRebuildGroups();
+			cleared = TRUE;
+		}
 		return;
 	}
+	cleared = FALSE;
 
 	LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec());
 
@@ -613,6 +631,11 @@ void LLViewerTextureList::updateImages(F32 max_time)
 	LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory));
 	LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
 
+	{
+		//loading from fast cache 
+		LLFastTimer t(FTM_FAST_CACHE_IMAGE_FETCH);
+		max_time -= updateImagesLoadingFastCache(max_time);
+	}
 
 	{
 		LLFastTimer t(FTM_IMAGE_UPDATE_PRIORITIES);
@@ -673,14 +696,13 @@ void LLViewerTextureList::clearFetchingRequests()
 		return;
 	}
 
+	LLAppViewer::getTextureFetch()->deleteAllRequests();
+
 	for (image_priority_list_t::iterator iter = mImageList.begin();
 		 iter != mImageList.end(); ++iter)
 	{
-		LLViewerFetchedTexture* image = *iter;
-		if(image->hasFetcher())
-		{
-			image->forceToDeleteRequest() ;
-		}
+		LLViewerFetchedTexture* imagep = *iter;
+		imagep->forceToDeleteRequest() ;
 	}
 }
 
@@ -688,10 +710,11 @@ void LLViewerTextureList::updateImagesDecodePriorities()
 {
 	// Update the decode priority for N images each frame
 	{
-		const size_t max_update_count = llmin((S32) (1024*gFrameIntervalSeconds) + 1, 32); //target 1024 textures per second
-		S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10);
+        static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities");         // default: 32
+		const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds) + 1, MAX_PRIO_UPDATES);
+		S32 update_counter = llmin(max_update_count, mUUIDMap.size());
 		uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID);
-		while(update_counter > 0 && !mUUIDMap.empty())
+		while ((update_counter-- > 0) && !mUUIDMap.empty())
 		{
 			if (iter == mUUIDMap.end())
 			{
@@ -699,7 +722,13 @@ void LLViewerTextureList::updateImagesDecodePriorities()
 			}
 			mLastUpdateUUID = iter->first;
 			LLPointer<LLViewerFetchedTexture> imagep = iter->second;
-			++iter; // safe to incrament now
+			++iter; // safe to increment now
+
+			if(imagep->isInDebug())
+			{
+				update_counter--;
+				continue; //is in debug, ignore.
+			}
 
 			//
 			// Flush formatted images using a lazy flush
@@ -754,7 +783,16 @@ void LLViewerTextureList::updateImagesDecodePriorities()
 					imagep->setInactive() ;										
 				}
 			}
-			
+
+			if (!imagep->isInImageList())
+			{
+				continue;
+			}
+			if(imagep->isInFastCacheList())
+			{
+				continue; //wait for loading from the fast cache.
+			}
+
 			imagep->processTextureStats();
 			F32 old_priority = imagep->getDecodePriority();
 			F32 old_priority_test = llmax(old_priority, 0.0f);
@@ -764,15 +802,35 @@ void LLViewerTextureList::updateImagesDecodePriorities()
 			if ((decode_priority_test < old_priority_test * .8f) ||
 				(decode_priority_test > old_priority_test * 1.25f))
 			{
-				removeImageFromList(imagep);
+				mImageList.erase(imagep) ;
 				imagep->setDecodePriority(decode_priority);
-				addImageToList(imagep);
+				mImageList.insert(imagep);
 			}
-			update_counter--;
 		}
 	}
 }
 
+void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level)
+{
+	if(!tex->setDebugFetching(debug_level))
+	{
+		return;
+	}
+
+	const F32 DEBUG_PRIORITY = 100000.f;
+	F32 old_priority_test = llmax(tex->getDecodePriority(), 0.0f);
+	F32 decode_priority_test = DEBUG_PRIORITY;
+	
+	// Ignore < 20% difference
+	if ((decode_priority_test < old_priority_test * .8f) ||
+		(decode_priority_test > old_priority_test * 1.25f))
+	{
+		removeImageFromList(tex);
+		tex->setDecodePriority(decode_priority_test);
+		addImageToList(tex);
+	}
+}
+
 /*
  static U8 get_image_type(LLViewerFetchedTexture* imagep, LLHost target_host)
  {
@@ -827,6 +885,36 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
 	return create_timer.getElapsedTimeF32();
 }
 
+F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
+{
+	if (gGLManager.mIsDisabled) return 0.0f;
+	if(mFastCacheList.empty())
+	{
+		return 0.f;
+	}
+	
+	//
+	// loading texture raw data from the fast cache directly.
+	//
+		
+	LLTimer timer;
+	image_list_t::iterator enditer = mFastCacheList.begin();
+	for (image_list_t::iterator iter = mFastCacheList.begin();
+		 iter != mFastCacheList.end();)
+	{
+		image_list_t::iterator curiter = iter++;
+		enditer = iter;
+		LLViewerFetchedTexture *imagep = *curiter;
+		imagep->loadFromFastCache();
+		if (timer.getElapsedTimeF32() > max_time)
+		{
+			break;
+		}
+	}
+	mFastCacheList.erase(mFastCacheList.begin(), enditer);
+	return timer.getElapsedTimeF32();
+}
+
 void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
 {
 	if(!imagep)
@@ -850,15 +938,24 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 {
 	LLTimer image_op_timer;
 	
-	// Update the decode priority for N images each frame
-	// Make a list with 32 high priority entries + 256 cycled entries
-	const size_t max_priority_count = llmin((S32) (256*10.f*gFrameIntervalSeconds)+1, 32);
-	const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256);
+	// Update fetch for N images each frame
+	static const S32 MAX_HIGH_PRIO_COUNT = gSavedSettings.getS32("TextureFetchUpdateHighPriority");         // default: 32
+	static const S32 MAX_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMaxMediumPriority");       // default: 256
+	static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinMediumPriority");       // default: 32
+	static const F32 MIN_PRIORITY_THRESHOLD = gSavedSettings.getF32("TextureFetchUpdatePriorityThreshold"); // default: 0.0
+	static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority");          // default: false
+
+	size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT);
+	max_priority_count = llmin(max_priority_count, mImageList.size());
+	
+	size_t total_update_count = mUUIDMap.size();
+	size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT);
+	max_update_count = llmin(max_update_count, total_update_count);	
 	
-	// 32 high priority entries
+	// MAX_HIGH_PRIO_COUNT high priority entries
 	typedef std::vector<LLViewerFetchedTexture*> entries_list_t;
 	entries_list_t entries;
-	size_t update_counter = llmin(max_priority_count, mImageList.size());
+	size_t update_counter = max_priority_count;
 	image_priority_list_t::iterator iter1 = mImageList.begin();
 	while(update_counter > 0)
 	{
@@ -868,43 +965,46 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
 		update_counter--;
 	}
 	
-	// 256 cycled entries
-	update_counter = llmin(max_update_count, mUUIDMap.size());	
+	// MAX_UPDATE_COUNT cycled entries
+	update_counter = max_update_count;	
 	if(update_counter > 0)
 	{
 		uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
-		uuid_map_t::iterator iter2p = iter2;
-		while(update_counter > 0)
+		while ((update_counter > 0) && (total_update_count > 0))
 		{
 			if (iter2 == mUUIDMap.end())
 			{
 				iter2 = mUUIDMap.begin();
 			}
-			entries.push_back(iter2->second);
-			iter2p = iter2++;
-			update_counter--;
+			LLViewerFetchedTexture* imagep = iter2->second;
+            // Skip the textures where there's really nothing to do so to give some times to others. Also skip the texture if it's already in the high prio set.
+            if (!SKIP_LOW_PRIO || (SKIP_LOW_PRIO && ((imagep->getDecodePriority() > MIN_PRIORITY_THRESHOLD) || imagep->hasFetcher())))
+            {
+                entries.push_back(imagep);
+                update_counter--;
+            }
+
+			iter2++;
+			total_update_count--;
 		}
-
-		mLastFetchUUID = iter2p->first;
 	}
 	
 	S32 fetch_count = 0;
-	S32 min_count = max_priority_count + max_update_count/4;
+	size_t min_update_count = llmin(MIN_UPDATE_COUNT,(S32)(entries.size()-max_priority_count));
+	S32 min_count = max_priority_count + min_update_count;
 	for (entries_list_t::iterator iter3 = entries.begin();
 		 iter3 != entries.end(); )
 	{
 		LLViewerFetchedTexture* imagep = *iter3++;
-		
-		bool fetching = imagep->updateFetch();
-		if (fetching)
+		fetch_count += (imagep->updateFetch() ? 1 : 0);
+		if (min_count <= min_update_count)
 		{
-			fetch_count++;
+			mLastFetchUUID = imagep->getID();
 		}
-		if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time)
+		if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time))
 		{
 			break;
 		}
-		min_count--;
 	}
 	//if (fetch_count == 0)
 	//{
@@ -936,6 +1036,9 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
 {
 	LLTimer timer;
 
+	//loading from fast cache 
+	updateImagesLoadingFastCache(max_time);
+
 	// Update texture stats and priorities
 	std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
 	for (image_priority_list_t::iterator iter = mImageList.begin();
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index e89997fe283950870a3da2b4fe2481966f3325eb..3dda973d3fa98edf01d20a9c573c8cd514e2589f 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -111,6 +111,7 @@ class LLViewerTextureList
 	void doPrefetchImages();
 
 	void clearFetchingRequests();
+	void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
 
 	static S32 getMinVideoRamSetting();
 	static S32 getMaxVideoRamSetting(bool get_recommended = false);
@@ -120,6 +121,7 @@ class LLViewerTextureList
 	F32  updateImagesCreateTextures(F32 max_time);
 	F32  updateImagesFetchTextures(F32 max_time);
 	void updateImagesUpdateStats();
+	F32  updateImagesLoadingFastCache(F32 max_time);
 
 	void addImage(LLViewerFetchedTexture *image);
 	void deleteImage(LLViewerFetchedTexture *image);
@@ -173,6 +175,7 @@ class LLViewerTextureList
 	image_list_t mLoadingStreamList;
 	image_list_t mCreateTextureList;
 	image_list_t mCallbackList;
+	image_list_t mFastCacheList;
 
 	// Note: just raw pointers because they are never referenced, just compared against
 	std::set<LLViewerFetchedTexture*> mDirtyTextureList;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
old mode 100644
new mode 100755
index c0ef1d7a4bf2c2422b3190274f9077443f862445..366b6004bee8420b316fd227b7512c532446d999
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6676,7 +6676,7 @@ void LLVOAvatar::updateMeshTextures()
 	if(!isSelf())
 	{
 		src_callback_list = &mCallbackTextureList ;
-		paused = mLoadedCallbacksPaused ;
+		paused = !isVisible();
 	}
 
 	std::vector<BOOL> is_layer_baked;
@@ -7221,7 +7221,7 @@ void LLVOAvatar::onFirstTEMessageReceived()
 		if(!isSelf())
 		{
 			src_callback_list = &mCallbackTextureList ;
-			paused = mLoadedCallbacksPaused ;
+			paused = !isVisible();
 		}
 
 		for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
old mode 100644
new mode 100755
index 07b9b782554615712d434ca11ed703b1c840c4ed..7a81063f8331ea4c5d619f53aea2839371c6d971
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2130,9 +2130,7 @@ LLSD LLVOAvatarSelf::metricsData()
 {
 	// runway - add region info
 	LLSD result;
-	result["id"] = getID();
 	result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-	result["is_self"] = isSelf();
 	std::vector<S32> rez_counts;
 	LLVOAvatar::getNearbyRezzedStats(rez_counts);
 	result["nearby"] = LLSD::emptyMap();
@@ -2146,7 +2144,6 @@ LLSD LLVOAvatarSelf::metricsData()
 	result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
 	result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32();
 	result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32();
-	result["phases"] = getPhases().dumpPhases();
 	result["startup"] = LLStartUp::getPhases().dumpPhases();
 	
 	return result;
@@ -2155,7 +2152,12 @@ LLSD LLVOAvatarSelf::metricsData()
 class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 {
 public:
-	ViewerAppearanceChangeMetricsResponder()
+	ViewerAppearanceChangeMetricsResponder( S32 expected_sequence,
+											volatile const S32 & live_sequence,
+											volatile bool & reporting_started):
+		mExpectedSequence(expected_sequence),
+		mLiveSequence(live_sequence),
+		mReportingStarted(reporting_started)
 	{
 	}
 
@@ -2174,14 +2176,44 @@ class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
 			error(status,reason);
 		}
 	}
+
+	// virtual
+	void error(U32 status_num, const std::string & reason)
+	{
+	}
+
+	// virtual
+	void result(const LLSD & content)
+	{
+		if (mLiveSequence == mExpectedSequence)
+		{
+			mReportingStarted = true;
+		}
+	}
+
+private:
+	S32 mExpectedSequence;
+	volatile const S32 & mLiveSequence;
+	volatile bool & mReportingStarted;
 };
 
 void LLVOAvatarSelf::sendAppearanceChangeMetrics()
 {
 	// gAgentAvatarp->stopAllPhases();
+	static volatile bool reporting_started(false);
+	static volatile S32 report_sequence(0);
 
 	LLSD msg = metricsData();
 	msg["message"] = "ViewerAppearanceChangeMetrics";
+	msg["session_id"] = gAgentSessionID;
+	msg["agent_id"] = gAgentID;
+	msg["sequence"] = report_sequence;
+	msg["initial"] = !reporting_started;
+	msg["break"] = false;
+
+	// Update sequence number
+	if (S32_MAX == ++report_sequence)
+		report_sequence = 0;
 
 	LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL;
 	std::string	caps_url;
@@ -2194,8 +2226,10 @@ void LLVOAvatarSelf::sendAppearanceChangeMetrics()
 	{
 		LLCurlRequest::headers_t headers;
 		LLHTTPClient::post(caps_url,
-							msg,
-							new ViewerAppearanceChangeMetricsResponder);
+						   msg,
+						   new ViewerAppearanceChangeMetricsResponder(report_sequence,
+																	  report_sequence,
+																	  reporting_started));
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
old mode 100644
new mode 100755
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 958282f1ebe7d35fabf4e875fc77714ffffddb7a..9c36cfee5995ec8e047095ac38b4c17a9c0247df 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -822,7 +822,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
 				}
 			}
 	
-			S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
+			S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture
 			S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
 
 			if (texture_discard >= 0 && //texture has some data available
@@ -1128,7 +1128,7 @@ void LLVOVolume::sculpt()
 		S8 sculpt_components = 0;
 		const U8* sculpt_data = NULL;
 	
-		S32 discard_level = mSculptTexture->getDiscardLevel() ;
+		S32 discard_level = mSculptTexture->getCachedRawImageLevel() ;
 		LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
 		
 		S32 max_discard = mSculptTexture->getMaxDiscardLevel();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index f6b0d6c5fa2bd95952302dc986927edb5d0a774a..75eb8c460ed9d879e4c907259eba1081ec342528 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2563,6 +2563,31 @@ void LLPipeline::updateGL()
 
 static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups");
 
+void LLPipeline::clearRebuildGroups()
+{
+	mGroupQ1Locked = true;
+	// Iterate through all drawables on the priority build queue,
+	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
+		 iter != mGroupQ1.end(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+	}
+	mGroupQ1.clear();
+	mGroupQ1Locked = false;
+
+	mGroupQ2Locked = true;
+	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin();
+		 iter != mGroupQ2.end(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+	}	
+
+	mGroupQ2.clear();
+	mGroupQ2Locked = false;
+}
+
 void LLPipeline::rebuildPriorityGroups()
 {
 	LLFastTimer t(FTM_REBUILD_PRIORITY_GROUPS);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 0140e24d636bbb3abfd70ccdf6b07c75a51a8bfd..0ecae40d496a8092385c250d3e4a8fa17036136b 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -223,6 +223,7 @@ class LLPipeline
 	void updateGL();
 	void rebuildPriorityGroups();
 	void rebuildGroups();
+	void clearRebuildGroups();
 
 	//calculate pixel area of given box from vantage point of given camera
 	static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera);
diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
index f3f8d4ddca4c875a36bd8e08e00db2fc5c7161b2..1ea256b8b310dd5cfb18b0ee4a0efde237d3124f 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
@@ -2,7 +2,7 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="550"
+ height="600"
  layout="topleft"
  name="TexFetchDebugger"
  help_topic="texfetchdebugger"
@@ -195,10 +195,34 @@
   height="25"
   layout="topleft"
   left_delta="0"
+  name="total_time_refetch_all_cache_label"
+  top_delta="25"
+  width="540">
+    16, Refetching all textures from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
+  </text>
+  <text
+  type="string"
+  length="1"
+  follows="left|top"
+  height="25"
+  layout="topleft"
+  left_delta="0"
   name="total_time_refetch_vis_http_label"
   top_delta="25"
   width="540">
-    16, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
+    17, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
+  </text>
+  <text
+  type="string"
+  length="1"
+  follows="left|top"
+  height="25"
+  layout="topleft"
+  left_delta="0"
+  name="total_time_refetch_all_http_label"
+  top_delta="25"
+  width="540">
+    18, Refetching all textures from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels
   </text>
   <spinner
      decimal_digits="2"
@@ -206,7 +230,7 @@
      height="20"
      increment="0.01"
      initial_value="1.0"
-     label="17, Ratio of Texel/Pixel:"
+     label="19, Ratio of Texel/Pixel:"
      label_width="130"
      layout="topleft"
      left_delta="0"
@@ -218,14 +242,53 @@
     <spinner.commit_callback
 		function="TexFetchDebugger.ChangeTexelPixelRatio" />
   </spinner>
+  <text
+  type="string"
+  length="1"
+  follows="left|top"
+  height="25"
+  layout="topleft"
+  left_delta="0"
+  name="texture_source_label"
+  top_delta="30"
+  width="110">
+    20, Texture Source:
+  </text>
+  <radio_group
+     control_name="TextureFetchSource"
+     follows="top|left"
+     draw_border="false"
+     height="25"
+     layout="topleft"
+     left_pad="0"
+     name="texture_source"
+     top_delta="0"
+     width="264">
+    <radio_item
+     height="16"
+     label="Cache + HTTP"
+     layout="topleft"
+     left="3"
+     name="0"
+     top="0"
+     width="100" />
+    <radio_item
+     height="16"
+     label="HTTP Only"
+     layout="topleft"
+     left_delta="100"
+     name="1"
+     top_delta="0"
+     width="200" />
+  </radio_group>
   <button
    follows="left|top"
    height="20"
    label="Start"
    layout="topleft"
-   left_delta="0"
+   left="10"
    name="start_btn"
-   top_delta="30"
+   top_delta="20"
    width="70">
     <button.commit_callback
 		function="TexFetchDebugger.Start" />
@@ -261,7 +324,7 @@
    layout="topleft"
    left="10"
    name="cacheread_btn"
-   top_delta="30"
+   top_delta="20"
    width="80">
     <button.commit_callback
 		function="TexFetchDebugger.CacheRead" />
@@ -321,11 +384,23 @@
    layout="topleft"
    left="10"
    name="refetchviscache_btn"
-   top_delta="30"
+   top_delta="20"
    width="120">
     <button.commit_callback
 		function="TexFetchDebugger.RefetchVisCache" />
   </button>
+  <button
+   follows="left|top"
+   height="20"
+   label="Refetch All Cache"
+   layout="topleft"
+   left_pad="7"
+   name="refetchallcache_btn"
+   top_delta="0"
+   width="120">
+    <button.commit_callback
+		function="TexFetchDebugger.RefetchAllCache" />
+  </button>
   <button
    follows="left|top"
    height="20"
@@ -338,4 +413,16 @@
     <button.commit_callback
 		function="TexFetchDebugger.RefetchVisHTTP" />
   </button>
+  <button
+   follows="left|top"
+   height="20"
+   label="Refetch All HTTP"
+   layout="topleft"
+   left_pad="7"
+   name="refetchallhttp_btn"
+   top_delta="0"
+   width="120">
+    <button.commit_callback
+		function="TexFetchDebugger.RefetchAllHTTP" />
+  </button>
 </floater>
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
old mode 100644
new mode 100755