llappviewer.cpp 137 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832
  1. /**
  2. * @file llappviewer.cpp
  3. * @brief The LLAppViewer class definitions
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewergpl$
  6. *
  7. * Copyright (c) 2007-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. #if LL_WINDOWS
  34. # include <share.h> // For _SH_DENYWR in initMarkerFile
  35. # include <stdio.h> // For sscanf()
  36. #else
  37. # include <sys/file.h> // For initMarkerFile support
  38. #endif
  39. #include "cef/dullahan.h" // For HB_DULLAHAN_EXTENDED
  40. #include "llappviewer.h"
  41. #include "llalertdialog.h"
  42. #include "llapp.h"
  43. #include "llassetstorage.h"
  44. #include "llaudioengine.h"
  45. #include "llaudiodecodemgr.h"
  46. #include "llbase64.h"
  47. #include "llbutton.h"
  48. #include "llcachename.h"
  49. #include "llcallbacklist.h"
  50. #include "llcombobox.h"
  51. #include "llcommandlineparser.h"
  52. #include "llconsole.h"
  53. #include "llcoproceduremanager.h"
  54. #include "lldir.h"
  55. #include "lldiriterator.h"
  56. #include "lldiskcache.h"
  57. #include "llerrorcontrol.h"
  58. #include "llexperiencecache.h"
  59. #include "llevents.h"
  60. #include "hbfileselector.h"
  61. #include "llfontfreetype.h"
  62. #include "llgl.h"
  63. #include "llimagedecodethread.h"
  64. #include "llimagej2c.h"
  65. #include "llinitdestroyclass.h"
  66. #include "llkeyframemotion.h"
  67. #include "llmd5.h"
  68. #include "llmimetypes.h"
  69. #include "llnotifications.h"
  70. #include "llparcel.h"
  71. #include "llpolymesh.h"
  72. #include "llprimitive.h"
  73. #include "llproxy.h"
  74. #include "llpumpio.h"
  75. #include "llrender.h"
  76. #include "llsdserialize.h"
  77. #include "llsettingstype.h"
  78. #include "llspellcheck.h"
  79. #include "llstatusbar.h"
  80. #include "llsys.h"
  81. #include "lltexteditor.h"
  82. #include "lltrans.h"
  83. #include "lluictrlfactory.h"
  84. #include "llurlhistory.h"
  85. #include "lluserauth.h"
  86. #include "llversionviewer.h"
  87. #include "llvertexbuffer.h"
  88. #include "llvolume.h"
  89. #include "llvolumemgr.h"
  90. #include "llwindow.h"
  91. #if LL_WINDOWS
  92. # include "llwindowwin32.h" // For gIgnoreHiDPIEvents
  93. #elif LL_LINUX
  94. # include "llwindowsdl.h" // For gUseFullDesktop
  95. #endif
  96. #if LL_DARWIN
  97. # include "llwindowmacosx.h" // For LLWindowMacOSX::sUseMultGL
  98. #endif
  99. #include "llworkqueue.h"
  100. #include "llworkerthread.h"
  101. #include "llxfermanager.h"
  102. #include "llxmlrpctransaction.h"
  103. #include "llxorcipher.h"
  104. #include "llagent.h"
  105. #include "llagentpilot.h"
  106. #if LL_LINUX
  107. # include "llappviewerlinux.h" // For pumpGlib()
  108. #endif
  109. #include "llavatartracker.h"
  110. #include "lldebugview.h"
  111. #include "lldrawpoolbump.h"
  112. #include "llenvironment.h"
  113. #include "lleventnotifier.h"
  114. #include "lleventpoll.h"
  115. #include "llfasttimerview.h" // For HBTracyProfiler
  116. #include "llfeaturemanager.h"
  117. #include "llflexibleobject.h"
  118. #include "hbfloaterareasearch.h"
  119. #include "hbfloaterbump.h"
  120. #include "llfloaterim.h"
  121. #include "llfloaterinventory.h"
  122. #include "llfloaterjoystick.h"
  123. #include "llfloatersnapshot.h"
  124. #include "llfloaterstats.h"
  125. #include "llfolderview.h"
  126. #include "llgesturemgr.h"
  127. #include "llgltfscenemanager.h"
  128. #include "llgridmanager.h"
  129. #include "llgroupmgr.h"
  130. #include "llgroupnotify.h"
  131. #include "llhoverview.h"
  132. #include "llhudeffectlookat.h"
  133. #include "llhudeffectspiral.h"
  134. #include "llhudmanager.h"
  135. #include "llimmgr.h"
  136. #include "llinventorymodelfetch.h"
  137. #include "lllocalbitmaps.h"
  138. #include "lllocalgltfmaterials.h"
  139. #include "llmaterialmgr.h"
  140. #include "llmeshrepository.h"
  141. #include "llmutelist.h"
  142. #include "llnotify.h"
  143. #include "llpanelworldmap.h"
  144. #include "llpipeline.h"
  145. //MK
  146. #include "mkrlinterface.h"
  147. //mk
  148. #include "llselectmgr.h"
  149. #include "llskinningutil.h"
  150. #include "llsky.h"
  151. #include "llslurl.h"
  152. #include "llstartup.h"
  153. #include "llstatusbar.h"
  154. #include "llsurface.h"
  155. #include "llsurfacepatch.h"
  156. #include "lltexturecache.h"
  157. #include "lltexturefetch.h"
  158. #include "lltoolbar.h"
  159. #include "lltoolmgr.h"
  160. #include "lltracker.h"
  161. #include "llurldispatcher.h"
  162. #include "llvieweraudio.h"
  163. #include "hbviewerautomation.h"
  164. #include "llviewercamera.h"
  165. #include "llviewercontrol.h"
  166. #include "llviewerdisplay.h"
  167. #include "llviewerjoystick.h"
  168. #include "llviewerkeyboard.h"
  169. #include "llviewermedia.h"
  170. #include "llviewermediafocus.h"
  171. #include "llviewermenu.h"
  172. #include "llviewermessage.h"
  173. #include "llviewerobjectlist.h"
  174. #include "llviewerparcelmedia.h"
  175. #include "llviewerparcelmgr.h"
  176. #include "llviewerpartsim.h"
  177. #include "llviewershadermgr.h"
  178. #include "llviewerstats.h"
  179. #include "llviewertextureanim.h"
  180. #include "llviewertexturelist.h"
  181. #include "llviewerthrottle.h"
  182. #include "llviewerwindow.h"
  183. #include "llvlmanager.h"
  184. #include "llvoavatarself.h"
  185. #include "llvocache.h"
  186. #include "llvoiceclient.h"
  187. #include "llvosky.h"
  188. #include "llvosurfacepatch.h"
  189. #include "llvotree.h"
  190. #include "llvovolume.h"
  191. #include "llvowlsky.h"
  192. #include "llweb.h"
  193. #include "llwlskyparammgr.h"
  194. #include "llwlwaterparammgr.h"
  195. #include "llworld.h"
  196. #include "llworldmap.h"
  197. #if LL_JEMALLOC
  198. # include "jemalloc/jemalloc.h"
  199. // We configure four general purpose arenas, plus the ones we will add for the
  200. // textures, the vertex buffers and the volumes/meshes. We also use transparent
  201. // huge pages, activate the background thread for memory purging (with decays
  202. // reduced to 100ms), and disable profiling by default. Note: you may override
  203. // these settings with an exported MALLOC_CONF environment variable; Debug and
  204. // RelWithDebInfo builds are linked with a jemalloc build supporting profiling,
  205. // and you may for example, enable memory leaks detection with:
  206. // export MALLOC_CONF="prof_leak:true,prof_final:true"
  207. // NOTE: disabled debug jemalloc build due to a crash bug occurring with it and
  208. // FMOD Studio.
  209. # if 0 // LL_DEBUG || LL_NO_FORCE_INLINE
  210. const char* malloc_conf = "narenas:4,thp:always,background_thread:true,dirty_decay_ms:500,muzzy_decay_ms:500,prof:false";
  211. # else // Release build: no profiling option available in jemalloc.
  212. const char* malloc_conf = "narenas:4,thp:always,background_thread:true,dirty_decay_ms:500,muzzy_decay_ms:500";
  213. # endif
  214. #endif
  215. // Global variables
  216. // The single viewer app.
  217. LLAppViewer* gAppViewerp = NULL;
  218. U64 gViewerVersionNumber; // In Mmmmbbbrrr form
  219. std::string gViewerVersionString; // In "Major.minor.branch.release" form
  220. std::string gViewerVersion; // In "viewer name M.m.b.r" form
  221. std::string gCurrentVersion; // In "viewer channel M.m.b.r" form
  222. F32 gSimLastTime; // Used in LLAppViewer::init and LLViewerStats::sendStats()
  223. F32 gSimFrames;
  224. std::string gSecondLife;
  225. std::string gWindowTitle;
  226. eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
  227. LLSD gDebugInfo;
  228. LLPumpIO* gServicePumpIOp = NULL;
  229. LLWorkQueue* gMainloopWorkp = NULL;
  230. S32 gExitCode = LLAppViewer::EXIT_OK;
  231. U32 gFrameCount = 0;
  232. // Number of frames that app window was in foreground:
  233. U32 gForegroundFrameCount = 0;
  234. U64 gFrameTime = 0;
  235. F32 gFrameTimeSeconds = 0.f;
  236. F32 gFrameIntervalSeconds = 0.f;
  237. F32 gFPSClamped = 30.f; // Pretend we start at target rate.
  238. // Time between adjacent checks to network for packets:
  239. F32 gFrameDT = 0.f;
  240. // gStartTime is "private", used only to calculate gFrameTimeSeconds:
  241. U64 gStartTime = 0;
  242. U32 gFrameSleepTime = 0;
  243. LLTimer gRenderStartTime;
  244. LLFrameTimer gForegroundTime;
  245. LLTimer gLogoutTimer;
  246. // This will be cut short by the LogoutReply msg:
  247. constexpr F32 LOGOUT_REQUEST_TIME = 6.f;
  248. F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
  249. bool gDisconnected = false;
  250. // Minimap scale in pixels per region
  251. // Used to restore texture state after a mode switch
  252. LLFrameTimer gRestoreGLTimer;
  253. bool gRestoreGL = false;
  254. bool gUseWireframe = false;
  255. // Set to true only while the fast timer view is opened
  256. bool gEnableFastTimers = false;
  257. // Memory checks
  258. LLFrameTimer gMemoryCheckTimer;
  259. // Updated in display_stats() in llviewerdisplay.cpp:
  260. U64 gMemoryAllocated = 0;
  261. bool gBalanceObjectCache = true;
  262. std::string gLastVersionChannel;
  263. LLVector3 gWindVec(3.0, 3.0, 0.0);
  264. LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
  265. U32 gPacketsIn = 0;
  266. bool gAllowTapTapHoldRun = true;
  267. bool gShowObjectUpdates = false;
  268. bool gAcceptTOS = false;
  269. bool gAcceptCriticalMessage = false;
  270. bool gAvatarMovedOnLogin = false;
  271. bool gLogoutInProgress = false;
  272. unsigned char gMACAddress[MAC_ADDRESS_BYTES];
  273. const std::string PREVIOUS_LOG("CoolVLViewer.old");
  274. const std::string CURRENT_LOG("CoolVLViewer.log");
  275. const char* TEMP_LOG_FMT = "CoolVLViewer_%d.log";
  276. // We must keep the same MARKER_FILE_NAME as for other viewers so to be able to
  277. // detect multiple instances... But we use the contents of this file to
  278. // distinguish our marker from others' (see anotherInstanceRunning() and
  279. // initMarkerFile())
  280. const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
  281. // Use custom marker files to avoid being attributed other viewers' crashes !
  282. const std::string ERROR_MARKER_FILE_NAME("CoolVLViewer.error_marker");
  283. const std::string LLERROR_MARKER_FILE_NAME("CoolVLViewer.llerror_marker");
  284. const std::string LOGOUT_MARKER_FILE_NAME("CoolVLViewer.logout_marker");
  285. static bool sLLErrorActivated = false;
  286. static bool sDoDisconnect = false;
  287. static bool sLoggingOut = false;
  288. // Plugin presence
  289. bool gHasGstreamer = false;
  290. // Static members.
  291. const std::string LLAppViewer::sGlobalSettingsName = "Global";
  292. const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount";
  293. ///////////////////////////////////////////////////////////////////////////////
  294. // LLControlGroupCLP class
  295. // Uses the command line parser to configure an LLControlGroup
  296. ///////////////////////////////////////////////////////////////////////////////
  297. class LLControlGroupCLP : public LLCommandLineParser
  298. {
  299. protected:
  300. LOG_CLASS(LLControlGroupCLP);
  301. public:
  302. /**
  303. * @brief Configure the command line parser according the given config file.
  304. *
  305. * @param config_filename The name of the XML based LLSD config file.
  306. * @param clp A reference to the command line parser object to configure.
  307. *
  308. * *FIX:Mani Specify config file format.
  309. */
  310. void configure(const std::string& config_filename, LLControlGroup* group);
  311. private:
  312. static void setControlValueCB(const LLCommandLineParser::token_vector_t& value,
  313. const std::string& opt_name,
  314. LLControlGroup* ctrl_group);
  315. };
  316. //static
  317. void LLControlGroupCLP::setControlValueCB(const LLCommandLineParser::token_vector_t& value,
  318. const std::string& opt_name,
  319. LLControlGroup* ctrl_group)
  320. {
  321. // *FIXME: do sematic conversion here ? LLSD(ImplString) is no good for
  322. // doing string to type conversion for... booleans, compound types ?...
  323. LLControlVariable* ctrl = ctrl_group->getControl(opt_name.c_str());
  324. if (!ctrl)
  325. {
  326. llwarns << "Command Line option mapping '" << opt_name
  327. << "' not found ! Ignoring." << llendl;
  328. return;
  329. }
  330. if (ctrl->type() == TYPE_BOOLEAN)
  331. {
  332. if (value.size() > 1)
  333. {
  334. llwarns << "Ignoring extra tokens." << llendl;
  335. }
  336. if (value.size() > 0)
  337. {
  338. // There is a token. Check the string for true/false/1/0 etc.
  339. bool result = false;
  340. bool gotSet = LLStringUtil::convertToBool(value[0], result);
  341. if (gotSet)
  342. {
  343. ctrl->setValue(LLSD(result), false);
  344. }
  345. }
  346. else
  347. {
  348. ctrl->setValue(LLSD(true), false);
  349. }
  350. }
  351. // For the default types, let llsd do the conversion.
  352. else if (value.size() > 1 && ctrl->isType(TYPE_LLSD))
  353. {
  354. // Assume it is an array...
  355. LLSD llsd_array;
  356. for (U32 i = 0; i < value.size(); ++i)
  357. {
  358. LLSD llsd_value;
  359. llsd_value.assign(LLSD::String(value[i]));
  360. llsd_array.set(i, llsd_value);
  361. }
  362. ctrl->setValue(llsd_array, false);
  363. }
  364. else if (value.size() > 0)
  365. {
  366. if (value.size() > 1)
  367. {
  368. llwarns << "Ignoring extra tokens mapped to the setting: "
  369. << opt_name << "." << llendl;
  370. }
  371. LLSD llsd_value;
  372. llsd_value.assign(LLSD::String(value[0]));
  373. ctrl->setValue(llsd_value, false);
  374. }
  375. }
  376. // This method reads the LLSD based config file, and uses it to set members of
  377. // a control group.
  378. void LLControlGroupCLP::configure(const std::string& config_filename,
  379. LLControlGroup* ctrl_group)
  380. {
  381. llifstream input_stream(config_filename.c_str(),
  382. std::ios::in | std::ios::binary);
  383. if (!input_stream.is_open())
  384. {
  385. llwarns << "Could not open: " << config_filename << llendl;
  386. return;
  387. }
  388. LLSD config;
  389. LLSDSerialize::fromXML(config, input_stream);
  390. for (LLSD::map_iterator it = config.beginMap(); it != config.endMap();
  391. ++it)
  392. {
  393. LLSD::String long_name = it->first;
  394. LLSD option_params = it->second;
  395. std::string desc("n/a");
  396. if (option_params.has("desc"))
  397. {
  398. desc = option_params["desc"].asString();
  399. }
  400. std::string short_name = LLStringUtil::null;
  401. if (option_params.has("short"))
  402. {
  403. short_name = option_params["short"].asString();
  404. }
  405. unsigned int token_count = 0;
  406. if (option_params.has("count"))
  407. {
  408. token_count = option_params["count"].asInteger();
  409. }
  410. bool composing = false;
  411. if (option_params.has("compose"))
  412. {
  413. composing = option_params["compose"].asBoolean();
  414. }
  415. bool positional = false;
  416. if (option_params.has("positional"))
  417. {
  418. positional = option_params["positional"].asBoolean();
  419. }
  420. bool last_option = false;
  421. if (option_params.has("last_option"))
  422. {
  423. last_option = option_params["last_option"].asBoolean();
  424. }
  425. boost::function1<void, const token_vector_t&> callback;
  426. if (ctrl_group && option_params.has("map-to"))
  427. {
  428. std::string ctrl_name = option_params["map-to"].asString();
  429. callback = boost::bind(&LLControlGroupCLP::setControlValueCB, _1,
  430. ctrl_name, ctrl_group);
  431. }
  432. addOptionDesc(long_name, callback, token_count, desc, short_name,
  433. composing, positional, last_option);
  434. }
  435. }
  436. ///////////////////////////////////////////////////////////////////////////////
  437. // LLFrameStatsTimer class
  438. // This class is an LLFrameTimer that can be created with an elapsed time that
  439. // starts counting up from the given value rather than 0.0.
  440. // Otherwise it behaves the same way as LLFrameTimer.
  441. ///////////////////////////////////////////////////////////////////////////////
  442. class LLFrameStatsTimer : public LLFrameTimer
  443. {
  444. public:
  445. LLFrameStatsTimer(F64 elapsed_already = 0.0)
  446. : LLFrameTimer()
  447. {
  448. mStartTime -= elapsed_already;
  449. }
  450. };
  451. //----------------------------------------------------------------------------
  452. // File scope definitons
  453. std::string gLoginPage;
  454. std::vector<std::string> gLoginURIs;
  455. static std::string gHelperURI;
  456. // Show only appropriate debug controls in settings editor. HB
  457. static void hide_useless_settings()
  458. {
  459. LLControlVariable* control = NULL;
  460. #if !LL_FAST_TIMERS_ENABLED
  461. control = gSavedSettings.getControl("FastTimersAlwaysEnabled");
  462. if (control)
  463. {
  464. control->setHiddenFromUser(true);
  465. }
  466. #endif
  467. #if LL_PENDING_MESH_REQUEST_SORTING
  468. control = gSavedSettings.getControl("DelayPendingMeshFetchesOnTP");
  469. if (control)
  470. {
  471. control->setHiddenFromUser(true);
  472. }
  473. #endif
  474. #if !LL_USE_NEW_DESERIALIZE
  475. control = gSavedSettings.getControl("PuppetryBinaryInputStream");
  476. if (control)
  477. {
  478. control->setHiddenFromUser(true);
  479. }
  480. #endif
  481. #if !LL_PUPPETRY
  482. control = gSavedSettings.getControl("PuppetryAllowed");
  483. if (control)
  484. {
  485. control->setHiddenFromUser(true);
  486. }
  487. control = gSavedSettings.getControl("PuppetryBinaryInputStream");
  488. if (control)
  489. {
  490. control->setHiddenFromUser(true);
  491. }
  492. control = gSavedSettings.getControl("PuppetryBinaryOutputStream");
  493. if (control)
  494. {
  495. control->setHiddenFromUser(true);
  496. }
  497. control = gSavedSettings.getControl("PuppetryCamera");
  498. if (control)
  499. {
  500. control->setHiddenFromUser(true);
  501. }
  502. control = gSavedSettings.getControl("PuppetryCameraOption");
  503. if (control)
  504. {
  505. control->setHiddenFromUser(true);
  506. }
  507. control = gSavedSettings.getControl("PuppetryLastCommand");
  508. if (control)
  509. {
  510. control->setHiddenFromUser(true);
  511. }
  512. control = gSavedSettings.getControl("PuppetryParts");
  513. if (control)
  514. {
  515. control->setHiddenFromUser(true);
  516. }
  517. control = gSavedSettings.getControl("PuppetrySendAttachmentsData");
  518. if (control)
  519. {
  520. control->setHiddenFromUser(true);
  521. }
  522. control = gSavedSettings.getControl("PuppetryUseServerEcho");
  523. if (control)
  524. {
  525. control->setHiddenFromUser(true);
  526. }
  527. #endif
  528. #if LL_LINUX
  529. // Not (yet) used under Linux.
  530. control = gSavedSettings.getControl("RenderHiDPI");
  531. if (control)
  532. {
  533. control->setHiddenFromUser(true);
  534. }
  535. #else
  536. // Not (yet ?) used under Windows and macOS.
  537. control = gSavedSettings.getControl("FullDesktop");
  538. if (control)
  539. {
  540. control->setHiddenFromUser(true);
  541. }
  542. // No D-Bus under Windows or macOS.
  543. control = gSavedPerAccountSettings.getControl("LuaAcceptDbusCommands");
  544. if (control)
  545. {
  546. control->setHiddenFromUser(true);
  547. }
  548. #endif
  549. #if LL_WINDOWS
  550. control = gSavedSettings.getControl("ShowConsoleWindow");
  551. if (control)
  552. {
  553. control->setHiddenFromUser(false);
  554. }
  555. control = gSavedSettings.getControl("IgnoreHiDPIEvents");
  556. if (control)
  557. {
  558. control->setHiddenFromUser(false);
  559. }
  560. #endif
  561. #if LL_DARWIN
  562. control = gSavedSettings.getControl("MainThreadCPUAffinity");
  563. if (control)
  564. {
  565. control->setHiddenFromUser(true);
  566. }
  567. control = gSavedSettings.getControl("MacUseThreadedGL");
  568. if (control)
  569. {
  570. control->setHiddenFromUser(false);
  571. }
  572. control = gSavedSettings.getControl("RenderGLSetSubImagePerLine");
  573. if (control)
  574. {
  575. control->setHiddenFromUser(false);
  576. }
  577. #endif
  578. #if !LL_LINUX || !LL_FMOD
  579. control = gSavedSettings.getControl("FMODDisableALSA");
  580. if (control)
  581. {
  582. control->setHiddenFromUser(true);
  583. }
  584. control = gSavedSettings.getControl("FMODDisablePulseAudio");
  585. if (control)
  586. {
  587. control->setHiddenFromUser(true);
  588. }
  589. #endif
  590. #if !LL_FMOD
  591. control = gSavedSettings.getControl("AudioDisableFMOD");
  592. if (control)
  593. {
  594. control->setHiddenFromUser(true);
  595. }
  596. #endif
  597. #if !LL_OPENAL
  598. control = gSavedSettings.getControl("AudioDisableOpenAL");
  599. if (control)
  600. {
  601. control->setHiddenFromUser(true);
  602. }
  603. #endif
  604. #ifndef HB_DULLAHAN_EXTENDED
  605. control = gSavedSettings.getControl("CEFPreferredFont");
  606. if (control)
  607. {
  608. control->setHiddenFromUser(true);
  609. }
  610. control = gSavedSettings.getControl("CEFMinimumFontSize");
  611. if (control)
  612. {
  613. control->setHiddenFromUser(true);
  614. }
  615. control = gSavedSettings.getControl("CEFDefaultFontSize");
  616. if (control)
  617. {
  618. control->setHiddenFromUser(true);
  619. }
  620. control = gSavedSettings.getControl("CEFRemoteFonts");
  621. if (control)
  622. {
  623. control->setHiddenFromUser(true);
  624. }
  625. #endif
  626. // Plugins support has been entirely gutted out from CEF 100
  627. #if CHROME_VERSION_MAJOR >= 100
  628. control = gSavedSettings.getControl("BrowserPluginsEnabled");
  629. if (control)
  630. {
  631. control->setHiddenFromUser(true);
  632. }
  633. #endif
  634. // Check plugins existence for this particular build/installation
  635. std::string plugin_file = gDirUtil.getLLPluginFilename("media_plugin_cef");
  636. if (!LLFile::isfile(plugin_file))
  637. {
  638. llwarns << "No web browser plugin found !" << llendl;
  639. }
  640. plugin_file = gDirUtil.getLLPluginFilename("media_plugin_gstreamer");
  641. gHasGstreamer = LLFile::isfile(plugin_file);
  642. if (!gHasGstreamer)
  643. {
  644. llwarns << "No streaming media plugin found !" << llendl;
  645. }
  646. }
  647. // Deals with settings that must be passed to already constructed classes or
  648. // affected to global variables.
  649. static void settings_to_globals()
  650. {
  651. gButtonHPad = gSavedSettings.getS32("ButtonHPad");
  652. gButtonVPad = gSavedSettings.getS32("ButtonVPad");
  653. gBtnHeightSmall = gSavedSettings.getS32("ButtonHeightSmall");
  654. gBtnHeight = gSavedSettings.getS32("ButtonHeight");
  655. gMenuBarHeight = gSavedSettings.getS32("MenuBarHeight");
  656. gStatusBarHeight = gSavedSettings.getS32("StatusBarHeight");
  657. #if LL_LINUX
  658. gUseFullDesktop = gSavedSettings.getBool("FullDesktop");
  659. #else
  660. gHiDPISupport = gSavedSettings.getBool("RenderHiDPI");
  661. #endif
  662. #if LL_WINDOWS
  663. gIgnoreHiDPIEvents = gSavedSettings.getBool("IgnoreHiDPIEvents");
  664. #endif
  665. #if LL_DARWIN
  666. LLWindowMacOSX::sUseMultGL = gSavedSettings.getBool("MacUseThreadedGL");
  667. #endif
  668. // For HTML parsing in text boxes.
  669. LLTextEditor::setLinksColor(gSavedSettings.getColor4("HTMLLinkColor"));
  670. gUsePBRShaders = gSavedSettings.getBool("RenderUsePBR");
  671. LLRender::sGLCoreProfile = gSavedSettings.getBool("RenderGLCoreProfile");
  672. LLRender::sUseBufferCache = gSavedSettings.getBool("RenderGLUseVBCache");
  673. gFocusMgr.setFocusColor(gColors.getColor("FocusColor"));
  674. LLFloaterView::setStackMinimizedTopToBottom(gSavedSettings.getBool("StackMinimizedTopToBottom"));
  675. LLFloaterView::setStackMinimizedRightToLeft(gSavedSettings.getBool("StackMinimizedRightToLeft"));
  676. LLFloaterView::setStackScreenWidthFraction(gSavedSettings.getU32("StackScreenWidthFraction"));
  677. LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
  678. LLSurfacePatch::setAutoReloadDelay(gSavedSettings.getU32("AutoReloadFailedPatchTexDelay"));
  679. LLImageGL::setDelayedTextureDelete(gSavedSettings.getBool("DelayGLTextureDelete"));
  680. LLImageGL::sGlobalUseAnisotropic =
  681. gSavedSettings.getBool("RenderAnisotropic");
  682. #if LL_DARWIN
  683. LLImageGL::sSetSubImagePerLine = false;
  684. #else
  685. LLImageGL::sSetSubImagePerLine =
  686. gSavedSettings.getBool("RenderGLSetSubImagePerLine");
  687. #endif
  688. LLImageGL::sSyncInThread =
  689. gSavedSettings.getBool("RenderGLImageSyncInThread");
  690. LLFontGL::setColorUse(gSavedSettings.getBool("AllowColoredFonts"));
  691. // Clamp auto-open time to some minimum usable value
  692. LLFolderView::sAutoOpenTime =
  693. llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
  694. LLToolBar::sInventoryAutoOpenTime =
  695. gSavedSettings.getF32("InventoryAutoOpenDelay");
  696. // Work-around for Wine bug. HB
  697. LLFile::sFlushOnWrite = gSavedSettings.getBool("FSFlushOnWrite");
  698. #if LL_WINDOWS
  699. if (gAppViewerp->isRunningUnderWine())
  700. {
  701. if (!LLFile::sFlushOnWrite)
  702. {
  703. llinfos << "Forcing flush-on-writes to work-around a bug in Wine."
  704. << llendl;
  705. // Note: this will set LLFile::sFlushOnWrite to true via the
  706. // listener in llviewercontrol.cpp.
  707. gSavedSettings.setBool("FSFlushOnWrite", true);
  708. }
  709. }
  710. #endif
  711. LLInventoryModelFetch::setUseAISFetching(gSavedSettings.getBool("UseAISForFetching"));
  712. gAgent.mHideGroupTitle = gSavedSettings.getBool("RenderHideGroupTitle");
  713. gDebugWindowProc = gSavedSettings.getBool("DebugWindowProc");
  714. gAllowTapTapHoldRun = gSavedSettings.getBool("AllowTapTapHoldRun");
  715. gShowObjectUpdates = gSavedSettings.getBool("ShowObjectUpdates");
  716. LLPanelWorldMap::sMapScale = gSavedSettings.getF32("MapScale");
  717. LLHoverView::sShowHoverTips = gSavedSettings.getBool("ShowHoverTips");
  718. LLAvatarName::sLegacyNamesForFriends =
  719. gSavedSettings.getBool("LegacyNamesForFriends");
  720. LLAvatarName::sLegacyNamesForSpeakers =
  721. gSavedSettings.getBool("LegacyNamesForSpeakers");
  722. // Setup the spell checker
  723. LLSpellCheck* spchk = LLSpellCheck::getInstance();
  724. spchk->setSpellCheck(gSavedSettings.getBool("SpellCheck"));
  725. spchk->setShowMisspelled(gSavedSettings.getBool("SpellCheckShow"));
  726. spchk->setDictionary(gSavedSettings.getString("SpellCheckLanguage"));
  727. LLVolume::sOptimizeCache =
  728. gSavedSettings.getBool("RenderOptimizeMeshVertexCache");
  729. LLVOSurfacePatch::sLODFactor =
  730. gSavedSettings.getF32("RenderTerrainLODFactor");
  731. // Square lod factor to get exponential range of [1, 4]
  732. LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor;
  733. gDebugGL = gSavedSettings.getBool("DebugGLOnRestart");
  734. if (gDebugGL)
  735. {
  736. gSavedSettings.setBool("DebugGLOnRestart", false);
  737. }
  738. LLHUDEffectLookAt::updateSettings();
  739. }
  740. class LLUITranslationBridge final : public LLTranslationBridge
  741. {
  742. public:
  743. std::string getString(const std::string& xml_desc) override
  744. {
  745. return LLTrans::getString(xml_desc);
  746. }
  747. };
  748. //----------------------------------------------------------------------------
  749. // LLAppViewer class
  750. //----------------------------------------------------------------------------
  751. LLAppViewer::LLAppViewer()
  752. : mMarkerFile(NULL),
  753. mGeneralThreadPool(NULL),
  754. mOwnsLogoutMarkerFile(false),
  755. mPurgeCache(false),
  756. mPurgeOnExit(false),
  757. mSavedMACValid(false),
  758. mSecondInstance(false),
  759. mIsOurViewer(false),
  760. mSameBranchViewer(false),
  761. mIsSiblingViewer(false),
  762. #if LL_WINDOWS
  763. mUnderWine(false),
  764. #endif
  765. mSavedFinalSnapshot(false),
  766. mSavePerAccountSettings(false),
  767. mQuitRequested(false),
  768. mLogoutRequestSent(false),
  769. mLastAgentControlFlags(0),
  770. mLastAgentForceUpdate(0),
  771. mAgentRegionLastAlive(false)
  772. {
  773. if (gAppViewerp)
  774. {
  775. llerrs << "An instance of LLAppViewer already exists !" << llendl;
  776. }
  777. gAppViewerp = this;
  778. }
  779. LLAppViewer::~LLAppViewer()
  780. {
  781. // If we got to this destructor somehow, the app did not hang.
  782. removeMarkerFile();
  783. gAppViewerp = NULL;
  784. }
  785. // Start of the application
  786. //
  787. // IMPORTANT ! Do NOT put anything that will write into the log files during
  788. // normal startup until AFTER we run the "program crashed last time" error
  789. // handler below.
  790. LLApp::InitState LLAppViewer::init()
  791. {
  792. // Reserve some memory space that will get freed on crash.
  793. LLMemory::initClass();
  794. // Initialize the translation bridge for LLWearableType...
  795. LLTranslationBridge::ptr_t trans =
  796. std::make_shared<LLUITranslationBridge>();
  797. LLWearableType::initClass(trans);
  798. // ... and LLSettingsType
  799. LLSettingsType::initClass(trans);
  800. // Initialize SSE2 math
  801. LLVector4a::initClass();
  802. // Need to do this initialization before we do anything else, since
  803. // anything that touches files should really go through the lldir API
  804. gDirUtil.initAppDirs("SecondLife");
  805. // Set skin search path to default, will be overridden later: this allows
  806. // simple skinned file lookups to work
  807. gDirUtil.setSkinFolder("default");
  808. initLogging();
  809. // OK to write stuff to logs now, we have now crash reported if necessary
  810. // This sets LLError::Log::sIsBeingDebugged appropriatley to abort()
  811. // instead of crashing when encountering an llerrs while being debugged.
  812. if (gAppViewerp->beingDebugged())
  813. {
  814. llinfos << "Running under a debugger. llerrs will cause abort() instead of a crash."
  815. << llendl;
  816. }
  817. InitState init_state = initConfiguration();
  818. // Bail if init failed/aborted
  819. // Rename the log if possible
  820. renameLog(false);
  821. if (init_state != INIT_OK)
  822. {
  823. return init_state;
  824. }
  825. // Now that we have the global settings initialized, we can set this:
  826. LLError::Log::sPreciseTimeStamp =
  827. gSavedSettings.getBool("PreciseLogTimestamps");
  828. hide_useless_settings();
  829. if (!gSavedSettings.getBool("SkipStaticVectorSizing"))
  830. {
  831. // These are not true intialization routines, but rather memory
  832. // reserving functions to avoid (as much as possible) fragmentation
  833. // by making enough room for a few static/permanent std::vectors that
  834. // would otherwise slowly grow over time and might end up in the middle
  835. // of freed memory blocks after a TP if they were not large enough at
  836. // the start of the session.
  837. // By setting SkipStaticVectorSizing to true (and restarting the
  838. // viewer), you may skip this initialization so to verify (via
  839. // "Advanced" -> "Consoles" -> "Info to Debug Console" ->
  840. // "Memory Stats") what capacity is naturally reached during a session
  841. // and check it against the capacity reserved in the following
  842. // functions (this is how I determined the suitable values).
  843. LLCharacter::initClass();
  844. LLMotionController::initClass();
  845. LLVolumeImplFlexible::initClass();
  846. LLViewerTextureAnim::initClass();
  847. }
  848. // Initialize the private memory pool for volumes
  849. LLVolumeFace::initClass();
  850. writeSystemInfo();
  851. // This must be called *after* writeSystemInfo() under Windows, since the
  852. // latter causes the CPU affinity to be reset after the CPU frequency is
  853. // calculated in LLProcessorInfo(). HB
  854. initThreads();
  855. // Set LLXMLRPCTransaction parameters
  856. LLXMLRPCTransaction::setVerifyCert(!gSavedSettings.getBool("NoVerifySSLCert"));
  857. // Avatar name cache and preferences
  858. U32 maxreq = llclamp(gSavedSettings.getU32("AvatarNameCacheMaxRequests"),
  859. 4U, 32U);
  860. LLAvatarNameCache::setMaximumRequests(maxreq);
  861. llinfos << "LLAvatarNameCache maximum simultaneous requests set to: "
  862. << maxreq << llendl;
  863. LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getU32("DisplayNamesUsage"));
  864. LLAvatarName::sOmitResidentAsLastName =
  865. gSavedSettings.getBool("OmitResidentAsLastName");
  866. // Build a string representing the advertized name and version number.
  867. gCurrentVersion =
  868. llformat("%s %d.%d.%d.%d",
  869. gSavedSettings.getString("VersionChannelName").c_str(),
  870. LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_BRANCH,
  871. LL_VERSION_RELEASE);
  872. llinfos << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << llendl;
  873. /////////////////////////////////////////////////
  874. // OS-specific login dialogs
  875. /////////////////////////////////////////////////
  876. gSavedSettings.setString("HelpLastVisitedURL",
  877. gSavedSettings.getString("HelpHomeURL"));
  878. if (gSavedSettings.getBool("VerboseLogs"))
  879. {
  880. LLError::setPrintLocation(true);
  881. }
  882. // Load art UUID information; do not require these strings to be declared
  883. // in code.
  884. std::string colors_base_filename =
  885. gDirUtil.findSkinnedFilename("colors_base.xml");
  886. LL_DEBUGS("AppInit") << "Loading base colors from " << colors_base_filename
  887. << LL_ENDL;
  888. gColors.loadFromFileLegacy(colors_base_filename, false, TYPE_COL4U);
  889. // Load overrides from user colors file, if any
  890. std::string user_colors_filename =
  891. gDirUtil.findSkinnedFilename("colors.xml");
  892. if (!user_colors_filename.empty())
  893. {
  894. llinfos << "Loading user colors from " << user_colors_filename
  895. << llendl;
  896. if (gColors.loadFromFileLegacy(user_colors_filename, false,
  897. TYPE_COL4U) == 0)
  898. {
  899. llwarns << "Failed to load user colors from "
  900. << user_colors_filename << llendl;
  901. }
  902. }
  903. // Widget construction depends on LLUI being initialized
  904. LLUI::initClass(&gSavedSettings, &gSavedSettings, &gColors,
  905. LLUIImageList::getInstance(), ui_audio_callback,
  906. &LLUI::sGLScaleFactor);
  907. LLWeb::initClass(); // do this after LLUI
  908. LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
  909. &LLURLDispatcher::dispatchFromTextEditor,
  910. &LLURLDispatcher::dispatchFromTextEditor);
  911. // Update paths with correct language set
  912. LLUICtrlFactory::getInstance()->setupPaths();
  913. // Now that settings and colors are loaded, we can call this:
  914. gSelectMgr.initClass();
  915. /////////////////////////////////////////////////
  916. // Load settings files
  917. LLGroupMgr::parseRoleActions("role_actions.xml");
  918. LLAgent::parseTeleportMessages("teleport_strings.xml");
  919. // Load MIME type -> media impl mappings
  920. LLMIMETypes::parseMIMETypes(std::string("mime_types.xml"));
  921. if (gSavedSettings.getBool("SaveFileSelectorPaths"))
  922. {
  923. // Load the file selector default paths
  924. HBFileSelector::loadDefaultPaths("selector_paths.xml");
  925. }
  926. #if LL_WINDOWS
  927. // We need this info in settings_to_globals(). HB
  928. mUnderWine = LLOSInfo::getInstance()->underWine();
  929. #endif
  930. // Copy settings to globals and already constructed classes.
  931. settings_to_globals();
  932. // Setup settings listeners
  933. settings_setup_listeners();
  934. //MK
  935. RLInterface::init();
  936. //mk
  937. // Do any necessary setup for accepting incoming SLURLs and Lua commands
  938. // from apps
  939. initAppMessagesHandler();
  940. if (!initHardwareTest())
  941. {
  942. // Early out from user choice.
  943. return INIT_FAILED;
  944. }
  945. // Derive an "unique" serial number out of the system disks serial numbers
  946. // (Windows, Linux) or out of the hardware serial (macOS).
  947. mSerialNumber = generateSerialNumber();
  948. // Hash it so that we can store it into the user settings, without
  949. // disclosing it (just in case the settings file and hashed passwords would
  950. // get stolen by someone ill-intentioned; of course, this does not offer
  951. // any protection against someone gaining full access to the computer since
  952. // they can easily get/compute the serial number in this case). HB
  953. LLMD5 serial_hash((unsigned char*)mSerialNumber.c_str());
  954. char md5serial[MD5HEX_STR_BYTES + 1];
  955. serial_hash.hex_digest(md5serial);
  956. // Check to see if the serial number changed since last session (could be
  957. // the case should there be a changed disk or should the settings be ported
  958. // to another computer); if so, clear any saved MAC since the latter was
  959. // encrypted with the serial number... HB
  960. std::string saved_hash = gSavedSettings.getString("SerialNumberHash");
  961. if (!saved_hash.empty() &&
  962. strncmp(md5serial, saved_hash.c_str(), MD5HEX_STR_BYTES))
  963. {
  964. llwarns << "Detected unique serial number change: clearing the saved settings depending on it."
  965. << llendl;
  966. gSavedSettings.setString("SavedMACAddress", "");
  967. }
  968. gSavedSettings.setString("SerialNumberHash", md5serial);
  969. // Always fetch the Ethernet MAC address, needed both for login and
  970. // password load.
  971. // Since the MAC address changes with the network I/F and we do not want to
  972. // loose our saved passwords each time we switch I/F on our computer (e.g.
  973. // from the Ethernet port to a Wi-Fi connection or vice versa), we store
  974. // the currrent MAC address the first time we get one, and then reuse that
  975. // same address on the subsequent sessions (the address being stored in the
  976. // saved settings, it is kept the same for all avatar accounts used from
  977. // this computer account, which is exactly what we want to happen).
  978. // To avoid (or at least make much less easy and likely) potential security
  979. // issues (such as in case of the stealing of both the user settings and
  980. // the saved grids login files by a third person for reuse on their own
  981. // computer), the MAC address is encrypted (using our unique computer Id):
  982. // of course, if a person could get access to your computer account, they
  983. // likely can get/deduce/compute that computer Id... But they can just as
  984. // well and in fact more easily, get access to the network I/F MAC address,
  985. // so... HB
  986. mSavedMACValid = false;
  987. std::string saved_mac = gSavedSettings.getString("SavedMACAddress");
  988. if (saved_mac.size() > MAC_ADDRESS_BYTES)
  989. {
  990. saved_mac = LLBase64::decode(saved_mac);
  991. if (saved_mac.size() == MAC_ADDRESS_BYTES)
  992. {
  993. LLXORCipher cipher(mSerialNumber);
  994. if (cipher.decrypt(saved_mac, (U8*)gMACAddress))
  995. {
  996. mSavedMACValid = true;
  997. llinfos << "Got the MAC address from the user settings."
  998. << llendl;
  999. }
  1000. }
  1001. }
  1002. if (!mSavedMACValid)
  1003. {
  1004. // Get the actual and current network I/F MAC address
  1005. LLOSInfo::getNodeID(gMACAddress);
  1006. // Try and save it in settings, encrypted with our unique serial number
  1007. saved_mac.assign((const char*)gMACAddress, MAC_ADDRESS_BYTES);
  1008. LLXORCipher cipher(mSerialNumber);
  1009. if (cipher.encrypt(saved_mac))
  1010. {
  1011. saved_mac = LLBase64::encode(saved_mac);
  1012. llinfos << "Saved the current MAC address into the user settings."
  1013. << llendl;
  1014. }
  1015. else
  1016. {
  1017. llwarns << "Could not encrypt the MAC address to store it into the user settings."
  1018. << llendl;
  1019. saved_mac.clear();
  1020. }
  1021. gSavedSettings.setString("SavedMACAddress", saved_mac);
  1022. }
  1023. // *Note: this is where gViewerStats used to be created.
  1024. // Initialize the cache, and gracefully handle initialization errors
  1025. if (!initCache())
  1026. {
  1027. std::ostringstream msg;
  1028. msg << gSecondLife << " is unable to access a file that it needs.\n\n"
  1029. << "This can be because you somehow have multiple copies running, "
  1030. << "or your system incorrectly thinks a file is open. "
  1031. << "If this message persists, restart your computer and try again. "
  1032. << "If it continues to persist, you may need to completely uninstall "
  1033. << gSecondLife << " and reinstall it.";
  1034. OSMessageBox(msg.str());
  1035. return INIT_FAILED;
  1036. }
  1037. // Initialize the window
  1038. if (!initWindow())
  1039. {
  1040. OSMessageBox(gNotifications.getGlobalString("UnsupportedGLRequirements"));
  1041. return INIT_FAILED;
  1042. }
  1043. // Call all self-registered classes
  1044. LLInitClassList::getInstance()->fireCallbacks();
  1045. // SJB: Needs to happen after initWindow(), not sure why but related to
  1046. // fonts
  1047. LLFolderViewItem::initClass();
  1048. gGLManager.getGLInfo(gDebugInfo);
  1049. gGLManager.printGLInfoString();
  1050. // Load key settings
  1051. bind_keyboard_functions();
  1052. // Load Default bindings
  1053. if (!gViewerKeyboard.loadBindings(gDirUtil.getFullPath(LL_PATH_APP_SETTINGS,
  1054. "keys.ini")))
  1055. {
  1056. llerrs << "Unable to open keys.ini" << llendl;
  1057. }
  1058. // Load Custom bindings (override defaults)
  1059. gViewerKeyboard.loadBindings(gDirUtil.getFullPath(LL_PATH_APP_SETTINGS,
  1060. "custom_keys.ini"));
  1061. // Without SSE2 support we will crash almost immediately, warn here.
  1062. LLCPUInfo* cpuinfo = LLCPUInfo::getInstance();
  1063. if (!cpuinfo->hasSSE2())
  1064. {
  1065. // Cannot use an alert here since we are exiting and all hell breaks
  1066. // lose.
  1067. OSMessageBox(gNotifications.getGlobalString("UnsupportedCPUSSE2"));
  1068. return INIT_FAILED;
  1069. }
  1070. // Alert the user if they are using unsupported hardware
  1071. // Note: initWindow() also initialized the Feature List.
  1072. if (!gSavedSettings.getBool("AlertedUnsupportedHardware"))
  1073. {
  1074. bool unsupported = false;
  1075. LLSD args;
  1076. std::string minSpecs;
  1077. // Get cpu data from xml
  1078. std::stringstream min_cpu_string(gNotifications.getGlobalString("UnsupportedCPUAmount"));
  1079. S32 min_cpu = 0;
  1080. min_cpu_string >> min_cpu;
  1081. // Get RAM data from XML
  1082. std::stringstream min_ram_str(gNotifications.getGlobalString("UnsupportedRAMAmount"));
  1083. U64 min_ram = 0;
  1084. min_ram_str >> min_ram;
  1085. min_ram = min_ram * 1024;
  1086. if (!gFeatureManager.isGPUSupported() &&
  1087. gFeatureManager.getGPUClass() != GPU_CLASS_UNKNOWN)
  1088. {
  1089. minSpecs += gNotifications.getGlobalString("UnsupportedGPU");
  1090. minSpecs += "\n";
  1091. unsupported = true;
  1092. }
  1093. if (cpuinfo->getMHz() < min_cpu)
  1094. {
  1095. minSpecs += gNotifications.getGlobalString("UnsupportedCPU");
  1096. minSpecs += "\n";
  1097. unsupported = true;
  1098. }
  1099. if (LLMemory::getPhysicalMemoryKB() < min_ram)
  1100. {
  1101. minSpecs += gNotifications.getGlobalString("UnsupportedRAM");
  1102. minSpecs += "\n";
  1103. unsupported = true;
  1104. }
  1105. if (gFeatureManager.getGPUClass() == GPU_CLASS_UNKNOWN)
  1106. {
  1107. gNotifications.add("UnknownGPU");
  1108. }
  1109. if (unsupported)
  1110. {
  1111. if (!gSavedSettings.controlExists("WarnUnsupportedHardware") ||
  1112. gSavedSettings.getBool("WarnUnsupportedHardware"))
  1113. {
  1114. args["MINSPECS"] = minSpecs;
  1115. gNotifications.add("UnsupportedHardware", args);
  1116. }
  1117. }
  1118. }
  1119. #if LL_WINDOWS
  1120. if (mUnderWine)
  1121. {
  1122. // Let's discourage the user from running the viewer under Wine; beyond
  1123. // testing purposes, this is plain silly and totally unsafe ! HB
  1124. std::ostringstream msg;
  1125. msg << "You are running " << gSecondLife
  1126. << " under Wine, which got bugs that do impact SL viewers.\n"
  1127. << "Workarounds for those bugs are in place in this viewer,"
  1128. << " but you will nonetheless suffer from slowdowns, glitches,"
  1129. << " and maybe spurious crashes or data corruptions.\n"
  1130. << "Running this viewer under Wine is *unsupported*.\n\n"
  1131. << "Pretty please, use the native Linux viewer build instead !";
  1132. OSMessageBox(msg.str(), "Warning");
  1133. }
  1134. #endif
  1135. if (!LLRender::sGLCoreProfile &&
  1136. gSavedSettings.getBool("RenderGLCoreProfile"))
  1137. {
  1138. gNotifications.add("CoreProfileAfterRestart");
  1139. }
  1140. // Save the graphics card
  1141. gDebugInfo["GraphicsCard"] = gFeatureManager.getGPUString();
  1142. // Save the current version to the prefs file
  1143. gSavedSettings.setString("LastRunVersion", gCurrentVersion);
  1144. // Initialize the constant data for the login authentication. HB
  1145. char hashed_mac_string[MD5HEX_STR_SIZE];
  1146. LLMD5 hashed_mac;
  1147. hashed_mac.update(gMACAddress, MAC_ADDRESS_BYTES);
  1148. hashed_mac.finalize();
  1149. hashed_mac.hex_digest(hashed_mac_string);
  1150. const LLOSInfo* osinfo = LLOSInfo::getInstance();
  1151. gUserAuth.init(osinfo->getOSVersionString(), osinfo->getOSStringSimple(),
  1152. gCurrentVersion,
  1153. gSavedSettings.getString("VersionChannelName"),
  1154. mSerialNumber, hashed_mac_string);
  1155. gSimLastTime = gRenderStartTime.getElapsedTimeF32();
  1156. gSimFrames = (F32)gFrameCount;
  1157. LLViewerJoystick::getInstance()->init(false);
  1158. gViewerParcelMgr.initClass();
  1159. LLViewerMedia::initClass();
  1160. llinfos << "Viewer media initialized." << llendl;
  1161. // Tell the coprocedure manager how to discover and store the pool sizes
  1162. LLCoprocedureManager::getInstance()->setPropertyMethods(getSettingU32,
  1163. setSettingU32);
  1164. // Register the Lua UI command registration function. HB
  1165. LLUICtrl::setRegisterLuaCommandFunc(register_ui_lua_command);
  1166. // Try and start the automation script, if any. HB
  1167. std::string lua_script = gSavedSettings.getString("LuaAutomationScript");
  1168. if (!lua_script.empty())
  1169. {
  1170. lua_script = gDirUtil.getFullPath(LL_PATH_USER_SETTINGS, lua_script);
  1171. if (LLFile::exists(lua_script))
  1172. {
  1173. HBViewerAutomation::start(lua_script);
  1174. }
  1175. }
  1176. return INIT_OK;
  1177. }
  1178. // Loads up the initial grid choice from:
  1179. // 1.- hard coded defaults,
  1180. // 2.- command line settings,
  1181. // 3.- persisted settings.
  1182. void LLAppViewer::initGridChoice()
  1183. {
  1184. // Get the grid choice specified via the command line.
  1185. std::string grid_choice = gSavedSettings.getString("CmdLineGridChoice");
  1186. LLGridManager* gm = LLGridManager::getInstance();
  1187. // Load last server choice by default, ignored if the command line grid
  1188. // choice has been set
  1189. if (grid_choice.empty())
  1190. {
  1191. EGridInfo server = (EGridInfo)gSavedSettings.getS32("ServerChoice");
  1192. if (server == GRID_INFO_OTHER)
  1193. {
  1194. grid_choice = gSavedSettings.getString("CustomServer");
  1195. }
  1196. else if (server != GRID_INFO_NONE)
  1197. {
  1198. gm->setGridChoice(server);
  1199. return;
  1200. }
  1201. else
  1202. {
  1203. gm->setGridChoice(DEFAULT_GRID_CHOICE);
  1204. return;
  1205. }
  1206. }
  1207. // Note: this call is no op when string is empty:
  1208. gm->setGridChoice(grid_choice);
  1209. }
  1210. //virtual
  1211. bool LLAppViewer::initAppMessagesHandler()
  1212. {
  1213. // Does nothing unless subclassed
  1214. return false;
  1215. }
  1216. //virtual
  1217. bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
  1218. {
  1219. // Does nothing unless subclassed
  1220. return false;
  1221. }
  1222. //static
  1223. U32 LLAppViewer::getSettingU32(const std::string& name)
  1224. {
  1225. if (gSavedSettings.getControl(name.c_str()))
  1226. {
  1227. return gSavedSettings.getU32(name.c_str());
  1228. }
  1229. return 0;
  1230. }
  1231. //static
  1232. void LLAppViewer::setSettingU32(const std::string& name, U32 value)
  1233. {
  1234. if (gSavedSettings.getControl(name.c_str()))
  1235. {
  1236. gSavedSettings.setU32(name.c_str(), value);
  1237. }
  1238. }
  1239. void LLAppViewer::checkMemory()
  1240. {
  1241. LL_FAST_TIMER(FTM_MEMORY_CHECK);
  1242. constexpr F32 MEMORY_TRIM_LONG_INTERVAL = 60.f; // In seconds
  1243. static F32 last_check = 0.f;
  1244. F32 elapsed = gMemoryCheckTimer.getElapsedTimeF32();
  1245. if (elapsed - last_check > MEMORY_TRIM_LONG_INTERVAL)
  1246. {
  1247. // We never reset gMemoryCheckTimer because it is used elsewhere: just
  1248. // keep track of the last time we checked memory instead.
  1249. last_check = elapsed;
  1250. // Update memory info after trimming the heap when possible/supported.
  1251. LLMemory::updateMemoryInfo(true);
  1252. }
  1253. }
  1254. void LLAppViewer::idleAFKCheck(bool force_afk)
  1255. {
  1256. static LLCachedControl<U32> afk_timeout(gSavedSettings, "AFKTimeout");
  1257. U32 timeout = afk_timeout;
  1258. if (timeout > 0 && timeout < 30)
  1259. {
  1260. timeout = 30;
  1261. }
  1262. // Check idle timers
  1263. if (timeout > 0 &&
  1264. !gAgent.getAFK() && !gAgent.getBusy() && !gAgent.getAutoReply() &&
  1265. (force_afk || gAwayTriggerTimer.getElapsedTimeF32() > (F32)timeout))
  1266. {
  1267. U32 away_action = gSavedSettings.getU32("AwayAction");
  1268. switch (away_action)
  1269. {
  1270. case 0:
  1271. gAgent.setAFK();
  1272. break;
  1273. case 1:
  1274. gAgent.setBusy();
  1275. break;
  1276. default:
  1277. gAgent.setAutoReply();
  1278. }
  1279. }
  1280. }
  1281. static void sleep_viewer(U32 sleep_time)
  1282. {
  1283. // Do not sleep when a reshape() occurred (gScreenIsDirty == true) so to
  1284. // avoid excessive flicker during window resizing. HB
  1285. if (!gScreenIsDirty)
  1286. {
  1287. ms_sleep(sleep_time);
  1288. }
  1289. }
  1290. void LLAppViewer::frame(LLEventPump& mainloop)
  1291. {
  1292. static LLViewerJoystick* joystick = LLViewerJoystick::getInstance();
  1293. // As we do not (yet) send data on the mainloop LLEventPump that varies
  1294. // with each frame, no need to instantiate a new LLSD event object each
  1295. // time. Obviously, if that changes, just instantiate the LLSD at the
  1296. // point of posting.
  1297. static LLSD new_frame;
  1298. // Used to limit the frame rate in a smart way (i.e. doing extra work
  1299. // instead of sleeping). HB
  1300. static LLTimer frame_timer;
  1301. LL_FAST_TIMER(FTM_FRAME);
  1302. frame_timer.start();
  1303. // Check memory availability information
  1304. checkMemory();
  1305. #if LL_LINUX
  1306. // Pump glib events to avoid starvation for DBus servicing.
  1307. LLAppViewerLinux::pumpGlib();
  1308. #endif
  1309. if (gWindowp)
  1310. {
  1311. LL_FAST_TIMER(FTM_MESSAGES);
  1312. if (!restoreErrorTrap())
  1313. {
  1314. llwarns << " Someone took over my signal/exception handler !"
  1315. << llendl;
  1316. }
  1317. gWindowp->gatherInput();
  1318. }
  1319. if (!isExiting())
  1320. {
  1321. // Scan keyboard for movement keys. Command keys and typing are handled
  1322. // by windows callbacks. Do not do this until we are done initializing.
  1323. if (gViewerWindowp && gKeyboardp && gWindowp->getVisible() &&
  1324. gViewerWindowp->getActive() && !gWindowp->getMinimized() &&
  1325. LLStartUp::isLoggedIn() && !gViewerWindowp->getShowProgress() &&
  1326. !gFocusMgr.focusLocked())
  1327. {
  1328. joystick->scanJoystick();
  1329. gKeyboardp->scanKeyboard();
  1330. }
  1331. // Update state based on messages, user input, object idle.
  1332. {
  1333. LL_FAST_TIMER(FTM_IDLE);
  1334. idle();
  1335. {
  1336. LL_FAST_TIMER(FTM_PUMP);
  1337. {
  1338. LL_FAST_TIMER(FTM_PUMP_EVENT);
  1339. // Canonical per-frame event
  1340. mainloop.post(new_frame);
  1341. // Give listeners a chance to run
  1342. llcoro::suspend();
  1343. }
  1344. {
  1345. LL_FAST_TIMER(FTM_PUMP_SERVICE);
  1346. gServicePumpIOp->pump();
  1347. }
  1348. }
  1349. }
  1350. if (sDoDisconnect && LLStartUp::isLoggedIn())
  1351. {
  1352. saveFinalSnapshot();
  1353. disconnectViewer();
  1354. }
  1355. // Render scene.
  1356. if (!isExiting())
  1357. {
  1358. gRLInterface.mRenderLimitRenderedThisFrame = false;
  1359. display();
  1360. if (gUsePBRShaders)
  1361. {
  1362. gPipeline.mReflectionMapManager.update();
  1363. }
  1364. LLFloaterSnapshot::update(); // Take any snapshot
  1365. }
  1366. }
  1367. #if LL_LINUX && !LL_CALL_SLURL_DISPATCHER_IN_CALLBACK
  1368. const std::string& url = getReceivedSLURL();
  1369. if (!url.empty())
  1370. {
  1371. LLMediaCtrl* web = NULL;
  1372. LLURLDispatcher::dispatch(url, "clicked", web, false);
  1373. clearReceivedSLURL();
  1374. }
  1375. #endif
  1376. // Run background threads and sleep if needed/requested.
  1377. {
  1378. LL_FAST_TIMER(FTM_POST_DISPLAY);
  1379. // Performing this once per frame is enough.
  1380. gMeshRepo.update();
  1381. // Register the actual frame render time (in ms) in the stats, before
  1382. // we would add any frame-limiting delay. HB
  1383. F32 frame_render_time = frame_timer.getElapsedTimeF64() * 1000.0;
  1384. gViewerStats.addRenderTimeStat(frame_render_time);
  1385. if (gDisconnected)
  1386. {
  1387. // Always sleep 10ms per frame after a spurious disconnection to
  1388. // avoid excessive CPU and GPU usage while just rendering the UI...
  1389. gFrameSleepTime = 10;
  1390. }
  1391. else if (LLStartUp::isLoggedIn())
  1392. {
  1393. // Reset at each frame once logged in and not yet disconnected
  1394. gFrameSleepTime = 0;
  1395. }
  1396. // See if we must yield cooperatively when not running as foreground
  1397. // window.
  1398. static LLCachedControl<U32> bg_yield_time(gSavedSettings,
  1399. "BackgroundYieldTime");
  1400. bool must_yield = bg_yield_time > 0 &&
  1401. gFrameSleepTime < (U32)bg_yield_time &&
  1402. (!gFocusMgr.getAppHasFocus() ||
  1403. (gWindowp && !gWindowp->getVisible()));
  1404. if (must_yield)
  1405. {
  1406. if (bg_yield_time > 500)
  1407. {
  1408. llwarns << "Out of range BackgroundYieldTime setting; resetting to default (40ms)."
  1409. << llendl;
  1410. gFrameSleepTime = 40;
  1411. gSavedSettings.setU32("BackgroundYieldTime", gFrameSleepTime);
  1412. }
  1413. else
  1414. {
  1415. gFrameSleepTime = bg_yield_time;
  1416. }
  1417. }
  1418. // See if we wish to limit the frame rate. HB
  1419. F64 target_time = 0.0;
  1420. static LLCachedControl<U32> max_fps(gSavedSettings, "FrameRateLimit");
  1421. if (max_fps >= 20 && !gScreenIsDirty)
  1422. {
  1423. target_time = 1.0 / F64(max_fps);
  1424. // If we need to yield, do not use the "free time" to perform
  1425. // ancillary tasks and just use the largest value (between the
  1426. // yield time and the target time) as a sleep time.
  1427. if (gFrameSleepTime)
  1428. {
  1429. gFrameSleepTime = llmax(gFrameSleepTime,
  1430. U32(target_time * 1000.0));
  1431. target_time = 0.0;
  1432. }
  1433. }
  1434. bool fps_limiting = target_time > 0.0;
  1435. bool has_been_limited = false;
  1436. S32 work_pending;
  1437. // Limit the number of additional image updates iterations to avoid
  1438. // excessive image re-decoding per frame, that would cause excessive
  1439. // bound GL textures usage in some circumstances.
  1440. static LLCachedControl<U32> max_updates(gSavedSettings,
  1441. "MaxExtraImagesUpdates");
  1442. U32 image_updates_iterations = llmin(10, max_updates);
  1443. if (LLViewerTexture::sDesiredDiscardBias >= 4.5f)
  1444. {
  1445. // Do not do additional passes when we are trying to free up
  1446. // the textures in excess: this is counterproductive ! HB
  1447. image_updates_iterations = 0;
  1448. }
  1449. static LLTimer work_timer;
  1450. static LLTimer limiting_timer;
  1451. F64 last_work_time = 0.0;
  1452. F64 last_limiting_time = 0.005; // Estimated minimum for first loop
  1453. do
  1454. {
  1455. // Perform this work at least once per frame, and as much times as
  1456. // we can fit it while frame-limiting.
  1457. if (!has_been_limited ||
  1458. target_time > frame_timer.getElapsedTimeF64() + last_work_time)
  1459. {
  1460. work_timer.reset();
  1461. {
  1462. LL_FAST_TIMER(FTM_TEXTURE_CACHE);
  1463. // Unpauses the texture cache thread
  1464. work_pending = gTextureCachep->update();
  1465. }
  1466. {
  1467. LL_FAST_TIMER(FTM_DECODE);
  1468. // Unpauses the image thread
  1469. work_pending += gImageDecodeThreadp->getPending();
  1470. }
  1471. {
  1472. LL_FAST_TIMER(FTM_FETCH);
  1473. // Unpauses the texture fetch thread
  1474. work_pending += gTextureFetchp->update();
  1475. }
  1476. last_work_time = work_timer.getElapsedTimeF64();
  1477. }
  1478. // When frame-rate limiting, use the "free time" at best instead of
  1479. // just sleeping... HB
  1480. if (fps_limiting &&
  1481. target_time > frame_timer.getElapsedTimeF64() +
  1482. last_limiting_time)
  1483. {
  1484. LL_FAST_TIMER(FTM_FPS_LIMITING);
  1485. limiting_timer.reset();
  1486. has_been_limited = true;
  1487. // Do useful stuff at each loop.
  1488. if (image_updates_iterations)
  1489. {
  1490. --image_updates_iterations;
  1491. gTextureList.updateImages(0.002f);
  1492. }
  1493. // Pump again UDP services.
  1494. gServicePumpIOp->pump();
  1495. // Yield to other coroutines in this thread.
  1496. llcoro::suspend();
  1497. // Process any event poll message received while yielding.
  1498. LLEventPoll::dispatchMessages();
  1499. last_limiting_time = limiting_timer.getElapsedTimeF64();
  1500. }
  1501. // Sleep for 1ms if we still have more than that amount of time
  1502. // to wait; this lets time for threads to finish some work that
  1503. // we will be able to recover at next loop.
  1504. if (fps_limiting &&
  1505. target_time > frame_timer.getElapsedTimeF64() + 0.001)
  1506. {
  1507. LL_FAST_TIMER(FTM_SLEEP);
  1508. has_been_limited = true;
  1509. sleep_viewer(1);
  1510. }
  1511. }
  1512. while (fps_limiting &&
  1513. target_time > frame_timer.getElapsedTimeF64() + 0.001);
  1514. // Pause texture fetching threads if nothing to process or yielding
  1515. if (!work_pending || must_yield)
  1516. {
  1517. pauseTextureFetch();
  1518. }
  1519. if (must_yield)
  1520. {
  1521. // Subtract the time taken to render this frame from the sleep
  1522. // time, but sleep at least for half the configured sleep time.
  1523. U32 frame_time = U32(1000.0 * frame_timer.getElapsedTimeF64());
  1524. if (2 * frame_time < gFrameSleepTime)
  1525. {
  1526. gFrameSleepTime -= frame_time;
  1527. }
  1528. else if (gFrameSleepTime > 1)
  1529. {
  1530. gFrameSleepTime /= 2;
  1531. }
  1532. else
  1533. {
  1534. // And sleep at the strict minimum for 1ms anyway...
  1535. gFrameSleepTime = 1;
  1536. }
  1537. }
  1538. if (gStatusBarp)
  1539. {
  1540. // Set the status bar fps counter to white when we have limited
  1541. // the frame rate or have been yielding to the OS. HB
  1542. gStatusBarp->setFrameRateLimited(has_been_limited ||
  1543. gFrameSleepTime);
  1544. }
  1545. // Update FPS statistics when not yielding and only when in
  1546. // foreground. HB
  1547. if (!gFrameSleepTime && gFocusMgr.getAppHasFocus())
  1548. {
  1549. gForegroundTime.unpause();
  1550. ++gForegroundFrameCount;
  1551. }
  1552. else
  1553. {
  1554. gForegroundTime.pause();
  1555. }
  1556. if (gFrameSleepTime)
  1557. {
  1558. LL_FAST_TIMER(FTM_SLEEP);
  1559. sleep_viewer(gFrameSleepTime);
  1560. }
  1561. }
  1562. }
  1563. // Runs the main loop until time to quit. NOTE: for macOS, this method returns
  1564. // at each frame, while for Linux and Windows, it only returns on shutdown.
  1565. bool LLAppViewer::mainLoop()
  1566. {
  1567. static bool init_needed = true;
  1568. if (init_needed)
  1569. {
  1570. init_needed = false;
  1571. // Create IO Pump
  1572. gServicePumpIOp = new LLPumpIO();
  1573. gMainloopWorkp = new LLWorkQueue("mainloop");
  1574. LLViewerJoystick::getInstance()->setNeedsReset(true);
  1575. }
  1576. LLEventPump& mainloop = gEventPumps.obtain("mainloop");
  1577. #if LL_DARWIN
  1578. if (!isExiting())
  1579. #else
  1580. while (!isExiting())
  1581. #endif
  1582. {
  1583. #if LL_FAST_TIMERS_ENABLED
  1584. // Must be outside of any timer instances
  1585. LLFastTimer::enabledFastTimers(gEnableFastTimers);
  1586. LLFastTimer::reset();
  1587. #endif
  1588. frame(mainloop);
  1589. #if TRACY_ENABLE
  1590. FrameMark;
  1591. #endif
  1592. }
  1593. #if LL_DARWIN
  1594. else
  1595. #endif
  1596. {
  1597. // Save snapshot for next time, if we made it through initialization
  1598. if (LLStartUp::isLoggedIn())
  1599. {
  1600. saveFinalSnapshot();
  1601. }
  1602. delete gServicePumpIOp;
  1603. gServicePumpIOp = NULL;
  1604. llinfos << "Exiting main loop." << llendl;
  1605. }
  1606. #if LL_DARWIN
  1607. return isExiting();
  1608. #else
  1609. return true;
  1610. #endif
  1611. }
  1612. bool LLAppViewer::cleanup()
  1613. {
  1614. llinfos << "Cleaning up..." << llendl;
  1615. gVoiceClient.terminate();
  1616. llinfos << "LLVoiceClient terminated" << llendl;
  1617. #if TRACY_ENABLE
  1618. // Let any profiler run to allow examining data after the session
  1619. HBTracyProfiler::detach();
  1620. #endif
  1621. if (gWindowp && gSavedSettings.getBool("MinimizeOnClose"))
  1622. {
  1623. llinfos << "Minimizing the viewer windows." << llendl;
  1624. gWindowp->minimize();
  1625. }
  1626. HBViewerAutomation::cleanup();
  1627. HBFloaterBump::cleanup();
  1628. // Ditch LLVOAvatarSelf instance
  1629. gAgentAvatarp = NULL;
  1630. llinfos << "LLVOAvatarSelf destroyed" << llendl;
  1631. disconnectViewer();
  1632. llinfos << "Viewer disconnected" << llendl;
  1633. // Shut down any still running SLPlugin instance; we make use of the
  1634. // mainloop pumping below, to give plugins a chance to exit cleanly. HB
  1635. llinfos << "Asking any remaining plugins to shutdown..." << llendl;
  1636. LLPluginProcessParent::shutdown();
  1637. // Cleanup the environment class now, since it uses a pump on experiences
  1638. gEnvironment.cleanupClass();
  1639. // Let some time for coroutines and plugins to notice and exit
  1640. llinfos << "Pumping 'mainloop' to let coroutines and plugins shut down..."
  1641. << llendl;
  1642. LLEventPump& mainloop = gEventPumps.obtain("mainloop");
  1643. LLSD frame_llsd;
  1644. gLogoutTimer.reset(); // Let's reuse an existing timer...
  1645. bool first_try = true;
  1646. while (first_try || gCoros.hasActiveCoroutines())
  1647. {
  1648. mainloop.post(frame_llsd);
  1649. // Give listeners a chance to run
  1650. llcoro::suspend();
  1651. if (gLogoutTimer.getElapsedTimeF64() > 0.5)
  1652. {
  1653. if (first_try)
  1654. {
  1655. first_try = false;
  1656. // Abort remaining suspended HTTP operations
  1657. LLCoreHttpUtil::HttpCoroutineAdapter::cleanup();
  1658. // And retry...
  1659. gLogoutTimer.reset();
  1660. continue;
  1661. }
  1662. break;
  1663. }
  1664. }
  1665. gCoros.printActiveCoroutines();
  1666. // Stop the plugin read thread if it is running.
  1667. LLPluginProcessParent::setUseReadThread(false);
  1668. #if 1 // This should not be necessary any more (reset() is now called in
  1669. // ~LLEventPumps()), but it does not hurt, so just in case... HB
  1670. // Workaround for DEV-35406 crash on shutdown
  1671. gEventPumps.reset();
  1672. llinfos << "LLEventPumps reset" << llendl;
  1673. #endif
  1674. gEventPumps.clear();
  1675. llinfos << "LLEventPumps cleared" << llendl;
  1676. // Flag all elements as needing to be destroyed immediately to ensure
  1677. // shutdown order
  1678. LLMortician::setZealous(true);
  1679. llinfos << "LLMortician::setZealous() called" << llendl;
  1680. // Note, we do this early in case of a crash when cleaning up the UI or
  1681. // threads. This way, user settings and data get saved despite the crash...
  1682. llinfos << "Saving data..." << llendl;
  1683. // Quitting with "Remember login credentials" turned off should always
  1684. // stomp your saved password, whether or not you successfully logged in.
  1685. if (!mIsSiblingViewer && !gSavedSettings.getBool("RememberLogin"))
  1686. {
  1687. gSavedSettings.setString("HashedPassword", "");
  1688. }
  1689. gSavedSettings.setString("VersionChannelName", LL_CHANNEL);
  1690. saveGlobalSettings();
  1691. // PerAccountSettingsFile is empty if the user never logged on.
  1692. std::string filename = gSavedSettings.getString("PerAccountSettingsFile");
  1693. if (filename.empty())
  1694. {
  1695. llinfos << "Not saving per-account settings; no account name yet."
  1696. << llendl;
  1697. }
  1698. else if (!mSavePerAccountSettings)
  1699. {
  1700. llinfos << "Not saving per-account settings; last login was not successful."
  1701. << llendl;
  1702. }
  1703. else
  1704. {
  1705. //MK
  1706. if (gRLenabled)
  1707. {
  1708. gRLInterface.refreshTPflag(false);
  1709. }
  1710. // Do this even if !gRLenabled
  1711. gRLInterface.validateLastStandingLoc();
  1712. //mk
  1713. // Store the time of our current logoff
  1714. gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
  1715. gSavedPerAccountSettings.saveToFile(filename);
  1716. }
  1717. llinfos << "All user settings saved" << llendl;
  1718. if (gSavedSettings.getBool("SaveFileSelectorPaths"))
  1719. {
  1720. // Save the file selector default paths
  1721. HBFileSelector::saveDefaultPaths("selector_paths.xml");
  1722. llinfos << "selector_paths.xml saved" << llendl;
  1723. }
  1724. // Save URL history file
  1725. LLURLHistory::saveFile("url_history.xml");
  1726. llinfos << "url_history.xml saved" << llendl;
  1727. // Save mute list if needed.
  1728. LLMuteList::cache();
  1729. display_cleanup();
  1730. gStartTexture = NULL;
  1731. llinfos << "Display cleaned up" << llendl;
  1732. LLError::logToFixedBuffer(NULL);
  1733. llinfos << "Stopped logging to fixed buffer" << llendl;
  1734. // Shut down mesh streamer
  1735. gMeshRepo.shutdown();
  1736. llinfos << "Mesh repository shut down" << llendl;
  1737. // Must clean up texture references before viewer window is destroyed.
  1738. LLHUDManager::updateEffects();
  1739. LLHUDObject::updateAll();
  1740. LLHUDManager::cleanupEffects();
  1741. LLHUDObject::cleanupHUDObjects();
  1742. llinfos << "HUD objects cleaned up" << llendl;
  1743. LLKeyframeDataCache::clear();
  1744. LLHUDManager::cleanupClass();
  1745. llinfos << "HUD manager shut down" << llendl;
  1746. LLMaterialMgr::cleanupClass();
  1747. LLLocalGLTFMaterial::cleanupClass();
  1748. llinfos << "Local materials cleaned up" << llendl;
  1749. LLLocalBitmap::cleanupClass();
  1750. llinfos << "Local bitmaps cleaned up" << llendl;
  1751. delete gAssetStoragep;
  1752. gAssetStoragep = NULL;
  1753. llinfos << "Asset storage deleted" << llendl;
  1754. LLPolyMesh::freeAllMeshes();
  1755. llinfos << "All polymeshes freed" << llendl;
  1756. LLAvatarNameCache::cleanupClass();
  1757. delete gCacheNamep;
  1758. gCacheNamep = NULL;
  1759. llinfos << "Name cache cleaned up" << llendl;
  1760. // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be
  1761. // deleted.
  1762. gWorldMap.reset(); // Release any images
  1763. llinfos << "World map images cleared" << llendl;
  1764. LLStartUp::shutdownAudioEngine();
  1765. llinfos << "Audio engine shut down" << llendl;
  1766. // Note: this is where gFeatureManager used to be deleted.
  1767. // Patch up settings for next time. Must do this before we delete the
  1768. // viewer window, such that we can suck rectangle information out of it.
  1769. cleanupSavedSettings();
  1770. llinfos << "Settings patched up" << llendl;
  1771. if (!mSecondInstance)
  1772. {
  1773. // Delete some of the files left around in the cache.
  1774. // But only do this if no other instance is running !
  1775. removeCacheFiles("*.wav");
  1776. removeCacheFiles("*.tmp");
  1777. removeCacheFiles("*.lso");
  1778. removeCacheFiles("*.out");
  1779. removeCacheFiles("*.dsf");
  1780. removeCacheFiles("*.bodypart");
  1781. removeCacheFiles("*.clothing");
  1782. llinfos << "Temporary cache files removed" << llendl;
  1783. }
  1784. // Destroy the UI
  1785. LLFloaterInventory::cleanup();
  1786. LLUI::deleteSingletonInstances();
  1787. if (gViewerWindowp)
  1788. {
  1789. gViewerWindowp->shutdownViews();
  1790. llinfos << "Shut down views" << llendl;
  1791. }
  1792. LLMortician::updateClass();
  1793. // Cleanup inventory after the UI since it will delete any remaining
  1794. // observers (deleted observers should have already removed themselves)
  1795. stop_new_inventory_observer();
  1796. gInventory.cleanupInventory();
  1797. llinfos << "Inventory cleaned up" << llendl;
  1798. LLGLTFSceneManager::cleanup();
  1799. // Clean up selections in selections manager after UI is destroyed, as UI
  1800. // may be observing them. Also, clean up before GL is shut down because we
  1801. // might be holding onto objects with texture references
  1802. gSelectMgr.clearSelections();
  1803. llinfos << "Selections cleaned up" << llendl;
  1804. // Shut down OpenGL
  1805. if (gViewerWindowp)
  1806. {
  1807. gViewerWindowp->shutdownGL();
  1808. delete gViewerWindowp;
  1809. gViewerWindowp = NULL;
  1810. llinfos << "Viewer window deleted" << llendl;
  1811. }
  1812. LLSplashScreen::show();
  1813. LLSplashScreen::update("Cleaning up...");
  1814. // Viewer UI relies on keyboard so keep it aound until viewer UI is gone
  1815. delete gKeyboardp;
  1816. gKeyboardp = NULL;
  1817. llinfos << "Keyboard handler destroyed" << llendl;
  1818. // Turn off Space Navigator and similar devices
  1819. LLViewerJoystick::getInstance()->terminate();
  1820. llinfos << "Joystick handler terminated" << llendl;
  1821. LLViewerObject::cleanupVOClasses();
  1822. llinfos << "Viewer objects cleaned up" << llendl;
  1823. LLAvatarAppearance::cleanupClass();
  1824. llinfos << "Avatar appearance cleaned up" << llendl;
  1825. LLVolumeMgr::cleanupClass();
  1826. gViewerParcelMgr.cleanupClass();
  1827. // *Note: this is where gViewerStats used to be deleted.
  1828. LLFollowCamMgr::cleanupClass();
  1829. llinfos << "LLFollowCamMgr cleaned up" << llendl;
  1830. LLPanelWorldMap::cleanupClass();
  1831. llinfos << "LLPanelWorldMap cleaned up" << llendl;
  1832. LLFolderViewItem::cleanupClass();
  1833. llinfos << "LLFolderViewItem cleaned up" << llendl;
  1834. LLUI::cleanupClass();
  1835. llinfos << "LLUI cleaned up" << llendl;
  1836. // Must do this (again) after all panels have been deleted because panels
  1837. // that have persistent rects save their rects on delete.
  1838. saveGlobalSettings();
  1839. llinfos << "User settings saved again to update closed floaters rects"
  1840. << llendl;
  1841. LLMuteList::shutDownClass();
  1842. removeMarkerFile(); // Any crashes from here on we will just have to ignore
  1843. llinfos << "Removed marker files" << llendl;
  1844. writeDebugInfo();
  1845. llinfos << "Shutting down Threads..." << llendl;
  1846. // Let threads finish
  1847. gLogoutTimer.reset(); // Let's reuse an existing timer...
  1848. while (true)
  1849. {
  1850. S32 pending = 0;
  1851. // Un-pause the cache worker, image worker and texture fetcher threads
  1852. pending += gTextureCachep->update();
  1853. pending += gImageDecodeThreadp->getPending();
  1854. pending += gTextureFetchp->update();
  1855. size_t remaining = 0;
  1856. gMainloopWorkp->runFor(std::chrono::milliseconds(1), &remaining);
  1857. pending += remaining;
  1858. if (pending == 0)
  1859. {
  1860. break;
  1861. }
  1862. if (gLogoutTimer.getElapsedTimeF64() >= 5.0)
  1863. {
  1864. llwarns << "Quitting with pending background tasks." << llendl;
  1865. break;
  1866. }
  1867. }
  1868. // Delete workers first: shutdown all worker threads before deleting them
  1869. // in case of co-dependencies.
  1870. mAppCoreHttp.requestStop();
  1871. gTextureFetchp->shutdown();
  1872. gTextureCachep->shutdown();
  1873. gImageDecodeThreadp->shutdown();
  1874. gMainloopWorkp->close();
  1875. mGeneralThreadPool->close();
  1876. llinfos << "Threads shut down, cleaning up threads..." << llendl;
  1877. end_messaging_system();
  1878. llinfos << "Message system deleted." << llendl;
  1879. // LLCore::Http libcurl library
  1880. mAppCoreHttp.cleanup();
  1881. llinfos << "LLCore HTTP cleaned up." << llendl;
  1882. // MUST happen AFTER mAppCoreHttp.cleanup();
  1883. delete gTextureCachep;
  1884. gTextureCachep = NULL;
  1885. delete gTextureFetchp;
  1886. gTextureFetchp = NULL;
  1887. delete gImageDecodeThreadp;
  1888. gImageDecodeThreadp = NULL;
  1889. delete gMainloopWorkp;
  1890. gMainloopWorkp = NULL;
  1891. delete mGeneralThreadPool;
  1892. mGeneralThreadPool = NULL;
  1893. LLImageGLThread::cleanup();
  1894. llinfos << "Image caching/fetching/decoding threads destroyed."
  1895. << llendl;
  1896. LLViewerMediaFocus::cleanupClass();
  1897. LLViewerMedia::cleanupClass();
  1898. LLViewerParcelMedia::cleanupClass();
  1899. llinfos << "Media classes cleaned up." << llendl;
  1900. // Call this again (already done via gViewerWindowp->shutdownGL() above),
  1901. // in case new images have been generated during media classes cleanup.
  1902. gTextureList.shutdown();
  1903. LLUIImageList::getInstance()->cleanUp();
  1904. // This should eventually be done in LLAppViewer
  1905. LLImage::cleanupClass();
  1906. // This must be done *after* the texture cache is stopped
  1907. if (mPurgeOnExit)
  1908. {
  1909. llinfos << "Purging all cache files on exit..." << llendl;
  1910. LLDirIterator::deleteFilesInDir(gDirUtil.getCacheDir());
  1911. llinfos << "Cache files purged." << llendl;
  1912. }
  1913. // Cleanup settings last in case other clases reference them
  1914. gSavedSettings.cleanup();
  1915. gColors.cleanup();
  1916. LLProxy::cleanupClass();
  1917. llinfos << "LLProxy cleaned up." << llendl;
  1918. LLCore::LLHttp::cleanup();
  1919. llinfos << "LLCoreHttp cleaned up." << llendl;
  1920. LLWearableType::cleanupClass();
  1921. llinfos << "Wearable types cleaned up." << llendl;
  1922. if (gAvatarAppDictp)
  1923. {
  1924. delete gAvatarAppDictp;
  1925. llinfos << "Avatar appearance dictionnary cleaned up." << llendl;
  1926. }
  1927. LLSettingsType::cleanupClass();
  1928. llinfos << "Settings types cleaned up." << llendl;
  1929. #if LL_UUID_ALIGMENT_STATS
  1930. llinfos << "Number of created LLUUIDs per address alignment:\n";
  1931. U64 total = 0;
  1932. for (U32 i = 0; i < 8; ++i)
  1933. {
  1934. total += LLUUID::sAlignmentCounts[i];
  1935. }
  1936. for (U32 i = 0; i < 8; ++i)
  1937. {
  1938. U64 number = LLUUID::sAlignmentCounts[i];
  1939. llcont << " - " << i << ": " << number << " ("
  1940. << F32(1000L * number / total) * 0.1f << "%)\n";
  1941. }
  1942. llcont << llendl;
  1943. #endif
  1944. LLMemory::cleanupClass();
  1945. llinfos << "Goodbye." << llendl;
  1946. // This is needed to ensure that the log file is properly flushed,
  1947. // especially under Linux (there is apparently a destructors ordering
  1948. // issue that prevents it to flush and close naturally otherwise)...
  1949. LLError::logToFile("");
  1950. // Rename the log if needed
  1951. renameLog(true);
  1952. LLSplashScreen::hide();
  1953. return true;
  1954. }
  1955. void LLAppViewer::initThreads()
  1956. {
  1957. // Do not set affinity if a first Cool VL Viewer instance is already
  1958. // running... This would be detrimental to both instances.
  1959. if (!mIsSiblingViewer)
  1960. {
  1961. // Set the CPU affinity for the main thread; the affinity for all child
  1962. // threads will be set to the complementary of this affinity, so that
  1963. // they run on other cores than the main thread. This call must be done
  1964. // before we start any LLThread if we want the corresponding affinity
  1965. // set on them. When MainThreadCPUAffinity is 0 (or, for now, under
  1966. // Darwin and Windows) this call is a no-operation and no affinity is
  1967. // set for any threads. HB
  1968. U32 cpu_mask = gSavedSettings.getU32("MainThreadCPUAffinity");
  1969. LLCPUInfo::setMainThreadCPUAffinifty(cpu_mask);
  1970. }
  1971. // Initialize the LLCore::Http libcurl library and its thread. It must be
  1972. // called before consumers.
  1973. mAppCoreHttp.init();
  1974. llinfos << "LLCore::Http initialized. libcurl version is: "
  1975. << LLCore::LLHttp::getCURLVersion() << llendl;
  1976. // Image decoding
  1977. U32 decode_threads = gSavedSettings.getU32("NumImageDecodeThreads");
  1978. gImageDecodeThreadp = new LLImageDecodeThread(decode_threads);
  1979. gTextureCachep = new LLTextureCache();
  1980. gTextureFetchp = new LLTextureFetch();
  1981. LLImage::initClass();
  1982. // Mesh streaming and caching
  1983. gMeshRepo.init();
  1984. // General threads pool
  1985. U32 general_threads = gSavedSettings.getU32("ThreadsPoolSize");
  1986. if (!general_threads)
  1987. {
  1988. general_threads = LLCPUInfo::getInstance()->getMaxThreadConcurrency();
  1989. // Half the recommended max thread concurrency for this CPU,
  1990. // rounded up. HB
  1991. general_threads = general_threads / 2 + 1;
  1992. }
  1993. llinfos << "Initializing the \"General\" pool with " << general_threads
  1994. << " threads." << llendl;
  1995. mGeneralThreadPool = new LLThreadPool("General", general_threads);
  1996. // true = wait until all threads are started.
  1997. mGeneralThreadPool->start(true);
  1998. LLAudioDecodeMgr::setGeneralPoolSize(general_threads);
  1999. }
  2000. //static
  2001. void LLAppViewer::errorCallback(const std::string& error_string)
  2002. {
  2003. // Since this is a volontary (controlled) "crash" (llerrs) due to the lack
  2004. // of a fallback path in the viewer code for an unexpected or unhandled
  2005. // situation, let's at least try and quit elegantly, notifying properly the
  2006. // user and logging out cleanly whenever possible ! HB
  2007. static bool called_once = false;
  2008. if (!called_once)
  2009. {
  2010. // Do not try this twice, in case another llerrs would get triggered
  2011. // during OSMessageBox() or sendLogoutRequest() ! HB
  2012. called_once = true;
  2013. OSMessageBox(error_string, "Unrecoverable error");
  2014. // If we have a region, make some attempt to send a logout request
  2015. // first. This prevents the halfway-logged-in avatar from hanging
  2016. // around inworld for a couple minutes. HB
  2017. if (gAgent.getRegion())
  2018. {
  2019. gAppViewerp->sendLogoutRequest();
  2020. }
  2021. // Let some time for the user to read the message box, in case it would
  2022. // get force-closed together with the application, by the OS. HB
  2023. ms_sleep(5000);
  2024. }
  2025. // Set the ErrorActivated global so we know to create a marker file
  2026. sLLErrorActivated = true;
  2027. // Flag status to error
  2028. LLApp::setError();
  2029. // Crash now to generate a stack trace log or crash dump file. HB
  2030. LL_ERROR_CRASH;
  2031. }
  2032. // Sets up logging defaults for the viewer
  2033. void LLAppViewer::initLogging()
  2034. {
  2035. std::string filename = gDirUtil.getFullPath(LL_PATH_APP_SETTINGS);
  2036. LLError::initForApplication(filename);
  2037. LLError::setFatalFunction(errorCallback);
  2038. // Setup our temporary log file name.
  2039. #if LL_WINDOWS
  2040. S32 pid = _getpid();
  2041. #else
  2042. S32 pid = getpid();
  2043. #endif
  2044. filename = llformat(TEMP_LOG_FMT, pid);
  2045. mLogFileName = gDirUtil.getFullPath(LL_PATH_LOGS, filename);
  2046. // Set the log file
  2047. LLError::logToFile(mLogFileName);
  2048. llinfos << "Viewer process id is: " << pid
  2049. << ". Logging to temporary file: " << mLogFileName << llendl;
  2050. }
  2051. void LLAppViewer::renameLog(bool on_exit)
  2052. {
  2053. if (mLogFileName.empty())
  2054. {
  2055. llinfos << "User-supplied log file name. Not renaming it." << llendl;
  2056. return;
  2057. }
  2058. std::string old_log_file = gDirUtil.getFullPath(LL_PATH_LOGS,
  2059. PREVIOUS_LOG);
  2060. if (mSecondInstance && mIsSiblingViewer)
  2061. {
  2062. if (on_exit)
  2063. {
  2064. // Remove the last PREVIOUS_LOG log file, if any.
  2065. LLFile::remove(old_log_file);
  2066. // Rename our log as PREVIOUS_LOG
  2067. LLFile::rename(mLogFileName, old_log_file);
  2068. #if 0 // Log file already closed at this point: do not restart logging !
  2069. LLError::setLogFileName(old_log_file);
  2070. llinfos << "Renamed log file '" << mLogFileName << "' into '"
  2071. << old_log_file << "'" << llendl;
  2072. #endif
  2073. }
  2074. }
  2075. #if LL_WINDOWS // Windows cannot rename a file which is in use... Bleh !
  2076. else if (on_exit)
  2077. #else
  2078. else if (!on_exit)
  2079. #endif
  2080. {
  2081. // Remove the last PREVIOUS_LOG log file, if any.
  2082. LLFile::remove(old_log_file);
  2083. std::string log_file = gDirUtil.getFullPath(LL_PATH_LOGS, CURRENT_LOG);
  2084. // Rename the last CURRENT_LOG log file to PREVIOUS_LOG, if any
  2085. if (LLFile::exists(log_file))
  2086. {
  2087. LLFile::rename(log_file, old_log_file);
  2088. }
  2089. // Rename our log as CURRENT_LOG
  2090. LLFile::rename(mLogFileName, log_file);
  2091. #if !LL_WINDOWS
  2092. LLError::setLogFileName(log_file);
  2093. llinfos << "Renamed log file '" << mLogFileName << "' into '"
  2094. << log_file << "'" << llendl;
  2095. mLogFileName = log_file;
  2096. #endif
  2097. }
  2098. }
  2099. bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
  2100. bool set_defaults)
  2101. {
  2102. // Find and vet the location key.
  2103. if (!mSettingsLocationList.has(location_key))
  2104. {
  2105. LL_DEBUGS("AppInit") << "Requested unknown location: "
  2106. << location_key << LL_ENDL;
  2107. return false;
  2108. }
  2109. LLSD location = mSettingsLocationList.get(location_key);
  2110. if (!location.has("PathIndex"))
  2111. {
  2112. llerrs << "Settings location is missing PathIndex value. Settings cannot be loaded."
  2113. << llendl;
  2114. }
  2115. ELLPath path_index = (ELLPath)(location.get("PathIndex").asInteger());
  2116. if (path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
  2117. {
  2118. llerrs << "Out of range path index in app_settings/settings_files.xml"
  2119. << llendl;
  2120. }
  2121. // Iterate through the locations list of files.
  2122. LLSD files = location.get("Files");
  2123. for (LLSD::map_iterator it = files.beginMap(); it != files.endMap(); ++it)
  2124. {
  2125. std::string settings_group = it->first;
  2126. llinfos << "Attempting to load settings for the group '"
  2127. << settings_group << "' from location '" << location_key << "'"
  2128. << llendl;
  2129. if (gSettings.find(settings_group) == gSettings.end())
  2130. {
  2131. llwarns << "No matching settings group for name " << settings_group
  2132. << llendl;
  2133. continue;
  2134. }
  2135. LLSD file = it->second;
  2136. std::string full_settings_path;
  2137. if (file.has("NameFromSetting"))
  2138. {
  2139. std::string custom_settings = file.get("NameFromSetting");
  2140. // *NOTE: Regardless of the group currently being lodaed, this
  2141. // settings file is always read from the Global settings.
  2142. if (gSettings[sGlobalSettingsName]->controlExists(custom_settings.c_str()))
  2143. {
  2144. full_settings_path =
  2145. gSettings[sGlobalSettingsName]->getString(custom_settings.c_str());
  2146. }
  2147. }
  2148. if (full_settings_path.empty())
  2149. {
  2150. std::string file_name = file.get("Name");
  2151. full_settings_path = gDirUtil.getFullPath(path_index, file_name);
  2152. }
  2153. S32 requirement = 0;
  2154. if (file.has("Requirement"))
  2155. {
  2156. requirement = file.get("Requirement").asInteger();
  2157. }
  2158. if (requirement != 1 && !LLFile::exists(full_settings_path))
  2159. {
  2160. llinfos << "Ignoring absent settings file: " << full_settings_path
  2161. << llendl;
  2162. return false;
  2163. }
  2164. if (!gSettings[settings_group]->loadFromFile(full_settings_path,
  2165. set_defaults))
  2166. {
  2167. if (requirement == 1)
  2168. {
  2169. llwarns << "Error: Cannot load required settings file from: "
  2170. << full_settings_path << llendl;
  2171. return false;
  2172. }
  2173. llwarns << "Cannot load " << full_settings_path
  2174. << " - No settings found." << llendl;
  2175. }
  2176. else
  2177. {
  2178. llinfos << "Loaded settings file " << full_settings_path << llendl;
  2179. }
  2180. }
  2181. return true;
  2182. }
  2183. void LLAppViewer::saveGlobalSettings()
  2184. {
  2185. // Do not fight over the global settings between Cool VL Viewer instances
  2186. // pertaining to the same branch (other viewers and viewers of a different
  2187. // branch got a different settings file name, so we do not care).
  2188. if (!mSameBranchViewer)
  2189. {
  2190. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"));
  2191. }
  2192. }
  2193. std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
  2194. const std::string& file)
  2195. {
  2196. if (mSettingsLocationList.has(location_key))
  2197. {
  2198. LLSD location = mSettingsLocationList.get(location_key);
  2199. if (location.has("Files"))
  2200. {
  2201. LLSD files = location.get("Files");
  2202. if (files.has(file) && files[file].has("Name"))
  2203. {
  2204. return files.get(file).get("Name").asString();
  2205. }
  2206. }
  2207. }
  2208. return std::string();
  2209. }
  2210. LLApp::InitState LLAppViewer::initConfiguration()
  2211. {
  2212. // Set up internal pointers
  2213. gSettings[sGlobalSettingsName] = &gSavedSettings;
  2214. gSettings[sPerAccountSettingsName] = &gSavedPerAccountSettings;
  2215. // Load settings files list
  2216. std::string filename = gDirUtil.getFullPath(LL_PATH_APP_SETTINGS,
  2217. "settings_files.xml");
  2218. LLControlGroup settings_control("SettingsFiles");
  2219. llinfos << "Loading settings file list " << filename << llendl;
  2220. if (!settings_control.loadFromFile(filename))
  2221. {
  2222. llwarns << "Cannot load default configuration file '" << filename
  2223. << "'. Aborting." << llendl;
  2224. return INIT_FAILED;
  2225. }
  2226. mSettingsLocationList = settings_control.getLLSD("Locations");
  2227. // The settings and command line parsing have a fragile order-of-operation:
  2228. // - load defaults from app_settings
  2229. // - set procedural settings values
  2230. // - read command line settings
  2231. // - selectively apply settings needed to load user settings.
  2232. // - load overrides from user_settings
  2233. // - apply command line settings (to override the overrides)
  2234. // - load per account settings (happens in llstartup.cpp)
  2235. // - load defaults
  2236. bool set_defaults = true;
  2237. if (!loadSettingsFromDirectory("Default", set_defaults))
  2238. {
  2239. std::ostringstream msg;
  2240. msg << gSecondLife << " could not load its default settings file. \n"
  2241. << "The installation may be corrupted. \n";
  2242. OSMessageBox(msg.str());
  2243. return INIT_FAILED;
  2244. }
  2245. // Set procedural settings
  2246. gSavedSettings.setString("ClientSettingsFile",
  2247. gDirUtil.getFullPath(LL_PATH_USER_SETTINGS,
  2248. getSettingsFilename("User",
  2249. "Global")));
  2250. // Read command line settings.
  2251. filename = gDirUtil.getFullPath(LL_PATH_APP_SETTINGS, "cmd_line.xml");
  2252. LLControlGroupCLP clp;
  2253. clp.configure(filename, &gSavedSettings);
  2254. if (!initParseCommandLine(clp))
  2255. {
  2256. llwarns << "Error parsing command line options. Command Line options ignored."
  2257. << llendl;
  2258. llinfos << "Command line usage:\n" << clp << llendl;
  2259. std::ostringstream msg;
  2260. msg << "An error was found while parsing the command line. Please see:\n"
  2261. << "http://wiki.secondlife.com/wiki/Client_parameters&oldid=878593\n"
  2262. << "or use the --help option to list the available options.\n \n"
  2263. << "Error: " << clp.getErrorMessage();
  2264. OSMessageBox(msg.str());
  2265. return INIT_FAILED;
  2266. }
  2267. // Selectively apply settings
  2268. // If the user has specified an alternate settings file name, load it now
  2269. // before loading the user_settings/settings.xml
  2270. if (clp.hasOption("settings"))
  2271. {
  2272. filename = gDirUtil.getFullPath(LL_PATH_USER_SETTINGS,
  2273. clp.getOption("settings")[0]);
  2274. gSavedSettings.setString("ClientSettingsFile", filename);
  2275. llinfos << "Using command line specified user settings filename: "
  2276. << filename << llendl;
  2277. }
  2278. // Load overrides from user_settings
  2279. if (!loadSettingsFromDirectory("User"))
  2280. {
  2281. // If no user settings file found for current version, try the former
  2282. // experimental branch settings file. HB
  2283. if (!loadSettingsFromDirectory("UserFormerExperimental"))
  2284. {
  2285. // If still no user settings file found, try the former stable
  2286. // branch settings file. HB
  2287. loadSettingsFromDirectory("UserFormerStable");
  2288. }
  2289. }
  2290. // Apply command line settings
  2291. clp.notify();
  2292. // Handle initialization from settings.
  2293. // Start up the debugging console before handling other options.
  2294. #if !LL_DEBUG // always show the console for debug builds
  2295. if (gSavedSettings.getBool("ShowConsoleWindow"))
  2296. #endif
  2297. {
  2298. initConsole();
  2299. }
  2300. if (clp.hasOption("help"))
  2301. {
  2302. std::ostringstream msg;
  2303. msg << "Command line usage:\n" << clp;
  2304. OSMessageBox(msg.str().c_str(), gSecondLife);
  2305. return INIT_OK_EXIT;
  2306. }
  2307. //////////////////////////
  2308. // Apply settings...
  2309. if (clp.hasOption("set"))
  2310. {
  2311. const LLCommandLineParser::token_vector_t& set_values =
  2312. clp.getOption("set");
  2313. if (0x1 & set_values.size())
  2314. {
  2315. llwarns << "Invalid '--set' parameter count." << llendl;
  2316. }
  2317. else
  2318. {
  2319. for (LLCommandLineParser::token_vector_t::const_iterator
  2320. it = set_values.begin(); it != set_values.end(); ++it)
  2321. {
  2322. const std::string& name = *it;
  2323. const std::string& value = *(++it);
  2324. LLControlVariable* c =
  2325. gSettings[sGlobalSettingsName]->getControl(name.c_str());
  2326. if (c)
  2327. {
  2328. c->setValue(value.c_str(), false);
  2329. }
  2330. else
  2331. {
  2332. llwarns << "'--set' specified with unknown setting: '"
  2333. << name << "'." << llendl;
  2334. }
  2335. }
  2336. }
  2337. }
  2338. initGridChoice();
  2339. // Handle slurl use.
  2340. // *NOTE: the command line parser parses tokens and is setup to bail after
  2341. // parsing the '--url' option or the first option specified without an
  2342. // '--option' flag (or any other option that uses the 'last_option'
  2343. // setting. See LLControlGroupCLP::configure())
  2344. if (clp.hasOption("url"))
  2345. {
  2346. std::string url = clp.getOption("url")[0];
  2347. LLSLURL slurl(url);
  2348. LLStartUp::setStartSLURL(slurl);
  2349. if (slurl.getType() == LLSLURL::LOCATION)
  2350. {
  2351. LLGridManager::getInstance()->setGridChoice(slurl.getGrid());
  2352. }
  2353. }
  2354. std::string skin_name = gSavedSettings.getString("SkinCurrent");
  2355. if (skin_name.empty())
  2356. {
  2357. skin_name = "default";
  2358. }
  2359. else if (!gDirUtil.hasSkin(skin_name))
  2360. {
  2361. llwarns << "Invalid skin '" << skin_name
  2362. << "', switching to the default skin." << llendl;
  2363. skin_name = "default";
  2364. gSavedSettings.setString("SkinCurrent", skin_name);
  2365. }
  2366. gDirUtil.setSkinFolder(skin_name);
  2367. // The version number is in the form Mmmmbbbrrr. It is used as a constant
  2368. // #define token by HBPreprocessor, and as a default Lua number constant by
  2369. // HBViewerAutomation. It is designed to be easily compared to and to stay
  2370. // in human readable form. HB
  2371. gViewerVersionNumber = LL_VERSION_MAJOR * 1000 + LL_VERSION_MINOR;
  2372. gViewerVersionNumber *= 1000;
  2373. gViewerVersionNumber += LL_VERSION_BRANCH;
  2374. gViewerVersionNumber *= 1000;
  2375. gViewerVersionNumber += LL_VERSION_RELEASE;
  2376. // The viewer official (i.e. hard-coded) name.
  2377. gSecondLife.assign(LL_CHANNEL);
  2378. // Version number as a string.
  2379. gViewerVersionString = llformat("%d.%d.%d.%d", LL_VERSION_MAJOR,
  2380. LL_VERSION_MINOR, LL_VERSION_BRANCH,
  2381. LL_VERSION_RELEASE);
  2382. // Full viewer official name and its version.
  2383. gViewerVersion = gSecondLife + " " + gViewerVersionString;
  2384. // Display splash screen. Must be after above check for previous crash as
  2385. // this dialog is always frontmost.
  2386. LLSplashScreen::show();
  2387. LLSplashScreen::update("Loading " + gSecondLife + "...");
  2388. LLVolumeMgr::initClass();
  2389. // Note: this is where we used to initialize gFeatureManagerp.
  2390. gStartTime = LLTimer::totalTime();
  2391. //
  2392. // Set the name of the window
  2393. //
  2394. #if LL_DEBUG
  2395. gWindowTitle = gSecondLife + " [DEBUG]";
  2396. #else
  2397. gWindowTitle = gSecondLife;
  2398. #endif
  2399. LLStringUtil::truncate(gWindowTitle, 255);
  2400. // Check for another instance of the app running
  2401. mSecondInstance = anotherInstanceRunning();
  2402. // If we received a SLURL and it is not a login command, hand it off to the
  2403. // existing instance, if any.
  2404. LLSLURL slurl = LLStartUp::getStartSLURL();
  2405. if (slurl.isValid() && slurl.getAppCmd() != "login" && mSecondInstance &&
  2406. sendURLToOtherInstance(slurl.getSLURLString()))
  2407. {
  2408. llinfos << "Sent SLURL '" << slurl.getSLURLString()
  2409. << "' to the already running viewer instance. Exiting."
  2410. << llendl;
  2411. // Let's consider we are also using the same viewer to avoid
  2412. // overwriting the log with our (mostly irrelevant) log.
  2413. mIsSiblingViewer = true;
  2414. renameLog(true); // Rename the log now
  2415. // Successfully handed off URL to existing instance; let's exit now.
  2416. return INIT_OK_EXIT;
  2417. }
  2418. if (mSecondInstance)
  2419. {
  2420. if (gSavedSettings.getBool("AllowMultipleViewers"))
  2421. {
  2422. // This is the second instance of SL. Turn off voice support, but
  2423. // make sure the setting is *not* persisted.
  2424. LLControlVariable* disable_voice =
  2425. gSavedSettings.getControl("CmdLineDisableVoice");
  2426. if (disable_voice)
  2427. {
  2428. disable_voice->setValue(LLSD(true), false);
  2429. }
  2430. }
  2431. else
  2432. {
  2433. std::ostringstream msg;
  2434. msg << "A viewer instance is already running and " << gSecondLife
  2435. << "\nwas configured to refuse to run as a second instance.\n"
  2436. << "You may change that preference if you wish...";
  2437. OSMessageBox(msg.str(), gSecondLife);
  2438. return INIT_FAILED;
  2439. }
  2440. }
  2441. else
  2442. {
  2443. // This is the first instance: check for stale/crash markers and
  2444. // initialize the instance marker.
  2445. initMarkerFile();
  2446. }
  2447. // Need to do this here because we must have initialized global settings
  2448. // first
  2449. std::string next_login_loc = gSavedSettings.getString("NextLoginLocation");
  2450. if (next_login_loc.length())
  2451. {
  2452. LLStartUp::setStartSLURL(LLSLURL(next_login_loc));
  2453. }
  2454. return INIT_OK; // Config was successful.
  2455. }
  2456. bool LLAppViewer::initWindow()
  2457. {
  2458. llinfos << "Initializing window..." << llendl;
  2459. // Linux may reuse the splash screen, even after startup. See the
  2460. // LLViewerShaderMgr::setShaders() method where this is called instead. HB
  2461. #if !LL_LINUX
  2462. // This step may take some time (and could fail), so let's inform the
  2463. // user. HB
  2464. LLSplashScreen::update("Compiling shaders...");
  2465. #endif
  2466. S32 x0 = 0;
  2467. S32 y0 = 0;
  2468. bool full_screen = gSavedSettings.getBool("FullScreen");
  2469. if (!full_screen)
  2470. {
  2471. x0 = gSavedSettings.getS32("WindowX");
  2472. y0 = gSavedSettings.getS32("WindowY");
  2473. }
  2474. U32 width, height;
  2475. LLViewerWindow::getTargetWindow(full_screen, width, height);
  2476. gViewerWindowp = new LLViewerWindow(gWindowTitle, x0, y0, width, height,
  2477. full_screen);
  2478. // Hide the splash screen
  2479. LLSplashScreen::hide();
  2480. // This happens when we do not have the minimum OpenGL requirements.
  2481. if (!LLViewerShaderMgr::sInitialized)
  2482. {
  2483. return false;
  2484. }
  2485. if (gSavedSettings.getBool("WindowMaximized"))
  2486. {
  2487. gWindowp->maximize();
  2488. gWindowp->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
  2489. }
  2490. // Initialize the environment classes
  2491. llinfos << "Initializing environment classes..." << llendl;
  2492. gWLSkyParamMgr.initClass();
  2493. gWLWaterParamMgr.initClass();
  2494. gEnvironment.initClass();
  2495. //
  2496. // Initialize GL stuff
  2497. //
  2498. // Set this flag in case we crash while initializing GL
  2499. gSavedSettings.setBool("RenderInitError", true);
  2500. saveGlobalSettings();
  2501. llinfos << "Initializing the render pipeline..." << llendl;
  2502. gPipeline.init();
  2503. llinfos << "Render pipeline initialized." << llendl;
  2504. gViewerWindowp->initGLDefaults();
  2505. gSavedSettings.setBool("RenderInitError", false);
  2506. saveGlobalSettings();
  2507. LLTrans::init();
  2508. // Set error messages for LLXMLRPCTransaction, now that the strings are
  2509. // parsed.
  2510. LLXMLRPCTransaction::setMessages(LLTrans::getString("server_is_down"),
  2511. LLTrans::getString("dns_not_resolving"),
  2512. LLTrans::getString("cert_not_verified"),
  2513. LLTrans::getString("connect_error"));
  2514. // Show watch cursor
  2515. gViewerWindowp->setCursor(UI_CURSOR_WAIT);
  2516. // Finish view initialization
  2517. gViewerWindowp->initBase();
  2518. // We can now (potentially) enable this.
  2519. LLView::sDebugRects = gSavedSettings.getBool("DebugViews");
  2520. #if LL_LINUX
  2521. // *HACK: this will cause a proper screen refresh by triggering a full
  2522. // redraw event at the SDL level (redrawing at the viewer level is not
  2523. // enough). Without this hack, when shared GL contexts are enabled, you
  2524. // get a "blocky" UI until SDL receives a redraw event (which may take
  2525. // several seconds).
  2526. LLCoordScreen size;
  2527. if (gWindowp->getSize(&size))
  2528. {
  2529. gWindowp->setSize(size);
  2530. }
  2531. #endif
  2532. llinfos << "Window initialization done." << llendl;
  2533. return true;
  2534. }
  2535. void LLAppViewer::writeDebugInfo(bool log_interesting_info)
  2536. {
  2537. // Since the debug_info.log is mostly useless (see the comment below), and
  2538. // is overwritten without care by any other viewer running instances, I
  2539. // made it optional (and OFF by default) in the Cool VL Viewer. HB
  2540. if (gSavedSettings.getBool("WriteDebugInfo"))
  2541. {
  2542. std::string filename = gDirUtil.getFullPath(LL_PATH_LOGS,
  2543. "debug_info.log");
  2544. llinfos << "Opening debug file " << filename << llendl;
  2545. llofstream out_file(filename.c_str());
  2546. if (out_file.is_open())
  2547. {
  2548. LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
  2549. out_file.close();
  2550. }
  2551. }
  2552. if (!log_interesting_info)
  2553. {
  2554. return;
  2555. }
  2556. // Really, this is the only interesting info that has not already been
  2557. // logged (or is hard to find in the log)... HB
  2558. if (gDebugInfo.has("MainloopTimeoutState"))
  2559. {
  2560. llinfos << "Mainloop timeout state: "
  2561. << gDebugInfo["MainloopTimeoutState"].asString() << llendl;
  2562. }
  2563. llinfos << "Grid: " << gDebugInfo["GridName"].asString() << llendl;
  2564. // This info may exist on crashes, and is interesting...
  2565. if (gDebugInfo.has("CurrentLocationX"))
  2566. {
  2567. llinfos << "Agent position: " << gDebugInfo["CurrentRegion"].asString()
  2568. << " " << (S32)gDebugInfo["CurrentLocationX"].asReal()
  2569. << "," << (S32)gDebugInfo["CurrentLocationY"].asReal()
  2570. << "," << (S32)gDebugInfo["CurrentLocationZ"].asReal()
  2571. << llendl;
  2572. if (gDebugInfo.has("ParcelMusicURL"))
  2573. {
  2574. llinfos << "Parcel music URL: "
  2575. << gDebugInfo["ParcelMusicURL"].asString() << llendl;
  2576. }
  2577. if (gDebugInfo.has("ParcelMediaURL"))
  2578. {
  2579. llinfos << "Parcel media URL: "
  2580. << gDebugInfo["ParcelMediaURL"].asString() << llendl;
  2581. }
  2582. }
  2583. }
  2584. void LLAppViewer::cleanupSavedSettings()
  2585. {
  2586. gSavedSettings.setBool("FlyBtnState", false);
  2587. gSavedSettings.setBool("BuildBtnState", false);
  2588. gSavedSettings.setBool("DebugWindowProc", gDebugWindowProc);
  2589. gSavedSettings.setBool("AllowTapTapHoldRun", gAllowTapTapHoldRun);
  2590. gSavedSettings.setBool("ShowObjectUpdates", gShowObjectUpdates);
  2591. if (gDebugViewp && gDebugViewp->mDebugConsolep)
  2592. {
  2593. gSavedSettings.setBool("ShowDebugConsole",
  2594. gDebugViewp->mDebugConsolep->getVisible());
  2595. }
  2596. // Save window position if not fullscreen as we do not track it in
  2597. // callbacks
  2598. if (gWindowp)
  2599. {
  2600. bool fullscreen = gWindowp->getFullscreen();
  2601. bool maximized = gWindowp->getMaximized();
  2602. if (!fullscreen && !maximized)
  2603. {
  2604. LLCoordScreen window_pos;
  2605. if (gWindowp->getPosition(&window_pos))
  2606. {
  2607. gSavedSettings.setS32("WindowX", window_pos.mX);
  2608. gSavedSettings.setS32("WindowY", window_pos.mY);
  2609. }
  2610. }
  2611. }
  2612. gSavedSettings.setF32("MapScale", LLPanelWorldMap::sMapScale);
  2613. gSavedSettings.setBool("ShowHoverTips", LLHoverView::sShowHoverTips);
  2614. // Some things are cached in LLAgent.
  2615. if (gAgent.mInitialized)
  2616. {
  2617. gSavedSettings.setF32("RenderFarClip", gAgent.mDrawDistance);
  2618. }
  2619. }
  2620. void LLAppViewer::removeCacheFiles(const char* file_mask)
  2621. {
  2622. LLDirIterator::deleteFilesInDir(gDirUtil.getCacheDir(), file_mask);
  2623. }
  2624. void LLAppViewer::writeSystemInfo()
  2625. {
  2626. gDebugInfo["SLLog"] = LLError::logFileName();
  2627. gDebugInfo["ClientInfo"]["Name"] =
  2628. gSavedSettings.getString("VersionChannelName");
  2629. gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
  2630. gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
  2631. gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_BRANCH;
  2632. gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_RELEASE;
  2633. gDebugInfo["CRTFilename"] = gDirUtil.getCRTFile();
  2634. // Call LLOSInfo::getInstance() first (before LLCPUInfo::getInstance())
  2635. // so that, under Windows 10+, the timeBeginPeriod(1) call will have been
  2636. // issued to set the sleep time accuracy to 1ms (needed for benchmarking
  2637. // the CPU in LLCPUInfo). HB
  2638. gDebugInfo["RAMInfo"]["Physical"] =
  2639. (LLSD::Integer)LLMemory::getPhysicalMemoryKB();
  2640. gDebugInfo["RAMInfo"]["Allocated"] =
  2641. (LLSD::Integer)(gMemoryAllocated >> 10); // MB -> KB
  2642. gDebugInfo["OSInfo"] = LLOSInfo::getInstance()->getOSStringSimple();
  2643. LLCPUInfo* cpuinfo = LLCPUInfo::getInstance();
  2644. gDebugInfo["CPUInfo"]["CPUString"] = cpuinfo->getCPUString();
  2645. gDebugInfo["CPUInfo"]["CPUFamily"] = cpuinfo->getFamily();
  2646. gDebugInfo["CPUInfo"]["CPUMhz"] = cpuinfo->getMHz();
  2647. gDebugInfo["CPUInfo"]["CPUSSE2"] = cpuinfo->hasSSE2();
  2648. // The user is not logged on yet, but record the current grid choice login url
  2649. // which may have been the intended grid.
  2650. gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
  2651. // *FIX:Mani - move this ddown in llappviewerwin32
  2652. #if LL_WINDOWS
  2653. DWORD thread_id = GetCurrentThreadId();
  2654. gDebugInfo["MainloopThreadID"] = (S32)thread_id;
  2655. #endif
  2656. // "CrashNotHandled" is set here, while things are running well. If the
  2657. // crash is handled by LLAppViewer::handleViewerCrash, i.e. not a freeze,
  2658. // then the value of "CrashNotHandled" will be set to false.
  2659. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
  2660. // Dump some debugging info
  2661. llinfos << gSecondLife << " version " << LL_VERSION_MAJOR << "."
  2662. << LL_VERSION_MINOR << "." << LL_VERSION_BRANCH << "."
  2663. << LL_VERSION_RELEASE << llendl;
  2664. // Dump the local time and time zone
  2665. time_t now;
  2666. time(&now);
  2667. char tbuffer[256];
  2668. strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
  2669. llinfos << "Local time: " << tbuffer << llendl;
  2670. // Query some system information
  2671. llinfos << "CPU info:\n" << LLCPUInfo::getInstance()->getInfo() << llendl;
  2672. llinfos << "Memory info:\n" << LLMemory::getInfo() << llendl;
  2673. llinfos << "OS: " << LLOSInfo::getInstance()->getOSStringSimple()
  2674. << llendl;
  2675. llinfos << "OS info: " << LLOSInfo::getInstance()->getOSString() << llendl;
  2676. llinfos << "CPU single-core benchmarking..." << llendl;
  2677. cpuinfo->benchmarkFactor();
  2678. writeDebugInfo(false); // Save out debug_info.log early, in case of crash.
  2679. }
  2680. //static
  2681. void LLAppViewer::handleSyncViewerCrash()
  2682. {
  2683. // Call to pure virtual, handled by platform specific llappviewer instance.
  2684. gAppViewerp->handleSyncCrashTrace();
  2685. }
  2686. //static
  2687. void LLAppViewer::handleViewerCrash()
  2688. {
  2689. // Free our reserved memory space before dumping the stack trace
  2690. LLMemory::cleanupClass();
  2691. llinfos << "Handle viewer crash entry." << llendl;
  2692. LLMemory::logMemoryInfo();
  2693. if (gAppViewerp) // The crash could happen on app destruction... HB
  2694. {
  2695. // We do not remove the marker file on crash (so that the next running
  2696. // instance can detect that crash and report it at login), but we still
  2697. // make sure the file is unlocked and closed properly (even if this
  2698. // should be automatically done by the OS on program exit). HB
  2699. if (gAppViewerp->mMarkerFile)
  2700. {
  2701. LL_DEBUGS("MarkerFile") << "Marker file unlocked." << LL_ENDL;
  2702. gAppViewerp->mMarkerFile->unlock();
  2703. delete gAppViewerp->mMarkerFile;
  2704. gAppViewerp->mMarkerFile = NULL;
  2705. }
  2706. if (gAppViewerp->beingDebugged())
  2707. {
  2708. // This will drop us into the debugger (if not already done). HB
  2709. abort();
  2710. }
  2711. }
  2712. // We already do this in writeSystemInfo(), but we do it again here to make
  2713. // *sure* we have a version to check against no matter what
  2714. gDebugInfo["ClientInfo"]["Name"] =
  2715. gSavedSettings.getString("VersionChannelName");
  2716. gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
  2717. gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
  2718. gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_BRANCH;
  2719. gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_RELEASE;
  2720. gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
  2721. LLParcel* parcel = gViewerParcelMgr.getAgentParcel();
  2722. if (parcel && parcel->getMusicURL()[0])
  2723. {
  2724. gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
  2725. }
  2726. if (parcel && !parcel->getMediaURL().empty())
  2727. {
  2728. gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
  2729. }
  2730. gDebugInfo["SettingsFilename"] =
  2731. gSavedSettings.getString("ClientSettingsFile");
  2732. gDebugInfo["CRTFilename"] = gDirUtil.getCRTFile();
  2733. gDebugInfo["ViewerExePath"] = gDirUtil.getExecutablePathAndName();
  2734. gDebugInfo["CurrentPath"] = gDirUtil.getCurPath();
  2735. gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
  2736. gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
  2737. gDebugInfo["RAMInfo"]["Allocated"] =
  2738. (LLSD::Integer)(LLMemory::getCurrentRSS() >> 10);
  2739. gDebugInfo["FirstLogin"] = (LLSD::Boolean)gAgent.isFirstLogin();
  2740. gDebugInfo["FirstRunThisInstall"] =
  2741. gSavedSettings.getBool("FirstRunThisInstall");
  2742. if (gLogoutInProgress)
  2743. {
  2744. gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
  2745. }
  2746. else
  2747. {
  2748. gDebugInfo["LastExecEvent"] =
  2749. sLLErrorActivated ? LAST_EXEC_LLERROR_CRASH
  2750. : LAST_EXEC_OTHER_CRASH;
  2751. }
  2752. LLViewerRegion* regionp = gAgent.getRegion();
  2753. if (regionp)
  2754. {
  2755. gDebugInfo["CurrentSimHost"] = regionp->getSimHostName();
  2756. gDebugInfo["CurrentRegion"] = regionp->getName();
  2757. const LLVector3& loc = gAgent.getPositionAgent();
  2758. gDebugInfo["CurrentLocationX"] = loc.mV[0];
  2759. gDebugInfo["CurrentLocationY"] = loc.mV[1];
  2760. gDebugInfo["CurrentLocationZ"] = loc.mV[2];
  2761. }
  2762. // The crash is being handled here so set this value to false.
  2763. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
  2764. // Write out the crash status file. Use marker file style setup, as that is
  2765. // the simplest, especially since we are already in a crash situation.
  2766. std::string filename;
  2767. if (sLLErrorActivated)
  2768. {
  2769. filename = gDirUtil.getFullPath(LL_PATH_LOGS,
  2770. LLERROR_MARKER_FILE_NAME);
  2771. }
  2772. else
  2773. {
  2774. filename = gDirUtil.getFullPath(LL_PATH_LOGS,
  2775. ERROR_MARKER_FILE_NAME);
  2776. }
  2777. llinfos << "Creating crash marker file " << filename << llendl;
  2778. LLFile marker_file(filename, "w");
  2779. if (marker_file)
  2780. {
  2781. if (gAppViewerp)
  2782. {
  2783. gAppViewerp->stampMarkerFile(&marker_file);
  2784. }
  2785. llinfos << "Created marker file " << filename << llendl;
  2786. }
  2787. else
  2788. {
  2789. llwarns << "Cannot create marker file " << filename << llendl;
  2790. }
  2791. if (gMessageSystemp)
  2792. {
  2793. gMessageSystemp->getCircuitInfo(gDebugInfo["CircuitInfo"]);
  2794. gMessageSystemp->stopLogging();
  2795. std::ostringstream stats;
  2796. gMessageSystemp->summarizeLogs(stats);
  2797. gDebugInfo["MessageSystemStats"] = stats.str();
  2798. }
  2799. gWorld.getInfo(gDebugInfo);
  2800. if (gAppViewerp)
  2801. {
  2802. // Close the debug file
  2803. gAppViewerp->writeDebugInfo();
  2804. // Remove the marker file, since we will spawn a process that would
  2805. // otherwise keep it locked
  2806. if (gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
  2807. {
  2808. gAppViewerp->removeMarkerFile(true);
  2809. }
  2810. else
  2811. {
  2812. gAppViewerp->removeMarkerFile(false);
  2813. }
  2814. }
  2815. // This is needed to ensure that the log file is properly flushed,
  2816. // especially under Linux (there is apparently a destructors ordering
  2817. // issue that prevents it to flush and close naturally otherwise)...
  2818. LLError::logToFile("");
  2819. }
  2820. bool LLAppViewer::anotherInstanceRunning()
  2821. {
  2822. // Do not check again since the file will contain gViewerVersion after a
  2823. // successful run of initMarkerFile(). We use mMarkerFileName, initialized
  2824. // in this method, to check for a possible double call... HB
  2825. if (!mMarkerFileName.empty())
  2826. {
  2827. llerrs << "This method must only be called once !" << llendl;
  2828. }
  2829. // We create a marker file when the program starts and remove the file when
  2830. // it finishes. If the file is currently locked, it that means another
  2831. // viewer is already running.
  2832. mMarkerFileName = gDirUtil.getFullPath(LL_PATH_LOGS, MARKER_FILE_NAME);
  2833. if (LLFile::exists(mMarkerFileName))
  2834. {
  2835. // File exists, look at what is inside...
  2836. mIsOurViewer = isOurMarkerFile(mMarkerFileName);
  2837. checkSiblingMarkerFile(mMarkerFileName);
  2838. LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
  2839. // Try opening with appending permissions (*should* fail if locked):
  2840. // Using append to avoid wiping the file contents on success (since we
  2841. // will need to examine that contents later on in initMarkerFile()). HB
  2842. LLFile outfile(mMarkerFileName, "a");
  2843. if (!outfile)
  2844. {
  2845. // Another instance is running. Skip the rest of these operations.
  2846. llinfos << "Cannot open marker file for writing." << llendl;
  2847. return true;
  2848. }
  2849. LL_DEBUGS("MarkerFile") << "Could open the marker file for writing."
  2850. << LL_ENDL;
  2851. // Try acquiring an exclusive lock (shall fail if locked).
  2852. if (!outfile.lock(true))
  2853. {
  2854. llinfos << "Marker file is locked by another instance." << llendl;
  2855. return true;
  2856. }
  2857. #if LL_WINDOWS
  2858. // Ensure the OS immediately releases the lock we just acquired
  2859. outfile.unlock();
  2860. #endif
  2861. LL_DEBUGS("MarkerFile") << "Marker file does not pertain to a running instance."
  2862. << LL_ENDL;
  2863. }
  2864. // No other instance running
  2865. return false;
  2866. }
  2867. // We have got 5 things to check for here:
  2868. // - Other viewer running (SecondLife.exec_marker present, locked)
  2869. // - Freeze (SecondLife.exec_marker present, not locked)
  2870. // - LLError crash (llerror_marker present)
  2871. // - Unexpected crash (error_marker present)
  2872. // - Crash or freeze after logout (logout_marker present)
  2873. // These checks should also remove all but the exec_marker file if they
  2874. // currently exist
  2875. void LLAppViewer::initMarkerFile()
  2876. {
  2877. if (mMarkerFileName.empty())
  2878. {
  2879. // anotherInstanceRunning() must be called before this method: it is
  2880. // responsible for setting the file name and the various flags we use
  2881. // here. HB
  2882. llerrs << "mMarkerFileName must be initialized before calling this method !"
  2883. << llendl;
  2884. }
  2885. // LLError/Error checks. Only one of these should ever happen at a time.
  2886. std::string logout_marker_file =
  2887. gDirUtil.getFullPath(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
  2888. std::string llerror_marker_file =
  2889. gDirUtil.getFullPath(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
  2890. std::string error_marker_file =
  2891. gDirUtil.getFullPath(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
  2892. std::string diagnosis;
  2893. if (!mSecondInstance && LLFile::exists(mMarkerFileName))
  2894. {
  2895. if (mIsOurViewer)
  2896. {
  2897. gLastExecEvent = LAST_EXEC_FROZE;
  2898. diagnosis = "Last session froze unexpectedly";
  2899. }
  2900. else
  2901. {
  2902. llinfos << "An execution marker file has been found but is not ours: another viewer froze..."
  2903. << llendl;
  2904. }
  2905. }
  2906. if (LLFile::exists(logout_marker_file))
  2907. {
  2908. if (isOurMarkerFile(logout_marker_file))
  2909. {
  2910. gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
  2911. diagnosis = "Last session froze after logout";
  2912. }
  2913. else
  2914. {
  2915. llinfos << "A logout marker file has been found but is not ours: another viewer crashed after logout..."
  2916. << llendl;
  2917. }
  2918. LLFile::remove(logout_marker_file);
  2919. }
  2920. if (LLFile::exists(llerror_marker_file))
  2921. {
  2922. if (isOurMarkerFile(llerror_marker_file))
  2923. {
  2924. if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
  2925. {
  2926. gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
  2927. diagnosis = "Last session crashed on a LLError after logout";
  2928. }
  2929. else
  2930. {
  2931. gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
  2932. diagnosis = "Last session crashed on a LLError";
  2933. }
  2934. }
  2935. else
  2936. {
  2937. llinfos << "An LLError marker file has been found but is not ours: another viewer crashed..."
  2938. << llendl;
  2939. }
  2940. LLFile::remove(llerror_marker_file);
  2941. }
  2942. if (LLFile::exists(error_marker_file))
  2943. {
  2944. if (isOurMarkerFile(error_marker_file))
  2945. {
  2946. if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
  2947. {
  2948. gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
  2949. diagnosis = "Last session crashed unexpectedly after logout";
  2950. }
  2951. else if (gLastExecEvent != LAST_EXEC_LOGOUT_CRASH)
  2952. {
  2953. gLastExecEvent = LAST_EXEC_OTHER_CRASH;
  2954. diagnosis = "Last session crashed unexpectedly";
  2955. }
  2956. }
  2957. else
  2958. {
  2959. llinfos << "An unexpected error marker file has been found but is not ours: another viewer crashed..."
  2960. << llendl;
  2961. }
  2962. LLFile::remove(error_marker_file);
  2963. }
  2964. if (!diagnosis.empty())
  2965. {
  2966. llwarns << diagnosis << llendl;
  2967. }
  2968. // No new markers if another instance is running.
  2969. if (mSecondInstance)
  2970. {
  2971. return;
  2972. }
  2973. // Since no other instance is running and any left over marker file was
  2974. // from a crashed instance, let's reset these flags (they are used later
  2975. // on to determine whether or we can open or not the caches and settings
  2976. // files for writing). HB
  2977. mIsOurViewer = mSameBranchViewer = mIsSiblingViewer = false;
  2978. // Create the marker file for this execution & lock it
  2979. mMarkerFile = new LLFile(mMarkerFileName, "w");
  2980. if (mMarkerFile->getStream())
  2981. {
  2982. LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL;
  2983. }
  2984. else
  2985. {
  2986. delete mMarkerFile;
  2987. mMarkerFile = NULL;
  2988. llwarns << "Failed to create marker file." << llendl;
  2989. // Marker file is likely locked, meaning another instance is running.
  2990. mSecondInstance = true;
  2991. return;
  2992. }
  2993. if (!mMarkerFile->lock())
  2994. {
  2995. delete mMarkerFile;
  2996. mMarkerFile = NULL;
  2997. llwarns << "Marker file cannot be locked." << llendl;
  2998. return;
  2999. }
  3000. // Windows is stupid: you cannot change the contents of a locked file, when
  3001. // you own a shared lock on it, and you cannot read it from another process
  3002. // if you take an exclusive lock on it. This is unlike POSIX systems where
  3003. // a write-locked file can still be written by the lock holder and read by
  3004. // everyone... HB
  3005. #if LL_WINDOWS
  3006. LL_DEBUGS("MarkerFile") << "Marker file unlocked." << LL_ENDL;
  3007. mMarkerFile->unlock();
  3008. #else
  3009. LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
  3010. #endif
  3011. LL_DEBUGS("MarkerFile") << "Stamping marker file: " << mMarkerFileName
  3012. << LL_ENDL;
  3013. stampMarkerFile(mMarkerFile);
  3014. #if LL_WINDOWS
  3015. mMarkerFile->lock();
  3016. LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
  3017. #endif
  3018. }
  3019. // Stamp the marker file as pertaining to our viewer
  3020. void LLAppViewer::stampMarkerFile(LLFile* marker_file)
  3021. {
  3022. if (marker_file->getStream())
  3023. {
  3024. // Stamp the marker file as pertaining to our viewer
  3025. marker_file->write((const U8*)gViewerVersion.c_str(),
  3026. strlen(gViewerVersion.c_str()));
  3027. marker_file->flush();
  3028. }
  3029. }
  3030. bool LLAppViewer::isOurMarkerFile(std::string& filename)
  3031. {
  3032. char buff[256]; // Must be able to hold gViewerVersion.c_str()
  3033. LLFile infile(filename, "rb");
  3034. S32 n = infile.read((U8*)buff, strlen(gViewerVersion.c_str()));
  3035. buff[n] = '\0';
  3036. bool is_ours = strcmp(buff, gViewerVersion.c_str()) == 0;
  3037. LL_DEBUGS("MarkerFile") << "Marker file " << filename
  3038. << (is_ours ? " matches this viewer version."
  3039. : " is not ours.")
  3040. << LL_ENDL;
  3041. return is_ours;
  3042. }
  3043. void LLAppViewer::checkSiblingMarkerFile(std::string& filename)
  3044. {
  3045. char buff[256]; // Must be able to hold gViewerVersion.c_str()
  3046. LLFile infile(filename, "rb");
  3047. S32 n = infile.read((U8*)buff, 255);
  3048. std::string viewer(buff, n);
  3049. size_t i = gViewerVersion.rfind('.');
  3050. if (i != std::string::npos && viewer.rfind('.') == i)
  3051. {
  3052. mSameBranchViewer = viewer.substr(0, i) == gViewerVersion.substr(0, i);
  3053. }
  3054. mIsSiblingViewer = viewer.find(gSecondLife) == 0;
  3055. if (mSameBranchViewer)
  3056. {
  3057. llinfos << "Found a " << gViewerVersion.substr(0, i) << " marker file."
  3058. << llendl;
  3059. }
  3060. else if (mIsSiblingViewer)
  3061. {
  3062. llinfos << "Found a " << gSecondLife << " marker file." << llendl;
  3063. }
  3064. }
  3065. void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
  3066. {
  3067. if (mMarkerFile)
  3068. {
  3069. LL_DEBUGS("MarkerFile") << "Removing main marker file: "
  3070. << mMarkerFileName << LL_ENDL;
  3071. delete mMarkerFile;
  3072. mMarkerFile = NULL;
  3073. LLFile::remove(mMarkerFileName);
  3074. }
  3075. if (mOwnsLogoutMarkerFile && !leave_logout_marker)
  3076. {
  3077. LL_DEBUGS("MarkerFile") << "Removing logout marker file: "
  3078. << mLogoutMarkerFileName << LL_ENDL;
  3079. LLFile::remove(mLogoutMarkerFileName);
  3080. mOwnsLogoutMarkerFile = false;
  3081. }
  3082. }
  3083. void LLAppViewer::forceQuit()
  3084. {
  3085. llinfos << "Quitting..." << llendl;
  3086. LLApp::setQuitting();
  3087. }
  3088. void LLAppViewer::requestQuit()
  3089. {
  3090. llinfos << "Quitting..." << llendl;
  3091. LLViewerRegion* region = gAgent.getRegion();
  3092. if (!region || !LLStartUp::isLoggedIn())
  3093. {
  3094. // If we have a region, make some attempt to send a logout request
  3095. // first. This prevents the halfway-logged-in avatar from hanging
  3096. // around inworld for a couple minutes.
  3097. if (region)
  3098. {
  3099. sendLogoutRequest();
  3100. }
  3101. // Quit immediately
  3102. forceQuit();
  3103. return;
  3104. }
  3105. // Send logout swirling particles effect to server and mark it dead
  3106. // immediately after.
  3107. LLHUDEffectSpiral::swirlAtPosition(gAgent.getPositionGlobal(), 0.f, true);
  3108. // Attempt to close all floaters that might be/ editing things.
  3109. if (gFloaterViewp)
  3110. {
  3111. // Application is quitting
  3112. gFloaterViewp->closeAllChildren(true);
  3113. }
  3114. gViewerStats.sendStats();
  3115. gLogoutTimer.reset();
  3116. mQuitRequested = true;
  3117. }
  3118. static bool finish_quit(const LLSD& notification, const LLSD& response)
  3119. {
  3120. if (LLNotification::getSelectedOption(notification, response) == 0)
  3121. {
  3122. // Some OpenSim grids can really be annoying and spuriously trigger
  3123. // "You have been disconnected" dialogs on normal logouts... Let's flag
  3124. // that it is a normal logout. NOTE: do NOT flag it with sDoDisconnect
  3125. // or LLApp::setQuitting() (the first would make the viewer wait
  3126. // forever, and the second would cause a truncated logout process). HB
  3127. sLoggingOut = true;
  3128. gAppViewerp->requestQuit();
  3129. }
  3130. return false;
  3131. }
  3132. static LLNotificationFunctorRegistration finish_quit_reg1("ConfirmQuit",
  3133. finish_quit);
  3134. static LLNotificationFunctorRegistration finish_quit_reg2("ConfirmQuitNotifications",
  3135. finish_quit);
  3136. void LLAppViewer::userQuit()
  3137. {
  3138. llinfos << "Quitting..." << llendl;
  3139. if (gDisconnected || !gViewerWindowp ||
  3140. !gViewerWindowp->getProgressView() ||
  3141. gViewerWindowp->getProgressView()->getVisible())
  3142. {
  3143. requestQuit();
  3144. }
  3145. else if (LLNotifyBox::getNotifyBoxCount() +
  3146. LLGroupNotifyBox::getGroupNotifyBoxCount() > 0)
  3147. {
  3148. if (!LLNotifyBox::areNotificationsShown())
  3149. {
  3150. LLNotifyBox::setShowNotifications(true);
  3151. }
  3152. gNotifications.add("ConfirmQuitNotifications");
  3153. }
  3154. else
  3155. {
  3156. gNotifications.add("ConfirmQuit");
  3157. }
  3158. }
  3159. static bool finish_early_exit(const LLSD& notification, const LLSD& response)
  3160. {
  3161. gAppViewerp->forceQuit();
  3162. return false;
  3163. }
  3164. void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
  3165. {
  3166. llwarns << "app_early_exit: " << name << llendl;
  3167. sDoDisconnect = true;
  3168. gNotifications.add(name, substitutions, LLSD(), finish_early_exit);
  3169. }
  3170. void LLAppViewer::forceExit()
  3171. {
  3172. LLSplashScreen::update("Shutting down...");
  3173. ms_sleep(1000);
  3174. removeMarkerFile();
  3175. LLSplashScreen::hide();
  3176. // *FIXME: this kind of exit hardly seems appropriate - Mani.
  3177. exit(-1); // -1 is the code we use for "application init failed".
  3178. }
  3179. void LLAppViewer::abortQuit()
  3180. {
  3181. llinfos << "abortQuit()" << llendl;
  3182. mQuitRequested = false;
  3183. }
  3184. bool LLAppViewer::initCache()
  3185. {
  3186. mPurgeCache = false;
  3187. bool read_only = mIsSiblingViewer; // If same cache directory in use
  3188. gTextureCachep->setReadOnly(read_only);
  3189. LLVOCache::getInstance()->setReadOnly(read_only);
  3190. // Get the maximum cache size from the debug settings and clamp it
  3191. constexpr S64 MB = 1024L * 1024L;
  3192. S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
  3193. constexpr S64 MAX_CACHE_SIZE = 10240L * MB;
  3194. cache_size = llmin(cache_size, MAX_CACHE_SIZE);
  3195. // Percent of the cache to reserve to assets
  3196. F64 assets_percent = gSavedSettings.getF32("AssetsCachePercentOfTotal");
  3197. // Assets cache maximum size
  3198. U64 assets_cache_size = (U64)((F64)cache_size * assets_percent / 100.0);
  3199. // Give textures the rest of the cache less 5% for objects cache and
  3200. // inventory.
  3201. S64 texture_cache_size = 100 * cache_size / 95 - (S64)assets_cache_size;
  3202. if (!read_only)
  3203. {
  3204. // Purge cache if user requested it
  3205. if (gSavedSettings.getBool("PurgeCacheOnStartup") ||
  3206. gSavedSettings.getBool("PurgeCacheOnNextStartup"))
  3207. {
  3208. gSavedSettings.setBool("PurgeCacheOnNextStartup", false);
  3209. mPurgeCache = true;
  3210. }
  3211. // Setup and verify the cache location
  3212. std::string cache_location = gSavedSettings.getString("CacheLocation");
  3213. std::string new_loc = gSavedSettings.getString("NewCacheLocation");
  3214. if (new_loc != cache_location)
  3215. {
  3216. if (gDirUtil.setCacheDir(cache_location))
  3217. {
  3218. // Purge all caches at the old location
  3219. LLSplashScreen::update("Clearing old caches...");
  3220. purgeCache();
  3221. mPurgeCache = false;
  3222. // Set the new location for caches
  3223. gSavedSettings.setString("CacheLocation", new_loc);
  3224. }
  3225. else
  3226. {
  3227. llwarns << "Unable to set old cache location: purge cancelled."
  3228. << llendl;
  3229. }
  3230. }
  3231. }
  3232. if (!gDirUtil.setCacheDir(gSavedSettings.getString("CacheLocation")))
  3233. {
  3234. llwarns << "Unable to set cache location" << llendl;
  3235. gSavedSettings.setString("CacheLocation", "");
  3236. }
  3237. if (!read_only)
  3238. {
  3239. if (mPurgeCache)
  3240. {
  3241. LLSplashScreen::update("Clearing all caches...");
  3242. purgeCache();
  3243. }
  3244. // NOTE: purgeCache() resets the "Clear*Cache" settings. HB
  3245. if (gSavedSettings.getBool("ClearTextureCache"))
  3246. {
  3247. LLSplashScreen::update("Clearing the texture cache...");
  3248. llinfos << "Clearing the cached textures, on user request."
  3249. << llendl;
  3250. gTextureCachep->purgeCache(LL_PATH_CACHE);
  3251. gSavedSettings.setBool("ClearTextureCache", false);
  3252. }
  3253. if (gSavedSettings.getBool("ClearObjectCache"))
  3254. {
  3255. LLSplashScreen::update("Clearing the object cache...");
  3256. llinfos << "Clearing the cached objects, on user request."
  3257. << llendl;
  3258. LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
  3259. gSavedSettings.setBool("ClearObjectCache", false);
  3260. }
  3261. }
  3262. LLSplashScreen::update("Initializing texture cache...");
  3263. S64 extra = gTextureCachep->initCache(LL_PATH_CACHE, texture_cache_size);
  3264. texture_cache_size -= extra;
  3265. // This is where the object cache used to be initialized, but we now do it
  3266. // after login (in llstartup.cpp), so that it can take the grid name into
  3267. // account and keep cached regions on a per-grid basis. HB
  3268. LLSplashScreen::update("Initializing asset cache...");
  3269. LLDiskCache::init(assets_cache_size, read_only);
  3270. if (!read_only)
  3271. {
  3272. if (gSavedSettings.getBool("ClearAssetCache"))
  3273. {
  3274. LLSplashScreen::update("Clearing the asset cache...");
  3275. llinfos << "Clearing the cached assets, on user request."
  3276. << llendl;
  3277. gSavedSettings.setBool("ClearAssetCache", false);
  3278. LLDiskCache::clear();
  3279. }
  3280. else
  3281. {
  3282. LLDiskCache::threadedPurge();
  3283. }
  3284. }
  3285. return true;
  3286. }
  3287. void LLAppViewer::purgeCache()
  3288. {
  3289. llinfos << "Clearing all caches..." << llendl;
  3290. gTextureCachep->purgeCache(LL_PATH_CACHE);
  3291. LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
  3292. LLDiskCache::clear();
  3293. LLDirIterator::deleteFilesInDir(gDirUtil.getCacheDir());
  3294. gSavedSettings.setBool("ClearAssetCache", false);
  3295. gSavedSettings.setBool("ClearTextureCache", false);
  3296. gSavedSettings.setBool("ClearObjectCache", false);
  3297. }
  3298. // Callback from a dialog indicating user was logged out.
  3299. bool finish_disconnect(const LLSD& notification, const LLSD& response)
  3300. {
  3301. if (LLNotification::getSelectedOption(notification, response) == 1)
  3302. {
  3303. gAppViewerp->forceQuit();
  3304. }
  3305. return false;
  3306. }
  3307. // Callback from an early disconnect dialog, force an exit
  3308. bool finish_forced_disconnect(const LLSD& notification, const LLSD& response)
  3309. {
  3310. gAppViewerp->forceQuit();
  3311. return false;
  3312. }
  3313. void LLAppViewer::forceDisconnect(const std::string& mesg)
  3314. {
  3315. if (sDoDisconnect)
  3316. {
  3317. // Already popped up one of these dialogs, do not do this again.
  3318. return;
  3319. }
  3320. sDoDisconnect = true;
  3321. if (!gIsInSecondLife && sLoggingOut)
  3322. {
  3323. // In OpenSim, we may get here while logging out normally (see the
  3324. // comment in finish_quit())... So just confirm that we are indeed
  3325. // quitting ! HB
  3326. gAppViewerp->forceQuit();
  3327. return;
  3328. }
  3329. // Translate the message if possible
  3330. std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
  3331. if (big_reason.size() == 0)
  3332. {
  3333. big_reason = mesg;
  3334. }
  3335. // Tell the user what happened
  3336. LLSD args;
  3337. if (LLStartUp::isLoggedIn())
  3338. {
  3339. args["MESSAGE"] = big_reason;
  3340. gNotifications.add("YouHaveBeenLoggedOut", args, LLSD(),
  3341. finish_disconnect);
  3342. gExitCode = EXIT_FORCE_LOGGED_OUT;
  3343. }
  3344. else
  3345. {
  3346. args["ERROR_MESSAGE"] = big_reason;
  3347. gNotifications.add("ErrorMessage", args, LLSD(),
  3348. finish_forced_disconnect);
  3349. gExitCode = EXIT_LOGIN_FAILED;
  3350. }
  3351. }
  3352. void LLAppViewer::badNetworkHandler()
  3353. {
  3354. // Dump the packet
  3355. gMessageSystemp->dumpPacketToLog();
  3356. // Flush all of our caches on exit in the case of disconnect due to invalid
  3357. // packets.
  3358. mPurgeOnExit = true;
  3359. std::ostringstream message;
  3360. message << gSecondLife << " has detected mangled\n"
  3361. << "network data indicative of a bad upstream network\n"
  3362. << "connection or an incompatibility between the viewer\n"
  3363. << "and the grid you are connected to.\n"
  3364. << "If the problem persists, please report it on the\n"
  3365. << "support forum at: http://sldev.free.fr/forum/";
  3366. forceDisconnect(message.str());
  3367. }
  3368. // This routine may get called more than once during the shutdown process.
  3369. // This can happen because we need to get the screenshot before the window
  3370. // is destroyed.
  3371. void LLAppViewer::saveFinalSnapshot()
  3372. {
  3373. if (gViewerWindowp && !mSavedFinalSnapshot)
  3374. {
  3375. gViewerWindowp->setCursor(UI_CURSOR_WAIT);
  3376. // Do not animate, need immediate switch:
  3377. gAgent.changeCameraToThirdPerson(false);
  3378. gSavedSettings.setBool("ShowParcelOwners", false);
  3379. gSavedSettings.setBool("RenderHUDInSnapshot", false);
  3380. idle(false);
  3381. std::string snap_filename = gDirUtil.getLindenUserDir();
  3382. snap_filename += LL_DIR_DELIM_STR;
  3383. if (gIsInProductionGrid)
  3384. {
  3385. snap_filename += SCREEN_LAST_FILENAME;
  3386. }
  3387. else
  3388. {
  3389. snap_filename += SCREEN_LAST_BETA_FILENAME;
  3390. }
  3391. // Use full pixel dimensions of viewer window (do not post-scale
  3392. // dimensions)
  3393. gViewerWindowp->saveSnapshot(snap_filename,
  3394. gViewerWindowp->getWindowDisplayWidth(),
  3395. gViewerWindowp->getWindowDisplayHeight(),
  3396. false, true);
  3397. mSavedFinalSnapshot = true;
  3398. }
  3399. }
  3400. void LLAppViewer::loadNameCache()
  3401. {
  3402. std::string prefix;
  3403. if (!gIsInSecondLife)
  3404. {
  3405. prefix = LLGridManager::getInstance()->getGridLabel() + "_";
  3406. }
  3407. // Display names cache
  3408. std::string filename = gDirUtil.getFullPath(LL_PATH_CACHE,
  3409. prefix +
  3410. "avatar_name_cache.xml");
  3411. llifstream name_cache_stream(filename.c_str());
  3412. if (name_cache_stream.is_open())
  3413. {
  3414. if (!LLAvatarNameCache::importFile(name_cache_stream))
  3415. {
  3416. llwarns << "Removing invalid name cache file." << llendl;
  3417. name_cache_stream.close();
  3418. LLFile::remove(filename);
  3419. }
  3420. }
  3421. if (!gCacheNamep) return;
  3422. filename = gDirUtil.getFullPath(LL_PATH_CACHE, prefix + "name.cache");
  3423. llifstream cache_file(filename.c_str());
  3424. if (cache_file.is_open())
  3425. {
  3426. gCacheNamep->importFile(cache_file);
  3427. }
  3428. }
  3429. void LLAppViewer::saveNameCache()
  3430. {
  3431. std::string prefix;
  3432. if (!gIsInSecondLife)
  3433. {
  3434. prefix = LLGridManager::getInstance()->getGridLabel() + "_";
  3435. }
  3436. // Display names cache
  3437. std::string filename =
  3438. gDirUtil.getFullPath(LL_PATH_CACHE, prefix + "avatar_name_cache.xml");
  3439. llofstream name_cache_stream(filename.c_str());
  3440. if (name_cache_stream.is_open())
  3441. {
  3442. LLAvatarNameCache::exportFile(name_cache_stream);
  3443. }
  3444. else
  3445. {
  3446. llwarns << "Could not open file '" << filename << "' for writing."
  3447. << llendl;
  3448. }
  3449. if (!gCacheNamep) return;
  3450. filename = gDirUtil.getFullPath(LL_PATH_CACHE, prefix + "name.cache");
  3451. llofstream cache_file(filename.c_str());
  3452. if (cache_file.is_open())
  3453. {
  3454. gCacheNamep->exportFile(cache_file);
  3455. }
  3456. else
  3457. {
  3458. llwarns << "Could not open file '" << filename << "' for writing."
  3459. << llendl;
  3460. }
  3461. }
  3462. void LLAppViewer::saveExperienceCache()
  3463. {
  3464. std::string prefix;
  3465. if (!gIsInSecondLife)
  3466. {
  3467. prefix = LLGridManager::getInstance()->getGridLabel() + "_";
  3468. }
  3469. std::string filename =
  3470. gDirUtil.getFullPath(LL_PATH_CACHE, prefix + "experience_cache.xml");
  3471. llinfos << "Saving: " << filename << llendl;
  3472. llofstream cache_stream(filename.c_str());
  3473. if (cache_stream.is_open())
  3474. {
  3475. LLExperienceCache::getInstance()->exportFile(cache_stream);
  3476. }
  3477. else
  3478. {
  3479. llwarns << "Could not open file '" << filename << "' for writing."
  3480. << llendl;
  3481. }
  3482. }
  3483. void LLAppViewer::loadExperienceCache()
  3484. {
  3485. std::string prefix;
  3486. if (!gIsInSecondLife)
  3487. {
  3488. prefix = LLGridManager::getInstance()->getGridLabel() + "_";
  3489. }
  3490. std::string filename =
  3491. gDirUtil.getFullPath(LL_PATH_CACHE, prefix + "experience_cache.xml");
  3492. llifstream cache_stream(filename.c_str());
  3493. if (cache_stream.is_open())
  3494. {
  3495. llinfos << "Loading: " << filename << llendl;
  3496. LLExperienceCache::getInstance()->importFile(cache_stream);
  3497. }
  3498. }
  3499. // Called every time the window is not doing anything. Receive packets, update
  3500. // statistics, and schedule a redisplay.
  3501. void LLAppViewer::idle(bool run_rlv_maintenance)
  3502. {
  3503. // Update frame timers
  3504. static LLTimer idle_timer;
  3505. //MK
  3506. if (run_rlv_maintenance)
  3507. {
  3508. LL_FAST_TIMER(FTM_RLV);
  3509. if (gRLenabled && LLStartUp::isLoggedIn() &&
  3510. gViewerWindowp && !gViewerWindowp->getShowProgress())
  3511. {
  3512. // Do some RLV maintenance (garbage collector, etc)
  3513. gRLInterface.idleTasks();
  3514. }
  3515. }
  3516. //mk
  3517. LLApp::stepFrame(); // Updates frame timer classes.
  3518. LLCriticalDamp::updateInterpolants();
  3519. LLMortician::updateClass();
  3520. gFrameDT = idle_timer.getElapsedTimeAndResetF32();
  3521. F32 frame_rate_clamped = 1.f / gFrameDT;
  3522. // Cap out-of-control frame times. Too low because in menus, swapping,
  3523. // debugger, etc. Too high because idle called with no objects in view,
  3524. // etc.
  3525. constexpr F32 MIN_FRAME_RATE = 1.f;
  3526. constexpr F32 MAX_FRAME_RATE = 200.f;
  3527. frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE,
  3528. MAX_FRAME_RATE);
  3529. // Global frame timer. Smoothly weight toward current frame
  3530. gFPSClamped = (frame_rate_clamped + 4.f * gFPSClamped) / 5.f;
  3531. if (LLFile::hadWriteErrors()) // This also resets the error flag. HB
  3532. {
  3533. static LLUUID last_notification_id;
  3534. static F32 last_warning = 0.f;
  3535. // Do not spam the user and print at most one warning every 90s.
  3536. // Note: since the error flag is reset by LLFile::hadWriteErrors(), and
  3537. // given this minimum interval between warnings, all errors occurring
  3538. // within 90s of the last warning will be ignored, which is the desired
  3539. // behaviour so that if the user frees disk space just after a warning,
  3540. // they would not see another (now stale/irrelevant) warning popping up
  3541. // a few seconds later, just because an error occurred before they
  3542. // could free the space. HB
  3543. constexpr F32 WARNING_INTERVAL = 90.f; // In seconds.
  3544. if (gFrameTimeSeconds - last_warning > WARNING_INTERVAL)
  3545. {
  3546. last_warning = gFrameTimeSeconds;
  3547. // Also check that the last notification is not still displayed. HB
  3548. if (last_notification_id.isNull() ||
  3549. !gNotifications.find(last_notification_id))
  3550. {
  3551. LLNotificationPtr n = gNotifications.add("WriteError");
  3552. if (n)
  3553. {
  3554. last_notification_id = n->getID();
  3555. }
  3556. }
  3557. }
  3558. }
  3559. LLGLTFMaterialList::flushUpdates();
  3560. if (!gMainloopWorkp->empty())
  3561. {
  3562. // Service the LLWorkQueue we use for replies from worker threads.
  3563. static auto one_ms = std::chrono::milliseconds(1);
  3564. gMainloopWorkp->runFor(one_ms);
  3565. }
  3566. static LLCachedControl<F32> qas(gSavedSettings, "QuitAfterSeconds");
  3567. if (qas > 0.f)
  3568. {
  3569. if (gRenderStartTime.getElapsedTimeF32() > qas)
  3570. {
  3571. gAppViewerp->forceQuit();
  3572. }
  3573. }
  3574. // Must wait until both have avatar object and mute list, so poll here.
  3575. // Auto-accepted inventory items may require the avatar object to build a
  3576. // correct name. Likewise, inventory offers from muted avatars require the
  3577. // mute list to properly mute.
  3578. static bool ims_requested = false;
  3579. if (!ims_requested && LLMuteList::isLoaded() && isAgentAvatarValid())
  3580. {
  3581. ims_requested = LLIMMgr::requestOfflineMessages();
  3582. }
  3583. ///////////////////////////////////
  3584. // Special case idle if still starting up
  3585. if (!LLStartUp::isLoggedIn())
  3586. {
  3587. // Skip rest if idle startup returns false (essentially, no world yet)
  3588. if (!LLStartUp::idleStartup())
  3589. {
  3590. return;
  3591. }
  3592. }
  3593. F32 yaw = 0.f; // radians
  3594. if (!gDisconnected)
  3595. {
  3596. LL_FAST_TIMER(FTM_NETWORK);
  3597. #if LL_CURL_BUG
  3598. // HACK: to work around libcurl bugs that sometimes cause the HTTP
  3599. // pipeline to return corrupted data... The idea of this hack is to
  3600. // temporarily turn off pipelining when we detect an issue, and
  3601. // automatically turn it back on a minute later, with fresh pipelined
  3602. // connections, once the old ones have been closed. This call renables
  3603. // HTTP pipelining after a delay has elasped. HB
  3604. mAppCoreHttp.checkPipelinedTempOff();
  3605. #endif
  3606. //////////////////////////////////////
  3607. // Update simulator agent state
  3608. static LLCachedControl<bool> rotate_right(gSavedSettings,
  3609. "RotateRight");
  3610. if (rotate_right)
  3611. {
  3612. gAgent.moveYaw(-1.f);
  3613. }
  3614. // Handle automatic walking towards points
  3615. gAgentPilot.updateTarget();
  3616. gAgentPilot.autoPilot(&yaw);
  3617. // When appropriate, update agent location to the simulator.
  3618. constexpr F32 AFUPS = 1.f / AGENT_FORCE_UPDATES_PER_SECOND;
  3619. constexpr F32 AUPS = 1.f / AGENT_UPDATES_PER_SECOND;
  3620. static LLFrameTimer agent_update_timer;
  3621. F32 agent_update_time = agent_update_timer.getElapsedTimeF32() +
  3622. // Extrapolate to next frame probable render
  3623. // time, based on last frame time. HB
  3624. gFrameIntervalSeconds;
  3625. F32 agent_force_upd_time = mLastAgentForceUpdate + agent_update_time;
  3626. bool force_upd = gAgent.controlFlagsDirty() ||
  3627. mLastAgentControlFlags != gAgent.getControlFlags() ||
  3628. agent_force_upd_time > AFUPS;
  3629. if (force_upd || agent_update_time > AUPS)
  3630. {
  3631. // Send avatar and camera info
  3632. mLastAgentControlFlags = gAgent.getControlFlags();
  3633. mLastAgentForceUpdate = force_upd ? 0 : agent_force_upd_time;
  3634. send_agent_update(force_upd);
  3635. agent_update_timer.reset();
  3636. }
  3637. //////////////////////////////////////
  3638. // Manage statistics
  3639. gViewerStats.idleUpdate();
  3640. // Print the object debugging stats
  3641. static LLFrameTimer object_debug_timer;
  3642. if (object_debug_timer.getElapsedTimeF32() > 5.f)
  3643. {
  3644. object_debug_timer.reset();
  3645. if (gObjectList.mNumDeadObjectUpdates)
  3646. {
  3647. llinfos << "Dead object updates: "
  3648. << gObjectList.mNumDeadObjectUpdates << llendl;
  3649. gObjectList.mNumDeadObjectUpdates = 0;
  3650. }
  3651. if (gObjectList.mNumUnknownUpdates)
  3652. {
  3653. llinfos << "Unknown object updates: "
  3654. << gObjectList.mNumUnknownUpdates << llendl;
  3655. gObjectList.mNumUnknownUpdates = 0;
  3656. }
  3657. }
  3658. ////////////////////////////////////////////////
  3659. // Network processing
  3660. //
  3661. // NOTE: Starting at this point, we may still have pointers to "dead"
  3662. // objects floating throughout the various object lists.
  3663. idleNameCache();
  3664. idleNetwork();
  3665. // Check for away from keyboard, kick idle agents.
  3666. idleAFKCheck();
  3667. // Update statistics for this frame
  3668. gViewerStats.updateStatistics(gFrameCount);
  3669. }
  3670. ////////////////////////////////////////
  3671. // Handle the regular UI idle callbacks as well as hover callbacks
  3672. {
  3673. LL_FAST_TIMER(FTM_IDLE_CB);
  3674. // Do event notifications if necessary. Yes, we may want to move this
  3675. // elsewhere.
  3676. gEventNotifier.update();
  3677. gIdleCallbacks.callFunctions();
  3678. gInventory.idleNotifyObservers();
  3679. gAvatarTracker.idleNotifyObservers();
  3680. // The "new inventory" observer (used to auto-open newly received
  3681. // inventory items) gets triggered each time a new item appears in
  3682. // the viewer-side representation of the inventory. If we start this
  3683. // observer too early (before the initial inventory is fully fetched
  3684. // after login), we see item preview floaters popping up (this is
  3685. // thankfully throttled, so not all items are previewed, but it is
  3686. // still annoying). So, we check in this idle() method for the end
  3687. // of the first inventory fetching operation and start the observer
  3688. // only after is has completed. HB
  3689. static bool must_start_observer = true;
  3690. if (must_start_observer && LLStartUp::isLoggedIn() &&
  3691. LLInventoryModelFetch::getInstance()->isEverythingFetched())
  3692. {
  3693. must_start_observer = false;
  3694. start_new_inventory_observer();
  3695. }
  3696. }
  3697. if (gDisconnected)
  3698. {
  3699. return;
  3700. }
  3701. gViewerWindowp->handlePerFrameHover();
  3702. ///////////////////////////////////////
  3703. // Agent and camera movement
  3704. LLCoordGL current_mouse = gViewerWindowp->getCurrentMouse();
  3705. // After agent and camera moved, figure out if we need to deselect objects.
  3706. gSelectMgr.deselectAllIfTooFar();
  3707. // Handle pending gesture processing
  3708. gGestureManager.update();
  3709. gAgent.updateAgentPosition(gFrameDT, yaw, current_mouse.mX,
  3710. current_mouse.mY);
  3711. if (!(logoutRequestSent() && mSavedFinalSnapshot) && !isExiting())
  3712. {
  3713. // Actually "object update"
  3714. LL_FAST_TIMER(FTM_OBJECTLIST_UPDATE);
  3715. gObjectList.update();
  3716. }
  3717. //////////////////////////////////////
  3718. // Deletes objects...
  3719. // Has to be done after doing idleUpdates (which can kill objects)
  3720. #if 0
  3721. if (gAgent.notTPingFar())
  3722. #endif
  3723. {
  3724. LL_FAST_TIMER(FTM_CLEANUP);
  3725. gObjectList.cleanDeadObjects();
  3726. #if LL_DEBUG && 0
  3727. LLDrawable::cleanupDeadDrawables();
  3728. #endif
  3729. }
  3730. {
  3731. LL_FAST_TIMER(FTM_AREASEARCH_UPDATE);
  3732. // Send background requests for the area search is needed
  3733. HBFloaterAreaSearch::idleUpdate();
  3734. }
  3735. // After this point, in theory we should never see a dead object in the
  3736. // various object/drawable lists.
  3737. //////////////////////////////////////
  3738. // Update/send HUD effects
  3739. //
  3740. // At this point, HUD effects may clean up some references to dead objects.
  3741. {
  3742. gSelectMgr.updateEffects();
  3743. LLHUDManager::cleanupEffects();
  3744. LLHUDManager::sendEffects();
  3745. }
  3746. stop_glerror();
  3747. ////////////////////////////////////////
  3748. // Unpack layer data that we have received
  3749. {
  3750. LL_FAST_TIMER(FTM_NETWORK);
  3751. gVLManager.unpackData();
  3752. }
  3753. /////////////////////////
  3754. // Update surfaces, and surface textures as well.
  3755. gWorld.updateVisibilities();
  3756. {
  3757. LL_FAST_TIMER(FTM_REGION_UPDATE);
  3758. constexpr F32 max_region_update_time = .001f; // 1ms
  3759. gWorld.updateRegions(max_region_update_time);
  3760. }
  3761. /////////////////////////
  3762. // Update weather effects
  3763. gWorld.updateClouds(gFrameDT);
  3764. // Update wind vector
  3765. LLVector3 wind_position_region;
  3766. static LLVector3 average_wind;
  3767. // Puts agent's local coords into wind_position:
  3768. LLViewerRegion* regionp =
  3769. gWorld.resolveRegionGlobal(wind_position_region,
  3770. gAgent.getPositionGlobal());
  3771. if (regionp)
  3772. {
  3773. gWindVec = regionp->mWind.getVelocity(wind_position_region);
  3774. // Compute average wind and use to drive motion of water
  3775. F32 cloud_density =
  3776. regionp->mCloudLayer.getDensityRegion(wind_position_region);
  3777. gSky.setCloudDensityAtAgent(cloud_density);
  3778. average_wind = regionp->mWind.getAverage();
  3779. gSky.setWind(average_wind);
  3780. }
  3781. else
  3782. {
  3783. gWindVec.set(0.f, 0.f, 0.f);
  3784. }
  3785. stop_glerror();
  3786. //////////////////////////////////////
  3787. // Sort and cull in the new renderer are moved to pipeline.cpp
  3788. // Here, particles are updated and drawables are moved.
  3789. {
  3790. LL_FAST_TIMER(FTM_WORLD_UPDATE);
  3791. // Do not loose time to balance the object cache at every frame: only
  3792. // do it once every 100 frames.
  3793. gPipeline.updateMove(gBalanceObjectCache && gFrameCount % 100 == 0 &&
  3794. // Do not perform the following during TPs to
  3795. // avoid race conditions that cause crashes.
  3796. !gAgent.notTPingFar());
  3797. gViewerPartSim.updateSimulation();
  3798. }
  3799. stop_glerror();
  3800. if (LLViewerJoystick::getInstance()->getOverrideCamera())
  3801. {
  3802. LLViewerJoystick::getInstance()->moveFlycam();
  3803. }
  3804. else
  3805. {
  3806. if (gToolMgr.inBuildMode())
  3807. {
  3808. LLViewerJoystick::getInstance()->moveObjects();
  3809. }
  3810. gAgent.updateCamera();
  3811. }
  3812. // Update media focus
  3813. LLViewerMediaFocus::getInstance()->update();
  3814. // Objects and camera should be in sync, do LOD calculations now
  3815. {
  3816. LL_FAST_TIMER(FTM_LOD_UPDATE);
  3817. gObjectList.updateApparentAngles();
  3818. }
  3819. if (gAudiop)
  3820. {
  3821. LL_FAST_TIMER(FTM_AUDIO_UPDATE);
  3822. audio_update_volume(false);
  3823. audio_update_listener();
  3824. audio_update_wind(false);
  3825. // This line actually commits the changes we have made to source
  3826. // positions, etc.
  3827. gAudiop->idle();
  3828. }
  3829. // Handle shutdown process, for example, wait for floaters to close, send
  3830. // quit message, forcibly quit if it has taken too long
  3831. if (mQuitRequested)
  3832. {
  3833. idleShutdown();
  3834. }
  3835. }
  3836. void LLAppViewer::idleShutdown()
  3837. {
  3838. // Wait for all modal alerts to get resolved
  3839. if (LLModalDialog::activeCount() > 0)
  3840. {
  3841. return;
  3842. }
  3843. // Close IM interface
  3844. if (gIMMgrp)
  3845. {
  3846. gIMMgrp->disconnectAllSessions();
  3847. }
  3848. // Wait for all floaters to get resolved
  3849. if (gFloaterViewp && !gFloaterViewp->allChildrenClosed())
  3850. {
  3851. return;
  3852. }
  3853. static bool saved_snapshot = false;
  3854. if (!saved_snapshot)
  3855. {
  3856. saved_snapshot = true;
  3857. saveFinalSnapshot();
  3858. return;
  3859. }
  3860. constexpr F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
  3861. S32 uploads = gAssetStoragep ? gAssetStoragep->getNumPendingUploads() : 0;
  3862. if (uploads > 0 &&
  3863. gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME &&
  3864. !logoutRequestSent())
  3865. {
  3866. static S32 total_uploads = 0;
  3867. // Sometimes total upload count can change during logout.
  3868. total_uploads = llmax(total_uploads, uploads);
  3869. gViewerWindowp->setShowProgress(true);
  3870. S32 finished_uploads = total_uploads - uploads;
  3871. F32 percent = 100.f * finished_uploads / total_uploads;
  3872. gViewerWindowp->setProgressPercent(percent);
  3873. gViewerWindowp->setProgressString("Saving final data...");
  3874. return;
  3875. }
  3876. // All floaters are closed. Tell server we want to quit.
  3877. if (!logoutRequestSent())
  3878. {
  3879. sendLogoutRequest();
  3880. // Wait for a LogoutReply message
  3881. gViewerWindowp->setShowProgress(true);
  3882. gViewerWindowp->setProgressPercent(100.f);
  3883. gViewerWindowp->setProgressString("Logging out...");
  3884. return;
  3885. }
  3886. // Make sure that we quit if we have not received a reply from the server.
  3887. if (logoutRequestSent() &&
  3888. gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime)
  3889. {
  3890. forceQuit();
  3891. }
  3892. }
  3893. void LLAppViewer::sendLogoutRequest()
  3894. {
  3895. LLMessageSystem* msg = gMessageSystemp;
  3896. if (msg && !mLogoutRequestSent)
  3897. {
  3898. mLogoutRequestSent = true;
  3899. msg->newMessageFast(_PREHASH_LogoutRequest);
  3900. msg->nextBlockFast(_PREHASH_AgentData);
  3901. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  3902. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  3903. gAgent.sendReliableMessage();
  3904. gLogoutTimer.reset();
  3905. gLogoutMaxTime = LOGOUT_REQUEST_TIME;
  3906. if (gVoiceClient.ready())
  3907. {
  3908. gVoiceClient.setVoiceEnabled(false);
  3909. }
  3910. // Set internal status variables and marker files
  3911. gLogoutInProgress = true;
  3912. mLogoutMarkerFileName =
  3913. gDirUtil.getFullPath(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
  3914. LLFile outfile(mLogoutMarkerFileName, "w");
  3915. mOwnsLogoutMarkerFile = bool(outfile);
  3916. if (mOwnsLogoutMarkerFile)
  3917. {
  3918. stampMarkerFile(&outfile);
  3919. llinfos << "Created logout marker file " << mLogoutMarkerFileName
  3920. << llendl;
  3921. }
  3922. else
  3923. {
  3924. llwarns << "Cannot create logout marker file "
  3925. << mLogoutMarkerFileName << llendl;
  3926. }
  3927. }
  3928. }
  3929. void LLAppViewer::idleNameCache()
  3930. {
  3931. // Neither old nor new name cache can function before agent has a region
  3932. LLViewerRegion* regionp = gAgent.getRegion();
  3933. if (!regionp || !gCacheNamep)
  3934. {
  3935. return;
  3936. }
  3937. // Deal with any queued name requests and replies.
  3938. gCacheNamep->processPending();
  3939. // Cannot run the new cache until we have the list of capabilities for the
  3940. // agent region, and can therefore decide whether to use display names or
  3941. // fall back to the old name system.
  3942. if (!regionp->capabilitiesReceived())
  3943. {
  3944. return;
  3945. }
  3946. LLAvatarNameCache::idle();
  3947. }
  3948. //
  3949. // Handle messages, and all message related stuff
  3950. //
  3951. #define TIME_THROTTLE_MESSAGES
  3952. #ifdef TIME_THROTTLE_MESSAGES
  3953. #define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
  3954. static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
  3955. #endif
  3956. void LLAppViewer::idleNetwork()
  3957. {
  3958. if (gDisconnected)
  3959. {
  3960. return;
  3961. }
  3962. // Disable the next queued simulator, if any.
  3963. LLWorld::idleDisableQueuedSim();
  3964. gObjectList.mNumNewObjects = 0;
  3965. S32 total_decoded = 0;
  3966. static LLCachedControl<bool> speed_test(gSavedSettings, "SpeedTest");
  3967. if (!speed_test)
  3968. {
  3969. LL_FAST_TIMER(FTM_IDLE_NETWORK); // Decode
  3970. // Process event poll replies now. HB
  3971. LLEventPoll::dispatchMessages();
  3972. LLTimer check_message_timer;
  3973. // Read all available packets from network
  3974. const S64 frame_count = gFrameCount; // U32->S64
  3975. F32 total_time = 0.f;
  3976. { // Scope-guard for LockMessageChecker
  3977. #if LL_USE_FIBER_AWARE_MUTEX
  3978. LockMessageChecker lmc(gMessageSystemp);
  3979. while (lmc.checkAllMessages(frame_count, gServicePumpIOp))
  3980. #else
  3981. while (gMessageSystemp->checkAllMessages(frame_count,
  3982. gServicePumpIOp))
  3983. #endif
  3984. {
  3985. if (sDoDisconnect)
  3986. {
  3987. // We are disconnecting, do not process any more messages
  3988. // from the server. We are usually disconnecting due to
  3989. // either network corruption or a server going down, so
  3990. // this is OK.
  3991. break;
  3992. }
  3993. ++gPacketsIn;
  3994. if (++total_decoded > MESSAGE_MAX_PER_FRAME)
  3995. {
  3996. break;
  3997. }
  3998. #ifdef TIME_THROTTLE_MESSAGES
  3999. // Prevent slow packets from completely destroying the frame
  4000. // rate. This usually happens due to clumps of avatars taking
  4001. // huge amount of network processing time (which needs to be
  4002. // fixed, but this is a good limit anyway).
  4003. total_time = check_message_timer.getElapsedTimeF32();
  4004. if (total_time >= CheckMessagesMaxTime)
  4005. {
  4006. break;
  4007. }
  4008. #endif
  4009. }
  4010. // Handle per-frame message system processing.
  4011. static LLCachedControl<F32> collect_time(gSavedSettings,
  4012. "AckCollectTime");
  4013. #if LL_USE_FIBER_AWARE_MUTEX
  4014. lmc.processAcks(collect_time);
  4015. #else
  4016. gMessageSystemp->processAcks(collect_time);
  4017. #endif
  4018. } // End of scope for LockMessageChecker
  4019. #ifdef TIME_THROTTLE_MESSAGES
  4020. if (total_time >= CheckMessagesMaxTime)
  4021. {
  4022. // Increase CheckMessagesMaxTime so that we will eventually catch
  4023. // up. 3.5% ~= x2 in 20 frames, ~8x in 60 frames
  4024. CheckMessagesMaxTime *= 1.035f;
  4025. }
  4026. else
  4027. {
  4028. // Reset CheckMessagesMaxTime to default value
  4029. CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
  4030. }
  4031. #endif
  4032. // We want to clear the control after sending out all necessary agent
  4033. // updates
  4034. gAgent.resetControlFlags();
  4035. // Decode enqueued messages...
  4036. S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
  4037. if (remaining_possible_decodes <= 0)
  4038. {
  4039. llinfos << "Maxed out number of messages per frame at "
  4040. << MESSAGE_MAX_PER_FRAME << llendl;
  4041. }
  4042. }
  4043. gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
  4044. // Retransmit unacknowledged packets.
  4045. if (gXferManagerp)
  4046. {
  4047. gXferManagerp->retransmitUnackedPackets();
  4048. }
  4049. if (gAssetStoragep)
  4050. {
  4051. gAssetStoragep->checkForTimeouts();
  4052. }
  4053. gViewerThrottle.updateDynamicThrottle();
  4054. // Check that the circuit between the viewer and the agent's current region
  4055. // is still alive
  4056. LLViewerRegion* regionp = gAgent.getRegion();
  4057. if (regionp && LLStartUp::isLoggedIn())
  4058. {
  4059. const LLUUID& this_region_id = regionp->getRegionID();
  4060. bool this_region_alive = regionp->isAlive();
  4061. if (mAgentRegionLastAlive && !this_region_alive && // newly dead
  4062. mAgentRegionLastID == this_region_id) // same region
  4063. {
  4064. forceDisconnect(LLTrans::getString("AgentLostConnection"));
  4065. }
  4066. mAgentRegionLastID = this_region_id;
  4067. mAgentRegionLastAlive = this_region_alive;
  4068. }
  4069. }
  4070. void LLAppViewer::disconnectViewer()
  4071. {
  4072. if (gDisconnected)
  4073. {
  4074. return;
  4075. }
  4076. // Cleanup after quitting.
  4077. // Save snapshot for next time, if we made it through initialization
  4078. llinfos << "Disconnecting viewer !" << llendl;
  4079. // Dump our frame statistics
  4080. // Dump memory the statistics
  4081. LLMemory::logMemoryInfo();
  4082. // Remember if we were flying
  4083. gSavedPerAccountSettings.setBool("FlyingAtExit", gAgent.getFlying());
  4084. // Un-minimize all windows so they do not get saved minimized
  4085. if (gFloaterViewp)
  4086. {
  4087. gFloaterViewp->restoreAll();
  4088. std::list<LLFloater*> floaters_to_close;
  4089. std::string name;
  4090. for (LLView::child_list_const_iter_t
  4091. it = gFloaterViewp->getChildList()->begin();
  4092. it != gFloaterViewp->getChildList()->end(); ++it)
  4093. {
  4094. LLView* viewp = *it;
  4095. if (!viewp) continue; // Paranoia
  4096. LLFloater* floaterp = viewp->asFloater();
  4097. if (floaterp)
  4098. {
  4099. // The following names are defined in the XUI files:
  4100. // floater_image_preview.xml
  4101. // floater_sound_preview.xml
  4102. // floater_animation_preview.xml
  4103. name = floaterp->getName();
  4104. if (name == "image preview" || name == "sound preview" ||
  4105. name == "animation preview")
  4106. {
  4107. floaters_to_close.push_back(floaterp);
  4108. }
  4109. }
  4110. }
  4111. while (!floaters_to_close.empty())
  4112. {
  4113. LLFloater* floaterp = floaters_to_close.front();
  4114. floaters_to_close.pop_front();
  4115. floaterp->close();
  4116. }
  4117. }
  4118. gSelectMgr.deselectAll();
  4119. // Save inventory if appropriate
  4120. if (gInventory.isInventoryUsable()) // Paranoia
  4121. {
  4122. gInventory.cache(gInventory.getRootFolderID(), gAgentID);
  4123. // Agent is unique, but not the library...
  4124. if (!mSecondInstance)
  4125. {
  4126. gInventory.cache(gInventory.getLibraryRootFolderID(),
  4127. gInventory.getLibraryOwnerID());
  4128. }
  4129. }
  4130. saveNameCache();
  4131. if (LLExperienceCache::instanceExists())
  4132. {
  4133. saveExperienceCache();
  4134. LLExperienceCache::getInstance()->cleanup();
  4135. }
  4136. if (LLCoprocedureManager::instanceExists())
  4137. {
  4138. LLCoprocedureManager::getInstance()->cleanup();
  4139. }
  4140. // Close all inventory floaters
  4141. LLFloaterInventory::cleanup();
  4142. // Also writes cached agent settings to gSavedSettings
  4143. gAgent.cleanup();
  4144. // Make gWorld cleanly shut down.
  4145. gWorld.cleanupClass();
  4146. LLVOCache::deleteSingleton();
  4147. // Call all self-registered classes
  4148. llinfos << "Firing LLDestroyClassList callbacks..." << llendl;
  4149. LLDestroyClassList::getInstance()->fireCallbacks();
  4150. delete gXferManagerp;
  4151. gXferManagerp = NULL;
  4152. llinfos << "Transfer manager destroyed." << llendl;
  4153. LLDiskCache::shutdown();
  4154. gDisconnected = true;
  4155. }
  4156. void LLAppViewer::handleLoginComplete()
  4157. {
  4158. // Store some data to DebugInfo in case of a freeze.
  4159. gDebugInfo["ClientInfo"]["Name"] =
  4160. gSavedSettings.getString("VersionChannelName");
  4161. gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
  4162. gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
  4163. gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_BRANCH;
  4164. gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_RELEASE;
  4165. gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
  4166. LLParcel* parcel = gViewerParcelMgr.getAgentParcel();
  4167. if (parcel && parcel->getMusicURL()[0])
  4168. {
  4169. gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
  4170. }
  4171. if (parcel && !parcel->getMediaURL().empty())
  4172. {
  4173. gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
  4174. }
  4175. gDebugInfo["SettingsFilename"] =
  4176. gSavedSettings.getString("ClientSettingsFile");
  4177. gDebugInfo["CRTFilename"] = gDirUtil.getCRTFile();
  4178. gDebugInfo["ViewerExePath"] = gDirUtil.getExecutablePathAndName();
  4179. gDebugInfo["CurrentPath"] = gDirUtil.getCurPath();
  4180. LLViewerRegion* regionp = gAgent.getRegion();
  4181. if (regionp)
  4182. {
  4183. gDebugInfo["CurrentSimHost"] = regionp->getSimHostName();
  4184. gDebugInfo["CurrentRegion"] = regionp->getName();
  4185. }
  4186. writeDebugInfo(false);
  4187. mSavePerAccountSettings = true;
  4188. }
  4189. //static
  4190. void LLAppViewer::pauseTextureFetch()
  4191. {
  4192. gTextureFetchp->pause();
  4193. // Attempt to empty out the GL worker thread queue after pausing. HB
  4194. if (LLImageGLThread::sEnabled)
  4195. {
  4196. size_t remaining = 0;
  4197. gMainloopWorkp->runFor(std::chrono::milliseconds(100), &remaining);
  4198. LLViewerFetchedTexture::sImageThreadQueueSize = remaining;
  4199. }
  4200. }
  4201. //static
  4202. void LLAppViewer::updateTextureFetch()
  4203. {
  4204. gTextureFetchp->update(); // Un-pauses the texture fetch thread
  4205. gTextureList.updateImages(0.1f);
  4206. }