From e344b2afa21adf072837f1bcf4b38dd511b76f0e Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Thu, 26 Apr 2012 15:53:35 -0600
Subject: [PATCH] For SH-3121: collect time of reloading all textures from
 cache and through HTTP when all objects loading are done.

---
 indra/newview/llappviewer.cpp                 | 18 ++--
 .../newview/llfloatertexturefetchdebugger.cpp | 60 ++++++++++++++
 indra/newview/llfloatertexturefetchdebugger.h |  2 +
 indra/newview/lltexturefetch.cpp              | 83 ++++++++++++++++++-
 indra/newview/lltexturefetch.h                | 26 +++++-
 indra/newview/llviewertexture.cpp             |  8 ++
 indra/newview/llviewertexture.h               |  2 +
 .../xui/en/floater_texture_fetch_debugger.xml | 64 ++++++++++++--
 8 files changed, 242 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3ee53c679f3..bb6658dc489 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1219,15 +1219,7 @@ bool LLAppViewer::mainLoop()
 			if(mem_leak_instance)
 			{
 				mem_leak_instance->idle() ;				
-			}			
-
-			//texture fetching debugger
-			LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
-				LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
-			if(tex_fetch_debugger_instance)
-			{
-				tex_fetch_debugger_instance->idle() ;				
-			}			
+			}							
 
             // canonical per-frame event
             mainloop.post(newFrame);
@@ -1412,6 +1404,14 @@ bool LLAppViewer::mainLoop()
 					LLLFSThread::sLocal->pause(); 
 				}									
 
+				//texture fetching debugger
+				LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
+					LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
+				if(tex_fetch_debugger_instance)
+				{
+					tex_fetch_debugger_instance->idle() ;				
+				}		
+
 				if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
 					(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
 				{
diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp
index 6756f9bbc18..448c562134c 100644
--- a/indra/newview/llfloatertexturefetchdebugger.cpp
+++ b/indra/newview/llfloatertexturefetchdebugger.cpp
@@ -58,6 +58,9 @@ LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
 	mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad",	boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this));
 	mCommitCallbackRegistrar.add("TexFetchDebugger.Decode",	boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this));
 	mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture",	boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this));
+
+	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this));
+	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this));
 }
 //----------------------------------------------
 
@@ -74,6 +77,10 @@ BOOL LLFloaterTextureFetchDebugger::postBuild(void)
 	mButtonStateMap["http_btn"] = false;
 	mButtonStateMap["decode_btn"] = false;
 	mButtonStateMap["gl_btn"] = false;
+
+	mButtonStateMap["refetchviscache_btn"] = true;
+	mButtonStateMap["refetchvishttp_btn"] = true;
+
 	updateButtons();
 
 	return TRUE ;
@@ -109,6 +116,8 @@ void LLFloaterTextureFetchDebugger::disableButtons()
 	childDisable("http_btn");
 	childDisable("decode_btn");
 	childDisable("gl_btn");
+	childDisable("refetchviscache_btn");
+	childDisable("refetchvishttp_btn");
 }
 
 void LLFloaterTextureFetchDebugger::idle()
@@ -142,6 +151,11 @@ void LLFloaterTextureFetchDebugger::idle()
 		case LLTextureFetchDebugger::GL_TEX:
 			updateButtons();
 			break;
+		case LLTextureFetchDebugger::REFETCH_VIS_CACHE:
+			updateButtons();
+		case LLTextureFetchDebugger::REFETCH_VIS_HTTP:
+			updateButtons();
+			break;
 		default:
 			break;
 		}
@@ -184,6 +198,8 @@ void LLFloaterTextureFetchDebugger::onClickClear()
 	mButtonStateMap["http_btn"] = false;
 	mButtonStateMap["decode_btn"] = false;
 	mButtonStateMap["gl_btn"] = false;
+	mButtonStateMap["refetchviscache_btn"] = true;
+	mButtonStateMap["refetchvishttp_btn"] = true;
 	updateButtons();
 
 	//stop everything
@@ -226,6 +242,20 @@ void LLFloaterTextureFetchDebugger::onClickGLTexture()
 	mDebugger->debugGLTextureCreation();
 }
 
+void LLFloaterTextureFetchDebugger::onClickRefetchVisCache()
+{
+	disableButtons();
+
+	mDebugger->debugRefetchVisibleFromCache();
+}
+
+void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP()
+{
+	disableButtons();
+
+	mDebugger->debugRefetchVisibleFromHTTP();
+}
+
 void LLFloaterTextureFetchDebugger::draw()
 {
 	//total number of fetched textures
@@ -257,6 +287,7 @@ void LLFloaterTextureFetchDebugger::draw()
 	{
 		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10));		
 		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10));
