Newer
Older
Steven Bennetts
committed
initWindow();
Xiaohong Bao
committed
LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
Steven Bennetts
committed
// initWindow also initializes the Feature List, so now we can initialize this global.
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
// call all self-registered classes
LLInitClassList::instance().fireCallbacks();
LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
Kyle Machulis
committed
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
Steven Bennetts
committed
// Load Default bindings
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))
Steven Bennetts
committed
{
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;
}
Steven Bennetts
committed
}
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements)
// can't use an alert here since we're exiting and
// all hell breaks lose.
LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedGLRequirements");
Steven Bennetts
committed
OSMessageBox(
LLStringUtil::null,
Steven Bennetts
committed
OSMB_OK);
return 0;
}
// If we don't have the right shader requirements.
if (!gGLManager.mHasShaderObjects
|| !gGLManager.mHasVertexShader
|| !gGLManager.mHasFragmentShader)
{
LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedShaderRequirements");
OSMessageBox(
details.getString(),
LLStringUtil::null,
OSMB_OK);
return 0;
}
Brad Payne (Vir Linden)
committed
// Without SSE2 support we will crash almost immediately, warn here.
if (!gSysCPU.hasSSE2())
Brad Payne (Vir Linden)
committed
// can't use an alert here since we're exiting and
// all hell breaks lose.
OSMessageBox(
LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
LLStringUtil::null,
OSMB_OK);
return 0;
}
// alert the user if they are using unsupported hardware
if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
bool unsupported = false;
LLSD args;
std::string minSpecs;
// 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"));
U64Bytes minRAM;
minRAMString >> minRAM;
if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
{
minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
minSpecs += "\n";
unsupported = true;
}
Tofu Linden
committed
if(gSysCPU.getMHz() < minCPU)
{
minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
minSpecs += "\n";
unsupported = true;
}
if(gSysMemory.getPhysicalMemoryKB() < minRAM)
{
minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
minSpecs += "\n";
unsupported = true;
}
if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
{
LLNotificationsUtil::add("UnknownGPU");
if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
{
args["MINSPECS"] = minSpecs;
LLNotificationsUtil::add("UnsupportedHardware", args );
}
#if LL_WINDOWS
David Parks
committed
if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
{
andreykproductengine
committed
std::string url;
David Parks
committed
if (gGLManager.mIsIntel)
{
andreykproductengine
committed
url = LLTrans::getString("IntelDriverPage");
David Parks
committed
}
else if (gGLManager.mIsNVIDIA)
{
url = LLTrans::getString("NvidiaDriverPage");
David Parks
committed
}
else if (gGLManager.mIsATI)
{
andreykproductengine
committed
url = LLTrans::getString("AMDDriverPage");
}
if (!url.empty())
{
LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url));
David Parks
committed
}
}
#endif
// save the graphics card
gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
Steven Bennetts
committed
// Save the current version to the prefs file
gSavedSettings.setString("LastRunVersion",
LLVersionInfo::instance().getChannelAndVersion());
Steven Bennetts
committed
gSimLastTime = gRenderStartTime.getElapsedTimeF32();
gSimFrames = (F32)gFrameCount;
if (gSavedSettings.getBOOL("JoystickEnabled"))
{
LLViewerJoystick::getInstance()->init(false);
}
try {
initializeSecHandler();
}
{
LLNotificationsUtil::add("CorruptedProtectedDataStore");
}
if (!gSavedSettings.getBOOL("CmdLineSkipUpdater"))
{
LLProcess::Params updater;
updater.desc = "updater process";
// Because it's the updater, it MUST persist beyond the lifespan of the
// viewer itself.
updater.autokill = false;
#if LL_WINDOWS
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker.exe");
// explicitly run the system Python interpreter on SLVersionChecker.py
updater.executable = "python";
updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "SLVersionChecker.py"));
updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker");
// add LEAP mode command-line argument to whichever of these we selected
updater.args.add("leap");
// UpdaterServiceSettings
updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// channel
updater.args.add(LLVersionInfo::instance().getChannel());
// testok
updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// ForceAddressSize
updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
// Run the updater. An exception from launching the updater should bother us.
LLLeap::create(updater, true);
}
else
LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
// Iterate over --leap command-line options. But this is a bit tricky: if
// there's only one, it won't be an array at all.
LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand"));
LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL;
if (LeapCommand.isDefined() && ! LeapCommand.isArray())
// If LeapCommand is actually a scalar value, make an array of it.
// Have to do it in two steps because LeapCommand.append(LeapCommand)
// trashes content! :-P
LLSD item(LeapCommand);
LeapCommand.append(item);
}
for (const LLSD& leap : llsd::inArray(LeapCommand))
{
LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL;
// We don't have any better description of this plugin than the
// user-specified command line. Passing "" causes LLLeap to derive a
// description from the command line itself.
// Suppress LLLeap::Error exception: trust LLLeap's own logging. We
// don't consider any one --leap command mission-critical, so if one
// fails, log it, shrug and carry on.
LLLeap::create("", leap.asString(), false); // exception=false
}
if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
{
LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: "
<< "lleventhost no longer supported as a dynamic library"
<< LL_ENDL;
Yuri Chebotarev
committed
LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
Yuri Chebotarev
committed
//EXT-7013 - On windows for some locale (Japanese) standard
Yuri Chebotarev
committed
//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).
Aaron Stone
committed
std::string language = gSavedSettings.getString("Language");
if(language == "ja" || language == "pl")
Yuri Chebotarev
committed
{
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");
}
Yuri Chebotarev
committed
Vadim Savchuk
committed
LLAgentLanguage::init();
/// Tell the Coprocedure manager how to discover and store the pool sizes
// what I wanted
LLCoprocedureManager::getInstance()->setPropertyMethods(
boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
andreykproductengine
committed
// TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement
// some other protection to make sure we don't use network before initializng proxy
/*----------------------------------------------------------------------*/
// nat 2016-06-29 moved the following here from the former mainLoop().
mMainloopTimeout = new LLWatchdogTimeout();
// Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp);
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
LLVoiceChannel::initClass();
LLVoiceClient::initParamSingleton(gServicePump);
LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
joystick = LLViewerJoystick::getInstance();
joystick->setNeedsReset(true);
Steven Bennetts
committed
return true;
}
Don Kjer
committed
void LLAppViewer::initMaxHeapSize()
{
//set the max heap size.
//here is some info regarding to the max heap size:
//------------------------------------------------------------------------------------------
// OS | setting | SL address bits | max manageable memory space | max heap size
// Win 32 | default | 32-bit | 2GB | < 1.7GB
// Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
//Linux 32 | default | 32-bit | 3GB | < 2.7GB
//Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
//64-bit OS |default | 32-bit | 4GB | < 3.7GB
//64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
//------------------------------------------------------------------------------------------
//currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
//F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ;
LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
}
Don Kjer
committed
void LLAppViewer::checkMemory()
{
const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
//const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
//static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
if(!gGLManager.mDebugGPU)
if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
return ;
mMemCheckTimer.reset() ;
//update the availability of memory
LLMemory::updateMemoryInfo() ;
bool is_low = LLMemory::isMemoryPoolLow() ;
LLPipeline::throttleNewMemoryAllocation(is_low) ;
if(is_low)
{
LLMemory::logMemoryInfo() ;
}
Steven Bennetts
committed
}
static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
static LLTrace::BlockTimerStatHandle FTM_SLEEP("Sleep");
static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield");
static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch");
static LLTrace::BlockTimerStatHandle FTM_VFS("VFS Thread");
static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump");
static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service");
static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback");
static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot");
static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
// externally visible timers
LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
bool LLAppViewer::frame()
AndreyL ProductEngine
committed
{
bool ret = false;
if (gSimulateMemLeak)
{
try
{
ret = doFrame();
}
catch (const LLContinueError&)
{
LOG_UNHANDLED_EXCEPTION("");
}
AndreyL ProductEngine
committed
{
LLMemory::logMemoryInfo(TRUE);
LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
if (mem_leak_instance)
{
mem_leak_instance->stop();
}
LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL;
}
}
else
{
try
{
ret = doFrame();
}
catch (const LLContinueError&)
{
LOG_UNHANDLED_EXCEPTION("");
}
AndreyL ProductEngine
committed
}
return ret;
}
bool LLAppViewer::doFrame()
Steven Bennetts
committed
{
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
LLTrace::BlockTimer::processTimes();
LLTrace::get_frame_recording().nextPeriod();
LLTrace::BlockTimer::logStats();
LLTrace::get_thread_recorder()->pullFromChildren();
//clear call stack records
LL_CLEAR_CALLSTACKS();
//check memory availability information
checkMemory() ;
Steven Bennetts
committed
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
if (gViewerWindow)
Steven Bennetts
committed
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
gViewerWindow->getWindow()->processMiscNativeEvents();
}
pingMainloopTimeout("Main:GatherInput");
if (gViewerWindow)
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
if (!restoreErrorTrap())
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
Steven Bennetts
committed
gViewerWindow->getWindow()->gatherInput();
}
Steven Bennetts
committed
//memory leaking simulation
AndreyL ProductEngine
committed
if (gSimulateMemLeak)
Steven Bennetts
committed
{
AndreyL ProductEngine
committed
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
if (mem_leak_instance)
{
mem_leak_instance->idle();
}
}
// canonical per-frame event
mainloop.post(newFrame);
// give listeners a chance to run
llcoro::suspend();
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:JoystickKeyboard");
// Scan keyboard for movement keys. Command keys and typing
// are handled by windows callbacks. Don't do this until we're
// done initializing. JC
andreykproductengine
committed
if (gViewerWindow
&& (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
&& gViewerWindow->getActive()
&& !gViewerWindow->getWindow()->getMinimized()
&& LLStartUp::getStartupState() == STATE_STARTED
&& (gHeadlessClient || !gViewerWindow->getShowProgress())
&& !gFocusMgr.focusLocked())
joystick->scanJoystick();
gKeyboard->scanKeyboard();
// Update state based on messages, user input, object idle.
Steven Bennetts
committed
{
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
idle();
Steven Bennetts
committed
resumeMainloopTimeout();
Steven Bennetts
committed
}
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
Steven Bennetts
committed
{
pauseMainloopTimeout();
saveFinalSnapshot();
disconnectViewer();
resumeMainloopTimeout();
Steven Bennetts
committed
}
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
Steven Bennetts
committed
{
pingMainloopTimeout("Main:Display");
gGLActive = TRUE;
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
LLFloaterOutfitSnapshot::update();
gGLActive = FALSE;
Steven Bennetts
committed
}
Steven Bennetts
committed
pingMainloopTimeout("Main:Sleep");
pauseMainloopTimeout();
Steven Bennetts
committed
// Sleep and run background threads
{
// yield some time to the os based on command line option
static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
if(yield_time >= 0)
{
LL_RECORD_BLOCK_TIME(FTM_YIELD);
ms_sleep(yield_time);
// yield cooperatively when not running as foreground window
// and when not quiting (causes trouble at mac's cleanup stage)
if (!LLApp::isExiting()
&& ((gViewerWindow && !gViewerWindow->getWindow()->getVisible())
|| !gFocusMgr.getAppHasFocus()))
Steven Bennetts
committed
{
// Sleep if we're not rendering, or the window is minimized.
static LLCachedControl<S32> s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40);
S32 milliseconds_to_sleep = llclamp((S32)s_bacground_yeild_time, 0, 1000);
// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
// of equal priority on Windows
if (milliseconds_to_sleep > 0)
Steven Bennetts
committed
{
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
Steven Bennetts
committed
}
}
if (mRandomizeFramerate)
{
if (mPeriodicSlowFrame
&& (gFrameCount % 10 == 0))
Steven Bennetts
committed
{
LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
ms_sleep(500);
}
S32 total_work_pending = 0;
S32 total_io_pending = 0;
{
S32 work_pending = 0;
S32 io_pending = 0;
F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
work_pending += updateTextureThreads(max_time);
Steven Bennetts
committed
{
LL_RECORD_BLOCK_TIME(FTM_VFS);
io_pending += LLVFSThread::updateClass(1);
Steven Bennetts
committed
}
{
LL_RECORD_BLOCK_TIME(FTM_LFS);
io_pending += LLLFSThread::updateClass(1);
Steven Bennetts
committed
}
if (io_pending > 1000)
Steven Bennetts
committed
{
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
Steven Bennetts
committed
}
total_work_pending += work_pending ;
total_io_pending += io_pending ;
Rider Linden
committed
}
gMeshRepo.update() ;
if(!total_work_pending) //pause texture fetching threads if nothing to process.
{
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
LLAppViewer::getTextureFetch()->pause();
}
if(!total_io_pending) //pause file threads if nothing to process.
{
LLVFSThread::sLocal->pause();
LLLFSThread::sLocal->pause();
}
//texture fetching debugger
if(LLTextureFetchDebugger::isEnabled())
{
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
if(tex_fetch_debugger_instance)
Xiaohong Bao
committed
{
tex_fetch_debugger_instance->idle() ;
Xiaohong Bao
committed
}
Xiaohong Bao
committed
resumeMainloopTimeout();
pingMainloopTimeout("Main:End");
Steven Bennetts
committed
}
}
Steven Bennetts
committed
Steven Bennetts
committed
{
// Save snapshot for next time, if we made it through initialization
if (STATE_STARTED == LLStartUp::getStartupState())
AndreyL ProductEngine
committed
saveFinalSnapshot();
andreykproductengine
committed
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->terminate();
}
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
Steven Bennetts
committed
}
return ! LLApp::isRunning();
Steven Bennetts
committed
}
S32 LLAppViewer::updateTextureThreads(F32 max_time)
{
S32 work_pending = 0;
{
LL_RECORD_BLOCK_TIME(FTM_TEXTURE_CACHE);
work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
}
{
LL_RECORD_BLOCK_TIME(FTM_DECODE);
work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
}
{
LL_RECORD_BLOCK_TIME(FTM_FETCH);
work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
}
return work_pending;
}
void LLAppViewer::flushVFSIO()
{
while (1)
{
S32 pending = LLVFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0);
if (!pending)
{
break;
}
LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL;
ms_sleep(100);
}
}
Steven Bennetts
committed
bool LLAppViewer::cleanup()
{
LLAtmosphere::cleanupClass();
//ditch LLVOAvatarSelf instance
gAgentAvatarp = NULL;
Graham Madarasz (Graham Linden)
committed
LLNotifications::instance().clear();
// workaround for DEV-35406 crash on shutdown
LLEventPumps::instance().reset();
Xiaohong Bao
committed
//dump scene loading monitor results
if (LLSceneMonitor::instanceExists())
{
LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"));
}
Xiaohong Bao
committed
// There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block
// here, completely redundant with the one that occurs later in this same
// function. Presumably the duplication was due to an automated merge gone
// bad. Not knowing which instance to prefer, we chose to retain the later
// one because it happens just after mFastTimerLogThread is deleted. This
// comment is in case we guessed wrong, so we can move it here instead.
David Parks
committed
// remove any old breakpad minidump files from the log directory
if (! isError())
{
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
}
// Kill off LLLeap objects. We can find them all because LLLeap is derived
// from LLInstanceTracker.
LLLeap::instance_snapshot().deleteAll();
brad kittenbrink
committed
Steven Bennetts
committed
//flag all elements as needing to be destroyed immediately
// to ensure shutdown order
LLMortician::setZealous(TRUE);
Rider Linden
committed
// Give any remaining SLPlugin instances a chance to exit cleanly.
LLPluginProcessParent::shutdown();
Steven Bennetts
committed
disconnectViewer();
LL_INFOS() << "Viewer disconnected" << LL_ENDL;
if (gKeyboard)
{
gKeyboard->resetKeys();
}
Steven Bennetts
committed
display_cleanup();
Steven Bennetts
committed
release_start_screen(); // just in case
Oz Linden
committed
LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder
Steven Bennetts
committed
Steven Bennetts
committed
// shut down mesh streamer
gMeshRepo.shutdown();
// shut down Havok
LLPhysicsExtensions::quitSystem();
Steven Bennetts
committed
// Must clean up texture references before viewer window is destroyed.
Mark Palange (Mani)
committed
if(LLHUDManager::instanceExists())
{
LLHUDManager::getInstance()->updateEffects();
LLHUDObject::updateAll();
LLHUDManager::getInstance()->cleanupEffects();
LLHUDObject::cleanupHUDObjects();
LL_INFOS() << "HUD Objects cleaned up" << LL_ENDL;
Mark Palange (Mani)
committed
}
Steven Bennetts
committed
Steven Bennetts
committed
// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
#if 0 // this seems to get us stuck in an infinite loop...
gTransferManager.cleanup();
#endif
// Note: this is where gWorldMap used to be deleted.
Steven Bennetts
committed
// Note: this is where gHUDManager used to be deleted.
Mark Palange (Mani)
committed
if(LLHUDManager::instanceExists())
{
LLHUDManager::getInstance()->shutdownClass();
}
Steven Bennetts
committed
delete gAssetStorage;
gAssetStorage = NULL;
LLPolyMesh::freeAllMeshes();
LLStartUp::cleanupNameCache();
Steven Bennetts
committed
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
Steven Bennetts
committed
if (LLWorldMap::instanceExists())
{
LLWorldMap::getInstance()->reset(); // release any images
}
LLCalc::cleanUp();
LL_INFOS() << "Global stuff deleted" << LL_ENDL;
Steven Bennetts
committed
if (gAudiop)
{
// shut down the audio subsystem
gAudiop = nullptr;
Steven Bennetts
committed
}
// Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
Steven Bennetts
committed
// Patch up settings for next time
// Must do this before we delete the viewer window,
// such that we can suck rectangle information out of
// it.
cleanupSavedSettings();
LL_INFOS() << "Settings patched up" << LL_ENDL;
Steven Bennetts
committed
// delete some of the files left around in the cache.
removeCacheFiles("*.wav");
removeCacheFiles("*.tmp");
removeCacheFiles("*.lso");
removeCacheFiles("*.out");
removeCacheFiles("*.dsf");
removeCacheFiles("*.bodypart");
removeCacheFiles("*.clothing");
LL_INFOS() << "Cache files removed" << LL_ENDL;
Steven Bennetts
committed
// Wait for any pending VFS IO
flushVFSIO();
LL_INFOS() << "Shutting down Views" << LL_ENDL;
// Destroy the UI
if( gViewerWindow)
gViewerWindow->shutdownViews();
Steve Bennetts
committed
LL_INFOS() << "Cleaning up Inventory" << LL_ENDL;
Steve Bennetts
committed
// Cleanup Inventory after the UI since it will delete any remaining observers
// (Deleted observers should have already removed themselves)
gInventory.cleanupInventory();
Steve Bennetts
committed
andreykproductengine
committed
LLCoros::getInstance()->printActiveCoroutines();
LL_INFOS() << "Cleaning up Selections" << LL_ENDL;
// Clean up selection managers after UI is destroyed, as UI may be observing them.
// Clean up before GL is shut down because we might be holding on to objects with texture references
LLSelectMgr::cleanupGlobals();
LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
// Shut down OpenGL
if( gViewerWindow)
{
gViewerWindow->shutdownGL();
// Destroy window, and make sure we're not fullscreen
// This may generate window reshape and activation events.
// Therefore must do this before destroying the message system.
delete gViewerWindow;
gViewerWindow = NULL;
LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
Steve Bennetts
committed
LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
Steven Bennetts
committed
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
if (LLViewerJoystick::instanceExists())
{
// Turn off Space Navigator and similar devices
LLViewerJoystick::getInstance()->terminate();
}
LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
Steven Bennetts
committed
LLViewerObject::cleanupVOClasses();
SUBSYSTEM_CLEANUP(LLAvatarAppearance);
SUBSYSTEM_CLEANUP(LLAvatarAppearance);
SUBSYSTEM_CLEANUP(LLPostProcess);
Steven Bennetts
committed
LLTracker::cleanupInstance();
Steven Bennetts
committed
// *FIX: This is handled in LLAppViewerWin32::cleanup().
// I'm keeping the comment to remember its order in cleanup,
// in case of unforseen dependency.
//#if LL_WINDOWS
// gDXHardware.cleanup();
//#endif // LL_WINDOWS
Steven Bennetts
committed
Kelly Washington
committed
LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
if (!volume_manager->cleanup())
Steven Bennetts
committed
{
LL_WARNS() << "Remaining references in the volume manager!" << LL_ENDL;
Steven Bennetts
committed
}
Kelly Washington
committed
LLPrimitive::cleanupVolumeManager();
Steven Bennetts
committed
LL_INFOS() << "Additional Cleanup..." << LL_ENDL;
Steven Bennetts
committed
LLViewerParcelMgr::cleanupGlobals();
// *Note: this is where gViewerStats used to be deleted.
Steven Bennetts
committed
//end_messaging_system();
Kelly Washington
committed
LLPrimitive::cleanupVolumeManager();
SUBSYSTEM_CLEANUP(LLWorldMapView);
SUBSYSTEM_CLEANUP(LLFolderViewItem);
Steven Bennetts
committed
//
// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
// Also after viewerwindow is deleted, since it may have image pointers (which have vfiles)
// Also after shutting down the messaging system since it has VFS dependencies
Steven Bennetts
committed
//
LL_INFOS() << "Cleaning up VFS" << LL_ENDL;
SUBSYSTEM_CLEANUP(LLVFile);
Steven Bennetts
committed
Steven Bennetts
committed
// Store the time of our current logoff
gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
if (LLEnvironment::instanceExists())
{
//Store environment settings if nessesary
LLEnvironment::getInstance()->saveToSettings();
}
Steven Bennetts
committed
// Must do this after all panels have been deleted because panels that have persistent rects
// save their rects on delete.
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
LLUIColorTable::instance().saveUserSettings(gSavedSettings.getBool("ResetUserColorsOnLogout"));
James Cook
committed
// PerAccountSettingsFile should be empty if no user has been logged on.
// *FIX:Mani This should get really saved in a "logoff" mode.
Tofu Linden
committed
if (gSavedSettings.getString("PerAccountSettingsFile").empty())
{
LL_INFOS() << "Not saving per-account settings; don't know the account name yet." << LL_ENDL;
Tofu Linden
committed
}
// Only save per account settings if the previous login succeeded, otherwise
// we might end up with a cleared out settings file in case a previous login
// failed after loading per account settings.
else if (!mSavePerAccountSettings)
{
LL_INFOS() << "Not saving per-account settings; last login was not successful." << LL_ENDL;
Tofu Linden
committed
else
{
gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
LL_INFOS() << "Saved settings" << LL_ENDL;
if (LLViewerParcelAskPlay::instanceExists())
{
LLViewerParcelAskPlay::getInstance()->saveSettings();
}
Tofu Linden
committed
}
Steven Bennetts
committed
std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
// Save URL history file
LLURLHistory::saveFile("url_history.xml");
// save mute list. gMuteList used to also be deleted here too.
if (gAgent.isInitialized() && LLMuteList::instanceExists())
{
LLMuteList::getInstance()->cache(gAgent.getID());
}
Steven Bennetts
committed
if (LLConversationLog::instanceExists())
{
LLConversationLog::instance().cache();
}
Steven Bennetts
committed
{
LL_INFOS() << "Purging all cache files on exit" << LL_ENDL;
Vadim ProductEngine
committed
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
Steven Bennetts
committed
}
Steven Bennetts
committed
Steve Bennetts
committed
LLLocationHistory::getInstance()->save();
LLAvatarIconIDCache::getInstance()->save();
// Stop the plugin read thread if it's running.
LLPluginProcessParent::setUseReadThread(false);
LL_INFOS() << "Shutting down Threads" << LL_ENDL;
Xiaohong Bao
committed
Steven Bennetts
committed
// Let threads finish
LLTimer idleTimer;
idleTimer.reset();
const F64 max_idle_time = 5.f; // 5 seconds
while(1)
{
S32 pending = 0;
pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
pending += LLVFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0);
F64 idle_time = idleTimer.getElapsedTimeF64();
Xiaohong Bao
committed
if(!pending)
{
break ; //done