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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewertexture.cpp
  3.  * @brief Object which handles a received image (and associated texture(s))
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llviewertexture.h"
  34. // Library includes
  35. #include "imageids.h"
  36. #include "llmath.h"
  37. #include "llerror.h"
  38. #include "llgl.h"
  39. #include "llglheaders.h"
  40. #include "llhost.h"
  41. #include "llimage.h"
  42. #include "llimagebmp.h"
  43. #include "llimagej2c.h"
  44. #include "llimagetga.h"
  45. #include "llmemtype.h"
  46. #include "llstl.h"
  47. #include "llvfile.h"
  48. #include "llvfs.h"
  49. #include "message.h"
  50. #include "lltimer.h"
  51. // viewer includes
  52. #include "llimagegl.h"
  53. #include "lldrawpool.h"
  54. #include "lltexturefetch.h"
  55. #include "llviewertexturelist.h"
  56. #include "llviewercontrol.h"
  57. #include "pipeline.h"
  58. #include "llappviewer.h"
  59. #include "llface.h"
  60. #include "llviewercamera.h"
  61. #include "lltextureatlas.h"
  62. #include "lltextureatlasmanager.h"
  63. #include "lltextureentry.h"
  64. #include "llmediaentry.h"
  65. #include "llvovolume.h"
  66. #include "llviewermedia.h"
  67. ///////////////////////////////////////////////////////////////////////////////
  68. // statics
  69. LLPointer<LLViewerTexture>        LLViewerTexture::sNullImagep = NULL;
  70. LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
  71. LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
  72. LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
  73. LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
  74. LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
  75. LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
  76. S32 LLViewerTexture::sImageCount = 0;
  77. S32 LLViewerTexture::sRawCount = 0;
  78. S32 LLViewerTexture::sAuxCount = 0;
  79. LLTimer LLViewerTexture::sEvaluationTimer;
  80. F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
  81. F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
  82. S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0;
  83. S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0;
  84. S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
  85. S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
  86. S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
  87. S8  LLViewerTexture::sCameraMovingDiscardBias = 0 ;
  88. S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
  89. const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
  90. const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ;
  91. const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ;
  92. S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256.
  93. S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
  94. BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
  95. F32 LLViewerTexture::sCurrentTime = 0.0f ;
  96. BOOL LLViewerTexture::sUseTextureAtlas        = FALSE ;
  97. const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
  98. const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
  99. const F64 log_2 = log(2.0);
  100. //----------------------------------------------------------------------------------------------
  101. //namespace: LLViewerTextureAccess
  102. //----------------------------------------------------------------------------------------------
  103. LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb,
  104.   S32 discard_level,
  105.   BOOL need_imageraw, // Needs image raw for the callback
  106.   void* userdata ) 
  107. : mCallback(cb),
  108.   mLastUsedDiscard(MAX_DISCARD_LEVEL+1),
  109.   mDesiredDiscard(discard_level),
  110.   mNeedsImageRaw(need_imageraw),
  111.   mUserData(userdata)
  112. {
  113. }
  114. LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image)
  115. {
  116. return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ;
  117. }
  118.  
  119. LLViewerTexture*  LLViewerTextureManager::findTexture(const LLUUID& id) 
  120. {
  121. LLViewerTexture* tex ;
  122. //search fetched texture list
  123. tex = gTextureList.findImage(id) ;
  124. //search media texture list
  125. if(!tex)
  126. {
  127. tex = LLViewerTextureManager::findMediaTexture(id) ;
  128. }
  129. return tex ;
  130. }
  131. LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
  132. {
  133. return LLViewerMediaTexture::findMediaTexture(media_id) ;
  134. }
  135. LLViewerMediaTexture*  LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) 
  136. {
  137. LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ;
  138. if(!tex)
  139. {
  140. tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ;
  141. }
  142. tex->initVirtualSize() ;
  143. return tex ;
  144. }
  145. LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
  146. {
  147. if(!tex)
  148. {
  149. return NULL ;
  150. }
  151. S8 type = tex->getType() ;
  152. if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
  153. {
  154. return static_cast<LLViewerFetchedTexture*>(tex) ;
  155. }
  156. if(report_error)
  157. {
  158. llerrs << "not a fetched texture type: " << type << llendl ;
  159. }
  160. return NULL ;
  161. }
  162. LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipmaps, BOOL generate_gl_tex)
  163. {
  164. LLPointer<LLViewerTexture> tex = new LLViewerTexture(usemipmaps) ;
  165. if(generate_gl_tex)
  166. {
  167. tex->generateGLTexture() ;
  168. tex->setCategory(LLViewerTexture::LOCAL) ;
  169. }
  170. return tex ;
  171. }
  172. LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex) 
  173. {
  174. LLPointer<LLViewerTexture> tex = new LLViewerTexture(id, usemipmaps) ;
  175. if(generate_gl_tex)
  176. {
  177. tex->generateGLTexture() ;
  178. tex->setCategory(LLViewerTexture::LOCAL) ;
  179. }
  180. return tex ;
  181. }
  182. LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) 
  183. {
  184. LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ;
  185. tex->setCategory(LLViewerTexture::LOCAL) ;
  186. return tex ;
  187. }
  188. LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) 
  189. {
  190. LLPointer<LLViewerTexture> tex = new LLViewerTexture(width, height, components, usemipmaps) ;
  191. if(generate_gl_tex)
  192. {
  193. tex->generateGLTexture() ;
  194. tex->setCategory(LLViewerTexture::LOCAL) ;
  195. }
  196. return tex ;
  197. }
  198. LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
  199.                                                const LLUUID &image_id,        
  200.    BOOL usemipmaps,
  201.    LLViewerTexture::EBoostLevel boost_priority,
  202.    S8 texture_type,
  203.    LLGLint internal_format,
  204.    LLGLenum primary_format,
  205.    LLHost request_from_host)
  206. {
  207. return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
  208. }
  209. LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile(
  210.                                                const std::string& filename,    
  211.    BOOL usemipmaps,
  212.    LLViewerTexture::EBoostLevel boost_priority,
  213.    S8 texture_type,
  214.    LLGLint internal_format,
  215.    LLGLenum primary_format, 
  216.    const LLUUID& force_id)
  217. {
  218. return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
  219. }
  220. //static 
  221. LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url,  
  222.  BOOL usemipmaps,
  223.  LLViewerTexture::EBoostLevel boost_priority,
  224.  S8 texture_type,
  225.  LLGLint internal_format,
  226.  LLGLenum primary_format,
  227.  const LLUUID& force_id
  228.  )
  229. {
  230. return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
  231. }
  232. LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) 
  233. {
  234. return gTextureList.getImageFromHost(image_id, host) ;
  235. }
  236. void LLViewerTextureManager::init()
  237. {
  238. LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
  239. raw->clear(0x77, 0x77, 0x77, 0xFF);
  240. LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
  241. #if 1
  242. LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
  243. LLViewerFetchedTexture::sDefaultImagep = imagep;
  244. const S32 dim = 128;
  245. LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
  246. U8* data = image_raw->getData();
  247. for (S32 i = 0; i<dim; i++)
  248. {
  249. for (S32 j = 0; j<dim; j++)
  250. {
  251. #if 0
  252. const S32 border = 2;
  253. if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
  254. {
  255. *data++ = 0xff;
  256. *data++ = 0xff;
  257. *data++ = 0xff;
  258. }
  259. else
  260. #endif
  261. {
  262. *data++ = 0x7f;
  263. *data++ = 0x7f;
  264. *data++ = 0x7f;
  265. }
  266. }
  267. }
  268. imagep->createGLTexture(0, image_raw);
  269. image_raw = NULL;
  270. #else
  271.   LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
  272. #endif
  273. LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
  274. LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ;
  275.   LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
  276. LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
  277. LLViewerTexture::initClass() ;
  278. if(LLFastTimer::sMetricLog)
  279. {
  280. LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
  281. }
  282. }
  283. void LLViewerTextureManager::cleanup()
  284. {
  285. stop_glerror();
  286. LLImageGL::sDefaultGLTexture = NULL ;
  287. LLViewerTexture::sNullImagep = NULL;
  288. LLViewerFetchedTexture::sDefaultImagep = NULL;
  289. LLViewerFetchedTexture::sSmokeImagep = NULL;
  290. LLViewerFetchedTexture::sMissingAssetImagep = NULL;
  291. LLViewerFetchedTexture::sWhiteImagep = NULL;
  292. LLViewerMediaTexture::cleanup() ;
  293. LLViewerTexture::cleanupClass() ;
  294. }
  295. //----------------------------------------------------------------------------------------------
  296. //----------------------------------------------------------------------------------------------
  297. //start of LLViewerTexture
  298. //----------------------------------------------------------------------------------------------
  299. // static
  300. void LLViewerTexture::initClass()
  301. {
  302. LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
  303. if(gAuditTexture)
  304. {
  305. LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ;
  306. }
  307. }
  308. // static
  309. void LLViewerTexture::cleanupClass()
  310. {
  311. }
  312. // static
  313. S32 LLViewerTexture::getTotalNumOfCategories() 
  314. {
  315. return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ;
  316. }
  317. // static
  318. //index starts from zero.
  319. S32 LLViewerTexture::getIndexFromCategory(S32 category) 
  320. {
  321. return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ;
  322. }
  323. //static 
  324. S32 LLViewerTexture::getCategoryFromIndex(S32 index)
  325. {
  326. return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ;
  327. }
  328. // tuning params
  329. const F32 discard_bias_delta = .05f;
  330. const F32 discard_delta_time = 0.5f;
  331. const S32 min_non_tex_system_mem = (128<<20); // 128 MB
  332. // non-const (used externally
  333. F32 texmem_lower_bound_scale = 0.85f;
  334. F32 texmem_middle_bound_scale = 0.925f;
  335. //static
  336. void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
  337. {
  338. sCurrentTime = gFrameTimeSeconds ;
  339. if(LLViewerTextureManager::sTesterp)
  340. {
  341. LLViewerTextureManager::sTesterp->update() ;
  342. }
  343. LLViewerMediaTexture::updateClass() ;
  344. sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
  345. sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
  346. sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB
  347. sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB
  348. sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small.
  349. if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes ||
  350. BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes)
  351. {
  352. //when texture memory overflows, lower down the threashold to release the textures more aggressively.
  353. sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB
  354. // If we are using more texture memory than we should,
  355. // scale up the desired discard level
  356. if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
  357. {
  358. sDesiredDiscardBias += discard_bias_delta;
  359. sEvaluationTimer.reset();
  360. }
  361. }
  362. else if (sDesiredDiscardBias > 0.0f &&
  363.  BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
  364.  BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
  365. {  
  366. // If we are using less texture memory than we should,
  367. // scale down the desired discard level
  368. if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
  369. {
  370. sDesiredDiscardBias -= discard_bias_delta;
  371. sEvaluationTimer.reset();
  372. }
  373. }
  374. sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
  375. LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
  376. F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
  377. F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
  378. sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
  379. LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
  380. (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
  381. }
  382. //end of static functions
  383. //-------------------------------------------------------------------------------------------
  384. const U32 LLViewerTexture::sCurrentFileVersion = 1;
  385. LLViewerTexture::LLViewerTexture(BOOL usemipmaps)
  386. {
  387. init(true);
  388. mUseMipMaps = usemipmaps ;
  389. mID.generate();
  390. sImageCount++;
  391. }
  392. LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps)
  393. : mID(id)
  394. {
  395. init(true);
  396. mUseMipMaps = usemipmaps ;
  397. sImageCount++;
  398. }
  399. LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) 
  400. {
  401. init(true);
  402. mFullWidth = width ;
  403. mFullHeight = height ;
  404. mUseMipMaps = usemipmaps ;
  405. mComponents = components ;
  406. mID.generate();
  407. sImageCount++;
  408. }
  409. LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps)
  410. {
  411. init(true);
  412. mUseMipMaps = usemipmaps ;
  413. mGLTexturep = new LLImageGL(raw, usemipmaps) ;
  414. // Create an empty image of the specified size and width
  415. mID.generate();
  416. sImageCount++;
  417. }
  418. LLViewerTexture::~LLViewerTexture()
  419. {
  420. sImageCount--;
  421. }
  422. void LLViewerTexture::init(bool firstinit)
  423. {
  424. mBoostLevel = LLViewerTexture::BOOST_NONE;
  425. mFullWidth = 0;
  426. mFullHeight = 0;
  427. mUseMipMaps = FALSE ;
  428. mComponents = 0 ;
  429. mTextureState = NO_DELETE ;
  430. mDontDiscard = FALSE;
  431. mMaxVirtualSize = 0.f;
  432. mNeedsGLTexture = FALSE ;
  433. mNeedsResetMaxVirtualSize = FALSE ;
  434. mAdditionalDecodePriority = 0.f ;
  435. mParcelMedia = NULL ;
  436. mNumFaces = 0 ;
  437. mNumVolumes = 0;
  438. mFaceList.clear() ;
  439. mVolumeList.clear();
  440. }
  441. //virtual 
  442. S8 LLViewerTexture::getType() const
  443. {
  444. return LLViewerTexture::LOCAL_TEXTURE ;
  445. }
  446. void LLViewerTexture::cleanup()
  447. {
  448. mFaceList.clear() ;
  449. mVolumeList.clear();
  450. if(mGLTexturep)
  451. {
  452. mGLTexturep->cleanup();
  453. }
  454. }
  455. // virtual
  456. void LLViewerTexture::dump()
  457. {
  458. if(mGLTexturep)
  459. {
  460. mGLTexturep->dump();
  461. }
  462. llinfos << "LLViewerTexture"
  463. << " mID " << mID
  464. << llendl;
  465. }
  466. void LLViewerTexture::setBoostLevel(S32 level)
  467. {
  468. if(mBoostLevel != level)
  469. {
  470. mBoostLevel = level ;
  471. if(mBoostLevel != LLViewerTexture::BOOST_NONE)
  472. {
  473. setNoDelete() ;
  474. }
  475. if(gAuditTexture)
  476. {
  477. setCategory(mBoostLevel);
  478. }
  479. }
  480. }
  481. bool LLViewerTexture::bindDefaultImage(S32 stage) 
  482. {
  483. if (stage < 0) return false;
  484. bool res = true;
  485. if (LLViewerFetchedTexture::sDefaultImagep.notNull() && (this != LLViewerFetchedTexture::sDefaultImagep.get()))
  486. {
  487. // use default if we've got it
  488. res = gGL.getTexUnit(stage)->bind(LLViewerFetchedTexture::sDefaultImagep);
  489. }
  490. if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep))
  491. {
  492. res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ;
  493. }
  494. if (!res)
  495. {
  496. llwarns << "LLViewerTexture::bindDefaultImage failed." << llendl;
  497. }
  498. stop_glerror();
  499. //check if there is cached raw image and switch to it if possible
  500. switchToCachedImage() ;
  501. if(LLViewerTextureManager::sTesterp)
  502. {
  503. LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ;
  504. }
  505. return res;
  506. }
  507. //virtual 
  508. BOOL LLViewerTexture::isMissingAsset()const
  509. return FALSE; 
  510. }
  511. //virtual 
  512. void LLViewerTexture::forceImmediateUpdate() 
  513. {
  514. }
  515. void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const 
  516. {
  517. if(needs_gltexture)
  518. {
  519. mNeedsGLTexture = TRUE ;
  520. }
  521. if(mNeedsResetMaxVirtualSize)
  522. {
  523. //flag to reset the values because the old values are used.
  524. mNeedsResetMaxVirtualSize = FALSE ;
  525. mMaxVirtualSize = virtual_size;
  526. mAdditionalDecodePriority = 0.f ;
  527. mNeedsGLTexture = needs_gltexture ;
  528. }
  529. else if (virtual_size > mMaxVirtualSize)
  530. {
  531. mMaxVirtualSize = virtual_size;
  532. }
  533. }
  534. void LLViewerTexture::resetTextureStats()
  535. {
  536. mMaxVirtualSize = 0.0f;
  537. mAdditionalDecodePriority = 0.f ;
  538. mNeedsResetMaxVirtualSize = FALSE ;
  539. }
  540. //virtual 
  541. F32 LLViewerTexture::getMaxVirtualSize()
  542. {
  543. return mMaxVirtualSize ;
  544. }
  545. //virtual 
  546. void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
  547. {
  548. //nothing here.
  549. }
  550. //virtual
  551. void LLViewerTexture::addFace(LLFace* facep) 
  552. {
  553. if(mNumFaces >= mFaceList.size())
  554. {
  555. mFaceList.resize(2 * mNumFaces + 1) ;
  556. }
  557. mFaceList[mNumFaces] = facep ;
  558. facep->setIndexInTex(mNumFaces) ;
  559. mNumFaces++ ;
  560. mLastFaceListUpdateTimer.reset() ;
  561. }
  562. //virtual
  563. void LLViewerTexture::removeFace(LLFace* facep) 
  564. {
  565. if(mNumFaces > 1)
  566. {
  567. S32 index = facep->getIndexInTex() ; 
  568. mFaceList[index] = mFaceList[--mNumFaces] ;
  569. mFaceList[index]->setIndexInTex(index) ;
  570. }
  571. else 
  572. {
  573. mFaceList.clear() ;
  574. mNumFaces = 0 ;
  575. }
  576. mLastFaceListUpdateTimer.reset() ;
  577. }
  578. S32 LLViewerTexture::getNumFaces() const
  579. {
  580. return mNumFaces ;
  581. }
  582. //virtual
  583. void LLViewerTexture::addVolume(LLVOVolume* volumep) 
  584. {
  585. if( mNumVolumes >= mVolumeList.size())
  586. {
  587. mVolumeList.resize(2 * mNumVolumes + 1) ;
  588. }
  589. mVolumeList[mNumVolumes] = volumep ;
  590. volumep->setIndexInTex(mNumVolumes) ;
  591. mNumVolumes++ ;
  592. mLastVolumeListUpdateTimer.reset() ;
  593. }
  594. //virtual
  595. void LLViewerTexture::removeVolume(LLVOVolume* volumep) 
  596. {
  597. if(mNumVolumes > 1)
  598. {
  599. S32 index = volumep->getIndexInTex() ; 
  600. mVolumeList[index] = mVolumeList[--mNumVolumes] ;
  601. mVolumeList[index]->setIndexInTex(index) ;
  602. }
  603. else 
  604. {
  605. mVolumeList.clear() ;
  606. mNumVolumes = 0 ;
  607. }
  608. mLastVolumeListUpdateTimer.reset() ;
  609. }
  610. S32 LLViewerTexture::getNumVolumes() const
  611. {
  612. return mNumVolumes ;
  613. }
  614. void LLViewerTexture::reorganizeFaceList()
  615. {
  616. static const F32 MAX_WAIT_TIME = 20.f; // seconds
  617. static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
  618. if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size())
  619. {
  620. return ;
  621. }
  622. if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
  623. {
  624. return ;
  625. }
  626. mLastFaceListUpdateTimer.reset() ;
  627. mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end());
  628. }
  629. void LLViewerTexture::reorganizeVolumeList()
  630. {
  631. static const F32 MAX_WAIT_TIME = 20.f; // seconds
  632. static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
  633. if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size())
  634. {
  635. return ;
  636. }
  637. if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
  638. {
  639. return ;
  640. }
  641. mLastVolumeListUpdateTimer.reset() ;
  642. mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end());
  643. }
  644. //virtual
  645. void LLViewerTexture::switchToCachedImage()
  646. {
  647. //nothing here.
  648. }
  649. void LLViewerTexture::forceActive()
  650. {
  651. mTextureState = ACTIVE ; 
  652. }
  653. void LLViewerTexture::setActive() 
  654. if(mTextureState != NO_DELETE)
  655. {
  656. mTextureState = ACTIVE ; 
  657. }
  658. }
  659. //set the texture to stay in memory
  660. void LLViewerTexture::setNoDelete() 
  661. mTextureState = NO_DELETE ;
  662. }
  663. void LLViewerTexture::generateGLTexture() 
  664. {
  665. if(mGLTexturep.isNull())
  666. {
  667. mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
  668. }
  669. }
  670. LLImageGL* LLViewerTexture::getGLTexture() const
  671. {
  672. llassert(mGLTexturep.notNull()) ;
  673. return mGLTexturep ;
  674. }
  675. BOOL LLViewerTexture::createGLTexture() 
  676. {
  677. if(mGLTexturep.isNull())
  678. {
  679. generateGLTexture() ;
  680. }
  681. return mGLTexturep->createGLTexture() ;
  682. }
  683. BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category)
  684. {
  685. llassert(mGLTexturep.notNull()) ;
  686. BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ;
  687. if(ret)
  688. {
  689. mFullWidth = mGLTexturep->getCurrentWidth() ;
  690. mFullHeight = mGLTexturep->getCurrentHeight() ; 
  691. mComponents = mGLTexturep->getComponents() ;
  692. }
  693. return ret ;
  694. }
  695. void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
  696. {
  697. llassert(mGLTexturep.notNull()) ;
  698. mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
  699. }
  700. void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
  701. {
  702. llassert(mGLTexturep.notNull()) ;
  703. mGLTexturep->setAddressMode(mode) ;
  704. }
  705. void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
  706. {
  707. llassert(mGLTexturep.notNull()) ;
  708. mGLTexturep->setFilteringOption(option) ;
  709. }
  710. //virtual
  711. S32 LLViewerTexture::getWidth(S32 discard_level) const
  712. {
  713. llassert(mGLTexturep.notNull()) ;
  714. return mGLTexturep->getWidth(discard_level) ;
  715. }
  716. //virtual
  717. S32 LLViewerTexture::getHeight(S32 discard_level) const
  718. {
  719. llassert(mGLTexturep.notNull()) ;
  720. return mGLTexturep->getHeight(discard_level) ;
  721. }
  722. S32 LLViewerTexture::getMaxDiscardLevel() const
  723. {
  724. llassert(mGLTexturep.notNull()) ;
  725. return mGLTexturep->getMaxDiscardLevel() ;
  726. }
  727. S32 LLViewerTexture::getDiscardLevel() const
  728. {
  729. llassert(mGLTexturep.notNull()) ;
  730. return mGLTexturep->getDiscardLevel() ;
  731. }
  732. S8  LLViewerTexture::getComponents() const 
  733. llassert(mGLTexturep.notNull()) ;
  734. return mGLTexturep->getComponents() ;
  735. }
  736. LLGLuint LLViewerTexture::getTexName() const 
  737. llassert(mGLTexturep.notNull()) ;
  738. return mGLTexturep->getTexName() ; 
  739. }
  740. BOOL LLViewerTexture::hasGLTexture() const 
  741. {
  742. if(mGLTexturep.notNull())
  743. {
  744. return mGLTexturep->getHasGLTexture() ;
  745. }
  746. return FALSE ;
  747. }
  748. BOOL LLViewerTexture::getBoundRecently() const
  749. {
  750. if(mGLTexturep.notNull())
  751. {
  752. return mGLTexturep->getBoundRecently() ;
  753. }
  754. return FALSE ;
  755. }
  756. LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const
  757. {
  758. llassert(mGLTexturep.notNull()) ;
  759. return mGLTexturep->getTarget() ;
  760. }
  761. BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
  762. {
  763. llassert(mGLTexturep.notNull()) ;
  764. return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ;
  765. }
  766. BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
  767. {
  768. llassert(mGLTexturep.notNull()) ;
  769. return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ;
  770. }
  771. void LLViewerTexture::setGLTextureCreated (bool initialized)
  772. {
  773. llassert(mGLTexturep.notNull()) ;
  774. mGLTexturep->setGLTextureCreated (initialized) ;
  775. }
  776. void  LLViewerTexture::setCategory(S32 category) 
  777. {
  778. llassert(mGLTexturep.notNull()) ;
  779. mGLTexturep->setCategory(category) ;
  780. }
  781. LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const
  782. {
  783. llassert(mGLTexturep.notNull()) ;
  784. return mGLTexturep->getAddressMode() ;
  785. }
  786. S32 LLViewerTexture::getTextureMemory() const
  787. {
  788. llassert(mGLTexturep.notNull()) ;
  789. return mGLTexturep->mTextureMemory ;
  790. }
  791. LLGLenum LLViewerTexture::getPrimaryFormat() const
  792. {
  793. llassert(mGLTexturep.notNull()) ;
  794. return mGLTexturep->getPrimaryFormat() ;
  795. }
  796. BOOL LLViewerTexture::getIsAlphaMask() const
  797. {
  798. llassert(mGLTexturep.notNull()) ;
  799. return mGLTexturep->getIsAlphaMask() ;
  800. }
  801. BOOL LLViewerTexture::getMask(const LLVector2 &tc)
  802. {
  803. llassert(mGLTexturep.notNull()) ;
  804. return mGLTexturep->getMask(tc) ;
  805. }
  806. F32 LLViewerTexture::getTimePassedSinceLastBound()
  807. {
  808. llassert(mGLTexturep.notNull()) ;
  809. return mGLTexturep->getTimePassedSinceLastBound() ;
  810. }
  811. BOOL LLViewerTexture::getMissed() const 
  812. {
  813. llassert(mGLTexturep.notNull()) ;
  814. return mGLTexturep->getMissed() ;
  815. }
  816. BOOL LLViewerTexture::isJustBound() const
  817. {
  818. llassert(mGLTexturep.notNull()) ;
  819. return mGLTexturep->isJustBound() ;
  820. }
  821. void LLViewerTexture::forceUpdateBindStats(void) const
  822. {
  823. llassert(mGLTexturep.notNull()) ;
  824. return mGLTexturep->forceUpdateBindStats() ;
  825. }
  826. U32 LLViewerTexture::getTexelsInAtlas() const
  827. {
  828. llassert(mGLTexturep.notNull()) ;
  829. return mGLTexturep->getTexelsInAtlas() ;
  830. }
  831. U32 LLViewerTexture::getTexelsInGLTexture() const
  832. {
  833. llassert(mGLTexturep.notNull()) ;
  834. return mGLTexturep->getTexelsInGLTexture() ;
  835. }
  836. BOOL LLViewerTexture::isGLTextureCreated() const
  837. {
  838. llassert(mGLTexturep.notNull()) ;
  839. return mGLTexturep->isGLTextureCreated() ;
  840. }
  841. S32  LLViewerTexture::getDiscardLevelInAtlas() const
  842. {
  843. llassert(mGLTexturep.notNull()) ;
  844. return mGLTexturep->getDiscardLevelInAtlas() ;
  845. }
  846. void LLViewerTexture::destroyGLTexture() 
  847. {
  848. if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
  849. {
  850. mGLTexturep->destroyGLTexture() ;
  851. mTextureState = DELETED ;
  852. }
  853. }
  854. BOOL LLViewerTexture::isLargeImage()
  855. {
  856. return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ;
  857. }
  858. //virtual 
  859. void LLViewerTexture::updateBindStatsForTester()
  860. {
  861. if(LLViewerTextureManager::sTesterp)
  862. {
  863. LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
  864. }
  865. }
  866. //----------------------------------------------------------------------------------------------
  867. //end of LLViewerTexture
  868. //----------------------------------------------------------------------------------------------
  869. //----------------------------------------------------------------------------------------------
  870. //start of LLViewerFetchedTexture
  871. //----------------------------------------------------------------------------------------------
  872. LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
  873. : LLViewerTexture(id, usemipmaps),
  874. mTargetHost(host)
  875. {
  876. init(TRUE) ;
  877. generateGLTexture() ;
  878. }
  879. LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps)
  880. : LLViewerTexture(raw, usemipmaps)
  881. {
  882. init(TRUE) ;
  883. }
  884. LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps)
  885. : LLViewerTexture(id, usemipmaps),
  886. mUrl(url)
  887. {
  888. init(TRUE) ;
  889. generateGLTexture() ;
  890. }
  891. void LLViewerFetchedTexture::init(bool firstinit)
  892. {
  893. mOrigWidth = 0;
  894. mOrigHeight = 0;
  895. mNeedsAux = FALSE;
  896. mRequestedDiscardLevel = -1;
  897. mRequestedDownloadPriority = 0.f;
  898. mFullyLoaded = FALSE;
  899. mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
  900. mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
  901. mDecodingAux = FALSE;
  902. mKnownDrawWidth = 0;
  903. mKnownDrawHeight = 0;
  904. mKnownDrawSizeChanged = FALSE ;
  905. if (firstinit)
  906. {
  907. mDecodePriority = 0.f;
  908. mInImageList = 0;
  909. }
  910. // Only set mIsMissingAsset true when we know for certain that the database
  911. // does not contain this image.
  912. mIsMissingAsset = FALSE;
  913. mLoadedCallbackDesiredDiscardLevel = 0;
  914. mNeedsCreateTexture = FALSE;
  915. mIsRawImageValid = FALSE;
  916. mRawDiscardLevel = INVALID_DISCARD_LEVEL;
  917. mMinDiscardLevel = 0;
  918. mHasFetcher = FALSE;
  919. mIsFetching = FALSE;
  920. mFetchState = 0;
  921. mFetchPriority = 0;
  922. mDownloadProgress = 0.f;
  923. mFetchDeltaTime = 999999.f;
  924. mRequestDeltaTime = 0.f;
  925. mForSculpt = FALSE ;
  926. mIsFetched = FALSE ;
  927. mCachedRawImage = NULL ;
  928. mCachedRawDiscardLevel = -1 ;
  929. mCachedRawImageReady = FALSE ;
  930. mSavedRawImage = NULL ;
  931. mForceToSaveRawImage  = FALSE ;
  932. mSavedRawDiscardLevel = -1 ;
  933. mDesiredSavedRawDiscardLevel = -1 ;
  934. mLastReferencedSavedRawImageTime = 0.0f ;
  935. }
  936. LLViewerFetchedTexture::~LLViewerFetchedTexture()
  937. {
  938. //*NOTE getTextureFetch can return NULL when Viewer is shutting down.
  939. // This is due to LLWearableList is singleton and is destroyed after 
  940. // LLAppViewer::cleanup() was called. (see ticket EXT-177)
  941. if (mHasFetcher && LLAppViewer::getTextureFetch())
  942. {
  943. LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
  944. }
  945. cleanup();
  946. }
  947. //virtual 
  948. S8 LLViewerFetchedTexture::getType() const
  949. {
  950. return LLViewerTexture::FETCHED_TEXTURE ;
  951. }
  952. void LLViewerFetchedTexture::cleanup()
  953. {
  954. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  955. iter != mLoadedCallbackList.end(); )
  956. {
  957. LLLoadedCallbackEntry *entryp = *iter++;
  958. // We never finished loading the image.  Indicate failure.
  959. // Note: this allows mLoadedCallbackUserData to be cleaned up.
  960. entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData );
  961. delete entryp;
  962. }
  963. mLoadedCallbackList.clear();
  964. mNeedsAux = FALSE;
  965. // Clean up image data
  966. destroyRawImage();
  967. mCachedRawImage = NULL ;
  968. mCachedRawDiscardLevel = -1 ;
  969. mCachedRawImageReady = FALSE ;
  970. mSavedRawImage = NULL ;
  971. }
  972. void LLViewerFetchedTexture::setForSculpt()
  973. {
  974. mForSculpt = TRUE ;
  975. if(isForSculptOnly() && !getBoundRecently())
  976. {
  977. destroyGLTexture() ; //sculpt image does not need gl texture.
  978. }
  979. checkCachedRawSculptImage() ;
  980. }
  981. BOOL LLViewerFetchedTexture::isForSculptOnly() const
  982. {
  983. return mForSculpt && !mNeedsGLTexture ;
  984. }
  985. BOOL LLViewerFetchedTexture::isDeleted()  
  986. return mTextureState == DELETED ; 
  987. }
  988. BOOL LLViewerFetchedTexture::isInactive()  
  989. return mTextureState == INACTIVE ; 
  990. }
  991. BOOL LLViewerFetchedTexture::isDeletionCandidate()  
  992. return mTextureState == DELETION_CANDIDATE ; 
  993. }
  994. void LLViewerFetchedTexture::setDeletionCandidate()  
  995. if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE))
  996. {
  997. mTextureState = DELETION_CANDIDATE ;
  998. }
  999. }
  1000. //set the texture inactive
  1001. void LLViewerFetchedTexture::setInactive()
  1002. {
  1003. if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently())
  1004. {
  1005. mTextureState = INACTIVE ; 
  1006. }
  1007. }
  1008. BOOL LLViewerFetchedTexture::isFullyLoaded() const
  1009. {
  1010. // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic
  1011. // to check if the texture is there and completely downloaded
  1012. return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher;
  1013. }
  1014. // virtual
  1015. void LLViewerFetchedTexture::dump()
  1016. {
  1017. LLViewerTexture::dump();
  1018. llinfos << "Dump : " << mID 
  1019. << ", mIsMissingAsset = " << (S32)mIsMissingAsset
  1020. << ", mFullWidth = " << (S32)mFullWidth
  1021. << ", mFullHeight = " << (S32)mFullHeight
  1022. << ", mOrigWidth = " << (S32)mOrigWidth
  1023. << ", mOrigHeight = " << (S32)mOrigHeight
  1024. << llendl;
  1025. llinfos << "     : " 
  1026. << " mFullyLoaded = " << (S32)mFullyLoaded
  1027. << ", mFetchState = " << (S32)mFetchState
  1028. << ", mFetchPriority = " << (S32)mFetchPriority
  1029. << ", mDownloadProgress = " << (F32)mDownloadProgress
  1030. << llendl;
  1031. llinfos << "     : " 
  1032. << " mHasFetcher = " << (S32)mHasFetcher
  1033. << ", mIsFetching = " << (S32)mIsFetching
  1034. << ", mIsFetched = " << (S32)mIsFetched
  1035. << ", mBoostLevel = " << (S32)mBoostLevel
  1036. << llendl;
  1037. }
  1038. ///////////////////////////////////////////////////////////////////////////////
  1039. // ONLY called from LLViewerFetchedTextureList
  1040. void LLViewerFetchedTexture::destroyTexture() 
  1041. {
  1042. if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
  1043. {
  1044. return ;
  1045. }
  1046. if (mNeedsCreateTexture)//return if in the process of generating a new texture.
  1047. {
  1048. return ;
  1049. }
  1050. destroyGLTexture() ;
  1051. mFullyLoaded = FALSE ;
  1052. }
  1053. //
  1054. //do not change the discard level of the loaded texture image.
  1055. BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel()
  1056. {
  1057. if (!mLoadedCallbackList.empty())
  1058. {
  1059. return TRUE ;
  1060. }
  1061. return FALSE ;
  1062. }
  1063. void LLViewerFetchedTexture::addToCreateTexture()
  1064. {
  1065. if(isForSculptOnly())
  1066. {
  1067. //just update some variables, not to create a real GL texture.
  1068. createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ;
  1069. mNeedsCreateTexture = FALSE ;
  1070. destroyRawImage();
  1071. }
  1072. else
  1073. {
  1074. #if 1
  1075. //
  1076. //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up,
  1077. //so do not scale down the over qualified image.
  1078. //Note: scaling down image is expensensive. Do it only when very necessary.
  1079. //
  1080. if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !keepReuestedDiscardLevel())
  1081. {
  1082. S32 w = mFullWidth >> mRawDiscardLevel;
  1083. S32 h = mFullHeight >> mRawDiscardLevel;
  1084. //if big image, do not load extra data
  1085. //scale it down to size >= LLViewerTexture::sMinLargeImageSize
  1086. if(w * h > LLViewerTexture::sMinLargeImageSize)
  1087. {
  1088. S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ;
  1089. if(d_level > 0)
  1090. {
  1091. S32 i = 0 ;
  1092. while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize))
  1093. {
  1094. i++;
  1095. d_level--;
  1096. }
  1097. if(i > 0)
  1098. {
  1099. mRawDiscardLevel += i ;
  1100. if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0)
  1101. {
  1102. mNeedsCreateTexture = FALSE ;
  1103. destroyRawImage();
  1104. return ;
  1105. }
  1106. mRawImage->scale(w >> i, h >> i) ;
  1107. }
  1108. }
  1109. }
  1110. }
  1111. #endif
  1112. mNeedsCreateTexture = TRUE;
  1113. gTextureList.mCreateTextureList.insert(this);
  1114. }
  1115. return ;
  1116. }
  1117. // ONLY called from LLViewerTextureList
  1118. BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
  1119. {
  1120. if (!mNeedsCreateTexture)
  1121. {
  1122. destroyRawImage();
  1123. return FALSE;
  1124. }
  1125. mNeedsCreateTexture = FALSE;
  1126. if (mRawImage.isNull())
  1127. {
  1128. llerrs << "LLViewerTexture trying to create texture with no Raw Image" << llendl;
  1129. }
  1130. //  llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ",
  1131. //  mRawDiscardLevel, 
  1132. //  mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize())
  1133. //  << mID.getString() << llendl;
  1134. BOOL res = TRUE;
  1135. if (!gNoRender)
  1136. {
  1137. // store original size only for locally-sourced images
  1138. if (mUrl.compare(0, 7, "file://") == 0)
  1139. {
  1140. mOrigWidth = mRawImage->getWidth();
  1141. mOrigHeight = mRawImage->getHeight();
  1142. // leave black border, do not scale image content
  1143. mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE);
  1144. mFullWidth = mRawImage->getWidth();
  1145. mFullHeight = mRawImage->getHeight();
  1146. }
  1147. else
  1148. {
  1149. mOrigWidth = mFullWidth;
  1150. mOrigHeight = mFullHeight;
  1151. }
  1152. bool size_okay = true;
  1153. U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel;
  1154. U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel;
  1155. if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
  1156. {
  1157. llinfos << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << llendl;
  1158. size_okay = false;
  1159. }
  1160. if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight()))
  1161. {
  1162. // A non power-of-two image was uploaded (through a non standard client)
  1163. llinfos << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << llendl;
  1164. size_okay = false;
  1165. }
  1166. if( !size_okay )
  1167. {
  1168. // An inappropriately-sized image was uploaded (through a non standard client)
  1169. // We treat these images as missing assets which causes them to
  1170. // be renderd as 'missing image' and to stop requesting data
  1171. setIsMissingAsset();
  1172. destroyRawImage();
  1173. return FALSE;
  1174. }
  1175. if(!(res = insertToAtlas()))
  1176. {
  1177. res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
  1178. resetFaceAtlas() ;
  1179. }
  1180. setActive() ;
  1181. }
  1182. //
  1183. // Iterate through the list of image loading callbacks to see
  1184. // what sort of data they need.
  1185. //
  1186. // *TODO: Fix image callback code
  1187. BOOL imageraw_callbacks = FALSE;
  1188. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  1189. iter != mLoadedCallbackList.end(); )
  1190. {
  1191. LLLoadedCallbackEntry *entryp = *iter++;
  1192. if (entryp->mNeedsImageRaw)
  1193. {
  1194. imageraw_callbacks = TRUE;
  1195. break;
  1196. }
  1197. }
  1198. if (!imageraw_callbacks)
  1199. {
  1200. mNeedsAux = FALSE;
  1201. destroyRawImage();
  1202. }
  1203. return res;
  1204. }
  1205. // Call with 0,0 to turn this feature off.
  1206. //virtual
  1207. void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
  1208. {
  1209. if(mKnownDrawWidth != width || mKnownDrawHeight != height)
  1210. {
  1211. mKnownDrawWidth = width;
  1212. mKnownDrawHeight = height;
  1213. mKnownDrawSizeChanged = TRUE ;
  1214. mFullyLoaded = FALSE ;
  1215. }
  1216. addTextureStats((F32)(width * height));
  1217. }
  1218. //virtual
  1219. void LLViewerFetchedTexture::processTextureStats()
  1220. {
  1221. if(mFullyLoaded)//already loaded
  1222. {
  1223. return ;
  1224. }
  1225. updateVirtualSize() ;
  1226. static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
  1227. if (textures_fullres)
  1228. {
  1229. mDesiredDiscardLevel = 0;
  1230. }
  1231. else if(!mFullWidth || !mFullHeight)
  1232. {
  1233. mDesiredDiscardLevel =  getMaxDiscardLevel() ;
  1234. }
  1235. else
  1236. {
  1237. if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
  1238. {
  1239. if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
  1240. {
  1241. mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
  1242. }
  1243. else
  1244. {
  1245. mDesiredDiscardLevel = 0;
  1246. }
  1247. }
  1248. else if(mKnownDrawSizeChanged)//known draw size is set
  1249. {
  1250. mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, 
  1251.                              log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
  1252. mDesiredDiscardLevel =  llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
  1253. }
  1254. mKnownDrawSizeChanged = FALSE ;
  1255. if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
  1256. {
  1257. mFullyLoaded = TRUE ;
  1258. }
  1259. }
  1260. }
  1261. const F32 MAX_PRIORITY_PIXEL                         = 999.f ;     //pixel area
  1262. const F32 PRIORITY_BOOST_LEVEL_FACTOR                = 1000.f ;    //boost level
  1263. const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR        = 100000.f ;  //delta discard
  1264. const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY       = 4 ;
  1265. const F32 PRIORITY_ADDITIONAL_FACTOR                 = 1000000.f ; //additional 
  1266. const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY          = 8 ;
  1267. const F32 PRIORITY_BOOST_HIGH_FACTOR                 = 10000000.f ;//boost high
  1268. F32 LLViewerFetchedTexture::calcDecodePriority()
  1269. {
  1270. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1271. if (mID == LLAppViewer::getTextureFetch()->mDebugID)
  1272. {
  1273. LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
  1274. }
  1275. #endif
  1276. if(mFullyLoaded)//already loaded for static texture
  1277. {
  1278. return -4.0f ; //alreay fetched
  1279. }
  1280. if (mNeedsCreateTexture)
  1281. {
  1282. return mDecodePriority; // no change while waiting to create
  1283. }
  1284. if(mForceToSaveRawImage)
  1285. {
  1286. return maxDecodePriority() ;
  1287. }
  1288. S32 cur_discard = getDiscardLevel();
  1289. bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
  1290. F32 pixel_priority = fsqrtf(mMaxVirtualSize);
  1291. F32 priority = 0.f;
  1292. if (mIsMissingAsset)
  1293. {
  1294. priority = 0.0f;
  1295. }
  1296. else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1)
  1297. {
  1298. priority = -1.0f ;
  1299. }
  1300. else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel)
  1301. {
  1302. priority = -1.0f;
  1303. }
  1304. else if (mDesiredDiscardLevel > getMaxDiscardLevel())
  1305. {
  1306. // Don't decode anything we don't need
  1307. priority = -1.0f;
  1308. }
  1309. else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
  1310. {
  1311. priority = 1.f;
  1312. }
  1313. else if (pixel_priority <= 0.f && !have_all_data)
  1314. {
  1315. // Not on screen but we might want some data
  1316. if (mBoostLevel > BOOST_HIGH)
  1317. {
  1318. // Always want high boosted images
  1319. priority = 1.f;
  1320. }
  1321. else
  1322. {
  1323. // Leave the priority as-is
  1324. return mDecodePriority;
  1325. }
  1326. }
  1327. else if (cur_discard < 0)
  1328. {
  1329. //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
  1330. // priority range = 100,000 - 500,000
  1331. static const F64 log_2 = log(2.0);
  1332. F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
  1333. S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
  1334. ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
  1335. priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
  1336. }
  1337. else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
  1338. {
  1339. // larger mips are corrupted
  1340. priority = -3.0f;
  1341. }
  1342. else if (cur_discard <= mDesiredDiscardLevel)
  1343. {
  1344. priority = -4.0f;
  1345. }
  1346. else
  1347. {
  1348. // priority range = 100,000 - 500,000
  1349. S32 desired_discard = mDesiredDiscardLevel;
  1350. if (getDontDiscard())
  1351. {
  1352. desired_discard -= 2;
  1353. }
  1354. else if (!isJustBound() && mCachedRawImageReady)
  1355. {
  1356. //if(mBoostLevel < BOOST_HIGH)
  1357. //{
  1358. // // We haven't rendered this in a while, de-prioritize it
  1359. // desired_discard += 2;
  1360. //}
  1361. //else
  1362. {
  1363. // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is
  1364. desired_discard = cur_discard;
  1365. }
  1366. }
  1367. S32 ddiscard = cur_discard - desired_discard;
  1368. ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
  1369. priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
  1370. }
  1371. // Priority Formula:
  1372. // BOOST_HIGH  +  ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS
  1373. // [10,000,000] + [1,000,000-9,000,000]  + [100,000-500,000]   + [1-20,000]  + [0-999]
  1374. if (priority > 0.0f)
  1375. {
  1376. pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); 
  1377. priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel;
  1378. if ( mBoostLevel > BOOST_HIGH)
  1379. {
  1380. priority += PRIORITY_BOOST_HIGH_FACTOR;
  1381. }
  1382. if(mAdditionalDecodePriority > 0.0f)
  1383. {
  1384. // priority range += 1,000,000.f-9,000,000.f
  1385. priority += PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY);
  1386. }
  1387. }
  1388. return priority;
  1389. }
  1390. //static
  1391. F32 LLViewerFetchedTexture::maxDecodePriority()
  1392. {
  1393. static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR +                           //boost_high
  1394. PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) +             //additional (view dependent factors)
  1395. PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard
  1396. PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) +                              //boost level
  1397. MAX_PRIORITY_PIXEL + 1.0f ;                                                        //pixel area.
  1398. return max_priority ;
  1399. }
  1400. //============================================================================
  1401. void LLViewerFetchedTexture::setDecodePriority(F32 priority)
  1402. {
  1403. //llassert(!mInImageList); // firing a lot, figure out why
  1404.         if (mInImageList) // above llassert() softened to a warning
  1405.         {
  1406.                 llwarns << "BAD STUFF!  mInImageList" << llendl;
  1407.         }
  1408. mDecodePriority = priority;
  1409. }
  1410. void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority)
  1411. {
  1412. priority = llclamp(priority, 0.f, 1.f);
  1413. if(mAdditionalDecodePriority < priority)
  1414. {
  1415. mAdditionalDecodePriority = priority;
  1416. }
  1417. }
  1418. void LLViewerFetchedTexture::updateVirtualSize() 
  1419. {
  1420. if(mNeedsResetMaxVirtualSize)
  1421. {
  1422. addTextureStats(0.f, FALSE) ;//reset
  1423. }
  1424. for(U32 i = 0 ; i < mNumFaces ; i++)
  1425. {
  1426. LLFace* facep = mFaceList[i] ;
  1427. if(facep->getDrawable()->isRecentlyVisible())
  1428. {
  1429. addTextureStats(facep->getVirtualSize()) ;
  1430. setAdditionalDecodePriority(facep->getImportanceToCamera()) ;
  1431. }
  1432. }
  1433. mNeedsResetMaxVirtualSize = TRUE ;
  1434. reorganizeFaceList() ;
  1435. reorganizeVolumeList();
  1436. }
  1437. bool LLViewerFetchedTexture::updateFetch()
  1438. {
  1439. static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
  1440. if(textures_decode_disabled)
  1441. {
  1442. return false ;
  1443. }
  1444. mFetchState = 0;
  1445. mFetchPriority = 0;
  1446. mFetchDeltaTime = 999999.f;
  1447. mRequestDeltaTime = 999999.f;
  1448. #ifndef LL_RELEASE_FOR_DOWNLOAD
  1449. if (mID == LLAppViewer::getTextureFetch()->mDebugID)
  1450. {
  1451. LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
  1452. }
  1453. #endif
  1454. if (mNeedsCreateTexture)
  1455. {
  1456. // We may be fetching still (e.g. waiting on write)
  1457. // but don't check until we've processed the raw data we have
  1458. return false;
  1459. }
  1460. if (mIsMissingAsset)
  1461. {
  1462. llassert_always(!mHasFetcher);
  1463. return false; // skip
  1464. }
  1465. if (!mLoadedCallbackList.empty() && mRawImage.notNull())
  1466. {
  1467. return false; // process any raw image data in callbacks before replacing
  1468. }
  1469. S32 current_discard = getDiscardLevel() ;
  1470. S32 desired_discard = getDesiredDiscardLevel();
  1471. F32 decode_priority = getDecodePriority();
  1472. decode_priority = llmax(decode_priority, 0.0f);
  1473. if (mIsFetching)
  1474. {
  1475. // Sets mRawDiscardLevel, mRawImage, mAuxRawImage
  1476. S32 fetch_discard = current_discard;
  1477. if(mForceToSaveRawImage)
  1478. {
  1479. if(fetch_discard >= 0)
  1480. {
  1481. fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ;
  1482. }
  1483. }
  1484. if (mRawImage.notNull()) sRawCount--;
  1485. if (mAuxRawImage.notNull()) sAuxCount--;
  1486. bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
  1487. if (mRawImage.notNull()) sRawCount++;
  1488. if (mAuxRawImage.notNull()) sAuxCount++;
  1489. if (finished)
  1490. {
  1491. mIsFetching = FALSE;
  1492. }
  1493. else
  1494. {
  1495. mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
  1496. mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
  1497. }
  1498. // We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
  1499. if (mRawImage.notNull())
  1500. {
  1501. if(LLViewerTextureManager::sTesterp)
  1502. {
  1503. mIsFetched = TRUE ;
  1504. LLViewerTextureManager::sTesterp->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
  1505. }
  1506. mRawDiscardLevel = fetch_discard;
  1507. if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
  1508. (current_discard < 0 || mRawDiscardLevel < current_discard))
  1509. {
  1510. if (getComponents() != mRawImage->getComponents())
  1511. {
  1512. // We've changed the number of components, so we need to move any
  1513. // objects using this pool to a different pool.
  1514. mComponents = mRawImage->getComponents();
  1515. mGLTexturep->setComponents(mComponents) ;
  1516. for(U32 i = 0 ; i < mNumFaces ; i++)
  1517. {
  1518. mFaceList[i]->dirtyTexture() ;
  1519. }
  1520. }
  1521. mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
  1522. mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
  1523. if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
  1524. //discard all oversized textures.
  1525. destroyRawImage();
  1526. setIsMissingAsset();
  1527. mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
  1528. mIsFetching = FALSE ;
  1529. }
  1530. else
  1531. {
  1532. mIsRawImageValid = TRUE;
  1533. addToCreateTexture() ;
  1534. }
  1535. return TRUE ;
  1536. }
  1537. else
  1538. {
  1539. // Data is ready but we don't need it
  1540. // (received it already while fetcher was writing to disk)
  1541. destroyRawImage();
  1542. return false; // done
  1543. }
  1544. }
  1545. if (!mIsFetching)
  1546. {
  1547. if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
  1548. {
  1549. // We finished but received no data
  1550. if (current_discard < 0)
  1551. {
  1552. setIsMissingAsset();
  1553. desired_discard = -1;
  1554. }
  1555. else
  1556. {
  1557. //llwarns << mID << ": Setting min discard to " << current_discard << llendl;
  1558. mMinDiscardLevel = current_discard;
  1559. desired_discard = current_discard;
  1560. }
  1561. destroyRawImage();
  1562. }
  1563. else if (mRawImage.notNull())
  1564. {
  1565. // We have data, but our fetch failed to return raw data
  1566. // *TODO: FIgure out why this is happening and fix it
  1567. destroyRawImage();
  1568. }
  1569. }
  1570. else
  1571. {
  1572. //  // Useful debugging code for undesired deprioritization of textures.
  1573. //  if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard)
  1574. //  {
  1575. //  llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl;
  1576. //  calcDecodePriority();
  1577. //  }
  1578. LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority);
  1579. }
  1580. }
  1581. if (!mDontDiscard)
  1582. {
  1583. if (mBoostLevel == 0)
  1584. {
  1585. desired_discard = llmax(desired_discard, current_discard-1);
  1586. }
  1587. else
  1588. {
  1589. desired_discard = llmax(desired_discard, current_discard-2);
  1590. }
  1591. }
  1592. bool make_request = true;
  1593. if (decode_priority <= 0)
  1594. {
  1595. make_request = false;
  1596. }
  1597. else if (mNeedsCreateTexture || mIsMissingAsset)
  1598. {
  1599. make_request = false;
  1600. }
  1601. else if (current_discard >= 0 && current_discard <= mMinDiscardLevel)
  1602. {
  1603. make_request = false;
  1604. }
  1605. //else if (!isJustBound() && mCachedRawImageReady)
  1606. //{
  1607. // make_request = false;
  1608. //}
  1609. else
  1610. {
  1611. if (mIsFetching)
  1612. {
  1613. if (mRequestedDiscardLevel <= desired_discard)
  1614. {
  1615. make_request = false;
  1616. }
  1617. }
  1618. else
  1619. {
  1620. if (current_discard >= 0 && current_discard <= desired_discard)
  1621. {
  1622. make_request = false;
  1623. }
  1624. }
  1625. }
  1626. if (make_request)
  1627. {
  1628. S32 w=0, h=0, c=0;
  1629. if (current_discard >= 0)
  1630. {
  1631. w = mGLTexturep->getWidth(0);
  1632. h = mGLTexturep->getHeight(0);
  1633. c = mComponents;
  1634. }
  1635. // bypass texturefetch directly by pulling from LLTextureCache
  1636. bool fetch_request_created = false;
  1637. fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority,
  1638.   w, h, c, desired_discard, needsAux());
  1639. if (fetch_request_created)
  1640. {
  1641. mHasFetcher = TRUE;
  1642. mIsFetching = TRUE;
  1643. mRequestedDiscardLevel = desired_discard;
  1644. mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
  1645.    mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
  1646. }
  1647. // if createRequest() failed, we're finishing up a request for this UUID,
  1648. // wait for it to complete
  1649. }
  1650. else if (mHasFetcher && !mIsFetching)
  1651. {
  1652. // Only delete requests that haven't receeived any network data for a while
  1653. const F32 FETCH_IDLE_TIME = 5.f;
  1654. if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME)
  1655. {
  1656. //  llinfos << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << llendl;
  1657. LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
  1658. mHasFetcher = FALSE;
  1659. }
  1660. }
  1661. llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid));
  1662. return mIsFetching ? true : false;
  1663. }
  1664. //
  1665. //force to fetch a new raw image for this texture
  1666. //
  1667. BOOL LLViewerFetchedTexture::forceFetch()
  1668. {
  1669. if(!mForceToSaveRawImage)
  1670. {
  1671. return false ;
  1672. }
  1673. //if(mDesiredSavedRawDiscardLevel < getDiscardLevel())
  1674. {
  1675. //no need to force fetching. normal fetching flow will do the work.
  1676. //return false ;
  1677. }
  1678. //if (mNeedsCreateTexture)
  1679. {
  1680. // We may be fetching still (e.g. waiting on write)
  1681. // but don't check until we've processed the raw data we have
  1682. //return false;
  1683. }
  1684. if(mIsFetching)
  1685. {
  1686. return false ;
  1687. }
  1688. if (mIsMissingAsset)
  1689. {
  1690. mForceToSaveRawImage = false ;
  1691. llassert_always(!mHasFetcher);
  1692. return false; // skip
  1693. }
  1694. if (!mLoadedCallbackList.empty() && mRawImage.notNull())
  1695. {
  1696. return false; // process any raw image data in callbacks before replacing
  1697. }
  1698. if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
  1699. {
  1700. return false ; // mRawImage is enough
  1701. }
  1702. S32 desired_discard = mDesiredSavedRawDiscardLevel ;
  1703. S32 current_discard = getDiscardLevel();
  1704. bool fetch_request_created = false;
  1705. S32 w=0, h=0, c=0;
  1706. if (current_discard >= 0)
  1707. {
  1708. w = getWidth(0);
  1709. h = getHeight(0);
  1710. c = getComponents();
  1711. }
  1712. setDecodePriority(maxDecodePriority()) ;
  1713. fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), getDecodePriority(),
  1714.   w, h, c, desired_discard, needsAux());
  1715. if (fetch_request_created)
  1716. {
  1717. mHasFetcher = TRUE;
  1718. mIsFetching = TRUE;
  1719. mRequestedDiscardLevel = desired_discard ;
  1720. mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
  1721. mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
  1722. }
  1723. return mIsFetching ? true : false;
  1724. }
  1725. void LLViewerFetchedTexture::setIsMissingAsset()
  1726. {
  1727. if (mUrl.empty())
  1728. {
  1729. llwarns << mID << ": Marking image as missing" << llendl;
  1730. }
  1731. else
  1732. {
  1733. llwarns << mUrl << ": Marking image as missing" << llendl;
  1734. }
  1735. if (mHasFetcher)
  1736. {
  1737. LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
  1738. mHasFetcher = FALSE;
  1739. mIsFetching = FALSE;
  1740. mFetchState = 0;
  1741. mFetchPriority = 0;
  1742. }
  1743. mIsMissingAsset = TRUE;
  1744. }
  1745. void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
  1746.    S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata)
  1747. {
  1748. //
  1749. // Don't do ANYTHING here, just add it to the global callback list
  1750. //
  1751. if (mLoadedCallbackList.empty())
  1752. {
  1753. // Put in list to call this->doLoadedCallbacks() periodically
  1754. gTextureList.mCallbackList.insert(this);
  1755. mLoadedCallbackDesiredDiscardLevel = (S8)discard_level;
  1756. }
  1757. else
  1758. {
  1759. mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ;
  1760. }
  1761. LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata);
  1762. mLoadedCallbackList.push_back(entryp);
  1763. mNeedsAux |= needs_aux;
  1764. if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
  1765. {
  1766. // We need aux data, but we've already loaded the image, and it didn't have any
  1767. llwarns << "No aux data available for callback for image:" << getID() << llendl;
  1768. }
  1769. }
  1770. bool LLViewerFetchedTexture::doLoadedCallbacks()
  1771. {
  1772. if (mNeedsCreateTexture)
  1773. {
  1774. return false;
  1775. }
  1776. bool res = false;
  1777. if (isMissingAsset())
  1778. {
  1779. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  1780. iter != mLoadedCallbackList.end(); )
  1781. {
  1782. LLLoadedCallbackEntry *entryp = *iter++;
  1783. // We never finished loading the image.  Indicate failure.
  1784. // Note: this allows mLoadedCallbackUserData to be cleaned up.
  1785. entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData);
  1786. delete entryp;
  1787. }
  1788. mLoadedCallbackList.clear();
  1789. // Remove ourself from the global list of textures with callbacks
  1790. gTextureList.mCallbackList.erase(this);
  1791. }
  1792. S32 gl_discard = getDiscardLevel();
  1793. // If we don't have a legit GL image, set it to be lower than the worst discard level
  1794. if (gl_discard == -1)
  1795. {
  1796. gl_discard = MAX_DISCARD_LEVEL + 1;
  1797. }
  1798. //
  1799. // Determine the quality levels of textures that we can provide to callbacks
  1800. // and whether we need to do decompression/readback to get it
  1801. //
  1802. S32 current_raw_discard = MAX_DISCARD_LEVEL + 1; // We can always do a readback to get a raw discard
  1803. S32 best_raw_discard = gl_discard; // Current GL quality level
  1804. S32 current_aux_discard = MAX_DISCARD_LEVEL + 1;
  1805. S32 best_aux_discard = MAX_DISCARD_LEVEL + 1;
  1806. if (mIsRawImageValid)
  1807. {
  1808. // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels.
  1809. best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel);
  1810. best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw
  1811. current_aux_discard = llmin(current_aux_discard, best_aux_discard);
  1812. }
  1813. else
  1814. {
  1815. // We have no data at all, we need to get it
  1816. // Do this by forcing the best aux discard to be 0.
  1817. best_aux_discard = 0;
  1818. }
  1819. //
  1820. // See if any of the callbacks would actually run using the data that we can provide,
  1821. // and also determine if we need to perform any readbacks or decodes.
  1822. //
  1823. bool run_gl_callbacks = false;
  1824. bool run_raw_callbacks = false;
  1825. bool need_readback = false;
  1826. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  1827. iter != mLoadedCallbackList.end(); )
  1828. {
  1829. LLLoadedCallbackEntry *entryp = *iter++;
  1830. if (entryp->mNeedsImageRaw)
  1831. {
  1832. if (mNeedsAux)
  1833. {
  1834. //
  1835. // Need raw and auxiliary channels
  1836. //
  1837. if (entryp->mLastUsedDiscard > current_aux_discard)
  1838. {
  1839. // We have useful data, run the callbacks
  1840. run_raw_callbacks = true;
  1841. }
  1842. }
  1843. else
  1844. {
  1845. if (entryp->mLastUsedDiscard > current_raw_discard)
  1846. {
  1847. // We have useful data, just run the callbacks
  1848. run_raw_callbacks = true;
  1849. }
  1850. else if (entryp->mLastUsedDiscard > best_raw_discard)
  1851. {
  1852. // We can readback data, and then run the callbacks
  1853. need_readback = true;
  1854. run_raw_callbacks = true;
  1855. }
  1856. }
  1857. }
  1858. else
  1859. {
  1860. // Needs just GL
  1861. if (entryp->mLastUsedDiscard > gl_discard)
  1862. {
  1863. // We have enough data, run this callback requiring GL data
  1864. run_gl_callbacks = true;
  1865. }
  1866. }
  1867. }
  1868. //
  1869. // Do a readback if required, OR start off a texture decode
  1870. //
  1871. if (need_readback && (getMaxDiscardLevel() > gl_discard))
  1872. {
  1873. // Do a readback to get the GL data into the raw image
  1874. // We have GL data.
  1875. destroyRawImage();
  1876. reloadRawImage(mLoadedCallbackDesiredDiscardLevel);
  1877. llassert_always(mRawImage.notNull());
  1878. llassert_always(!mNeedsAux || mAuxRawImage.notNull());
  1879. }
  1880. //
  1881. // Run raw/auxiliary data callbacks
  1882. //
  1883. if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel()))
  1884. {
  1885. // Do callbacks which require raw image data.
  1886. //llinfos << "doLoadedCallbacks raw for " << getID() << llendl;
  1887. // Call each party interested in the raw data.
  1888. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  1889. iter != mLoadedCallbackList.end(); )
  1890. {
  1891. callback_list_t::iterator curiter = iter++;
  1892. LLLoadedCallbackEntry *entryp = *curiter;
  1893. if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel))
  1894. {
  1895. // If we've loaded all the data there is to load or we've loaded enough
  1896. // to satisfy the interested party, then this is the last time that
  1897. // we're going to call them.
  1898. llassert_always(mRawImage.notNull());
  1899. if(mNeedsAux && mAuxRawImage.isNull())
  1900. {
  1901. llwarns << "Raw Image with no Aux Data for callback" << llendl;
  1902. }
  1903. BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE;
  1904. //llinfos << "Running callback for " << getID() << llendl;
  1905. //llinfos << mRawImage->getWidth() << "x" << mRawImage->getHeight() << llendl;
  1906. if (final)
  1907. {
  1908. //llinfos << "Final!" << llendl;
  1909. }
  1910. entryp->mLastUsedDiscard = mRawDiscardLevel;
  1911. entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData);
  1912. if (final)
  1913. {
  1914. iter = mLoadedCallbackList.erase(curiter);
  1915. delete entryp;
  1916. }
  1917. res = true;
  1918. }
  1919. }
  1920. }
  1921. //
  1922. // Run GL callbacks
  1923. //
  1924. if (run_gl_callbacks && (gl_discard <= getMaxDiscardLevel()))
  1925. {
  1926. //llinfos << "doLoadedCallbacks GL for " << getID() << llendl;
  1927. // Call the callbacks interested in GL data.
  1928. for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
  1929. iter != mLoadedCallbackList.end(); )
  1930. {
  1931. callback_list_t::iterator curiter = iter++;
  1932. LLLoadedCallbackEntry *entryp = *curiter;
  1933. if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard))
  1934. {
  1935. BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE;
  1936. entryp->mLastUsedDiscard = gl_discard;
  1937. entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData);
  1938. if (final)
  1939. {
  1940. iter = mLoadedCallbackList.erase(curiter);
  1941. delete entryp;
  1942. }
  1943. res = true;
  1944. }
  1945. }
  1946. }
  1947. //
  1948. // If we have no callbacks, take us off of the image callback list.
  1949. //
  1950. if (mLoadedCallbackList.empty())
  1951. {
  1952. gTextureList.mCallbackList.erase(this);
  1953. }
  1954. // Done with any raw image data at this point (will be re-created if we still have callbacks)
  1955. destroyRawImage();
  1956. return res;
  1957. }
  1958. //virtual
  1959. void LLViewerFetchedTexture::forceImmediateUpdate()
  1960. {
  1961. //only immediately update a deleted texture which is now being re-used.
  1962. if(!isDeleted())
  1963. {
  1964. return ;
  1965. }
  1966. //if already called forceImmediateUpdate()
  1967. if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority())
  1968. {
  1969. return ;
  1970. }
  1971. gTextureList.forceImmediateUpdate(this) ;
  1972. return ;
  1973. }
  1974. LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
  1975. {
  1976. llassert_always(mGLTexturep.notNull()) ;
  1977. llassert_always(discard_level >= 0);
  1978. llassert_always(mComponents > 0);
  1979. if (mRawImage.notNull())
  1980. {
  1981. //mRawImage is in use by somebody else, do not delete it.
  1982. return NULL ;
  1983. }
  1984. if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
  1985. {
  1986. mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
  1987. mRawImage->copy(getSavedRawImage()) ;
  1988. mRawDiscardLevel = discard_level ;
  1989. }
  1990. else
  1991. {
  1992. //force to fetch raw image again if cached raw image is not good enough.
  1993. if(mCachedRawDiscardLevel > discard_level)
  1994. {
  1995. mRawImage = mCachedRawImage ;
  1996. mRawDiscardLevel = mCachedRawDiscardLevel;
  1997. forceToSaveRawImage(discard_level) ;
  1998. }
  1999. else //cached raw image is good enough, copy it.
  2000. {
  2001. mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
  2002. mRawImage->copy(mCachedRawImage) ;
  2003. mRawDiscardLevel = discard_level ;
  2004. }
  2005. }
  2006. mIsRawImageValid = TRUE ;
  2007. sRawCount++;
  2008. return mRawImage;
  2009. }
  2010. void LLViewerFetchedTexture::destroyRawImage()
  2011. {
  2012. if (mAuxRawImage.notNull()) sAuxCount--;
  2013. if (mRawImage.notNull()) 
  2014. {
  2015. sRawCount--;
  2016. if(mForceToSaveRawImage)
  2017. {
  2018. saveRawImage() ;
  2019. }
  2020. setCachedRawImage() ;
  2021. }
  2022. mRawImage = NULL;
  2023. mAuxRawImage = NULL;
  2024. mIsRawImageValid = FALSE;
  2025. mRawDiscardLevel = INVALID_DISCARD_LEVEL;
  2026. if(mForceToSaveRawImage)
  2027. {
  2028. forceFetch() ;
  2029. }
  2030. }
  2031. //use the mCachedRawImage to (re)generate the gl texture.
  2032. //virtual
  2033. void LLViewerFetchedTexture::switchToCachedImage()
  2034. {
  2035. if(mCachedRawImage.notNull())
  2036. {
  2037. mRawImage = mCachedRawImage ;
  2038. if (getComponents() != mRawImage->getComponents())
  2039. {
  2040. // We've changed the number of components, so we need to move any
  2041. // objects using this pool to a different pool.
  2042. mComponents = mRawImage->getComponents();
  2043. mGLTexturep->setComponents(mComponents) ;
  2044. gTextureList.dirtyImage(this);
  2045. }
  2046. mIsRawImageValid = TRUE;
  2047. mRawDiscardLevel = mCachedRawDiscardLevel ;
  2048. gTextureList.mCreateTextureList.insert(this);
  2049. mNeedsCreateTexture = TRUE;
  2050. }
  2051. }
  2052. void LLViewerFetchedTexture::setCachedRawImage()
  2053. {
  2054. if(mRawImage == mCachedRawImage)
  2055. {
  2056. return ;
  2057. }
  2058. if(!mIsRawImageValid)
  2059. {
  2060. return ;
  2061. }
  2062. if(mCachedRawImageReady)
  2063. {
  2064. return ;
  2065. }
  2066. if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel)
  2067. {
  2068. S32 i = 0 ;
  2069. S32 w = mRawImage->getWidth() ;
  2070. S32 h = mRawImage->getHeight() ;
  2071. S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ;
  2072. if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel)
  2073. {
  2074. max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ;
  2075. }
  2076. if(mForSculpt)
  2077. {
  2078. max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ;
  2079. mCachedRawImageReady = !mRawDiscardLevel ;
  2080. }
  2081. else
  2082. {
  2083. mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ;
  2084. }
  2085. while(((w >> i) * (h >> i)) > max_size)
  2086. {
  2087. ++i ;
  2088. }
  2089. if(i)
  2090. {
  2091. if(!(w >> i) || !(h >> i))
  2092. {
  2093. --i ;
  2094. }
  2095. mRawImage->scale(w >> i, h >> i) ;
  2096. }
  2097. mCachedRawImage = mRawImage ;
  2098. mRawDiscardLevel += i ;
  2099. mCachedRawDiscardLevel = mRawDiscardLevel ;
  2100. }
  2101. }
  2102. void LLViewerFetchedTexture::checkCachedRawSculptImage()
  2103. {
  2104. if(mCachedRawImageReady && mCachedRawDiscardLevel > 0)
  2105. {
  2106. if(getDiscardLevel() != 0)
  2107. {
  2108. mCachedRawImageReady = FALSE ;
  2109. }
  2110. else if(isForSculptOnly())
  2111. {
  2112. resetTextureStats() ; //do not update this image any more.
  2113. }
  2114. }
  2115. }
  2116. void LLViewerFetchedTexture::saveRawImage() 
  2117. {
  2118. if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel)
  2119. {
  2120. return ;
  2121. }
  2122. mSavedRawDiscardLevel = mRawDiscardLevel ;
  2123. mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ;
  2124. if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
  2125. {
  2126. mForceToSaveRawImage = FALSE ;
  2127. }
  2128. mLastReferencedSavedRawImageTime = sCurrentTime ;
  2129. }
  2130. void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) 
  2131. if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard))
  2132. {
  2133. mForceToSaveRawImage = TRUE ;
  2134. mDesiredSavedRawDiscardLevel = desired_discard ;
  2135. forceFetch() ;
  2136. }
  2137. }
  2138. void LLViewerFetchedTexture::destroySavedRawImage()
  2139. {
  2140. mSavedRawImage = NULL ;
  2141. mForceToSaveRawImage  = FALSE ;
  2142. mSavedRawDiscardLevel = -1 ;
  2143. mDesiredSavedRawDiscardLevel = -1 ;
  2144. mLastReferencedSavedRawImageTime = 0.0f ;
  2145. }
  2146. LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() 
  2147. {
  2148. mLastReferencedSavedRawImageTime = sCurrentTime ;
  2149. return mSavedRawImage ;
  2150. }
  2151. BOOL LLViewerFetchedTexture::hasSavedRawImage() const
  2152. {
  2153. return mSavedRawImage.notNull() ;
  2154. }
  2155. F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const
  2156. return sCurrentTime - mLastReferencedSavedRawImageTime ;
  2157. }
  2158. //----------------------------------------------------------------------------------------------
  2159. //atlasing
  2160. //----------------------------------------------------------------------------------------------
  2161. void LLViewerFetchedTexture::resetFaceAtlas()
  2162. {
  2163. //Nothing should be done here.
  2164. }
  2165. //invalidate all atlas slots for this image.
  2166. void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom)
  2167. {
  2168. for(U32 i = 0 ; i < mNumFaces ; i++)
  2169. {
  2170. LLFace* facep = mFaceList[i] ;
  2171. facep->removeAtlas() ;
  2172. if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup())
  2173. {
  2174. facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY);
  2175. }
  2176. }
  2177. }
  2178. BOOL LLViewerFetchedTexture::insertToAtlas()
  2179. {
  2180. if(!LLViewerTexture::sUseTextureAtlas)
  2181. {
  2182. return FALSE ;
  2183. }
  2184. if(getNumFaces() < 1)
  2185. {
  2186. return FALSE ;
  2187. }
  2188. if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas())
  2189. {
  2190. return FALSE ;
  2191. }
  2192. if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget()))
  2193. {
  2194. return FALSE ;
  2195. }
  2196. BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image.
  2197. S32 raw_w = mRawImage->getWidth() ;
  2198. S32 raw_h = mRawImage->getHeight() ;
  2199. F32 xscale = 1.0f, yscale = 1.0f ;
  2200. LLPointer<LLTextureAtlasSlot> slot_infop;
  2201. LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer.
  2202. LLSpatialGroup* groupp ;
  2203. LLFace* facep;
  2204. //if the atlas slot pointers for some faces are null, process them later.
  2205. ll_face_list_t waiting_list ;
  2206. for(U32 i = 0 ; i < mNumFaces ; i++)
  2207. {
  2208. {
  2209. facep = mFaceList[i] ;
  2210. //face can not use atlas.
  2211. if(!facep->canUseAtlas())
  2212. {
  2213. if(facep->getAtlasInfo())
  2214. {
  2215. facep->removeAtlas() ;
  2216. }
  2217. ret = FALSE ;
  2218. continue ;
  2219. }
  2220. //the atlas slot is updated
  2221. slot_infop = facep->getAtlasInfo() ;
  2222. groupp = facep->getDrawable()->getSpatialGroup() ;
  2223. if(slot_infop) 
  2224. {
  2225. if(slot_infop->getSpatialGroup() != groupp)
  2226. {
  2227. if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot
  2228. {
  2229. facep->setAtlasInfo(cur_slotp) ;
  2230. facep->setAtlasInUse(TRUE) ;
  2231. continue ;
  2232. }
  2233. else //do not forget to update slot_infop->getSpatialGroup().
  2234. {
  2235. LLSpatialGroup* gp = slot_infop->getSpatialGroup() ;
  2236. gp->setCurUpdatingTime(gFrameCount) ;
  2237. gp->setCurUpdatingTexture(this) ;
  2238. gp->setCurUpdatingSlot(slot_infop) ;
  2239. }
  2240. }
  2241. else //same group
  2242. {
  2243. if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated
  2244. {
  2245. facep->setAtlasInUse(TRUE) ;
  2246. continue ;
  2247. }
  2248. }
  2249. }
  2250. else
  2251. {
  2252. //if the slot is null, wait to process them later.
  2253. waiting_list.push_back(facep) ;
  2254. continue ;
  2255. }
  2256. //----------
  2257. //insert to atlas
  2258. if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
  2259. {
  2260. //the texture does not qualify to add to atlas, do not bother to try for other faces.
  2261. //invalidateAtlas();
  2262. return FALSE ;
  2263. }
  2264. //update texture scale
  2265. slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
  2266. slot_infop->setTexCoordScale(xscale, yscale) ;
  2267. slot_infop->setValid() ;
  2268. slot_infop->setUpdatedTime(gFrameCount) ;
  2269. //update spatial group atlas info
  2270. groupp->setCurUpdatingTime(gFrameCount) ;
  2271. groupp->setCurUpdatingTexture(this) ;
  2272. groupp->setCurUpdatingSlot(slot_infop) ;
  2273. //make the face to switch to the atlas.
  2274. facep->setAtlasInUse(TRUE) ;
  2275. }
  2276. }
  2277. //process the waiting_list
  2278. for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter)
  2279. {
  2280. facep = (LLFace*)*iter ;
  2281. groupp = facep->getDrawable()->getSpatialGroup() ;
  2282. //check if this texture already inserted to atlas for this group
  2283. if((cur_slotp = groupp->getCurUpdatingSlot(this)))
  2284. {
  2285. facep->setAtlasInfo(cur_slotp) ;
  2286. facep->setAtlasInUse(TRUE) ;
  2287. continue ;
  2288. }
  2289. //need to reserve a slot from atlas
  2290. slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ;
  2291. facep->setAtlasInfo(slot_infop) ;
  2292. groupp->setCurUpdatingTime(gFrameCount) ;
  2293. groupp->setCurUpdatingTexture(this) ;
  2294. groupp->setCurUpdatingSlot(slot_infop) ;
  2295. //slot allocation failed.
  2296. if(!slot_infop || !slot_infop->getAtlas())
  2297. {
  2298. ret = FALSE ;
  2299. facep->setAtlasInUse(FALSE) ;
  2300. continue ;
  2301. }
  2302. //insert to atlas
  2303. if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
  2304. {
  2305. //the texture does not qualify to add to atlas, do not bother to try for other faces.
  2306. ret = FALSE ;
  2307. //invalidateAtlas();
  2308. break ; 
  2309. }
  2310. //update texture scale
  2311. slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
  2312. slot_infop->setTexCoordScale(xscale, yscale) ;
  2313. slot_infop->setValid() ;
  2314. slot_infop->setUpdatedTime(gFrameCount) ;
  2315. //make the face to switch to the atlas.
  2316. facep->setAtlasInUse(TRUE) ;
  2317. }
  2318. return ret ;
  2319. }
  2320. //----------------------------------------------------------------------------------------------
  2321. //end of LLViewerFetchedTexture
  2322. //----------------------------------------------------------------------------------------------
  2323. //----------------------------------------------------------------------------------------------
  2324. //start of LLViewerLODTexture
  2325. //----------------------------------------------------------------------------------------------
  2326. LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
  2327. : LLViewerFetchedTexture(id, host, usemipmaps)
  2328. {
  2329. init(TRUE) ;
  2330. }
  2331. LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps)
  2332. : LLViewerFetchedTexture(url, id, usemipmaps)
  2333. {
  2334. init(TRUE) ;
  2335. }
  2336. void LLViewerLODTexture::init(bool firstinit)
  2337. {
  2338. mTexelsPerImage = 64.f*64.f;
  2339. mDiscardVirtualSize = 0.f;
  2340. mCalculatedDiscardLevel = -1.f;
  2341. }
  2342. //virtual 
  2343. S8 LLViewerLODTexture::getType() const
  2344. {
  2345. return LLViewerTexture::LOD_TEXTURE ;
  2346. }
  2347. BOOL LLViewerLODTexture::isUpdateFrozen()
  2348. {
  2349. return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel() ;
  2350. }
  2351. // This is gauranteed to get called periodically for every texture
  2352. //virtual
  2353. void LLViewerLODTexture::processTextureStats()
  2354. {
  2355. updateVirtualSize() ;
  2356. static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
  2357. if (textures_fullres)
  2358. {
  2359. mDesiredDiscardLevel = 0;
  2360. }
  2361. // Generate the request priority and render priority
  2362. else if (mDontDiscard || !mUseMipMaps)
  2363. {
  2364. mDesiredDiscardLevel = 0;
  2365. if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
  2366. mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
  2367. }
  2368. else if (mBoostLevel < LLViewerTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f)
  2369. {
  2370. // If the image has not been significantly visible in a while, we don't want it
  2371. mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1));
  2372. }
  2373. else if (!mFullWidth  || !mFullHeight)
  2374. {
  2375. mDesiredDiscardLevel =  getMaxDiscardLevel() ;
  2376. }
  2377. else
  2378. {
  2379. //static const F64 log_2 = log(2.0);
  2380. static const F64 log_4 = log(4.0);
  2381. S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
  2382. S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
  2383. mTexelsPerImage = (F32)fullwidth * fullheight;
  2384. F32 discard_level = 0.f;
  2385. // If we know the output width and height, we can force the discard
  2386. // level to the correct value, and thus not decode more texture
  2387. // data than we need to.
  2388. if (mKnownDrawWidth && mKnownDrawHeight)
  2389. {
  2390. S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight;
  2391. // Use log_4 because we're in square-pixel space, so an image
  2392. // with twice the width and twice the height will have mTexelsPerImage
  2393. // 4 * draw_size
  2394. discard_level = (F32)(log(mTexelsPerImage/draw_texels) / log_4);
  2395. }
  2396. else
  2397. {
  2398. if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f)
  2399. {
  2400. //if is a big image and not being used recently, nor close to the view point, do not load hi-res data.
  2401. mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize) ;
  2402. }
  2403. if ((mCalculatedDiscardLevel >= 0.f) &&
  2404. (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f))
  2405. {
  2406. // < 20% change in virtual size = no change in desired discard
  2407. discard_level = mCalculatedDiscardLevel; 
  2408. }
  2409. else
  2410. {
  2411. // Calculate the required scale factor of the image using pixels per texel
  2412. discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4);
  2413. mDiscardVirtualSize = mMaxVirtualSize;
  2414. mCalculatedDiscardLevel = discard_level;
  2415. }
  2416. }
  2417. if (mBoostLevel < LLViewerTexture::BOOST_HIGH)
  2418. {
  2419. discard_level += sDesiredDiscardBias;
  2420. discard_level *= sDesiredDiscardScale; // scale
  2421. discard_level += sCameraMovingDiscardBias ;
  2422. }
  2423. discard_level = floorf(discard_level);
  2424. F32 min_discard = 0.f;
  2425. if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
  2426. min_discard = 1.f; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
  2427. discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL);
  2428. // Can't go higher than the max discard level
  2429. mDesiredDiscardLevel = llmin(getMaxDiscardLevel() + 1, (S32)discard_level);
  2430. // Clamp to min desired discard
  2431. mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, mDesiredDiscardLevel);
  2432. //
  2433. // At this point we've calculated the quality level that we want,
  2434. // if possible.  Now we check to see if we have it, and take the
  2435. // proper action if we don't.
  2436. //
  2437. S32 current_discard = getDiscardLevel();
  2438. if ((sDesiredDiscardBias > 0.0f) &&
  2439. (current_discard >= 0 && mDesiredDiscardLevel >= current_discard))
  2440. {
  2441. // Limit the amount of GL memory bound each frame
  2442. if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
  2443. (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
  2444. {
  2445. scaleDown() ;
  2446. }
  2447. // Only allow GL to have 2x the video card memory
  2448. else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale &&
  2449. (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
  2450. {
  2451. scaleDown() ;
  2452. }
  2453. }
  2454. }
  2455. }
  2456. void LLViewerLODTexture::scaleDown()
  2457. {
  2458. if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
  2459. {
  2460. switchToCachedImage() ;
  2461. if(LLViewerTextureManager::sTesterp)
  2462. {
  2463. LLViewerTextureManager::sTesterp->setStablizingTime() ;
  2464. }
  2465. }
  2466. }
  2467. //----------------------------------------------------------------------------------------------
  2468. //end of LLViewerLODTexture
  2469. //----------------------------------------------------------------------------------------------
  2470. //----------------------------------------------------------------------------------------------
  2471. //start of LLViewerMediaTexture
  2472. //----------------------------------------------------------------------------------------------
  2473. //static
  2474. void LLViewerMediaTexture::updateClass()
  2475. {
  2476. static const F32 MAX_INACTIVE_TIME = 30.f ;
  2477. #if 0
  2478. //force to play media.
  2479. gSavedSettings.setBOOL("AudioStreamingMedia", true) ;
  2480. #endif
  2481. for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); )
  2482. {
  2483. LLViewerMediaTexture* mediap = iter->second;
  2484. if(mediap->getNumRefs() == 1) //one reference by sMediaMap
  2485. {
  2486. //
  2487. //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
  2488. //
  2489. if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME)
  2490. {
  2491. media_map_t::iterator cur = iter++ ;
  2492. sMediaMap.erase(cur) ;
  2493. continue ;
  2494. }
  2495. }
  2496. ++iter ;
  2497. }
  2498. }
  2499. //static 
  2500. void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) 
  2501. {
  2502. LLViewerMediaTexture* media_tex = findMediaTexture(media_id) ;
  2503. if(media_tex)
  2504. {
  2505. media_tex->invalidateMediaImpl() ;
  2506. }
  2507. }
  2508. //static
  2509. void LLViewerMediaTexture::cleanup()
  2510. {
  2511. sMediaMap.clear() ;
  2512. }
  2513. //static
  2514. LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media_id)
  2515. {
  2516. media_map_t::iterator iter = sMediaMap.find(media_id);
  2517. if(iter == sMediaMap.end())
  2518. {
  2519. return NULL;
  2520. }
  2521. LLViewerMediaTexture* media_tex = iter->second ;
  2522. media_tex->setMediaImpl() ;
  2523. media_tex->getLastReferencedTimer()->reset() ;
  2524. return media_tex;
  2525. }
  2526. LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) 
  2527. : LLViewerTexture(id, usemipmaps),
  2528. mMediaImplp(NULL),
  2529. mUpdateVirtualSizeTime(0)
  2530. {
  2531. sMediaMap.insert(std::make_pair(id, this));
  2532. mGLTexturep = gl_image ;
  2533. if(mGLTexturep.isNull())
  2534. {
  2535. generateGLTexture() ;
  2536. }
  2537. mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
  2538. mIsPlaying = FALSE ;
  2539. setMediaImpl() ;
  2540. setCategory(LLViewerTexture::MEDIA) ;
  2541. LLViewerTexture* tex = gTextureList.findImage(mID) ;
  2542. if(tex) //this media is a parcel media for tex.
  2543. {
  2544. tex->setParcelMedia(this) ;
  2545. }
  2546. }
  2547. //virtual 
  2548. LLViewerMediaTexture::~LLViewerMediaTexture() 
  2549. {
  2550. LLViewerTexture* tex = gTextureList.findImage(mID) ;
  2551. if(tex) //this media is a parcel media for tex.
  2552. {
  2553. tex->setParcelMedia(NULL) ;
  2554. }
  2555. }
  2556. void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */)
  2557. {
  2558. llassert(mGLTexturep.notNull()) ;
  2559. mUseMipMaps = usemipmaps ;
  2560. getLastReferencedTimer()->reset() ;
  2561. mGLTexturep->setUseMipMaps(mUseMipMaps) ;
  2562. mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
  2563. }
  2564. void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) 
  2565. {
  2566. mUseMipMaps = mipmap;
  2567. if(mGLTexturep.notNull())
  2568. {
  2569. mGLTexturep->setUseMipMaps(mipmap) ;
  2570. }
  2571. }
  2572. //virtual 
  2573. S8 LLViewerMediaTexture::getType() const
  2574. {
  2575. return LLViewerTexture::MEDIA_TEXTURE ;
  2576. }
  2577. void LLViewerMediaTexture::invalidateMediaImpl() 
  2578. {
  2579. mMediaImplp = NULL ;
  2580. }
  2581. void LLViewerMediaTexture::setMediaImpl()
  2582. {
  2583. if(!mMediaImplp)
  2584. {
  2585. mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID) ;
  2586. }
  2587. }
  2588. //return true if all faces to reference to this media texture are found
  2589. //Note: mMediaFaceList is valid only for the current instant 
  2590. //      because it does not check the face validity after the current frame.
  2591. BOOL LLViewerMediaTexture::findFaces()
  2592. {
  2593. mMediaFaceList.clear() ;
  2594. BOOL ret = TRUE ;
  2595. LLViewerTexture* tex = gTextureList.findImage(mID) ;
  2596. if(tex) //this media is a parcel media for tex.
  2597. {
  2598. const ll_face_list_t* face_list = tex->getFaceList() ;
  2599. U32 end = tex->getNumFaces() ;
  2600. for(U32 i = 0 ; i < end ; i++)
  2601. {
  2602. mMediaFaceList.push_back((*face_list)[i]) ;
  2603. }
  2604. }
  2605. if(!mMediaImplp)
  2606. {
  2607. return TRUE ; 
  2608. }
  2609. //for media on a face.
  2610. const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList() ;
  2611. std::list< LLVOVolume* >::const_iterator iter = obj_list->begin() ;
  2612. for(; iter != obj_list->end(); ++iter)
  2613. {
  2614. LLVOVolume* obj = *iter ;
  2615. if(obj->mDrawable.isNull())
  2616. {
  2617. ret = FALSE ;
  2618. continue ;
  2619. }
  2620. S32 face_id = -1 ;
  2621. S32 num_faces = obj->mDrawable->getNumFaces() ;
  2622. while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces)
  2623. {
  2624. LLFace* facep = obj->mDrawable->getFace(face_id) ;
  2625. if(facep)
  2626. {
  2627. mMediaFaceList.push_back(facep) ;
  2628. }
  2629. else
  2630. {
  2631. ret = FALSE ;
  2632. }
  2633. }
  2634. }
  2635. return ret ;
  2636. }
  2637. void LLViewerMediaTexture::initVirtualSize()
  2638. {
  2639. if(mIsPlaying)
  2640. {
  2641. return ;
  2642. }
  2643. findFaces() ;
  2644. for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
  2645. {
  2646. addTextureStats((*iter)->getVirtualSize()) ;
  2647. }
  2648. }
  2649. void LLViewerMediaTexture::addMediaToFace(LLFace* facep) 
  2650. {
  2651. if(facep)
  2652. {
  2653. facep->setHasMedia(true) ;
  2654. }
  2655. if(!mIsPlaying)
  2656. {
  2657. return ; //no need to add the face because the media is not in playing.
  2658. }
  2659. switchTexture(facep) ;
  2660. }
  2661. void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) 
  2662. {
  2663. if(!facep)
  2664. {
  2665. return ;
  2666. }
  2667. facep->setHasMedia(false) ;
  2668. if(!mIsPlaying)
  2669. {
  2670. return ; //no need to remove the face because the media is not in playing.
  2671. }
  2672. mIsPlaying = FALSE ; //set to remove the media from the face.
  2673. switchTexture(facep) ;
  2674. mIsPlaying = TRUE ; //set the flag back.
  2675. if(getNumFaces() < 1) //no face referencing to this media
  2676. {
  2677. stopPlaying() ;
  2678. }
  2679. }
  2680. //virtual 
  2681. void LLViewerMediaTexture::addFace(LLFace* facep) 
  2682. {
  2683. LLViewerTexture::addFace(facep) ;
  2684. const LLTextureEntry* te = facep->getTextureEntry() ;
  2685. if(te && te->getID().notNull())
  2686. {
  2687. LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
  2688. if(tex)
  2689. {
  2690. mTextureList.push_back(tex) ;//increase the reference number by one for tex to avoid deleting it.
  2691. return ;
  2692. }
  2693. }
  2694. //check if it is a parcel media
  2695. if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID)
  2696. {
  2697. mTextureList.push_back(facep->getTexture()) ; //a parcel media.
  2698. return ;
  2699. }
  2700. if(te && te->getID().notNull()) //should have a texture
  2701. {
  2702. llerrs << "The face does not have a valid texture before media texture." << llendl ;
  2703. }
  2704. }
  2705. //virtual 
  2706. void LLViewerMediaTexture::removeFace(LLFace* facep) 
  2707. {
  2708. LLViewerTexture::removeFace(facep) ;
  2709. const LLTextureEntry* te = facep->getTextureEntry() ;
  2710. if(te && te->getID().notNull())
  2711. {
  2712. LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
  2713. if(tex)
  2714. {
  2715. for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
  2716. iter != mTextureList.end(); ++iter)
  2717. {
  2718. if(*iter == tex)
  2719. {
  2720. mTextureList.erase(iter) ; //decrease the reference number for tex by one.
  2721. return ;
  2722. }
  2723. }
  2724. //
  2725. //we have some trouble here: the texture of the face is changed.
  2726. //we need to find the former texture, and remove it from the list to avoid memory leaking.
  2727. if(!mNumFaces)
  2728. {
  2729. mTextureList.clear() ;
  2730. return ;
  2731. }
  2732. S32 end = getNumFaces() ;
  2733. std::vector<const LLTextureEntry*> te_list(end) ;
  2734. S32 i = 0 ;
  2735. for(U32 j = 0 ; j < mNumFaces ; j++)
  2736. {
  2737. te_list[i++] = mFaceList[j]->getTextureEntry() ;//all textures are in use.
  2738. }
  2739. for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
  2740. iter != mTextureList.end(); ++iter)
  2741. {
  2742. for(i = 0 ; i < end ; i++)
  2743. {
  2744. if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use.
  2745. {
  2746. te_list[i] = NULL ;
  2747. break ;
  2748. }
  2749. }
  2750. if(i == end) //no hit for this texture, remove it.
  2751. {
  2752. mTextureList.erase(iter) ; //decrease the reference number for tex by one.
  2753. return ;
  2754. }
  2755. }
  2756. }
  2757. }
  2758. //check if it is a parcel media
  2759. for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
  2760. iter != mTextureList.end(); ++iter)
  2761. {
  2762. if((*iter)->getID() == mID)
  2763. {
  2764. mTextureList.erase(iter) ; //decrease the reference number for tex by one.
  2765. return ;
  2766. }
  2767. }
  2768. if(te && te->getID().notNull()) //should have a texture
  2769. {
  2770. llerrs << "mTextureList texture reference number is corrupted." << llendl ;
  2771. }
  2772. }
  2773. void LLViewerMediaTexture::stopPlaying()
  2774. {
  2775. // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser).
  2776. // if(mMediaImplp)
  2777. // {
  2778. // mMediaImplp->stop() ;
  2779. // }
  2780. mIsPlaying = FALSE ;
  2781. }
  2782. void LLViewerMediaTexture::switchTexture(LLFace* facep)
  2783. {
  2784. if(facep)
  2785. {
  2786. //check if another media is playing on this face.
  2787. if(facep->getTexture() && facep->getTexture() != this 
  2788. && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE)
  2789. {
  2790. if(mID == facep->getTexture()->getID()) //this is a parcel media
  2791. {
  2792. return ; //let the prim media win.
  2793. }
  2794. }
  2795. if(mIsPlaying) //old textures switch to the media texture
  2796. {
  2797. facep->switchTexture(this) ;
  2798. }
  2799. else //switch to old textures.
  2800. {
  2801. const LLTextureEntry* te = facep->getTextureEntry() ;
  2802. if(te)
  2803. {
  2804. LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
  2805. if(!tex && te->getID() != mID)//try parcel media.
  2806. {
  2807. tex = gTextureList.findImage(mID) ;
  2808. }
  2809. if(!tex)
  2810. {
  2811. tex = LLViewerFetchedTexture::sDefaultImagep ;
  2812. }
  2813. facep->switchTexture(tex) ;
  2814. }
  2815. }
  2816. }
  2817. }
  2818. void LLViewerMediaTexture::setPlaying(BOOL playing) 
  2819. {
  2820. if(!mMediaImplp)
  2821. {
  2822. return ; 
  2823. }
  2824. if(!playing && !mIsPlaying)
  2825. {
  2826. return ; //media is already off
  2827. }
  2828. if(playing == mIsPlaying && !mMediaImplp->isUpdated())
  2829. {
  2830. return ; //nothing has changed since last time.
  2831. }
  2832. mIsPlaying = playing ;
  2833. if(mIsPlaying) //is about to play this media
  2834. {
  2835. if(findFaces())
  2836. {
  2837. //about to update all faces.
  2838. mMediaImplp->setUpdated(FALSE) ;
  2839. }
  2840. if(mMediaFaceList.empty())//no face pointing to this media
  2841. {
  2842. stopPlaying() ;
  2843. return ;
  2844. }
  2845. for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
  2846. {
  2847. switchTexture(*iter) ;
  2848. }
  2849. }
  2850. else //stop playing this media
  2851. {
  2852. for(U32 i = mNumFaces ; i ; i--)
  2853. {
  2854. switchTexture(mFaceList[i - 1]) ; //current face could be removed in this function.
  2855. }
  2856. }
  2857. return ;
  2858. }
  2859. //virtual 
  2860. F32 LLViewerMediaTexture::getMaxVirtualSize() 
  2861. {
  2862. if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime)
  2863. {
  2864. return mMaxVirtualSize ;
  2865. }
  2866. mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ;
  2867. if(mNeedsResetMaxVirtualSize)
  2868. {
  2869. addTextureStats(0.f, FALSE) ;//reset
  2870. }
  2871. if(mIsPlaying) //media is playing
  2872. {
  2873. for(U32 i = 0 ; i < mNumFaces ; i++)
  2874. {
  2875. LLFace* facep = mFaceList[i] ;
  2876. if(facep->getDrawable()->isRecentlyVisible())
  2877. {
  2878. addTextureStats(facep->getVirtualSize()) ;
  2879. }
  2880. }
  2881. }
  2882. else //media is not in playing
  2883. {
  2884. findFaces() ;
  2885. if(!mMediaFaceList.empty())
  2886. {
  2887. for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
  2888. {
  2889. LLFace* facep = *iter ;
  2890. if(facep->getDrawable()->isRecentlyVisible())
  2891. {
  2892. addTextureStats(facep->getVirtualSize()) ;
  2893. }
  2894. }
  2895. }
  2896. }
  2897. mNeedsResetMaxVirtualSize = TRUE ;
  2898. reorganizeFaceList() ;
  2899. reorganizeVolumeList();
  2900. return mMaxVirtualSize ;
  2901. }
  2902. //----------------------------------------------------------------------------------------------
  2903. //end of LLViewerMediaTexture
  2904. //----------------------------------------------------------------------------------------------
  2905. //----------------------------------------------------------------------------------------------
  2906. //start of LLTexturePipelineTester
  2907. //----------------------------------------------------------------------------------------------
  2908. LLTexturePipelineTester::LLTexturePipelineTester() :
  2909. LLMetricPerformanceTester("TextureTester", FALSE) 
  2910. {
  2911. addMetricString("TotalBytesLoaded") ;
  2912. addMetricString("TotalBytesLoadedFromCache") ;
  2913. addMetricString("TotalBytesLoadedForLargeImage") ;
  2914. addMetricString("TotalBytesLoadedForSculpties") ;
  2915. addMetricString("StartFetchingTime") ;
  2916. addMetricString("TotalGrayTime") ;
  2917. addMetricString("TotalStablizingTime") ;
  2918. addMetricString("StartTimeLoadingSculpties") ;
  2919. addMetricString("EndTimeLoadingSculpties") ;
  2920. addMetricString("Time") ;
  2921. addMetricString("TotalBytesBound") ;
  2922. addMetricString("TotalBytesBoundForLargeImage") ;
  2923. addMetricString("PercentageBytesBound") ;
  2924. mTotalBytesLoaded = 0 ;
  2925. mTotalBytesLoadedFromCache = 0 ;
  2926. mTotalBytesLoadedForLargeImage = 0 ;
  2927. mTotalBytesLoadedForSculpties = 0 ;
  2928. reset() ;
  2929. }
  2930. LLTexturePipelineTester::~LLTexturePipelineTester()
  2931. {
  2932. LLViewerTextureManager::sTesterp = NULL ;
  2933. }
  2934. void LLTexturePipelineTester::update()
  2935. {
  2936. mLastTotalBytesUsed = mTotalBytesUsed ;
  2937. mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ;
  2938. mTotalBytesUsed = 0 ;
  2939. mTotalBytesUsedForLargeImage = 0 ;
  2940. if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty
  2941. {
  2942. if(mPause)
  2943. {
  2944. //start a new fetching session
  2945. reset() ;
  2946. mStartFetchingTime = LLImageGL::sLastFrameTime ;
  2947. mPause = FALSE ;
  2948. }
  2949. //update total gray time
  2950. if(mUsingDefaultTexture)
  2951. {
  2952. mUsingDefaultTexture = FALSE ;
  2953. mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime ;
  2954. }
  2955. //update the stablizing timer.
  2956. updateStablizingTime() ;
  2957. outputTestResults() ;
  2958. }
  2959. else if(!mPause)
  2960. {
  2961. //stop the current fetching session
  2962. mPause = TRUE ;
  2963. outputTestResults() ;
  2964. reset() ;
  2965. }
  2966. }
  2967. void LLTexturePipelineTester::reset() 
  2968. {
  2969. mPause = TRUE ;
  2970. mUsingDefaultTexture = FALSE ;
  2971. mStartStablizingTime = 0.0f ;
  2972. mEndStablizingTime = 0.0f ;
  2973. mTotalBytesUsed = 0 ;
  2974. mTotalBytesUsedForLargeImage = 0 ;
  2975. mLastTotalBytesUsed = 0 ;
  2976. mLastTotalBytesUsedForLargeImage = 0 ;
  2977. mStartFetchingTime = 0.0f ;
  2978. mTotalGrayTime = 0.0f ;
  2979. mTotalStablizingTime = 0.0f ;
  2980. mStartTimeLoadingSculpties = 1.0f ;
  2981. mEndTimeLoadingSculpties = 0.0f ;
  2982. }
  2983. //virtual 
  2984. void LLTexturePipelineTester::outputTestRecord(LLSD *sd) 
  2985. {
  2986. (*sd)[mCurLabel]["TotalBytesLoaded"]              = (LLSD::Integer)mTotalBytesLoaded ;
  2987. (*sd)[mCurLabel]["TotalBytesLoadedFromCache"]     = (LLSD::Integer)mTotalBytesLoadedFromCache ;
  2988. (*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
  2989. (*sd)[mCurLabel]["TotalBytesLoadedForSculpties"]  = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
  2990. (*sd)[mCurLabel]["StartFetchingTime"]             = (LLSD::Real)mStartFetchingTime ;
  2991. (*sd)[mCurLabel]["TotalGrayTime"]                 = (LLSD::Real)mTotalGrayTime ;
  2992. (*sd)[mCurLabel]["TotalStablizingTime"]           = (LLSD::Real)mTotalStablizingTime ;
  2993. (*sd)[mCurLabel]["StartTimeLoadingSculpties"]     = (LLSD::Real)mStartTimeLoadingSculpties ;
  2994. (*sd)[mCurLabel]["EndTimeLoadingSculpties"]       = (LLSD::Real)mEndTimeLoadingSculpties ;
  2995. (*sd)[mCurLabel]["Time"]                          = LLImageGL::sLastFrameTime ;
  2996. (*sd)[mCurLabel]["TotalBytesBound"]               = (LLSD::Integer)mLastTotalBytesUsed ;
  2997. (*sd)[mCurLabel]["TotalBytesBoundForLargeImage"]  = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
  2998. (*sd)[mCurLabel]["PercentageBytesBound"]          = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
  2999. }
  3000. void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) 
  3001. {
  3002. U32 mem_size = (U32)imagep->getTextureMemory() ;
  3003. mTotalBytesUsed += mem_size ; 
  3004. if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size / (U32)imagep->getComponents()))
  3005. {
  3006. mTotalBytesUsedForLargeImage += mem_size ;
  3007. }
  3008. }
  3009. void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) 
  3010. {
  3011. U32 data_size = (U32)raw_imagep->getDataSize() ;
  3012. mTotalBytesLoaded += data_size ;
  3013. if(from_cache)
  3014. {
  3015. mTotalBytesLoadedFromCache += data_size ;
  3016. }
  3017. if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size / (U32)raw_imagep->getComponents()))
  3018. {
  3019. mTotalBytesLoadedForLargeImage += data_size ;
  3020. }
  3021. if(imagep->forSculpt())
  3022. {
  3023. mTotalBytesLoadedForSculpties += data_size ;
  3024. if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties)
  3025. {
  3026. mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
  3027. }
  3028. mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
  3029. }
  3030. }
  3031. void LLTexturePipelineTester::updateGrayTextureBinding()
  3032. {
  3033. mUsingDefaultTexture = TRUE ;
  3034. }
  3035. void LLTexturePipelineTester::setStablizingTime()
  3036. {
  3037. if(mStartStablizingTime <= mStartFetchingTime)
  3038. {
  3039. mStartStablizingTime = LLImageGL::sLastFrameTime ;
  3040. }
  3041. mEndStablizingTime = LLImageGL::sLastFrameTime ;
  3042. }
  3043. void LLTexturePipelineTester::updateStablizingTime()
  3044. {
  3045. if(mStartStablizingTime > mStartFetchingTime)
  3046. {
  3047. F32 t = mEndStablizingTime - mStartStablizingTime ;
  3048. if(t > 0.0001f && (t - mTotalStablizingTime) < 0.0001f)
  3049. {
  3050. //already stablized
  3051. mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime ;
  3052. //cancel the timer
  3053. mStartStablizingTime = 0.f ;
  3054. mEndStablizingTime = 0.f ;
  3055. }
  3056. else
  3057. {
  3058. mTotalStablizingTime = t ;
  3059. }
  3060. }
  3061. mTotalStablizingTime = 0.f ;
  3062. }
  3063. //virtual 
  3064. void LLTexturePipelineTester::compareTestSessions(std::ofstream* os) 
  3065. {
  3066. LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast<LLTexturePipelineTester::LLTextureTestSession*>(mBaseSessionp) ;
  3067. LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast<LLTexturePipelineTester::LLTextureTestSession*>(mCurrentSessionp) ;
  3068. if(!base_sessionp || !current_sessionp)
  3069. {
  3070. llerrs << "type of test session does not match!" << llendl ;
  3071. }
  3072. //compare and output the comparison
  3073. *os << llformat("%sn", mName.c_str()) ;
  3074. *os << llformat("AggregateResultsn") ;
  3075. compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ;
  3076. compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime) ;
  3077. compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime);
  3078. compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties) ;
  3079. compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties) ;
  3080. compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded) ;
  3081. compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache) ;
  3082. compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage) ;
  3083. compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties) ;
  3084. *os << llformat("InstantResultsn") ;
  3085. S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter) ;
  3086. for(S32 i = 0 ; i < size ; i++)
  3087. {
  3088. *os << llformat("Time(B-T)-%.4f-%.4fn", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime) ;
  3089. compareTestResults(os, "AverageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond,
  3090. current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
  3091. compareTestResults(os, "AverageBytesUsedForLargeImagePerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond,
  3092. current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
  3093. compareTestResults(os, "AveragePercentageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond,
  3094. current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
  3095. }
  3096. if(size < base_sessionp->mInstantPerformanceListCounter)
  3097. {
  3098. for(S32 i = size ; i < base_sessionp->mInstantPerformanceListCounter ; i++)
  3099. {
  3100. *os << llformat("Time(B-T)-%.4f- n", base_sessionp->mInstantPerformanceList[i].mTime) ;
  3101. *os << llformat(", AverageBytesUsedPerSecond, %d, N/A n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
  3102. *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
  3103. *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
  3104. }
  3105. }
  3106. else if(size < current_sessionp->mInstantPerformanceListCounter)
  3107. {
  3108. for(S32 i = size ; i < current_sessionp->mInstantPerformanceListCounter ; i++)
  3109. {
  3110. *os << llformat("Time(B-T)- -%.4fn", current_sessionp->mInstantPerformanceList[i].mTime) ;
  3111. *os << llformat(", AverageBytesUsedPerSecond, N/A, %dn", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
  3112. *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %dn", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
  3113. *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4fn", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
  3114. }
  3115. }
  3116. }
  3117. //virtual 
  3118. LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
  3119. {
  3120. LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ;
  3121. if(!sessionp)
  3122. {
  3123. return NULL ;
  3124. }
  3125. F32 total_fetching_time = 0.f ;
  3126. F32 total_gray_time = 0.f ;
  3127. F32 total_stablizing_time = 0.f ;
  3128. F32 total_loading_sculpties_time = 0.f ;
  3129. F32 start_fetching_time = -1.f ;
  3130. F32 start_fetching_sculpties_time = 0.f ;
  3131. F32 last_time = 0.0f ;
  3132. S32 frame_count = 0 ;
  3133. sessionp->mInstantPerformanceListCounter = 0 ;
  3134. sessionp->mInstantPerformanceList.resize(128) ;
  3135. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ;
  3136. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
  3137. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
  3138. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
  3139. //load a session
  3140. BOOL in_log = (*log).has(mCurLabel) ;
  3141. while(in_log)
  3142. {
  3143. LLSD::String label = mCurLabel ;
  3144. incLabel() ;
  3145. in_log = (*log).has(mCurLabel) ;
  3146. if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size())
  3147. {
  3148. sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128) ;
  3149. }
  3150. //time
  3151. F32 start_time = (*log)[label]["StartFetchingTime"].asReal() ;
  3152. F32 cur_time   = (*log)[label]["Time"].asReal() ;
  3153. if(start_time - start_fetching_time > 0.0001f) //fetching has paused for a while
  3154. {
  3155. sessionp->mTotalFetchingTime += total_fetching_time ;
  3156. sessionp->mTotalGrayTime += total_gray_time ;
  3157. sessionp->mTotalStablizingTime += total_stablizing_time ;
  3158. sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ; 
  3159. sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ;
  3160. start_fetching_time = start_time ;
  3161. total_fetching_time = 0.0f ;
  3162. total_gray_time = 0.f ;
  3163. total_stablizing_time = 0.f ;
  3164. total_loading_sculpties_time = 0.f ;
  3165. }
  3166. else
  3167. {
  3168. total_fetching_time = cur_time - start_time ;
  3169. total_gray_time = (*log)[label]["TotalGrayTime"].asReal() ;
  3170. total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal() ;
  3171. total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal() ;
  3172. if(start_fetching_sculpties_time < 0.f && total_loading_sculpties_time > 0.f)
  3173. {
  3174. start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal() ;
  3175. }
  3176. }
  3177. //total loaded bytes
  3178. sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger() ; 
  3179. sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger() ;
  3180. sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger() ;
  3181. sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger() ; 
  3182. //instant metrics
  3183. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond +=
  3184. (*log)[label]["TotalBytesBound"].asInteger() ;
  3185. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond +=
  3186. (*log)[label]["TotalBytesBoundForLargeImage"].asInteger() ;
  3187. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond +=
  3188. (*log)[label]["PercentageBytesBound"].asReal() ;
  3189. frame_count++ ;
  3190. if(cur_time - last_time >= 1.0f)
  3191. {
  3192. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count ;
  3193. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count ;
  3194. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count ;
  3195. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time ;
  3196. frame_count = 0 ;
  3197. last_time = cur_time ;
  3198. sessionp->mInstantPerformanceListCounter++ ;
  3199. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ;
  3200. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
  3201. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
  3202. sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
  3203. }
  3204. }
  3205. sessionp->mTotalFetchingTime += total_fetching_time ;
  3206. sessionp->mTotalGrayTime += total_gray_time ;
  3207. sessionp->mTotalStablizingTime += total_stablizing_time ;
  3208. if(sessionp->mStartTimeLoadingSculpties < 0.f)
  3209. {
  3210. sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ; 
  3211. }
  3212. sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ;
  3213. return sessionp;
  3214. }
  3215. LLTexturePipelineTester::LLTextureTestSession::LLTextureTestSession() 
  3216. {
  3217. reset() ;
  3218. }
  3219. LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession() 
  3220. {
  3221. }
  3222. void LLTexturePipelineTester::LLTextureTestSession::reset() 
  3223. {
  3224. mTotalFetchingTime = 0.0f ;
  3225. mTotalGrayTime = 0.0f ;
  3226. mTotalStablizingTime = 0.0f ;
  3227. mStartTimeLoadingSculpties = 0.0f ; 
  3228. mTotalTimeLoadingSculpties = 0.0f ;
  3229. mTotalBytesLoaded = 0 ; 
  3230. mTotalBytesLoadedFromCache = 0 ;
  3231. mTotalBytesLoadedForLargeImage = 0 ;
  3232. mTotalBytesLoadedForSculpties = 0 ; 
  3233. mInstantPerformanceListCounter = 0 ;
  3234. }
  3235. //----------------------------------------------------------------------------------------------
  3236. //end of LLTexturePipelineTester
  3237. //----------------------------------------------------------------------------------------------