+		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f));
 	}
 
 	//total number of visible fetched data
@@ -269,6 +300,7 @@ void LLFloaterTextureFetchDebugger::draw()
 	{
 		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10));		
 		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10));
+		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f));
 	}
 
 	//total time on cache readings
@@ -326,5 +358,33 @@ void LLFloaterTextureFetchDebugger::draw()
 		getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime()));
 	}
 
+	//total time on refetching visible textures from cache
+	if(mDebugger->getRefetchVisCacheTime() < 0.f)
+	{
+		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----"));
+	}
+	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));
+	}
+
+	//total time on refetching visible textures from http
+	if(mDebugger->getRefetchVisHTTPTime() < 0.f)
+	{
+		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----"));
+		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----"));
+	}
+	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));
+	}
+
 	LLFloater::draw();
 }
diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h
index 9f2e62fd2cc..7181dc04d54 100644
--- a/indra/newview/llfloatertexturefetchdebugger.h
+++ b/indra/newview/llfloatertexturefetchdebugger.h
@@ -51,6 +51,8 @@ class LLFloaterTextureFetchDebugger : public LLFloater
 	void onClickDecode();
 	void onClickGLTexture();
 
+	void onClickRefetchVisCache();
+	void onClickRefetchVisHTTP();
 public:
 	void idle() ;
 
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index d7742219bfb..2816c162616 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -3139,6 +3139,8 @@ void LLTextureFetchDebugger::init()
 	mHTTPTime = -1.f;
 	mGLCreationTime = -1.f;
 	mTotalFetchingTime = 0.f;
+	mRefetchVisCacheTime = -1.f;
+	mRefetchVisHTTPTime = -1.f;
 
 	mNumFetchedTextures = 0;
 	mNumCacheHits = 0;
@@ -3150,12 +3152,19 @@ void LLTextureFetchDebugger::init()
 	mVisibleDecodedData = 0;
 	mRenderedData = 0;
 	mRenderedDecodedData = 0;
+	mFetchedPixels = 0;
+	mRenderedPixels = 0;
+	mRefetchedData = 0;
+	mRefetchedPixels = 0;
+
+	mFreezeHistory = FALSE;
 }
 
 void LLTextureFetchDebugger::startDebug()
 {
 	//lock the fetcher
 	mFetcher->lockFetcher(true);
+	mFreezeHistory = TRUE;
 
 	//clear the current fetching queue
 	gTextureList.clearFetchingRequests();
@@ -3203,6 +3212,7 @@ void LLTextureFetchDebugger::startDebug()
 			{
 				mRenderedData += mFetchingHistory[i].mFetchedSize;
 				mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
+				mRenderedPixels += tex->getWidth() * tex->getHeight();
 			}
 		}
 	}
@@ -3254,6 +3264,8 @@ void LLTextureFetchDebugger::stopDebug()
 
 	//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
@@ -3265,12 +3277,20 @@ void LLTextureFetchDebugger::clearHistory()
 
 void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
 {
+	if(mFreezeHistory)
+	{
+		mRefetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
+		mRefetchedData += worker->mFormattedImage->getDataSize();
+		return;
+	}
+
 	if(worker->mInCache)
 	{
 		mNumCacheHits++;
 	}
 	mFetchedData += worker->mFormattedImage->getDataSize();
 	mDecodedData += worker->mRawImage->getDataSize();
+	mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight();
 
 	mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDecodedDiscard, worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize()));
 	//mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mHaveAllData ? 0 : worker->mLoadedDiscard, worker->mFormattedImage->getComponents(),
@@ -3301,9 +3321,8 @@ void LLTextureFetchDebugger::debugCacheRead()
 	}
 }
 	
-void LLTextureFetchDebugger::debugCacheWrite()
+void LLTextureFetchDebugger::clearCache()
 {
-	//remove from cache
 	S32 size = mFetchingHistory.size();
 	{
 		std::set<LLUUID> deleted_list;
@@ -3316,12 +3335,19 @@ void LLTextureFetchDebugger::debugCacheWrite()
 			}
 		}
 	}
