summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp458
1 files changed, 343 insertions, 115 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 94e8fabcb2..c34441932d 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -131,7 +131,7 @@
#include "stringize.h"
#include "llcoros.h"
#include "llexception.h"
-#if 1 // !LL_LINUX
+#if !_M_ARM64 // !LL_LINUX
#include "cef/dullahan_version.h"
#include "vlc/libvlc_version.h"
#endif // LL_LINUX
@@ -278,6 +278,16 @@ using namespace LL;
#pragma warning (disable:4702)
#endif
+#ifdef LL_DISCORD
+#define DISCORDPP_IMPLEMENTATION
+#include <discordpp.h>
+static std::shared_ptr<discordpp::Client> gDiscordClient;
+static uint64_t gDiscordTimestampsStart;
+static std::string gDiscordActivityDetails;
+static int32_t gDiscordPartyCurrentSize;
+static int32_t gDiscordPartyMaxSize;
+#endif
+
static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
@@ -295,6 +305,7 @@ extern bool gDebugGL;
#if LL_DARWIN
extern bool gHiDPISupport;
+extern bool gHDRDisplaySupport;
#endif
////////////////////////////////////////////////////////////
@@ -456,13 +467,28 @@ static bool app_metrics_qa_mode = false;
void idle_afk_check()
{
+ // Don't check AFK status during startup states
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ return;
+ }
+
// check idle timers
F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
- if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK())
+ if (afk_timeout() && (current_idle > afk_timeout()))
{
- LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
- gAgent.setAFK();
+ if (!gAgent.getAFK())
+ {
+ LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
+ gAgent.setAFK();
+ }
+ else
+ {
+ // Refresh timer so that random one click or hover won't clear the status.
+ // But expanding the window still should lift afk status
+ gAwayTimer.reset();
+ }
}
}
@@ -571,6 +597,7 @@ static void settings_to_globals()
LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");
#endif // LL_SDL
gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
+ gHDRDisplaySupport = gSavedSettings.getBOOL("MPHDRDisplay");
#endif
}
@@ -582,6 +609,8 @@ static void settings_modify()
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
gDebugGL = gDebugGLSession || gDebugSession;
+ bool noGLDebug = gSavedSettings.getBOOL("MPNoGLDebug");
+ if(noGLDebug) gDebugGL = false;
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
}
@@ -1259,6 +1288,7 @@ bool LLAppViewer::init()
LLViewerCamera::createInstance();
LL::GLTFSceneManager::createInstance();
+ gSavedSettings.setU32("DebugQualityPerformance", gSavedSettings.getU32("RenderQualityPerformance"));
#if LL_WINDOWS
if (!mSecondInstance)
@@ -1285,11 +1315,15 @@ void LLAppViewer::initMaxHeapSize()
//------------------------------------------------------------------------------------------
//currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
- #ifndef LL_X86_64
+/*
+#ifndef LL_X86_64
F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
#else
+*/
F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize64");
+/*
#endif
+*/
LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
}
@@ -1341,14 +1375,21 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
U32 fpsLimitMaxFps = (U32)gSavedSettings.getU32("MaxFPS");
- if(fpsLimitMaxFps>120) fpsLimitMaxFps=0;
+ if(fpsLimitMaxFps > 120) fpsLimitMaxFps = 0;
using TimePoint = std::chrono::steady_clock::time_point;
+ U64 additionalSleepTime = 0;
+ TimePoint frameStartTime = std::chrono::steady_clock::now();
- U64 fpsLimitSleepFor = 0;
- TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now();
+#ifdef LL_DISCORD
+ {
+ LL_PROFILE_ZONE_NAMED("discord_callbacks");
+ discordpp::RunCallbacks();
+ }
+#endif
LL_RECORD_BLOCK_TIME(FTM_FRAME);
+ LL_PROFILE_GPU_ZONE("Frame");
{
// and now adjust the visuals from previous frame.
if(LLPerfStats::tunables.userAutoTuneEnabled && LLPerfStats::tunables.tuningFlag != LLPerfStats::Tunables::Nothing)
@@ -1438,24 +1479,26 @@ bool LLAppViewer::doFrame()
if (!LLApp::isExiting())
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard");
- 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
- if (gViewerWindow
- && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
- && gViewerWindow->getActive()
- && !gViewerWindow->getWindow()->getMinimized()
- && LLStartUp::getStartupState() == STATE_STARTED
- && (gHeadlessClient || !gViewerWindow->getShowProgress())
- && !gFocusMgr.focusLocked())
{
- LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
- joystick->scanJoystick();
- gKeyboard->scanKeyboard();
- gViewerInput.scanMouse();
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df JoystickKeyboard");
+ 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
+ if (gViewerWindow
+ && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
+ && gViewerWindow->getActive()
+ && !gViewerWindow->getWindow()->getMinimized()
+ && LLStartUp::getStartupState() == STATE_STARTED
+ && (gHeadlessClient || !gViewerWindow->getShowProgress())
+ && !gFocusMgr.focusLocked())
+ {
+ LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE);
+ joystick->scanJoystick();
+ gKeyboard->scanKeyboard();
+ gViewerInput.scanMouse();
+ }
}
// Update state based on messages, user input, object idle.
@@ -1518,18 +1561,6 @@ bool LLAppViewer::doFrame()
}
}
- if(fpsLimitMaxFps > 0)
- {
- auto elapsed = std::chrono::steady_clock::now() - fpsLimitFrameStartTime;
-
- long long fpsLimitFrameTime = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
- U64 desired_time_us = (U32)(1000000.f / fpsLimitMaxFps);
- if((fpsLimitFrameTime+1000) < desired_time_us)
- {
- fpsLimitSleepFor = (desired_time_us - fpsLimitFrameTime - 1000) * 1.0;
- }
- }
-
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout");
pingMainloopTimeout("Main:Sleep");
@@ -1542,13 +1573,25 @@ bool LLAppViewer::doFrame()
//LL_RECORD_BLOCK_TIME(SLEEP2);
LL_PROFILE_ZONE_WARN("Sleep2");
- if(fpsLimitSleepFor)
+ auto elapsed = std::chrono::steady_clock::now() - frameStartTime;
+ long long frameTime = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
+
+ if(fpsLimitMaxFps > 0)
{
-#if LL_WINDOWS
- std::this_thread::sleep_for(std::chrono::microseconds(fpsLimitSleepFor));
-#else
- usleep(fpsLimitSleepFor);
-#endif
+ U64 desired_time_us = (U32)(1000000.f / fpsLimitMaxFps);
+ if((frameTime+1000) < desired_time_us)
+ {
+ additionalSleepTime = 0.92 * (F64)(desired_time_us - frameTime);
+ if(additionalSleepTime < 200)
+ {
+ additionalSleepTime = 0;
+ }
+ }
+ }
+
+ if(additionalSleepTime > 0)
+ {
+ std::this_thread::sleep_for(std::chrono::microseconds(additionalSleepTime));
}
// yield some time to the os based on command line option
@@ -1644,6 +1687,9 @@ bool LLAppViewer::doFrame()
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout");
resumeMainloopTimeout();
}
+
+ //swap();
+
pingMainloopTimeout("Main:End");
}
}
@@ -1888,36 +1934,6 @@ bool LLAppViewer::cleanup()
// 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;
- }
-
- LLSplashScreen::show();
- LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
-
- LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
-
- // 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;
LLViewerObject::cleanupVOClasses();
@@ -2078,6 +2094,36 @@ bool LLAppViewer::cleanup()
sTextureFetch->shutDownTextureCacheThread() ;
LLLFSThread::sLocal->shutdown();
+ 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;
+ }
+
+ LLSplashScreen::show();
+ LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
+
+ LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
+
+ // 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() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
@@ -2298,10 +2344,7 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
// Callback for LLError::LLUserWarningMsg
void errorHandler(const std::string& title_string, const std::string& message_string, S32 code)
{
- if (!message_string.empty())
- {
- OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
- }
+ // message is going to hang viewer, create marker first
switch (code)
{
case LLError::LLUserWarningMsg::ERROR_OTHER:
@@ -2309,6 +2352,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st
break;
case LLError::LLUserWarningMsg::ERROR_BAD_ALLOC:
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_BAD_ALLOC);
+ // When system run out of memory and errorHandler gets called from a thread,
+ // main thread might keep going while OSMessageBox freezes the caller.
+ // Todo: handle it better, but for now disconnect to avoid making things worse
+ gDisconnected = true;
break;
case LLError::LLUserWarningMsg::ERROR_MISSING_FILES:
LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES);
@@ -2316,6 +2363,10 @@ void errorHandler(const std::string& title_string, const std::string& message_st
default:
break;
}
+ if (!message_string.empty())
+ {
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ }
}
void LLAppViewer::initLoggingAndGetLastDuration()
@@ -2408,7 +2459,6 @@ void LLAppViewer::initLoggingAndGetLastDuration()
if (gDirUtilp->fileExists(user_data_path_cef_log))
{
std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
- LLFile::remove(user_data_path_cef_old, ENOENT);
LLFile::rename(user_data_path_cef_log, user_data_path_cef_old);
}
}
@@ -3141,7 +3191,15 @@ bool LLAppViewer::initWindow()
.height(gSavedSettings.getU32("WindowHeight"))
.min_width(gSavedSettings.getU32("MinWindowWidth"))
.min_height(gSavedSettings.getU32("MinWindowHeight"))
+#ifdef LL_DARWIN
+ // Setting it to true causes black screen with no UI displayed.
+ // Given that it's a DEBUG settings and application goes fullscreen
+ // on mac simply by expanding it, it was decided to not support/use
+ // this setting on mac.
+ .fullscreen(false)
+#else // LL_DARWIN
.fullscreen(gSavedSettings.getBOOL("FullScreen"))
+#endif
.ignore_pixel_depth(ignorePixelDepth)
.first_run(mIsFirstRun);
@@ -3175,17 +3233,6 @@ bool LLAppViewer::initWindow()
LLNotificationsUI::LLNotificationManager::getInstance();
-
-#ifdef LL_DARWIN
- //Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later)
- LLOSInfo& os_info = LLOSInfo::instance();
- if (os_info.mMajorVer == 10 && os_info.mMinorVer < 7)
- {
- if ( os_info.mMinorVer == 6 && os_info.mBuild < 8 )
- gViewerWindow->getWindow()->setOldResize(true);
- }
-#endif
-
if (gSavedSettings.getBOOL("WindowMaximized"))
{
gViewerWindow->getWindow()->maximize();
@@ -3300,6 +3347,11 @@ LLSD LLAppViewer::getViewerInfo() const
info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
info["CHANNEL"] = versionInfo.getChannel();
info["ADDRESS_SIZE"] = ADDRESS_SIZE;
+#if LL_ARM64
+ info["ARCHITECTURE"] = "ARM";
+#else
+ info["ARCHITECTURE"] = "x86";
+#endif
std::string build_config = versionInfo.getBuildConfig();
if (build_config != "Release")
{
@@ -3392,7 +3444,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["FONT_SIZE_ADJUSTMENT"] = gSavedSettings.getF32("FontScreenDPI");
info["UI_SCALE"] = gSavedSettings.getF32("UIScaleFactor");
info["DRAW_DISTANCE"] = gSavedSettings.getF32("RenderFarClip");
- info["NET_BANDWITH"] = gSavedSettings.getF32("ThrottleBandwidthKBPS");
+ info["NET_BANDWITH"] = LLViewerThrottle::getMaxBandwidthKbps();
info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");
info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");
info["TEXTURE_MEMORY"] = LLSD::Integer(gGLManager.mVRAM);
@@ -3427,7 +3479,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
}
-#if 1 // !LL_LINUX
+#if !_M_ARM64 // !LL_LINUX
std::ostringstream cef_ver_codec;
cef_ver_codec << "Dullahan: ";
cef_ver_codec << DULLAHAN_VERSION_MAJOR;
@@ -3457,7 +3509,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["LIBCEF_VERSION"] = "Undefined";
#endif
-#if 1 // !LL_LINUX
+#if !_M_ARM64 // !LL_LINUX
std::ostringstream vlc_ver_codec;
vlc_ver_codec << LIBVLC_VERSION_MAJOR;
vlc_ver_codec << ".";
@@ -3954,8 +4006,15 @@ void LLAppViewer::processMarkerFiles()
else if (marker_is_same_version)
{
// the file existed, is ours, and matched our version, so we can report on what it says
- LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed or froze" << LL_ENDL;
+#if LL_WINDOWS && LL_BUGSPLAT
+ // bugsplat will set correct state in bugsplatSendLog
+ // Might be more accurate to rename this one into 'unknown'
+ gLastExecEvent = LAST_EXEC_FROZE;
+#else
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+#endif // LL_WINDOWS
+
}
else
{
@@ -4204,7 +4263,7 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
// case where we need the viewer to exit without any need for notifications
void LLAppViewer::earlyExitNoNotify()
{
- LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL;
+ LL_WARNS() << "app_early_exit with no notification." << LL_ENDL;
gDoDisconnect = true;
finish_early_exit( LLSD(), LLSD() );
}
@@ -4328,8 +4387,8 @@ bool LLAppViewer::initCache()
const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
const U32 MB = 1024 * 1024;
- const uintmax_t MIN_CACHE_SIZE = 256 * MB;
- const uintmax_t MAX_CACHE_SIZE = 9984ll * MB;
+ const uintmax_t MIN_CACHE_SIZE = 896 * MB;
+ const uintmax_t MAX_CACHE_SIZE = 32768ll * MB;
const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB;
const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal");
@@ -4435,6 +4494,9 @@ bool LLAppViewer::initCache()
const U32 CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS = 128;
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS, getObjectCacheVersion());
+ // Remove old, stale CEF cache folders
+ purgeCefStaleCaches();
+
return true;
}
@@ -4459,18 +4521,28 @@ void LLAppViewer::loadKeyBindings()
LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput);
}
+// As per GHI #4498, remove old, stale CEF cache folders from previous sessions
+void LLAppViewer::purgeCefStaleCaches()
+{
+ // TODO: we really shouldn't use a hard coded name for the cache folder here...
+ const std::string browser_parent_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache");
+ if (LLFile::isdir(browser_parent_cache))
+ {
+ // This is a sledgehammer approach - nukes the cef_cache dir entirely
+ // which is then recreated the first time a CEF instance creates an
+ // individual cache folder. If we ever decide to retain some folders
+ // e.g. Search UI cache - then we will need a more granular approach.
+ gDirUtilp->deleteDirAndContents(browser_parent_cache);
+ }
+}
+
void LLAppViewer::purgeCache()
{
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
LLViewerShaderMgr::instance()->clearShaderCache();
- std::string browser_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache");
- if (LLFile::isdir(browser_cache))
- {
- // cef does not support clear_cache and clear_cookies, so clear what we can manually.
- gDirUtilp->deleteDirAndContents(browser_cache);
- }
+ purgeCefStaleCaches();
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*");
}
@@ -4539,6 +4611,7 @@ void LLAppViewer::forceDisconnect(const std::string& mesg)
}
else
{
+ sendSimpleLogoutRequest();
args["MESSAGE"] = big_reason;
LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
}
@@ -5319,6 +5392,27 @@ void LLAppViewer::sendLogoutRequest()
}
}
+void LLAppViewer::sendSimpleLogoutRequest()
+{
+ if (!mLogoutRequestSent && gMessageSystem)
+ {
+ gLogoutInProgress = true;
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_LogoutRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+
+ LL_INFOS("Agent") << "Logging out as agent: " << gAgent.getID() << " Session: " << gAgent.getSessionID() << LL_ENDL;
+
+ gLogoutTimer.reset();
+ gLogoutMaxTime = LOGOUT_REQUEST_TIME;
+ mLogoutRequestSent = true;
+ }
+}
+
void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp)
{
if (!regionp || !regionp->capabilitiesReceived())
@@ -5383,6 +5477,12 @@ void LLAppViewer::createErrorMarker(eLastExecEvent error_code) const
}
}
+bool LLAppViewer::errorMarkerExists() const
+{
+ std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
+ return LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB);
+}
+
void LLAppViewer::outOfMemorySoftQuit()
{
if (!mQuitRequested)
@@ -5514,7 +5614,10 @@ void LLAppViewer::idleNetwork()
add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects);
// Retransmit unacknowledged packets.
- gXferManager->retransmitUnackedPackets();
+ if (gXferManager)
+ {
+ gXferManager->retransmitUnackedPackets();
+ }
gAssetStorage->checkForTimeouts();
gViewerThrottle.setBufferLoadRate(gMessageSystem->getBufferLoadRate());
gViewerThrottle.updateDynamicThrottle();
@@ -5635,6 +5738,8 @@ void LLAppViewer::forceErrorBreakpoint()
DebugBreak();
#elif __i386__ || __x86_64__
asm ("int $3");
+#else
+ __builtin_trap();
#endif
return;
}
@@ -5733,9 +5838,31 @@ void LLAppViewer::forceErrorThreadCrash()
thread->start();
}
-void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::forceExceptionThreadCrash()
+{
+ class LLCrashTestThread : public LLThread
+ {
+ public:
+
+ LLCrashTestThread() : LLThread("Crash logging test thread")
+ {
+ }
+
+ void run()
+ {
+ const std::string exception_text = "This is a deliberate exception in a thread";
+ throw std::runtime_error(exception_text);
+ }
+ };
+
+ LL_WARNS() << "This is a deliberate exception in a thread" << LL_ENDL;
+ LLCrashTestThread* thread = new LLCrashTestThread();
+ thread->start();
+}
+
+void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs)
{
- if(!mMainloopTimeout)
+ if (!mMainloopTimeout)
{
mMainloopTimeout = new LLWatchdogTimeout();
resumeMainloopTimeout(state, secs);
@@ -5744,20 +5871,20 @@ void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::destroyMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
delete mMainloopTimeout;
- mMainloopTimeout = NULL;
+ mMainloopTimeout = nullptr;
}
}
-void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::resumeMainloopTimeout(std::string_view state, F32 secs)
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
- static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
+ static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60.f);
secs = mainloop_timeout;
}
@@ -5768,19 +5895,19 @@ void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::pauseMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
mMainloopTimeout->stop();
}
}
-void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::pingMainloopTimeout(std::string_view state, F32 secs)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
secs = mainloop_timeout;
@@ -5907,3 +6034,104 @@ void LLAppViewer::metricsSend(bool enable_reporting)
// resolution in time.
gViewerAssetStats->restart();
}
+
+#ifdef LL_DISCORD
+
+void LLAppViewer::initDiscordSocial()
+{
+ gDiscordPartyCurrentSize = 1;
+ gDiscordPartyMaxSize = 0;
+ gDiscordTimestampsStart = time(nullptr);
+ gDiscordClient = std::make_shared<discordpp::Client>();
+ gDiscordClient->SetApplicationId(1393451183741599796);
+ updateDiscordActivity();
+}
+
+void LLAppViewer::updateDiscordActivity()
+{
+ LL_PROFILE_ZONE_SCOPED;
+
+ static LLCachedControl<bool> integration_enabled(gSavedSettings, "EnableDiscord", true);
+ if (!integration_enabled)
+ {
+ gDiscordClient->ClearRichPresence();
+ return;
+ }
+
+ discordpp::Activity activity;
+ activity.SetType(discordpp::ActivityTypes::Playing);
+ discordpp::ActivityTimestamps timestamps;
+ timestamps.SetStart(gDiscordTimestampsStart);
+ activity.SetTimestamps(timestamps);
+
+ if (gAgent.getID() == LLUUID::null)
+ {
+ gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
+ return;
+ }
+
+ static LLCachedControl<bool> show_details(gSavedSettings, "ShowDiscordActivityDetails", false);
+ if (show_details)
+ {
+ if (gDiscordActivityDetails.empty())
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(gAgent.getID(), &av_name);
+ gDiscordActivityDetails = av_name.getUserName();
+ auto displayName = av_name.getDisplayName();
+ if (gDiscordActivityDetails != displayName)
+ gDiscordActivityDetails = displayName + " (" + gDiscordActivityDetails + ")";
+ }
+ activity.SetDetails(gDiscordActivityDetails);
+ }
+
+ auto agent_pos_region = gAgent.getPositionAgent();
+ S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
+ S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
+ S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
+ F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
+ const F32 FLY_CUTOFF = 6.f;
+ const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
+ const F32 WALK_CUTOFF = 1.5f;
+ const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
+ if (velocity_mag_sq > FLY_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 4;
+ pos_y -= pos_y % 4;
+ }
+ else if (velocity_mag_sq > WALK_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 2;
+ pos_y -= pos_y % 2;
+ }
+
+ std::string location = "Hidden Region";
+ static LLCachedControl<bool> show_state(gSavedSettings, "ShowDiscordActivityState", false);
+ if (show_state)
+ {
+ location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z);
+ }
+ activity.SetState(location);
+
+ discordpp::ActivityParty party;
+ party.SetId(location);
+ party.SetCurrentSize(gDiscordPartyCurrentSize);
+ party.SetMaxSize(gDiscordPartyMaxSize);
+ activity.SetParty(party);
+
+ gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
+}
+
+void LLAppViewer::updateDiscordPartyCurrentSize(int32_t size)
+{
+ gDiscordPartyCurrentSize = size;
+ updateDiscordActivity();
+}
+
+void LLAppViewer::updateDiscordPartyMaxSize(int32_t size)
+{
+ gDiscordPartyMaxSize = size;
+ updateDiscordActivity();
+}
+
+#endif