PageRenderTime 1569ms CodeModel.GetById 151ms app.highlight 979ms RepoModel.GetById 422ms app.codeStats 1ms

/indra/newview/lltextureview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1350 lines | 1057 code | 188 blank | 105 comment | 124 complexity | d5484afc42ce98e49f3263a0a089dec5 MD5 | raw file
   1/** 
   2 * @file lltextureview.cpp
   3 * @brief LLTextureView class implementation
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include <set>
  30
  31#include "lltextureview.h"
  32
  33#include "llrect.h"
  34#include "llerror.h"
  35#include "lllfsthread.h"
  36#include "llui.h"
  37#include "llimageworker.h"
  38#include "llrender.h"
  39
  40#include "lltooltip.h"
  41#include "llappviewer.h"
  42#include "llselectmgr.h"
  43#include "lltexlayer.h"
  44#include "lltexturecache.h"
  45#include "lltexturefetch.h"
  46#include "llviewercontrol.h"
  47#include "llviewerobject.h"
  48#include "llviewertexture.h"
  49#include "llviewertexturelist.h"
  50#include "llvovolume.h"
  51#include "llviewerstats.h"
  52
  53// For avatar texture view
  54#include "llvoavatarself.h"
  55#include "lltexlayer.h"
  56
  57extern F32 texmem_lower_bound_scale;
  58
  59LLTextureView *gTextureView = NULL;
  60LLTextureSizeView *gTextureSizeView = NULL;
  61LLTextureSizeView *gTextureCategoryView = NULL;
  62
  63#define HIGH_PRIORITY 100000000.f
  64
  65//static
  66std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages;
  67
  68////////////////////////////////////////////////////////////////////////////
  69
  70static std::string title_string1a("Tex UUID Area  DDis(Req)  DecodePri(Fetch)     [download] pk/max");
  71static std::string title_string1b("Tex UUID Area  DDis(Req)  Fetch(DecodePri)     [download] pk/max");
  72static std::string title_string2("State");
  73static std::string title_string3("Pkt Bnd");
  74static std::string title_string4("  W x H (Dis) Mem");
  75
  76static S32 title_x1 = 0;
  77static S32 title_x2 = 460;
  78static S32 title_x3 = title_x2 + 40;
  79static S32 title_x4 = title_x3 + 50;
  80static S32 texture_bar_height = 8;
  81
  82////////////////////////////////////////////////////////////////////////////
  83
  84class LLTextureBar : public LLView
  85{
  86public:
  87	LLPointer<LLViewerFetchedTexture> mImagep;
  88	S32 mHilite;
  89
  90public:
  91	struct Params : public LLInitParam::Block<Params, LLView::Params>
  92	{
  93		Mandatory<LLTextureView*> texture_view;
  94		Params()
  95		:	texture_view("texture_view")
  96		{
  97			changeDefault(mouse_opaque, false);
  98		}
  99	};
 100	LLTextureBar(const Params& p)
 101	:	LLView(p),
 102		mHilite(0),
 103		mTextureView(p.texture_view)
 104	{}
 105
 106	virtual void draw();
 107	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
 108	virtual LLRect getRequiredRect();	// Return the height of this object, given the set options.
 109
 110// Used for sorting
 111	struct sort
 112	{
 113		bool operator()(const LLView* i1, const LLView* i2)
 114		{
 115			LLTextureBar* bar1p = (LLTextureBar*)i1;
 116			LLTextureBar* bar2p = (LLTextureBar*)i2;
 117			LLViewerFetchedTexture *i1p = bar1p->mImagep;
 118			LLViewerFetchedTexture *i2p = bar2p->mImagep;
 119			F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
 120			F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
 121			if (pri1 > pri2)
 122				return true;
 123			else if (pri2 > pri1)
 124				return false;
 125			else
 126				return i1p->getID() < i2p->getID();
 127		}
 128	};
 129
 130	struct sort_fetch
 131	{
 132		bool operator()(const LLView* i1, const LLView* i2)
 133		{
 134			LLTextureBar* bar1p = (LLTextureBar*)i1;
 135			LLTextureBar* bar2p = (LLTextureBar*)i2;
 136			LLViewerFetchedTexture *i1p = bar1p->mImagep;
 137			LLViewerFetchedTexture *i2p = bar2p->mImagep;
 138			U32 pri1 = i1p->getFetchPriority() ;
 139			U32 pri2 = i2p->getFetchPriority() ;
 140			if (pri1 > pri2)
 141				return true;
 142			else if (pri2 > pri1)
 143				return false;
 144			else
 145				return i1p->getID() < i2p->getID();
 146		}
 147	};	
 148private:
 149	LLTextureView* mTextureView;
 150};
 151
 152void LLTextureBar::draw()
 153{
 154	if (!mImagep)
 155	{
 156		return;
 157	}
 158
 159	LLColor4 color;
 160	if (mImagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
 161	{
 162		color = LLColor4::cyan2;
 163	}
 164	else if (mHilite)
 165	{
 166		S32 idx = llclamp(mHilite,1,3);
 167		if (idx==1) color = LLColor4::orange;
 168		else if (idx==2) color = LLColor4::yellow;
 169		else color = LLColor4::pink2;
 170	}
 171	else if (mImagep->mDontDiscard)
 172	{
 173		color = LLColor4::green4;
 174	}
 175	else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE)
 176	{
 177		color = LLColor4::magenta;
 178	}
 179	else if (mImagep->getDecodePriority() <= 0.0f)
 180	{
 181		color = LLColor4::grey; color[VALPHA] = .7f;
 182	}
 183	else
 184	{
 185		color = LLColor4::white; color[VALPHA] = .7f;
 186	}
 187
 188	// We need to draw:
 189	// The texture UUID or name
 190	// The progress bar for the texture, highlighted if it's being download
 191	// Various numerical stats.
 192	std::string tex_str;
 193	S32 left, right;
 194	S32 top = 0;
 195	S32 bottom = top + 6;
 196	LLColor4 clr;
 197
 198	LLGLSUIDefault gls_ui;
 199	
 200	// Name, pixel_area, requested pixel area, decode priority
 201	std::string uuid_str;
 202	mImagep->mID.toString(uuid_str);
 203	uuid_str = uuid_str.substr(0,7);
 204	if (mTextureView->mOrderFetch)
 205	{
 206		tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)",
 207						   uuid_str.c_str(),
 208						   mImagep->mMaxVirtualSize,
 209						   mImagep->mDesiredDiscardLevel,
 210						   mImagep->mRequestedDiscardLevel,
 211						   mImagep->mFetchPriority,
 212						   mImagep->getDecodePriority());
 213	}
 214	else
 215	{
 216		tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)",
 217						   uuid_str.c_str(),
 218						   mImagep->mMaxVirtualSize,
 219						   mImagep->mDesiredDiscardLevel,
 220						   mImagep->mRequestedDiscardLevel,
 221						   mImagep->getDecodePriority(),
 222						   mImagep->mFetchPriority);
 223	}
 224
 225	LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(),
 226									 color, LLFontGL::LEFT, LLFontGL::TOP);
 227
 228	// State
 229	// Hack: mirrored from lltexturefetch.cpp
 230	struct { const std::string desc; LLColor4 color; } fetch_state_desc[] = {
 231		{ "---", LLColor4::red },	// INVALID
 232		{ "INI", LLColor4::white },	// INIT
 233		{ "DSK", LLColor4::cyan },	// LOAD_FROM_TEXTURE_CACHE
 234		{ "DSK", LLColor4::blue },	// CACHE_POST
 235		{ "NET", LLColor4::green },	// LOAD_FROM_NETWORK
 236		{ "SIM", LLColor4::green },	// LOAD_FROM_SIMULATOR
 237		{ "REQ", LLColor4::yellow },// SEND_HTTP_REQ
 238		{ "HTP", LLColor4::green },	// WAIT_HTTP_REQ
 239		{ "DEC", LLColor4::yellow },// DECODE_IMAGE
 240		{ "DEC", LLColor4::green }, // DECODE_IMAGE_UPDATE
 241		{ "WRT", LLColor4::purple },// WRITE_TO_CACHE
 242		{ "WRT", LLColor4::orange },// WAIT_ON_WRITE
 243		{ "END", LLColor4::red },   // DONE
 244#define LAST_STATE 12
 245		{ "CRE", LLColor4::magenta }, // LAST_STATE+1
 246		{ "FUL", LLColor4::green }, // LAST_STATE+2
 247		{ "BAD", LLColor4::red }, // LAST_STATE+3
 248		{ "MIS", LLColor4::red }, // LAST_STATE+4
 249		{ "---", LLColor4::white }, // LAST_STATE+5
 250	};
 251	const S32 fetch_state_desc_size = (S32)LL_ARRAY_SIZE(fetch_state_desc);
 252	S32 state =
 253		mImagep->mNeedsCreateTexture ? LAST_STATE+1 :
 254		mImagep->mFullyLoaded ? LAST_STATE+2 :
 255		mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 :
 256		mImagep->mIsMissingAsset ? LAST_STATE+4 :
 257		!mImagep->mIsFetching ? LAST_STATE+5 :
 258		mImagep->mFetchState;
 259	state = llclamp(state,0,fetch_state_desc_size-1);
 260
 261	LLFontGL::getFontMonospace()->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, getRect().getHeight(),
 262									 fetch_state_desc[state].color,
 263									 LLFontGL::LEFT, LLFontGL::TOP);
 264	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 265
 266	// Draw the progress bar.
 267	S32 bar_width = 100;
 268	S32 bar_left = 260;
 269	left = bar_left;
 270	right = left + bar_width;
 271
 272	gGL.color4f(0.f, 0.f, 0.f, 0.75f);
 273	gl_rect_2d(left, top, right, bottom);
 274
 275	F32 data_progress = mImagep->mDownloadProgress;
 276	
 277	if (data_progress > 0.0f)
 278	{
 279		// Downloaded bytes
 280		right = left + llfloor(data_progress * (F32)bar_width);
 281		if (right > left)
 282		{
 283			gGL.color4f(0.f, 0.f, 1.f, 0.75f);
 284			gl_rect_2d(left, top, right, bottom);
 285		}
 286	}
 287
 288	S32 pip_width = 6;
 289	S32 pip_space = 14;
 290	S32 pip_x = title_x3 + pip_space/2;
 291	
 292	// Draw the packet pip
 293	const F32 pip_max_time = 5.f;
 294	F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32();
 295	if (last_event < pip_max_time)
 296	{
 297		clr = LLColor4::white; 
 298	}
 299	else
 300	{
 301		last_event = mImagep->mRequestDeltaTime;
 302		if (last_event < pip_max_time)
 303		{
 304			clr = LLColor4::green;
 305		}
 306		else
 307		{
 308			last_event = mImagep->mFetchDeltaTime;
 309			if (last_event < pip_max_time)
 310			{
 311				clr = LLColor4::yellow;
 312			}
 313		}
 314	}
 315	if (last_event < pip_max_time)
 316	{
 317		clr.setAlpha(1.f - last_event/pip_max_time);
 318		gGL.color4fv(clr.mV);
 319		gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
 320	}
 321	pip_x += pip_width + pip_space;
 322
 323	// we don't want to show bind/resident pips for textures using the default texture
 324	if (mImagep->hasGLTexture())
 325	{
 326		// Draw the bound pip
 327		last_event = mImagep->getTimePassedSinceLastBound();
 328		if (last_event < 1.f)
 329		{
 330			clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1;
 331			clr.setAlpha(1.f - last_event);
 332			gGL.color4fv(clr.mV);
 333			gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
 334		}
 335	}
 336	pip_x += pip_width + pip_space;
 337
 338	
 339	{
 340		LLGLSUIDefault gls_ui;
 341		// draw the packet data
 342// 		{
 343// 			std::string num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets);
 344// 			LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, bar_left + 100, getRect().getHeight(), color,
 345// 											 LLFontGL::LEFT, LLFontGL::TOP);
 346// 		}
 347		
 348		// draw the image size at the end
 349		{
 350			std::string num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(),
 351				mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0);
 352			LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color,
 353											LLFontGL::LEFT, LLFontGL::TOP);
 354		}
 355	}
 356
 357}
 358
 359BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask)
 360{
 361	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == MASK_ALT)
 362	{
 363		LLAppViewer::getTextureFetch()->mDebugID = mImagep->getID();
 364		return TRUE;
 365	}
 366	return LLView::handleMouseDown(x,y,mask);
 367}
 368
 369LLRect LLTextureBar::getRequiredRect()
 370{
 371	LLRect rect;
 372
 373	rect.mTop = texture_bar_height;
 374
 375	return rect;
 376}
 377
 378////////////////////////////////////////////////////////////////////////////
 379
 380class LLAvatarTexBar : public LLView
 381{
 382public:
 383	struct Params : public LLInitParam::Block<Params, LLView::Params>
 384	{
 385		Mandatory<LLTextureView*>	texture_view;
 386		Params()
 387		:	texture_view("texture_view")
 388		{
 389			S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
 390			changeDefault(rect, LLRect(0,0,100,line_height * 4));
 391		}
 392	};
 393
 394	LLAvatarTexBar(const Params& p)
 395	:	LLView(p),
 396		mTextureView(p.texture_view)
 397	{}
 398
 399	virtual void draw();	
 400	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
 401	virtual LLRect getRequiredRect();	// Return the height of this object, given the set options.
 402
 403private:
 404	LLTextureView* mTextureView;
 405};
 406
 407void LLAvatarTexBar::draw()
 408{	
 409	if (!gSavedSettings.getBOOL("DebugAvatarRezTime")) return;
 410
 411	LLVOAvatarSelf* avatarp = gAgentAvatarp;
 412	if (!avatarp) return;
 413
 414	const S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
 415	const S32 v_offset = 0;
 416	const S32 l_offset = 3;
 417
 418	//----------------------------------------------------------------------------
 419	LLGLSUIDefault gls_ui;
 420	LLColor4 color;
 421	
 422	U32 line_num = 1;
 423	for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
 424		 baked_iter != LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
 425		 ++baked_iter)
 426	{
 427		const LLVOAvatarDefines::EBakedTextureIndex baked_index = baked_iter->first;
 428		const LLTexLayerSet *layerset = avatarp->debugGetLayerSet(baked_index);
 429		if (!layerset) continue;
 430		const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite();
 431		if (!layerset_buffer) continue;
 432
 433		LLColor4 text_color = LLColor4::white;
 434		
 435		if (layerset_buffer->uploadNeeded())
 436		{
 437			text_color = LLColor4::red;
 438		}
 439 		if (layerset_buffer->uploadInProgress())
 440		{
 441			text_color = LLColor4::magenta;
 442		}
 443		std::string text = layerset_buffer->dumpTextureInfo();
 444		LLFontGL::getFontMonospace()->renderUTF8(text, 0, l_offset, v_offset + line_height*line_num,
 445												 text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
 446		line_num++;
 447	}
 448	const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
 449	const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel");
 450	
 451	LLColor4 header_color(1.f, 1.f, 1.f, 0.9f);
 452
 453	const std::string texture_timeout_str = texture_timeout ? llformat("%d",texture_timeout) : "Disabled";
 454	const std::string override_tex_discard_level_str = override_tex_discard_level ? llformat("%d",override_tex_discard_level) : "Disabled";
 455	std::string header_text = llformat("[ Timeout('AvatarBakedTextureUploadTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str());
 456	LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, l_offset, v_offset + line_height*line_num,
 457											 header_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
 458	line_num++;
 459	std::string section_text = "Avatar Textures Information:";
 460	LLFontGL::getFontMonospace()->renderUTF8(section_text, 0, 0, v_offset + line_height*line_num,
 461											 header_color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
 462}
 463
 464BOOL LLAvatarTexBar::handleMouseDown(S32 x, S32 y, MASK mask)
 465{
 466	return FALSE;
 467}
 468
 469LLRect LLAvatarTexBar::getRequiredRect()
 470{
 471	LLRect rect;
 472	rect.mTop = 100;
 473	if (!gSavedSettings.getBOOL("DebugAvatarRezTime")) rect.mTop = 0;
 474	return rect;
 475}
 476
 477////////////////////////////////////////////////////////////////////////////
 478
 479class LLGLTexMemBar : public LLView
 480{
 481public:
 482	struct Params : public LLInitParam::Block<Params, LLView::Params>
 483	{
 484		Mandatory<LLTextureView*>	texture_view;
 485		Params()
 486		:	texture_view("texture_view")
 487		{
 488			S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
 489			changeDefault(rect, LLRect(0,0,100,line_height * 4));
 490		}
 491	};
 492
 493	LLGLTexMemBar(const Params& p)
 494	:	LLView(p),
 495		mTextureView(p.texture_view)
 496	{}
 497
 498	virtual void draw();	
 499	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
 500	virtual LLRect getRequiredRect();	// Return the height of this object, given the set options.
 501
 502private:
 503	LLTextureView* mTextureView;
 504};
 505
 506void LLGLTexMemBar::draw()
 507{
 508	S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes);
 509 	S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes;
 510	S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
 511	S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
 512	F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
 513	F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
 514	F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
 515	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
 516	S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
 517	F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
 518	F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
 519	U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
 520	//----------------------------------------------------------------------------
 521	LLGLSUIDefault gls_ui;
 522	LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
 523	LLColor4 color;
 524	
 525	std::string text = "";
 526
 527	LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
 528											 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 529
 530	text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d",
 531					total_mem,
 532					max_total_mem,
 533					bound_mem,
 534					max_bound_mem,
 535					LLRenderTarget::sBytesAllocated/(1024*1024),
 536					LLImageRaw::sGlobalRawMemory >> 20,	discard_bias,
 537					cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests);
 538	//, cache_entries, cache_max_entries
 539
 540	LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
 541											 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 542
 543	//----------------------------------------------------------------------------
 544#if 0
 545	S32 bar_left = 400;
 546	S32 bar_width = 200;
 547	S32 top = line_height*3 - 2 + v_offset;
 548	S32 bottom = top - 6;
 549	S32 left = bar_left;
 550	S32 right = left + bar_width;
 551	F32 bar_scale;
 552	
 553	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 554
 555	// GL Mem Bar
 556		
 557	left = bar_left;
 558	text = "GL";
 559	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
 560											 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 561	
 562	left = bar_left+20;
 563	right = left + bar_width;
 564	
 565	gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey
 566	gl_rect_2d(left, top, right, bottom);
 567
 568	bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
 569	right = left + llfloor(total_mem * bar_scale);
 570	right = llclamp(right, bar_left, bar_left + bar_width);
 571	
 572	color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green :
 573		  	(total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red;
 574	color[VALPHA] = .75f;
 575	gGL.diffuseColor4fv(color.mV);
 576	
 577	gl_rect_2d(left, top, right, bottom); // red/yellow/green
 578
 579	//
 580	bar_left += bar_width + bar_space;
 581	//top = bottom - 2; bottom = top - 6;
 582	
 583	// Bound Mem Bar
 584
 585	left = bar_left;
 586	text = "GL";
 587	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
 588									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 589	left = bar_left + 20;
 590	right = left + bar_width;
 591	
 592	gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f);
 593	gl_rect_2d(left, top, right, bottom);
 594
 595	color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green :
 596		  	(bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red;
 597	color[VALPHA] = .75f;
 598	gGL.diffuseColor4fv(color.mV);
 599
 600	gl_rect_2d(left, top, right, bottom);
 601#else
 602	S32 left = 0 ;
 603#endif
 604	//----------------------------------------------------------------------------
 605
 606	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",
 607					gTextureList.getNumImages(),
 608					LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
 609					LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, 
 610					LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
 611					LLLFSThread::sLocal->getPending(),
 612					LLImageRaw::sRawImageCount,
 613					LLAppViewer::getTextureFetch()->getNumHTTPRequests(),
 614					LLAppViewer::getImageDecodeThread()->getPending(), 
 615					gTextureList.mCreateTextureList.size());
 616
 617	LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*2,
 618									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 619
 620
 621	left = 550;
 622	F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth();
 623	F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
 624	color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color;
 625	color[VALPHA] = text_color[VALPHA];
 626	text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth);
 627	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2,
 628											 color, LLFontGL::LEFT, LLFontGL::TOP);
 629	
 630	S32 dx1 = 0;
 631	if (LLAppViewer::getTextureFetch()->mDebugPause)
 632	{
 633		LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, v_offset + line_height,
 634										 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 635		dx1 += 8;
 636	}
 637	if (mTextureView->mFreezeView)
 638	{
 639		LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, v_offset + line_height,
 640										 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 641		dx1 += 8;
 642	}
 643	if (mTextureView->mOrderFetch)
 644	{
 645		LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, v_offset + line_height,
 646										 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 647	}
 648	else
 649	{	
 650		LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, v_offset + line_height,
 651										 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 652	}
 653	
 654	LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, v_offset + line_height,
 655									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 656
 657	LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, v_offset + line_height,
 658									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 659
 660	LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, v_offset + line_height,
 661									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 662}
 663
 664BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask)
 665{
 666	return FALSE;
 667}
 668
 669LLRect LLGLTexMemBar::getRequiredRect()
 670{
 671	LLRect rect;
 672	//rect.mTop = 50;
 673	rect.mTop = 0;
 674	return rect;
 675}
 676
 677////////////////////////////////////////////////////////////////////////////
 678class LLGLTexSizeBar
 679{
 680public:
 681	LLGLTexSizeBar(S32 index, S32 left, S32 bottom, S32 right, S32 line_height)
 682	{
 683		mIndex = index ;
 684		mLeft = left ;
 685		mBottom = bottom ;
 686		mRight = right ;
 687		mLineHeight = line_height ;
 688		mTopLoaded = 0 ;
 689		mTopBound = 0 ;
 690		mScale = 1.0f ;
 691	}
 692
 693	void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;}
 694
 695	void draw();	
 696	BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ;
 697	
 698private:
 699	S32 mIndex ;
 700	S32 mLeft ;
 701	S32 mBottom ;
 702	S32 mRight ;
 703	S32 mTopLoaded ;
 704	S32 mTopBound ;
 705	S32 mLineHeight ;
 706	F32 mScale ;
 707};
 708
 709BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) 
 710{
 711	if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale)))
 712	{
 713		LLImageGL::setCurTexSizebar(mIndex, set_pick_size);
 714	}
 715	return TRUE ;
 716}
 717void LLGLTexSizeBar::draw()
 718{
 719	LLGLSUIDefault gls_ui;
 720
 721	if(LLImageGL::sCurTexSizeBar == mIndex)
 722	{
 723		F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};	
 724		std::string text;
 725	
 726		text = llformat("%d", mTopLoaded) ;
 727		LLFontGL::getFontMonospace()->renderUTF8(text, 0, mLeft, mBottom + (S32)(mTopLoaded * mScale) + mLineHeight,
 728									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 729
 730		text = llformat("%d", mTopBound) ;
 731		LLFontGL::getFontMonospace()->renderUTF8(text, 0, (mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale) + mLineHeight,
 732									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
 733	}
 734
 735	F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
 736	F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
 737	gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ;
 738	gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ;
 739}
 740////////////////////////////////////////////////////////////////////////////
 741
 742LLTextureView::LLTextureView(const LLTextureView::Params& p)
 743	:	LLContainerView(p),
 744		mFreezeView(FALSE),
 745		mOrderFetch(FALSE),
 746		mPrintList(FALSE),
 747		mNumTextureBars(0)
 748{
 749	setVisible(FALSE);
 750	
 751	setDisplayChildren(TRUE);
 752	mGLTexMemBar = 0;
 753	mAvatarTexBar = 0;
 754}
 755
 756LLTextureView::~LLTextureView()
 757{
 758	// Children all cleaned up by default view destructor.
 759	delete mGLTexMemBar;
 760	mGLTexMemBar = 0;
 761	
 762	delete mAvatarTexBar;
 763	mAvatarTexBar = 0;
 764}
 765
 766typedef std::pair<F32,LLViewerFetchedTexture*> decode_pair_t;
 767struct compare_decode_pair
 768{
 769	bool operator()(const decode_pair_t& a, const decode_pair_t& b)
 770	{
 771		return a.first > b.first;
 772	}
 773};
 774
 775struct KillView
 776{
 777	void operator()(LLView* viewp)
 778	{
 779		viewp->getParent()->removeChild(viewp);
 780		viewp->die();
 781	}
 782};
 783
 784void LLTextureView::draw()
 785{
 786	if (!mFreezeView)
 787	{
 788// 		LLViewerObject *objectp;
 789// 		S32 te;
 790
 791		for_each(mTextureBars.begin(), mTextureBars.end(), KillView());
 792		mTextureBars.clear();
 793			
 794		if (mGLTexMemBar)
 795		{
 796			removeChild(mGLTexMemBar);
 797			mGLTexMemBar->die();
 798			mGLTexMemBar = 0;
 799		}
 800
 801		if (mAvatarTexBar)
 802		{
 803			removeChild(mAvatarTexBar);
 804			mAvatarTexBar->die();
 805			mAvatarTexBar = 0;
 806		}
 807
 808		typedef std::multiset<decode_pair_t, compare_decode_pair > display_list_t;
 809		display_list_t display_image_list;
 810	
 811		if (mPrintList)
 812		{
 813			llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl;
 814		}
 815	
 816		for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
 817			 iter != gTextureList.mImageList.end(); )
 818		{
 819			LLPointer<LLViewerFetchedTexture> imagep = *iter++;
 820			if(!imagep->hasFetcher())
 821			{
 822				continue ;
 823			}
 824
 825			S32 cur_discard = imagep->getDiscardLevel();
 826			S32 desired_discard = imagep->mDesiredDiscardLevel;
 827			
 828			if (mPrintList)
 829			{
 830				S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ;
 831				llinfos << imagep->getID()
 832						<< "\t" << tex_mem
 833						<< "\t" << imagep->getBoostLevel()
 834						<< "\t" << imagep->getDecodePriority()
 835						<< "\t" << imagep->getWidth()
 836						<< "\t" << imagep->getHeight()
 837						<< "\t" << cur_discard
 838						<< llendl;
 839			}
 840
 841			if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
 842			{
 843				static S32 debug_count = 0;
 844				++debug_count; // for breakpoints
 845			}
 846			
 847			F32 pri;
 848			if (mOrderFetch)
 849			{
 850				pri = ((F32)imagep->mFetchPriority)/256.f;
 851			}
 852			else
 853			{
 854				pri = imagep->getDecodePriority();
 855			}
 856			pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f);
 857			
 858			if (sDebugImages.find(imagep) != sDebugImages.end())
 859			{
 860				pri += 4*HIGH_PRIORITY;
 861			}
 862
 863			if (!mOrderFetch)
 864			{
 865				if (pri < HIGH_PRIORITY && LLSelectMgr::getInstance())
 866				{
 867					struct f : public LLSelectedTEFunctor
 868					{
 869						LLViewerFetchedTexture* mImage;
 870						f(LLViewerFetchedTexture* image) : mImage(image) {}
 871						virtual bool apply(LLViewerObject* object, S32 te)
 872						{
 873							return (mImage == object->getTEImage(te));
 874						}
 875					} func(imagep);
 876					const bool firstonly = true;
 877					bool match = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, firstonly);
 878					if (match)
 879					{
 880						pri += 3*HIGH_PRIORITY;
 881					}
 882				}
 883
 884				if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard))
 885				{
 886					LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode();
 887					if (hover_node)
 888					{
 889						LLViewerObject *objectp = hover_node->getObject();
 890						if (objectp)
 891						{
 892							S32 tex_count = objectp->getNumTEs();
 893							for (S32 i = 0; i < tex_count; i++)
 894							{
 895								if (imagep == objectp->getTEImage(i))
 896								{
 897									pri += 2*HIGH_PRIORITY;
 898									break;
 899								}
 900							}
 901						}
 902					}
 903				}
 904
 905				if (pri > 0.f && pri < HIGH_PRIORITY)
 906				{
 907					if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f ||
 908						imagep->mFetchDeltaTime < 0.25f)
 909					{
 910						pri += 1*HIGH_PRIORITY;
 911					}
 912				}
 913			}
 914			
 915	 		if (pri > 0.0f)
 916			{
 917				display_image_list.insert(std::make_pair(pri, imagep));
 918			}
 919		}
 920		
 921		if (mPrintList)
 922		{
 923			mPrintList = FALSE;
 924		}
 925		
 926		static S32 max_count = 50;
 927		S32 count = 0;
 928		mNumTextureBars = 0 ;
 929		for (display_list_t::iterator iter = display_image_list.begin();
 930			 iter != display_image_list.end(); iter++)
 931		{
 932			LLViewerFetchedTexture* imagep = iter->second;
 933			S32 hilite = 0;
 934			F32 pri = iter->first;
 935			if (pri >= 1 * HIGH_PRIORITY)
 936			{
 937				hilite = (S32)((pri+1) / HIGH_PRIORITY) - 1;
 938			}
 939			if ((hilite || count < max_count-10) && (count < max_count))
 940			{
 941				if (addBar(imagep, hilite))
 942				{
 943					count++;
 944				}
 945			}
 946		}
 947
 948		if (mOrderFetch)
 949			sortChildren(LLTextureBar::sort_fetch());
 950		else
 951			sortChildren(LLTextureBar::sort());
 952
 953		LLGLTexMemBar::Params tmbp;
 954		LLRect tmbr;
 955		tmbp.name("gl texmem bar");
 956		tmbp.rect(tmbr);
 957		tmbp.texture_view(this);
 958		mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp);
 959		addChildInBack(mGLTexMemBar);
 960
 961		LLAvatarTexBar::Params atbp;
 962		LLRect atbr;
 963		atbp.name("gl avatartex bar");
 964		atbp.texture_view(this);
 965		atbp.rect(atbr);
 966		mAvatarTexBar = LLUICtrlFactory::create<LLAvatarTexBar>(atbp);
 967		addChild(mAvatarTexBar);
 968
 969		reshape(getRect().getWidth(), getRect().getHeight(), TRUE);
 970
 971		/*
 972		  count = gTextureList.getNumImages();
 973		  std::string info_string;
 974		  info_string = llformat("Global Info:\nTexture Count: %d", count);
 975		  mInfoTextp->setText(info_string);
 976		*/
 977
 978
 979		for (child_list_const_iter_t child_iter = getChildList()->begin();
 980			 child_iter != getChildList()->end(); ++child_iter)
 981		{
 982			LLView *viewp = *child_iter;
 983			if (viewp->getRect().mBottom < 0)
 984			{
 985				viewp->setVisible(FALSE);
 986			}
 987		}
 988	}
 989	
 990	LLContainerView::draw();
 991
 992}
 993
 994BOOL LLTextureView::addBar(LLViewerFetchedTexture *imagep, S32 hilite)
 995{
 996	llassert(imagep);
 997	
 998	LLTextureBar *barp;
 999	LLRect r;
1000
1001	mNumTextureBars++;
1002
1003	LLTextureBar::Params tbp;
1004	tbp.name("texture bar");
1005	tbp.rect(r);
1006	tbp.texture_view(this);
1007	barp = LLUICtrlFactory::create<LLTextureBar>(tbp);
1008	barp->mImagep = imagep;	
1009	barp->mHilite = hilite;
1010
1011	addChild(barp);
1012	mTextureBars.push_back(barp);
1013
1014	return TRUE;
1015}
1016
1017BOOL LLTextureView::handleMouseDown(S32 x, S32 y, MASK mask)
1018{
1019	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_ALT|MASK_SHIFT))
1020	{
1021		mPrintList = TRUE;
1022		return TRUE;
1023	}
1024	if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_CONTROL|MASK_SHIFT))
1025	{
1026		LLAppViewer::getTextureFetch()->mDebugPause = !LLAppViewer::getTextureFetch()->mDebugPause;
1027		return TRUE;
1028	}
1029	if (mask & MASK_SHIFT)
1030	{
1031		mFreezeView = !mFreezeView;
1032		return TRUE;
1033	}
1034	if (mask & MASK_CONTROL)
1035	{
1036		mOrderFetch = !mOrderFetch;
1037		return TRUE;
1038	}
1039	return LLView::handleMouseDown(x,y,mask);
1040}
1041
1042BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask)
1043{
1044	return FALSE;
1045}
1046
1047BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
1048{
1049	return FALSE;
1050}
1051
1052//-----------------------------------------------------------------
1053LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p)
1054{
1055	setVisible(FALSE) ;
1056
1057	mTextureSizeBarWidth = 30 ;
1058}
1059
1060LLTextureSizeView::~LLTextureSizeView()
1061{
1062	if(mTextureSizeBar.size())
1063	{
1064		for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
1065		{
1066			delete mTextureSizeBar[i] ;
1067		}
1068		mTextureSizeBar.clear() ;
1069	}
1070}
1071void LLTextureSizeView::draw()
1072{
1073	if(mType == TEXTURE_MEM_OVER_SIZE)
1074	{
1075		drawTextureSizeGraph();
1076	}
1077	else
1078	{
1079		drawTextureCategoryGraph() ;
1080	}
1081	
1082	LLView::draw();
1083}
1084
1085BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) 
1086{
1087	if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
1088	{
1089		mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ;
1090	}
1091
1092	return TRUE ;
1093}
1094
1095//draw real-time texture mem bar over size
1096void LLTextureSizeView::drawTextureSizeGraph()
1097{
1098	if(mTextureSizeBar.size() == 0)
1099	{
1100		S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
1101		mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
1102		mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
1103		
1104		for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
1105		{				
1106			mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , 
1107				line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;				
1108		}			
1109	}
1110
1111	F32 size_bar_scale = drawTextureSizeDistributionGraph() ;		
1112	for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
1113	{
1114		mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ;
1115		mTextureSizeBar[i]->draw() ;
1116	}		
1117	LLImageGL::resetCurTexSizebar();
1118}
1119
1120//draw background of texture size bar graph
1121F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
1122{	
1123	//scale
1124	F32 scale = 1.0f ;
1125	
1126	LLGLSUIDefault gls_ui;
1127
1128	{
1129		S32 count = 0 ;
1130		for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
1131		{
1132			if(LLImageGL::sTextureLoadedCounter[i] > count)
1133			{
1134				count = LLImageGL::sTextureLoadedCounter[i] ;
1135			}
1136		}
1137		if(count > mTextureSizeBarRect.getHeight())
1138		{
1139			scale = (F32)mTextureSizeBarRect.getHeight() / count ;
1140		}
1141	}
1142
1143	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
1144	S32 left = mTextureSizeBarRect.mLeft ;
1145	S32 bottom = mTextureSizeBarRect.mBottom ;
1146	S32 right = mTextureSizeBarRect.mRight ;
1147	S32 top = mTextureSizeBarRect.mTop ;
1148
1149	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1150	
1151	//background rect
1152	gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
1153
1154	//--------------------------------------------------
1155	gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
1156	gl_line_2d(left, bottom, right, bottom) ; //x axis
1157	gl_line_2d(left, bottom, left, top) ; //y axis
1158
1159	//ruler
1160	//--------------------------------------------------
1161	gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
1162	for(S32 i = bottom + 50 ; i <= top ; i += 50)
1163	{
1164		gl_line_2d(left, i, right, i) ;
1165	}
1166
1167	//texts
1168	//--------------------------------------------------
1169	F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};	
1170	std::string text;
1171	
1172	//-------
1173	//x axis: size label
1174	text = llformat("%d", 0) ;
1175	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
1176									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1177	for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
1178	{
1179		text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ;
1180		LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
1181									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1182	}
1183	text = llformat("(w + h)/2") ;
1184	LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2,
1185									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1186	//-------
1187
1188	//y axis: number label
1189	for(S32 i = bottom + 50 ; i <= top ; i += 50)
1190	{
1191		text = llformat("%d", (S32)((i - bottom) / scale)) ;
1192		LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
1193									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1194		LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
1195									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1196	}
1197
1198	//--------------------------------------------------
1199	F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
1200	gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
1201	text = llformat("Loaded") ;
1202	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
1203									 loaded_color, LLFontGL::LEFT, LLFontGL::TOP);
1204
1205	F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
1206	gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
1207	text = llformat("Bound") ;
1208	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
1209									 bound_color, LLFontGL::LEFT, LLFontGL::TOP);
1210
1211	//--------------------------------------------------
1212
1213	//title
1214	text = llformat("Texture Size Distribution") ;
1215	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
1216									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1217	return scale ;
1218}
1219
1220//draw real-time texture mem bar over category
1221void LLTextureSizeView::drawTextureCategoryGraph()
1222{
1223	if(mTextureSizeBar.size() == 0)
1224	{
1225		S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
1226		mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;
1227		mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
1228		
1229		for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
1230		{				
1231			mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , 
1232				line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;				
1233		}			
1234	}
1235
1236	F32 size_bar_scale = drawTextureCategoryDistributionGraph() ;		
1237	for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
1238	{
1239		U32 k = LLViewerTexture::getIndexFromCategory(i) ;
1240		mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ;
1241		mTextureSizeBar[i]->draw() ;
1242	}		
1243	LLImageGL::resetCurTexSizebar();
1244}
1245
1246//draw background for TEXTURE_MEM_OVER_CATEGORY
1247F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() 
1248{
1249	//scale
1250	F32 scale = 4.0f ;
1251	
1252	LLGLSUIDefault gls_ui;
1253
1254	{
1255		S32 count = 0 ;
1256		for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
1257		{
1258			S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ;
1259			if(tmp > count)
1260			{
1261				count = tmp ;
1262			}
1263		}
1264		if(count > mTextureSizeBarRect.getHeight() * 0.25f)
1265		{
1266			scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ;
1267		}
1268	}
1269
1270	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
1271	S32 left = mTextureSizeBarRect.mLeft ;
1272	S32 bottom = mTextureSizeBarRect.mBottom ;
1273	S32 right = mTextureSizeBarRect.mRight ;
1274	S32 top = mTextureSizeBarRect.mTop ;
1275
1276	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1277	
1278	//background rect
1279	gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
1280
1281	//--------------------------------------------------
1282	gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
1283	gl_line_2d(left, bottom, right, bottom) ; //x axis
1284	gl_line_2d(left, bottom, left, top) ; //y axis
1285
1286	//ruler
1287	//--------------------------------------------------
1288	gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
1289	for(S32 i = bottom + 50 ; i <= top ; i += 50)
1290	{
1291		gl_line_2d(left, i, right, i) ;
1292	}
1293
1294	//texts
1295	//--------------------------------------------------
1296	F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};	
1297	std::string text;
1298	
1299	//-------
1300	//x axis: size label			
1301	static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] = 
1302	{"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ;
1303
1304	text = llformat("%s", category[0]) ;
1305	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
1306									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1307	for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
1308	{
1309		text = llformat("%s", category[i]) ;
1310		LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
1311									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1312	}
1313	//-------
1314
1315	//y axis: number label
1316	for(S32 i = bottom + 50 ; i <= top ; i += 50)
1317	{
1318		text = llformat("%d", (S32)((i - bottom) / scale)) ;
1319		LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
1320									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1321		LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
1322									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1323	}
1324
1325	text = llformat("MB") ;
1326	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 ,
1327									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1328	//--------------------------------------------------
1329	F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
1330	gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
1331	text = llformat("Loaded") ;
1332	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
1333									 loaded_color, 
1334									 LLFontGL::LEFT, LLFontGL::TOP);
1335
1336	F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
1337	gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
1338	text = llformat("Bound") ;
1339	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
1340									 bound_color, LLFontGL::LEFT, LLFontGL::TOP);
1341
1342	//--------------------------------------------------
1343
1344	//title
1345	text = llformat("Texture Category Distribution") ;
1346	LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
1347									 text_color, LLFontGL::LEFT, LLFontGL::TOP);
1348
1349	return scale ;
1350}