+}
+
+void LLTextureFetchDebugger::debugCacheWrite()
+{
+	//remove from cache
+	clearCache();
 
 	lockCache();
 	llassert_always(mState == IDLE);
 	mTimer.reset();
 	mState = WRITE_CACHE;
 
+	S32 size = mFetchingHistory.size();
 	for(S32 i = 0 ; i < size ; i++)
 	{		
 		mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 
@@ -3403,6 +3429,43 @@ void LLTextureFetchDebugger::debugGLTextureCreation()
 	return;
 }
 
+//clear fetching results of all textures.
+void LLTextureFetchDebugger::clearTextures()
+{
+	S32 size = mFetchingHistory.size();
+	for(S32 i = 0 ; i < size ; i++)
+	{
+		LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
+		if(tex)
+		{
+			tex->clearFetchedResults() ;
+		}
+	}
+}
+
+void LLTextureFetchDebugger::debugRefetchVisibleFromCache()
+{
+	llassert_always(mState == IDLE);
+	mState = REFETCH_VIS_CACHE;
+
+	clearTextures();
+
+	mTimer.reset();
+	mFetcher->lockFetcher(false);
+}
+
+void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP()
+{
+	llassert_always(mState == IDLE);
+	mState = REFETCH_VIS_HTTP;
+
+	clearCache();
+	clearTextures();
+
+	mTimer.reset();
+	mFetcher->lockFetcher(false);
+}
+
 bool LLTextureFetchDebugger::update()
 {
 	switch(mState)
@@ -3437,6 +3500,22 @@ bool LLTextureFetchDebugger::update()
 	case GL_TEX:
 		mState = IDLE;
 		break;
+	case REFETCH_VIS_CACHE:
+		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+		{
+			mRefetchVisCacheTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+			mState = IDLE;
+			mFetcher->lockFetcher(true);
+		}
+		break;
+	case REFETCH_VIS_HTTP:
+		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
+		{
+			mRefetchVisHTTPTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+			mState = IDLE;
+			mFetcher->lockFetcher(true);
+		}
+		break;
 	default:
 		mState = IDLE;
 		break;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 529a2e68347..fc8855089cf 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -243,6 +243,10 @@ class LLTextureFetchDebugger
 		DECODING,
 		HTTP_FETCHING,
 		GL_TEX,
+		REFETCH_VIS_CACHE,
+		REFETCH_VIS_HTTP,
+		REFETCH_ALL_CACHE,
+		REFETCH_ALL_HTTP,
 		INVALID
 	};
 
@@ -287,14 +291,17 @@ class LLTextureFetchDebugger
 	F32 mHTTPTime;
 	F32 mGLCreationTime;
 
+	F32 mTotalFetchingTime;
+	F32 mRefetchVisCacheTime;
+	F32 mRefetchVisHTTPTime;
+
 	LLTimer mTimer;
 	
 	LLTextureFetch* mFetcher;
 	LLTextureCache* mTextureCache;
 	LLImageDecodeThread* mImageDecodeThread;
 	LLCurlRequest* mCurlGetRequest;
-
-	F32 mTotalFetchingTime;
+	
 	S32 mNumFetchedTextures;
 	S32 mNumCacheHits;
 	S32 mNumVisibleFetchedTextures;
@@ -305,7 +312,12 @@ class LLTextureFetchDebugger
 	U32 mVisibleDecodedData;
 	U32 mRenderedData;
 	U32 mRenderedDecodedData;
+	U32 mFetchedPixels;
+	U32 mRenderedPixels;
+	U32 mRefetchedData;
+	U32 mRefetchedPixels;
 
+	BOOL mFreezeHistory;
 public:
 	bool update(); //called in the main thread once per frame
 
@@ -322,6 +334,8 @@ class LLTextureFetchDebugger
 	void debugHTTP();
 	void debugDecoder();
 	void debugGLTextureCreation();
+	void debugRefetchVisibleFromCache();
+	void debugRefetchVisibleFromHTTP();
 
 	void callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
 						   S32 imagesize, BOOL islocal);
@@ -340,6 +354,10 @@ class LLTextureFetchDebugger
 	U32  getVisibleDecodedData()         {return mVisibleDecodedData;}
 	U32  getRenderedData()               {return mRenderedData;}
 	U32  getRenderedDecodedData()        {return mRenderedDecodedData;}
+	U32  getFetchedPixels()              {return mFetchedPixels;}
+	U32  getRenderedPixels()             {return mRenderedPixels;}
+	U32  getRefetchedData()              {return mRefetchedData;}
+	U32  getRefetchedPixels()            {return mRefetchedPixels;}
 
 	F32  getCacheReadTime()     {return mCacheReadTime;}
 	F32  getCacheWriteTime()    {return mCacheWriteTime;}
