diff options
Diffstat (limited to 'indra/newview/llappviewer.cpp')
| -rw-r--r-- | indra/newview/llappviewer.cpp | 273 |
1 files changed, 261 insertions, 12 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 441f43163d..26542a29c6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -46,6 +46,7 @@ #include "llagentwearables.h" #include "lldirpicker.h" #include "llfloaterimcontainer.h" +#include "llfloaterpreference.h" #include "llimprocessing.h" #include "llwindow.h" #include "llviewerstats.h" @@ -55,13 +56,16 @@ #include "llmarketplacenotifications.h" #include "llmd5.h" #include "llmeshrepository.h" +#include "llpanelpreferencegamecontrol.h" #include "llpumpio.h" #include "llmimetypes.h" #include "llslurl.h" #include "llstartup.h" +#include "llviewermcp.h" #include "llfocusmgr.h" #include "llurlfloaterdispatchhandler.h" #include "llviewerjoystick.h" +#include "llgamecontrol.h" #include "llcalc.h" #include "llconversationlog.h" #if LL_WINDOWS @@ -138,10 +142,14 @@ #include "stringize.h" #include "llcoros.h" #include "llexception.h" +#if defined(LL_CEF) #include "cef/dullahan_version.h" +#endif +#if defined(LL_VLC) #include "vlc/libvlc_version.h" +#endif -#if LL_DARWIN +#if LL_DARWIN && !LL_SDL_WINDOW #include "llwindowmacosx.h" #endif @@ -194,6 +202,7 @@ #include "lldebugview.h" #include "llconsole.h" #include "llcontainerview.h" +#include "lltoolfocus.h" #include "lltooltip.h" #include "llsdutil.h" @@ -220,6 +229,7 @@ #include "llvosurfacepatch.h" #include "llviewerfloaterreg.h" #include "llcommandlineparser.h" +#include "llfloaterpreference.h" #include "llfloatermemleak.h" #include "llfloaterreg.h" #include "llfloatersimplesnapshot.h" @@ -259,6 +269,11 @@ using namespace LL; #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" +#include <chrono> +#include "rlvactions.h" +#include "rlvcommon.h" +#include "rlvhandler.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 @@ -274,6 +289,12 @@ using namespace LL; #include "llappviewerlistener.h" #ifdef LL_DISCORD +#ifdef None +#undef None +#endif +#ifdef BadRequest +#undef BadRequest +#endif #define DISCORDPP_IMPLEMENTATION #include <discordpp.h> static std::shared_ptr<discordpp::Client> gDiscordClient; @@ -292,6 +313,7 @@ static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); #if LL_DARWIN extern void init_apple_menu(const char* product); +extern bool gHDRDisplaySupport; #endif // LL_DARWIN extern bool gRandomizeFramerate; @@ -328,6 +350,8 @@ LLUUID gLastAgentSessionId; # define LL_PLATFORM_KEY "mac" #elif LL_LINUX # define LL_PLATFORM_KEY "lnx" +#elif __FreeBSD__ +# define LL_PLATFORM_KEY "bsd" #else # error "Unknown Platform" #endif @@ -584,8 +608,13 @@ static void settings_to_globals() LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); #if LL_DARWIN +#if LL_SDL_WINDOW + LLWindowSDL::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); +#else LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); #endif + gHDRDisplaySupport = gSavedSettings.getBOOL("MPHDRDisplay"); +#endif #if LL_DARWIN || LL_SDL_WINDOW gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); @@ -600,6 +629,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"); } @@ -691,7 +722,7 @@ LLAppViewer::LLAppViewer() // 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"); + gDirUtilp->initAppDirs("Megapahit"); // // IMPORTANT! Do NOT put anything that will write // into the log files during normal startup until AFTER @@ -933,7 +964,7 @@ bool LLAppViewer::init() std::string mime_types_name; #if LL_DARWIN mime_types_name = "mime_types_mac.xml"; -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ mime_types_name = "mime_types_linux.xml"; #else mime_types_name = "mime_types.xml"; @@ -1138,6 +1169,31 @@ bool LLAppViewer::init() LLViewerJoystick::getInstance()->init(false); } + LLGameControl::init(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "gamecontrollerdb.txt"), + [](const std::vector<std::string>& keys) -> LLSD + { + LLSD result = LLSD::emptyMap(); + for (const std::string& key : keys) + { + if (gSavedSettings.controlExists(key)) + { + result[key] = gSavedSettings.getLLSD(key); + } + } + return result; + }, + [](const LLSD& key_values) + { + for (auto it = key_values.beginMap(); it != key_values.endMap(); ++it) + { + if (gSavedSettings.controlExists(it->first)) + { + gSavedSettings.setLLSD(it->first, it->second); + } + } + }, + []() { LLPanelPreferenceGameControl::updateDeviceList(); }); + try { initializeSecHandler(); @@ -1149,7 +1205,7 @@ bool LLAppViewer::init() gGLActive = false; -#if !LL_LINUX +#if 0 // Launch VVM update check (Linux updater is future work: Velopack port) if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") && !gNonInteractive) { @@ -1247,6 +1303,7 @@ bool LLAppViewer::init() LLWorld::createInstance(); LLViewerStatsRecorder::createInstance(); LLSelectMgr::createInstance(); + LLToolCamera::createInstance(); LLViewerCamera::createInstance(); LL::GLTFSceneManager::createInstance(); @@ -1334,9 +1391,85 @@ bool LLAppViewer::frame() return ret; } +void sendGameControlData() +{ + LLMessageSystem* msg = gMessageSystem; + const LLGameControl::ServerState& state = LLGameControl::getServerState(); + + msg->newMessageFast(_PREHASH_GameControlData); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgentID); + msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + msg->addU8Fast(_PREHASH_Packet, LLGameControl::getNextPacketNum()); + msg->addU8Fast(_PREHASH_ActionMode, state.mActionMode); + + // Non-modal canonical axes/buttons: pack every available value every message, + // whether or not it changed since the last one (no per-field diffing). Trailing + // zero axes are truncated and the Buttons block is skipped entirely when zero -- + // the server assumes anything not packed is zero -- to save bytes. + size_t num_axes = state.mAxes.size(); + while (num_axes > 0 && state.mAxes[num_axes - 1] == 0) + { + --num_axes; + } + for (size_t i = 0; i < num_axes; ++i) + { + msg->nextBlockFast(_PREHASH_Axes); + msg->addS16Fast(_PREHASH_Value, state.mAxes[i]); + } + if (state.mButtons != 0) + { + msg->nextBlockFast(_PREHASH_Buttons); + msg->addU32Fast(_PREHASH_Flags, state.mButtons); + } + + // Modal semantic axes/buttons: same truncation policy, except the number of + // axes considered depends on ActionMode -- see message_template.msg's + // GameControlData doc and LLGameControl::numSemanticAxesForMode() -- since the + // server computes its own expected axis count from the mode and zeros anything + // not packed. + size_t num_mode_axes = LLGameControl::numSemanticAxesForMode((LLGameControl::AgentControlMode)state.mActionMode); + while (num_mode_axes > 0 && state.mSemanticAxes[num_mode_axes - 1] == 0) + { + --num_mode_axes; + } + for (size_t i = 0; i < num_mode_axes; ++i) + { + msg->nextBlockFast(_PREHASH_ModeAxes); + msg->addS16Fast(_PREHASH_Value, state.mSemanticAxes[i]); + } + if (state.mSemanticButtons != 0) + { + msg->nextBlockFast(_PREHASH_ModeButtons); + msg->addU32Fast(_PREHASH_Flags, state.mSemanticButtons); + } + + LLGameControl::updateResendPeriod(); + gAgent.sendMessage(); + + // Mirror the just-sent channel values into the preferences "Data Output" tab. + LLPanelPreferenceGameControl::updateDataOutput(); +} + bool LLAppViewer::doFrame() { + // SIGTERM asks for a normal logout. Quitting immediately skips + // LogoutRequest and leaves the agent in the region. + if (LLApp::consumeSignalQuit() && !mQuitRequested && !isQuitting()) + { + LL_INFOS() << "Terminate signal, logging out before exit" << LL_ENDL; + requestQuit(); + } + resumeMainloopTimeout("Main:doFrameStart"); + + U32 fpsLimitMaxFps = (U32)gSavedSettings.getU32("MaxFPS"); + if(fpsLimitMaxFps > 120) fpsLimitMaxFps = 0; + + using TimePoint = std::chrono::steady_clock::time_point; + U64 additionalSleepTime = 0; + TimePoint frameStartTime = std::chrono::steady_clock::now(); + #ifdef LL_DISCORD { LL_PROFILE_ZONE_NAMED("discord_callbacks"); @@ -1404,7 +1537,7 @@ bool LLAppViewer::doFrame() LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; } - gViewerWindow->getWindow()->gatherInput(); + gViewerWindow->getWindow()->gatherInput(gFocusMgr.getAppHasFocus()); } //memory leaking simulation @@ -1456,6 +1589,11 @@ bool LLAppViewer::doFrame() joystick->scanJoystick(); gKeyboard->scanKeyboard(); gViewerInput.scanMouse(); + + if (gAgent.isCrouching()) + { + gAgent.moveUp(-1); + } } } @@ -1532,6 +1670,27 @@ bool LLAppViewer::doFrame() //LL_RECORD_BLOCK_TIME(SLEEP2); LL_PROFILE_ZONE_WARN("Sleep2"); + auto elapsed = std::chrono::steady_clock::now() - frameStartTime; + long long frameTime = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count(); + + if(fpsLimitMaxFps > 0) + { + 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 static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1); if(yield_time >= 0) @@ -1625,6 +1784,9 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout"); resumeMainloopTimeout(); } + + //swap(); + pingMainloopTimeout("Main:End"); } } @@ -1701,6 +1863,7 @@ void LLAppViewer::flushLFSIO() bool LLAppViewer::cleanup() { + LLViewerMCP::shutdown(); #if LL_VELOPACK // Apply any pending Velopack update before shutdown if (velopack_is_update_pending()) @@ -1714,6 +1877,9 @@ bool LLAppViewer::cleanup() //ditch LLVOAvatarSelf instance gAgentAvatarp = NULL; + // Sanity check to catch cases where someone forgot to do an RlvActions::isRlvEnabled() check + LL_ERRS_IF(!RlvHandler::isEnabled() && RlvHandler::instanceExists()) << "RLV handler instance exists even though RLVa is disabled" << LL_ENDL; + LLNotifications::instance().clear(); // workaround for DEV-35406 crash on shutdown @@ -1737,7 +1903,7 @@ bool LLAppViewer::cleanup() // one because it happens just after mFastTimerLogThread is deleted. This // comment is in case we guessed wrong, so we can move it here instead. -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ // remove any old breakpad minidump files from the log directory if (! isError()) { @@ -2081,6 +2247,8 @@ bool LLAppViewer::cleanup() LLViewerJoystick::getInstance()->terminate(); } + LLGameControl::terminate(); + LL_INFOS() << "Shutting down message system" << LL_ENDL; end_messaging_system(); @@ -2695,20 +2863,27 @@ bool LLAppViewer::initConfiguration() bool success = LLXMLNode::parseFile(settings_file_list, root, NULL); if (!success) { - LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; + std::string parse_error = LLXMLNode::getLastFileError(); + const std::string& run_context = gDirUtilp->getRunContextDescription(); + + LL_WARNS() << "Cannot load default configuration file " << settings_file_list + << (parse_error.empty() ? "" : (" - " + parse_error)) << LL_ENDL; LLError::LLUserWarningMsg::showMissingFiles(); if (gDirUtilp->fileExists(settings_file_list)) { LL_ERRS() << "Cannot load default configuration file settings_files.xml. " << "Please reinstall viewer from https://secondlife.com/support/downloads/ " - << "and contact https://support.secondlife.com if issue persists after reinstall." + << "and contact https://support.secondlife.com if issue persists after reinstall. " + << "Reason: " << (parse_error.empty() ? "unknown (file is present but could not be parsed)" : parse_error) + << ". Install type: " << run_context << LL_ENDL; } else { LL_ERRS() << "Default configuration file settings_files.xml not found. " << "Please reinstall viewer from https://secondlife.com/support/downloads/ " - << "and contact https://support.secondlife.com if issue persists after reinstall." + << "and contact https://support.secondlife.com if issue persists after reinstall. " + << "Install type: " << run_context << LL_ENDL; } } @@ -3565,7 +3740,7 @@ LLSD LLAppViewer::getViewerInfo() const url = LLTrans::getString("RELEASE_NOTES_BASE_URL"); if (!LLStringUtil::endsWith(url, "/")) url += "/"; - url += LLURI::escape(versionInfo.getVersion()) + ".html"; + url += "#" + LLURI::escape(versionInfo.getVersion()); // + ".html"; } info["VIEWER_RELEASE_NOTES_URL"] = url; @@ -3632,6 +3807,7 @@ LLSD LLAppViewer::getViewerInfo() const } #endif + info["RLV_VERSION"] = RlvActions::isRlvEnabled() ? Rlv::Strings::getVersionAbout() : "(disabled)"; info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION))); // Settings @@ -3677,6 +3853,7 @@ LLSD LLAppViewer::getViewerInfo() const info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); } +#if defined(LL_CEF) std::ostringstream cef_ver_codec; cef_ver_codec << "Dullahan: "; cef_ver_codec << DULLAHAN_VERSION_MAJOR; @@ -3702,7 +3879,9 @@ LLSD LLAppViewer::getViewerInfo() const cef_ver_codec << CHROME_VERSION_PATCH; info["LIBCEF_VERSION"] = cef_ver_codec.str(); +#endif +#if defined(LL_VLC) std::ostringstream vlc_ver_codec; vlc_ver_codec << LIBVLC_VERSION_MAJOR; vlc_ver_codec << "."; @@ -3710,6 +3889,7 @@ LLSD LLAppViewer::getViewerInfo() const vlc_ver_codec << "."; vlc_ver_codec << LIBVLC_VERSION_REVISION; info["LIBVLC_VERSION"] = vlc_ver_codec.str(); +#endif LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); S32 packets_in = (S32)recording.getSum(LLStatViewer::PACKETS_IN); @@ -4854,6 +5034,7 @@ void LLAppViewer::loadKeyBindings() } } LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput); + LLUrlRegistry::instance().setGameControllerHandler(LLGameControl::getInstance()); } // As per GHI #4498, remove old, stale CEF cache folders from previous sessions @@ -5210,6 +5391,7 @@ void LLAppViewer::idle() { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; pingMainloopTimeout("Main:Idle"); + LLViewerMCP::pump(); // Update frame timers static LLTimer idle_timer; @@ -5326,6 +5508,68 @@ void LLAppViewer::idle() gAgent.autoPilot(&yaw); } + // Auto-derive the active game-control mode (Avatar/Captive/FlyCam) from + // current avatar state so the runtime mappings and gating track it. + gAgent.updateGameControlMode(); + + // Read the agent's control flags now, before applyExternalActions() below + // (which drives the avatar from a real game controller) has a chance to + // fold any controller-driven movement into them this frame -- so the + // keyboard-derived GameControl state computed here can never be sourced + // from the controller's own output. See LLGameControllerManager:: + // setExternalInput()/accumulateFinalState() for where the two are + // combined (only as fully-independent final ServerStates). + U32 control_flags = gAgent.getControlFlags(); + + // apply to GameControl + LLGameControl::setExternalInput(control_flags, gAgent.getGameControlButtonsFromKeys(), gAgent.getRunning()); + + // Feed the actual on-screen cursor position to GameControl + // Matches the same whole-window clamp LLViewerWindow::moveCursorTo() + // uses to keep a gamepad-driven cursor on-screen. + if (LLGameControl::getAgentControlMode() == LLGameControl::CONTROL_MODE_CURSOR) + { + LLCoordGL cursor_pos = gViewerWindow->getCurrentMouse(); + S32 rect_width = gViewerWindow->getWindowWidthScaled(); + S32 rect_height = gViewerWindow->getWindowHeightScaled(); + S32 pixel_x = llclamp(cursor_pos.mX, 0, rect_width); + S32 pixel_y = llclamp(rect_height - cursor_pos.mY, 0, rect_height); + LLGameControl::setMouseCursorPosition(pixel_x, pixel_y, rect_width, rect_height); + } + + if (LLPanelPreferenceGameControl::isWaitingForInputChannel()) + { + LLPanelPreferenceGameControl::applyGameControlInput(); + } + else + { + // Recompute canonical controller state (also populates the internal + // state consumed below) and send it to the server when it changed, + // but only if the agent's region advertises support for it (the + // "GameControlEnabled" simulator feature). While unsupported the + // resend deadline is left untouched, so the first frame after the + // feature appears sends immediately. + if (LLGameControl::computeFinalStateAndCheckForChanges()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp && regionp->gameControlEnabled()) + { + sendGameControlData(); + } + } + + // Drive the local avatar from the controller. In Avatar/Captive + // modes this moves the avatar; in FlyCam mode applyExternalActions + // ignores movement bits (it early-returns while flycam is active) but + // still services the flycam on/off toggle, so we run it either way. + // Flycam *motion* is driven separately below via gAgent.updateFlycam(). + if (LLGameControl::willControlAvatar() || LLGameControl::willControlFlycam()) + { + LLGameControl::AgentActions game_control_actions = LLGameControl::computeAgentActions(); + gAgent.applyExternalActions(game_control_actions); + } + } + send_agent_update(false); // After calling send_agent_update() in the mainloop we always clear @@ -5593,9 +5837,14 @@ void LLAppViewer::idle() { gAgentPilot.moveCamera(); } - else if (LLViewerJoystick::getInstance()->getOverrideCamera()) + else if (gAgent.isUsingFlycam()) { + // Flycam is now a single shared state (LLAgentCamera) driven by + // whichever input sources are actually present; each is a no-op + // when its device/mode isn't active, so it's safe to feed both + // every frame rather than picking one exclusively. LLViewerJoystick::getInstance()->moveFlycam(); + gAgent.updateFlycam(); } else { @@ -6572,7 +6821,7 @@ void LLAppViewer::initDiscordSocial() gDiscordPartyMaxSize = 0; gDiscordTimestampsStart = time(nullptr); gDiscordClient = std::make_shared<discordpp::Client>(); - gDiscordClient->SetApplicationId(1394782217405862001); + gDiscordClient->SetApplicationId(1393451183741599796); updateDiscordActivity(); } |
