PageRenderTime 111ms CodeModel.GetById 22ms app.highlight 75ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llappviewer.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2191 lines | 1448 code | 399 blank | 344 comment | 149 complexity | 2d022bdd69b86b347004945c8eb65f14 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llappviewer.cpp
   3 * @brief The LLAppViewer class definitions
   4 *
   5 * $LicenseInfo:firstyear=2007&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llappviewer.h"
  30
  31// Viewer includes
  32#include "llversioninfo.h"
  33#include "llversionviewer.h"
  34#include "llfeaturemanager.h"
  35#include "lluictrlfactory.h"
  36#include "lltexteditor.h"
  37#include "llerrorcontrol.h"
  38#include "lleventtimer.h"
  39#include "llviewertexturelist.h"
  40#include "llgroupmgr.h"
  41#include "llagent.h"
  42#include "llagentcamera.h"
  43#include "llagentlanguage.h"
  44#include "llagentwearables.h"
  45#include "llwindow.h"
  46#include "llviewerstats.h"
  47#include "llviewerstatsrecorder.h"
  48#include "llmarketplacefunctions.h"
  49#include "llmarketplacenotifications.h"
  50#include "llmd5.h"
  51#include "llmeshrepository.h"
  52#include "llpumpio.h"
  53#include "llmimetypes.h"
  54#include "llslurl.h"
  55#include "llstartup.h"
  56#include "llfocusmgr.h"
  57#include "llviewerjoystick.h"
  58#include "llallocator.h"
  59#include "llares.h" 
  60#include "llcurl.h"
  61#include "llcalc.h"
  62#include "lltexturestats.h"
  63#include "lltexturestats.h"
  64#include "llviewerwindow.h"
  65#include "llviewerdisplay.h"
  66#include "llviewermedia.h"
  67#include "llviewerparcelmedia.h"
  68#include "llviewermediafocus.h"
  69#include "llviewermessage.h"
  70#include "llviewerobjectlist.h"
  71#include "llworldmap.h"
  72#include "llmutelist.h"
  73#include "llviewerhelp.h"
  74#include "lluicolortable.h"
  75#include "llurldispatcher.h"
  76#include "llurlhistory.h"
  77//#include "llfirstuse.h"
  78#include "llrender.h"
  79#include "llteleporthistory.h"
  80#include "lltoast.h"
  81#include "lllocationhistory.h"
  82#include "llfasttimerview.h"
  83#include "llvector4a.h"
  84#include "llviewermenufile.h"
  85#include "llvoicechannel.h"
  86#include "llvoavatarself.h"
  87#include "llurlmatch.h"
  88#include "lltextutil.h"
  89#include "lllogininstance.h"
  90#include "llprogressview.h"
  91#include "llvocache.h"
  92#include "llweb.h"
  93#include "llsecondlifeurls.h"
  94#include "llupdaterservice.h"
  95#include "llcallfloater.h"
  96
  97// Linden library includes
  98#include "llavatarnamecache.h"
  99#include "lldiriterator.h"
 100#include "llimagej2c.h"
 101#include "llmemory.h"
 102#include "llprimitive.h"
 103#include "llurlaction.h"
 104#include "llurlentry.h"
 105#include "llvfile.h"
 106#include "llvfsthread.h"
 107#include "llvolumemgr.h"
 108#include "llxfermanager.h"
 109
 110#include "llnotificationmanager.h"
 111#include "llnotifications.h"
 112#include "llnotificationsutil.h"
 113
 114// Third party library includes
 115#include <boost/bind.hpp>
 116#include <boost/foreach.hpp>
 117
 118
 119
 120#if LL_WINDOWS
 121#	include <share.h> // For _SH_DENYWR in initMarkerFile
 122#else
 123#   include <sys/file.h> // For initMarkerFile support
 124#endif
 125
 126#include "llapr.h"
 127#include "apr_dso.h"
 128#include <boost/lexical_cast.hpp>
 129
 130#include "llviewerkeyboard.h"
 131#include "lllfsthread.h"
 132#include "llworkerthread.h"
 133#include "lltexturecache.h"
 134#include "lltexturefetch.h"
 135#include "llimageworker.h"
 136#include "llevents.h"
 137
 138// The files below handle dependencies from cleanup.
 139#include "llkeyframemotion.h"
 140#include "llworldmap.h"
 141#include "llhudmanager.h"
 142#include "lltoolmgr.h"
 143#include "llassetstorage.h"
 144#include "llpolymesh.h"
 145#include "llproxy.h"
 146#include "llaudioengine.h"
 147#include "llstreamingaudio.h"
 148#include "llviewermenu.h"
 149#include "llselectmgr.h"
 150#include "lltrans.h"
 151#include "lltransutil.h"
 152#include "lltracker.h"
 153#include "llviewerparcelmgr.h"
 154#include "llworldmapview.h"
 155#include "llpostprocess.h"
 156#include "llwlparammanager.h"
 157#include "llwaterparammanager.h"
 158
 159#include "lldebugview.h"
 160#include "llconsole.h"
 161#include "llcontainerview.h"
 162#include "lltooltip.h"
 163
 164#include "llsdserialize.h"
 165
 166#include "llworld.h"
 167#include "llhudeffecttrail.h"
 168#include "llvectorperfoptions.h"
 169#include "llslurl.h"
 170#include "llwatchdog.h"
 171
 172// Included so that constants/settings might be initialized
 173// in save_settings_to_globals()
 174#include "llbutton.h"
 175#include "llstatusbar.h"
 176#include "llsurface.h"
 177#include "llvosky.h"
 178#include "llvotree.h"
 179#include "llvoavatar.h"
 180#include "llfolderview.h"
 181#include "llagentpilot.h"
 182#include "llvovolume.h"
 183#include "llflexibleobject.h" 
 184#include "llvosurfacepatch.h"
 185#include "llviewerfloaterreg.h"
 186#include "llcommandlineparser.h"
 187#include "llfloatermemleak.h"
 188#include "llfloaterreg.h"
 189#include "llfloatersnapshot.h"
 190#include "llfloaterinventory.h"
 191
 192// includes for idle() idleShutdown()
 193#include "llviewercontrol.h"
 194#include "lleventnotifier.h"
 195#include "llcallbacklist.h"
 196#include "pipeline.h"
 197#include "llgesturemgr.h"
 198#include "llsky.h"
 199#include "llvlmanager.h"
 200#include "llviewercamera.h"
 201#include "lldrawpoolbump.h"
 202#include "llvieweraudio.h"
 203#include "llimview.h"
 204#include "llviewerthrottle.h"
 205#include "llparcel.h"
 206#include "llavatariconctrl.h"
 207#include "llgroupiconctrl.h"
 208#include "llviewerassetstats.h"
 209
 210// Include for security api initialization
 211#include "llsecapi.h"
 212#include "llmachineid.h"
 213#include "llmainlooprepeater.h"
 214
 215// *FIX: These extern globals should be cleaned up.
 216// The globals either represent state/config/resource-storage of either 
 217// this app, or another 'component' of the viewer. App globals should be 
 218// moved into the app class, where as the other globals should be 
 219// moved out of here.
 220// If a global symbol reference seems valid, it will be included
 221// via header files above.
 222
 223//----------------------------------------------------------------------------
 224// llviewernetwork.h
 225#include "llviewernetwork.h"
 226// define a self-registering event API object
 227#include "llappviewerlistener.h"
 228
 229#if (LL_LINUX || LL_SOLARIS) && LL_GTK
 230#include "glib.h"
 231#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
 232
 233#if LL_MSVC
 234// disable boost::lexical_cast warning
 235#pragma warning (disable:4702)
 236#endif
 237
 238static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
 239
 240////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
 241//
 242//----------------------------------------------------------------------------
 243// viewer.cpp - these are only used in viewer, should be easily moved.
 244
 245#if LL_DARWIN
 246extern void init_apple_menu(const char* product);
 247#endif // LL_DARWIN
 248
 249extern BOOL gRandomizeFramerate;
 250extern BOOL gPeriodicSlowFrame;
 251extern BOOL gDebugGL;
 252
 253////////////////////////////////////////////////////////////
 254// All from the last globals push...
 255
 256F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
 257F32 gSimFrames;
 258
 259BOOL gShowObjectUpdates = FALSE;
 260BOOL gUseQuickTime = TRUE;
 261
 262eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
 263
 264LLSD gDebugInfo;
 265
 266U32	gFrameCount = 0;
 267U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
 268LLPumpIO* gServicePump = NULL;
 269
 270U64 gFrameTime = 0;
 271F32 gFrameTimeSeconds = 0.f;
 272F32 gFrameIntervalSeconds = 0.f;
 273F32 gFPSClamped = 10.f;						// Pretend we start at target rate.
 274F32 gFrameDTClamped = 0.f;					// Time between adjacent checks to network for packets
 275U64	gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
 276U32 gFrameStalls = 0;
 277const F64 FRAME_STALL_THRESHOLD = 1.0;
 278
 279LLTimer gRenderStartTime;
 280LLFrameTimer gForegroundTime;
 281LLFrameTimer gLoggedInTime;
 282LLTimer gLogoutTimer;
 283static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
 284F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
 285
 286BOOL				gDisconnected = FALSE;
 287
 288// used to restore texture state after a mode switch
 289LLFrameTimer	gRestoreGLTimer;
 290BOOL			gRestoreGL = FALSE;
 291BOOL				gUseWireframe = FALSE;
 292
 293// VFS globals - see llappviewer.h
 294LLVFS* gStaticVFS = NULL;
 295
 296LLMemoryInfo gSysMemory;
 297U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
 298
 299std::string gLastVersionChannel;
 300
 301LLVector3			gWindVec(3.0, 3.0, 0.0);
 302LLVector3			gRelativeWindVec(0.0, 0.0, 0.0);
 303
 304U32		gPacketsIn = 0;
 305
 306BOOL				gPrintMessagesThisFrame = FALSE;
 307
 308BOOL gRandomizeFramerate = FALSE;
 309BOOL gPeriodicSlowFrame = FALSE;
 310
 311BOOL gCrashOnStartup = FALSE;
 312BOOL gLLErrorActivated = FALSE;
 313BOOL gLogoutInProgress = FALSE;
 314
 315////////////////////////////////////////////////////////////
 316// Internal globals... that should be removed.
 317static std::string gArgs;
 318
 319const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
 320const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
 321const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
 322const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
 323static BOOL gDoDisconnect = FALSE;
 324static std::string gLaunchFileOnQuit;
 325
 326// Used on Win32 for other apps to identify our window (eg, win_setup)
 327const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
 328
 329//-- LLDeferredTaskList ------------------------------------------------------
 330
 331/**
 332 * A list of deferred tasks.
 333 *
 334 * We sometimes need to defer execution of some code until the viewer gets idle,
 335 * e.g. removing an inventory item from within notifyObservers() may not work out.
 336 *
 337 * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration.
 338 * All tasks are executed only once.
 339 */
 340class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>
 341{
 342	LOG_CLASS(LLDeferredTaskList);
 343
 344	friend class LLAppViewer;
 345	typedef boost::signals2::signal<void()> signal_t;
 346
 347	void addTask(const signal_t::slot_type& cb)
 348	{
 349		mSignal.connect(cb);
 350	}
 351
 352	void run()
 353	{
 354		if (!mSignal.empty())
 355		{
 356			mSignal();
 357			mSignal.disconnect_all_slots();
 358		}
 359	}
 360
 361	signal_t mSignal;
 362};
 363
 364//----------------------------------------------------------------------------
 365
 366// List of entries from strings.xml to always replace
 367static std::set<std::string> default_trans_args;
 368void init_default_trans_args()
 369{
 370	default_trans_args.insert("SECOND_LIFE"); // World
 371	default_trans_args.insert("APP_NAME");
 372	default_trans_args.insert("CAPITALIZED_APP_NAME");
 373	default_trans_args.insert("SECOND_LIFE_GRID");
 374	default_trans_args.insert("SUPPORT_SITE");
 375}
 376
 377//----------------------------------------------------------------------------
 378// File scope definitons
 379const char *VFS_DATA_FILE_BASE = "data.db2.x.";
 380const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
 381
 382
 383struct SettingsFile : public LLInitParam::Block<SettingsFile>
 384{
 385	Mandatory<std::string>	name;
 386	Optional<std::string>	file_name;
 387	Optional<bool>			required,
 388							persistent;
 389	Optional<std::string>	file_name_setting;
 390
 391	SettingsFile()
 392	:	name("name"),
 393		file_name("file_name"),
 394		required("required", false),
 395		persistent("persistent", true),
 396		file_name_setting("file_name_setting")
 397	{}
 398};
 399
 400struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
 401{
 402	Mandatory<std::string>	name;
 403	Mandatory<S32>			path_index;
 404	Multiple<SettingsFile>	files;
 405
 406	SettingsGroup()
 407	:	name("name"),
 408		path_index("path_index"),
 409		files("file")
 410	{}
 411};
 412
 413struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
 414{
 415	Multiple<SettingsGroup>	groups;
 416
 417	SettingsFiles()
 418	: groups("group")
 419	{}
 420};
 421
 422static std::string gWindowTitle;
 423
 424LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
 425
 426//----------------------------------------------------------------------------
 427// Metrics logging control constants
 428//----------------------------------------------------------------------------
 429static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
 430static const F32 METRICS_INTERVAL_QA = 30.0;
 431static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
 432static bool app_metrics_qa_mode = false;
 433
 434void idle_afk_check()
 435{
 436	// check idle timers
 437	F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
 438	F32 afk_timeout  = gSavedSettings.getS32("AFKTimeout");
 439	if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK())
 440	{
 441		LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
 442		gAgent.setAFK();
 443	}
 444}
 445
 446// A callback set in LLAppViewer::init()
 447static void ui_audio_callback(const LLUUID& uuid)
 448{
 449	if (gAudiop)
 450	{
 451		gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
 452	}
 453}
 454
 455bool	create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
 456{
 457	if(!match || !base || base->getPlainText())
 458		return false;
 459
 460	LLUUID match_id = match->getID();
 461
 462	LLIconCtrl* icon;
 463
 464	if(gAgent.isInGroup(match_id, TRUE))
 465	{
 466		LLGroupIconCtrl::Params icon_params;
 467		icon_params.group_id = match_id;
 468		icon_params.rect = LLRect(0, 16, 16, 0);
 469		icon_params.visible = true;
 470		icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
 471	}
 472	else
 473	{
 474		LLAvatarIconCtrl::Params icon_params;
 475		icon_params.avatar_id = match_id;
 476		icon_params.rect = LLRect(0, 16, 16, 0);
 477		icon_params.visible = true;
 478		icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
 479	}
 480
 481	LLInlineViewSegment::Params params;
 482	params.force_newline = false;
 483	params.view = icon;
 484	params.left_pad = 4;
 485	params.right_pad = 4;
 486	params.top_pad = -2;
 487	params.bottom_pad = 2;
 488
 489	base->appendWidget(params," ",false);
 490	
 491	return true;
 492}
 493
 494void request_initial_instant_messages()
 495{
 496	static BOOL requested = FALSE;
 497	if (!requested
 498		&& gMessageSystem
 499		&& LLMuteList::getInstance()->isLoaded()
 500		&& isAgentAvatarValid())
 501	{
 502		// Auto-accepted inventory items may require the avatar object
 503		// to build a correct name.  Likewise, inventory offers from
 504		// muted avatars require the mute list to properly mute.
 505		LLMessageSystem* msg = gMessageSystem;
 506		msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
 507		msg->nextBlockFast(_PREHASH_AgentData);
 508		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 509		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 510		gAgent.sendReliableMessage();
 511		requested = TRUE;
 512	}
 513}
 514
 515// Use these strictly for things that are constructed at startup,
 516// or for things that are performance critical.  JC
 517static void settings_to_globals()
 518{
 519	LLBUTTON_H_PAD		= gSavedSettings.getS32("ButtonHPad");
 520	BTN_HEIGHT_SMALL	= gSavedSettings.getS32("ButtonHeightSmall");
 521	BTN_HEIGHT			= gSavedSettings.getS32("ButtonHeight");
 522
 523	MENU_BAR_HEIGHT		= gSavedSettings.getS32("MenuBarHeight");
 524	MENU_BAR_WIDTH		= gSavedSettings.getS32("MenuBarWidth");
 525
 526	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
 527	
 528	LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile");
 529
 530	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");
 531	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor");
 532	LLVOVolume::sDistanceFactor			= 1.f-LLVOVolume::sLODFactor * 0.1f;
 533	LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
 534	LLVOTree::sTreeFactor				= gSavedSettings.getF32("RenderTreeLODFactor");
 535	LLVOAvatar::sLODFactor				= gSavedSettings.getF32("RenderAvatarLODFactor");
 536	LLVOAvatar::sPhysicsLODFactor		= gSavedSettings.getF32("RenderAvatarPhysicsLODFactor");
 537	LLVOAvatar::sMaxVisible				= (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
 538	LLVOAvatar::sVisibleInFirstPerson	= gSavedSettings.getBOOL("FirstPersonAvatarVisible");
 539	// clamp auto-open time to some minimum usable value
 540	LLFolderView::sAutoOpenTime			= llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
 541	LLSelectMgr::sRectSelectInclusive	= gSavedSettings.getBOOL("RectangleSelectInclusive");
 542	LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
 543	LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
 544
 545	gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns"));
 546	gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns"));
 547	gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
 548
 549	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
 550	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
 551	LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
 552}
 553
 554static void settings_modify()
 555{
 556	LLRenderTarget::sUseFBO				= gSavedSettings.getBOOL("RenderDeferred");
 557	LLPipeline::sRenderDeferred			= gSavedSettings.getBOOL("RenderDeferred");
 558	LLVOAvatar::sUseImpostors			= gSavedSettings.getBOOL("RenderUseImpostors");
 559	LLVOSurfacePatch::sLODFactor		= gSavedSettings.getF32("RenderTerrainLODFactor");
 560	LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
 561	gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
 562	gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
 563	gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
 564}
 565
 566class LLFastTimerLogThread : public LLThread
 567{
 568public:
 569	std::string mFile;
 570
 571	LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
 572 	{
 573		std::string file_name = test_name + std::string(".slp");
 574		mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
 575	}
 576
 577	void run()
 578	{
 579		std::ofstream os(mFile.c_str());
 580		
 581		while (!LLAppViewer::instance()->isQuitting())
 582		{
 583			LLFastTimer::writeLog(os);
 584			os.flush();
 585			ms_sleep(32);
 586		}
 587
 588		os.close();
 589	}
 590};
 591
 592//virtual
 593bool LLAppViewer::initSLURLHandler()
 594{
 595	// does nothing unless subclassed
 596	return false;
 597}
 598
 599//virtual
 600bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
 601{
 602	// does nothing unless subclassed
 603	return false;
 604}
 605
 606//----------------------------------------------------------------------------
 607// LLAppViewer definition
 608
 609// Static members.
 610// The single viewer app.
 611LLAppViewer* LLAppViewer::sInstance = NULL;
 612LLTextureCache* LLAppViewer::sTextureCache = NULL; 
 613LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; 
 614LLTextureFetch* LLAppViewer::sTextureFetch = NULL; 
 615
 616LLAppViewer::LLAppViewer() : 
 617	mMarkerFile(),
 618	mLogoutMarkerFile(NULL),
 619	mReportedCrash(false),
 620	mNumSessions(0),
 621	mPurgeCache(false),
 622	mPurgeOnExit(false),
 623	mSecondInstance(false),
 624	mSavedFinalSnapshot(false),
 625	mForceGraphicsDetail(false),
 626	mQuitRequested(false),
 627	mLogoutRequestSent(false),
 628	mYieldTime(-1),
 629	mMainloopTimeout(NULL),
 630	mAgentRegionLastAlive(false),
 631	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
 632	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
 633	mFastTimerLogThread(NULL),
 634	mUpdater(new LLUpdaterService()),
 635	mSettingsLocationList(NULL)
 636{
 637	if(NULL != sInstance)
 638	{
 639		llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
 640	}
 641
 642	setupErrorHandling();
 643	sInstance = this;
 644	gLoggedInTime.stop();
 645	
 646	LLLoginInstance::instance().setUpdaterService(mUpdater.get());
 647}
 648
 649LLAppViewer::~LLAppViewer()
 650{
 651	delete mSettingsLocationList;
 652
 653	LLLoginInstance::instance().setUpdaterService(0);
 654	
 655	destroyMainloopTimeout();
 656
 657	// If we got to this destructor somehow, the app didn't hang.
 658	removeMarkerFile();
 659}
 660
 661bool LLAppViewer::init()
 662{	
 663	//
 664	// Start of the application
 665	//
 666	// IMPORTANT! Do NOT put anything that will write
 667	// into the log files during normal startup until AFTER
 668	// we run the "program crashed last time" error handler below.
 669	//
 670	LLFastTimer::reset();
 671
 672	// initialize SSE options
 673	LLVector4a::initClass();
 674
 675	// Need to do this initialization before we do anything else, since anything
 676	// that touches files should really go through the lldir API
 677	gDirUtilp->initAppDirs("SecondLife");
 678	// set skin search path to default, will be overridden later
 679	// this allows simple skinned file lookups to work
 680	gDirUtilp->setSkinFolder("default");
 681
 682	initLogging();
 683	
 684	//
 685	// OK to write stuff to logs now, we've now crash reported if necessary
 686	//
 687	
 688	init_default_trans_args();
 689	
 690	if (!initConfiguration())
 691		return false;
 692
 693	LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
 694
 695	//set the max heap size.
 696	initMaxHeapSize() ;
 697
 698	LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ;
 699
 700	// write Google Breakpad minidump files to our log directory
 701	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
 702	logdir += gDirUtilp->getDirDelimiter();
 703	setMiniDumpDir(logdir);
 704
 705	// Although initLogging() is the right place to mess with
 706	// setFatalFunction(), we can't query gSavedSettings until after
 707	// initConfiguration().
 708	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
 709	if (rc >= 0)
 710	{
 711		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
 712		// rather than exit() because normal cleanup depends too much on
 713		// successful startup!
 714		LLError::setFatalFunction(boost::bind(_exit, rc));
 715	}
 716
 717    mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
 718
 719#if LL_RECORD_VIEWER_STATS
 720	LLViewerStatsRecorder::initClass();
 721#endif
 722
 723    // *NOTE:Mani - LLCurl::initClass is not thread safe. 
 724    // Called before threads are created.
 725    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), 
 726						gSavedSettings.getS32("CurlMaximumNumberOfHandles"), 
 727						gSavedSettings.getBOOL("CurlUseMultipleThreads"));
 728	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
 729
 730    LLMachineID::init();
 731	
 732	{
 733		// Viewer metrics initialization
 734		static LLCachedControl<bool> metrics_submode(gSavedSettings,
 735													 "QAModeMetrics",
 736													 false,
 737													 "Enables QA features (logging, faster cycling) for metrics collector");
 738
 739		if (metrics_submode)
 740		{
 741			app_metrics_qa_mode = true;
 742			app_metrics_interval = METRICS_INTERVAL_QA;
 743		}
 744		LLViewerAssetStatsFF::init();
 745	}
 746
 747	initThreads();
 748	LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
 749
 750	// Initialize settings early so that the defaults for ignorable dialogs are
 751	// picked up and then correctly re-saved after launching the updater (STORM-1268).
 752	LLUI::settings_map_t settings_map;
 753	settings_map["config"] = &gSavedSettings;
 754	settings_map["ignores"] = &gWarningSettings;
 755	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
 756	settings_map["account"] = &gSavedPerAccountSettings;
 757
 758	LLUI::initClass(settings_map,
 759		LLUIImageList::getInstance(),
 760		ui_audio_callback,
 761		&LLUI::sGLScaleFactor);
 762	LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
 763
 764	// Setup paths and LLTrans after LLUI::initClass has been called.
 765	LLUI::setupPaths();
 766	LLTransUtil::parseStrings("strings.xml", default_trans_args);
 767	LLTransUtil::parseLanguageStrings("language_settings.xml");
 768
 769	// Setup notifications after LLUI::setupPaths() has been called.
 770	LLNotifications::instance();
 771	LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
 772
 773    writeSystemInfo();
 774
 775	// Initialize updater service (now that we have an io pump)
 776	initUpdater();
 777	if(isQuitting())
 778	{
 779		// Early out here because updater set the quitting flag.
 780		return true;
 781	}
 782
 783	//////////////////////////////////////////////////////////////////////////////
 784	//////////////////////////////////////////////////////////////////////////////
 785	//////////////////////////////////////////////////////////////////////////////
 786	//////////////////////////////////////////////////////////////////////////////
 787	// *FIX: The following code isn't grouped into functions yet.
 788
 789	// Statistics / debug timer initialization
 790	init_statistics();
 791	
 792	//
 793	// Various introspection concerning the libs we're using - particularly
 794	// the libs involved in getting to a full login screen.
 795	//
 796	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
 797	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
 798
 799	/////////////////////////////////////////////////
 800	// OS-specific login dialogs
 801	/////////////////////////////////////////////////
 802
 803	//test_cached_control();
 804
 805	// track number of times that app has run
 806	mNumSessions = gSavedSettings.getS32("NumSessions");
 807	mNumSessions++;
 808	gSavedSettings.setS32("NumSessions", mNumSessions);
 809
 810	if (gSavedSettings.getBOOL("VerboseLogs"))
 811	{
 812		LLError::setPrintLocation(true);
 813	}
 814
 815	// LLKeyboard relies on LLUI to know what some accelerator keys are called.
 816	LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
 817
 818	LLWeb::initClass();			  // do this after LLUI
 819	
 820	// Provide the text fields with callbacks for opening Urls
 821	LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
 822	LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
 823	LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
 824	LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
 825
 826	// Let code in llui access the viewer help floater
 827	LLUI::sHelpImpl = LLViewerHelp::getInstance();
 828
 829	LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ;
 830
 831	// Load translations for tooltips
 832	LLFloater::initClass();
 833
 834	/////////////////////////////////////////////////
 835	
 836	LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
 837	
 838	LLViewerFloaterReg::registerFloaters();
 839	
 840	/////////////////////////////////////////////////
 841	//
 842	// Load settings files
 843	//
 844	//
 845	LLGroupMgr::parseRoleActions("role_actions.xml");
 846
 847	LLAgent::parseTeleportMessages("teleport_strings.xml");
 848
 849	// load MIME type -> media impl mappings
 850	std::string mime_types_name;
 851#if LL_DARWIN
 852	mime_types_name = "mime_types_mac.xml";
 853#elif LL_LINUX
 854	mime_types_name = "mime_types_linux.xml";
 855#else
 856	mime_types_name = "mime_types.xml";
 857#endif
 858	LLMIMETypes::parseMIMETypes( mime_types_name ); 
 859
 860	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
 861	settings_to_globals();
 862	// Setup settings listeners
 863	settings_setup_listeners();
 864	// Modify settings based on system configuration and compile options
 865	settings_modify();
 866
 867	// Find partition serial number (Windows) or hardware serial (Mac)
 868	mSerialNumber = generateSerialNumber();
 869
 870	// do any necessary set-up for accepting incoming SLURLs from apps
 871	initSLURLHandler();
 872
 873	if(false == initHardwareTest())
 874	{
 875		// Early out from user choice.
 876		return false;
 877	}
 878	LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
 879
 880	// Prepare for out-of-memory situations, during which we will crash on
 881	// purpose and save a dump.
 882#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
 883	MemSetErrorHandler(first_mem_error_handler);
 884#endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
 885
 886	// *Note: this is where gViewerStats used to be created.
 887
 888	//
 889	// Initialize the VFS, and gracefully handle initialization errors
 890	//
 891
 892	if (!initCache())
 893	{
 894		std::ostringstream msg;
 895		msg << LLTrans::getString("MBUnableToAccessFile");
 896		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
 897		return 1;
 898	}
 899	LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
 900
 901	// Initialize the repeater service.
 902	LLMainLoopRepeater::instance().start();
 903
 904	//
 905	// Initialize the window
 906	//
 907	gGLActive = TRUE;
 908	initWindow();
 909	LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
 910
 911	// initWindow also initializes the Feature List, so now we can initialize this global.
 912	LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
 913
 914	// call all self-registered classes
 915	LLInitClassList::instance().fireCallbacks();
 916
 917	LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
 918		
 919	gGLManager.getGLInfo(gDebugInfo);
 920	gGLManager.printGLInfoString();
 921
 922	// Load Default bindings
 923	std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
 924														gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
 925														gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
 926
 927
 928	if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
 929	{
 930		std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
 931															gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
 932															gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
 933		if (!gViewerKeyboard.loadBindings(key_bindings_file))
 934		{
 935			LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
 936		}
 937	}
 938
 939	// If we don't have the right GL requirements, exit.
 940	if (!gGLManager.mHasRequirements)
 941	{	
 942		// can't use an alert here since we're exiting and
 943		// all hell breaks lose.
 944		OSMessageBox(
 945			LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
 946			LLStringUtil::null,
 947			OSMB_OK);
 948		return 0;
 949	}
 950
 951	// Without SSE2 support we will crash almost immediately, warn here.
 952	if (!gSysCPU.hasSSE2())
 953	{	
 954		// can't use an alert here since we're exiting and
 955		// all hell breaks lose.
 956		OSMessageBox(
 957			LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
 958			LLStringUtil::null,
 959			OSMB_OK);
 960		return 0;
 961	}
 962
 963	// alert the user if they are using unsupported hardware
 964	if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
 965	{
 966		bool unsupported = false;
 967		LLSD args;
 968		std::string minSpecs;
 969		
 970		// get cpu data from xml
 971		std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
 972		S32 minCPU = 0;
 973		minCPUString >> minCPU;
 974
 975		// get RAM data from XML
 976		std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
 977		U64 minRAM = 0;
 978		minRAMString >> minRAM;
 979		minRAM = minRAM * 1024 * 1024;
 980
 981		if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
 982		{
 983			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
 984			minSpecs += "\n";
 985			unsupported = true;
 986		}
 987		if(gSysCPU.getMHz() < minCPU)
 988		{
 989			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
 990			minSpecs += "\n";
 991			unsupported = true;
 992		}
 993		if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
 994		{
 995			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
 996			minSpecs += "\n";
 997			unsupported = true;
 998		}
 999
1000		if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
1001		{
1002			LLNotificationsUtil::add("UnknownGPU");
1003		} 
1004			
1005		if(unsupported)
1006		{
1007			if(!gSavedSettings.controlExists("WarnUnsupportedHardware") 
1008				|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
1009			{
1010				args["MINSPECS"] = minSpecs;
1011				LLNotificationsUtil::add("UnsupportedHardware", args );
1012			}
1013
1014		}
1015	}
1016
1017
1018	// save the graphics card
1019	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
1020
1021	// Save the current version to the prefs file
1022	gSavedSettings.setString("LastRunVersion",
1023							 LLVersionInfo::getChannelAndVersion());
1024
1025	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
1026	gSimFrames = (F32)gFrameCount;
1027
1028	LLViewerJoystick::getInstance()->init(false);
1029
1030	try {
1031		initializeSecHandler();
1032	}
1033	catch (LLProtectedDataException ex)
1034	{
1035	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
1036	}
1037	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
1038
1039
1040	gGLActive = FALSE;
1041	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
1042	{
1043		loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
1044	}
1045	
1046	LLViewerMedia::initClass();
1047	LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ;
1048
1049	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
1050
1051	//EXT-7013 - On windows for some locale (Japanese) standard 
1052	//datetime formatting functions didn't support some parameters such as "weekday".
1053	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
1054	std::string language = gSavedSettings.getString("Language");
1055	if(language == "ja" || language == "pl")
1056	{
1057		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
1058		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
1059		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
1060		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
1061		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
1062
1063		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
1064		LLStringOps::sPM = LLTrans::getString("dateTimePM");
1065	}
1066
1067	LLAgentLanguage::init();
1068
1069	return true;
1070}
1071
1072void LLAppViewer::initMaxHeapSize()
1073{
1074	//set the max heap size.
1075	//here is some info regarding to the max heap size:
1076	//------------------------------------------------------------------------------------------
1077	// OS       | setting | SL address bits | max manageable memory space | max heap size
1078	// Win 32   | default | 32-bit          | 2GB                         | < 1.7GB
1079	// Win 32   | /3G     | 32-bit          | 3GB                         | < 1.7GB or 2.7GB
1080	//Linux 32  | default | 32-bit          | 3GB                         | < 2.7GB
1081	//Linux 32  |HUGEMEM  | 32-bit          | 4GB                         | < 3.7GB
1082	//64-bit OS |default  | 32-bit          | 4GB                         | < 3.7GB
1083	//64-bit OS |default  | 64-bit          | N/A (> 4GB)                 | N/A (> 4GB)
1084	//------------------------------------------------------------------------------------------
1085	//currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
1086
1087	//F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
1088	F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ;
1089	BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ;
1090
1091	LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
1092}
1093
1094void LLAppViewer::checkMemory()
1095{
1096	const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
1097	//const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
1098	//static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
1099
1100	if(!gGLManager.mDebugGPU)
1101	{
1102		return ;
1103	}
1104
1105	if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
1106	{
1107		return ;
1108	}
1109	mMemCheckTimer.reset() ;
1110
1111		//update the availability of memory
1112		LLMemory::updateMemoryInfo() ;
1113
1114	bool is_low = LLMemory::isMemoryPoolLow() ;
1115
1116	LLPipeline::throttleNewMemoryAllocation(is_low) ;		
1117	
1118	if(is_low)
1119	{
1120		LLMemory::logMemoryInfo() ;
1121	}
1122}
1123
1124static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
1125static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
1126static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
1127static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
1128static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
1129static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
1130static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
1131static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
1132static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
1133static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares");
1134static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service");
1135static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback");
1136static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot");
1137static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update");
1138
1139bool LLAppViewer::mainLoop()
1140{
1141	LLMemType mt1(LLMemType::MTYPE_MAIN);
1142	mMainloopTimeout = new LLWatchdogTimeout();
1143	
1144	//-------------------------------------------
1145	// Run main loop until time to quit
1146	//-------------------------------------------
1147
1148	// Create IO Pump to use for HTTP Requests.
1149	gServicePump = new LLPumpIO(gAPRPoolp);
1150	LLHTTPClient::setPump(*gServicePump);
1151	LLCurl::setCAFile(gDirUtilp->getCAFile());
1152
1153	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
1154
1155	LLVoiceChannel::initClass();
1156	LLVoiceClient::getInstance()->init(gServicePump);
1157	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);
1158	LLTimer frameTimer,idleTimer;
1159	LLTimer debugTime;
1160	LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
1161	joystick->setNeedsReset(true);
1162
1163    LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
1164    // As we do not (yet) send data on the mainloop LLEventPump that varies
1165    // with each frame, no need to instantiate a new LLSD event object each
1166    // time. Obviously, if that changes, just instantiate the LLSD at the
1167    // point of posting.
1168    LLSD newFrame;
1169
1170	//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
1171	//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
1172	//LLPrivateMemoryPoolTester::destroy() ;
1173
1174	// Handle messages
1175	while (!LLApp::isExiting())
1176	{
1177		LLFastTimer::nextFrame(); // Should be outside of any timer instances
1178
1179		//clear call stack records
1180		llclearcallstacks;
1181
1182		//check memory availability information
1183		checkMemory() ;
1184		
1185		try
1186		{
1187			pingMainloopTimeout("Main:MiscNativeWindowEvents");
1188
1189			if (gViewerWindow)
1190			{
1191				LLFastTimer t2(FTM_MESSAGES);
1192				gViewerWindow->getWindow()->processMiscNativeEvents();
1193			}
1194		
1195			pingMainloopTimeout("Main:GatherInput");
1196			
1197			if (gViewerWindow)
1198			{
1199				LLFastTimer t2(FTM_MESSAGES);
1200				if (!restoreErrorTrap())
1201				{
1202					llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
1203				}
1204
1205				gViewerWindow->getWindow()->gatherInput();
1206			}
1207
1208#if 1 && !LL_RELEASE_FOR_DOWNLOAD
1209			// once per second debug info
1210			if (debugTime.getElapsedTimeF32() > 1.f)
1211			{
1212				debugTime.reset();
1213			}
1214			
1215#endif
1216			//memory leaking simulation
1217			LLFloaterMemLeak* mem_leak_instance =
1218				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
1219			if(mem_leak_instance)
1220			{
1221				mem_leak_instance->idle() ;				
1222			}			
1223
1224            // canonical per-frame event
1225            mainloop.post(newFrame);
1226
1227			if (!LLApp::isExiting())
1228			{
1229				pingMainloopTimeout("Main:JoystickKeyboard");
1230				
1231				// Scan keyboard for movement keys.  Command keys and typing
1232				// are handled by windows callbacks.  Don't do this until we're
1233				// done initializing.  JC
1234				if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible())
1235					&& gViewerWindow->getActive()
1236					&& !gViewerWindow->getWindow()->getMinimized()
1237					&& LLStartUp::getStartupState() == STATE_STARTED
1238					&& (gHeadlessClient || !gViewerWindow->getShowProgress())
1239					&& !gFocusMgr.focusLocked())
1240				{
1241					LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
1242					joystick->scanJoystick();
1243					gKeyboard->scanKeyboard();
1244				}
1245
1246				// Update state based on messages, user input, object idle.
1247				{
1248					pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
1249					
1250					LLFastTimer t3(FTM_IDLE);
1251					idle();
1252
1253					if (gAres != NULL && gAres->isInitialized())
1254					{
1255						LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
1256						pingMainloopTimeout("Main:ServicePump");				
1257						LLFastTimer t4(FTM_PUMP);
1258						{
1259							LLFastTimer t(FTM_PUMP_ARES);
1260							gAres->process();
1261						}
1262						{
1263							LLFastTimer t(FTM_PUMP_SERVICE);
1264							// this pump is necessary to make the login screen show up
1265							gServicePump->pump();
1266
1267							{
1268								LLFastTimer t(FTM_SERVICE_CALLBACK);
1269								gServicePump->callback();
1270							}
1271						}
1272					}
1273					
1274					resumeMainloopTimeout();
1275				}
1276 
1277				if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
1278				{
1279					pauseMainloopTimeout();
1280					saveFinalSnapshot();
1281					disconnectViewer();
1282					resumeMainloopTimeout();
1283				}
1284
1285				// Render scene.
1286				// *TODO: Should we run display() even during gHeadlessClient?  DK 2011-02-18
1287				if (!LLApp::isExiting() && !gHeadlessClient)
1288				{
1289					pingMainloopTimeout("Main:Display");
1290					gGLActive = TRUE;
1291					display();
1292					pingMainloopTimeout("Main:Snapshot");
1293					LLFloaterSnapshot::update(); // take snapshots
1294					gGLActive = FALSE;
1295				}
1296
1297			}
1298
1299			pingMainloopTimeout("Main:Sleep");
1300			
1301			pauseMainloopTimeout();
1302
1303			// Sleep and run background threads
1304			{
1305				LLMemType mt_sleep(LLMemType::MTYPE_SLEEP);
1306				LLFastTimer t2(FTM_SLEEP);
1307				
1308				// yield some time to the os based on command line option
1309				if(mYieldTime >= 0)
1310				{
1311					ms_sleep(mYieldTime);
1312				}
1313
1314				// yield cooperatively when not running as foreground window
1315				if (   (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
1316						|| !gFocusMgr.getAppHasFocus())
1317				{
1318					// Sleep if we're not rendering, or the window is minimized.
1319					S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
1320					// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
1321					// of equal priority on Windows
1322					if (milliseconds_to_sleep > 0)
1323					{
1324						ms_sleep(milliseconds_to_sleep);
1325						// also pause worker threads during this wait period
1326						LLAppViewer::getTextureCache()->pause();
1327						LLAppViewer::getImageDecodeThread()->pause();
1328					}
1329				}
1330				
1331				if (mRandomizeFramerate)
1332				{
1333					ms_sleep(rand() % 200);
1334				}
1335
1336				if (mPeriodicSlowFrame
1337					&& (gFrameCount % 10 == 0))
1338				{
1339					llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
1340					ms_sleep(500);
1341				}
1342
1343				static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds				
1344				const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second
1345				idleTimer.reset();
1346				bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
1347				S32 total_work_pending = 0;
1348				S32 total_io_pending = 0;	
1349				while(!is_slow)//do not unpause threads if the frame rates are very low.
1350				{
1351					S32 work_pending = 0;
1352					S32 io_pending = 0;
1353					F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
1354
1355					{
1356						LLFastTimer ftm(FTM_TEXTURE_CACHE);
1357 						work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
1358					}
1359					{
1360						LLFastTimer ftm(FTM_DECODE);
1361	 					work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
1362					}
1363					{
1364						LLFastTimer ftm(FTM_DECODE);
1365	 					work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
1366					}
1367
1368					{
1369						LLFastTimer ftm(FTM_VFS);
1370	 					io_pending += LLVFSThread::updateClass(1);
1371					}
1372					{
1373						LLFastTimer ftm(FTM_LFS);
1374	 					io_pending += LLLFSThread::updateClass(1);
1375					}
1376
1377					if (io_pending > 1000)
1378					{
1379						ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
1380					}
1381
1382					total_work_pending += work_pending ;
1383					total_io_pending += io_pending ;
1384					
1385					if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
1386					{
1387						break;
1388					}
1389				}
1390				gMeshRepo.update() ;
1391				
1392				if(!LLCurl::getCurlThread()->update(1))
1393				{
1394					LLCurl::getCurlThread()->pause() ; //nothing in the curl thread.
1395				}
1396
1397				if(!total_work_pending) //pause texture fetching threads if nothing to process.
1398				{
1399					LLAppViewer::getTextureCache()->pause();
1400					LLAppViewer::getImageDecodeThread()->pause();
1401					LLAppViewer::getTextureFetch()->pause(); 
1402				}
1403				if(!total_io_pending) //pause file threads if nothing to process.
1404				{
1405					LLVFSThread::sLocal->pause(); 
1406					LLLFSThread::sLocal->pause(); 
1407				}									
1408
1409				if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
1410					(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
1411				{
1412					gFrameStalls++;
1413				}
1414				frameTimer.reset();
1415
1416				resumeMainloopTimeout();
1417	
1418				pingMainloopTimeout("Main:End");
1419			}	
1420		}
1421		catch(std::bad_alloc)
1422		{			
1423			LLMemory::logMemoryInfo(TRUE) ;
1424
1425			//stop memory leaking simulation
1426			LLFloaterMemLeak* mem_leak_instance =
1427				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
1428			if(mem_leak_instance)
1429			{
1430				mem_leak_instance->stop() ;				
1431				llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
1432			}
1433			else
1434			{
1435				//output possible call stacks to log file.
1436				LLError::LLCallStacks::print() ;
1437
1438				llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
1439			}
1440		}
1441	}
1442
1443	// Save snapshot for next time, if we made it through initialization
1444	if (STATE_STARTED == LLStartUp::getStartupState())
1445	{
1446		try
1447		{
1448			saveFinalSnapshot();
1449		}
1450		catch(std::bad_alloc)
1451		{
1452			llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
1453
1454			//stop memory leaking simulation
1455			LLFloaterMemLeak* mem_leak_instance =
1456				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
1457			if(mem_leak_instance)
1458			{
1459				mem_leak_instance->stop() ;				
1460			}	
1461		}
1462	}
1463	
1464	delete gServicePump;
1465
1466	destroyMainloopTimeout();
1467
1468	llinfos << "Exiting main_loop" << llendflush;
1469
1470	return true;
1471}
1472
1473void LLAppViewer::flushVFSIO()
1474{
1475	while (1)
1476	{
1477		S32 pending = LLVFSThread::updateClass(0);
1478		pending += LLLFSThread::updateClass(0);
1479		if (!pending)
1480		{
1481			break;
1482		}
1483		llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
1484		ms_sleep(100);
1485	}
1486}
1487
1488bool LLAppViewer::cleanup()
1489{
1490	// workaround for DEV-35406 crash on shutdown
1491	LLEventPumps::instance().reset();
1492
1493	if (LLFastTimerView::sAnalyzePerformance)
1494	{
1495		llinfos << "Analyzing performance" << llendl;
1496		std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
1497		std::string current_name  = LLFastTimer::sLogName + ".slp"; 
1498		std::string report_name   = LLFastTimer::sLogName + "_report.csv";
1499
1500		LLFastTimerView::doAnalysis(
1501			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
1502			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
1503			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));		
1504	}
1505	LLMetricPerformanceTesterBasic::cleanClass();
1506
1507	// remove any old breakpad minidump files from the log directory
1508	if (! isError())
1509	{
1510		std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
1511		logdir += gDirUtilp->getDirDelimiter();
1512		gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
1513	}
1514
1515	// *TODO - generalize this and move DSO wrangling to a helper class -brad
1516	std::set<struct apr_dso_handle_t *>::const_iterator i;
1517	for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
1518	{
1519		int (*ll_plugin_stop_func)(void) = NULL;
1520		apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
1521		ll_plugin_stop_func();
1522
1523		rv = apr_dso_unload(*i);
1524	}
1525	mPlugins.clear();
1526
1527	//flag all elements as needing to be destroyed immediately
1528	// to ensure shutdown order
1529	LLMortician::setZealous(TRUE);
1530
1531	LLVoiceClient::getInstance()->terminate();
1532	
1533	disconnectViewer();
1534
1535	llinfos << "Viewer disconnected" << llendflush;
1536
1537	display_cleanup(); 
1538
1539	release_start_screen(); // just in case
1540
1541	LLError::logToFixedBuffer(NULL);
1542
1543	llinfos << "Cleaning Up" << llendflush;
1544
1545	// shut down mesh streamer
1546	gMeshRepo.shutdown();
1547
1548	// Must clean up texture references before viewer window is destroyed.
1549	if(LLHUDManager::instanceExists())
1550	{
1551		LLHUDManager::getInstance()->updateEffects();
1552		LLHUDObject::updateAll();
1553		LLHUDManager::getInstance()->cleanupEffects();
1554		LLHUDObject::cleanupHUDObjects();
1555		llinfos << "HUD Objects cleaned up" << llendflush;
1556	}
1557
1558	LLKeyframeDataCache::clear();
1559	
1560 	// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
1561#if 0 // this seems to get us stuck in an infinite loop...
1562	gTransferManager.cleanup();
1563#endif
1564	
1565	// Note: this is where gWorldMap used to be deleted.
1566
1567	// Note: this is where gHUDManager used to be deleted.
1568	if(LLHUDManager::instanceExists())
1569	{
1570		LLHUDManager::getInstance()->shutdownClass();
1571	}
1572
1573	delete gAssetStorage;
1574	gAssetStorage = NULL;
1575
1576	LLPolyMesh::freeAllMeshes();
1577
1578	LLStartUp::cleanupNameCache();
1579
1580	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
1581
1582	LLWorldMap::getInstance()->reset(); // release any images
1583
1584	LLCalc::cleanUp();
1585
1586	llinfos << "Global stuff deleted" << llendflush;
1587
1588	if (gAudiop)
1589	{
1590		// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
1591
1592		LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
1593		delete sai;
1594		gAudiop->setStreamingAudioImpl(NULL);
1595
1596		// shut down the audio subsystem
1597
1598		bool want_longname = false;
1599		if (gAudiop->getDriverName(want_longname) == "FMOD")
1600		{
1601			// This hack exists because fmod likes to occasionally
1602			// crash or hang forever when shutting down, for no
1603			// apparent reason.
1604			llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
1605		}
1606		else
1607		{
1608			gAudiop->shutdown();
1609		}
1610
1611		delete gAudiop;
1612		gAudiop = NULL;
1613	}
1614
1615	// Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
1616
1617	// Patch up settings for next time
1618	// Must do this before we delete the viewer window,
1619	// such that we can suck rectangle information out of
1620	// it.
1621	cleanupSavedSettings();
1622	llinfos << "Settings patched up" << llendflush;
1623
1624	// delete some of the files left around in the cache.
1625	removeCacheFiles("*.wav");
1626	removeCacheFiles("*.tmp");
1627	removeCacheFiles("*.lso");
1628	removeCacheFiles("*.out");
1629	removeCacheFiles("*.dsf");
1630	removeCacheFiles("*.bodypart");
1631	removeCacheFiles("*.clothing");
1632
1633	llinfos << "Cache files removed" << llendflush;
1634
1635	// Wait for any pending VFS IO
1636	flushVFSIO();
1637	llinfos << "Shutting down Views" << llendflush;
1638
1639	// Destroy the UI
1640	if( gViewerWindow)
1641		gViewerWindow->shutdownViews();
1642
1643	llinfos << "Cleaning up Inventory" << llendflush;
1644	
1645	// Cleanup Inventory after the UI since it will delete any remaining observers
1646	// (Deleted observers should have already removed themselves)
1647	gInventory.cleanupInventory();
1648
1649	llinfos << "Cleaning up Selections" << llendflush;
1650	
1651	// Clean up selection managers after UI is destroyed, as UI may be observing them.
1652	// Clean up before GL is shut down because we might be holding on to objects with texture references
1653	LLSelectMgr::cleanupGlobals();
1654	
1655	llinfos << "Shutting down OpenGL" << llendflush;
1656
1657	// Shut down OpenGL
1658	if( gViewerWindow)
1659	{
1660		gViewerWindow->shutdownGL();
1661	
1662		// Destroy window, and make sure we're not ful…

Large files files are truncated, but you can click here to view the full file