@@ -347,9 +365,13 @@ class LLTextureFetchDebugger
 	F32  getGLCreationTime()    {return mGLCreationTime;}
 	F32  getHTTPTime()          {return mHTTPTime;}
 	F32  getTotalFetchingTime() {return mTotalFetchingTime;}
+	F32  getRefetchVisCacheTime() {return mRefetchVisCacheTime;}
+	F32  getRefetchVisHTTPTime()  {return mRefetchVisHTTPTime;}
 
 private:
 	void init();
+	void clearTextures();//clear fetching results of all textures.
+	void clearCache();
 
 	void lockFetcher();
 	void unlockFetcher();
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 49faae3fdb6..a7e2ed85fa7 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2144,6 +2144,14 @@ bool LLViewerFetchedTexture::updateFetch()
 	return mIsFetching ? true : false;
 }
 
+void LLViewerFetchedTexture::clearFetchedResults()
+{
+	llassert_always(!mNeedsCreateTexture && !mIsFetching);
+	
+	cleanup();
+	destroyGLTexture();
+}
+
 void LLViewerFetchedTexture::forceToDeleteRequest()
 {
 	if (mHasFetcher)
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index d0bc534c5af..95896f9d419 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -433,6 +433,8 @@ class LLViewerFetchedTexture : public LLViewerTexture
 
 	bool updateFetch();
 	
+	void clearFetchedResults(); //clear all fetched results, for debug use.
+
 	// Override the computation of discard levels if we know the exact output
 	// size of the image.  Used for UI textures to not decode, even if we have
 	// more data.
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 ff7528eeb70..7f95d0e84b0 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,12 +2,12 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="480"
+ height="550"
  layout="topleft"
  name="TexFetchDebugger"
  help_topic="texfetchdebugger"
  title="Texture Fetching Debugger"
- width="500">
+ width="540">
   <text
    type="string"
    length="1"
@@ -77,8 +77,8 @@
    left_delta="0"
    name="total_fetched_data_label"
    top_delta="25"
-   width="480">
-    6, Total number of fetched data/Decoded Data: [SIZE1]KB / [SIZE2]KB
+   width="530">
+    6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
   </text>
   <text
    type="string"
@@ -90,7 +90,7 @@
    name="total_fetched_vis_data_label"
    top_delta="25"
    width="480">
-    7, Total number of visible fetched data/Decoded Data: [SIZE1]KB / [SIZE2]KB
+    7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
   </text>
   <text
    type="string"
@@ -101,8 +101,8 @@
    left_delta="0"
    name="total_fetched_rendered_data_label"
    top_delta="25"
-   width="480">
-    8, Total number of rendered fetched data/Decoded Data: [SIZE1]KB / [SIZE2]KB
+   width="530">
+    8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
   </text>
   <text
    type="string"
@@ -176,13 +176,37 @@
    width="400">
     14, Total time on entire fetching: [TIME] seconds
   </text>
+  <text
+  type="string"
+  length="1"
+  follows="left|top"
+  height="25"
+  layout="topleft"
+  left_delta="0"
+  name="total_time_refetch_vis_cache_label"
+  top_delta="25"
+  width="540">
+    15, Refetching visibles 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
+  </text>
   <spinner
      decimal_digits="1"
      follows="left|top"
      height="20"
      increment="0.1"
      initial_value="1.0"
-     label="15, Ratio of Texel/Pixel:"
+     label="17, Ratio of Texel/Pixel:"
      label_width="130"
      layout="topleft"
      left_delta="0"
@@ -289,4 +313,28 @@
     <button.commit_callback
 		function="TexFetchDebugger.GLTexture" />
   </button>
+  <button
+   follows="left|top"
+   height="20"
+   label="Refetch Vis Cache"
+   layout="topleft"
+   left="10"
+   name="refetchviscache_btn"
+   top_delta="30"
+   width="120">
+    <button.commit_callback
+		function="TexFetchDebugger.RefetchVisCache" />
+  </button>
+  <button
+   follows="left|top"
+   height="20"
+   label="Refetch Vis HTTP"
+   layout="topleft"
+   left_pad="7"
+   name="refetchvishttp_btn"
+   top_delta="0"
+   width="120">
+    <button.commit_callback
+		function="TexFetchDebugger.RefetchVisHTTP" />
+  </button>
 </floater>
-- 
GitLab