PageRenderTime 218ms CodeModel.GetById 65ms app.highlight 138ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llviewertexture.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2430 lines | 1914 code | 309 blank | 207 comment | 327 complexity | 0741c41b5059d516ab42952772805c6b MD5 | raw file
   1/** 
   2 * @file llviewertexture.cpp
   3 * @brief Object which handles a received image (and associated texture(s))
   4 *
   5 * $LicenseInfo:firstyear=2000&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 "llviewertexture.h"
  30
  31// Library includes
  32#include "imageids.h"
  33#include "llmath.h"
  34#include "llerror.h"
  35#include "llgl.h"
  36#include "llglheaders.h"
  37#include "llhost.h"
  38#include "llimage.h"
  39#include "llimagebmp.h"
  40#include "llimagej2c.h"
  41#include "llimagetga.h"
  42#include "llmemtype.h"
  43#include "llstl.h"
  44#include "llvfile.h"
  45#include "llvfs.h"
  46#include "message.h"
  47#include "lltimer.h"
  48
  49// viewer includes
  50#include "llimagegl.h"
  51#include "lldrawpool.h"
  52#include "lltexturefetch.h"
  53#include "llviewertexturelist.h"
  54#include "llviewercontrol.h"
  55#include "pipeline.h"
  56#include "llappviewer.h"
  57#include "llface.h"
  58#include "llviewercamera.h"
  59#include "lltextureatlas.h"
  60#include "lltextureatlasmanager.h"
  61#include "lltextureentry.h"
  62#include "llmediaentry.h"
  63#include "llvovolume.h"
  64#include "llviewermedia.h"
  65///////////////////////////////////////////////////////////////////////////////
  66
  67// statics
  68LLPointer<LLViewerTexture>        LLViewerTexture::sNullImagep = NULL;
  69LLPointer<LLViewerTexture>        LLViewerTexture::sBlackImagep = NULL;
  70LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
  71LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
  72LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
  73LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
  74LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
  75LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
  76const std::string sTesterName("TextureTester");
  77
  78S32 LLViewerTexture::sImageCount = 0;
  79S32 LLViewerTexture::sRawCount = 0;
  80S32 LLViewerTexture::sAuxCount = 0;
  81LLFrameTimer LLViewerTexture::sEvaluationTimer;
  82F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
  83F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
  84S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0;
  85S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0;
  86S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
  87S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
  88S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
  89S8  LLViewerTexture::sCameraMovingDiscardBias = 0 ;
  90S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
  91const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
  92const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ;
  93const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ;
  94S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256.
  95S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
  96BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
  97F32 LLViewerTexture::sCurrentTime = 0.0f ;
  98BOOL LLViewerTexture::sUseTextureAtlas        = FALSE ;
  99
 100const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
 101const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by
 102const F64 log_2 = log(2.0);
 103
 104//----------------------------------------------------------------------------------------------
 105//namespace: LLViewerTextureAccess
 106//----------------------------------------------------------------------------------------------
 107
 108LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb,
 109					  S32 discard_level,
 110					  BOOL need_imageraw, // Needs image raw for the callback
 111					  void* userdata,
 112					  LLLoadedCallbackEntry::source_callback_list_t* src_callback_list,
 113					  LLViewerFetchedTexture* target,
 114					  BOOL pause) 
 115	: mCallback(cb),
 116	  mLastUsedDiscard(MAX_DISCARD_LEVEL+1),
 117	  mDesiredDiscard(discard_level),
 118	  mNeedsImageRaw(need_imageraw),
 119	  mUserData(userdata),
 120	  mSourceCallbackList(src_callback_list),
 121	  mPaused(pause)
 122{
 123	if(mSourceCallbackList)
 124	{
 125		mSourceCallbackList->insert(target->getID());
 126	}
 127}
 128
 129LLLoadedCallbackEntry::~LLLoadedCallbackEntry()
 130{
 131}
 132
 133void LLLoadedCallbackEntry::removeTexture(LLViewerFetchedTexture* tex)
 134{
 135	if(mSourceCallbackList)
 136	{
 137		mSourceCallbackList->erase(tex->getID()) ;
 138	}
 139}
 140
 141//static 
 142void LLLoadedCallbackEntry::cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list)
 143{
 144	//clear texture callbacks.
 145	if(callback_list && !callback_list->empty())
 146	{
 147		for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = callback_list->begin();
 148				iter != callback_list->end(); ++iter)
 149		{
 150			LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ;
 151			if(tex)
 152			{
 153				tex->deleteCallbackEntry(callback_list) ;			
 154			}
 155		}
 156		callback_list->clear() ;
 157	}
 158}
 159
 160LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image)
 161{
 162	return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ;		
 163}
 164 
 165LLViewerTexture*  LLViewerTextureManager::findTexture(const LLUUID& id) 
 166{
 167	LLViewerTexture* tex ;
 168	//search fetched texture list
 169	tex = gTextureList.findImage(id) ;
 170	
 171	//search media texture list
 172	if(!tex)
 173	{
 174		tex = LLViewerTextureManager::findMediaTexture(id) ;
 175	}
 176	return tex ;
 177}
 178		
 179LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
 180{
 181	return LLViewerMediaTexture::findMediaTexture(media_id) ;	
 182}
 183
 184LLViewerMediaTexture*  LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) 
 185{
 186	LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ;	
 187	if(!tex)
 188	{
 189		tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ;
 190	}
 191
 192	tex->initVirtualSize() ;
 193
 194	return tex ;
 195}
 196
 197LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
 198{
 199	if(!tex)
 200	{
 201		return NULL ;
 202	}
 203
 204	S8 type = tex->getType() ;
 205	if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
 206	{
 207		return static_cast<LLViewerFetchedTexture*>(tex) ;
 208	}
 209
 210	if(report_error)
 211	{
 212		llerrs << "not a fetched texture type: " << type << llendl ;
 213	}
 214
 215	return NULL ;
 216}
 217
 218LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipmaps, BOOL generate_gl_tex)
 219{
 220	LLPointer<LLViewerTexture> tex = new LLViewerTexture(usemipmaps) ;
 221	if(generate_gl_tex)
 222	{
 223		tex->generateGLTexture() ;
 224		tex->setCategory(LLViewerTexture::LOCAL) ;
 225	}
 226	return tex ;
 227}
 228LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex) 
 229{
 230	LLPointer<LLViewerTexture> tex = new LLViewerTexture(id, usemipmaps) ;
 231	if(generate_gl_tex)
 232	{
 233		tex->generateGLTexture() ;
 234		tex->setCategory(LLViewerTexture::LOCAL) ;
 235	}
 236	return tex ;
 237}
 238LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) 
 239{
 240	LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ;
 241	tex->setCategory(LLViewerTexture::LOCAL) ;
 242	return tex ;
 243}
 244LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) 
 245{
 246	LLPointer<LLViewerTexture> tex = new LLViewerTexture(width, height, components, usemipmaps) ;
 247	if(generate_gl_tex)
 248	{
 249		tex->generateGLTexture() ;
 250		tex->setCategory(LLViewerTexture::LOCAL) ;
 251	}
 252	return tex ;
 253}
 254
 255LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
 256	                                               const LLUUID &image_id,											       
 257												   BOOL usemipmaps,
 258												   LLViewerTexture::EBoostLevel boost_priority,
 259												   S8 texture_type,
 260												   LLGLint internal_format,
 261												   LLGLenum primary_format,
 262												   LLHost request_from_host)
 263{
 264	return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
 265}
 266	
 267LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile(
 268	                                               const std::string& filename,												   
 269												   BOOL usemipmaps,
 270												   LLViewerTexture::EBoostLevel boost_priority,
 271												   S8 texture_type,
 272												   LLGLint internal_format,
 273												   LLGLenum primary_format, 
 274												   const LLUUID& force_id)
 275{
 276	return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
 277}
 278
 279//static 
 280LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url,									 
 281									 BOOL usemipmaps,
 282									 LLViewerTexture::EBoostLevel boost_priority,
 283									 S8 texture_type,
 284									 LLGLint internal_format,
 285									 LLGLenum primary_format,
 286									 const LLUUID& force_id
 287									 )
 288{
 289	return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
 290}
 291
 292LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) 
 293{
 294	return gTextureList.getImageFromHost(image_id, host) ;
 295}
 296
 297void LLViewerTextureManager::init()
 298{
 299	{
 300		LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
 301		raw->clear(0x77, 0x77, 0x77, 0xFF);
 302		LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
 303	}
 304
 305	const S32 dim = 128;
 306	LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
 307	U8* data = image_raw->getData();
 308	
 309	memset(data, 0, dim * dim * 3) ;
 310	LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ;
 311
 312#if 1
 313	LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
 314	LLViewerFetchedTexture::sDefaultImagep = imagep;
 315	
 316	for (S32 i = 0; i<dim; i++)
 317	{
 318		for (S32 j = 0; j<dim; j++)
 319		{
 320#if 0
 321			const S32 border = 2;
 322			if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
 323			{
 324				*data++ = 0xff;
 325				*data++ = 0xff;
 326				*data++ = 0xff;
 327			}
 328			else
 329#endif
 330			{
 331				*data++ = 0x7f;
 332				*data++ = 0x7f;
 333				*data++ = 0x7f;
 334			}
 335		}
 336	}
 337	imagep->createGLTexture(0, image_raw);
 338	//cache the raw image
 339	imagep->setCachedRawImage(0, image_raw) ;
 340	image_raw = NULL;
 341#else
 342 	LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
 343#endif
 344	LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
 345	LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ;
 346
 347 	LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
 348	LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
 349
 350	LLViewerTexture::initClass() ;
 351
 352	if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
 353	{
 354		sTesterp = new LLTexturePipelineTester() ;
 355		if (!sTesterp->isValid())
 356		{
 357			delete sTesterp;
 358			sTesterp = NULL;
 359		}
 360	}
 361}
 362
 363void LLViewerTextureManager::cleanup()
 364{
 365	stop_glerror();
 366
 367	LLImageGL::sDefaultGLTexture = NULL ;
 368	LLViewerTexture::sNullImagep = NULL;
 369	LLViewerTexture::sBlackImagep = NULL;
 370	LLViewerFetchedTexture::sDefaultImagep = NULL;	
 371	LLViewerFetchedTexture::sSmokeImagep = NULL;
 372	LLViewerFetchedTexture::sMissingAssetImagep = NULL;
 373	LLViewerFetchedTexture::sWhiteImagep = NULL;
 374
 375	LLViewerMediaTexture::cleanUpClass() ;	
 376}
 377
 378//----------------------------------------------------------------------------------------------
 379//----------------------------------------------------------------------------------------------
 380//start of LLViewerTexture
 381//----------------------------------------------------------------------------------------------
 382// static
 383void LLViewerTexture::initClass()
 384{
 385	LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
 386
 387	if(gAuditTexture)
 388	{
 389		LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ;	
 390	}
 391}
 392
 393// static
 394S32 LLViewerTexture::getTotalNumOfCategories() 
 395{
 396	return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ;
 397}
 398
 399// static
 400//index starts from zero.
 401S32 LLViewerTexture::getIndexFromCategory(S32 category) 
 402{
 403	return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ;
 404}
 405
 406//static 
 407S32 LLViewerTexture::getCategoryFromIndex(S32 index)
 408{
 409	return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ;
 410}
 411
 412// tuning params
 413const F32 discard_bias_delta = .25f;
 414const F32 discard_delta_time = 0.5f;
 415const S32 min_non_tex_system_mem = (128<<20); // 128 MB
 416// non-const (used externally
 417F32 texmem_lower_bound_scale = 0.85f;
 418F32 texmem_middle_bound_scale = 0.925f;
 419
 420static LLFastTimer::DeclareTimer FTM_TEXTURE_MEMORY_CHECK("Memory Check");
 421
 422//static 
 423bool LLViewerTexture::isMemoryForTextureLow()
 424{
 425	const F32 WAIT_TIME = 1.0f ; //second
 426	static LLFrameTimer timer ;
 427
 428	if(timer.getElapsedTimeF32() < WAIT_TIME) //call this once per second.
 429	{
 430		return false;
 431	}
 432	timer.reset() ;
 433
 434	LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
 435
 436	const S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
 437	const S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB	
 438
 439	bool low_mem = false ;
 440	if (gGLManager.mHasATIMemInfo)
 441	{
 442		S32 meminfo[4];
 443		glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
 444
 445		if(meminfo[0] / 1024 < MIN_FREE_TEXTURE_MEMORY)
 446		{
 447			low_mem = true ;
 448		}
 449
 450		if(!low_mem) //check main memory, only works for windows.
 451		{
 452			LLMemory::updateMemoryInfo() ;
 453			if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
 454			{
 455				low_mem = true ;
 456			}
 457		}
 458	}
 459#if 0  //ignore nVidia cards
 460	else if (gGLManager.mHasNVXMemInfo)
 461	{
 462		S32 free_memory;
 463		glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
 464		
 465		if(free_memory / 1024 < MIN_FREE_TEXTURE_MEMORY)
 466		{
 467			low_mem = true ;
 468		}
 469	}
 470#endif	
 471
 472	return low_mem ;
 473}
 474
 475static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_MEDIA("Media");
 476static LLFastTimer::DeclareTimer FTM_TEXTURE_UPDATE_TEST("Test");
 477
 478//static
 479void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
 480{
 481	sCurrentTime = gFrameTimeSeconds ;
 482
 483	LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
 484	if (tester)
 485	{
 486		LLFastTimer t(FTM_TEXTURE_UPDATE_TEST);
 487		tester->update() ;
 488	}
 489
 490	{
 491		LLFastTimer t(FTM_TEXTURE_UPDATE_MEDIA);
 492		LLViewerMediaTexture::updateClass() ;
 493	}
 494
 495	sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
 496	sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
 497	sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB	
 498	sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB
 499	sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small.
 500
 501	if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes ||
 502		BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes)
 503	{
 504		//when texture memory overflows, lower down the threashold to release the textures more aggressively.
 505		sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB
 506	
 507		// If we are using more texture memory than we should,
 508		// scale up the desired discard level
 509		if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
 510		{
 511			sDesiredDiscardBias += discard_bias_delta;
 512			sEvaluationTimer.reset();
 513		}
 514	}
 515	else if(sEvaluationTimer.getElapsedTimeF32() > discard_delta_time && isMemoryForTextureLow())
 516	{
 517		sDesiredDiscardBias += discard_bias_delta;
 518		sEvaluationTimer.reset();
 519	}
 520	else if (sDesiredDiscardBias > 0.0f &&
 521			 BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
 522			 BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
 523	{			 
 524		// If we are using less texture memory than we should,
 525		// scale down the desired discard level
 526		if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
 527		{
 528			sDesiredDiscardBias -= discard_bias_delta;
 529			sEvaluationTimer.reset();
 530		}
 531	}
 532	sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
 533	LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
 534	
 535	F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
 536	F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
 537	sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
 538
 539	LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
 540				(BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
 541}
 542
 543//end of static functions
 544//-------------------------------------------------------------------------------------------
 545const U32 LLViewerTexture::sCurrentFileVersion = 1;
 546
 547LLViewerTexture::LLViewerTexture(BOOL usemipmaps)
 548{
 549	init(true);
 550	mUseMipMaps = usemipmaps ;
 551
 552	mID.generate();
 553	sImageCount++;
 554}
 555
 556LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps)
 557	: mID(id)
 558{
 559	init(true);
 560	mUseMipMaps = usemipmaps ;
 561	
 562	sImageCount++;
 563}
 564
 565LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) 
 566{
 567	init(true);
 568
 569	mFullWidth = width ;
 570	mFullHeight = height ;
 571	mUseMipMaps = usemipmaps ;
 572	mComponents = components ;
 573	setTexelsPerImage();
 574
 575	mID.generate();
 576	sImageCount++;
 577}
 578
 579LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps)	
 580{
 581	init(true);
 582	mUseMipMaps = usemipmaps ;
 583	mGLTexturep = new LLImageGL(raw, usemipmaps) ;
 584	
 585	// Create an empty image of the specified size and width
 586	mID.generate();
 587	sImageCount++;
 588}
 589
 590LLViewerTexture::~LLViewerTexture()
 591{
 592	cleanup();
 593	sImageCount--;
 594}
 595
 596void LLViewerTexture::init(bool firstinit)
 597{
 598	mBoostLevel = LLViewerTexture::BOOST_NONE;
 599
 600	mFullWidth = 0;
 601	mFullHeight = 0;
 602	mTexelsPerImage = 0 ;
 603	mUseMipMaps = FALSE ;
 604	mComponents = 0 ;
 605
 606	mTextureState = NO_DELETE ;
 607	mDontDiscard = FALSE;
 608	mMaxVirtualSize = 0.f;
 609	mNeedsGLTexture = FALSE ;
 610	mMaxVirtualSizeResetInterval = 1;
 611	mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ;
 612	mAdditionalDecodePriority = 0.f ;	
 613	mParcelMedia = NULL ;
 614	mNumFaces = 0 ;
 615	mNumVolumes = 0;
 616	mFaceList.clear() ;
 617	mVolumeList.clear();
 618}
 619
 620//virtual 
 621S8 LLViewerTexture::getType() const
 622{
 623	return LLViewerTexture::LOCAL_TEXTURE ;
 624}
 625
 626void LLViewerTexture::cleanup()
 627{
 628	mFaceList.clear() ;
 629	mVolumeList.clear();
 630	if(mGLTexturep)
 631	{
 632		mGLTexturep->cleanup();
 633	}
 634}
 635
 636// virtual
 637void LLViewerTexture::dump()
 638{
 639	if(mGLTexturep)
 640	{
 641		mGLTexturep->dump();
 642	}
 643
 644	llinfos << "LLViewerTexture"
 645			<< " mID " << mID
 646			<< llendl;
 647}
 648
 649void LLViewerTexture::setBoostLevel(S32 level)
 650{
 651	if(mBoostLevel != level)
 652	{
 653		mBoostLevel = level ;
 654		if(mBoostLevel != LLViewerTexture::BOOST_NONE)
 655		{
 656			setNoDelete() ;		
 657		}
 658		if(gAuditTexture)
 659		{
 660			setCategory(mBoostLevel);
 661		}
 662	}
 663}
 664
 665
 666bool LLViewerTexture::bindDefaultImage(S32 stage) 
 667{
 668	if (stage < 0) return false;
 669
 670	bool res = true;
 671	if (LLViewerFetchedTexture::sDefaultImagep.notNull() && (this != LLViewerFetchedTexture::sDefaultImagep.get()))
 672	{
 673		// use default if we've got it
 674		res = gGL.getTexUnit(stage)->bind(LLViewerFetchedTexture::sDefaultImagep);
 675	}
 676	if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep))
 677	{
 678		res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep);
 679	}
 680	if (!res)
 681	{
 682		llwarns << "LLViewerTexture::bindDefaultImage failed." << llendl;
 683	}
 684	stop_glerror();
 685
 686	//check if there is cached raw image and switch to it if possible
 687	switchToCachedImage() ;
 688
 689	LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
 690	if (tester)
 691	{
 692		tester->updateGrayTextureBinding() ;
 693	}
 694	return res;
 695}
 696
 697//virtual 
 698BOOL LLViewerTexture::isMissingAsset()const		
 699{ 
 700	return FALSE; 
 701}
 702
 703//virtual 
 704void LLViewerTexture::forceImmediateUpdate() 
 705{
 706}
 707
 708void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const 
 709{
 710	if(needs_gltexture)
 711	{
 712		mNeedsGLTexture = TRUE ;
 713	}
 714
 715	if(!mMaxVirtualSizeResetCounter)
 716	{
 717		//flag to reset the values because the old values are used.
 718		resetMaxVirtualSizeResetCounter() ;
 719		mMaxVirtualSize = virtual_size;		
 720		mAdditionalDecodePriority = 0.f ;	
 721		mNeedsGLTexture = needs_gltexture ;
 722	}
 723	else if (virtual_size > mMaxVirtualSize)
 724	{
 725		mMaxVirtualSize = virtual_size;
 726	}	
 727}
 728
 729void LLViewerTexture::resetTextureStats()
 730{
 731	mMaxVirtualSize = 0.0f ;
 732	mAdditionalDecodePriority = 0.f ;	
 733	mMaxVirtualSizeResetCounter = 0 ;
 734}
 735
 736//virtual 
 737F32 LLViewerTexture::getMaxVirtualSize()
 738{
 739	return mMaxVirtualSize ;
 740}
 741
 742//virtual 
 743void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
 744{
 745	//nothing here.
 746}
 747
 748//virtual
 749void LLViewerTexture::addFace(LLFace* facep) 
 750{
 751	if(mNumFaces >= mFaceList.size())
 752	{
 753		mFaceList.resize(2 * mNumFaces + 1) ;		
 754	}
 755	mFaceList[mNumFaces] = facep ;
 756	facep->setIndexInTex(mNumFaces) ;
 757	mNumFaces++ ;
 758	mLastFaceListUpdateTimer.reset() ;
 759}
 760
 761//virtual
 762void LLViewerTexture::removeFace(LLFace* facep) 
 763{
 764	if(mNumFaces > 1)
 765	{
 766		S32 index = facep->getIndexInTex() ; 
 767		mFaceList[index] = mFaceList[--mNumFaces] ;
 768		mFaceList[index]->setIndexInTex(index) ;
 769	}
 770	else 
 771	{
 772		mFaceList.clear() ;
 773		mNumFaces = 0 ;
 774	}
 775	mLastFaceListUpdateTimer.reset() ;
 776}
 777
 778S32 LLViewerTexture::getNumFaces() const
 779{
 780	return mNumFaces ;
 781}
 782
 783
 784//virtual
 785void LLViewerTexture::addVolume(LLVOVolume* volumep) 
 786{
 787	if( mNumVolumes >= mVolumeList.size())
 788	{
 789		mVolumeList.resize(2 * mNumVolumes + 1) ;		
 790	}
 791	mVolumeList[mNumVolumes] = volumep ;
 792	volumep->setIndexInTex(mNumVolumes) ;
 793	mNumVolumes++ ;
 794	mLastVolumeListUpdateTimer.reset() ;
 795}
 796
 797//virtual
 798void LLViewerTexture::removeVolume(LLVOVolume* volumep) 
 799{
 800	if(mNumVolumes > 1)
 801	{
 802		S32 index = volumep->getIndexInTex() ; 
 803		mVolumeList[index] = mVolumeList[--mNumVolumes] ;
 804		mVolumeList[index]->setIndexInTex(index) ;
 805	}
 806	else 
 807	{
 808		mVolumeList.clear() ;
 809		mNumVolumes = 0 ;
 810	}
 811	mLastVolumeListUpdateTimer.reset() ;
 812}
 813
 814S32 LLViewerTexture::getNumVolumes() const
 815{
 816	return mNumVolumes ;
 817}
 818
 819void LLViewerTexture::reorganizeFaceList()
 820{
 821	static const F32 MAX_WAIT_TIME = 20.f; // seconds
 822	static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
 823
 824	if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size())
 825	{
 826		return ;
 827	}
 828
 829	if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
 830	{
 831		return ;
 832	}
 833
 834	mLastFaceListUpdateTimer.reset() ;
 835	mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end());
 836}
 837
 838void LLViewerTexture::reorganizeVolumeList()
 839{
 840	static const F32 MAX_WAIT_TIME = 20.f; // seconds
 841	static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
 842
 843	if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size())
 844	{
 845		return ;
 846	}
 847
 848	if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
 849	{
 850		return ;
 851	}
 852
 853	mLastVolumeListUpdateTimer.reset() ;
 854	mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end());
 855}
 856
 857
 858
 859//virtual
 860void LLViewerTexture::switchToCachedImage()
 861{
 862	//nothing here.
 863}
 864
 865void LLViewerTexture::forceActive()
 866{
 867	mTextureState = ACTIVE ; 
 868}
 869
 870void LLViewerTexture::setActive() 
 871{ 
 872	if(mTextureState != NO_DELETE)
 873	{
 874		mTextureState = ACTIVE ; 
 875	}
 876}
 877
 878//set the texture to stay in memory
 879void LLViewerTexture::setNoDelete() 
 880{ 
 881	mTextureState = NO_DELETE ;
 882}
 883
 884void LLViewerTexture::generateGLTexture() 
 885{	
 886	if(mGLTexturep.isNull())
 887	{
 888		mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
 889	}
 890}
 891
 892LLImageGL* LLViewerTexture::getGLTexture() const
 893{
 894	llassert(mGLTexturep.notNull()) ;
 895
 896	return mGLTexturep ;
 897}
 898
 899BOOL LLViewerTexture::createGLTexture() 
 900{
 901	if(mGLTexturep.isNull())
 902	{
 903		generateGLTexture() ;
 904	}
 905
 906	return mGLTexturep->createGLTexture() ;
 907}
 908
 909BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category)
 910{
 911	llassert(mGLTexturep.notNull()) ;	
 912
 913	BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ;
 914
 915	if(ret)
 916	{
 917		mFullWidth = mGLTexturep->getCurrentWidth() ;
 918		mFullHeight = mGLTexturep->getCurrentHeight() ; 
 919		mComponents = mGLTexturep->getComponents() ;	
 920		setTexelsPerImage();
 921	}
 922
 923	return ret ;
 924}
 925
 926//virtual
 927void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
 928{
 929	//nothing here.
 930}
 931
 932void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
 933{
 934	llassert(mGLTexturep.notNull()) ;
 935	
 936	mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
 937}
 938void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
 939{
 940	llassert(mGLTexturep.notNull()) ;
 941	mGLTexturep->setAddressMode(mode) ;
 942}
 943void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
 944{
 945	llassert(mGLTexturep.notNull()) ;
 946	mGLTexturep->setFilteringOption(option) ;
 947}
 948
 949//virtual
 950S32	LLViewerTexture::getWidth(S32 discard_level) const
 951{
 952	llassert(mGLTexturep.notNull()) ;
 953	return mGLTexturep->getWidth(discard_level) ;
 954}
 955
 956//virtual
 957S32	LLViewerTexture::getHeight(S32 discard_level) const
 958{
 959	llassert(mGLTexturep.notNull()) ;
 960	return mGLTexturep->getHeight(discard_level) ;
 961}
 962
 963S32 LLViewerTexture::getMaxDiscardLevel() const
 964{
 965	llassert(mGLTexturep.notNull()) ;
 966	return mGLTexturep->getMaxDiscardLevel() ;
 967}
 968S32 LLViewerTexture::getDiscardLevel() const
 969{
 970	llassert(mGLTexturep.notNull()) ;
 971	return mGLTexturep->getDiscardLevel() ;
 972}
 973S8  LLViewerTexture::getComponents() const 
 974{ 
 975	llassert(mGLTexturep.notNull()) ;
 976	
 977	return mGLTexturep->getComponents() ;
 978}
 979
 980LLGLuint LLViewerTexture::getTexName() const 
 981{ 
 982	llassert(mGLTexturep.notNull()) ;
 983
 984	return mGLTexturep->getTexName() ; 
 985}
 986
 987BOOL LLViewerTexture::hasGLTexture() const 
 988{
 989	if(mGLTexturep.notNull())
 990	{
 991		return mGLTexturep->getHasGLTexture() ;
 992	}
 993	return FALSE ;
 994}
 995
 996BOOL LLViewerTexture::getBoundRecently() const
 997{
 998	if(mGLTexturep.notNull())
 999	{
1000		return mGLTexturep->getBoundRecently() ;
1001	}
1002	return FALSE ;
1003}
1004
1005LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const
1006{
1007	llassert(mGLTexturep.notNull()) ;
1008	return mGLTexturep->getTarget() ;
1009}
1010
1011BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
1012{
1013	llassert(mGLTexturep.notNull()) ;
1014
1015	return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ;
1016}
1017
1018BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
1019{
1020	llassert(mGLTexturep.notNull()) ;
1021
1022	return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ;
1023}
1024
1025void LLViewerTexture::setGLTextureCreated (bool initialized)
1026{
1027	llassert(mGLTexturep.notNull()) ;
1028
1029	mGLTexturep->setGLTextureCreated (initialized) ;
1030}
1031
1032void  LLViewerTexture::setCategory(S32 category) 
1033{
1034	llassert(mGLTexturep.notNull()) ;
1035
1036	mGLTexturep->setCategory(category) ;
1037}
1038
1039LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const
1040{
1041	llassert(mGLTexturep.notNull()) ;
1042
1043	return mGLTexturep->getAddressMode() ;
1044}
1045
1046S32 LLViewerTexture::getTextureMemory() const
1047{
1048	llassert(mGLTexturep.notNull()) ;
1049
1050	return mGLTexturep->mTextureMemory ;
1051}
1052
1053LLGLenum LLViewerTexture::getPrimaryFormat() const
1054{
1055	llassert(mGLTexturep.notNull()) ;
1056
1057	return mGLTexturep->getPrimaryFormat() ;
1058}
1059
1060BOOL LLViewerTexture::getIsAlphaMask() const
1061{
1062	llassert(mGLTexturep.notNull()) ;
1063
1064	return mGLTexturep->getIsAlphaMask() ;
1065}
1066
1067BOOL LLViewerTexture::getMask(const LLVector2 &tc)
1068{
1069	llassert(mGLTexturep.notNull()) ;
1070
1071	return mGLTexturep->getMask(tc) ;
1072}
1073
1074F32 LLViewerTexture::getTimePassedSinceLastBound()
1075{
1076	llassert(mGLTexturep.notNull()) ;
1077
1078	return mGLTexturep->getTimePassedSinceLastBound() ;
1079}
1080BOOL LLViewerTexture::getMissed() const 
1081{
1082	llassert(mGLTexturep.notNull()) ;
1083
1084	return mGLTexturep->getMissed() ;
1085}
1086
1087BOOL LLViewerTexture::isJustBound() const
1088{
1089	llassert(mGLTexturep.notNull()) ;
1090
1091	return mGLTexturep->isJustBound() ;
1092}
1093
1094void LLViewerTexture::forceUpdateBindStats(void) const
1095{
1096	llassert(mGLTexturep.notNull()) ;
1097
1098	return mGLTexturep->forceUpdateBindStats() ;
1099}
1100
1101U32 LLViewerTexture::getTexelsInAtlas() const
1102{
1103	llassert(mGLTexturep.notNull()) ;
1104
1105	return mGLTexturep->getTexelsInAtlas() ;
1106}
1107
1108U32 LLViewerTexture::getTexelsInGLTexture() const
1109{
1110	llassert(mGLTexturep.notNull()) ;
1111
1112	return mGLTexturep->getTexelsInGLTexture() ;
1113}
1114
1115BOOL LLViewerTexture::isGLTextureCreated() const
1116{
1117	llassert(mGLTexturep.notNull()) ;
1118
1119	return mGLTexturep->isGLTextureCreated() ;
1120}
1121
1122S32  LLViewerTexture::getDiscardLevelInAtlas() const
1123{
1124	llassert(mGLTexturep.notNull()) ;
1125
1126	return mGLTexturep->getDiscardLevelInAtlas() ;
1127}
1128
1129void LLViewerTexture::destroyGLTexture() 
1130{
1131	if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
1132	{
1133		mGLTexturep->destroyGLTexture() ;
1134		mTextureState = DELETED ;	
1135	}	
1136}
1137
1138void LLViewerTexture::setTexelsPerImage()
1139{
1140	S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
1141	S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
1142	mTexelsPerImage = (F32)fullwidth * fullheight;
1143}
1144
1145BOOL LLViewerTexture::isLargeImage()
1146{
1147	return  (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ;
1148}
1149
1150//virtual 
1151void LLViewerTexture::updateBindStatsForTester()
1152{
1153	LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
1154	if (tester)
1155	{
1156		tester->updateTextureBindingStats(this) ;
1157	}
1158}
1159
1160//----------------------------------------------------------------------------------------------
1161//end of LLViewerTexture
1162//----------------------------------------------------------------------------------------------
1163
1164//----------------------------------------------------------------------------------------------
1165//start of LLViewerFetchedTexture
1166//----------------------------------------------------------------------------------------------
1167
1168LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
1169	: LLViewerTexture(id, usemipmaps),
1170	mTargetHost(host)
1171{
1172	init(TRUE) ;
1173	generateGLTexture() ;
1174}
1175	
1176LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps)
1177	: LLViewerTexture(raw, usemipmaps)
1178{
1179	init(TRUE) ;
1180}
1181	
1182LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps)
1183	: LLViewerTexture(id, usemipmaps),
1184	mUrl(url)
1185{
1186	init(TRUE) ;
1187	generateGLTexture() ;
1188}
1189
1190void LLViewerFetchedTexture::init(bool firstinit)
1191{
1192	mOrigWidth = 0;
1193	mOrigHeight = 0;
1194	mNeedsAux = FALSE;
1195	mRequestedDiscardLevel = -1;
1196	mRequestedDownloadPriority = 0.f;
1197	mFullyLoaded = FALSE;
1198	mCanUseHTTP = true ;
1199	mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
1200	mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
1201	
1202	mDecodingAux = FALSE;
1203
1204	mKnownDrawWidth = 0;
1205	mKnownDrawHeight = 0;
1206	mKnownDrawSizeChanged = FALSE ;
1207
1208	if (firstinit)
1209	{
1210		mDecodePriority = 0.f;
1211		mInImageList = 0;
1212	}
1213
1214	// Only set mIsMissingAsset true when we know for certain that the database
1215	// does not contain this image.
1216	mIsMissingAsset = FALSE;
1217
1218	mLoadedCallbackDesiredDiscardLevel = S8_MAX;
1219	mPauseLoadedCallBacks = TRUE ;
1220
1221	mNeedsCreateTexture = FALSE;
1222	
1223	mIsRawImageValid = FALSE;
1224	mRawDiscardLevel = INVALID_DISCARD_LEVEL;
1225	mMinDiscardLevel = 0;
1226
1227	mHasFetcher = FALSE;
1228	mIsFetching = FALSE;
1229	mFetchState = 0;
1230	mFetchPriority = 0;
1231	mDownloadProgress = 0.f;
1232	mFetchDeltaTime = 999999.f;
1233	mRequestDeltaTime = 0.f;
1234	mForSculpt = FALSE ;
1235	mIsFetched = FALSE ;
1236
1237	mCachedRawImage = NULL ;
1238	mCachedRawDiscardLevel = -1 ;
1239	mCachedRawImageReady = FALSE ;
1240
1241	mSavedRawImage = NULL ;
1242	mForceToSaveRawImage  = FALSE ;
1243	mSaveRawImage = FALSE ;
1244	mSavedRawDiscardLevel = -1 ;
1245	mDesiredSavedRawDiscardLevel = -1 ;
1246	mLastReferencedSavedRawImageTime = 0.0f ;
1247	mKeptSavedRawImageTime = 0.f ;
1248	mLastCallBackActiveTime = 0.f;
1249}
1250
1251LLViewerFetchedTexture::~LLViewerFetchedTexture()
1252{
1253	//*NOTE getTextureFetch can return NULL when Viewer is shutting down.
1254	// This is due to LLWearableList is singleton and is destroyed after 
1255	// LLAppViewer::cleanup() was called. (see ticket EXT-177)
1256	if (mHasFetcher && LLAppViewer::getTextureFetch())
1257	{
1258		LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
1259	}
1260	cleanup();	
1261}
1262
1263//virtual 
1264S8 LLViewerFetchedTexture::getType() const
1265{
1266	return LLViewerTexture::FETCHED_TEXTURE ;
1267}
1268
1269void LLViewerFetchedTexture::cleanup()
1270{
1271	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
1272		iter != mLoadedCallbackList.end(); )
1273	{
1274		LLLoadedCallbackEntry *entryp = *iter++;
1275		// We never finished loading the image.  Indicate failure.
1276		// Note: this allows mLoadedCallbackUserData to be cleaned up.
1277		entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData );
1278		entryp->removeTexture(this) ;
1279		delete entryp;
1280	}
1281	mLoadedCallbackList.clear();
1282	mNeedsAux = FALSE;
1283	
1284	// Clean up image data
1285	destroyRawImage();
1286	mCachedRawImage = NULL ;
1287	mCachedRawDiscardLevel = -1 ;
1288	mCachedRawImageReady = FALSE ;
1289	mSavedRawImage = NULL ;
1290}
1291
1292void LLViewerFetchedTexture::setForSculpt()
1293{
1294	static const S32 MAX_INTERVAL = 8 ; //frames
1295
1296	mForSculpt = TRUE ;
1297	if(isForSculptOnly() && !getBoundRecently())
1298	{
1299		destroyGLTexture() ; //sculpt image does not need gl texture.
1300	}
1301	checkCachedRawSculptImage() ;
1302	setMaxVirtualSizeResetInterval(MAX_INTERVAL) ;
1303}
1304
1305BOOL LLViewerFetchedTexture::isForSculptOnly() const
1306{
1307	return mForSculpt && !mNeedsGLTexture ;
1308}
1309
1310BOOL LLViewerFetchedTexture::isDeleted()  
1311{ 
1312	return mTextureState == DELETED ; 
1313}
1314
1315BOOL LLViewerFetchedTexture::isInactive()  
1316{ 
1317	return mTextureState == INACTIVE ; 
1318}
1319
1320BOOL LLViewerFetchedTexture::isDeletionCandidate()  
1321{ 
1322	return mTextureState == DELETION_CANDIDATE ; 
1323}
1324
1325void LLViewerFetchedTexture::setDeletionCandidate()  
1326{ 
1327	if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE))
1328	{
1329		mTextureState = DELETION_CANDIDATE ;		
1330	}
1331}
1332
1333//set the texture inactive
1334void LLViewerFetchedTexture::setInactive()
1335{
1336	if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently())
1337	{
1338		mTextureState = INACTIVE ; 
1339	}
1340}
1341
1342BOOL LLViewerFetchedTexture::isFullyLoaded() const
1343{
1344	// Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic
1345	// to check if the texture is there and completely downloaded
1346	return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher;
1347}
1348
1349
1350// virtual
1351void LLViewerFetchedTexture::dump()
1352{
1353	LLViewerTexture::dump();
1354
1355	llinfos << "Dump : " << mID 
1356			<< ", mIsMissingAsset = " << (S32)mIsMissingAsset
1357			<< ", mFullWidth = " << (S32)mFullWidth
1358			<< ", mFullHeight = " << (S32)mFullHeight
1359			<< ", mOrigWidth = " << (S32)mOrigWidth
1360			<< ", mOrigHeight = " << (S32)mOrigHeight
1361			<< llendl;
1362	llinfos << "     : " 
1363			<< " mFullyLoaded = " << (S32)mFullyLoaded
1364			<< ", mFetchState = " << (S32)mFetchState
1365			<< ", mFetchPriority = " << (S32)mFetchPriority
1366			<< ", mDownloadProgress = " << (F32)mDownloadProgress
1367			<< llendl;
1368	llinfos << "     : " 
1369			<< " mHasFetcher = " << (S32)mHasFetcher
1370			<< ", mIsFetching = " << (S32)mIsFetching
1371			<< ", mIsFetched = " << (S32)mIsFetched
1372			<< ", mBoostLevel = " << (S32)mBoostLevel
1373			<< llendl;
1374}
1375
1376///////////////////////////////////////////////////////////////////////////////
1377// ONLY called from LLViewerFetchedTextureList
1378void LLViewerFetchedTexture::destroyTexture() 
1379{
1380	if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
1381	{
1382		return ;
1383	}
1384	if (mNeedsCreateTexture)//return if in the process of generating a new texture.
1385	{
1386		return ;
1387	}
1388	
1389	destroyGLTexture() ;
1390	mFullyLoaded = FALSE ;
1391}
1392
1393void LLViewerFetchedTexture::addToCreateTexture()
1394{
1395	bool force_update = false ;
1396	if (getComponents() != mRawImage->getComponents())
1397	{
1398		// We've changed the number of components, so we need to move any
1399		// objects using this pool to a different pool.
1400		mComponents = mRawImage->getComponents();
1401		mGLTexturep->setComponents(mComponents) ;
1402		force_update = true ;
1403
1404		for(U32 i = 0 ; i < mNumFaces ; i++)
1405		{
1406			mFaceList[i]->dirtyTexture() ;
1407		}
1408
1409		//discard the cached raw image and the saved raw image
1410		mCachedRawImageReady = FALSE ;
1411		mCachedRawDiscardLevel = -1 ;
1412		mCachedRawImage = NULL ;
1413		mSavedRawDiscardLevel = -1 ;
1414		mSavedRawImage = NULL ;
1415	}	
1416
1417	if(isForSculptOnly())
1418	{
1419		//just update some variables, not to create a real GL texture.
1420		createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ;
1421		mNeedsCreateTexture = FALSE ;
1422		destroyRawImage();
1423	}
1424	else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel)
1425	{
1426		mNeedsCreateTexture = FALSE ;
1427		destroyRawImage();
1428	}
1429	else
1430	{	
1431#if 1
1432		//
1433		//if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up,
1434		//so do not scale down the over qualified image.
1435		//Note: scaling down image is expensensive. Do it only when very necessary.
1436		//
1437		if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !mForceToSaveRawImage)
1438		{
1439			S32 w = mFullWidth >> mRawDiscardLevel;
1440			S32 h = mFullHeight >> mRawDiscardLevel;
1441
1442			//if big image, do not load extra data
1443			//scale it down to size >= LLViewerTexture::sMinLargeImageSize
1444			if(w * h > LLViewerTexture::sMinLargeImageSize)
1445			{
1446				S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ;
1447				
1448				if(d_level > 0)
1449				{
1450					S32 i = 0 ;
1451					while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize))
1452					{
1453						i++;
1454						d_level--;
1455					}
1456					if(i > 0)
1457					{
1458						mRawDiscardLevel += i ;
1459						if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0)
1460						{
1461							mNeedsCreateTexture = FALSE ;
1462							destroyRawImage();
1463							return ;
1464						}
1465						mRawImage->scale(w >> i, h >> i) ;					
1466					}
1467				}
1468			}
1469		}
1470#endif
1471		mNeedsCreateTexture = TRUE;
1472		gTextureList.mCreateTextureList.insert(this);
1473	}	
1474	return ;
1475}
1476
1477// ONLY called from LLViewerTextureList
1478BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
1479{
1480	if (!mNeedsCreateTexture)
1481	{
1482		destroyRawImage();
1483		return FALSE;
1484	}
1485	mNeedsCreateTexture	= FALSE;
1486	if (mRawImage.isNull())
1487	{
1488		llerrs << "LLViewerTexture trying to create texture with no Raw Image" << llendl;
1489	}
1490// 	llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ",
1491// 						mRawDiscardLevel, 
1492// 						mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize())
1493// 			<< mID.getString() << llendl;
1494	BOOL res = TRUE;
1495
1496	// store original size only for locally-sourced images
1497	if (mUrl.compare(0, 7, "file://") == 0)
1498	{
1499		mOrigWidth = mRawImage->getWidth();
1500		mOrigHeight = mRawImage->getHeight();
1501
1502			
1503		if (mBoostLevel == BOOST_PREVIEW)
1504		{ 
1505			mRawImage->biasedScaleToPowerOfTwo(1024);
1506		}
1507		else
1508		{ // leave black border, do not scale image content
1509			mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE);
1510		}
1511		
1512		mFullWidth = mRawImage->getWidth();
1513		mFullHeight = mRawImage->getHeight();
1514		setTexelsPerImage();
1515	}
1516	else
1517	{
1518		mOrigWidth = mFullWidth;
1519		mOrigHeight = mFullHeight;
1520	}
1521
1522	bool size_okay = true;
1523	
1524	U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel;
1525	U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel;
1526	if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
1527	{
1528		llinfos << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << llendl;
1529		size_okay = false;
1530	}
1531	
1532	if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight()))
1533	{
1534		// A non power-of-two image was uploaded (through a non standard client)
1535		llinfos << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << llendl;
1536		size_okay = false;
1537	}
1538	
1539	if( !size_okay )
1540	{
1541		// An inappropriately-sized image was uploaded (through a non standard client)
1542		// We treat these images as missing assets which causes them to
1543		// be renderd as 'missing image' and to stop requesting data
1544		setIsMissingAsset();
1545		destroyRawImage();
1546		return FALSE;
1547	}
1548	
1549	if(!(res = insertToAtlas()))
1550	{
1551		res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
1552		resetFaceAtlas() ;
1553	}
1554	setActive() ;
1555
1556	if (!needsToSaveRawImage())
1557	{
1558		mNeedsAux = FALSE;
1559		destroyRawImage();
1560	}
1561	return res;
1562}
1563
1564// Call with 0,0 to turn this feature off.
1565//virtual
1566void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
1567{
1568	if(mKnownDrawWidth < width || mKnownDrawHeight < height)
1569	{
1570		mKnownDrawWidth = llmax(mKnownDrawWidth, width) ;
1571		mKnownDrawHeight = llmax(mKnownDrawHeight, height) ;
1572
1573		mKnownDrawSizeChanged = TRUE ;
1574		mFullyLoaded = FALSE ;
1575	}
1576	addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight));
1577}
1578
1579//virtual
1580void LLViewerFetchedTexture::processTextureStats()
1581{
1582	if(mFullyLoaded)
1583	{		
1584		if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
1585		{
1586			mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ;
1587			mFullyLoaded = FALSE ;
1588		}
1589	}
1590	else
1591	{
1592		updateVirtualSize() ;
1593		
1594		static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
1595		
1596		if (textures_fullres)
1597		{
1598			mDesiredDiscardLevel = 0;
1599		}
1600		else if(!mFullWidth || !mFullHeight)
1601		{
1602			mDesiredDiscardLevel = 	llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel) ;
1603		}
1604		else
1605		{	
1606			if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
1607			{
1608				if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
1609				{
1610					mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
1611				}
1612				else
1613				{
1614					mDesiredDiscardLevel = 0;
1615				}
1616			}
1617			else if(mKnownDrawSizeChanged)//known draw size is set
1618			{			
1619				mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, 
1620													 log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
1621				mDesiredDiscardLevel = 	llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
1622				mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ;
1623			}
1624			mKnownDrawSizeChanged = FALSE ;
1625		
1626			if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
1627			{
1628				mFullyLoaded = TRUE ;
1629			}
1630		}
1631	}
1632
1633	if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture.
1634	{
1635		mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ;
1636		if(getDiscardLevel() < 0 || getDiscardLevel() > mDesiredDiscardLevel)
1637		{
1638			mFullyLoaded = FALSE ;
1639		}
1640	}
1641}
1642
1643const F32 MAX_PRIORITY_PIXEL                         = 999.f ;     //pixel area
1644const F32 PRIORITY_BOOST_LEVEL_FACTOR                = 1000.f ;    //boost level
1645const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR        = 100000.f ;  //delta discard
1646const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY       = 4 ;
1647const F32 PRIORITY_ADDITIONAL_FACTOR                 = 1000000.f ; //additional 
1648const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY          = 8 ;
1649const F32 PRIORITY_BOOST_HIGH_FACTOR                 = 10000000.f ;//boost high
1650F32 LLViewerFetchedTexture::calcDecodePriority()
1651{
1652#ifndef LL_RELEASE_FOR_DOWNLOAD
1653	if (mID == LLAppViewer::getTextureFetch()->mDebugID)
1654	{
1655		LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
1656	}
1657#endif
1658	
1659	if (mNeedsCreateTexture)
1660	{
1661		return mDecodePriority; // no change while waiting to create
1662	}
1663	if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture
1664	{
1665		return -1.0f ; //alreay fetched
1666	}
1667
1668	S32 cur_discard = getCurrentDiscardLevelForFetching();
1669	bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
1670	F32 pixel_priority = (F32) sqrt(mMaxVirtualSize);
1671
1672	F32 priority = 0.f;
1673
1674	if (mIsMissingAsset)
1675	{
1676		priority = 0.0f;
1677	}
1678	else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1)
1679	{
1680		priority = -2.0f ;
1681	}
1682	else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel)
1683	{
1684		priority = -3.0f;
1685	}
1686	else if (mDesiredDiscardLevel > getMaxDiscardLevel())
1687	{
1688		// Don't decode anything we don't need
1689		priority = -4.0f;
1690	}
1691	else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
1692	{
1693		priority = 1.f;
1694	}
1695	else if (pixel_priority < 0.001f && !have_all_data)
1696	{
1697		// Not on screen but we might want some data
1698		if (mBoostLevel > BOOST_HIGH)
1699		{
1700			// Always want high boosted images
1701			priority = 1.f;
1702		}
1703		else
1704		{
1705			priority = -5.f; //stop fetching
1706		}
1707	}
1708	else if (cur_discard < 0)
1709	{
1710		//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
1711		// priority range = 100,000 - 500,000
1712		static const F64 log_2 = log(2.0);
1713		F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
1714		S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
1715		ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
1716		priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
1717		setAdditionalDecodePriority(1.0f) ;//boost the textures without any data so far.
1718	}
1719	else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
1720	{
1721		// larger mips are corrupted
1722		priority = -6.0f;
1723	}
1724	else
1725	{
1726		// priority range = 100,000 - 500,000
1727		S32 desired_discard = mDesiredDiscardLevel;
1728		if (!isJustBound() && mCachedRawImageReady)
1729		{
1730			if(mBoostLevel < BOOST_HIGH)
1731			{
1732				// We haven't rendered this in a while, de-prioritize it
1733				desired_discard += 2;
1734			}
1735			else
1736			{
1737				// We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is
1738				desired_discard = cur_discard;
1739			}
1740		}
1741
1742		S32 ddiscard = cur_discard - desired_discard;
1743		ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
1744		priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;		
1745	}
1746
1747	// Priority Formula:
1748	// BOOST_HIGH  +  ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS
1749	// [10,000,000] + [1,000,000-9,000,000]  + [100,000-500,000]   + [1-20,000]  + [0-999]
1750	if (priority > 0.0f)
1751	{
1752		bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize) ;
1753		if(large_enough)
1754		{
1755			//Note: 
1756			//to give small, low-priority textures some chance to be fetched, 
1757			//cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready.
1758			priority *= 0.5f ; 
1759		}
1760
1761		pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); 
1762
1763		priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel;
1764
1765		if ( mBoostLevel > BOOST_HIGH)
1766		{
1767			if(mBoostLevel > BOOST_SUPER_HIGH)
1768			{
1769				//for very important textures, always grant the highest priority.
1770				priority += PRIORITY_BOOST_HIGH_FACTOR;
1771			}
1772			else if(mCachedRawImageReady)
1773			{
1774				//Note: 
1775				//to give small, low-priority textures some chance to be fetched, 
1776				//if high priority texture has a 64*64 ready, lower its fetching priority.
1777				setAdditionalDecodePriority(0.5f) ;
1778			}
1779			else
1780			{
1781				priority += PRIORITY_BOOST_HIGH_FACTOR;
1782			}
1783		}		
1784
1785		if(mAdditionalDecodePriority > 0.0f)
1786		{
1787			// priority range += 1,000,000.f-9,000,000.f
1788			F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY);
1789			if(large_enough)
1790			{
1791				//Note: 
1792				//to give small, low-priority textures some chance to be fetched, 
1793				//cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready.
1794				additional *= 0.25f ;
1795			}
1796			priority += additional;
1797		}
1798	}
1799	return priority;
1800}
1801
1802//static
1803F32 LLViewerFetchedTexture::maxDecodePriority()
1804{
1805	static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR +                           //boost_high
1806		PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) +             //additional (view dependent factors)
1807		PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard
1808		PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) +                              //boost level
1809		MAX_PRIORITY_PIXEL + 1.0f ;                                                        //pixel area.
1810	
1811	return max_priority ;
1812}
1813
1814//============================================================================
1815
1816void LLViewerFetchedTexture::setDecodePriority(F32 priority)
1817{
1818	llassert(!mInImageList); 
1819    
1820	mDecodePriority = priority;
1821
1822	if(mDecodePriority < F_ALMOST_ZERO)
1823	{
1824		mStopFetchingTimer.reset() ;
1825	}
1826}
1827
1828void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority)
1829{
1830	priority = llclamp(priority, 0.f, 1.f);
1831	if(mAdditionalDecodePriority < priority)
1832	{
1833		mAdditionalDecodePriority = priority;
1834	}
1835}
1836
1837void LLViewerFetchedTexture::updateVirtualSize() 
1838{	
1839	if(!mMaxVirtualSizeResetCounter)
1840	{
1841		addTextureStats(0.f, FALSE) ;//reset
1842	}
1843
1844	for(U32 i = 0 ; i < mNumFaces ; i++)
1845	{				
1846		LLFace* facep = mFaceList[i] ;
1847		if(facep->getDrawable()->isRecentlyVisible())
1848		{
1849			addTextureStats(facep->getVirtualSize()) ;
1850			setAdditionalDecodePriority(facep->getImportanceToCamera()) ;
1851		}
1852	}
1853
1854	if(mMaxVirtualSizeResetCounter > 0)
1855	{
1856		mMaxVirtualSizeResetCounter--;
1857	}
1858	reorganizeFaceList() ;
1859	reorganizeVolumeList();
1860}
1861
1862S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
1863{
1864	S32 current_discard = getDiscardLevel() ;
1865	if(mForceToSaveRawImage)
1866	{
1867		if(mSavedRawDiscardLevel < 0 || current_discard < 0)
1868		{
1869			current_discard = -1 ;
1870		}
1871		else
1872		{
1873			current_discard = llmax(current_discard, mSavedRawDiscardLevel) ;
1874		}		
1875	}
1876
1877	return current_discard ;
1878}
1879
1880bool LLViewerFetchedTexture::updateFetch()
1881{
1882	static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
1883	if(textures_decode_disabled)
1884	{
1885		return false ;
1886	}
1887
1888	mFetchState = 0;
1889	mFetchPriority = 0;
1890	mFetchDeltaTime = 999999.f;
1891	mRequestDeltaTime = 999999.f;
1892
1893#ifndef LL_RELEASE_FOR_DOWNLOAD
1894	if (mID == LLAppViewer::getTextureFetch()->mDebugID)
1895	{
1896		LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
1897	}
1898#endif
1899
1900	if (mNeedsCreateTexture)
1901	{
1902		// We may be fetching still (e.g. waiting on write)
1903		// but don't check until we've processed the raw data we have
1904		return false;
1905	}
1906	if (mIsMissingAsset)
1907	{
1908		llassert_always(!mHasFetcher);
1909		return false; // skip
1910	}
1911	if (!mLoadedCallbackList.empty() && mRawImage.notNull())
1912	{
1913		return false; // process any raw image data in callbacks before replacing
1914	}
1915	
1916	S32 current_discard = getCurrentDiscardLevelForFetching() ;
1917	S32 desired_discard = getDesiredDiscardLevel();
1918	F32 decode_priority = getDecodePriority();
1919	decode_priority = llclamp(decode_priority, 0.0f, maxDecodePriority());
1920
1921	if (mIsFetching)
1922	{
1923		// Sets mRawDiscardLevel, mRawImage, mAuxRawImage
1924		S32 fetch_discard = current_discard;
1925		
1926		if (mRawImage.notNull()) sRawCount--;
1927		if (mAuxRawImage.notNull()) sAuxCount--;
1928		bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
1929		if (mRawImage.notNull()) sRawCount++;
1930		if (mAuxRawImage.notNull()) sAuxCount++;
1931		if (finished)
1932		{
1933			mIsFetching = FALSE;
1934			mLastPacketTimer.reset() ;
1935		}
1936		else
1937		{
1938			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
1939																		mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
1940		}
1941		
1942		// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
1943		if (mRawImage.notNull())
1944		{
1945			LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
1946			if (tester)
1947			{
1948				mIsFetched = TRUE ;
1949				tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
1950			}
1951			mRawDiscardLevel = fetch_discard;
1952			if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
1953				(current_discard < 0 || mRawDiscardLevel < current_discard))
1954			{
1955				mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
1956				mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
1957				setTexelsPerImage();
1958
1959				if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
1960				{ 
1961					//discard all oversized textures.
1962					destroyRawImage();
1963					setIsMissingAsset();
1964					mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
1965					mIsFetching = FALSE ;
1966					mLastPacketTimer.reset();
1967				}
1968				else
1969				{
1970					mIsRawImageValid = TRUE;			
1971					addToCreateTexture() ;
1972				}
1973
1974				return TRUE ;
1975			}
1976			else
1977			{
1978				// Data is ready but we don't need it
1979				// (received it already while fetcher was writing to disk)
1980				destroyRawImage();
1981				return false; // done
1982			}
1983		}
1984		
1985		if (!mIsFetching)
1986		{
1987			if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
1988			{
1989				// We finished but received no data
1990				if (current_discard < 0)
1991				{
1992					setIsMissingAsset();
1993					desired_discard = -1;
1994				}
1995				else
1996				{
1997					//llwarns << mID << ": Setting min discard to " << current_discard << llendl;
1998					mMinDiscardLevel = current_discard;
1999					desired_discard = current_discard;
2000				}
2001				destroyRawImage();
2002			}
2003			else if (mRawImage.notNull())
2004			{
2005				// We have data, but our fetch failed to return raw data
2006				// *TODO: FIgure out why this is happening and fix it
2007				destroyRawImage();
2008			}
2009		}
2010		else
2011		{
2012// 			// Useful debugging code for undesired deprioritization of textures.
2013// 			if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard)
2014// 			{
2015// 				llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl;
2016// 				calcDecodePriority();
2017// 			}
2018			static const F32 MAX_HOLD_TIME = 5.0f ; //seconds to wait before canceling fecthing if decode_priority is 0.f.
2019			if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME)
2020			{
2021				mStopFetchingTimer.reset() ;
2022				LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority);
2023			}
2024		}
2025	}
2026
2027	bool make_request = true;	
2028	if (decode_priority <= 0)
2029	{
2030		make_request = false;
2031	}
2032	else if (mNeedsCreateTexture || mIsMissingAsset)
2033	{
2034		make_request = false;
2035	}
2036	else if (current_discard >= 0 && current_discard <= mMinDiscardLevel)
2037	{
2038		make_request = false;
2039	}
2040	//else if (!isJustBound() && mCachedRawImageReady)
2041	//{
2042	//	make_request = false;
2043	//}
2044	
2045	if(make_request)
2046	{
2047		//load the texture progressively.
2048		S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; 
2049		if(current_discard < 0)
2050		{
2051			desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level);
2052		}
2053		else
2054		{
2055			desired_discard = llmax(desired_discard, current_discard - delta_level);
2056		}
2057
2058		if (mIsFetching)
2059		{
2060			if (mRequestedDiscardLevel <= desired_discard)
2061			{
2062				make_request = false;
2063			}
2064		}
2065		else
2066		{
2067			if (current_discard >= 0 && current_discard <= desired_discard)
2068			{
2069				make_request = false;
2070			}
2071		}
2072	}
2073	
2074	if (make_request)
2075	{
2076		S32 w=0, h=0, c=0;
2077		if (getDiscardLevel() >= 0)
2078		{
2079			w = mGLTexturep->getWidth(0);
2080			h = mGLTexturep->getHeight(0);
2081			c = mComponents;
2082		}
2083
2084		const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel");
2085		if (override_tex_discard_level != 0)
2086		{
2087			desired_discard = override_tex_discard_level;
2088		}
2089		
2090		// bypass texturefetch directly by pulling from LLTextureCache
2091		bool fetch_request_created = false;
2092		fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority,
2093																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP);
2094		
2095		if (fetch_request_created)
2096		{
2097			mHasFetcher = TRUE;
2098			mIsFetching = TRUE;
2099			mRequestedDiscardLevel = desired_discard;
2100			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
2101													   mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
2102		}
2103
2104		// if createRequest() failed, we're finishing up a request for this UUID,
2105		// wait for it to complete
2106	}
2107	else if (mHasFetcher && !mIsFetching)
2108	{
2109		// Only delete requests that haven't receeived any network data for a while
2110		const F32 FETCH_IDLE_TIME = 5.f;
2111		if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME)
2112		{
2113// 			llinfos << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << llendl;
2114			LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
2115			mHasFetcher = FALSE;
2116		}
2117	}
2118	
2119	llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid));
2120	
2121	return mIsFetching ? true : false;
2122}
2123
2124void LLViewerFetchedTexture::setIsMissingAsset()
2125{
2126	if (mUrl.empty())
2127	{
2128		llwarns << mID << ": Marking image as missing" << llendl;
2129	}
2130	else
2131	{
2132		llwarns << mUrl << ": Marking image as missing" << llendl;
2133	}
2134	if (mHasFetcher)
2135	{
2136		LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
2137		mHasFetcher = FALSE;
2138		mIsFetching = FALSE;
2139		mLastPacketTimer.reset();
2140		mFetchState = 0;
2141		mFetchPriority = 0;
2142	}
2143	mIsMissingAsset = TRUE;
2144}
2145
2146void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
2147									   S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata, 
2148									   LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause)
2149{
2150	//
2151	// Don't do ANYTHING here, just add it to the global callback list
2152	//
2153	if (mLoadedCallbackList.empty())
2154	{
2155		// Put in list to call this->doLoadedCallbacks() periodically
2156		gTextureList.mCallbackList.insert(this);
2157		mLoadedCallbackDesiredDiscardLevel = (S8)discard_level;
2158	}
2159	else
2160	{
2161		mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ;
2162	}
2163
2164	if(mPauseLoadedCallBacks && !pause)
2165	{
2166		unpauseLoadedCallbacks(src_callback_list) ;
2167	}
2168	LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause);
2169	mLoadedCallbackList.push_back(entryp);	
2170
2171	mNeedsAux |= needs_aux;
2172	if(keep_imageraw)
2173	{
2174		mSaveRawImage = TRUE ;
2175	}
2176	if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
2177	{
2178		// We need aux data, but we've already loaded the image, and it didn't have any
2179		llwarns << "No aux data available for callback for image:" << getID() << llendl;
2180	}
2181	mLastCallBackActiveTime = sCurrentTime ;
2182}
2183
2184void LLViewerFetchedTexture::clearCallbackEntryList()
2185{
2186	if(mLoadedCallbackList.empty())
2187	{
2188		return ;
2189	}
2190
2191	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2192			iter != mLoadedCallbackList.end(); )
2193	{
2194		LLLoadedCallbackEntry *entryp = *iter;
2195			
2196		// We never finished loading the image.  Indicate failure.
2197		// Note: this allows mLoadedCallbackUserData to be cleaned up.
2198		entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData);
2199		iter = mLoadedCallbackList.erase(iter) ;
2200		delete entryp;
2201	}
2202	gTextureList.mCallbackList.erase(this);
2203		
2204	mLoadedCallbackDesiredDiscardLevel = S8_MAX ;
2205	if(needsToSaveRawImage())
2206	{
2207		destroySavedRawImage() ;
2208	}
2209
2210	return ;
2211}
2212
2213void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list)
2214{
2215	if(mLoadedCallbackList.empty() || !callback_list)
2216	{
2217		return ;
2218	}
2219
2220	S32 desired_discard = S8_MAX ;
2221	S32 desired_raw_discard = INVALID_DISCARD_LEVEL ;
2222	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2223			iter != mLoadedCallbackList.end(); )
2224	{
2225		LLLoadedCallbackEntry *entryp = *iter;
2226		if(entryp->mSourceCallbackList == callback_list)
2227		{
2228			// We never finished loading the image.  Indicate failure.
2229			// Note: this allows mLoadedCallbackUserData to be cleaned up.
2230			entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData);
2231			iter = mLoadedCallbackList.erase(iter) ;
2232			delete entryp;
2233		}
2234		else
2235		{
2236			++iter;
2237
2238			desired_discard = llmin(desired_discard, entryp->mDesiredDiscard) ;
2239			if(entryp->mNeedsImageRaw)
2240			{
2241				desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard) ;
2242			}
2243		}
2244	}
2245
2246	mLoadedCallbackDesiredDiscardLevel = desired_discard;
2247	if (mLoadedCallbackList.empty())
2248	{
2249		// If we have no callbacks, take us off of the image callback list.
2250		gTextureList.mCallbackList.erase(this);
2251		
2252		if(needsToSaveRawImage())
2253		{
2254			destroySavedRawImage() ;
2255		}
2256	}
2257	else if(needsToSaveRawImage() && mBoostLevel != LLViewerTexture::BOOST_PREVIEW)
2258	{
2259		if(desired_raw_discard != INVALID_DISCARD_LEVEL)
2260		{
2261			mDesiredSavedRawDiscardLevel = desired_raw_discard ;
2262		}
2263		else
2264		{
2265			destroySavedRawImage() ;
2266		}
2267	}
2268}
2269
2270void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list)
2271{
2272	if(!callback_list)
2273{
2274		mPauseLoadedCallBacks = FALSE ;
2275		return ;
2276	}
2277
2278	BOOL need_raw = FALSE ;
2279	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2280			iter != mLoadedCallbackList.end(); )
2281	{
2282		LLLoadedCallbackEntry *entryp = *iter++;
2283		if(entryp->mSourceCallbackList == callback_list)
2284		{
2285			entryp->mPaused = FALSE ;
2286			if(entryp->mNeedsImageRaw)
2287			{
2288				need_raw = TRUE ;
2289			}
2290		}
2291	}
2292	mPauseLoadedCallBacks = FALSE ;
2293	mLastCallBackActiveTime = sCurrentTime ;
2294	if(need_raw)
2295	{
2296		mSaveRawImage = TRUE ;
2297	}
2298}
2299
2300void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list)
2301{
2302	if(!callback_list)
2303{
2304		return ;
2305	}
2306
2307	bool paused = true ;
2308
2309	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2310			iter != mLoadedCallbackList.end(); )
2311	{
2312		LLLoadedCallbackEntry *entryp = *iter++;
2313		if(entryp->mSourceCallbackList == callback_list)
2314		{
2315			entryp->mPaused = TRUE ;
2316		}
2317		else if(!entryp->mPaused)
2318		{
2319			paused = false ;
2320		}
2321	}
2322
2323	if(paused)
2324	{
2325		mPauseLoadedCallBacks = TRUE ;//when set, loaded callback is paused.
2326		resetTextureStats();
2327		mSaveRawImage = FALSE ;
2328	}
2329}
2330
2331bool LLViewerFetchedTexture::doLoadedCallbacks()
2332{
2333	static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds
2334
2335	if (mNeedsCreateTexture)
2336	{
2337		return false;
2338	}
2339	if(mPauseLoadedCallBacks)
2340	{
2341		destroyRawImage();
2342		return false; //paused
2343	}	
2344	if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching)
2345	{
2346		clearCallbackEntryList() ; //remove all callbacks.
2347		return false ;
2348	}
2349
2350	bool res = false;
2351	
2352	if (isMissingAsset())
2353	{
2354		for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2355			iter != mLoadedCallbackList.end(); )
2356		{
2357			LLLoadedCallbackEntry *entryp = *iter++;
2358			// We never finished loading the image.  Indicate failure.
2359			// Note: this allows mLoadedCallbackUserData to be cleaned up.
2360			entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData);
2361			delete entryp;
2362		}
2363		mLoadedCallbackList.clear();
2364
2365		// Remove ourself from the global list of textures with callbacks
2366		gTextureList.mCallbackList.erase(this);
2367		return false ;
2368	}	
2369
2370	S32 gl_discard = getDiscardLevel();
2371
2372	// If we don't have a legit GL image, set it to be lower than the worst discard level
2373	if (gl_discard == -1)
2374	{
2375		gl_discard = MAX_DISCARD_LEVEL + 1;
2376	}
2377
2378	//
2379	// Determine the quality levels of textures that we can provide to callbacks
2380	// and whether we need to do decompression/readback to get it
2381	//
2382	S32 current_raw_discard = MAX_DISCARD_LEVEL + 1; // We can always do a readback to get a raw discard
2383	S32 best_raw_discard = gl_discard;	// Current GL quality level
2384	S32 current_aux_discard = MAX_DISCARD_LEVEL + 1;
2385	S32 best_aux_discard = MAX_DISCARD_LEVEL + 1;
2386
2387	if (mIsRawImageValid)
2388	{
2389		// If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels.
2390		best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel);
2391		best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw
2392		current_aux_discard = llmin(current_aux_discard, best_aux_discard);
2393	}
2394	else
2395	{
2396		// We have no data at all, we need to get it
2397		// Do this by forcing the best aux discard to be 0.
2398		best_aux_discard = 0;
2399	}
2400
2401
2402	//
2403	// See if any of the callbacks would actually run using the data that we can provide,
2404	// and also determine if we need to perform any readbacks or decodes.
2405	//
2406	bool run_gl_callbacks = false;
2407	bool run_raw_callbacks = false;
2408	bool need_readback = false;
2409
2410	for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
2411		iter != mLoadedCallbackList.end(); )
2412	{
2413		LLLoadedCallbackEntry *entryp = *iter++;
2414	
2415		if (entryp->mNeedsImageRaw)
2416		{
2417			if (mNeedsAux)
2418			{
2419				//
2420				// Need raw and auxiliary channels
2421				//
2422				if (entryp->mLastUsedDiscard > current_aux_discard)
2423				{
2424					// We have useful data, run the callbacks
2425					run_raw_callbacks = true;
2426				}
2427			}
2428			else
2429			{
2430				if (entryp->mLastUsedDiscard > current_raw_dis