Newer
Older
Steven Bennetts
committed
/**
* @file llappviewer.cpp
* @brief The LLAppViewer class definitions
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llappviewer.h"
Kelly Washington
committed
#include "llprimitive.h"
Steven Bennetts
committed
#include "llversionviewer.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
Steven Bennetts
committed
#include "llalertdialog.h"
#include "llerrorcontrol.h"
#include "llviewerimagelist.h"
#include "llgroupmgr.h"
#include "llagent.h"
#include "llwindow.h"
#include "llviewerstats.h"
#include "llmd5.h"
#include "llpumpio.h"
#include "llimpanel.h"
Steven Bennetts
committed
#include "llstartup.h"
#include "llfocusmgr.h"
#include "llviewerjoystick.h"
Steven Bennetts
committed
#include "llcurl.h"
#include "llfloatersnapshot.h"
#include "llviewerwindow.h"
#include "llviewerdisplay.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llworldmap.h"
#include "llmutelist.h"
#include "llurldispatcher.h"
#include "llfirstuse.h"
#include "llrender.h"
Steven Bennetts
committed
#include "llweb.h"
#include "llsecondlifeurls.h"
#include <boost/bind.hpp>
Steven Bennetts
committed
#if LL_WINDOWS
#include "llwindebug.h"
#endif
#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in initMarkerFile
#else
# include <sys/file.h> // For initMarkerFile support
#endif
#include "llnotify.h"
#include "llviewerkeyboard.h"
#include "lllfsthread.h"
#include "llworkerthread.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
#include "llimageworker.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 "audioengine.h"
#include "llviewermenu.h"
#include "llselectmgr.h"
James Cook
committed
#include "lltrans.h"
Steven Bennetts
committed
#include "lltracker.h"
#include "llviewerparcelmgr.h"
#include "llworldmapview.h"
#include "llpostprocess.h"
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
Steven Bennetts
committed
#include "lldebugview.h"
#include "llconsole.h"
#include "llcontainerview.h"
Josh Bell
committed
#include "llfloaterstats.h"
Steven Bennetts
committed
#include "llhoverview.h"
#include "llfloatermemleak.h"
Steven Bennetts
committed
Kyle Machulis
committed
#include "llsdserialize.h"
Steven Bennetts
committed
#include "llworld.h"
#include "llhudeffecttrail.h"
#include "llvectorperfoptions.h"
#include "llurlsimstring.h"
#include "llwatchdog.h"
Steven Bennetts
committed
// Included so that constants/settings might be initialized
// in save_settings_to_globals()
#include "llbutton.h"
#include "llcombobox.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "llvosky.h"
#include "llvotree.h"
#include "llvoavatar.h"
#include "llfolderview.h"
#include "lltoolbar.h"
#include "llframestats.h"
#include "llagentpilot.h"
#include "llsrv.h"
#include "llvovolume.h"
#include "llflexibleobject.h"
#include "llvosurfacepatch.h"
Steven Bennetts
committed
// 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"
Steven Bennetts
committed
//
#include "llinventoryview.h"
#include "llcommandlineparser.h"
Steven Bennetts
committed
// annoying detail to determine whether font prefs are over-ridden
#if LL_LINUX
# define LL_DYNAMIC_FONT_DISCOVERY 1
#else
# define LL_DYNAMIC_FONT_DISCOVERY 0
#endif
Steven Bennetts
committed
// *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"
////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
//
#if LL_WINDOWS && LL_LCD_COMPILE
#include "lllcd.h"
#endif
Steven Bennetts
committed
//----------------------------------------------------------------------------
// viewer.cpp - these are only used in viewer, should be easily moved.
extern void disable_win_error_reporting();
#if LL_DARWIN
#include <Carbon/Carbon.h>
extern void init_apple_menu(const char* product);
extern OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
extern OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
extern OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata);
extern OSStatus DisplayReleaseNotes(void);
#include <boost/tokenizer.hpp>
#endif // LL_DARWIN
extern BOOL gRandomizeFramerate;
extern BOOL gPeriodicSlowFrame;
Steven Bennetts
committed
////////////////////////////////////////////////////////////
// All from the last globals push...
BOOL gHandleKeysAsync = FALSE;
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;
std::string gDisabledMessage; // Set in LLAppViewer::initConfiguration used in idle_startup
Steven Bennetts
committed
BOOL gHideLinks = FALSE; // Set in LLAppViewer::initConfiguration, used externally
BOOL gAllowIdleAFK = TRUE;
Steven Bennetts
committed
BOOL gShowObjectUpdates = FALSE;
Steven Bennetts
committed
BOOL gAcceptTOS = FALSE;
BOOL gAcceptCriticalMessage = FALSE;
eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
Steven Bennetts
committed
Kyle Machulis
committed
LLSD gDebugInfo;
Steven Bennetts
committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
U32 gFrameCount = 0;
U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
LLPumpIO* gServicePump = NULL;
BOOL gPacificDaylightTime = FALSE;
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
LLTimer gRenderStartTime;
LLFrameTimer gForegroundTime;
LLTimer gLogoutTimer;
static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg.
F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
LLUUID gInventoryLibraryOwner;
LLUUID gInventoryLibraryRoot;
BOOL gDisconnected = FALSE;
// Map scale in pixels per region
F32 gMapScale = 128.f;
F32 gMiniMapScale = 128.f;
// 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
Steven Bennetts
committed
std::string gLastVersionChannel;
Steven Bennetts
committed
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;
Steven Bennetts
committed
////////////////////////////////////////////////////////////
// Internal globals... that should be removed.
static std::string gArgs;
Steven Bennetts
committed
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");
Steven Bennetts
committed
static BOOL gDoDisconnect = FALSE;
static std::string gLaunchFileOnQuit;
Steven Bennetts
committed
//----------------------------------------------------------------------------
// File scope definitons
const char *VFS_DATA_FILE_BASE = "data.db2.x.";
const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
static std::string gSecondLife;
static std::string gWindowTitle;
Steven Bennetts
committed
#ifdef LL_WINDOWS
static char sWindowClass[] = "Second Life";
#endif
Steven Bennetts
committed
std::vector<std::string> gLoginURIs;
static std::string gHelperURI;
void idle_afk_check()
{
// check idle timers
if (gAllowIdleAFK && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getF32("AFKTimeout")))
Steven Bennetts
committed
{
gAgent.setAFK();
}
}
// A callback set in LLAppViewer::init()
static void ui_audio_callback(const LLUUID& uuid)
{
if (gAudiop)
{
F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
Steven Bennetts
committed
gAudiop->triggerSound(uuid, gAgent.getID(), volume);
}
}
void request_initial_instant_messages()
{
static BOOL requested = FALSE;
if (!requested
&& gMessageSystem
&& LLMuteList::getInstance()->isLoaded()
Steven Bennetts
committed
&& gAgent.getAvatarObject())
{
// 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)
{
// LLWatchdog::getInstance()->cleanup(); // SJB: cleaning up a running watchdog thread is unsafe
LLAppViewer::instance()->destroyMainloopTimeout();
}
else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE)
{
// Don't re-enable the watchdog when we change the setting; this may get called before it's started
// LLWatchdog::getInstance()->init();
}
return true;
}
Steven Bennetts
committed
// Use these strictly for things that are constructed at startup,
// or for things that are performance critical. JC
static void settings_to_globals()
Steven Bennetts
committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
{
LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
LLBUTTON_V_PAD = gSavedSettings.getS32("ButtonVPad");
BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
STATUS_BAR_HEIGHT = gSavedSettings.getS32("StatusBarHeight");
LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2;
LLCOMBOBOX_WIDTH = 128;
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 = 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"));
LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay");
LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
gFrameStats.setTrackStats(gSavedSettings.getBOOL("StatsSessionTrackFrameStats"));
gAgentPilot.mNumRuns = gSavedSettings.getS32("StatsNumRuns");
gAgentPilot.mQuitAfterRuns = gSavedSettings.getBOOL("StatsQuitAfterRuns");
gAgent.mHideGroupTitle = gSavedSettings.getBOOL("RenderHideGroupTitle");
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
gAllowIdleAFK = gSavedSettings.getBOOL("AllowIdleAFK");
gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
Steven Bennetts
committed
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
gMapScale = gSavedSettings.getF32("MapScale");
gMiniMapScale = gSavedSettings.getF32("MiniMapScale");
gHandleKeysAsync = gSavedSettings.getBOOL("AsyncKeyboard");
LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
Steven Bennetts
committed
static void settings_modify()
{
LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderUseFBO");
LLVOAvatar::sUseImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //sqaure lod factor to get exponential range of [1,4]
gDebugGL = gSavedSettings.getBOOL("RenderDebugGL");
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
Steven Bennetts
committed
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
#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);
#endif
// propagate push to talk preference to current status
gSavedSettings.setBOOL("PTTCurrentlyEnabled", TRUE); //gSavedSettings.getBOOL("EnablePushToTalk"));
Steven Bennetts
committed
}
void LLAppViewer::initGridChoice()
Steven Bennetts
committed
{
// Load up the initial grid choice from:
// - hard coded defaults...
// - command line settings...
// - if dev build, persisted settings...
// Set the "grid choice", this is specified by command line.
std::string grid_choice = gSavedSettings.getString("CmdLineGridChoice");
LLViewerLogin::getInstance()->setGridChoice(grid_choice);
// Load last server choice by default
// ignored if the command line grid choice has been set
if(grid_choice.empty())
{
S32 server = gSavedSettings.getS32("ServerChoice");
server = llclamp(server, 0, (S32)GRID_INFO_COUNT - 1);
if(server == GRID_INFO_OTHER)
std::string custom_server = gSavedSettings.getString("CustomServer");
LLViewerLogin::getInstance()->setGridChoice(custom_server);
}
{
LLViewerLogin::getInstance()->setGridChoice((EGridInfo)server);
Steven Bennetts
committed
}
}
bool send_url_to_other_instance(const std::string& url)
{
#if LL_WINDOWS
wchar_t window_class[256]; /* Flawfinder: ignore */ // Assume max length < 255 chars.
mbstowcs(window_class, sWindowClass, 255);
window_class[255] = 0;
// Use the class instead of the window name.
HWND other_window = FindWindow(window_class, NULL);
Steven Bennetts
committed
if (other_window != NULL)
{
lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
COPYDATASTRUCT cds;
const S32 SLURL_MESSAGE_TYPE = 0;
cds.dwData = SLURL_MESSAGE_TYPE;
cds.cbData = url.length() + 1;
cds.lpData = (void*)url.c_str();
LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds);
lldebugs << "SendMessage(WM_COPYDATA) to other window '"
<< gWindowTitle << "' returned " << msg_result << llendl;
return true;
}
#endif
return false;
}
//----------------------------------------------------------------------------
// LLAppViewer definition
// Static members.
// The single viewer app.
LLAppViewer* LLAppViewer::sInstance = NULL;
const std::string LLAppViewer::sGlobalSettingsName = "Global";
const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount";
const std::string LLAppViewer::sCrashSettingsName = "CrashSettings";
Steven Bennetts
committed
LLTextureCache* LLAppViewer::sTextureCache = NULL;
LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL;
LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
LLAppViewer::LLAppViewer() :
mMarkerFile(NULL),
mReportedCrash(false),
mNumSessions(0),
mPurgeCache(false),
mPurgeOnExit(false),
mSecondInstance(false),
Steven Bennetts
committed
mSavedFinalSnapshot(false),
mQuitRequested(false),
mLogoutRequestSent(false),
mMainloopTimeout(NULL),
mAgentRegionLastAlive(false)
Steven Bennetts
committed
{
if(NULL != sInstance)
{
llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
}
sInstance = this;
}
LLAppViewer::~LLAppViewer()
{
destroyMainloopTimeout();
Steven Bennetts
committed
// 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");
Steven Bennetts
committed
initLogging();
//
// OK to write stuff to logs now, we've now crash reported if necessary
//
if (!initConfiguration())
return false;
// *NOTE:Mani - LLCurl::initClass is not thread safe.
// Called before threads are created.
LLCurl::initClass();
initThreads();
writeSystemInfo();
// Build a string representing the current version number.
gCurrentVersion = llformat("%s %d.%d.%d.%d",
gSavedSettings.getString("VersionChannelName").c_str(),
LL_VERSION_MAJOR,
LL_VERSION_MINOR,
LL_VERSION_PATCH,
LL_VERSION_BUILD );
Steven Bennetts
committed
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// *FIX: The following code isn't grouped into functions yet.
// 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;
Steven Bennetts
committed
// 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);
Steven Bennetts
committed
/////////////////////////////////////////////////
// OS-specific login dialogs
/////////////////////////////////////////////////
#if LL_WINDOWS
/*
// Display initial login screen, comes up quickly. JC
{
LLSplashScreen::hide();
INT_PTR result = DialogBox(hInstance, L"CONNECTBOX", NULL, login_dialog_func);
if (result < 0)
{
llwarns << "Connect dialog box failed, returned " << result << llendl;
return 1;
}
// success, result contains which button user clicked
llinfos << "Connect dialog box clicked " << result << llendl;
LLSplashScreen::show();
}
*/
#endif
//test_cached_control();
Steven Bennetts
committed
// track number of times that app has run
mNumSessions = gSavedSettings.getS32("NumSessions");
mNumSessions++;
gSavedSettings.setS32("NumSessions", mNumSessions);
gSavedSettings.setString("HelpLastVisitedURL",gSavedSettings.getString("HelpHomeURL"));
if (gSavedSettings.getBOOL("VerboseLogs"))
{
LLError::setPrintLocation(true);
}
// Load art UUID information, don't require these strings to be declared in code.
std::string colors_base_filename = gDirUtilp->findSkinnedFilename("colors_base.xml");
LL_DEBUGS("InitInfo") << "Loading base colors from " << colors_base_filename << LL_ENDL;
gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U);
Steven Bennetts
committed
// Load overrides from user colors file
std::string user_colors_filename = gDirUtilp->findSkinnedFilename("colors.xml");
LL_DEBUGS("InitInfo") << "Loading user colors from " << user_colors_filename << LL_ENDL;
if (gColors.loadFromFileLegacy(user_colors_filename, FALSE, TYPE_COL4U) == 0)
Steven Bennetts
committed
{
LL_DEBUGS("InitInfo") << "Cannot load user colors from " << user_colors_filename << LL_ENDL;
Steven Bennetts
committed
}
// Widget construction depends on LLUI being initialized
LLUI::initClass(&gSavedSettings,
&gColors,
LLUIImageList::getInstance(),
Steven Bennetts
committed
ui_audio_callback,
&LLUI::sGLScaleFactor);
LLWeb::initClass(); // do this after LLUI
LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set
Steven Bennetts
committed
/////////////////////////////////////////////////
//
// Load settings files
//
//
LLGroupMgr::parseRoleActions("role_actions.xml");
LLAgent::parseTeleportMessages("teleport_strings.xml");
LLViewerJointMesh::updateVectorize();
LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") );
Steven Bennetts
committed
// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
// Setup settings listeners
settings_setup_listeners();
// Modify settings based on system configuration and compile options
settings_modify();
Steven Bennetts
committed
// Find partition serial number (Windows) or hardware serial (Mac)
mSerialNumber = generateSerialNumber();
if(false == initHardwareTest())
{
// Early out from user choice.
return false;
}
// Always fetch the Ethernet MAC address, needed both for login
// and password load.
LLUUID::getNodeID(gMACAddress);
// 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.
Steven Bennetts
committed
//
// Initialize the VFS, and gracefully handle initialization errors
//
if (!initCache())
{
std::ostringstream msg;
msg <<
gSecondLife << " is unable to access a file that it needs.\n"
"\n"
"This can be because you somehow have multiple copies running, "
"or your system incorrectly thinks a file is open. "
"If this message persists, restart your computer and try again. "
"If it continues to persist, you may need to completely uninstall " <<
gSecondLife << " and reinstall it.";
OSMessageBox(
msg.str(),
LLStringUtil::null,
Steven Bennetts
committed
OSMB_OK);
return 1;
}
//
// Initialize the window
//
initWindow();
Bryan O'Sullivan
committed
#if LL_LCD_COMPILE
Steven Bennetts
committed
// start up an LCD window on a logitech keyboard, if there is one
HINSTANCE hInstance = GetModuleHandle(NULL);
Josh Bell
committed
gLcdScreen = new LLLCD(hInstance);
Steven Bennetts
committed
CreateLCDDebugWindows();
Bryan O'Sullivan
committed
#endif
Steven Bennetts
committed
Kyle Machulis
committed
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
Steven Bennetts
committed
//load key settings
bind_keyboard_functions();
// Load Default bindings
if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keys.ini")))
Steven Bennetts
committed
{
LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
Steven Bennetts
committed
}
// Load Custom bindings (override defaults)
gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini"));
Steven Bennetts
committed
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements && !gNoRender)
{
// can't use an alert here since we're existing and
// all hell breaks lose.
Steven Bennetts
committed
OSMessageBox(
LLAlertDialog::getTemplateMessage("UnsupportedGLRequirements"),
LLStringUtil::null,
Steven Bennetts
committed
OSMB_OK);
return 0;
}
LLStringUtil::format_map_t args;
std::string minSpecs;
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
// get cpu data from xml
std::stringstream minCPUString(LLAlertDialog::getTemplateMessage("UnsupportedCPUAmount"));
S32 minCPU = 0;
minCPUString >> minCPU;
// get RAM data from XML
std::stringstream minRAMString(LLAlertDialog::getTemplateMessage("UnsupportedRAMAmount"));
U64 minRAM = 0;
minRAMString >> minRAM;
minRAM = minRAM * 1024 * 1024;
if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
{
minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedGPU");
minSpecs += "\n";
unsupported = true;
}
if(gSysCPU.getMhz() < minCPU)
{
minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedCPU");
minSpecs += "\n";
unsupported = true;
}
if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
{
minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedRAM");
minSpecs += "\n";
unsupported = true;
}
if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
{
gViewerWindow->alertXml("UnknownGPU");
}
if(unsupported)
{
if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
{
args["MINSPECS"] = minSpecs;
gViewerWindow->alertXml("UnsupportedHardware", args );
}
}
Steven Bennetts
committed
// Save the current version to the prefs file
gSavedSettings.setString("LastRunVersion", gCurrentVersion);
gSimLastTime = gRenderStartTime.getElapsedTimeF32();
gSimFrames = (F32)gFrameCount;
LLViewerJoystick::getInstance()->init(false);
Steven Bennetts
committed
return true;
}
bool LLAppViewer::mainLoop()
{
mMainloopTimeout = new LLWatchdogTimeout();
// *FIX:Mani - Make this a setting, once new settings exist in this branch.
Steven Bennetts
committed
//-------------------------------------------
// Run main loop until time to quit
//-------------------------------------------
// Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp);
LLHTTPClient::setPump(*gServicePump);
Steven Bennetts
committed
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
Steven Bennetts
committed
LLVoiceChannel::initClass();
LLVoiceClient::init(gServicePump);
LLMemType mt1(LLMemType::MTYPE_MAIN);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
Steven Bennetts
committed
// Handle messages
while (!LLApp::isExiting())
{
LLFastTimer::reset(); // Should be outside of any timer instances
Steven Bennetts
committed
{
LLFastTimer t(LLFastTimer::FTM_FRAME);
pingMainloopTimeout("Main:GatherInput");
Steven Bennetts
committed
{
LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
#if LL_WINDOWS
if (!LLWinDebug::checkExceptionHandler())
Steven Bennetts
committed
{
llwarns << " Someone took over my exception handler (post messagehandling)!" << llendl;
}
#endif
gViewerWindow->mWindow->gatherInput();
}
Steven Bennetts
committed
// once per second debug info
if (debugTime.getElapsedTimeF32() > 1.f)
{
debugTime.reset();
}
Steven Bennetts
committed
#endif
//memory leaking simulation
if(LLFloaterMemLeak::getInstance())
{
LLFloaterMemLeak::getInstance()->idle() ;
}
Steven Bennetts
committed
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:JoystickKeyboard");
Steven Bennetts
committed
// Scan keyboard for movement keys. Command keys and typing
// are handled by windows callbacks. Don't do this until we're
// done initializing. JC
if (gViewerWindow->mWindow->getVisible()
&& gViewerWindow->getActive()
&& !gViewerWindow->mWindow->getMinimized()
&& LLStartUp::getStartupState() == STATE_STARTED
&& !gViewerWindow->getShowProgress()
&& !gFocusMgr.focusLocked())
{
Steven Bennetts
committed
gKeyboard->scanKeyboard();
}
pingMainloopTimeout("Main:Messages");
Steven Bennetts
committed
// Update state based on messages, user input, object idle.
{
LLFastTimer t3(LLFastTimer::FTM_IDLE);
idle();
{
LLFastTimer t4(LLFastTimer::FTM_PUMP);
gAres->process();
// this pump is necessary to make the login screen show up
gServicePump->pump();
gServicePump->callback();
}
Steven Bennetts
committed
}
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
pauseMainloopTimeout();
Steven Bennetts
committed
saveFinalSnapshot();
disconnectViewer();
resumeMainloopTimeout();
Steven Bennetts
committed
}
// Render scene.
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:Display");
Steven Bennetts
committed
display();
pingMainloopTimeout("Main:Snapshot");
Steven Bennetts
committed
LLFloaterSnapshot::update(); // take snapshots
Bryan O'Sullivan
committed
#if LL_LCD_COMPILE
Steven Bennetts
committed
// update LCD Screen
pingMainloopTimeout("Main:LCD");
Steven Bennetts
committed
gLcdScreen->UpdateDisplay();
#endif
}
}
pingMainloopTimeout("Main:Sleep");
pauseMainloopTimeout();
Steven Bennetts
committed
// Sleep and run background threads
{
LLFastTimer t2(LLFastTimer::FTM_SLEEP);
bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads");
// yield some time to the os based on command line option
Steven Bennetts
committed
{
ms_sleep(mYieldTime);
Steven Bennetts
committed
}
// yield cooperatively when not running as foreground window
if ( gNoRender
|| !gViewerWindow->mWindow->getVisible()
|| !gFocusMgr.getAppHasFocus())
{
// Sleep if we're not rendering, or the window is minimized.
S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
// of equal priority on Windows