llviewertexturelist.cpp 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162
  1. /**
  2. * @file llviewertexturelist.cpp
  3. * @brief Object for managing the list of images within a region
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewergpl$
  6. *
  7. * Copyright (c) 2000-2009, 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 <sys/stat.h>
  34. #include <utility>
  35. #include "llviewertexturelist.h"
  36. #include "imageids.h"
  37. #include "lldir.h"
  38. #include "llfasttimer.h"
  39. #include "llgl.h"
  40. #include "llimagedecodethread.h"
  41. #include "llimagegl.h"
  42. #include "llimagebmp.h"
  43. #include "llimagej2c.h"
  44. #include "llimagetga.h"
  45. #include "llimagejpeg.h"
  46. #include "llimagepng.h"
  47. #include "llmessage.h"
  48. #include "llsdserialize.h"
  49. #include "llxmltree.h"
  50. #include "llagent.h"
  51. #include "llappviewer.h"
  52. #include "lldrawpoolbump.h" // For LLStandardBumpmap::init()
  53. #include "llpipeline.h"
  54. #include "lltexturecache.h"
  55. #include "lltexturefetch.h"
  56. #include "llviewercontrol.h"
  57. #include "llviewerdisplay.h"
  58. #include "llviewertexture.h"
  59. #include "llviewermedia.h"
  60. #include "llviewerregion.h"
  61. #include "llviewerstats.h"
  62. #include "llviewerwindow.h" // For getShowProgress()
  63. // Global variables
  64. // Static members
  65. F32 LLViewerTextureList::sLastTeleportTime = 0.f;
  66. F32 LLViewerTextureList::sFetchingBoostFactor = 0.f;
  67. void (*LLViewerTextureList::sUUIDCallback)(void**, const LLUUID&) = NULL;
  68. U32 LLViewerTextureList::sTextureBits = 0;
  69. U32 LLViewerTextureList::sTexturePackets = 0;
  70. S32 LLViewerTextureList::sNumImages = 0;
  71. S32 LLViewerTextureList::sUpdatedThisFrame = 0;
  72. LLStat LLViewerTextureList::sNumImagesStat(32, true);
  73. LLStat LLViewerTextureList::sNumUpdatesStat(15, true);
  74. LLStat LLViewerTextureList::sNumRawImagesStat(32, true);
  75. LLStat LLViewerTextureList::sGLTexMemStat(32, true);
  76. LLStat LLViewerTextureList::sGLBoundMemStat(32, true);
  77. LLViewerTextureList gTextureList;
  78. LLViewerTexture* gImgPixieSmall = NULL;
  79. LLViewerTextureList::LLViewerTextureList()
  80. : mForceResetTextureStats(false),
  81. mMaxResidentTexMemInMegaBytes(0),
  82. mMaxTotalTextureMemInMegaBytes(0),
  83. mLastGLImageCleaning(0.f),
  84. mInitialized(false),
  85. mFlushOldImages(false)
  86. {
  87. }
  88. void LLViewerTextureList::init()
  89. {
  90. mInitialized = true;
  91. sNumImages = 0;
  92. mMaxResidentTexMemInMegaBytes = 0;
  93. mMaxTotalTextureMemInMegaBytes = 0;
  94. // Update how much texture RAM we are allowed to use.
  95. updateMaxResidentTexMem(0); // 0 = use current
  96. llassert_always(mInitialized && mImageList.empty() && mUUIDMap.empty());
  97. llinfos << "Preloading images (any crash would be the result of a missing image file)..."
  98. << llendl;
  99. // Set the "white" image
  100. LLViewerFetchedTexture* image =
  101. LLViewerTextureManager::getFetchedTextureFromFile("white.tga",
  102. MIPMAP_NO,
  103. LLGLTexture::BOOST_BUMP);
  104. llassert_always(image);
  105. image->dontDiscard();
  106. #if !LL_IMPLICIT_SETNODELETE
  107. image->setNoDelete();
  108. #endif
  109. LLViewerFetchedTexture::sWhiteImagep = image;
  110. // Set the default flat normal map. Note: in SL, this texture, which exists
  111. // server-side, has compression artifacts, so we must force-replace it here
  112. // with a texture we load from our own viewer distribution files.
  113. std::string tex_id = gSavedSettings.getString("DefaultNormalTexture");
  114. image =
  115. LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga",
  116. MIPMAP_NO,
  117. LLGLTexture::BOOST_BUMP,
  118. LLViewerTexture::FETCHED_TEXTURE,
  119. 0, 0, LLUUID(tex_id));
  120. llassert_always(image);
  121. image->dontDiscard();
  122. #if !LL_IMPLICIT_SETNODELETE
  123. image->setNoDelete();
  124. #endif
  125. LLViewerFetchedTexture::sFlatNormalImagep = image;
  126. // Set the default PBR irradiance map
  127. image =
  128. LLViewerTextureManager::getFetchedTextureFromFile("default_irradiance.png",
  129. MIPMAP_NO,
  130. LLGLTexture::BOOST_BUMP);
  131. llassert_always(image);
  132. image->dontDiscard();
  133. LLViewerFetchedTexture::sDefaultIrradiancePBRp = image;
  134. LLUIImageList::getInstance()->initFromFile();
  135. image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c");
  136. llassert_always(image);
  137. image->setAddressMode(LLTexUnit::TAM_WRAP);
  138. mImagePreloads.emplace_back(image);
  139. image = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c");
  140. llassert_always(image);
  141. image->setAddressMode(LLTexUnit::TAM_WRAP);
  142. mImagePreloads.emplace_back(image);
  143. image = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c");
  144. llassert_always(image);
  145. image->setAddressMode(LLTexUnit::TAM_WRAP);
  146. mImagePreloads.emplace_back(image);
  147. // DEFAULT_WATER_OPAQUE
  148. image =
  149. LLViewerTextureManager::getFetchedTextureFromFile("43c32285-d658-1793-c123-bf86315de055.j2c",
  150. MIPMAP_YES,
  151. LLGLTexture::BOOST_UI);
  152. llassert_always(image);
  153. image->setAddressMode(LLTexUnit::TAM_WRAP);
  154. LLViewerFetchedTexture::sOpaqueWaterImagep = image;
  155. // DEFAULT_WATER_TEXTURE
  156. image =
  157. LLViewerTextureManager::getFetchedTextureFromFile("2bfd3884-7e27-69b9-ba3a-3e673f680004.j2c",
  158. MIPMAP_YES,
  159. LLGLTexture::BOOST_UI);
  160. llassert_always(image);
  161. image->setAddressMode(LLTexUnit::TAM_WRAP);
  162. LLViewerFetchedTexture::sWaterImagep = image;
  163. // DEFAULT_WATER_NORMAL
  164. image =
  165. LLViewerTextureManager::getFetchedTextureFromFile("822ded49-9a6c-f61c-cb89-6df54f42cdf4.j2c",
  166. MIPMAP_YES,
  167. LLGLTexture::BOOST_UI);
  168. llassert_always(image);
  169. image->setAddressMode(LLTexUnit::TAM_WRAP);
  170. LLViewerFetchedTexture::sWaterNormapMapImagep = image;
  171. // Default Sun
  172. image =
  173. LLViewerTextureManager::getFetchedTextureFromFile("cce0f112-878f-4586-a2e2-a8f104bba271.j2c",
  174. MIPMAP_YES,
  175. LLGLTexture::BOOST_UI);
  176. llassert_always(image);
  177. image->setAddressMode(LLTexUnit::TAM_CLAMP);
  178. LLViewerFetchedTexture::sDefaultSunImagep = image;
  179. // Default Moon
  180. image =
  181. LLViewerTextureManager::getFetchedTextureFromFile("d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c",
  182. MIPMAP_YES,
  183. LLGLTexture::BOOST_UI);
  184. llassert_always(image);
  185. image->setAddressMode(LLTexUnit::TAM_CLAMP);
  186. LLViewerFetchedTexture::sDefaultMoonImagep = image;
  187. // Default clouds
  188. image =
  189. LLViewerTextureManager::getFetchedTextureFromFile("fc4b9f0b-d008-45c6-96a4-01dd947ac621.tga",
  190. MIPMAP_YES,
  191. LLGLTexture::BOOST_CLOUDS);
  192. llassert_always(image);
  193. image->dontDiscard();
  194. #if !LL_IMPLICIT_SETNODELETE
  195. image->setNoDelete();
  196. #endif
  197. LLViewerFetchedTexture::sDefaultCloudsImagep = image;
  198. // Default clouds noise
  199. image =
  200. LLViewerTextureManager::getFetchedTextureFromFile("clouds2.tga",
  201. MIPMAP_YES,
  202. LLGLTexture::BOOST_CLOUDS);
  203. llassert_always(image);
  204. image->dontDiscard();
  205. #if !LL_IMPLICIT_SETNODELETE
  206. image->setNoDelete();
  207. #endif
  208. LLViewerFetchedTexture::sDefaultCloudNoiseImagep = image;
  209. // Bloom
  210. image =
  211. LLViewerTextureManager::getFetchedTextureFromFile("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef.j2c",
  212. MIPMAP_YES,
  213. LLGLTexture::BOOST_UI);
  214. llassert_always(image);
  215. image->setAddressMode(LLTexUnit::TAM_CLAMP);
  216. LLViewerFetchedTexture::sBloomImagep = image;
  217. image =
  218. LLViewerTextureManager::getFetchedTextureFromFile("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903.j2c",
  219. MIPMAP_YES,
  220. LLGLTexture::BOOST_UI,
  221. LLViewerTexture::FETCHED_TEXTURE,
  222. 0, 0,
  223. IMG_TRANSPARENT);
  224. llassert_always(image);
  225. image->setAddressMode(LLTexUnit::TAM_WRAP);
  226. mImagePreloads.emplace_back(image);
  227. image =
  228. LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga",
  229. MIPMAP_YES,
  230. LLGLTexture::BOOST_UI,
  231. LLViewerTexture::FETCHED_TEXTURE,
  232. GL_ALPHA8, GL_ALPHA,
  233. IMG_ALPHA_GRAD);
  234. llassert_always(image);
  235. image->setAddressMode(LLTexUnit::TAM_CLAMP);
  236. mImagePreloads.emplace_back(image);
  237. image =
  238. LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c",
  239. MIPMAP_YES,
  240. LLGLTexture::BOOST_UI,
  241. LLViewerTexture::FETCHED_TEXTURE,
  242. GL_ALPHA8, GL_ALPHA,
  243. IMG_ALPHA_GRAD_2D);
  244. llassert_always(image);
  245. image->setAddressMode(LLTexUnit::TAM_CLAMP);
  246. mImagePreloads.emplace_back(image);
  247. image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
  248. llassert_always(image);
  249. mImagePreloads.emplace_back(image);
  250. gImgPixieSmall = image;
  251. LLUIImage::initClass();
  252. llinfos << "Images preloading successful." << llendl;
  253. }
  254. static std::string get_texture_list_name()
  255. {
  256. static LLCachedControl<bool> last_loc(gSavedSettings, "LoginLastLocation");
  257. std::string filename = "texture_list_";
  258. filename += (last_loc ? "last" : "home");
  259. filename += ".xml";
  260. return gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, filename);
  261. }
  262. void LLViewerTextureList::doPrefetchImages()
  263. {
  264. // Prefetch specific UUIDs, used by the sim server for some particle
  265. // systems defaults.
  266. LLViewerTextureManager::getFetchedTexture(IMG_SHOT);
  267. LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF);
  268. LLStandardBumpmap::init();
  269. if (gAppViewerp->getPurgeCache())
  270. {
  271. // Cache was purged, no point to pre-fetch last used cached images
  272. return;
  273. }
  274. // Pre-fetch textures from last logout
  275. LLSD imagelist;
  276. std::string filename = get_texture_list_name();
  277. llifstream file(filename.c_str());
  278. if (file.is_open())
  279. {
  280. LLSDSerialize::fromXML(imagelist, file);
  281. }
  282. for (LLSD::array_iterator iter = imagelist.beginArray();
  283. iter != imagelist.endArray(); ++iter)
  284. {
  285. LLSD imagesd = *iter;
  286. LLUUID uuid = imagesd["uuid"];
  287. S32 pixel_area = imagesd["area"];
  288. S32 texture_type = imagesd["type"];
  289. if (LLViewerTexture::FETCHED_TEXTURE == texture_type ||
  290. LLViewerTexture::LOD_TEXTURE == texture_type)
  291. {
  292. LLViewerFetchedTexture* image =
  293. LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT,
  294. MIPMAP_YES,
  295. LLGLTexture::BOOST_NONE,
  296. texture_type);
  297. if (image)
  298. {
  299. image->addTextureStats((F32)pixel_area);
  300. }
  301. }
  302. }
  303. }
  304. void LLViewerTextureList::shutdown()
  305. {
  306. // Prevent loading textures again.
  307. mInitialized = false;
  308. // Clear out preloads
  309. gImgPixieSmall = NULL;
  310. mImagePreloads.clear();
  311. // Write out list of currently loaded textures for precaching on startup
  312. typedef std::set<std::pair<S32, LLViewerFetchedTexture*> > image_area_list_t;
  313. image_area_list_t image_area_list;
  314. for (priority_list_t::iterator iter = mImageList.begin();
  315. iter != mImageList.end(); ++iter)
  316. {
  317. LLViewerFetchedTexture* image = *iter;
  318. if (image->getID() == IMG_DEFAULT || image->getFTType() != FTT_DEFAULT)
  319. {
  320. continue;
  321. }
  322. S8 type = image->getType();
  323. if (type != LLViewerTexture::FETCHED_TEXTURE &&
  324. type != LLViewerTexture::LOD_TEXTURE)
  325. {
  326. continue;
  327. }
  328. if (!image->hasGLTexture() || !image->getUseDiscard() ||
  329. image->needsAux() || !image->getBoundRecently())
  330. {
  331. continue;
  332. }
  333. S32 desired = image->getDesiredDiscardLevel();
  334. if (desired >= 0 && desired < MAX_DISCARD_LEVEL)
  335. {
  336. S32 pixel_area = image->getWidth(desired) *
  337. image->getHeight(desired);
  338. image_area_list.emplace(pixel_area, image);
  339. }
  340. }
  341. LLSD imagelist;
  342. constexpr S32 max_count = 1000;
  343. S32 count = 0;
  344. for (image_area_list_t::reverse_iterator riter = image_area_list.rbegin();
  345. riter != image_area_list.rend(); ++riter)
  346. {
  347. LLViewerFetchedTexture* image = riter->second;
  348. LLSD& entry = imagelist[count];
  349. entry["area"] = riter->first;
  350. entry["uuid"] = image->getID();
  351. entry["type"] = S32(image->getType());
  352. if (++count >= max_count)
  353. {
  354. break;
  355. }
  356. }
  357. if (count > 0 && !gDirUtil.getLindenUserDir().empty())
  358. {
  359. std::string filename = get_texture_list_name();
  360. llofstream file(filename.c_str());
  361. if (file.is_open())
  362. {
  363. LLSDSerialize::toPrettyXML(imagelist, file);
  364. file.close();
  365. }
  366. else
  367. {
  368. llwarns << "Could not open file '" << filename << "' for writing."
  369. << llendl;
  370. }
  371. }
  372. // Clean up "loaded" callbacks.
  373. mCallbackList.clear();
  374. // Flush all of the references
  375. mCreateTextureList.clear();
  376. mUUIDMap.clear();
  377. mImageList.clear();
  378. LLUIImage::cleanupClass();
  379. }
  380. void LLViewerTextureList::dump()
  381. {
  382. llinfos << "Image list begin dump:" << llendl;
  383. for (priority_list_t::iterator it = mImageList.begin(),
  384. end = mImageList.end();
  385. it != end; ++it)
  386. {
  387. LLViewerFetchedTexture* image = *it;
  388. if (!image) continue;
  389. llinfos << "priority " << image->getDecodePriority()
  390. << " boost " << image->getBoostLevel()
  391. << " size " << image->getWidth() << "x" << image->getHeight()
  392. << " discard " << image->getDiscardLevel()
  393. << " desired " << image->getDesiredDiscardLevel()
  394. << " http://asset.siva.lindenlab.com/" << image->getID()
  395. << ".texture" << llendl;
  396. }
  397. llinfos << "Image list end dump" << llendl;
  398. }
  399. //static
  400. void LLViewerTextureList::destroyGL(bool save_state)
  401. {
  402. LLImageGL::destroyGL(save_state);
  403. }
  404. //static
  405. void LLViewerTextureList::restoreGL()
  406. {
  407. llassert_always(gTextureList.mInitialized);
  408. LLImageGL::restoreGL();
  409. }
  410. LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename,
  411. bool usemipmaps,
  412. LLGLTexture::EBoostLevel boost_priority,
  413. S8 texture_type,
  414. S32 internal_format,
  415. U32 primary_format,
  416. const LLUUID& force_id)
  417. {
  418. if (!mInitialized)
  419. {
  420. return NULL;
  421. }
  422. std::string full_path = gDirUtil.findSkinnedFilename("textures", filename);
  423. if (full_path.empty())
  424. {
  425. llwarns << "Failed to find local image file: " << filename << llendl;
  426. return LLViewerFetchedTexture::sDefaultImagep;
  427. }
  428. std::string url = "file://" + full_path;
  429. return getImageFromUrl(url, FTT_LOCAL_FILE, usemipmaps, boost_priority,
  430. texture_type, internal_format, primary_format,
  431. force_id);
  432. }
  433. LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url,
  434. FTType f_type,
  435. bool usemipmaps,
  436. LLGLTexture::EBoostLevel boost_priority,
  437. S8 texture_type,
  438. S32 internal_format,
  439. U32 primary_format,
  440. const LLUUID& force_id)
  441. {
  442. if (!mInitialized)
  443. {
  444. return NULL;
  445. }
  446. // Generate UUID based on hash of filename
  447. LLUUID new_id;
  448. if (force_id.notNull())
  449. {
  450. new_id = force_id;
  451. }
  452. else
  453. {
  454. new_id.generate(url);
  455. }
  456. LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id);
  457. if (imagep.isNull())
  458. {
  459. switch (texture_type)
  460. {
  461. case LLViewerTexture::FETCHED_TEXTURE:
  462. imagep = new LLViewerFetchedTexture(url, f_type, new_id,
  463. usemipmaps);
  464. break;
  465. case LLViewerTexture::LOD_TEXTURE:
  466. imagep = new LLViewerLODTexture(url, f_type, new_id,
  467. usemipmaps);
  468. break;
  469. default:
  470. llerrs << "Invalid texture type " << texture_type << llendl;
  471. }
  472. if (internal_format && primary_format)
  473. {
  474. imagep->setExplicitFormat(internal_format, primary_format);
  475. }
  476. addImage(imagep);
  477. if (boost_priority != 0)
  478. {
  479. imagep->setBoostLevel(boost_priority);
  480. }
  481. }
  482. else
  483. {
  484. LLViewerFetchedTexture* texp = imagep.get();
  485. if (!texp) // Paranoia
  486. {
  487. llwarns << "Image " << new_id
  488. << " does not have a texture pointer !" << llendl;
  489. }
  490. else if (texp->getUrl().empty())
  491. {
  492. std::string type;
  493. switch (texture_type)
  494. {
  495. case LLViewerTexture::FETCHED_TEXTURE:
  496. type = "FETCHED_TEXTURE";
  497. break;
  498. case LLViewerTexture::LOD_TEXTURE:
  499. type = "LOD_TEXTURE";
  500. break;
  501. default:
  502. type = "unknown";
  503. }
  504. llwarns << "Requested texture " << new_id << " of type " << type
  505. << " already exists but does not have an URL." << llendl;
  506. if (!url.empty())
  507. {
  508. llinfos << "Setting new URL and forcing a refetch of "
  509. << new_id << llendl;
  510. texp->setUrl(url);
  511. texp->forceRefetch();
  512. }
  513. }
  514. else if (texp->getUrl() != url)
  515. {
  516. // This is not an error as long as the images really match -
  517. // e.g. could be two avatars wearing the same outfit.
  518. LL_DEBUGS("ViewerTexture") << "Requested texture " << new_id
  519. << " already exists with a different url, requested: "
  520. << url << " - current: "
  521. << texp->getUrl() << LL_ENDL;
  522. }
  523. }
  524. imagep->setGLTextureCreated(true);
  525. return imagep;
  526. }
  527. // Returns the image with ID image_id. If the image is not found, creates a new
  528. // image and enqueues a request for transmission
  529. LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID& image_id,
  530. FTType f_type,
  531. bool usemipmaps,
  532. LLGLTexture::EBoostLevel boost_priority,
  533. S8 texture_type,
  534. S32 internal_format,
  535. U32 primary_format,
  536. LLHost from_host)
  537. {
  538. if (!mInitialized)
  539. {
  540. return NULL;
  541. }
  542. if (image_id.isNull())
  543. {
  544. return LLViewerFetchedTexture::sDefaultImagep;
  545. }
  546. LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id);
  547. if (imagep.isNull())
  548. {
  549. imagep = createImage(image_id, f_type, usemipmaps, boost_priority,
  550. texture_type, internal_format, primary_format,
  551. from_host);
  552. }
  553. else
  554. {
  555. if (boost_priority != LLGLTexture::BOOST_ALM &&
  556. imagep->getBoostLevel() == LLGLTexture::BOOST_ALM)
  557. {
  558. // We need BOOST_ALM texture for something, 'rise' to NONE
  559. imagep->setBoostLevel(LLGLTexture::BOOST_NONE);
  560. }
  561. if (from_host.isOk())
  562. {
  563. LLViewerFetchedTexture* texp = imagep.get();
  564. if (!texp->getTargetHost().isOk())
  565. {
  566. // Common and normal occurrence with default textures such as
  567. // IMG_INVISIBLE. Made into a debug message to prevent useless
  568. // log spam.
  569. LL_DEBUGS("ViewerTexture") << "Requested texture " << image_id
  570. << " already exists but does not have a host."
  571. << LL_ENDL;
  572. }
  573. else if (from_host != texp->getTargetHost())
  574. {
  575. llwarns << "Requested texture " << image_id
  576. << " already exists with a different target host, requested: "
  577. << from_host << " - current: "
  578. << texp->getTargetHost() << llendl;
  579. }
  580. }
  581. }
  582. imagep->setGLTextureCreated(true);
  583. return imagep;
  584. }
  585. // When this function is called, there is no such texture in the gTextureList
  586. // with image_id.
  587. LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID& image_id,
  588. FTType f_type,
  589. bool usemipmaps,
  590. LLGLTexture::EBoostLevel boost_priority,
  591. S8 texture_type,
  592. S32 internal_format,
  593. U32 primary_format,
  594. LLHost from_host)
  595. {
  596. LLPointer<LLViewerFetchedTexture> texp;
  597. switch (texture_type)
  598. {
  599. case LLViewerTexture::FETCHED_TEXTURE:
  600. texp = new LLViewerFetchedTexture(image_id, f_type, from_host,
  601. usemipmaps);
  602. break;
  603. case LLViewerTexture::LOD_TEXTURE:
  604. texp = new LLViewerLODTexture(image_id, f_type, from_host,
  605. usemipmaps);
  606. break;
  607. default:
  608. llerrs << "Invalid texture type " << texture_type << llendl;
  609. }
  610. if (internal_format && primary_format)
  611. {
  612. texp->setExplicitFormat(internal_format, primary_format);
  613. }
  614. addImage(texp);
  615. if (boost_priority)
  616. {
  617. texp->setBoostLevel(boost_priority);
  618. }
  619. else
  620. {
  621. // By default, the texture can not be removed from memory even if it is
  622. // not used. Here turn this off. If this texture should be set to
  623. // NO_DELETE, call setNoDelete() afterwards.
  624. texp->forceActive();
  625. }
  626. return texp;
  627. }
  628. LLViewerFetchedTexture* LLViewerTextureList::findImage(const LLUUID& image_id)
  629. {
  630. uuid_map_t::iterator iter = mUUIDMap.find(image_id);
  631. if (iter != mUUIDMap.end())
  632. {
  633. return iter->second;
  634. }
  635. return NULL;
  636. }
  637. void LLViewerTextureList::addImageToList(LLViewerFetchedTexture* image)
  638. {
  639. llassert(image);
  640. if (image->isInImageList())
  641. {
  642. llwarns << "Image already in list" << llendl;
  643. llassert(false);
  644. }
  645. if ((mImageList.insert(image)).second != true)
  646. {
  647. llwarns << "An error occurred while inserting image into mImageList"
  648. << llendl;
  649. llassert(false);
  650. }
  651. image->setInImageList(true);
  652. }
  653. void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture* image)
  654. {
  655. llassert(image);
  656. S32 count = 0;
  657. if (image->isInImageList())
  658. {
  659. count = mImageList.erase(image);
  660. if (count != 1)
  661. {
  662. llwarns << "Image " << image->getID()
  663. << " had mInImageList set but mImageList.erase() returned "
  664. << count << llendl;
  665. }
  666. }
  667. else
  668. {
  669. // Something is wrong, image is expected in list or callers should
  670. // check first
  671. llwarns << "Called for " << image->getID()
  672. << " but does not have mInImageList set. Ref count is "
  673. << image->getNumRefs() << llendl;
  674. uuid_map_t::iterator iter = mUUIDMap.find(image->getID());
  675. if (iter == mUUIDMap.end())
  676. {
  677. llwarns << "Image " << image->getID() << " is not in mUUIDMap !"
  678. << llendl;
  679. }
  680. else if (iter->second != image)
  681. {
  682. llwarns << "Image " << image->getID()
  683. << " was in mUUIDMap but with different pointer" << llendl;
  684. }
  685. else
  686. {
  687. llwarns << "Image " << image->getID()
  688. << " was in mUUIDMap with same pointer" << llendl;
  689. }
  690. count = mImageList.erase(image);
  691. if (count)
  692. {
  693. llwarns << "Image " << image->getID()
  694. << " had mInImageList false but mImageList.erase() returned "
  695. << count << llendl;
  696. }
  697. llassert(false);
  698. }
  699. image->setInImageList(false);
  700. }
  701. void LLViewerTextureList::addImage(LLViewerFetchedTexture* new_texp)
  702. {
  703. if (!new_texp)
  704. {
  705. return;
  706. }
  707. const LLUUID& tex_id = new_texp->getID();
  708. LLViewerFetchedTexture* texp = findImage(tex_id);
  709. if (texp)
  710. {
  711. llwarns << "Texture with ID " << tex_id << " already in list"
  712. << llendl;
  713. }
  714. ++sNumImages;
  715. addImageToList(new_texp);
  716. mUUIDMap[tex_id] = new_texp;
  717. }
  718. void LLViewerTextureList::deleteImage(LLViewerFetchedTexture* image)
  719. {
  720. if (image)
  721. {
  722. if (image->hasCallbacks())
  723. {
  724. mCallbackList.erase(image);
  725. }
  726. if (mUUIDMap.erase(image->getID()) != 1)
  727. {
  728. llwarns << "Deleted texture " << image->getID()
  729. << " was not in the UUIDs list !" << llendl;
  730. llassert(false);
  731. }
  732. --sNumImages;
  733. removeImageFromList(image);
  734. }
  735. }
  736. void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture* image)
  737. {
  738. mDirtyTextureList.insert(image);
  739. }
  740. //static
  741. void LLViewerTextureList::resetFrameStats()
  742. {
  743. sNumUpdatesStat.addValue(sUpdatedThisFrame);
  744. sUpdatedThisFrame = 0;
  745. }
  746. void LLViewerTextureList::updateImages(F32 max_time)
  747. {
  748. if (gTeleportDisplay)
  749. {
  750. // Do not update images during teleports
  751. return;
  752. }
  753. bool can_queue = LLImageGLThread::sEnabled && gMainloopWorkp;
  754. if (can_queue)
  755. {
  756. // Subtract 1ms used to update the GL worker thread
  757. max_time -= 0.001f;
  758. }
  759. gTextureFetchp->setTextureBandwidth(gViewerStats.mTextureKBitStat.getMeanPerSec());
  760. sNumImagesStat.addValue(sNumImages);
  761. sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
  762. sGLTexMemStat.addValue((F32)BYTES2MEGABYTES(LLImageGL::sGlobalTexMemBytes));
  763. sGLBoundMemStat.addValue((F32)BYTES2MEGABYTES(LLImageGL::sBoundTexMemBytes));
  764. updateImagesDecodePriorities();
  765. static LLCachedControl<F32> allowed(gSavedSettings,
  766. "TextureUpdateMinAllowedTime");
  767. // Split in two equal minimum time slots clamped between 1ms and 50ms each.
  768. F32 min_time = llclamp((F32)allowed * 0.5f, 0.001f, 0.05f);
  769. // Update texture fetches.
  770. max_time = llmax(max_time, min_time);
  771. max_time -= updateImagesFetchTextures(max_time);
  772. // Update the new textures that must be created in the main thread.
  773. max_time = llmax(max_time, min_time);
  774. updateImagesCreateTextures(max_time);
  775. if (!mDirtyTextureList.empty())
  776. {
  777. LL_FAST_TIMER(FTM_IMAGE_MARK_DIRTY);
  778. gPipeline.dirtyPoolObjectTextures(mDirtyTextureList);
  779. mDirtyTextureList.clear();
  780. }
  781. {
  782. LL_FAST_TIMER(FTM_IMAGE_CALLBACKS);
  783. bool didone = false;
  784. for (callback_list_t::iterator iter = mCallbackList.begin(),
  785. end = mCallbackList.end();
  786. iter != end; )
  787. {
  788. // Trigger loaded callbacks on local textures immediately
  789. LLViewerFetchedTexture* image = *iter++;
  790. if (!image->getUrl().empty())
  791. {
  792. // Do stuff to handle callbacks, update priorities, etc.
  793. didone = image->doLoadedCallbacks();
  794. }
  795. else if (!didone)
  796. {
  797. // Do stuff to handle callbacks, update priorities, etc.
  798. didone = image->doLoadedCallbacks();
  799. }
  800. }
  801. }
  802. updateImagesUpdateStats();
  803. // Update the main work queue if needed. HB
  804. if (can_queue && !gMainloopWorkp->empty())
  805. {
  806. static auto one_ms = std::chrono::milliseconds(1);
  807. size_t remaining = 0;
  808. gMainloopWorkp->runFor(one_ms, &remaining);
  809. LLViewerFetchedTexture::sImageThreadQueueSize = remaining;
  810. }
  811. else
  812. {
  813. LLViewerFetchedTexture::sImageThreadQueueSize = 0;
  814. }
  815. }
  816. void LLViewerTextureList::clearFetchingRequests()
  817. {
  818. if (!gTextureFetchp || !gTextureFetchp->getNumRequests())
  819. {
  820. return;
  821. }
  822. uuid_list_t deleted_ids = gTextureFetchp->deleteAllRequests();
  823. for (priority_list_t::iterator iter = mImageList.begin(),
  824. end = mImageList.end();
  825. iter != end; ++iter)
  826. {
  827. LLViewerFetchedTexture* image = *iter;
  828. if (image && deleted_ids.count(image->getID()))
  829. {
  830. image->requestWasDeleted();
  831. }
  832. }
  833. }
  834. // Updates the decode priority for N images each frame
  835. void LLViewerTextureList::updateImagesDecodePriorities()
  836. {
  837. LL_FAST_TIMER(FTM_IMAGE_UPDATE_PRIO);
  838. // This algorithm ensures that old (unused) NO_DELETE textures are
  839. // re-ACTIVATEd, so to free up the VRAM. HB
  840. static LLCachedControl<U32> min_clean_delay(gSavedSettings,
  841. "StaleGLImageCleanupMinDelay");
  842. static LLCachedControl<U32> max_clean_delay(gSavedSettings,
  843. "StaleGLImageCleanupMaxDelay");
  844. if (min_clean_delay) // Disabled when set to 0
  845. {
  846. F32 min_cleaning_delay = llmin((F32)min_clean_delay, 30.f);
  847. F32 max_cleaning_delay = 999999.f; // No max delay by default.
  848. if (max_clean_delay)
  849. {
  850. max_cleaning_delay = llmax((F32)max_clean_delay,
  851. min_cleaning_delay);
  852. }
  853. // Still clean up every now and then, when we have a high pressure on
  854. // texture memory.
  855. else if (LLViewerTexture::sDesiredDiscardBias >= 3.f)
  856. {
  857. max_cleaning_delay = llmin(10.f * min_cleaning_delay, 60.f);
  858. }
  859. F32 last_cleaning_age = gFrameTimeSeconds - mLastGLImageCleaning;
  860. if ((mFlushOldImages || last_cleaning_age > max_cleaning_delay) &&
  861. (last_cleaning_age > min_cleaning_delay ||
  862. LLViewerTexture::sDesiredDiscardBias >= 4.5f))
  863. {
  864. mLastGLImageCleaning = gFrameTimeSeconds;
  865. U32 activated = LLImageGL::activateStaleTextures();
  866. if (activated)
  867. {
  868. LL_DEBUGS("TextureCleanup") << "Reactivated " << activated
  869. << " staled NO_DELETE textures."
  870. << LL_ENDL;
  871. }
  872. }
  873. }
  874. static LLCachedControl<U32> boost_after_tp(gSavedSettings,
  875. "TextureFetchBoostTimeAfterTP");
  876. static LLCachedControl<bool> boost_with_speed(gSavedSettings,
  877. "TextureFetchBoostWithSpeed");
  878. static LLCachedControl<bool> boost_with_fetches(gSavedSettings,
  879. "TextureFetchBoostWithFetches");
  880. static LLCachedControl<F32> high_prio_factor(gSavedSettings,
  881. "TextureFetchBoostHighPrioFactor");
  882. static LLCachedControl<U32> fetch_ratio(gSavedSettings,
  883. "TextureFetchBoostRatioPerFetch");
  884. static LLCachedControl<U32> updates_per_sec(gSavedSettings,
  885. "TextureFetchUpdatePrioPerSec");
  886. static LLCachedControl<U32> max_high_prio(gSavedSettings,
  887. "TextureFetchUpdateHighPriority");
  888. static LLCachedControl<U32> max_updates(gSavedSettings,
  889. "TextureFetchUpdateMaxMediumPriority");
  890. static LLCachedControl<U32> min_updates(gSavedSettings,
  891. "TextureFetchUpdateMinMediumPriority");
  892. static LLCachedControl<F32> upd_ratio(gSavedSettings,
  893. "TextureUpdateBoostRatioPerDiscard");
  894. // When showing the progress view, reset image last seen timer to avoid
  895. // removing prefetched textures too soon.
  896. bool reset_timer = gViewerWindowp && gViewerWindowp->getShowProgress();
  897. // Note: do not boost textures decoding in low memory conditions, to avoid
  898. // a yo-yo effect with discard bias and the ensuing constant redecoding. HB
  899. F32 factor = 1.f;
  900. if (!mFlushOldImages && !LLViewerTexture::inLowMemCondition())
  901. {
  902. if (gFrameTimeSeconds - sLastTeleportTime < (F32)boost_after_tp)
  903. {
  904. factor = 4.f;
  905. }
  906. else
  907. {
  908. if (boost_with_speed)
  909. {
  910. F32 cam_moving_speed = gViewerCamera.getAverageSpeed();
  911. F32 cam_angular_speed = gViewerCamera.getAverageAngularSpeed();
  912. factor = llmax(0.25f * cam_moving_speed,
  913. 2.f * cam_angular_speed - 1) + 1.f;
  914. factor = llmin(factor, 4.f);
  915. }
  916. U32 num_fetches = gTextureFetchp->getApproxNumRequests();
  917. if (boost_with_fetches && fetch_ratio)
  918. {
  919. factor = llclamp(F32(num_fetches) / F32(fetch_ratio),
  920. factor, 4.f);
  921. }
  922. }
  923. }
  924. sFetchingBoostFactor = factor;
  925. F32 update_priority_per_sec = (F32)updates_per_sec * factor;
  926. mUpdateHighPriority = (F32)max_high_prio * factor *
  927. llclamp((F32)high_prio_factor, 1.f, 4.f);
  928. mUpdateMaxMediumPriority = (F32)max_updates * factor;
  929. mUpdateMinMediumPriority = (F32)min_updates * factor;
  930. // Target between update_priority_per_sec and upd_ratio/2+1 times that
  931. // number of textures per second, depending on discard bias (the highest
  932. // the bias, the more textures we check so to delete unused ones faster).
  933. // HB
  934. F32 max_update_count = llclamp(update_priority_per_sec, 256.f, 4096.f);
  935. F32 uratio = llclamp((F32)upd_ratio, 0.f, 1.f) * 0.5f;
  936. max_update_count = (max_update_count * gFrameIntervalSeconds + 1.f) *
  937. (1.f + LLViewerTexture::sDesiredDiscardBias * uratio);
  938. S32 map_size = mUUIDMap.size();
  939. S32 update_counter = llmin((S32)max_update_count, map_size);
  940. sUpdatedThisFrame += update_counter;
  941. // Compute the max inactive time, based on the discard bias level (the
  942. // higher that level, the sooner unused textures are flushed so to free
  943. // memory faster).
  944. static LLCachedControl<U32> timeout(gSavedSettings,
  945. "TextureLazyFlushTimeout");
  946. F32 max_inactive_time =
  947. llmax(10.f,
  948. (F32)timeout /
  949. (1.f + LLViewerTexture::sDesiredDiscardBias * 0.5f));
  950. uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID);
  951. while ((update_counter-- > 0 || (mFlushOldImages && map_size-- > 0)) &&
  952. !mUUIDMap.empty())
  953. {
  954. if (iter == mUUIDMap.end())
  955. {
  956. iter = mUUIDMap.begin();
  957. }
  958. LLPointer<LLViewerFetchedTexture> imagep = iter->second;
  959. if (imagep.isNull())
  960. {
  961. llwarns << "NULL texture pointer found in list for texture Id: "
  962. << iter->first << ". Removing." << llendl;
  963. iter = mUUIDMap.erase(iter);
  964. --map_size;
  965. continue;
  966. }
  967. mLastUpdateUUID = iter++->first;
  968. // Flush formatted images using a lazy flush
  969. F32 last_referenced = 0.f;
  970. if (!reset_timer)
  971. {
  972. last_referenced = imagep->getElapsedLastReferenceTime();
  973. }
  974. // 1 for mImageList, 1 for mUUIDMap, 1 for local reference:
  975. constexpr S32 MIN_REFS = 3;
  976. S32 num_refs = imagep->getNumRefs();
  977. if (num_refs <= MIN_REFS)
  978. {
  979. if (last_referenced > max_inactive_time * 0.5f)
  980. {
  981. if (imagep->hasFetcher())
  982. {
  983. LL_DEBUGS("TextureCleanup") << "Removing stale fetcher for texture: "
  984. << imagep->getID()
  985. << LL_ENDL;
  986. gTextureFetchp->deleteRequest(imagep->getID());
  987. }
  988. // Remove the unused image from the image list
  989. deleteImage(imagep);
  990. imagep = NULL; // Should destroy the image
  991. }
  992. continue;
  993. }
  994. if (imagep->hasSavedRawImage() &&
  995. imagep->getElapsedLastReferencedSavedRawImageTime() >
  996. max_inactive_time)
  997. {
  998. imagep->destroySavedRawImage();
  999. }
  1000. if (imagep->isDeleted())
  1001. {
  1002. continue;
  1003. }
  1004. if (imagep->isDeletionCandidate())
  1005. {
  1006. if (imagep->destroyTexture())
  1007. {
  1008. continue;
  1009. }
  1010. // Cannot delete this image since it is actually waiting for GL
  1011. // image creation. Setting it INACTIVE (setActive() now, then
  1012. // setInactive() below). HB
  1013. LL_DEBUGS("TextureCleanup") << "Texture " << imagep->getID()
  1014. << " could not be deleted. Setting INACTIVE."
  1015. << LL_ENDL;
  1016. imagep->setActive();
  1017. }
  1018. else if (!reset_timer && imagep->isInactive())
  1019. {
  1020. if (last_referenced > max_inactive_time)
  1021. {
  1022. imagep->setDeletionCandidate();
  1023. }
  1024. continue;
  1025. }
  1026. // Images are often indirectly set NO_DELETE and this prevents them
  1027. // from being removed from memory while they are not in use any more.
  1028. // Let's make them active again to allow removal when actually needed.
  1029. // HB
  1030. else if (last_referenced > max_inactive_time && imagep->isNoDelete())
  1031. {
  1032. U32 boost_level = imagep->getBoostLevel();
  1033. // Never touch textures used by the UI, map, media, bumps, etc...
  1034. if (boost_level < LLGLTexture::BOOST_UI &&
  1035. // ... neither sculpties.
  1036. boost_level != LLGLTexture::BOOST_SCULPTED)
  1037. {
  1038. LL_DEBUGS("TextureCleanup") << "Setting old NO_DELETE texture "
  1039. << imagep->getID() << " ACTIVE."
  1040. << LL_ENDL;
  1041. imagep->forceActive();
  1042. }
  1043. }
  1044. imagep->resetLastReferencedTime();
  1045. // Set texture state to INACTIVE, if currently ACTIVE.
  1046. imagep->setInactive();
  1047. if (!imagep->isInImageList())
  1048. {
  1049. continue;
  1050. }
  1051. if (update_counter >= 0 && !mFlushOldImages)
  1052. {
  1053. imagep->processTextureStats();
  1054. F32 old_priority = imagep->getDecodePriority();
  1055. F32 old_priority_test = llmax(old_priority, 0.f);
  1056. F32 decode_priority = imagep->calcDecodePriority();
  1057. F32 decode_priority_test = llmax(decode_priority, 0.f);
  1058. // Ignore < 20% difference
  1059. if (decode_priority_test < old_priority_test * .8f ||
  1060. decode_priority_test > old_priority_test * 1.25f)
  1061. {
  1062. mImageList.erase(imagep);
  1063. imagep->setDecodePriority(decode_priority);
  1064. // Do not use imagep after this call ! HB
  1065. mImageList.emplace(std::move(imagep));
  1066. }
  1067. }
  1068. }
  1069. mFlushOldImages = false;
  1070. }
  1071. // Created GL textures for all textures that need them (images which have been
  1072. // decoded, but have not been pushed into GL).
  1073. F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
  1074. {
  1075. if (gGLManager.mIsDisabled)
  1076. {
  1077. return 0.f;
  1078. }
  1079. LL_FAST_TIMER(FTM_IMAGE_CREATE);
  1080. LLTimer create_timer;
  1081. image_list_t::iterator enditer = mCreateTextureList.begin();
  1082. for (image_list_t::iterator iter = mCreateTextureList.begin(),
  1083. end = mCreateTextureList.end();
  1084. iter != end; )
  1085. {
  1086. image_list_t::iterator curiter = iter++;
  1087. enditer = iter;
  1088. LLViewerFetchedTexture* imagep = *curiter;
  1089. imagep->createTexture();
  1090. imagep->postCreateTexture();
  1091. if (create_timer.getElapsedTimeF32() > max_time)
  1092. {
  1093. break;
  1094. }
  1095. }
  1096. mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
  1097. return create_timer.getElapsedTimeF32();
  1098. }
  1099. void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
  1100. {
  1101. if (!imagep)
  1102. {
  1103. return;
  1104. }
  1105. if (imagep->isInImageList())
  1106. {
  1107. removeImageFromList(imagep);
  1108. }
  1109. imagep->processTextureStats();
  1110. F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority();
  1111. imagep->setDecodePriority(decode_priority);
  1112. addImageToList(imagep);
  1113. }
  1114. F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
  1115. {
  1116. LL_FAST_TIMER(FTM_IMAGE_FETCH);
  1117. LLTimer image_op_timer;
  1118. // Update fetch for N images each frame
  1119. static LLCachedControl<F32> threshold(gSavedSettings,
  1120. "TextureFetchUpdatePriorityThreshold");
  1121. bool skip_low_prio = (F32)threshold > 0.f;
  1122. S32 max_priority_count = llmin((S32)(mUpdateHighPriority *
  1123. mUpdateHighPriority *
  1124. gFrameIntervalSeconds) + 1,
  1125. (S32)mUpdateHighPriority);
  1126. max_priority_count = llmin(max_priority_count, (S32)mImageList.size());
  1127. S32 total_update_count = mUUIDMap.size();
  1128. S32 max_update_count = llmin((S32)(mUpdateMaxMediumPriority *
  1129. mUpdateMaxMediumPriority *
  1130. gFrameIntervalSeconds) + 1,
  1131. (S32)mUpdateMaxMediumPriority);
  1132. max_update_count = llmin(max_update_count, total_update_count);
  1133. // max_high_prio high priority entries
  1134. typedef std::vector<LLViewerFetchedTexture*> entries_list_t;
  1135. static entries_list_t entries;
  1136. entries.clear();
  1137. entries.reserve(max_priority_count);
  1138. S32 update_counter = max_priority_count;
  1139. priority_list_t::iterator iter1 = mImageList.begin();
  1140. while (update_counter-- > 0)
  1141. {
  1142. entries.push_back(*iter1++);
  1143. }
  1144. // max_update_count cycled entries
  1145. static U32 skipped = 0;
  1146. update_counter = max_update_count;
  1147. if (update_counter > 0)
  1148. {
  1149. uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
  1150. while (update_counter > 0 && total_update_count-- > 0)
  1151. {
  1152. if (iter2 == mUUIDMap.end())
  1153. {
  1154. iter2 = mUUIDMap.begin();
  1155. }
  1156. LLViewerFetchedTexture* imagep = iter2->second;
  1157. ++iter2;
  1158. // Skip the textures where there is really nothing to do so to give
  1159. // some times to others. Also skip the texture if it is already in
  1160. // the high prio set.
  1161. if (skip_low_prio && imagep->getDecodePriority() <= threshold &&
  1162. !imagep->hasFetcher())
  1163. {
  1164. ++skipped;
  1165. }
  1166. else
  1167. {
  1168. entries.push_back(imagep);
  1169. --update_counter;
  1170. }
  1171. }
  1172. }
  1173. S32 min_update_count = llmin((S32)mUpdateMinMediumPriority,
  1174. (S32)(entries.size() - max_priority_count));
  1175. S32 min_count = max_priority_count + min_update_count;
  1176. LLViewerFetchedTexture* imagep = NULL;
  1177. for (U32 i = 0, count = entries.size(); i < count; ++i)
  1178. {
  1179. imagep = entries[i];
  1180. imagep->updateFetch();
  1181. if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time)
  1182. {
  1183. break;
  1184. }
  1185. --min_count;
  1186. }
  1187. if (imagep && min_count <= min_update_count)
  1188. {
  1189. mLastFetchUUID = imagep->getID();
  1190. }
  1191. // Report the number of skipped low priority texture updates, but do so in
  1192. // a non-spammy way (once a second, when the corresponding debug flag is
  1193. // set).
  1194. static F32 last_report = 0.f;
  1195. if (skipped && gFrameTimeSeconds - last_report > 1.f)
  1196. {
  1197. LL_DEBUGS("ViewerTexture") << "Skipped " << skipped
  1198. << " low priority textures update fetches."
  1199. << LL_ENDL;
  1200. skipped = 0;
  1201. last_report = gFrameTimeSeconds;
  1202. }
  1203. return image_op_timer.getElapsedTimeF32();
  1204. }
  1205. void LLViewerTextureList::updateImagesUpdateStats()
  1206. {
  1207. LL_FAST_TIMER(FTM_IMAGE_STATS);
  1208. if (mForceResetTextureStats)
  1209. {
  1210. for (priority_list_t::iterator iter = mImageList.begin(),
  1211. end = mImageList.end();
  1212. iter != end; )
  1213. {
  1214. LLViewerFetchedTexture* imagep = *iter++;
  1215. imagep->resetTextureStats();
  1216. }
  1217. mForceResetTextureStats = false;
  1218. }
  1219. }
  1220. S32 LLViewerTextureList::decodeAllImages(F32 max_time)
  1221. {
  1222. LLTimer timer;
  1223. // Update texture stats and priorities
  1224. std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
  1225. for (priority_list_t::iterator iter = mImageList.begin(),
  1226. end = mImageList.end();
  1227. iter != end; )
  1228. {
  1229. LLViewerFetchedTexture* imagep = *iter++;
  1230. image_list.push_back(imagep);
  1231. imagep->setInImageList(false);
  1232. }
  1233. mImageList.clear();
  1234. for (std::vector<LLPointer<LLViewerFetchedTexture> >::iterator
  1235. iter = image_list.begin(), end = image_list.end();
  1236. iter != end; ++iter)
  1237. {
  1238. LLViewerFetchedTexture* imagep = *iter;
  1239. imagep->processTextureStats();
  1240. F32 decode_priority = imagep->calcDecodePriority();
  1241. imagep->setDecodePriority(decode_priority);
  1242. addImageToList(imagep);
  1243. }
  1244. image_list.clear();
  1245. // Update fetch (decode)
  1246. for (priority_list_t::iterator iter = mImageList.begin(),
  1247. end = mImageList.end();
  1248. iter != end; )
  1249. {
  1250. LLViewerFetchedTexture* imagep = *iter++;
  1251. imagep->updateFetch();
  1252. }
  1253. // Run threads
  1254. bool can_queue = LLImageGLThread::sEnabled && gMainloopWorkp;
  1255. S32 fetch_pending = 0;
  1256. do
  1257. {
  1258. // Un-pauses the texture cache thread
  1259. gTextureCachep->update();
  1260. // Un-pauses the texture fetch thread
  1261. fetch_pending = gTextureFetchp->update();
  1262. // Service the threaded work queues
  1263. if (can_queue)
  1264. {
  1265. static auto one_ms = std::chrono::milliseconds(1);
  1266. size_t remaining = 0;
  1267. gMainloopWorkp->runFor(one_ms, &remaining);
  1268. fetch_pending += remaining;
  1269. LLViewerFetchedTexture::sImageThreadQueueSize = remaining;
  1270. }
  1271. }
  1272. while (fetch_pending && timer.getElapsedTimeF32() < max_time);
  1273. // Update fetch again
  1274. for (priority_list_t::iterator iter = mImageList.begin(),
  1275. end = mImageList.end();
  1276. iter != end; )
  1277. {
  1278. LLViewerFetchedTexture* imagep = *iter++;
  1279. imagep->updateFetch();
  1280. }
  1281. max_time -= timer.getElapsedTimeF32();
  1282. max_time = llmax(max_time, 0.1f);
  1283. F32 create_time = updateImagesCreateTextures(max_time);
  1284. LL_DEBUGS("ViewerTexture") << "decodeAllImages() took "
  1285. << timer.getElapsedTimeF32()
  1286. << " seconds - fetch_pending = "
  1287. << fetch_pending << " - create_time = "
  1288. << create_time << LL_ENDL;
  1289. return fetch_pending;
  1290. }
  1291. bool LLViewerTextureList::createUploadFile(const std::string& filename,
  1292. const std::string& out_filename,
  1293. U8 codec, bool* is_2k_texturep)
  1294. {
  1295. // First, load the image.
  1296. LLPointer<LLImageRaw> raw_image = new LLImageRaw;
  1297. switch (codec)
  1298. {
  1299. case IMG_CODEC_BMP:
  1300. {
  1301. LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
  1302. if (!bmp_image->load(filename))
  1303. {
  1304. return false;
  1305. }
  1306. if (!bmp_image->decode(raw_image))
  1307. {
  1308. return false;
  1309. }
  1310. break;
  1311. }
  1312. case IMG_CODEC_TGA:
  1313. {
  1314. LLPointer<LLImageTGA> tga_image = new LLImageTGA;
  1315. if (!tga_image->load(filename))
  1316. {
  1317. return false;
  1318. }
  1319. if (!tga_image->decode(raw_image))
  1320. {
  1321. return false;
  1322. }
  1323. if (tga_image->getComponents() != 3 &&
  1324. tga_image->getComponents() != 4)
  1325. {
  1326. tga_image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
  1327. return false;
  1328. }
  1329. break;
  1330. }
  1331. case IMG_CODEC_JPEG:
  1332. {
  1333. LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
  1334. if (!jpeg_image->load(filename))
  1335. {
  1336. return false;
  1337. }
  1338. if (!jpeg_image->decode(raw_image))
  1339. {
  1340. return false;
  1341. }
  1342. break;
  1343. }
  1344. case IMG_CODEC_PNG:
  1345. {
  1346. LLPointer<LLImagePNG> png_image = new LLImagePNG;
  1347. if (!png_image->load(filename))
  1348. {
  1349. return false;
  1350. }
  1351. if (!png_image->decode(raw_image))
  1352. {
  1353. return false;
  1354. }
  1355. break;
  1356. }
  1357. default:
  1358. return false;
  1359. }
  1360. LLPointer<LLImageJ2C> j2cp = convertToUploadFile(raw_image);
  1361. if (j2cp.isNull() || !j2cp->save(out_filename))
  1362. {
  1363. llinfos << "Could not create output file " << out_filename << llendl;
  1364. return false;
  1365. }
  1366. if (is_2k_texturep)
  1367. {
  1368. constexpr U32 tex_1k_area = 1024 * 1024;
  1369. U32 tex_area = j2cp->getWidth() * j2cp->getHeight();
  1370. *is_2k_texturep = tex_area > tex_1k_area;
  1371. }
  1372. // Test to see if the encode and save worked.
  1373. LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
  1374. if (!integrity_test->loadAndValidate(out_filename))
  1375. {
  1376. llinfos << "Image: " << out_filename << " is corrupt." << llendl;
  1377. return false;
  1378. }
  1379. return true;
  1380. }
  1381. // WARNING: this method modifies the rawp image !
  1382. LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> rawp,
  1383. S32 max_dimentions,
  1384. bool force_lossless)
  1385. {
  1386. if (max_dimentions < 0)
  1387. {
  1388. max_dimentions = gMaxImageSizeDefault;
  1389. }
  1390. rawp->biasedScaleToPowerOfTwo(max_dimentions);
  1391. LLPointer<LLImageJ2C> j2cp = new LLImageJ2C();
  1392. j2cp->setRate(0.f);
  1393. constexpr S32 MAX_AREA = LL_IMAGE_REZ_LOSSLESS_CUTOFF *
  1394. LL_IMAGE_REZ_LOSSLESS_CUTOFF;
  1395. static LLCachedControl<bool> lossless(gSavedSettings, "LosslessJ2CUpload");
  1396. if (force_lossless ||
  1397. (lossless && rawp->getWidth() * rawp->getHeight() <= MAX_AREA))
  1398. {
  1399. j2cp->setReversible(true);
  1400. }
  1401. if (!j2cp->encode(rawp))
  1402. {
  1403. llwarns << "Failure to encode as a J2C image !" << llendl;
  1404. j2cp = NULL;
  1405. }
  1406. return j2cp;
  1407. }
  1408. // Returns min setting for TextureMemory (in MB)
  1409. //static
  1410. S32 LLViewerTextureList::getMinVideoRamSetting()
  1411. {
  1412. // System memory in MB (used to be clamped to 4096MB for 32 bits builds via
  1413. // a now removed getPhysicalMemoryKBClamped() call). HB
  1414. S32 system_ram = LLMemory::getPhysicalMemoryKB() >> 10;
  1415. // min texture mem sets to 64MB if total physical memory is more than
  1416. // 1.5GB, and 32MB otherwise.
  1417. return system_ram > 1500 ? 64 : 32;
  1418. }
  1419. // Returns max setting for TextureMemory (in MB)
  1420. //static
  1421. S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
  1422. {
  1423. S32 max_texmem;
  1424. U32 vram_manual_override = gSavedSettings.getU32("VRAMOverride");
  1425. // In %, for integer divisions later. HB
  1426. S32 multiplier = llclamp(100.f * gSavedSettings.getF32("TexMemMultiplier"),
  1427. 100.f, 200.f);
  1428. if (vram_manual_override > 32)
  1429. {
  1430. static U32 last_override = 0;
  1431. if (vram_manual_override != last_override)
  1432. {
  1433. last_override = vram_manual_override;
  1434. llwarns << "Overriding the detected VRAM amount with the VRAMOverride debug settings: "
  1435. << vram_manual_override << "MB of VRAM assumed." << llendl;
  1436. }
  1437. max_texmem = (multiplier * vram_manual_override) / 100;
  1438. }
  1439. else if (gGLManager.mTexVRAM)
  1440. {
  1441. max_texmem = gGLManager.mTexVRAM;
  1442. // Treat any card with < 32 MB (shudder) as having 32 MB; it is going
  1443. // to be swapping constantly regardless
  1444. max_texmem = llmax(max_texmem, getMinVideoRamSetting());
  1445. if (!get_recommended)
  1446. {
  1447. max_texmem = (multiplier * max_texmem) / 100;
  1448. }
  1449. }
  1450. else if (gGLManager.mVRAM)
  1451. {
  1452. // 75% of total VRAM at most for textures.
  1453. max_texmem = 3 * gGLManager.mVRAM / 4;
  1454. // Treat any card with < 32 MB (shudder) as having 32 MB; it is going
  1455. // to be swapping constantly regardless
  1456. max_texmem = llmax(max_texmem, getMinVideoRamSetting());
  1457. if (!get_recommended)
  1458. {
  1459. max_texmem = (multiplier * max_texmem) / 100;
  1460. }
  1461. }
  1462. else
  1463. {
  1464. if (!get_recommended || gSavedSettings.getBool("NoHardwareProbe"))
  1465. {
  1466. max_texmem = 512;
  1467. }
  1468. else
  1469. {
  1470. max_texmem = 128;
  1471. }
  1472. llwarns << "VRAM amount not detected, defaulting to " << max_texmem
  1473. << " MB" << llendl;
  1474. }
  1475. // System memory in MB (used to be clamped to 4096MB for 32 bits builds via
  1476. // a now removed getPhysicalMemoryKBClamped() call). HB
  1477. S32 system_ram = LLMemory::getPhysicalMemoryKB() >> 10;
  1478. if (get_recommended)
  1479. {
  1480. max_texmem = llmin(max_texmem, system_ram / 2);
  1481. #if 0 // *TODO, maybe: further clamp down to 4096MB ?
  1482. max_texmem = llmin(max_texmem, 4096);
  1483. #endif
  1484. llinfos << "Recommended max texture RAM: " << max_texmem
  1485. << " MB - System RAM: " << system_ram << " MB."<< llendl;
  1486. }
  1487. else
  1488. {
  1489. max_texmem = llmin(max_texmem, system_ram);
  1490. llinfos << "Usable texture RAM: " << max_texmem
  1491. << " MB - System RAM: " << system_ram << " MB."<< llendl;
  1492. }
  1493. return max_texmem;
  1494. }
  1495. constexpr S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB
  1496. constexpr S32 MIN_MEM_FOR_NON_TEXTURE = 512; //MB
  1497. void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
  1498. {
  1499. // Initialize the image pipeline VRAM settings
  1500. S32 cur_mem = gSavedSettings.getS32("TextureMemory");
  1501. S32 default_mem = getMaxVideoRamSetting(true); // Recommended default
  1502. if (mem == 0)
  1503. {
  1504. mem = cur_mem > 0 ? cur_mem : default_mem;
  1505. }
  1506. else if (mem < 0)
  1507. {
  1508. mem = default_mem;
  1509. }
  1510. // Limit the texture memory to a multiple of the default if we have found
  1511. // some cards to behave poorly otherwise
  1512. mem = llmin(mem, default_mem);
  1513. // When asking for default, keep things reasonnable on modern gaphics cards
  1514. // with more VRAM than what the viewer will ever need or be able to cope
  1515. // with (see the MaxBoundTexMem limiting below). HB
  1516. if (cur_mem <= 0 && mem > 3072)
  1517. {
  1518. mem = 3072;
  1519. }
  1520. S32 max_vram = getMaxVideoRamSetting();
  1521. mem = llclamp(mem, getMinVideoRamSetting(), max_vram);
  1522. if (mem != cur_mem)
  1523. {
  1524. gSavedSettings.setS32("TextureMemory", mem);
  1525. // At this point the setting listener re-entered this method already.
  1526. return;
  1527. }
  1528. // *TODO: set available resident texture mem based on use by other
  1529. // subsystems currently max(12MB, llmin(VRAM/4, 512)) assumed...
  1530. S32 vb_mem = mem;
  1531. S32 fb_mem = llclamp(vb_mem / 4, VIDEO_CARD_FRAMEBUFFER_MEM, 512);
  1532. mMaxResidentTexMemInMegaBytes = vb_mem - fb_mem; // in MB
  1533. // Limit the total amount of textures to 1.25 * max_vram
  1534. mMaxTotalTextureMemInMegaBytes = llmin(2 * mMaxResidentTexMemInMegaBytes,
  1535. (S32)(5 * max_vram / 4));
  1536. S32 max_bound = llclamp((S32)gSavedSettings.getU32("MaxBoundTexMem"),
  1537. 512, 4096);
  1538. if (mMaxResidentTexMemInMegaBytes > max_bound)
  1539. {
  1540. // Limit the amount of resident (GL bound) textures to something sane:
  1541. // not doing so causes HUGE and NASTY slow downs in some conditions,
  1542. // such as when rotating the camera in texture-heavy environments. HB
  1543. mMaxResidentTexMemInMegaBytes = max_bound;
  1544. }
  1545. // System memory in MB (used to be clamped to 4096MB for 32 bits builds via
  1546. // a now removed getPhysicalMemoryKBClamped() call). HB
  1547. S32 system_ram = LLMemory::getPhysicalMemoryKB() >> 10;
  1548. // Minimum memory reserved for non-texture use. If system_raw >= 1GB then
  1549. // reserve at least 512MB for non-texture use, otherwise reserve half of
  1550. // the system_ram for non-texture use.
  1551. S32 min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE);
  1552. if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem)
  1553. {
  1554. mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem;
  1555. }
  1556. llinfos << "Total usable VRAM: " << vb_mem << " MB"
  1557. << " - Usable frame buffers VRAM: " << fb_mem << " MB"
  1558. << " - Usable texture VRAM: " << vb_mem - fb_mem << " MB"
  1559. << " - Maximum total texture memory set to: "
  1560. << mMaxTotalTextureMemInMegaBytes << " MB"
  1561. << " - Maximum total GL bound texture memory set to: "
  1562. << mMaxResidentTexMemInMegaBytes << " MB"
  1563. << llendl;
  1564. }
  1565. // Receive image header, copy into image object and decompresses if this is a
  1566. // one-packet image.
  1567. //static
  1568. void LLViewerTextureList::receiveImageHeader(LLMessageSystem* msg, void**)
  1569. {
  1570. LL_FAST_TIMER(FTM_PROCESS_IMAGES);
  1571. char ip_string[256];
  1572. u32_to_ip_string(msg->getSenderIP(), ip_string);
  1573. U32 received_size;
  1574. if (msg->getReceiveCompressedSize())
  1575. {
  1576. received_size = msg->getReceiveCompressedSize();
  1577. }
  1578. else
  1579. {
  1580. received_size = msg->getReceiveSize();
  1581. }
  1582. gTextureList.sTextureBits += received_size * 8;
  1583. ++gTextureList.sTexturePackets;
  1584. LLUUID id;
  1585. msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
  1586. U8 codec;
  1587. msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec);
  1588. U16 packets;
  1589. msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets);
  1590. U32 totalbytes;
  1591. msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes);
  1592. S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
  1593. if (data_size > 0)
  1594. {
  1595. // This buffer gets saved off in the packet list
  1596. U8* data = new U8[data_size];
  1597. msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data,
  1598. data_size);
  1599. LLViewerFetchedTexture* image =
  1600. LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true,
  1601. LLGLTexture::BOOST_NONE,
  1602. LLViewerTexture::LOD_TEXTURE);
  1603. if (!image ||
  1604. !gTextureFetchp->receiveImageHeader(msg->getSender(), id, codec,
  1605. packets, totalbytes, data_size,
  1606. data))
  1607. {
  1608. delete[] data;
  1609. }
  1610. }
  1611. else if (data_size < 0)
  1612. {
  1613. llwarns << "Invalid image header chunk size: " << data_size << llendl;
  1614. }
  1615. }
  1616. // Receives image packet, copy into image object, checks if all packets
  1617. // received, decompresses if so.
  1618. //static
  1619. void LLViewerTextureList::receiveImagePacket(LLMessageSystem* msg, void**)
  1620. {
  1621. LL_FAST_TIMER(FTM_PROCESS_IMAGES);
  1622. char ip_string[256];
  1623. u32_to_ip_string(msg->getSenderIP(), ip_string);
  1624. U32 received_size;
  1625. if (msg->getReceiveCompressedSize())
  1626. {
  1627. received_size = msg->getReceiveCompressedSize();
  1628. }
  1629. else
  1630. {
  1631. received_size = msg->getReceiveSize();
  1632. }
  1633. gTextureList.sTextureBits += received_size * 8;
  1634. ++gTextureList.sTexturePackets;
  1635. LLUUID id;
  1636. msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
  1637. U16 packet_num;
  1638. msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num);
  1639. S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
  1640. if (data_size > 0)
  1641. {
  1642. if (data_size > MTUBYTES)
  1643. {
  1644. llerrs << "Image data chunk too large: " << data_size << " bytes"
  1645. << llendl;
  1646. }
  1647. U8* data = new U8[data_size];
  1648. msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data,
  1649. data_size);
  1650. LLViewerFetchedTexture* image =
  1651. LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true,
  1652. LLGLTexture::BOOST_NONE,
  1653. LLViewerTexture::LOD_TEXTURE);
  1654. if (!image ||
  1655. !gTextureFetchp->receiveImagePacket(msg->getSender(), id,
  1656. packet_num, data_size, data))
  1657. {
  1658. delete[] data;
  1659. }
  1660. }
  1661. else if (data_size < 0)
  1662. {
  1663. llwarns << "Invalid image data chunk size: " << data_size << llendl;
  1664. }
  1665. }
  1666. // We have been that the asset server does not contain the requested image id.
  1667. //static
  1668. void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem* msg,
  1669. void**)
  1670. {
  1671. LL_FAST_TIMER(FTM_PROCESS_IMAGES);
  1672. LLUUID image_id;
  1673. msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id);
  1674. LLViewerFetchedTexture* image = gTextureList.findImage(image_id);
  1675. if (image)
  1676. {
  1677. image->setIsMissingAsset();
  1678. }
  1679. }
  1680. // Explicitly cleanup resources, as this is a singleton class with process
  1681. // lifetime so ability to perform std::map operations in destructor is not
  1682. // guaranteed.
  1683. void LLUIImageList::cleanUp()
  1684. {
  1685. mUIImages.clear();
  1686. mUITextureList.clear();
  1687. }
  1688. LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id)
  1689. {
  1690. // Look for existing image, using the UUID as an image name
  1691. uuid_ui_image_map_t::iterator it = mUIImages.find(image_id.asString());
  1692. if (it != mUIImages.end())
  1693. {
  1694. LL_DEBUGS("GetUIImageCalls") << "Requested UI image UUID: " << image_id
  1695. << LL_ENDL;
  1696. return it->second;
  1697. }
  1698. return loadUIImageByID(image_id);
  1699. }
  1700. LLUIImagePtr LLUIImageList::getUIImage(const std::string& name)
  1701. {
  1702. // Look for existing image
  1703. uuid_ui_image_map_t::iterator it = mUIImages.find(name);
  1704. if (it != mUIImages.end())
  1705. {
  1706. LL_DEBUGS("GetUIImageCalls") << "Requested UI image: " << name
  1707. << LL_ENDL;
  1708. return it->second;
  1709. }
  1710. return loadUIImageByName(name, name);
  1711. }
  1712. LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name,
  1713. const std::string& filename,
  1714. bool use_mips,
  1715. const LLRect& scale_rect)
  1716. {
  1717. LL_DEBUGS("GetUIImageCalls") << "Loaded UI image: " << name << LL_ENDL;
  1718. LLViewerFetchedTexture* imagep =
  1719. LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO,
  1720. LLGLTexture::BOOST_UI);
  1721. return loadUIImage(imagep, name, use_mips, scale_rect);
  1722. }
  1723. LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, bool use_mips,
  1724. const LLRect& scale_rect)
  1725. {
  1726. LL_DEBUGS("GetUIImageCalls") << "Loaded UI image UUID: " << id << LL_ENDL;
  1727. LLViewerFetchedTexture* imagep =
  1728. LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, MIPMAP_NO,
  1729. LLGLTexture::BOOST_UI);
  1730. return loadUIImage(imagep, id.asString(), use_mips, scale_rect);
  1731. }
  1732. LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep,
  1733. const std::string& name, bool use_mips,
  1734. const LLRect& scale_rect)
  1735. {
  1736. if (!imagep) return NULL;
  1737. imagep->setBoostLevel(LLGLTexture::BOOST_UI);
  1738. imagep->setAddressMode(LLTexUnit::TAM_CLAMP);
  1739. // Do not compress UI images
  1740. imagep->getGLImage()->setAllowCompression(false);
  1741. LLUIImagePtr new_imagep = new LLUIImage(name, imagep);
  1742. mUIImages[name] = new_imagep;
  1743. mUITextureList.emplace_back(imagep);
  1744. #if 0 // LLGLTexture::ICON is not used in the Cool VL Viewer... HB
  1745. // Note: some other textures such as ICON also go through this flow to be
  1746. // fetched. But only UI textures need to set this callback.
  1747. if (imagep->getBoostLevel() == LLGLTexture::BOOST_UI)
  1748. #endif
  1749. {
  1750. LLUIImageLoadData* datap = new LLUIImageLoadData;
  1751. datap->mImageName = name;
  1752. datap->mImageScaleRegion = scale_rect;
  1753. imagep->setLoadedCallback(onUIImageLoaded, 0, false, false, datap,
  1754. NULL);
  1755. }
  1756. return new_imagep;
  1757. }
  1758. LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name,
  1759. const std::string& filename,
  1760. bool use_mips,
  1761. const LLRect& scale_rect)
  1762. {
  1763. // Look for existing image
  1764. uuid_ui_image_map_t::iterator found_it = mUIImages.find(name);
  1765. if (found_it != mUIImages.end())
  1766. {
  1767. // Image already loaded !
  1768. llerrs << "UI Image " << name << " already loaded." << llendl;
  1769. }
  1770. return loadUIImageByName(name, filename, use_mips, scale_rect);
  1771. }
  1772. //static
  1773. void LLUIImageList::onUIImageLoaded(bool success, LLViewerFetchedTexture* texp,
  1774. LLImageRaw*, LLImageRaw*,
  1775. S32 discard_level, bool is_final,
  1776. void* datap)
  1777. {
  1778. if (!success || !datap)
  1779. {
  1780. return;
  1781. }
  1782. LLUIImageLoadData* image_datap = (LLUIImageLoadData*)datap;
  1783. std::string ui_image_name = image_datap->mImageName;
  1784. LLRect scale_rect = image_datap->mImageScaleRegion;
  1785. if (is_final)
  1786. {
  1787. delete image_datap;
  1788. }
  1789. if (!texp || texp->getUrl().compare(0, 7, "file://") != 0)
  1790. {
  1791. return;
  1792. }
  1793. LLUIImageList* self = getInstance();
  1794. uuid_ui_image_map_t::iterator it = self->mUIImages.find(ui_image_name);
  1795. if (it == self->mUIImages.end())
  1796. {
  1797. return;
  1798. }
  1799. LLUIImagePtr imagep = it->second;
  1800. if (imagep.isNull())
  1801. {
  1802. return;
  1803. }
  1804. // For images grabbed from local files, apply clipping rectangle to restore
  1805. // original dimensions from power-of-2 gl image
  1806. F32 clip_x = (F32)texp->getOriginalWidth() / (F32)texp->getFullWidth();
  1807. F32 clip_y = (F32)texp->getOriginalHeight() / (F32)texp->getFullHeight();
  1808. imagep->setClipRegion(LLRectf(0.f, clip_y, clip_x, 0.f));
  1809. if (scale_rect == LLRect::null)
  1810. {
  1811. return;
  1812. }
  1813. F32 width_div = 1.f / (F32)imagep->getWidth();
  1814. F32 height_div = 1.f / (F32)imagep->getHeight();
  1815. imagep->setScaleRegion(LLRectf(llclamp((F32)scale_rect.mLeft * width_div,
  1816. 0.f, 1.f),
  1817. llclamp((F32)scale_rect.mTop * height_div,
  1818. 0.f, 1.f),
  1819. llclamp((F32)scale_rect.mRight * width_div,
  1820. 0.f, 1.f),
  1821. llclamp((F32)scale_rect.mBottom *
  1822. height_div,
  1823. 0.f, 1.f)));
  1824. }
  1825. bool LLUIImageList::initFromFile()
  1826. {
  1827. // Construct path to canonical textures.xml in default skin dir
  1828. std::string base_file_path = gDirUtil.getFullPath(LL_PATH_SKINS, "default",
  1829. "textures",
  1830. "textures.xml");
  1831. LLXMLNodePtr root;
  1832. if (!LLXMLNode::parseFile(base_file_path, root, NULL))
  1833. {
  1834. llwarns << "Unable to parse UI image list file " << base_file_path
  1835. << llendl;
  1836. return false;
  1837. }
  1838. if (!root->hasAttribute("version"))
  1839. {
  1840. llwarns << "No valid version number in UI image list file "
  1841. << base_file_path << llendl;
  1842. return false;
  1843. }
  1844. std::vector<std::string> paths;
  1845. // Path to current selected skin
  1846. paths.emplace_back(gDirUtil.getSkinDir() + LL_DIR_DELIM_STR + "textures" +
  1847. LL_DIR_DELIM_STR + "textures.xml");
  1848. // Path to user overrides on current skin
  1849. paths.emplace_back(gDirUtil.getUserSkinDir() + LL_DIR_DELIM_STR +
  1850. "textures" + LL_DIR_DELIM_STR + "textures.xml");
  1851. // Apply skinned xml files incrementally
  1852. for (std::vector<std::string>::iterator path_it = paths.begin();
  1853. path_it != paths.end(); ++path_it)
  1854. {
  1855. // Do not reapply base file to itself
  1856. if (!path_it->empty() && *path_it != base_file_path)
  1857. {
  1858. LLXMLNodePtr update_root;
  1859. if (LLXMLNode::parseFile(*path_it, update_root, NULL))
  1860. {
  1861. LLXMLNode::updateNode(root, update_root);
  1862. }
  1863. }
  1864. }
  1865. enum
  1866. {
  1867. PASS_DECODE_NOW,
  1868. PASS_DECODE_LATER,
  1869. NUM_PASSES
  1870. };
  1871. std::string file_name;
  1872. for (S32 pass = PASS_DECODE_NOW; pass < NUM_PASSES; ++pass)
  1873. {
  1874. LLXMLNodePtr child_nodep = root->getFirstChild();
  1875. while (child_nodep.notNull())
  1876. {
  1877. std::string image_name;
  1878. child_nodep->getAttributeString("name", image_name);
  1879. file_name = image_name; // Use as default file name
  1880. // Load high priority textures on first pass (to kick off decode)
  1881. bool preload = false;
  1882. child_nodep->getAttributeBool("preload", preload);
  1883. if (preload)
  1884. {
  1885. if (pass == PASS_DECODE_LATER)
  1886. {
  1887. child_nodep = child_nodep->getNextSibling();
  1888. continue;
  1889. }
  1890. }
  1891. else if (pass == PASS_DECODE_NOW)
  1892. {
  1893. child_nodep = child_nodep->getNextSibling();
  1894. continue;
  1895. }
  1896. child_nodep->getAttributeString("file_name", file_name);
  1897. bool use_mip_maps = false;
  1898. child_nodep->getAttributeBool("use_mips", use_mip_maps);
  1899. LLRect scale_rect;
  1900. child_nodep->getAttributeS32("scale_left", scale_rect.mLeft);
  1901. child_nodep->getAttributeS32("scale_right", scale_rect.mRight);
  1902. child_nodep->getAttributeS32("scale_bottom", scale_rect.mBottom);
  1903. child_nodep->getAttributeS32("scale_top", scale_rect.mTop);
  1904. preloadUIImage(image_name, file_name, use_mip_maps, scale_rect);
  1905. child_nodep = child_nodep->getNextSibling();
  1906. }
  1907. if (pass == PASS_DECODE_NOW && !gSavedSettings.getBool("NoPreload"))
  1908. {
  1909. gTextureList.decodeAllImages(10.f); // Decode preloaded images
  1910. }
  1911. }
  1912. return true;
  1913. }