Skip to content
Snippets Groups Projects
llappviewer.cpp 145 KiB
Newer Older
  • Learn to ignore specific revisions
  • /** 
     * @file llappviewer.cpp
     * @brief The LLAppViewer class definitions
     *
    
     * $LicenseInfo:firstyear=2007&license=viewerlgpl$
    
     * Copyright (C) 2010, Linden Research, Inc.
     * 
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation;
     * version 2.1 of the License only.
    
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
    
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    
     * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
    
     * $/LicenseInfo$
     */
    
    #include "llviewerprecompiledheaders.h"
    
    #include "llversioninfo.h"
    
    #include "lluictrlfactory.h"
    
    #include "lltexteditor.h"
    
    #include "llviewertexturelist.h"
    
    #include "llgroupmgr.h"
    #include "llagent.h"
    
    #include "llagentwearables.h"
    
    #include "llwindow.h"
    #include "llviewerstats.h"
    
    Josh Bell's avatar
    Josh Bell committed
    #include "llmimetypes.h"
    
    #include "llstartup.h"
    #include "llfocusmgr.h"
    #include "llviewerjoystick.h"
    
    #include "llallocator.h"
    
    Josh Bell's avatar
    Josh Bell committed
    #include "llares.h" 
    
    #include "lltexturestats.h"
    #include "lltexturestats.h"
    
    #include "llviewerwindow.h"
    #include "llviewerdisplay.h"
    
    #include "llviewermedia.h"
    
    #include "llviewerparcelmedia.h"
    #include "llviewermediafocus.h"
    
    #include "llviewermessage.h"
    #include "llviewerobjectlist.h"
    #include "llworldmap.h"
    #include "llmutelist.h"
    
    #include "llviewerhelp.h"
    
    #include "lluicolortable.h"
    
    Josh Bell's avatar
    Josh Bell committed
    #include "llurlhistory.h"
    
    #include "llrender.h"
    
    #include "llteleporthistory.h"
    
    #include "lllocationhistory.h"
    #include "llfasttimerview.h"
    
    #include "llvoavatarself.h"
    
    #include "llurlmatch.h"
    #include "lltextutil.h"
    
    #include "lllogininstance.h"
    
    #include "llweb.h"
    #include "llsecondlifeurls.h"
    
    // Linden library includes
    
    #include "llavatarnamecache.h"
    
    #include "llvfsthread.h"
    #include "llvolumemgr.h"
    
    #include "llnotifications.h"
    #include "llnotificationsutil.h"
    
    // Third party library includes
    
    #if LL_WINDOWS
    #	include <share.h> // For _SH_DENYWR in initMarkerFile
    #else
    #   include <sys/file.h> // For initMarkerFile support
    #endif
    
    
    #include "llapr.h"
    #include "apr_dso.h"
    #include <boost/lexical_cast.hpp>
    
    
    #include "llviewerkeyboard.h"
    #include "lllfsthread.h"
    #include "llworkerthread.h"
    #include "lltexturecache.h"
    #include "lltexturefetch.h"
    #include "llimageworker.h"
    
    #include "llevents.h"
    
    
    // The files below handle dependencies from cleanup.
    #include "llkeyframemotion.h"
    #include "llworldmap.h"
    #include "llhudmanager.h"
    #include "lltoolmgr.h"
    #include "llassetstorage.h"
    #include "llpolymesh.h"
    #include "llcachename.h"
    
    #include "llaudioengine.h"
    #include "llstreamingaudio.h"
    
    #include "llviewermenu.h"
    #include "llselectmgr.h"
    
    #include "lltracker.h"
    #include "llviewerparcelmgr.h"
    #include "llworldmapview.h"
    
    #include "llpostprocess.h"
    #include "llwlparammanager.h"
    #include "llwaterparammanager.h"
    
    
    #include "lldebugview.h"
    #include "llconsole.h"
    #include "llcontainerview.h"
    
    #include "llworld.h"
    #include "llhudeffecttrail.h"
    #include "llvectorperfoptions.h"
    
    #include "llslurl.h"
    
    
    // Included so that constants/settings might be initialized
    // in save_settings_to_globals()
    #include "llbutton.h"
    #include "llstatusbar.h"
    #include "llsurface.h"
    #include "llvosky.h"
    #include "llvotree.h"
    #include "llvoavatar.h"
    #include "llfolderview.h"
    #include "llagentpilot.h"
    
    #include "llvovolume.h"
    #include "llflexibleobject.h" 
    #include "llvosurfacepatch.h"
    
    #include "llviewerfloaterreg.h"
    #include "llcommandlineparser.h"
    #include "llfloatermemleak.h"
    
    #include "llfloatersnapshot.h"
    
    
    // includes for idle() idleShutdown()
    #include "llviewercontrol.h"
    #include "lleventnotifier.h"
    #include "llcallbacklist.h"
    #include "pipeline.h"
    #include "llgesturemgr.h"
    #include "llsky.h"
    #include "llvlmanager.h"
    #include "llviewercamera.h"
    #include "lldrawpoolbump.h"
    #include "llvieweraudio.h"
    #include "llimview.h"
    #include "llviewerthrottle.h"
    
    #include "llparcel.h"
    
    #include "llviewerassetstats.h"
    
    // Include for security api initialization
    #include "llsecapi.h"
    
    #include "llmachineid.h"
    
    #include "llmainlooprepeater.h"
    
    
    // *FIX: These extern globals should be cleaned up.
    // The globals either represent state/config/resource-storage of either 
    // this app, or another 'component' of the viewer. App globals should be 
    // moved into the app class, where as the other globals should be 
    // moved out of here.
    // If a global symbol reference seems valid, it will be included
    // via header files above.
    
    //----------------------------------------------------------------------------
    // llviewernetwork.h
    #include "llviewernetwork.h"
    
    // define a self-registering event API object
    #include "llappviewerlistener.h"
    
    #if (LL_LINUX || LL_SOLARIS) && LL_GTK
    #include "glib.h"
    #endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
    
    
    #if LL_MSVC
    // disable boost::lexical_cast warning
    #pragma warning (disable:4702)
    #endif
    
    static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
    
    Josh Bell's avatar
    Josh Bell committed
    
    ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
    //
    
    //----------------------------------------------------------------------------
    // viewer.cpp - these are only used in viewer, should be easily moved.
    
    #if LL_DARWIN
    extern void init_apple_menu(const char* product);
    #endif // LL_DARWIN
    
    extern BOOL gRandomizeFramerate;
    extern BOOL gPeriodicSlowFrame;
    
    extern BOOL gDebugGL;
    
    
    ////////////////////////////////////////////////////////////
    // All from the last globals push...
    const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard
    
    F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
    F32 gSimFrames;
    
    
    BOOL gShowObjectUpdates = FALSE;
    
    Josh Bell's avatar
    Josh Bell committed
    BOOL gUseQuickTime = TRUE;
    
    eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
    
    U32	gFrameCount = 0;
    U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
    
    LLPumpIO* gServicePump = NULL;
    
    
    U64 gFrameTime = 0;
    F32 gFrameTimeSeconds = 0.f;
    F32 gFrameIntervalSeconds = 0.f;
    
    F32 gFPSClamped = 10.f;						// Pretend we start at target rate.
    F32 gFrameDTClamped = 0.f;					// Time between adjacent checks to network for packets
    
    U64	gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
    
    U32 gFrameStalls = 0;
    
    const F64 FRAME_STALL_THRESHOLD = 1.0;
    
    
    LLTimer gRenderStartTime;
    LLFrameTimer gForegroundTime;
    
    LLFrameTimer gLoggedInTime;
    
    LLTimer gLogoutTimer;
    static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
    F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
    
    
    BOOL				gDisconnected = FALSE;
    
    // used to restore texture state after a mode switch
    LLFrameTimer	gRestoreGLTimer;
    BOOL			gRestoreGL = FALSE;
    BOOL				gUseWireframe = FALSE;
    
    // VFS globals - see llappviewer.h
    LLVFS* gStaticVFS = NULL;
    
    LLMemoryInfo gSysMemory;
    
    U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
    
    std::string gLastVersionChannel;
    
    
    LLVector3			gWindVec(3.0, 3.0, 0.0);
    LLVector3			gRelativeWindVec(0.0, 0.0, 0.0);
    
    U32		gPacketsIn = 0;
    
    BOOL				gPrintMessagesThisFrame = FALSE;
    
    BOOL gRandomizeFramerate = FALSE;
    BOOL gPeriodicSlowFrame = FALSE;
    
    
    BOOL gCrashOnStartup = FALSE;
    
    BOOL gLLErrorActivated = FALSE;
    
    BOOL gLogoutInProgress = FALSE;
    
    ////////////////////////////////////////////////////////////
    // Internal globals... that should be removed.
    
    static std::string gArgs;
    
    const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
    const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
    const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
    const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
    
    static std::string gLaunchFileOnQuit;
    
    // Used on Win32 for other apps to identify our window (eg, win_setup)
    const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
    
    //----------------------------------------------------------------------------
    
    // List of entries from strings.xml to always replace
    static std::set<std::string> default_trans_args;
    void init_default_trans_args()
    {
    	default_trans_args.insert("SECOND_LIFE"); // World
    
    	default_trans_args.insert("APP_NAME");
    
    	default_trans_args.insert("CAPITALIZED_APP_NAME");
    
    	default_trans_args.insert("SECOND_LIFE_GRID");
    
    	default_trans_args.insert("SUPPORT_SITE");
    
    //----------------------------------------------------------------------------
    // File scope definitons
    const char *VFS_DATA_FILE_BASE = "data.db2.x.";
    const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
    
    
    static std::string gWindowTitle;
    
    LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
    
    
    //----------------------------------------------------------------------------
    // Metrics logging control constants
    //----------------------------------------------------------------------------
    static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
    
    static const F32 METRICS_INTERVAL_QA = 30.0;
    static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
    
    static bool app_metrics_qa_mode = false;
    
    	if (gSavedSettings.getS32("AFKTimeout") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getS32("AFKTimeout")))
    
    	{
    		gAgent.setAFK();
    	}
    }
    
    // A callback set in LLAppViewer::init()
    static void ui_audio_callback(const LLUUID& uuid)
    {
    	if (gAudiop)
    	{
    
    		gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
    
    bool	create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
    {
    
    	if(!match || !base || base->getPlainText())
    
    		return false;
    
    	LLUUID match_id = match->getID();
    
    	LLIconCtrl* icon;
    
    	if(gAgent.isInGroup(match_id, TRUE))
    	{
    
    		LLGroupIconCtrl::Params icon_params;
    
    		icon_params.group_id = match_id;
    		icon_params.rect = LLRect(0, 16, 16, 0);
    		icon_params.visible = true;
    
    		icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
    
    		LLAvatarIconCtrl::Params icon_params;
    
    		icon_params.avatar_id = match_id;
    		icon_params.rect = LLRect(0, 16, 16, 0);
    		icon_params.visible = true;
    
    		icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
    
    	}
    
    	LLInlineViewSegment::Params params;
    	params.force_newline = false;
    	params.view = icon;
    	params.left_pad = 4;
    	params.right_pad = 4;
    
    	params.bottom_pad = 2;
    
    	base->appendWidget(params," ",false);
    	
    	return true;
    }
    
    
    void request_initial_instant_messages()
    {
    	static BOOL requested = FALSE;
    	if (!requested
    
    		&& gMessageSystem
    		&& LLMuteList::getInstance()->isLoaded()
    
    		&& isAgentAvatarValid())
    
    	{
    		// Auto-accepted inventory items may require the avatar object
    		// to build a correct name.  Likewise, inventory offers from
    		// muted avatars require the mute list to properly mute.
    		LLMessageSystem* msg = gMessageSystem;
    		msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
    		msg->nextBlockFast(_PREHASH_AgentData);
    		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
    		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
    		gAgent.sendReliableMessage();
    		requested = TRUE;
    	}
    }
    
    
    // A settings system callback for CrashSubmitBehavior
    bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue)
    {
    	S32 cb = newvalue.asInteger();
    	const S32 NEVER_SUBMIT_REPORT = 2;
    	if(cb == NEVER_SUBMIT_REPORT)
    	{
    		LLAppViewer::instance()->destroyMainloopTimeout();
    	}
    	return true;
    }
    
    
    // Use these strictly for things that are constructed at startup,
    // or for things that are performance critical.  JC
    
    static void settings_to_globals()
    
    {
    	LLBUTTON_H_PAD		= gSavedSettings.getS32("ButtonHPad");
    	BTN_HEIGHT_SMALL	= gSavedSettings.getS32("ButtonHeightSmall");
    	BTN_HEIGHT			= gSavedSettings.getS32("ButtonHeight");
    
    	MENU_BAR_HEIGHT		= gSavedSettings.getS32("MenuBarHeight");
    	MENU_BAR_WIDTH		= gSavedSettings.getS32("MenuBarWidth");
    
    	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
    	
    	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");
    	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor");
    	LLVOVolume::sDistanceFactor			= 1.f-LLVOVolume::sLODFactor * 0.1f;
    	LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
    	LLVOTree::sTreeFactor				= gSavedSettings.getF32("RenderTreeLODFactor");
    	LLVOAvatar::sLODFactor				= gSavedSettings.getF32("RenderAvatarLODFactor");
    
    	LLVOAvatar::sMaxVisible				= (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
    
    	LLVOAvatar::sVisibleInFirstPerson	= gSavedSettings.getBOOL("FirstPersonAvatarVisible");
    	// clamp auto-open time to some minimum usable value
    	LLFolderView::sAutoOpenTime			= llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
    	LLSelectMgr::sRectSelectInclusive	= gSavedSettings.getBOOL("RectangleSelectInclusive");
    	LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
    	LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
    
    	gAgentPilot.mNumRuns		= gSavedSettings.getS32("StatsNumRuns");
    	gAgentPilot.mQuitAfterRuns	= gSavedSettings.getBOOL("StatsQuitAfterRuns");
    
    	gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
    
    
    	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
    	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
    
    	LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
    
    
    	LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
    
    static void settings_modify()
    {
    
    	LLRenderTarget::sUseFBO				= gSavedSettings.getBOOL("RenderUseFBO");
    
    	LLVOAvatar::sUseImpostors			= gSavedSettings.getBOOL("RenderUseImpostors");
    
    	LLVOSurfacePatch::sLODFactor		= gSavedSettings.getF32("RenderTerrainLODFactor");
    
    	LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
    
    	gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
    
    	gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
    
    	gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
    
    #if LL_VECTORIZE
    	if (gSysCPU.hasAltivec())
    	{
    		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
    		gSavedSettings.setU32("VectorizeProcessor", 0 );
    	}
    	else
    	if (gSysCPU.hasSSE2())
    	{
    		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
    		gSavedSettings.setU32("VectorizeProcessor", 2 );
    	}
    	else
    	if (gSysCPU.hasSSE())
    	{
    		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
    		gSavedSettings.setU32("VectorizeProcessor", 1 );
    	}
    	else
    	{
    		// Don't bother testing or running if CPU doesn't support it. JC
    		gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
    		gSavedSettings.setBOOL("VectorizeEnable", FALSE );
    		gSavedSettings.setU32("VectorizeProcessor", 0 );
    		gSavedSettings.setBOOL("VectorizeSkin", FALSE);
    	}
    #else
    	// This build target doesn't support SSE, don't test/run.
    	gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
    	gSavedSettings.setBOOL("VectorizeEnable", FALSE );
    	gSavedSettings.setU32("VectorizeProcessor", 0 );
    	gSavedSettings.setBOOL("VectorizeSkin", FALSE);
    
    
    	// disable fullscreen mode, unsupported
    	gSavedSettings.setBOOL("WindowFullScreen", FALSE);
    
    class LLFastTimerLogThread : public LLThread
    {
    public:
    	std::string mFile;
    
    
    	LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
    
    		std::string file_name = test_name + std::string(".slp");
    		mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
    
    	}
    
    	void run()
    	{
    		std::ofstream os(mFile.c_str());
    		
    		while (!LLAppViewer::instance()->isQuitting())
    		{
    			LLFastTimer::writeLog(os);
    			os.flush();
    			ms_sleep(32);
    		}
    
    		os.close();
    	}
    
    //virtual
    bool LLAppViewer::initSLURLHandler()
    
    	// does nothing unless subclassed
    	return false;
    }
    
    //virtual
    bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
    {
    	// does nothing unless subclassed
    
    	return false;
    }
    
    //----------------------------------------------------------------------------
    // LLAppViewer definition
    
    // Static members.
    // The single viewer app.
    LLAppViewer* LLAppViewer::sInstance = NULL;
    
    
    const std::string LLAppViewer::sGlobalSettingsName = "Global"; 
    
    
    LLTextureCache* LLAppViewer::sTextureCache = NULL; 
    
    LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; 
    
    LLTextureFetch* LLAppViewer::sTextureFetch = NULL; 
    
    LLAppViewer::LLAppViewer() : 
    
    Adam Moss's avatar
    Adam Moss committed
    	mLogoutMarkerFile(NULL),
    
    	mReportedCrash(false),
    	mNumSessions(0),
    	mPurgeCache(false),
    
    	mPurgeOnExit(false),
    	mSecondInstance(false),
    
    	mForceGraphicsDetail(false),
    
    	mQuitRequested(false),
    	mLogoutRequestSent(false),
    
    	mAgentRegionLastAlive(false),
    	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
    
    	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
    
    	mFastTimerLogThread(NULL),
    	mUpdater(new LLUpdaterService())
    
    {
    	if(NULL != sInstance)
    	{
    		llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
    	}
    
    
    	setupErrorHandling();
    
    	gLoggedInTime.stop();
    
    	
    	LLLoginInstance::instance().setUpdaterService(mUpdater.get());
    
    	LLLoginInstance::instance().setUpdaterService(0);
    	
    
    	destroyMainloopTimeout();
    
    	// If we got to this destructor somehow, the app didn't hang.
    	removeMarkerFile();
    }
    
    bool LLAppViewer::init()
    {
    	//
    	// Start of the application
    	//
    	// IMPORTANT! Do NOT put anything that will write
    	// into the log files during normal startup until AFTER
    	// we run the "program crashed last time" error handler below.
    	//
    
    	// Need to do this initialization before we do anything else, since anything
    	// that touches files should really go through the lldir API
    	gDirUtilp->initAppDirs("SecondLife");
    
    	// set skin search path to default, will be overridden later
    	// this allows simple skinned file lookups to work
    
    	gDirUtilp->setSkinFolder("default");
    
    
    	initLogging();
    	
    	//
    	// OK to write stuff to logs now, we've now crash reported if necessary
    	//
    
    	
    	init_default_trans_args();
    	
    	if (!initConfiguration())
    
    		return false;
    
    	// write Google Breakpad minidump files to our log directory
    	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
    	logdir += gDirUtilp->getDirDelimiter();
    	setMiniDumpDir(logdir);
    
    
    	// Although initLogging() is the right place to mess with
    	// setFatalFunction(), we can't query gSavedSettings until after
    	// initConfiguration().
    	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
    	if (rc >= 0)
    	{
    		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
    		// rather than exit() because normal cleanup depends too much on
    		// successful startup!
    		LLError::setFatalFunction(boost::bind(_exit, rc));
    	}
    
    
        mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
    
    #if LL_RECORD_VIEWER_STATS
    	LLViewerStatsRecorder::initClass();
    #endif
    
    
        // *NOTE:Mani - LLCurl::initClass is not thread safe. 
        // Called before threads are created.
        LLCurl::initClass();
    
        LLMachineID::init();
    
    		static LLCachedControl<bool> metrics_submode(gSavedSettings,
    
    													 "Enables QA features (logging, faster cycling) for metrics collector");
    
    			app_metrics_interval = METRICS_INTERVAL_QA;
    		}
    
    		LLViewerAssetStatsFF::init();
    
    	// Initialize updater service (now that we have an io pump)
    	initUpdater();
    	if(isQuitting())
    	{
    		// Early out here because updater set the quitting flag.
    		return true;
    	}
    
    
    	//////////////////////////////////////////////////////////////////////////////
    	//////////////////////////////////////////////////////////////////////////////
    	//////////////////////////////////////////////////////////////////////////////
    	//////////////////////////////////////////////////////////////////////////////
    	// *FIX: The following code isn't grouped into functions yet.
    
    	// Statistics / debug timer initialization
    	init_statistics();
    	
    
    	// Various introspection concerning the libs we're using - particularly
            // the libs involved in getting to a full login screen.
    
    	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
    	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
    
    	// Get the single value from the crash settings file, if it exists
    	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
    
    	gCrashSettings.loadFromFile(crash_settings_filename);
    
    Palmer Truelson's avatar
    Palmer Truelson committed
    	if(gSavedSettings.getBOOL("IgnoreAllNotifications"))
    	{
    		gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
    		gCrashSettings.saveToFile(crash_settings_filename, FALSE);
    	}
    
    
    	/////////////////////////////////////////////////
    	// OS-specific login dialogs
    	/////////////////////////////////////////////////
    
    
    	//test_cached_control();
    
    
    	// track number of times that app has run
    	mNumSessions = gSavedSettings.getS32("NumSessions");
    	mNumSessions++;
    	gSavedSettings.setS32("NumSessions", mNumSessions);
    
    	if (gSavedSettings.getBOOL("VerboseLogs"))
    	{
    		LLError::setPrintLocation(true);
    	}
    	
    	// Widget construction depends on LLUI being initialized
    
    	LLUI::settings_map_t settings_map;
    	settings_map["config"] = &gSavedSettings;
    	settings_map["ignores"] = &gWarningSettings;
    	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
    	settings_map["account"] = &gSavedPerAccountSettings;
    
    	LLUI::initClass(settings_map,
    
    		LLUIImageList::getInstance(),
    		ui_audio_callback,
    		&LLUI::sGLScaleFactor);
    
    	
    	// Setup paths and LLTrans after LLUI::initClass has been called
    	LLUI::setupPaths();
    
    	LLTransUtil::parseStrings("strings.xml", default_trans_args);		
    	LLTransUtil::parseLanguageStrings("language_settings.xml");
    
    	
    	// LLKeyboard relies on LLUI to know what some accelerator keys are called.
    	LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
    
    	LLWeb::initClass();			  // do this after LLUI
    	
    
    	// Provide the text fields with callbacks for opening Urls
    	LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
    	LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
    	LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal);
    	LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
    
    
    	// Let code in llui access the viewer help floater
    	LLUI::sHelpImpl = LLViewerHelp::getInstance();
    
    
    	// Load translations for tooltips
    	LLFloater::initClass();
    
    	/////////////////////////////////////////////////
    	
    	LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
    	
    	LLViewerFloaterReg::registerFloaters();
    	
    
    	/////////////////////////////////////////////////
    	//
    	// Load settings files
    	//
    	//
    	LLGroupMgr::parseRoleActions("role_actions.xml");
    
    	LLAgent::parseTeleportMessages("teleport_strings.xml");
    
    
    	LLViewerJointMesh::updateVectorize();
    
    
    Josh Bell's avatar
    Josh Bell committed
    	// load MIME type -> media impl mappings
    
    	std::string mime_types_name;
    #if LL_DARWIN
    	mime_types_name = "mime_types_mac.xml";
    #elif LL_LINUX
    	mime_types_name = "mime_types_linux.xml";
    #else
    	mime_types_name = "mime_types.xml";
    #endif
    	LLMIMETypes::parseMIMETypes( mime_types_name ); 
    
    	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
    
    Steven Bennetts's avatar
    Steven Bennetts committed
    	settings_to_globals();
    
    	// Setup settings listeners
    	settings_setup_listeners();
    	// Modify settings based on system configuration and compile options
    	settings_modify();
    
    
    	// Find partition serial number (Windows) or hardware serial (Mac)
    	mSerialNumber = generateSerialNumber();
    
    
    	// do any necessary set-up for accepting incoming SLURLs from apps
    	initSLURLHandler();
    
    
    	if(false == initHardwareTest())
    	{
    		// Early out from user choice.
    		return false;
    	}
    
    	// Prepare for out-of-memory situations, during which we will crash on
    	// purpose and save a dump.
    #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
    	MemSetErrorHandler(first_mem_error_handler);
    #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
    
    
    	// *Note: this is where gViewerStats used to be created.
    
    
    	//
    	// Initialize the VFS, and gracefully handle initialization errors
    	//
    
    	if (!initCache())
    	{
    		std::ostringstream msg;
    
    		msg << LLTrans::getString("MBUnableToAccessFile");
    		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
    
    	// Initialize the repeater service.
    
    	gGLActive = TRUE;
    
    Kent Quirk's avatar
    Kent Quirk committed
    	// call all self-registered classes
    	LLInitClassList::instance().fireCallbacks();
    
    
    	LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
    		
    
    	gGLManager.printGLInfoString();
    
    	std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
    														gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
    														gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
    
    
    	if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
    
    		std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
    															gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
    															gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
    		if (!gViewerKeyboard.loadBindings(key_bindings_file))
    		{
    			LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
    		}
    
    	}
    
    	// If we don't have the right GL requirements, exit.
    
    	if (!gGLManager.mHasRequirements && !gNoRender)
    	{	
    
    Kent Quirk's avatar
    Kent Quirk committed
    		// can't use an alert here since we're exiting and
    
    Kent Quirk's avatar
    Kent Quirk committed
    			LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
    
    Kent Quirk's avatar
    Kent Quirk committed
    	// alert the user if they are using unsupported hardware
    	if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
    
    Kent Quirk's avatar
    Kent Quirk committed
    		bool unsupported = false;
    		LLSD args;
    		std::string minSpecs;
    
    Kent Quirk's avatar
    Kent Quirk committed
    		// get cpu data from xml
    		std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
    		S32 minCPU = 0;
    		minCPUString >> minCPU;
    
    		// get RAM data from XML
    		std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
    		U64 minRAM = 0;
    		minRAMString >> minRAM;
    		minRAM = minRAM * 1024 * 1024;
    
    		if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
    		{
    			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
    			minSpecs += "\n";
    			unsupported = true;
    		}
    
    Kent Quirk's avatar
    Kent Quirk committed
    		{
    			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
    			minSpecs += "\n";
    			unsupported = true;
    		}
    		if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
    
    Kent Quirk's avatar
    Kent Quirk committed
    			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
    			minSpecs += "\n";
    			unsupported = true;
    
    Kent Quirk's avatar
    Kent Quirk committed
    		if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
    		{
    
    			LLNotificationsUtil::add("UnknownGPU");
    
    Kent Quirk's avatar
    Kent Quirk committed
    		} 
    			
    		if(unsupported)
    		{
    			if(!gSavedSettings.controlExists("WarnUnsupportedHardware") 
    				|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
    			{
    				args["MINSPECS"] = minSpecs;
    
    				LLNotificationsUtil::add("UnsupportedHardware", args );
    
    	// save the graphics card
    	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
    
    
    	// Save the current version to the prefs file
    
    							 LLVersionInfo::getChannelAndVersion());
    
    
    	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
    	gSimFrames = (F32)gFrameCount;
    
    
    	LLViewerJoystick::getInstance()->init(false);
    
    
    	try {
    		initializeSecHandler();
    	}
    	catch (LLProtectedDataException ex)
    	{
    	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
    	}
    	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
    
    
    
    	gGLActive = FALSE;
    
    	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
    	{
    		loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
    	}
    	
    
    	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
    
    	//EXT-7013 - On windows for some locale (Japanese) standard 
    	//datetime formatting functions didn't support some parameters such as "weekday".
    
    	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
    
    	std::string language = LLControlGroup::getInstance(sGlobalSettingsName)->getString("Language");
    
    	if(language == "ja" || language == "pl")
    
    	{
    		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
    		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
    		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
    		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
    		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
    
    		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
    		LLStringOps::sPM = LLTrans::getString("dateTimePM");
    	}