lltextureview.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:35k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltextureview.cpp
  3.  * @brief LLTextureView class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include <set>
  34. #include "lltextureview.h"
  35. #include "llrect.h"
  36. #include "llerror.h"
  37. #include "lllfsthread.h"
  38. #include "llui.h"
  39. #include "llimageworker.h"
  40. #include "llrender.h"
  41. #include "lltooltip.h"
  42. #include "llappviewer.h"
  43. #include "llselectmgr.h"
  44. #include "lltexlayer.h"
  45. #include "lltexturecache.h"
  46. #include "lltexturefetch.h"
  47. #include "llviewercontrol.h"
  48. #include "llviewerobject.h"
  49. #include "llviewertexture.h"
  50. #include "llviewertexturelist.h"
  51. #include "llvovolume.h"
  52. extern F32 texmem_lower_bound_scale;
  53. LLTextureView *gTextureView = NULL;
  54. LLTextureSizeView *gTextureSizeView = NULL;
  55. LLTextureSizeView *gTextureCategoryView = NULL;
  56. //static
  57. std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages;
  58. ////////////////////////////////////////////////////////////////////////////
  59. static std::string title_string1a("Tex UUID Area  DDis(Req)  DecodePri(Fetch)     [download] pk/max");
  60. static std::string title_string1b("Tex UUID Area  DDis(Req)  Fetch(DecodePri)     [download] pk/max");
  61. static std::string title_string2("State");
  62. static std::string title_string3("Pkt Bnd");
  63. static std::string title_string4("  W x H (Dis) Mem");
  64. static S32 title_x1 = 0;
  65. static S32 title_x2 = 460;
  66. static S32 title_x3 = title_x2 + 40;
  67. static S32 title_x4 = title_x3 + 50;
  68. static S32 texture_bar_height = 8;
  69. ////////////////////////////////////////////////////////////////////////////
  70. class LLTextureBar : public LLView
  71. {
  72. public:
  73. LLPointer<LLViewerFetchedTexture> mImagep;
  74. S32 mHilite;
  75. public:
  76. struct Params : public LLInitParam::Block<Params, LLView::Params>
  77. {
  78. Mandatory<LLTextureView*> texture_view;
  79. Params()
  80. : texture_view("texture_view")
  81. {
  82. mouse_opaque(false);
  83. }
  84. };
  85. LLTextureBar(const Params& p)
  86. : LLView(p),
  87. mHilite(0),
  88. mTextureView(p.texture_view)
  89. {}
  90. virtual void draw();
  91. virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
  92. virtual LLRect getRequiredRect(); // Return the height of this object, given the set options.
  93. // Used for sorting
  94. struct sort
  95. {
  96. bool operator()(const LLView* i1, const LLView* i2)
  97. {
  98. LLTextureBar* bar1p = (LLTextureBar*)i1;
  99. LLTextureBar* bar2p = (LLTextureBar*)i2;
  100. LLViewerFetchedTexture *i1p = bar1p->mImagep;
  101. LLViewerFetchedTexture *i2p = bar2p->mImagep;
  102. F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
  103. F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
  104. if (pri1 > pri2)
  105. return true;
  106. else if (pri2 > pri1)
  107. return false;
  108. else
  109. return i1p->getID() < i2p->getID();
  110. }
  111. };
  112. struct sort_fetch
  113. {
  114. bool operator()(const LLView* i1, const LLView* i2)
  115. {
  116. LLTextureBar* bar1p = (LLTextureBar*)i1;
  117. LLTextureBar* bar2p = (LLTextureBar*)i2;
  118. LLViewerFetchedTexture *i1p = bar1p->mImagep;
  119. LLViewerFetchedTexture *i2p = bar2p->mImagep;
  120. U32 pri1 = i1p->getFetchPriority() ;
  121. U32 pri2 = i2p->getFetchPriority() ;
  122. if (pri1 > pri2)
  123. return true;
  124. else if (pri2 > pri1)
  125. return false;
  126. else
  127. return i1p->getID() < i2p->getID();
  128. }
  129. };
  130. private:
  131. LLTextureView* mTextureView;
  132. };
  133. void LLTextureBar::draw()
  134. {
  135. if (!mImagep)
  136. {
  137. return;
  138. }
  139. LLColor4 color;
  140. if (mImagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
  141. {
  142. color = LLColor4::cyan2;
  143. }
  144. else if (mHilite)
  145. {
  146. S32 idx = llclamp(mHilite,1,3);
  147. if (idx==1) color = LLColor4::orange;
  148. else if (idx==2) color = LLColor4::yellow;
  149. else color = LLColor4::pink2;
  150. }
  151. else if (mImagep->mDontDiscard)
  152. {
  153. color = LLColor4::green4;
  154. }
  155. else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE)
  156. {
  157. color = LLColor4::magenta;
  158. }
  159. else if (mImagep->getDecodePriority() <= 0.0f)
  160. {
  161. color = LLColor4::grey; color[VALPHA] = .7f;
  162. }
  163. else
  164. {
  165. color = LLColor4::white; color[VALPHA] = .7f;
  166. }
  167. // We need to draw:
  168. // The texture UUID or name
  169. // The progress bar for the texture, highlighted if it's being download
  170. // Various numerical stats.
  171. std::string tex_str;
  172. S32 left, right;
  173. S32 top = 0;
  174. S32 bottom = top + 6;
  175. LLColor4 clr;
  176. LLGLSUIDefault gls_ui;
  177. // Name, pixel_area, requested pixel area, decode priority
  178. std::string uuid_str;
  179. mImagep->mID.toString(uuid_str);
  180. uuid_str = uuid_str.substr(0,7);
  181. if (mTextureView->mOrderFetch)
  182. {
  183. tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)",
  184.    uuid_str.c_str(),
  185.    mImagep->mMaxVirtualSize,
  186.    mImagep->mDesiredDiscardLevel,
  187.    mImagep->mRequestedDiscardLevel,
  188.    mImagep->mFetchPriority,
  189.    mImagep->getDecodePriority());
  190. }
  191. else
  192. {
  193. tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)",
  194.    uuid_str.c_str(),
  195.    mImagep->mMaxVirtualSize,
  196.    mImagep->mDesiredDiscardLevel,
  197.    mImagep->mRequestedDiscardLevel,
  198.    mImagep->getDecodePriority(),
  199.    mImagep->mFetchPriority);
  200. }
  201. LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(),
  202.  color, LLFontGL::LEFT, LLFontGL::TOP);
  203. // State
  204. // Hack: mirrored from lltexturefetch.cpp
  205. struct { const std::string desc; LLColor4 color; } fetch_state_desc[] = {
  206. { "---", LLColor4::red }, // INVALID
  207. { "INI", LLColor4::white }, // INIT
  208. { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE
  209. { "DSK", LLColor4::blue }, // CACHE_POST
  210. { "NET", LLColor4::green }, // LOAD_FROM_NETWORK
  211. { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR
  212. { "REQ", LLColor4::yellow },// SEND_HTTP_REQ
  213. { "HTP", LLColor4::green }, // WAIT_HTTP_REQ
  214. { "DEC", LLColor4::yellow },// DECODE_IMAGE
  215. { "DEC", LLColor4::green }, // DECODE_IMAGE_UPDATE
  216. { "WRT", LLColor4::purple },// WRITE_TO_CACHE
  217. { "WRT", LLColor4::orange },// WAIT_ON_WRITE
  218. { "END", LLColor4::red },   // DONE
  219. #define LAST_STATE 12
  220. { "CRE", LLColor4::magenta }, // LAST_STATE+1
  221. { "FUL", LLColor4::green }, // LAST_STATE+2
  222. { "BAD", LLColor4::red }, // LAST_STATE+3
  223. { "MIS", LLColor4::red }, // LAST_STATE+4
  224. { "---", LLColor4::white }, // LAST_STATE+5
  225. };
  226. const S32 fetch_state_desc_size = (S32)LL_ARRAY_SIZE(fetch_state_desc);
  227. S32 state =
  228. mImagep->mNeedsCreateTexture ? LAST_STATE+1 :
  229. mImagep->mFullyLoaded ? LAST_STATE+2 :
  230. mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 :
  231. mImagep->mIsMissingAsset ? LAST_STATE+4 :
  232. !mImagep->mIsFetching ? LAST_STATE+5 :
  233. mImagep->mFetchState;
  234. state = llclamp(state,0,fetch_state_desc_size-1);
  235. LLFontGL::getFontMonospace()->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, getRect().getHeight(),
  236.  fetch_state_desc[state].color,
  237.  LLFontGL::LEFT, LLFontGL::TOP);
  238. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  239. // Draw the progress bar.
  240. S32 bar_width = 100;
  241. S32 bar_left = 260;
  242. left = bar_left;
  243. right = left + bar_width;
  244. gGL.color4f(0.f, 0.f, 0.f, 0.75f);
  245. gl_rect_2d(left, top, right, bottom);
  246. F32 data_progress = mImagep->mDownloadProgress;
  247. if (data_progress > 0.0f)
  248. {
  249. // Downloaded bytes
  250. right = left + llfloor(data_progress * (F32)bar_width);
  251. if (right > left)
  252. {
  253. gGL.color4f(0.f, 0.f, 1.f, 0.75f);
  254. gl_rect_2d(left, top, right, bottom);
  255. }
  256. }
  257. S32 pip_width = 6;
  258. S32 pip_space = 14;
  259. S32 pip_x = title_x3 + pip_space/2;
  260. // Draw the packet pip
  261. const F32 pip_max_time = 5.f;
  262. F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32();
  263. if (last_event < pip_max_time)
  264. {
  265. clr = LLColor4::white; 
  266. }
  267. else
  268. {
  269. last_event = mImagep->mRequestDeltaTime;
  270. if (last_event < pip_max_time)
  271. {
  272. clr = LLColor4::green;
  273. }
  274. else
  275. {
  276. last_event = mImagep->mFetchDeltaTime;
  277. if (last_event < pip_max_time)
  278. {
  279. clr = LLColor4::yellow;
  280. }
  281. }
  282. }
  283. if (last_event < pip_max_time)
  284. {
  285. clr.setAlpha(1.f - last_event/pip_max_time);
  286. gGL.color4fv(clr.mV);
  287. gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
  288. }
  289. pip_x += pip_width + pip_space;
  290. // we don't want to show bind/resident pips for textures using the default texture
  291. if (mImagep->hasGLTexture())
  292. {
  293. // Draw the bound pip
  294. last_event = mImagep->getTimePassedSinceLastBound();
  295. if (last_event < 1.f)
  296. {
  297. clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1;
  298. clr.setAlpha(1.f - last_event);
  299. gGL.color4fv(clr.mV);
  300. gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
  301. }
  302. }
  303. pip_x += pip_width + pip_space;
  304. {
  305. LLGLSUIDefault gls_ui;
  306. // draw the packet data
  307. //  {
  308. //  std::string num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets);
  309. //  LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, bar_left + 100, getRect().getHeight(), color,
  310. //   LLFontGL::LEFT, LLFontGL::TOP);
  311. //  }
  312. // draw the image size at the end
  313. {
  314. std::string num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(),
  315. mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0);
  316. LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color,
  317. LLFontGL::LEFT, LLFontGL::TOP);
  318. }
  319. }
  320. }
  321. BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask)
  322. {
  323. if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == MASK_ALT)
  324. {
  325. LLAppViewer::getTextureFetch()->mDebugID = mImagep->getID();
  326. return TRUE;
  327. }
  328. return LLView::handleMouseDown(x,y,mask);
  329. }
  330. LLRect LLTextureBar::getRequiredRect()
  331. {
  332. LLRect rect;
  333. rect.mTop = texture_bar_height;
  334. return rect;
  335. }
  336. ////////////////////////////////////////////////////////////////////////////
  337. class LLGLTexMemBar : public LLView
  338. {
  339. public:
  340. struct Params : public LLInitParam::Block<Params, LLView::Params>
  341. {
  342. Mandatory<LLTextureView*> texture_view;
  343. Params()
  344. : texture_view("texture_view")
  345. {
  346. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  347. rect(LLRect(0,0,100,line_height * 4));
  348. }
  349. };
  350. LLGLTexMemBar(const Params& p)
  351. : LLView(p),
  352. mTextureView(p.texture_view)
  353. {}
  354. virtual void draw();
  355. virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
  356. virtual LLRect getRequiredRect(); // Return the height of this object, given the set options.
  357. private:
  358. LLTextureView* mTextureView;
  359. };
  360. void LLGLTexMemBar::draw()
  361. {
  362. S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes);
  363.   S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes;
  364. S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
  365. S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
  366. F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
  367. F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
  368. F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
  369. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  370. S32 v_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f);
  371. //----------------------------------------------------------------------------
  372. LLGLSUIDefault gls_ui;
  373. LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
  374. LLColor4 color;
  375. std::string text;
  376. text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
  377. total_mem,
  378. max_total_mem,
  379. bound_mem,
  380. max_bound_mem,
  381. LLImageRaw::sGlobalRawMemory >> 20, discard_bias,
  382. cache_usage, cache_max_usage);
  383. //, cache_entries, cache_max_entries
  384. LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
  385.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  386. //----------------------------------------------------------------------------
  387. #if 0
  388. S32 bar_left = 400;
  389. S32 bar_width = 200;
  390. S32 top = line_height*3 - 2 + v_offset;
  391. S32 bottom = top - 6;
  392. S32 left = bar_left;
  393. S32 right = left + bar_width;
  394. F32 bar_scale;
  395. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  396. // GL Mem Bar
  397. left = bar_left;
  398. text = "GL";
  399. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
  400.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  401. left = bar_left+20;
  402. right = left + bar_width;
  403. gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey
  404. gl_rect_2d(left, top, right, bottom);
  405. bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
  406. right = left + llfloor(total_mem * bar_scale);
  407. right = llclamp(right, bar_left, bar_left + bar_width);
  408. color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green :
  409.    (total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red;
  410. color[VALPHA] = .75f;
  411. glColor4fv(color.mV);
  412. gl_rect_2d(left, top, right, bottom); // red/yellow/green
  413. //
  414. bar_left += bar_width + bar_space;
  415. //top = bottom - 2; bottom = top - 6;
  416. // Bound Mem Bar
  417. left = bar_left;
  418. text = "GL";
  419. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
  420.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  421. left = bar_left + 20;
  422. right = left + bar_width;
  423. gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f);
  424. gl_rect_2d(left, top, right, bottom);
  425. color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green :
  426.    (bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red;
  427. color[VALPHA] = .75f;
  428. glColor4fv(color.mV);
  429. gl_rect_2d(left, top, right, bottom);
  430. #else
  431. S32 left = 0 ;
  432. #endif
  433. //----------------------------------------------------------------------------
  434. text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d",
  435. gTextureList.getNumImages(),
  436. LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
  437. LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, 
  438. LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
  439. LLLFSThread::sLocal->getPending(),
  440. LLImageRaw::sRawImageCount,
  441. LLAppViewer::getTextureFetch()->getNumHTTPRequests(),
  442. LLAppViewer::getImageDecodeThread()->getPending(), 
  443. gTextureList.mCreateTextureList.size());
  444. LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*2,
  445.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  446. left = 550;
  447. F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth();
  448. F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
  449. color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color;
  450. color[VALPHA] = text_color[VALPHA];
  451. text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth);
  452. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2,
  453.  color, LLFontGL::LEFT, LLFontGL::TOP);
  454. S32 dx1 = 0;
  455. if (LLAppViewer::getTextureFetch()->mDebugPause)
  456. {
  457. LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, v_offset + line_height,
  458.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  459. dx1 += 8;
  460. }
  461. if (mTextureView->mFreezeView)
  462. {
  463. LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, v_offset + line_height,
  464.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  465. dx1 += 8;
  466. }
  467. if (mTextureView->mOrderFetch)
  468. {
  469. LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, v_offset + line_height,
  470.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  471. }
  472. else
  473. {
  474. LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, v_offset + line_height,
  475.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  476. }
  477. LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, v_offset + line_height,
  478.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  479. LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, v_offset + line_height,
  480.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  481. LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, v_offset + line_height,
  482.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  483. }
  484. BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask)
  485. {
  486. return FALSE;
  487. }
  488. LLRect LLGLTexMemBar::getRequiredRect()
  489. {
  490. LLRect rect;
  491. rect.mTop = 8;
  492. return rect;
  493. }
  494. ////////////////////////////////////////////////////////////////////////////
  495. class LLGLTexSizeBar
  496. {
  497. public:
  498. LLGLTexSizeBar(S32 index, S32 left, S32 bottom, S32 right, S32 line_height)
  499. {
  500. mIndex = index ;
  501. mLeft = left ;
  502. mBottom = bottom ;
  503. mRight = right ;
  504. mLineHeight = line_height ;
  505. mTopLoaded = 0 ;
  506. mTopBound = 0 ;
  507. mScale = 1.0f ;
  508. }
  509. void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;}
  510. void draw();
  511. BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ;
  512. private:
  513. S32 mIndex ;
  514. S32 mLeft ;
  515. S32 mBottom ;
  516. S32 mRight ;
  517. S32 mTopLoaded ;
  518. S32 mTopBound ;
  519. S32 mLineHeight ;
  520. F32 mScale ;
  521. };
  522. BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) 
  523. {
  524. if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale)))
  525. {
  526. LLImageGL::setCurTexSizebar(mIndex, set_pick_size);
  527. }
  528. return TRUE ;
  529. }
  530. void LLGLTexSizeBar::draw()
  531. {
  532. LLGLSUIDefault gls_ui;
  533. if(LLImageGL::sCurTexSizeBar == mIndex)
  534. {
  535. F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
  536. std::string text;
  537. text = llformat("%d", mTopLoaded) ;
  538. LLFontGL::getFontMonospace()->renderUTF8(text, 0, mLeft, mBottom + (S32)(mTopLoaded * mScale) + mLineHeight,
  539.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  540. text = llformat("%d", mTopBound) ;
  541. LLFontGL::getFontMonospace()->renderUTF8(text, 0, (mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale) + mLineHeight,
  542.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  543. }
  544. F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
  545. F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
  546. gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ;
  547. gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ;
  548. }
  549. ////////////////////////////////////////////////////////////////////////////
  550. LLTextureView::LLTextureView(const LLTextureView::Params& p)
  551. : LLContainerView(p),
  552. mFreezeView(FALSE),
  553. mOrderFetch(FALSE),
  554. mPrintList(FALSE),
  555. mNumTextureBars(0)
  556. {
  557. setVisible(FALSE);
  558. setDisplayChildren(TRUE);
  559. mGLTexMemBar = 0;
  560. }
  561. LLTextureView::~LLTextureView()
  562. {
  563. // Children all cleaned up by default view destructor.
  564. delete mGLTexMemBar;
  565. mGLTexMemBar = 0;
  566. }
  567. typedef std::pair<F32,LLViewerFetchedTexture*> decode_pair_t;
  568. struct compare_decode_pair
  569. {
  570. bool operator()(const decode_pair_t& a, const decode_pair_t& b)
  571. {
  572. return a.first > b.first;
  573. }
  574. };
  575. void LLTextureView::draw()
  576. {
  577. if (!mFreezeView)
  578. {
  579. //  LLViewerObject *objectp;
  580. //  S32 te;
  581. for_each(mTextureBars.begin(), mTextureBars.end(), DeletePointer());
  582. mTextureBars.clear();
  583. delete mGLTexMemBar;
  584. mGLTexMemBar = 0;
  585. typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t;
  586. display_list_t display_image_list;
  587. if (mPrintList)
  588. {
  589. llinfos << "IDtMEMtBOOSTtPRItWIDTHtHEIGHTtDISCARD" << llendl;
  590. }
  591. for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
  592.  iter != gTextureList.mImageList.end(); )
  593. {
  594. LLPointer<LLViewerFetchedTexture> imagep = *iter++;
  595. S32 cur_discard = imagep->getDiscardLevel();
  596. S32 desired_discard = imagep->mDesiredDiscardLevel;
  597. if (mPrintList)
  598. {
  599. S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ;
  600. llinfos << imagep->getID()
  601. << "t" << tex_mem
  602. << "t" << imagep->getBoostLevel()
  603. << "t" << imagep->getDecodePriority()
  604. << "t" << imagep->getWidth()
  605. << "t" << imagep->getHeight()
  606. << "t" << cur_discard
  607. << llendl;
  608. }
  609. if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
  610. {
  611. static S32 debug_count = 0;
  612. ++debug_count; // for breakpoints
  613. }
  614. #if 0
  615. if (imagep->getDontDiscard())
  616. {
  617. continue;
  618. }
  619. if (imagep->isMissingAsset())
  620. {
  621. continue;
  622. }
  623. #endif
  624. #define HIGH_PRIORITY 100000000.f
  625. F32 pri;
  626. if (mOrderFetch)
  627. {
  628. pri = ((F32)imagep->mFetchPriority)/256.f;
  629. }
  630. else
  631. {
  632. pri = imagep->getDecodePriority();
  633. }
  634. pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f);
  635. if (sDebugImages.find(imagep) != sDebugImages.end())
  636. {
  637. pri += 4*HIGH_PRIORITY;
  638. }
  639. if (!mOrderFetch)
  640. {
  641. #if 1
  642. if (pri < HIGH_PRIORITY && LLSelectMgr::getInstance())
  643. {
  644. struct f : public LLSelectedTEFunctor
  645. {
  646. LLViewerFetchedTexture* mImage;
  647. f(LLViewerFetchedTexture* image) : mImage(image) {}
  648. virtual bool apply(LLViewerObject* object, S32 te)
  649. {
  650. return (mImage == object->getTEImage(te));
  651. }
  652. } func(imagep);
  653. const bool firstonly = true;
  654. bool match = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, firstonly);
  655. if (match)
  656. {
  657. pri += 3*HIGH_PRIORITY;
  658. }
  659. }
  660. #endif
  661. #if 1
  662. if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard))
  663. {
  664. LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode();
  665. if (hover_node)
  666. {
  667. LLViewerObject *objectp = hover_node->getObject();
  668. if (objectp)
  669. {
  670. S32 tex_count = objectp->getNumTEs();
  671. for (S32 i = 0; i < tex_count; i++)
  672. {
  673. if (imagep == objectp->getTEImage(i))
  674. {
  675. pri += 2*HIGH_PRIORITY;
  676. break;
  677. }
  678. }
  679. }
  680. }
  681. }
  682. #endif
  683. #if 1
  684. if (pri > 0.f && pri < HIGH_PRIORITY)
  685. {
  686. if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f ||
  687. imagep->mFetchDeltaTime < 0.25f)
  688. {
  689. pri += 1*HIGH_PRIORITY;
  690. }
  691. }
  692. #endif
  693. }
  694.   if (pri > 0.0f)
  695. {
  696. display_image_list.insert(std::make_pair(pri, imagep));
  697. }
  698. }
  699. if (mPrintList)
  700. {
  701. mPrintList = FALSE;
  702. }
  703. static S32 max_count = 50;
  704. S32 count = 0;
  705. mNumTextureBars = 0 ;
  706. for (display_list_t::iterator iter = display_image_list.begin();
  707.  iter != display_image_list.end(); iter++)
  708. {
  709. LLViewerFetchedTexture* imagep = iter->second;
  710. S32 hilite = 0;
  711. F32 pri = iter->first;
  712. if (pri >= 1 * HIGH_PRIORITY)
  713. {
  714. hilite = (S32)((pri+1) / HIGH_PRIORITY) - 1;
  715. }
  716. if ((hilite || count < max_count-10) && (count < max_count))
  717. {
  718. if (addBar(imagep, hilite))
  719. {
  720. count++;
  721. }
  722. }
  723. }
  724. if (mOrderFetch)
  725. sortChildren(LLTextureBar::sort_fetch());
  726. else
  727. sortChildren(LLTextureBar::sort());
  728. LLGLTexMemBar::Params tmbp;
  729. tmbp.name("gl texmem bar");
  730. tmbp.texture_view(this);
  731. mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp);
  732. addChild(mGLTexMemBar);
  733. reshape(getRect().getWidth(), getRect().getHeight(), TRUE);
  734. /*
  735.   count = gTextureList.getNumImages();
  736.   std::string info_string;
  737.   info_string = llformat("Global Info:nTexture Count: %d", count);
  738.   mInfoTextp->setText(info_string);
  739. */
  740. for (child_list_const_iter_t child_iter = getChildList()->begin();
  741.  child_iter != getChildList()->end(); ++child_iter)
  742. {
  743. LLView *viewp = *child_iter;
  744. if (viewp->getRect().mBottom < 0)
  745. {
  746. viewp->setVisible(FALSE);
  747. }
  748. }
  749. }
  750. LLContainerView::draw();
  751. }
  752. BOOL LLTextureView::addBar(LLViewerFetchedTexture *imagep, S32 hilite)
  753. {
  754. llassert(imagep);
  755. LLTextureBar *barp;
  756. LLRect r;
  757. mNumTextureBars++;
  758. LLTextureBar::Params tbp;
  759. tbp.name("texture bar");
  760. tbp.rect(r);
  761. tbp.texture_view(this);
  762. barp = LLUICtrlFactory::create<LLTextureBar>(tbp);
  763. barp->mImagep = imagep;
  764. barp->mHilite = hilite;
  765. addChild(barp);
  766. mTextureBars.push_back(barp);
  767. return TRUE;
  768. }
  769. BOOL LLTextureView::handleMouseDown(S32 x, S32 y, MASK mask)
  770. {
  771. if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_ALT|MASK_SHIFT))
  772. {
  773. mPrintList = TRUE;
  774. return TRUE;
  775. }
  776. if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_CONTROL|MASK_SHIFT))
  777. {
  778. LLAppViewer::getTextureFetch()->mDebugPause = !LLAppViewer::getTextureFetch()->mDebugPause;
  779. return TRUE;
  780. }
  781. if (mask & MASK_SHIFT)
  782. {
  783. mFreezeView = !mFreezeView;
  784. return TRUE;
  785. }
  786. if (mask & MASK_CONTROL)
  787. {
  788. mOrderFetch = !mOrderFetch;
  789. return TRUE;
  790. }
  791. return LLView::handleMouseDown(x,y,mask);
  792. }
  793. BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask)
  794. {
  795. return FALSE;
  796. }
  797. BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
  798. {
  799. return FALSE;
  800. }
  801. //-----------------------------------------------------------------
  802. LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p)
  803. {
  804. setVisible(FALSE) ;
  805. mTextureSizeBarWidth = 30 ;
  806. }
  807. LLTextureSizeView::~LLTextureSizeView()
  808. {
  809. if(mTextureSizeBar.size())
  810. {
  811. for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
  812. {
  813. delete mTextureSizeBar[i] ;
  814. }
  815. mTextureSizeBar.clear() ;
  816. }
  817. }
  818. void LLTextureSizeView::draw()
  819. {
  820. if(mType == TEXTURE_MEM_OVER_SIZE)
  821. {
  822. drawTextureSizeGraph();
  823. }
  824. else
  825. {
  826. drawTextureCategoryGraph() ;
  827. }
  828. LLView::draw();
  829. }
  830. BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) 
  831. {
  832. if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
  833. {
  834. mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ;
  835. }
  836. return TRUE ;
  837. }
  838. //draw real-time texture mem bar over size
  839. void LLTextureSizeView::drawTextureSizeGraph()
  840. {
  841. if(mTextureSizeBar.size() == 0)
  842. {
  843. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  844. mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
  845. mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
  846. for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
  847. {
  848. mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , 
  849. line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
  850. }
  851. }
  852. F32 size_bar_scale = drawTextureSizeDistributionGraph() ;
  853. for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
  854. {
  855. mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ;
  856. mTextureSizeBar[i]->draw() ;
  857. }
  858. LLImageGL::resetCurTexSizebar();
  859. }
  860. //draw background of texture size bar graph
  861. F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
  862. {
  863. //scale
  864. F32 scale = 1.0f ;
  865. LLGLSUIDefault gls_ui;
  866. {
  867. S32 count = 0 ;
  868. for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
  869. {
  870. if(LLImageGL::sTextureLoadedCounter[i] > count)
  871. {
  872. count = LLImageGL::sTextureLoadedCounter[i] ;
  873. }
  874. }
  875. if(count > mTextureSizeBarRect.getHeight())
  876. {
  877. scale = (F32)mTextureSizeBarRect.getHeight() / count ;
  878. }
  879. }
  880. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  881. S32 left = mTextureSizeBarRect.mLeft ;
  882. S32 bottom = mTextureSizeBarRect.mBottom ;
  883. S32 right = mTextureSizeBarRect.mRight ;
  884. S32 top = mTextureSizeBarRect.mTop ;
  885. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  886. //background rect
  887. gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
  888. //--------------------------------------------------
  889. gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
  890. gl_line_2d(left, bottom, right, bottom) ; //x axis
  891. gl_line_2d(left, bottom, left, top) ; //y axis
  892. //ruler
  893. //--------------------------------------------------
  894. gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
  895. for(S32 i = bottom + 50 ; i <= top ; i += 50)
  896. {
  897. gl_line_2d(left, i, right, i) ;
  898. }
  899. //texts
  900. //--------------------------------------------------
  901. F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
  902. std::string text;
  903. //-------
  904. //x axis: size label
  905. text = llformat("%d", 0) ;
  906. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
  907.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  908. for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
  909. {
  910. text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ;
  911. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
  912.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  913. }
  914. text = llformat("(w + h)/2") ;
  915. LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2,
  916.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  917. //-------
  918. //y axis: number label
  919. for(S32 i = bottom + 50 ; i <= top ; i += 50)
  920. {
  921. text = llformat("%d", (S32)((i - bottom) / scale)) ;
  922. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
  923.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  924. LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
  925.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  926. }
  927. //--------------------------------------------------
  928. F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
  929. gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
  930. text = llformat("Loaded") ;
  931. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
  932.  loaded_color, LLFontGL::LEFT, LLFontGL::TOP);
  933. F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
  934. gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
  935. text = llformat("Bound") ;
  936. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
  937.  bound_color, LLFontGL::LEFT, LLFontGL::TOP);
  938. //--------------------------------------------------
  939. //title
  940. text = llformat("Texture Size Distribution") ;
  941. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
  942.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  943. return scale ;
  944. }
  945. //draw real-time texture mem bar over category
  946. void LLTextureSizeView::drawTextureCategoryGraph()
  947. {
  948. if(mTextureSizeBar.size() == 0)
  949. {
  950. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  951. mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;
  952. mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
  953. for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
  954. {
  955. mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , 
  956. line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
  957. }
  958. }
  959. F32 size_bar_scale = drawTextureCategoryDistributionGraph() ;
  960. for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
  961. {
  962. U32 k = LLViewerTexture::getIndexFromCategory(i) ;
  963. mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ;
  964. mTextureSizeBar[i]->draw() ;
  965. }
  966. LLImageGL::resetCurTexSizebar();
  967. }
  968. //draw background for TEXTURE_MEM_OVER_CATEGORY
  969. F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() 
  970. {
  971. //scale
  972. F32 scale = 4.0f ;
  973. LLGLSUIDefault gls_ui;
  974. {
  975. S32 count = 0 ;
  976. for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
  977. {
  978. S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ;
  979. if(tmp > count)
  980. {
  981. count = tmp ;
  982. }
  983. }
  984. if(count > mTextureSizeBarRect.getHeight() * 0.25f)
  985. {
  986. scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ;
  987. }
  988. }
  989. S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
  990. S32 left = mTextureSizeBarRect.mLeft ;
  991. S32 bottom = mTextureSizeBarRect.mBottom ;
  992. S32 right = mTextureSizeBarRect.mRight ;
  993. S32 top = mTextureSizeBarRect.mTop ;
  994. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  995. //background rect
  996. gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
  997. //--------------------------------------------------
  998. gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
  999. gl_line_2d(left, bottom, right, bottom) ; //x axis
  1000. gl_line_2d(left, bottom, left, top) ; //y axis
  1001. //ruler
  1002. //--------------------------------------------------
  1003. gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
  1004. for(S32 i = bottom + 50 ; i <= top ; i += 50)
  1005. {
  1006. gl_line_2d(left, i, right, i) ;
  1007. }
  1008. //texts
  1009. //--------------------------------------------------
  1010. F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
  1011. std::string text;
  1012. //-------
  1013. //x axis: size label
  1014. static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] = 
  1015. {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ;
  1016. text = llformat("%s", category[0]) ;
  1017. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
  1018.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1019. for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
  1020. {
  1021. text = llformat("%s", category[i]) ;
  1022. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
  1023.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1024. }
  1025. //-------
  1026. //y axis: number label
  1027. for(S32 i = bottom + 50 ; i <= top ; i += 50)
  1028. {
  1029. text = llformat("%d", (S32)((i - bottom) / scale)) ;
  1030. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
  1031.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1032. LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
  1033.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1034. }
  1035. text = llformat("MB") ;
  1036. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 ,
  1037.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1038. //--------------------------------------------------
  1039. F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
  1040. gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
  1041. text = llformat("Loaded") ;
  1042. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
  1043.  loaded_color, 
  1044.  LLFontGL::LEFT, LLFontGL::TOP);
  1045. F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
  1046. gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
  1047. text = llformat("Bound") ;
  1048. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
  1049.  bound_color, LLFontGL::LEFT, LLFontGL::TOP);
  1050. //--------------------------------------------------
  1051. //title
  1052. text = llformat("Texture Category Distribution") ;
  1053. LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
  1054.  text_color, LLFontGL::LEFT, LLFontGL::TOP);
  1055. return scale ;
  1056. }