summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/llrender/llimagegl.cpp17
-rwxr-xr-xindra/llrender/llimagegl.h1
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rwxr-xr-xindra/newview/app_settings/settings.xml24
-rw-r--r--indra/newview/llappviewer.cpp14
-rw-r--r--indra/newview/llfloatertexturefetchdebugger.cpp390
-rw-r--r--indra/newview/llfloatertexturefetchdebugger.h71
-rwxr-xr-xindra/newview/lltexturefetch.cpp691
-rw-r--r--indra/newview/lltexturefetch.h193
-rw-r--r--indra/newview/llviewerfloaterreg.cpp6
-rw-r--r--indra/newview/llviewermenu.cpp11
-rw-r--r--indra/newview/llviewertexture.cpp46
-rw-r--r--indra/newview/llviewertexture.h4
-rw-r--r--indra/newview/llviewertexturelist.h6
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml341
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml17
16 files changed, 1810 insertions, 24 deletions
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ab744fb7ff..2c13fead97 100755
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1464,13 +1464,24 @@ void LLImageGL::destroyGLTexture()
}
LLImageGL::deleteTextures(1, &mTexName);
- mTexName = 0;
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
+ mTexName = 0;
mGLTextureCreated = FALSE ;
- }
+ }
}
-
+//force to invalidate the gl texture, most likely a sculpty texture
+void LLImageGL::forceToInvalidateGLTexture()
+{
+ if (mTexName != 0)
+ {
+ destroyGLTexture();
+ }
+ else
+ {
+ mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
+ }
+}
//----------------------------------------------------------------------------
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 2060be914b..e515d6b324 100755
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -114,6 +114,7 @@ public:
// Read back a raw image for this discard level, if it exists
BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
void destroyGLTexture();
+ void forceToInvalidateGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
void setComponents(S8 ncomponents) { mComponents = ncomponents; }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f85b943c70..6db97390aa 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -236,6 +236,7 @@ set(viewer_SOURCE_FILES
llfloatertelehub.cpp
llfloatertestinspectors.cpp
llfloatertestlistview.cpp
+ llfloatertexturefetchdebugger.cpp
llfloatertools.cpp
llfloatertopobjects.cpp
llfloatertos.cpp
@@ -792,6 +793,7 @@ set(viewer_HEADER_FILES
llfloatertelehub.h
llfloatertestinspectors.h
llfloatertestlistview.h
+ llfloatertexturefetchdebugger.h
llfloatertools.h
llfloatertopobjects.h
llfloatertos.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index eb3fcc30ee..c2f3d244f3 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10631,6 +10631,17 @@
<key>Value</key>
<real>20.0</real>
</map>
+ <key>TexelPixelRatio</key>
+ <map>
+ <key>Comment</key>
+ <string>texel pixel ratio = texel / pixel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
<key>TextureCameraMotionThreshold</key>
<map>
<key>Comment</key>
@@ -10640,7 +10651,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <integer>0.2</integer>
+ <real>0.2</real>
</map>
<key>TextureCameraMotionBoost</key>
<map>
@@ -10686,6 +10697,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>TextureFetchDebuggerEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable the texture fetching debugger if set</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>TextureLoadFullRes</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a627f3868b..178b96e42e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -93,6 +93,7 @@
#include "llsecondlifeurls.h"
#include "llupdaterservice.h"
#include "llcallfloater.h"
+#include "llfloatertexturefetchdebugger.h"
// Linden library includes
#include "llavatarnamecache.h"
@@ -1218,7 +1219,7 @@ bool LLAppViewer::mainLoop()
if(mem_leak_instance)
{
mem_leak_instance->idle() ;
- }
+ }
// canonical per-frame event
mainloop.post(newFrame);
@@ -1403,6 +1404,17 @@ bool LLAppViewer::mainLoop()
LLLFSThread::sLocal->pause();
}
+ //texture fetching debugger
+ if(LLTextureFetchDebugger::isEnabled())
+ {
+ 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
new file mode 100644
index 0000000000..2b34b72055
--- /dev/null
+++ b/indra/newview/llfloatertexturefetchdebugger.cpp
@@ -0,0 +1,390 @@
+/**
+ * @file llfloatertexturefetchdebugger.cpp
+ * @brief LLFloaterTextureFetchDebugger class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatertexturefetchdebugger.h"
+
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llspinctrl.h"
+#include "llresmgr.h"
+
+#include "llmath.h"
+#include "llviewerwindow.h"
+#include "llappviewer.h"
+#include "lltexturefetch.h"
+#include "llviewercontrol.h"
+
+LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key)
+ : LLFloater(key),
+ mDebugger(NULL)
+{
+ setTitle("Texture Fetching Debugger Floater");
+
+ mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this));
+
+ mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this));
+ mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this));
+ mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this));
+
+ mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this));
+ mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this));
+ 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));
+}
+//----------------------------------------------
+
+BOOL LLFloaterTextureFetchDebugger::postBuild(void)
+{
+ mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger();
+
+ //set states for buttons
+ mButtonStateMap["start_btn"] = true;
+ mButtonStateMap["close_btn"] = true;
+ mButtonStateMap["clear_btn"] = true;
+ mButtonStateMap["cacheread_btn"] = false;
+ mButtonStateMap["cachewrite_btn"] = false;
+ mButtonStateMap["http_btn"] = false;
+ mButtonStateMap["decode_btn"] = false;
+ mButtonStateMap["gl_btn"] = false;
+
+ mButtonStateMap["refetchviscache_btn"] = true;
+ mButtonStateMap["refetchvishttp_btn"] = true;
+
+ updateButtons();
+
+ getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio"));
+
+ return TRUE ;
+}
+
+LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger()
+{
+ //stop everything
+ mDebugger->stopDebug();
+}
+
+void LLFloaterTextureFetchDebugger::updateButtons()
+{
+ for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter)
+ {
+ if(iter->second)
+ {
+ childEnable(iter->first.c_str());
+ }
+ else
+ {
+ childDisable(iter->first.c_str());
+ }
+ }
+}
+
+void LLFloaterTextureFetchDebugger::disableButtons()
+{
+ childDisable("start_btn");
+ childDisable("clear_btn");
+ childDisable("cacheread_btn");
+ childDisable("cachewrite_btn");
+ childDisable("http_btn");
+ childDisable("decode_btn");
+ childDisable("gl_btn");
+ childDisable("refetchviscache_btn");
+ childDisable("refetchvishttp_btn");
+}
+
+void LLFloaterTextureFetchDebugger::idle()
+{
+ LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();
+
+ if(mDebugger->update())
+ {
+ switch(state)
+ {
+ case LLTextureFetchDebugger::IDLE:
+ break;
+ case LLTextureFetchDebugger::READ_CACHE:
+ mButtonStateMap["cachewrite_btn"] = true;
+ mButtonStateMap["decode_btn"] = true;
+ updateButtons();
+ break;
+ case LLTextureFetchDebugger::WRITE_CACHE:
+ updateButtons();
+ break;
+ case LLTextureFetchDebugger::DECODING:
+ mButtonStateMap["gl_btn"] = true;
+ updateButtons();
+ break;
+ case LLTextureFetchDebugger::HTTP_FETCHING:
+ mButtonStateMap["cacheread_btn"] = true;
+ mButtonStateMap["cachewrite_btn"] = true;
+ mButtonStateMap["decode_btn"] = true;
+ updateButtons();
+ break;
+ case LLTextureFetchDebugger::GL_TEX:
+ updateButtons();
+ break;
+ case LLTextureFetchDebugger::REFETCH_VIS_CACHE:
+ updateButtons();
+ case LLTextureFetchDebugger::REFETCH_VIS_HTTP:
+ updateButtons();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+//----------------------
+void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio()
+{
+ gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal());
+}
+
+void LLFloaterTextureFetchDebugger::onClickStart()
+{
+ disableButtons();
+
+ mDebugger->startDebug();
+
+ mButtonStateMap["start_btn"] = false;
+ mButtonStateMap["cacheread_btn"] = true;
+ mButtonStateMap["http_btn"] = true;
+ updateButtons();
+}
+
+void LLFloaterTextureFetchDebugger::onClickClose()
+{
+ setVisible(FALSE);
+
+ //stop everything
+ mDebugger->stopDebug();
+}
+
+void LLFloaterTextureFetchDebugger::onClickClear()
+{
+ mButtonStateMap["start_btn"] = true;
+ mButtonStateMap["close_btn"] = true;
+ mButtonStateMap["clear_btn"] = true;
+ mButtonStateMap["cacheread_btn"] = false;
+ mButtonStateMap["cachewrite_btn"] = false;
+ mButtonStateMap["http_btn"] = false;
+ mButtonStateMap["decode_btn"] = false;
+ mButtonStateMap["gl_btn"] = false;
+ mButtonStateMap["refetchviscache_btn"] = true;
+ mButtonStateMap["refetchvishttp_btn"] = true;
+ updateButtons();
+
+ //stop everything
+ mDebugger->stopDebug();
+ mDebugger->clearHistory();
+}
+
+void LLFloaterTextureFetchDebugger::onClickCacheRead()
+{
+ disableButtons();
+
+ mDebugger->debugCacheRead();
+}
+
+void LLFloaterTextureFetchDebugger::onClickCacheWrite()
+{
+ disableButtons();
+
+ mDebugger->debugCacheWrite();
+}
+
+void LLFloaterTextureFetchDebugger::onClickHTTPLoad()
+{
+ disableButtons();
+
+ mDebugger->debugHTTP();
+}
+
+void LLFloaterTextureFetchDebugger::onClickDecode()
+{
+ disableButtons();
+
+ mDebugger->debugDecoder();
+}
+
+void LLFloaterTextureFetchDebugger::onClickGLTexture()
+{
+ disableButtons();
+
+ mDebugger->debugGLTextureCreation();
+}
+
+void LLFloaterTextureFetchDebugger::onClickRefetchVisCache()
+{
+ disableButtons();
+
+ mDebugger->debugRefetchVisibleFromCache();
+}
+
+void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP()
+{
+ disableButtons();
+
+ mDebugger->debugRefetchVisibleFromHTTP();
+}
+
+void LLFloaterTextureFetchDebugger::draw()
+{
+ //total number of fetched textures
+ {
+ getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures()));
+ }
+
+ //total number of fetching requests
+ {
+ getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests()));
+ }
+
+ //total number of cache hits
+ {
+ getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits()));
+ }
+
+ //total number of visible textures
+ {
+ getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures()));
+ }
+
+ //total number of visible texture fetching requests
+ {
+ getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests()));
+ }
+
+ //total number of fetched data
+ {
+ 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
+ {
+ getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10));
+ getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10));
+ }
+
+ //total number of rendered fetched data
+ {
+ 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
+ if(mDebugger->getCacheReadTime() < 0.f)
+ {
+ getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime()));
+ }
+
+ //total time on cache writings
+ if(mDebugger->getCacheWriteTime() < 0.f)
+ {
+ getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime()));
+ }
+
+ //total time on decoding
+ if(mDebugger->getDecodeTime() < 0.f)
+ {
+ getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime()));
+ }
+
+ //total time on gl texture creation
+ if(mDebugger->getGLCreationTime() < 0.f)
+ {
+ getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime()));
+ }
+
+ //total time on HTTP fetching
+ if(mDebugger->getHTTPTime() < 0.f)
+ {
+ getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime()));
+ }
+
+ //total time on entire fetching
+ {
+ 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
new file mode 100644
index 0000000000..33012c6a3d
--- /dev/null
+++ b/indra/newview/llfloatertexturefetchdebugger.h
@@ -0,0 +1,71 @@
+/**
+ * @file llfloatertexturefetchdebugger.h
+ * @brief texture fetching debugger window, debug use only
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
+#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
+
+#include "llfloater.h"
+class LLTextureFetchDebugger;
+
+class LLFloaterTextureFetchDebugger : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+ /// initialize all the callbacks for the menu
+
+ virtual BOOL postBuild() ;
+ virtual void draw() ;
+
+ void onChangeTexelPixelRatio();
+
+ void onClickStart();
+ void onClickClear();
+ void onClickClose();
+
+ void onClickCacheRead();
+ void onClickCacheWrite();
+ void onClickHTTPLoad();
+ void onClickDecode();
+ void onClickGLTexture();
+
+ void onClickRefetchVisCache();
+ void onClickRefetchVisHTTP();
+public:
+ void idle() ;
+
+private:
+ LLFloaterTextureFetchDebugger(const LLSD& key);
+ virtual ~LLFloaterTextureFetchDebugger();
+
+ void updateButtons();
+ void disableButtons();
+
+private:
+ LLTextureFetchDebugger* mDebugger;
+ std::map<std::string, bool> mButtonStateMap;
+};
+
+#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 2e1b409fa7..efb6ed6079 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -54,7 +54,9 @@
#include "llworld.h"
#include "llsdutil.h"
#include "llstartup.h"
+#include "llviewerstats.h"
+bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128);
LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128);
@@ -63,6 +65,7 @@ class LLTextureFetchWorker : public LLWorkerClass
{
friend class LLTextureFetch;
friend class HTTPGetResponder;
+ friend class LLTextureFetchDebugger;
private:
class CacheReadResponder : public LLTextureCache::ReadResponder
@@ -265,6 +268,7 @@ private:
BOOL mNeedsAux;
BOOL mHaveAllData;
BOOL mInLocalCache;
+ BOOL mInCache;
bool mCanUseHTTP ;
bool mCanUseNET ; //can get from asset server.
S32 mHTTPFailCount;
@@ -677,6 +681,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mNeedsAux(FALSE),
mHaveAllData(FALSE),
mInLocalCache(FALSE),
+ mInCache(FALSE),
mCanUseHTTP(true),
mHTTPFailCount(0),
mRetryAttempt(0),
@@ -906,6 +911,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mCacheReadHandle = LLTextureCache::nullHandle();
mCacheWriteHandle = LLTextureCache::nullHandle();
mState = LOAD_FROM_TEXTURE_CACHE;
+ mInCache = FALSE;
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;
@@ -994,6 +1000,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mFormattedImage->getDataSize() > 0);
mLoadedDiscard = mDesiredDiscard;
mState = DECODE_IMAGE;
+ mInCache = TRUE;
mWriteToCacheState = NOT_WRITE ;
LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
<< " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
@@ -1418,6 +1425,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
{
if (mDecoded)
{
+ if(mFetcher->getFetchDebugger() && !mInLocalCache)
+ {
+ mFetcher->getFetchDebugger()->addHistoryEntry(this);
+ }
+
if (mDecodedDiscard < 0)
{
LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL;
@@ -1847,11 +1859,18 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHTTPTextureBits(0),
mTotalHTTPRequests(0),
mCurlGetRequest(NULL),
- mQAMode(qa_mode)
+ mQAMode(qa_mode),
+ mFetchDebugger(NULL)
{
mCurlPOSTRequestCount = 0;
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
+
+ LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
+ if(LLTextureFetchDebugger::isEnabled())
+ {
+ mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ;
+ }
}
LLTextureFetch::~LLTextureFetch()
@@ -1866,11 +1885,17 @@ LLTextureFetch::~LLTextureFetch()
}
// ~LLQueuedThread() called here
+
+ delete mFetchDebugger;
}
bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)
{
+ if(mFetcherLocked)
+ {
+ return false;
+ }
if (mDebugPause)
{
return false;
@@ -2292,6 +2317,11 @@ void LLTextureFetch::startThread()
{
// Construct mCurlGetRequest from Worker Thread
mCurlGetRequest = new LLCurlRequest();
+
+ if(mFetchDebugger)
+ {
+ mFetchDebugger->setCurlGetRequest(mCurlGetRequest);
+ }
}
// WORKER THREAD
@@ -2300,6 +2330,10 @@ void LLTextureFetch::endThread()
// Destroy mCurlGetRequest from Worker Thread
delete mCurlGetRequest;
mCurlGetRequest = NULL;
+ if(mFetchDebugger)
+ {
+ mFetchDebugger->setCurlGetRequest(NULL);
+ }
}
// WORKER THREAD
@@ -2837,7 +2871,6 @@ void LLTextureFetch::cmdDoWork()
}
}
-
//////////////////////////////////////////////////////////////////////////////
// Private (anonymous) class methods implementing the command scheme.
@@ -3041,5 +3074,659 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics)
} // end of anonymous namespace
+///////////////////////////////////////////////////////////////////////////////////////////
+//Start LLTextureFetchDebugger
+///////////////////////////////////////////////////////////////////////////////////////////
+//---------------------
+class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder
+{
+public:
+ LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image)
+ : mDebugger(debugger), mID(id)
+ {
+ setImage(image);
+ }
+ virtual void completed(bool success)
+ {
+ mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal);
+ }
+private:
+ LLTextureFetchDebugger* mDebugger;
+ S32 mID;
+};
+
+class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder
+{
+public:
+ LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id)
+ : mDebugger(debugger), mID(id)
+ {
+ }
+ virtual void completed(bool success)
+ {
+ mDebugger->callbackCacheWrite(mID, success);
+ }
+private:
+ LLTextureFetchDebugger* mDebugger;
+ S32 mID;
+};
+
+class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder
+{
+public:
+ LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id)
+ : mDebugger(debugger), mID(id)
+ {
+ }
+ virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
+ {
+ mDebugger->callbackDecoded(mID, success, raw, aux);
+ }
+private:
+ LLTextureFetchDebugger* mDebugger;
+ S32 mID;
+};
+
+class LLDebuggerHTTPResponder : public LLCurl::Responder
+{
+public:
+ LLDebuggerHTTPResponder(LLTextureFetchDebugger* debugger, S32 index)
+ : mDebugger(debugger), mIndex(index)
+ {
+ }
+ virtual void completedRaw(U32 status, const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ bool success = false;
+ bool partial = false;
+ if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES)
+ {
+ success = true;
+ if (HTTP_PARTIAL_CONTENT == status) // partial information
+ {
+ partial = true;
+ }
+ }
+ if (!success)
+ {
+ llinfos << "Fetch Debugger : CURL GET FAILED, index = " << mIndex << ", status:" << status << " reason:" << reason << llendl;
+ }
+ mDebugger->callbackHTTP(mIndex, channels, buffer, partial, success);
+ }
+ virtual bool followRedir()
+ {
+ return true;
+ }
+private:
+ LLTextureFetchDebugger* mDebugger;
+ S32 mIndex;
+};
+
+LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) :
+ mFetcher(fetcher),
+ mTextureCache(cache),
+ mImageDecodeThread(imagedecodethread),
+ mCurlGetRequest(NULL)
+{
+ init();
+}
+
+LLTextureFetchDebugger::~LLTextureFetchDebugger()
+{
+ mFetchingHistory.clear();
+ stopDebug();
+}
+
+void LLTextureFetchDebugger::init()
+{
+ mState = IDLE;
+
+ mCacheReadTime = -1.f;
+ mCacheWriteTime = -1.f;
+ mDecodingTime = -1.f;
+ mHTTPTime = -1.f;
+ mGLCreationTime = -1.f;
+ mTotalFetchingTime = 0.f;
+ mRefetchVisCacheTime = -1.f;
+ mRefetchVisHTTPTime = -1.f;
+
+ mNumFetchedTextures = 0;
+ mNumCacheHits = 0;
+ mNumVisibleFetchedTextures = 0;
+ mNumVisibleFetchingRequests = 0;
+ mFetchedData = 0;
+ mDecodedData = 0;
+ mVisibleFetchedData = 0;
+ 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();
+
+ //wait for all works to be done
+ while(1)
+ {
+ S32 pending = 0;
+ pending += LLAppViewer::getTextureCache()->update(1);
+ pending += LLAppViewer::getImageDecodeThread()->update(1);
+ pending += LLAppViewer::getTextureFetch()->update(1);
+ if(!pending)
+ {
+ break;
+ }
+ }
+
+ //collect statistics
+ mTotalFetchingTime = gDebugTimers[0].getElapsedTimeF32() - mTotalFetchingTime;
+
+ std::set<LLUUID> fetched_textures;
+ S32 size = mFetchingHistory.size();
+ for(S32 i = 0 ; i < size; i++)
+ {
+ bool in_list = true;
+ if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end())
+ {
+ fetched_textures.insert(mFetchingHistory[i].mID);
+ in_list = false;
+ }
+
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(mFetchingHistory[i].mID);
+ if(tex && tex->isJustBound()) //visible
+ {
+ if(!in_list)
+ {
+ mNumVisibleFetchedTextures++;
+ }
+ mNumVisibleFetchingRequests++;
+
+ mVisibleFetchedData += mFetchingHistory[i].mFetchedSize;
+ mVisibleDecodedData += mFetchingHistory[i].mDecodedSize;
+
+ if(tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel)
+ {
+ mRenderedData += mFetchingHistory[i].mFetchedSize;
+ mRenderedDecodedData += mFetchingHistory[i].mDecodedSize;
+ mRenderedPixels += tex->getWidth() * tex->getHeight();
+ }
+ }
+ }
+
+ mNumFetchedTextures = fetched_textures.size();
+}
+
+void LLTextureFetchDebugger::stopDebug()
+{
+ //clear the current debug work
+ S32 size = mFetchingHistory.size();
+ switch(mState)
+ {
+ case READ_CACHE:
+ for(S32 i = 0 ; i < size; i++)
+ {
+ if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle())
+ {
+ mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true);
+ }
+ }
+ break;
+ case WRITE_CACHE:
+ for(S32 i = 0 ; i < size; i++)
+ {
+ if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle())
+ {
+ mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true);
+ }
+ }
+ break;
+ case DECODING:
+ break;
+ case HTTP_FETCHING:
+ break;
+ case GL_TEX:
+ break;
+ default:
+ break;
+ }
+
+ while(1)
+ {
+ if(update())
+ {
+ break;
+ }
+ }
+
+ //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();
+}
+
+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->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()));
+}
+
+void LLTextureFetchDebugger::lockCache()
+{
+}
+
+void LLTextureFetchDebugger::unlockCache()
+{
+}
+
+void LLTextureFetchDebugger::debugCacheRead()
+{
+ lockCache();
+ llassert_always(mState == IDLE);
+ mTimer.reset();
+ mState = READ_CACHE;
+
+ S32 size = mFetchingHistory.size();
+ for(S32 i = 0 ; i < size ; i++)
+ {
+ mFetchingHistory[i].mFormattedImage = NULL;
+ mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize,
+ new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage));
+ }
+}
+
+void LLTextureFetchDebugger::clearCache()
+{
+ S32 size = mFetchingHistory.size();
+ {
+ std::set<LLUUID> deleted_list;
+ for(S32 i = 0 ; i < size ; i++)
+ {
+ if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end())
+ {
+ deleted_list.insert(mFetchingHistory[i].mID);
+ mTextureCache->removeFromCache(mFetchingHistory[i].mID);
+ }
+ }
+ }
+}
+
+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++)
+ {
+ if(mFetchingHistory[i].mFormattedImage.notNull())
+ {
+ 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));
+ }
+ }
+}
+
+void LLTextureFetchDebugger::lockDecoder()
+{
+}
+
+void LLTextureFetchDebugger::unlockDecoder()
+{
+}
+
+void LLTextureFetchDebugger::debugDecoder()
+{
+ lockDecoder();
+ llassert_always(mState == IDLE);
+ mTimer.reset();
+ mState = DECODING;
+
+ S32 size = mFetchingHistory.size();
+ for(S32 i = 0 ; i < size ; i++)
+ {
+ if(mFetchingHistory[i].mFormattedImage.isNull())
+ {
+ continue;
+ }
+
+ mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL,
+ mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux,
+ new LLDebuggerDecodeResponder(this, i));
+ }
+}
+
+void LLTextureFetchDebugger::debugHTTP()
+{
+ llassert_always(mState == IDLE);
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ llinfos << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << llendl;
+ return;
+ }
+
+ mHTTPUrl = region->getHttpUrl();
+ if (mHTTPUrl.empty())
+ {
+ llinfos << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << llendl;
+ return;
+ }
+
+ mTimer.reset();
+ mState = HTTP_FETCHING;
+
+ S32 size = mFetchingHistory.size();
+ for (S32 i = 0 ; i < size ; i++)
+ {
+ mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE;
+ mFetchingHistory[i].mCurlReceivedSize = 0;
+ mFetchingHistory[i].mHTTPFailCount = 0;
+ }
+ mNbCurlRequests = 0;
+ mNbCurlCompleted = 0;
+
+ fillCurlQueue();
+}
+
+S32 LLTextureFetchDebugger::fillCurlQueue()
+{
+ if (mNbCurlRequests == 24)
+ return mNbCurlRequests;
+
+ S32 size = mFetchingHistory.size();
+ for (S32 i = 0 ; i < size ; i++)
+ {
+ 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.
+ requestedSize = llmax(0,requestedSize);
+ // We request the whole file if the size was set to an absurdly high value (meaning all file)
+ 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
+ {
+ break;
+ }
+ }
+ //llinfos << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << llendl;
+ return mNbCurlRequests;
+}
+
+void LLTextureFetchDebugger::debugGLTextureCreation()
+{
+ llassert_always(mState == IDLE);
+ mState = GL_TEX;
+ std::vector<LLViewerFetchedTexture*> tex_list;
+
+ S32 size = mFetchingHistory.size();
+ for(S32 i = 0 ; i < size ; i++)
+ {
+ if(mFetchingHistory[i].mRawImage.notNull())
+ {
+ LLViewerFetchedTexture* tex = gTextureList.findImage(mFetchingHistory[i].mID) ;
+ if(tex && !tex->isForSculptOnly())
+ {
+ tex->destroyGLTexture() ;
+ tex_list.push_back(tex);
+ }
+ }
+ }
+
+ mTimer.reset();
+ S32 j = 0 ;
+ S32 size1 = tex_list.size();
+ for(S32 i = 0 ; i < size && j < size1; i++)
+ {
+ if(mFetchingHistory[i].mRawImage.notNull())
+ {
+ if(mFetchingHistory[i].mID == tex_list[j]->getID())
+ {
+ tex_list[j]->createGLTexture(mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mRawImage, 0, TRUE, tex_list[j]->getBoostLevel());
+ j++;
+ }
+ }
+ }
+
+ mGLCreationTime = mTimer.getElapsedTimeF32() ;
+ 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)
+ {
+ case READ_CACHE:
+ if(!mTextureCache->update(1))
+ {
+ mCacheReadTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ unlockCache();
+ }
+ break;
+ case WRITE_CACHE:
+ if(!mTextureCache->update(1))
+ {
+ mCacheWriteTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ unlockCache();
+ }
+ break;
+ case DECODING:
+ if(!mImageDecodeThread->update(1))
+ {
+ mDecodingTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ unlockDecoder();
+ }
+ break;
+ case HTTP_FETCHING:
+ mCurlGetRequest->process();
+ LLCurl::getCurlThread()->update(1);
+ if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size())
+ {
+ mHTTPTime = mTimer.getElapsedTimeF32() ;
+ mState = IDLE;
+ }
+ break;
+ 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;
+ }
+
+ return mState == IDLE;
+}
+
+void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
+ S32 imagesize, BOOL islocal)
+{
+ if (success)
+ {
+ mFetchingHistory[id].mFormattedImage = image;
+ }
+ mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false);
+ mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
+}
+
+void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success)
+{
+ mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle);
+ mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle();
+}
+
+void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux)
+{
+ if (success)
+ {
+ llassert_always(raw);
+ mFetchingHistory[id].mRawImage = raw;
+ }
+}
+
+void LLTextureFetchDebugger::callbackHTTP(S32 id, const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer,
+ bool partial, bool success)
+{
+ mNbCurlRequests--;
+ if (success)
+ {
+ mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
+ mNbCurlCompleted++;
+
+ S32 data_size = buffer->countAfter(channels.in(), NULL);
+ mFetchingHistory[id].mCurlReceivedSize += data_size;
+ //llinfos << "Fetch Debugger : got results for " << id << ", data_size = " << data_size << ", received = " << mFetchingHistory[id].mCurlReceivedSize << ", requested = " << mFetchingHistory[id].mRequestedSize << ", partial = " << partial << llendl;
+ if ((mFetchingHistory[id].mCurlReceivedSize >= mFetchingHistory[id].mRequestedSize) || !partial || (mFetchingHistory[id].mRequestedSize == 600))
+ {
+ 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());
+ {
+ // For now, create formatted image based on extension
+ std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[id].mID.asString().c_str();
+ std::string extension = gDirUtilp->getExtension(texture_url);
+ mFetchingHistory[id].mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension));
+ if (mFetchingHistory[id].mFormattedImage.isNull())
+ {
+ mFetchingHistory[id].mFormattedImage = new LLImageJ2C; // default
+ }
+ }
+
+ mFetchingHistory[id].mFormattedImage->setData(d_buffer, data_size);
+ }
+ }
+ else //failed
+ {
+ mFetchingHistory[id].mHTTPFailCount++;
+ if(mFetchingHistory[id].mHTTPFailCount < 5)
+ {
+ // Fetch will have to be redone
+ mFetchingHistory[id].mCurlState = FetchEntry::CURL_NOT_DONE;
+ }
+ else //skip
+ {
+ mFetchingHistory[id].mCurlState = FetchEntry::CURL_DONE;
+ mNbCurlCompleted++;
+ }
+ }
+}
+
+
+//---------------------
+///////////////////////////////////////////////////////////////////////////////////////////
+//End LLTextureFetchDebugger
+///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 710dd67e99..107e1623b0 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -34,14 +34,17 @@
#include "llcurl.h"
#include "lltextureinfo.h"
#include "llapr.h"
+#include "llimageworker.h"
+//#include "lltexturecache.h"
class LLViewerTexture;
class LLTextureFetchWorker;
class HTTPGetResponder;
-class LLTextureCache;
class LLImageDecodeThread;
class LLHost;
class LLViewerAssetStats;
+class LLTextureFetchDebugger;
+class LLTextureCache;
// Interface class
class LLTextureFetch : public LLWorkerThread
@@ -212,7 +215,195 @@ public:
// attempt to log metrics follows a break in the metrics stream
// reporting due to either startup or a problem POSTing data.
static volatile bool svMetricsDataBreak;
+
+private:
+ //debug use
+ LLTextureFetchDebugger* mFetchDebugger;
+ bool mFetcherLocked;
+
+public:
+ //debug use
+ LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;}
+ void lockFetcher(bool lock) { mFetcherLocked = lock;}
};
+//debug use
+class LLTextureFetchDebugger
+{
+ friend class LLTextureFetch;
+public:
+ LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ;
+ ~LLTextureFetchDebugger();
+
+public:
+ enum e_debug_state
+ {
+ IDLE = 0,
+ READ_CACHE,
+ WRITE_CACHE,
+ DECODING,
+ HTTP_FETCHING,
+ GL_TEX,
+ REFETCH_VIS_CACHE,
+ REFETCH_VIS_HTTP,
+ REFETCH_ALL_CACHE,
+ REFETCH_ALL_HTTP,
+ INVALID
+ };
+
+private:
+ struct FetchEntry
+ {
+ enum e_curl_state
+ {
+ CURL_NOT_DONE = 0,
+ CURL_IN_PROGRESS,
+ CURL_DONE
+ };
+ LLUUID mID;
+ S32 mRequestedSize;
+ S32 mDecodedLevel;
+ S32 mFetchedSize;
+ S32 mDecodedSize;
+ BOOL mNeedsAux;
+ U32 mCacheHandle;
+ LLPointer<LLImageFormatted> mFormattedImage;
+ LLPointer<LLImageRaw> mRawImage;
+ e_curl_state mCurlState;
+ S32 mCurlReceivedSize;
+ S32 mHTTPFailCount;
+
+ FetchEntry() :
+ mDecodedLevel(-1),
+ mFetchedSize(0),
+ mDecodedSize(0)
+ {}
+ FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) :
+ mID(id),
+ mRequestedSize(r_size),
+ mDecodedLevel(level),
+ mFetchedSize(f_size),
+ mDecodedSize(d_size),
+ mNeedsAux(false),
+ mHTTPFailCount(0)
+ {}
+ };
+ std::vector<FetchEntry> mFetchingHistory;
+
+ e_debug_state mState;
+
+ F32 mCacheReadTime;
+ F32 mCacheWriteTime;
+ F32 mDecodingTime;
+ F32 mHTTPTime;
+ F32 mGLCreationTime;
+
+ F32 mTotalFetchingTime;
+ F32 mRefetchVisCacheTime;
+ F32 mRefetchVisHTTPTime;
+
+ LLTimer mTimer;
+
+ LLTextureFetch* mFetcher;
+ LLTextureCache* mTextureCache;
+ LLImageDecodeThread* mImageDecodeThread;
+ LLCurlRequest* mCurlGetRequest;
+
+ S32 mNumFetchedTextures;
+ S32 mNumCacheHits;
+ S32 mNumVisibleFetchedTextures;
+ S32 mNumVisibleFetchingRequests;
+ U32 mFetchedData;
+ U32 mDecodedData;
+ U32 mVisibleFetchedData;
+ U32 mVisibleDecodedData;
+ U32 mRenderedData;
+ U32 mRenderedDecodedData;
+ U32 mFetchedPixels;
+ U32 mRenderedPixels;
+ U32 mRefetchedData;
+ U32 mRefetchedPixels;
+
+ BOOL mFreezeHistory;
+
+ std::string mHTTPUrl;
+ S32 mNbCurlRequests;
+ S32 mNbCurlCompleted;
+
+public:
+ bool update(); //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 callbackCacheRead(S32 id, bool success, LLImageFormatted* image,
+ S32 imagesize, BOOL islocal);
+ void callbackCacheWrite(S32 id, bool success);
+ void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux);
+ void callbackHTTP(S32 id, const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer,
+ bool partial, bool success);
+
+
+ e_debug_state getState() {return mState;}
+ S32 getNumFetchedTextures() {return mNumFetchedTextures;}
+ S32 getNumFetchingRequests() {return mFetchingHistory.size();}
+ S32 getNumCacheHits() {return mNumCacheHits;}
+ S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;}
+ S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;}
+ U32 getFetchedData() {return mFetchedData;}
+ U32 getDecodedData() {return mDecodedData;}
+ U32 getVisibleFetchedData() {return mVisibleFetchedData;}
+ 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;}
+ F32 getDecodeTime() {return mDecodingTime;}
+ 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();
+
+ void lockCache();
+ void unlockCache();
+
+ void lockDecoder();
+ void unlockDecoder();
+
+ S32 fillCurlQueue();
+
+private:
+ static bool sDebuggerEnabled;
+public:
+ static bool isEnabled() {return sDebuggerEnabled;}
+};
#endif // LL_LLTEXTUREFETCH_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index bb870f7651..a7ca7a0836 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -103,6 +103,7 @@
#include "llfloatertelehub.h"
#include "llfloatertestinspectors.h"
#include "llfloatertestlistview.h"
+#include "llfloatertexturefetchdebugger.h"
#include "llfloatertools.h"
#include "llfloatertos.h"
#include "llfloatertopobjects.h"
@@ -227,6 +228,11 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
+
+ if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"))
+ {
+ LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>);
+ }
LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7bdfd6df1d..2a3ba4e603 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2286,6 +2286,14 @@ class LLDevelopSetLoggingLevel : public view_listener_t
}
};
+class LLDevelopTextureFetchDebugger : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
+ }
+};
+
//////////////////
// ADMIN MENU //
//////////////////
@@ -8308,6 +8316,9 @@ void initialize_menus()
// Develop >Set logging level
view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
+
+ //Develop (Texture Fetch Debug Console)
+ view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index d5b53f3cb1..ea329f6aac 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -98,6 +98,8 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
F32 LLViewerTexture::sCurrentTime = 0.0f ;
BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
+F32 LLViewerTexture::sTexelPixelRatio = 1.0f;
+
LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
@@ -178,7 +180,12 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id)
}
return tex ;
}
-
+
+LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id)
+{
+ return gTextureList.findImage(id);
+}
+
LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
{
return LLViewerMediaTexture::findMediaTexture(media_id) ;
@@ -385,6 +392,7 @@ void LLViewerTextureManager::cleanup()
LLImageGL::sDefaultGLTexture = NULL ;
LLViewerTexture::sNullImagep = NULL;
LLViewerTexture::sBlackImagep = NULL;
+ LLViewerTexture::sCheckerBoardImagep = NULL;
LLViewerFetchedTexture::sDefaultImagep = NULL;
LLViewerFetchedTexture::sSmokeImagep = NULL;
LLViewerFetchedTexture::sMissingAssetImagep = NULL;
@@ -401,6 +409,7 @@ void LLViewerTextureManager::cleanup()
void LLViewerTexture::initClass()
{
LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
+ sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio");
}
// static
@@ -722,6 +731,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co
mNeedsGLTexture = TRUE ;
}
+ virtual_size *= sTexelPixelRatio;
if(!mMaxVirtualSizeResetCounter)
{
//flag to reset the values because the old values are used.
@@ -1297,6 +1307,7 @@ void LLViewerFetchedTexture::cleanup()
mCachedRawDiscardLevel = -1 ;
mCachedRawImageReady = FALSE ;
mSavedRawImage = NULL ;
+ mSavedRawDiscardLevel = -1;
}
void LLViewerFetchedTexture::setForSculpt()
@@ -2139,16 +2150,29 @@ bool LLViewerFetchedTexture::updateFetch()
return mIsFetching ? true : false;
}
-void LLViewerFetchedTexture::forceToDeleteRequest()
-{
- if (mHasFetcher)
- {
- LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
- mHasFetcher = FALSE;
- mIsFetching = FALSE ;
- resetTextureStats();
- }
-}
+void LLViewerFetchedTexture::clearFetchedResults()
+{
+ llassert_always(!mNeedsCreateTexture && !mIsFetching);
+
+ cleanup();
+ destroyGLTexture();
+
+ if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate
+ {
+ mGLTexturep->forceToInvalidateGLTexture();
+ }
+}
+
+void LLViewerFetchedTexture::forceToDeleteRequest()
+{
+ if (mHasFetcher)
+ {
+ LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+ mHasFetcher = FALSE;
+ mIsFetching = FALSE ;
+ resetTextureStats();
+ }
+}
void LLViewerFetchedTexture::setIsMissingAsset()
{
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 6ddff3e485..41bf625225 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -310,6 +310,7 @@ protected:
} LLGLTextureState;
LLGLTextureState mTextureState ;
+ static F32 sTexelPixelRatio;
public:
static const U32 sCurrentFileVersion;
static S32 sImageCount;
@@ -433,6 +434,8 @@ public:
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.
@@ -701,6 +704,7 @@ public:
//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
//
static LLViewerTexture* findTexture(const LLUUID& id) ;
+ static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id) ;
static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ;
static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 64e2c1f791..7038ea24ce 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -109,6 +109,8 @@ public:
void doPreloadImages();
void doPrefetchImages();
+ void clearFetchingRequests();
+
static S32 getMinVideoRamSetting();
static S32 getMaxVideoRamSetting(bool get_recommended = false);
@@ -163,9 +165,7 @@ private:
// Request image from a specific host, used for baked avatar textures.
// Implemented in header in case someone changes default params above. JC
LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host)
- { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
-
- void clearFetchingRequests();
+ { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
public:
typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;
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
new file mode 100644
index 0000000000..44b6a63bca
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="550"
+ layout="topleft"
+ name="TexFetchDebugger"
+ help_topic="texfetchdebugger"
+ title="Texture Fetching Debugger"
+ width="540">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="total_num_fetched_label"
+ top="30"
+ width="400">
+ 1, Total number of fetched textures: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_fetching_requests_label"
+ top_delta="25"
+ width="400">
+ 2, Total number of fetching requests: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_cache_hits_label"
+ top_delta="25"
+ width="400">
+ 3, Total number of cache hits: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_visible_tex_label"
+ top_delta="25"
+ width="400">
+ 4, Total number of visible textures: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_num_visible_tex_fetch_req_label"
+ top_delta="25"
+ width="450">
+ 5, Total number of visible texture fetching requests: [NUM]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_data_label"
+ top_delta="25"
+ width="530">
+ 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_vis_data_label"
+ top_delta="25"
+ width="480">
+ 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_fetched_rendered_data_label"
+ top_delta="25"
+ width="530">
+ 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_cache_read_label"
+ top_delta="25"
+ width="400">
+ 9, Total time on cache readings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_cache_write_label"
+ top_delta="25"
+ width="400">
+ 10, Total time on cache writings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_decode_label"
+ top_delta="25"
+ width="400">
+ 11, Total time on decodings: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_gl_label"
+ top_delta="25"
+ width="400">
+ 12, Total time on gl texture creation: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_http_label"
+ top_delta="25"
+ width="400">
+ 13, Total time on HTTP fetching: [TIME] seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_time_fetch_label"
+ top_delta="25"
+ 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="2"
+ follows="left|top"
+ height="20"
+ increment="0.01"
+ initial_value="1.0"
+ label="17, Ratio of Texel/Pixel:"
+ label_width="130"
+ layout="topleft"
+ left_delta="0"
+ max_val="10.0"
+ min_val="0.01"
+ name="texel_pixel_ratio"
+ top_delta="30"
+ width="200">
+ <spinner.commit_callback
+ function="TexFetchDebugger.ChangeTexelPixelRatio" />
+ </spinner>
+ <button
+ follows="left|top"
+ height="20"
+ label="Start"
+ layout="topleft"
+ left_delta="0"
+ name="start_btn"
+ top_delta="30"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Start" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Reset"
+ layout="topleft"
+ left_pad="7"
+ name="clear_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Clear" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Close"
+ layout="topleft"
+ left_pad="7"
+ name="close_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Close" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Cache Read"
+ layout="topleft"
+ left="10"
+ name="cacheread_btn"
+ top_delta="30"
+ width="80">
+ <button.commit_callback
+ function="TexFetchDebugger.CacheRead" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Cache Write"
+ layout="topleft"
+ left_pad="7"
+ name="cachewrite_btn"
+ top_delta="0"
+ width="80">
+ <button.commit_callback
+ function="TexFetchDebugger.CacheWrite" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="HTTP"
+ layout="topleft"
+ left_pad="7"
+ name="http_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.HTTPLoad" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Decode"
+ layout="topleft"
+ left_pad="7"
+ name="decode_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="TexFetchDebugger.Decode" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="GL Texture"
+ layout="topleft"
+ left_pad="7"
+ name="gl_btn"
+ top_delta="0"
+ width="70">
+ <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>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 8b0152b1a2..5d46b0f98d 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1876,7 +1876,7 @@
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="texture" />
- </menu_item_check>
+ </menu_item_check>
<menu_item_check
label="Debug Console"
name="Debug Console"
@@ -1931,7 +1931,20 @@
function="Advanced.ToggleConsole"
parameter="scene view" />
</menu_item_check>
-
+ <menu_item_call
+ enabled="false"
+ visible="false"
+ label="Texture Fetch Debug Console"
+ name="Texture Fetch Debug Console">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="tex_fetch_debugger" />
+ <on_enable
+ function="Develop.SetTexFetchDebugger" />
+ <on_visible
+ function="Develop.SetTexFetchDebugger" />
+ </menu_item_call>
+
<menu_item_separator/>
<menu_item_call