diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 6716f65d05..8457be2346 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1419,7 +1419,7 @@ void LLAudioEngine::logSoundPlay(const LLUUID& id, LLVector3d position, S32 type item->mOwnerID = ownerid; item->mSourceID = sourceid; item->mPlaying = true; - item->mTimeStarted = LLTimer::getElapsedSeconds(); + item->mTimeStarted = LLTimer::getUptimeSeconds(); item->mTimeStopped = F64_MAX; item->mIsTrigger = is_trigger; item->mIsLooped = is_looped; @@ -1437,7 +1437,7 @@ void LLAudioEngine::logSoundStop(const LLUUID& id) { LLSoundHistoryItem& hist_item = *iter->second; hist_item.mPlaying = false; - hist_item.mTimeStopped = LLTimer::getElapsedSeconds(); + hist_item.mTimeStopped = LLTimer::getUptimeSeconds(); pruneSoundLog(); } } diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 7e1f2f316a..58e2790960 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -340,6 +340,7 @@ if(AL_BUILD_TESTS) llstreamtools llstring llstring_utf + lltimer lltrace lltreeiterators llunits diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6d4b7f5b9f..1cad7b256d 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -38,13 +38,11 @@ #include "llcommon.h" -#include "llerrorcontrol.h" #include "llframetimer.h" #include "lllivefile.h" #include "llmemory.h" #include "llstl.h" // for DeletePointer() #include "llstring.h" -#include "llthread.h" // for on_main_thread() #include "lleventtimer.h" #include "stringize.h" #include "llcleanup.h" @@ -377,10 +375,9 @@ void LLApp::sendOutOfDiskSpaceNotification() #ifndef LL_WINDOWS // With a crash reporter in the process, the crash signals are its own: // crashpad on Linux and SentryCrash on macOS install their handlers after -// this runs, and a handler of ours underneath would run the app's shutdown -// from inside a crashed process once the reporter re-raises. The signals the -// app answers itself, for a graceful quit or to ignore, stay with it either -// way. +// this runs, and a handler of ours underneath would have nothing to add once +// the reporter re-raises. The signals the app answers itself, for a graceful +// quit or to ignore, stay with it either way. void setup_signals() { // @@ -484,8 +481,6 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) { // Unix implementation of synchronous signal handler // This runs in the thread that threw the signal. - // We do the somewhat sketchy operation of blocking in here until the error handler - // has gracefully stopped the app. // FIXME(brad) - we are using this handler for asynchronous signals as well, so sLogInSignal is currently // disabled for safety. we need to find a way to selectively reenable it when it is safe. @@ -555,11 +550,6 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) { LL_WARNS() << "Signal handler - Handling smackdown signal!" << LL_ENDL; } - else - { - // Don't log anything, even errors - this is because this signal could happen anywhere. - LLError::setDefaultLevel(LLError::LEVEL_NONE); - } // Change the signal that we reraise to SIGABRT, so we generate a core dump. signum = SIGABRT; @@ -567,54 +557,21 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) if (LLApp::sLogInSignal) { - LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL; - } - - if (LLApp::isError()) - { - // Received second fatal signal while handling first, just die right now - // Set the signal handlers back to default before handling the signal - this makes the next signal wipe out the app. - clear_signals(); - - if (LLApp::sLogInSignal) - { - LL_WARNS() << "Signal handler - Got another fatal signal while in the error handler, die now!" << LL_ENDL; - } - raise(signum); - return; + LL_WARNS() << "Signal handler - Fatal signal, passing it back to the operating system" << LL_ENDL; } - if (LLApp::sLogInSignal) - { - LL_WARNS() << "Signal handler - Flagging error status and waiting for shutdown" << LL_ENDL; - } - - if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem - { - clear_signals(); - LL_WARNS() << "Fatal signal received, not handling the crash here, passing back to operating system" << LL_ENDL; - raise(signum); - return; - } - - if (!on_main_thread()) - { - // A fatal signal on a helper thread cannot be handled gracefully: - // setError() posts events and joins thread pools, which deadlocks - // if the crashing thread is one the shutdown depends on, e.g. a - // libdispatch worker inside the macOS GL driver. Crash instead. - clear_signals(); - raise(signum); - return; - } - - // Flag status to ERROR - LLApp::setError(); - - if (LLApp::sLogInSignal) - { - LL_WARNS() << "Signal handler - App is stopped, reraising signal" << LL_ENDL; - } + // A fatal signal is never handled here, on any thread. LLApp::setError() + // posts the status change, and its listeners close work queues and join + // thread pools -- none of it safe inside a signal handler, least of all + // after a fault, when the heap may already be damaged. Each worker that + // exits frees its malloc cache on the way out and aborts on that damage, + // so the core records a worker's abort instead of the fault that started + // it; and a fault on a thread the shutdown waits for, such as a + // libdispatch worker inside the macOS GL driver, deadlocks outright. + // LLApp::isError() is no safer, since it locks a fiber mutex. + // + // Restoring the default handlers before re-raising also covers a second + // fatal signal: it takes the process down by default. clear_signals(); raise(signum); return; diff --git a/indra/llcommon/lldeadmantimer.cpp b/indra/llcommon/lldeadmantimer.cpp index 45c01eb84a..1116c3ad28 100644 --- a/indra/llcommon/lldeadmantimer.cpp +++ b/indra/llcommon/lldeadmantimer.cpp @@ -44,7 +44,7 @@ // true true Not allowed // LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu) - : mHorizon(time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency)), + : mHorizon(U64L(0)), mActive(false), // If true, a timer is running. mDone(false), // If true, timer has completed and can be read (once) mStarted(U64L(0)), @@ -56,7 +56,15 @@ LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu) mUEndCPU(LLProcInfo::time_type(U64L(0))), mSStartCPU(LLProcInfo::time_type(U64L(0))), mSEndCPU(LLProcInfo::time_type(U64L(0))) -{} +{ + // A timer constructed during static initialisation can come before + // anything has read the clock frequency, which would make the horizon 0. + if (!get_timer_info().mClockFrequency) + { + get_timer_info().update(); + } + mHorizon = time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency); +} // static diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index a0080b57bb..476be89e2b 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -51,18 +51,22 @@ void LLFrameTimer::updateFrameTime() void LLFrameTimer::start() { - reset(); mStarted = true; + reset(); } void LLFrameTimer::stop() { - mStarted = false; + // Frozen at the time run so far, as pause() leaves it: a stopped timer's + // elapsed time is otherwise read back as its absolute start time. + pause(); } void LLFrameTimer::reset() { - mStartTime = sFrameTime; + // A paused timer keeps its elapsed time where a running one keeps its + // start, so a reset while paused zeroes that rather than writing a start. + mStartTime = mStarted ? sFrameTime : 0.0; mExpiry = sFrameTime; } @@ -96,12 +100,12 @@ void LLFrameTimer::unpause() void LLFrameTimer::setTimerExpirySec(F32 expiration) { - mExpiry = expiration + mStartTime; + mExpiry = expiration + sFrameTime; } void LLFrameTimer::setExpiryAt(F64 seconds_since_epoch) { - mStartTime = sFrameTime; + reset(); mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime); } diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index ba4f075b57..4be90a5063 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -42,10 +42,10 @@ class LL_COMMON_API LLFrameTimer LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(true) {} // Return the number of seconds since the start of this - // application instance. - static F64SecondsImplicit getElapsedSeconds() + // application instance, as of the current frame. Static: it is not this + // timer's elapsed time, which is getElapsedTimeF32(). + static F64SecondsImplicit getUptimeSeconds() { - // Loses msec precision after ~4.5 hours... return sFrameTime; } @@ -82,12 +82,12 @@ class LL_COMMON_API LLFrameTimer void resetWithExpiry(F32 expiration); void pause(); void unpause(); - void setTimerExpirySec(F32 expiration); + void setTimerExpirySec(F32 expiration); // Expires this long from now, as LLTimer's does void setExpiryAt(F64 seconds_since_epoch); bool checkExpirationAndReset(F32 expiration); - F32 getElapsedTimeAndResetF32() { F32 t = F32(sFrameTime - mStartTime); reset(); return t; } + F32 getElapsedTimeAndResetF32() { F32 t = getElapsedTimeF32(); reset(); return t; } - void setAge(const F64 age) { mStartTime = sFrameTime - age; } + void setAge(const F64 age) { mStartTime = mStarted ? sFrameTime - age : age; } // ACCESSORS bool hasExpired() const { return (sFrameTime >= mExpiry); } diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 1614cc6e57..6b3292c597 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -442,8 +442,8 @@ class LLLeapImpl: public LLLeap LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); LLSD nop; - F64 until = (LLTimer::getElapsedSeconds() + 2).value(); - while (childin.size() && LLTimer::getElapsedSeconds() < until) + LLTimer waited; + while (childin.size() && waited.getElapsedTimeF64() < 2.0) { mainloop.post(nop); } diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 58de61a7e4..526aebd89e 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -161,30 +161,16 @@ std::string LLLiveFile::filename() const return impl.mFilename; } -namespace -{ - class LiveFileEventTimer : public LLEventTimer - { - public: - LiveFileEventTimer(LLLiveFile& f, F32 refresh) - : LLEventTimer(refresh), mLiveFile(f) - { } - - bool tick() - { - mLiveFile.checkAndReload(); - return false; - } - - private: - LLLiveFile& mLiveFile; - }; - -} - void LLLiveFile::addToEventTimer() { - impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod); + // The event timer keeps the refresh period itself, so each tick checks. + // Asking the frame-quantised gate again could find a frame less than a + // period since the last check and skip one, doubling the period. + impl.mEventTimer = LLEventTimer::run_every(impl.mRefreshPeriod, [this]() + { + impl.mForceCheck = true; + checkAndReload(); + }); } void LLLiveFile::setRefreshPeriod(F32 seconds) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index d8893c2526..869af9e57b 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -66,8 +66,9 @@ class LL_COMMON_API LLTimer static void cleanupClass(); // Return a high precision number of seconds since the start of - // this application instance. - static F64SecondsImplicit getElapsedSeconds() + // this application instance. Static: it is not this timer's elapsed + // time, which is getElapsedTimeF64(). + static F64SecondsImplicit getUptimeSeconds() { if (sTimer) { @@ -91,7 +92,8 @@ class LL_COMMON_API LLTimer void stop() { mStarted = false; } void reset(); // Resets the timer void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time - void setTimerExpirySec(F32SecondsImplicit expiration); + void setTimerExpirySec(F32SecondsImplicit expiration); // Expires this long from now + void resetWithExpiry(F32SecondsImplicit expiration) { reset(); setTimerExpirySec(expiration); } bool checkExpirationAndReset(F32 expiration); bool hasExpired() const; F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp index b9a8c91abf..2af7be4fe5 100644 --- a/indra/llcommon/tests/llframetimer_test.cpp +++ b/indra/llcommon/tests/llframetimer_test.cpp @@ -112,10 +112,65 @@ namespace tut ensure("timer took too long to expire", iterations_until_expiration <= 10); } -/* template<> template<> void frametimer_object_t::test<4>() { + set_test_name("an expiry counts from now, not from the timer's last reset"); + LLFrameTimer timer; + // Longer than the expiry passes between the timer starting and the + // expiry being set. + ms_sleep(300); + LLFrameTimer::updateFrameTime(); + timer.setTimerExpirySec(0.2f); + ensure("not expired the moment it is set", !timer.hasExpired()); + ensure("the whole expiry still to run", timer.getTimeToExpireF32() > 0.19f); + } + + template<> template<> + void frametimer_object_t::test<5>() + { + set_test_name("a stopped timer keeps the time it ran, and resumes from it"); + // Far enough from the start of the run that the absolute start time + // cannot pass for the time run. + ms_sleep(300); + LLFrameTimer::updateFrameTime(); + LLFrameTimer timer; + timer.start(); + ms_sleep(200); + LLFrameTimer::updateFrameTime(); + const F32 ran = timer.getElapsedTimeF32(); + timer.stop(); + ensure("stopped", !timer.getStarted()); + ensure_approximately_equals("the time it ran", timer.getElapsedTimeF32(), ran, 12); + ms_sleep(100); + LLFrameTimer::updateFrameTime(); + ensure_approximately_equals("not running while stopped", timer.getElapsedTimeF32(), ran, 12); + timer.unpause(); + ensure_approximately_equals("resumed from where it stopped", timer.getElapsedTimeF32(), ran, 12); + } + + template<> template<> + void frametimer_object_t::test<6>() + { + set_test_name("a reset while paused zeroes the time run and leaves it paused"); + ms_sleep(300); + LLFrameTimer::updateFrameTime(); + LLFrameTimer timer; + timer.start(); + ms_sleep(100); + LLFrameTimer::updateFrameTime(); + timer.pause(); + timer.reset(); + ensure("still paused", !timer.getStarted()); + ensure_approximately_equals("no time run", timer.getElapsedTimeF32(), 0.f, 12); + ms_sleep(100); + LLFrameTimer::updateFrameTime(); + ensure_approximately_equals("not running while paused", timer.getElapsedTimeF32(), 0.f, 12); + timer.unpause(); + ensure_approximately_equals("runs on from zero", timer.getElapsedTimeF32(), 0.f, 12); + timer.pause(); + timer.start(); + ensure("started", timer.getStarted()); + ensure_approximately_equals("start() runs from zero, paused or not", timer.getElapsedTimeF32(), 0.f, 12); } -*/ } diff --git a/indra/llcommon/tests/lltimer_test.cpp b/indra/llcommon/tests/lltimer_test.cpp new file mode 100644 index 0000000000..3af0abd405 --- /dev/null +++ b/indra/llcommon/tests/lltimer_test.cpp @@ -0,0 +1,85 @@ +/** + * @file lltimer_test.cpp + * @brief When an LLTimer's expiry is, and what resets it. + * + * $LicenseInfo:firstyear=2026&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2026, Rye + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../lltimer.h" + +#include "../test/lltut.h" + +namespace tut +{ + struct timer_data + { + // The global timer behind the uptime; an application makes it in + // LLCommon::initClass, which the test runner does not call. + timer_data() { LLTimer::initClass(); } + }; + typedef test_group timer_group; + typedef timer_group::object timer_object; + tut::timer_group timer_instance("LLTimer"); + + template<> template<> + void timer_object::test<1>() + { + set_test_name("a new timer reads expired until it is given an expiry"); + LLTimer timer; + ensure("expired", timer.hasExpired()); + timer.setTimerExpirySec(10.f); + ensure("not expired once given ten seconds", !timer.hasExpired()); + } + + template<> template<> + void timer_object::test<2>() + { + set_test_name("resetWithExpiry restarts the timer and keeps the expiry"); + LLTimer timer; + ms_sleep(50); + timer.resetWithExpiry(10.f); + ensure("not expired", !timer.hasExpired()); + ensure("the whole expiry to run", timer.getRemainingTimeF32() > 9.9f); + ensure("restarted", timer.getElapsedTimeF32() < 0.04f); + } + + template<> template<> + void timer_object::test<3>() + { + set_test_name("start() after an expiry clears it, which is why resetWithExpiry exists"); + LLTimer timer; + timer.setTimerExpirySec(10.f); + timer.start(); + ensure("start() cleared the expiry", timer.hasExpired()); + } + + template<> template<> + void timer_object::test<4>() + { + set_test_name("the uptime is the application's, not this timer's"); + LLTimer timer; + ms_sleep(50); + timer.reset(); + ensure("the timer was just reset", timer.getElapsedTimeF64() < 0.04); + ensure("the uptime runs from before the reset", LLTimer::getUptimeSeconds() > timer.getElapsedTimeF64()); + } +} diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index 694896fb80..645c41371e 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -1276,6 +1276,7 @@ void LLCircuitData::pingTimerStop(const U8 ping_id) // Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise // all of our ping calculations will be skewed. mt_secs = LLMessageSystem::getMessageTimeSeconds(true); + time = mt_secs - mPingTime; } mLastPingReceivedTime = mt_secs; diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 07d11932bc..77eebbe930 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -267,8 +267,6 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap if (!status) { - F64 now = LLFrameTimer::getTotalSeconds(); - LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; // build dummy entries for the failed requests for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) @@ -279,7 +277,8 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap { exp[PROPERTIES] = PROPERTY_INVALID; } - exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); + // A delta, as the server sends it: processExperience adds the time. + exp[EXPIRES] = LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); exp[EXPERIENCE_ID] = *it; exp["key_type"] = EXPERIENCE_ID; exp["uuid"] = *it; diff --git a/indra/llui/altextview.cpp b/indra/llui/altextview.cpp index 1e03b6daf2..5c53095138 100644 --- a/indra/llui/altextview.cpp +++ b/indra/llui/altextview.cpp @@ -2313,7 +2313,7 @@ ALTextDocument::Edit ALTextView::edit(const ALTextRange& range_in, std::string_v return done; } const ALTextPos after = mDocument.clamp(done.endAfter()); - mUndo.record(done, before, after, LLTimer::getElapsedSeconds(), std::move(others)); + mUndo.record(done, before, after, LLTimer::getUptimeSeconds(), std::move(others)); placeCaret(after, false); return done; } @@ -2340,7 +2340,7 @@ ALTextDocument::Edit ALTextView::editMany(std::vector template<> + void altextview_object::test<78>() + { + set_test_name("a third press where a double click took a word takes the line, however long the view has been open"); + ALTextView& v = make("hello world\nsecond"); + // Longer than the triple-click window passes between the view being + // made and the first click. + ms_sleep(400); + LLFrameTimer::updateFrameTime(); + S32 x, y; + pointOf(0, 8, x, y); + v.handleMouseDown(x, y, MASK_NONE); + v.handleMouseUp(x, y, MASK_NONE); + ensure("double", v.handleDoubleClick(x, y, MASK_NONE)); + ensure_equals("the word", v.selectedText(), std::string("world")); + v.handleMouseUp(x, y, MASK_NONE); + ensure("third", v.handleMouseDown(x, y, MASK_NONE)); + ensure("the line", v.selection().normalised() == ALTextRange(ALTextPos(0, 0), ALTextPos(1, 0))); + v.handleMouseUp(x, y, MASK_NONE); + } } diff --git a/indra/newview/alfloaterexploresounds.cpp b/indra/newview/alfloaterexploresounds.cpp index be4a9a07fb..f607c4e345 100644 --- a/indra/newview/alfloaterexploresounds.cpp +++ b/indra/newview/alfloaterexploresounds.cpp @@ -267,7 +267,7 @@ bool ALFloaterExploreSounds::tick() else { LLStringUtil::format_map_t format_args; - format_args["TIME"] = llformat("%.1f", static_cast((LLTimer::getElapsedSeconds() - item.mTimeStopped) / 60.0)); + format_args["TIME"] = llformat("%.1f", static_cast((LLTimer::getUptimeSeconds() - item.mTimeStopped) / 60.0)); str_not_playing.setArgs(format_args); playing_column["value"] = str_not_playing.getString(); } @@ -450,7 +450,7 @@ void ALFloaterExploreSounds::handleStop() if (iter != sound_log.end()) { iter->second->mPlaying = false; - iter->second->mTimeStopped = LLTimer::getElapsedSeconds(); + iter->second->mTimeStopped = LLTimer::getUptimeSeconds(); } else { @@ -459,7 +459,7 @@ void ALFloaterExploreSounds::handleStop() if (histItem.mID == item.mID) { histItem.mPlaying = false; - histItem.mTimeStopped = LLTimer::getElapsedSeconds(); + histItem.mTimeStopped = LLTimer::getUptimeSeconds(); break; } } diff --git a/indra/newview/alfloaterlightbox.cpp b/indra/newview/alfloaterlightbox.cpp index e792578ec1..685d45d956 100644 --- a/indra/newview/alfloaterlightbox.cpp +++ b/indra/newview/alfloaterlightbox.cpp @@ -1017,7 +1017,7 @@ void ALFloaterLightBox::endColorSession(bool escaped) if (mRecordedKeys.count(key) && !llsd_equals(picked, mColorOriginal)) { ScopedHistoryGroup group(mHistory); - mHistory.record(key, mColorOriginal, picked, (F32)LLTimer::getElapsedSeconds().value()); + mHistory.record(key, mColorOriginal, picked, (F32)LLTimer::getUptimeSeconds().value()); } } @@ -1693,7 +1693,7 @@ void ALFloaterLightBox::onGradeSettingChanged(const std::string& name, const LLS // A monotonic clock is all the history wants: it compares two of these to // decide whether one drag is still in progress, and never reads the value // on its own. - mHistory.record(name, before, after, (F32)LLTimer::getElapsedSeconds().value()); + mHistory.record(name, before, after, (F32)LLTimer::getUptimeSeconds().value()); } bool ALFloaterLightBox::applyHistory(bool redo_direction) diff --git a/indra/newview/alfloaterregiontracker.cpp b/indra/newview/alfloaterregiontracker.cpp index 1045678c99..d541de99fd 100644 --- a/indra/newview/alfloaterregiontracker.cpp +++ b/indra/newview/alfloaterregiontracker.cpp @@ -135,7 +135,7 @@ void ALFloaterRegionTracker::refresh() { maturity.value(info->getAccessIcon()); - info->updateAgentCount(LLTimer::getElapsedSeconds()); + info->updateAgentCount(LLTimer::getUptimeSeconds()); S32 agent_count = info->getAgentCount(); if (info->isDown()) { @@ -190,7 +190,7 @@ void ALFloaterRegionTracker::requestRegionData() const auto& name = it->first; if (LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromName(name)) { - info->updateAgentCount(LLTimer::getElapsedSeconds()); + info->updateAgentCount(LLTimer::getUptimeSeconds()); } else { diff --git a/indra/newview/alfloaterxuistudio.cpp b/indra/newview/alfloaterxuistudio.cpp index 08b5fe0b0e..5311359a97 100644 --- a/indra/newview/alfloaterxuistudio.cpp +++ b/indra/newview/alfloaterxuistudio.cpp @@ -4090,6 +4090,7 @@ void ALFloaterXUIStudio::documentRead(const std::string& status) fillHistory(); setStatus(status); mRereadPending = true; + mRereadAt.reset(); mRereadAt.setTimerExpirySec(REREAD_SECONDS); } diff --git a/indra/newview/fsjointpose.cpp b/indra/newview/fsjointpose.cpp index 449317b3b9..70a6c39c48 100644 --- a/indra/newview/fsjointpose.cpp +++ b/indra/newview/fsjointpose.cpp @@ -107,7 +107,7 @@ void FSJointPose::addStateToUndo(const FSJointState& stateToAddToUndo) { mModifiedThisSession = true; - auto now = std::chrono::system_clock::now(); + auto now = std::chrono::steady_clock::now(); auto timeIntervalSinceLastChange = now - mTimeLastUpdatedCurrentState; mTimeLastUpdatedCurrentState = now; diff --git a/indra/newview/fsjointpose.h b/indra/newview/fsjointpose.h index 42cec2abed..d54b78cbd1 100644 --- a/indra/newview/fsjointpose.h +++ b/indra/newview/fsjointpose.h @@ -487,7 +487,7 @@ class FSJointPose std::deque mLastSetJointStates; size_t mUndoneJointStatesIndex = 0; - std::chrono::system_clock::time_point mTimeLastUpdatedCurrentState = std::chrono::system_clock::now(); + std::chrono::steady_clock::time_point mTimeLastUpdatedCurrentState = std::chrono::steady_clock::now(); FSJointState mCurrentState; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index a921f6ccb7..b5226eebcc 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3622,7 +3622,7 @@ LLColor4 LLAgent::getEffectColor() if(AlchemyRainbowEffects) { LLColor3 rainbow; - rainbow.setHSL(fmodf((F32)LLFrameTimer::getElapsedSeconds()/4.f, 1.f), 1.f, 0.5f); + rainbow.setHSL(fmodf((F32)LLFrameTimer::getUptimeSeconds()/4.f, 1.f), 1.f, 0.5f); effect_color.set(rainbow, 1.0f); } return effect_color; diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 25b0dbc550..d56698a836 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1074,14 +1074,14 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& && type != AISAPI::UPDATEITEM && type != AISAPI::FETCHCOF && type != AISAPI::FETCHCATEGORYLINKS; - mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS); mTaskTimer.start(); + mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS); U32 current_frame = LLFrameTimer::getFrameCount(); if (sBatchFrameCount != current_frame) { - sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS); sBatchTimer.start(); + sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS); sBatchFrameCount = current_frame; } parseUpdate(update); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a504e3ab34..310e629cbf 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -649,7 +649,7 @@ LLPurgeDiskCacheThread* LLAppViewer::sPurgeDiskCacheThread = NULL; std::string getRuntime() { - return llformat("%.4f", (F32)LLTimer::getElapsedSeconds().value()); + return llformat("%.4f", (F32)LLTimer::getUptimeSeconds().value()); } LLAppViewer::LLAppViewer() @@ -6539,7 +6539,7 @@ void LLAppViewer::forceErrorInfiniteLoop() { if (timer_expiry.hasExpired()) { - LL_INFOS() << "Infinite loop time : " << timer_total.getElapsedSeconds() << LL_ENDL; + LL_INFOS() << "Infinite loop time : " << timer_total.getElapsedTimeF64() << LL_ENDL; timer_expiry.setTimerExpirySec(report_frequency); } } diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index dfa5979e03..c70ecaa591 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -751,9 +751,9 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva if (it == mRequestTimestamps.end()) return false; // We found a request, check if it has timed out - U32 now = (U32)time(nullptr); - const U32 REQUEST_EXPIRE_SECS = 5; - U32 expires = it->second + REQUEST_EXPIRE_SECS; + F64 now = LLFrameTimer::getUptimeSeconds(); + const F64 REQUEST_EXPIRE_SECS = 5.0; + F64 expires = it->second + REQUEST_EXPIRE_SECS; // Request is still pending if it hasn't expired yet // *NOTE: Expired requests will accumulate in this map, but they are rare, @@ -765,9 +765,8 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) { timestamp_map_t::key_type key = std::make_pair(avatar_id, type); - U32 now = (U32)time(nullptr); // Add or update existing (expired) request - mRequestTimestamps[ key ] = now; + mRequestTimestamps[ key ] = LLFrameTimer::getUptimeSeconds(); } void LLAvatarPropertiesProcessor::removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index fb9ae0df62..d877b1663d 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -357,7 +357,7 @@ class LLAvatarPropertiesProcessor // Maintain a timestamp for each request so a request that receives no reply // does not block future requests forever. // Map avatar_id+request_type -> U32 timestamp in seconds - typedef std::map< std::pair, U32> timestamp_map_t; + typedef std::map< std::pair, F64> timestamp_map_t; timestamp_map_t mRequestTimestamps; // Is returned by isHideAgeSupportedByServer() diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7c33a9258b..ed59c18a73 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -201,7 +201,7 @@ class LLChatHistoryHeader final: public LLPanel if (mTime > 0) // have frame time { time_t current_time = time_corrected(); - time_t message_time = (time_t)(current_time - LLFrameTimer::getElapsedSeconds() + mTime); + time_t message_time = (time_t)(current_time - LLFrameTimer::getUptimeSeconds() + mTime); // Report abuse shouldn't use AM/PM, use 24-hour time time_string = "[" + LLTrans::getString("TimeMonth") + "]/[" @@ -503,7 +503,7 @@ class LLChatHistoryHeader final: public LLPanel if (mTime > 0) // have frame time { time_t current_time = time_corrected(); - time_t message_time = (time_t)(current_time - LLFrameTimer::getElapsedSeconds() + mTime); + time_t message_time = (time_t)(current_time - LLFrameTimer::getUptimeSeconds() + mTime); // Report abuse shouldn't use AM/PM, use 24-hour time time_string = "[" + LLTrans::getString("TimeMonth") + "]/[" diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 4038ae8002..20f930300a 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -153,7 +153,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, { break; } - cur_time = LLTimer::getElapsedSeconds(); + cur_time = LLTimer::getUptimeSeconds(); if (cur_time < last_throttle_time + THROTTLE_PERIOD) { // block request from external browser if it happened diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index bfcc2e4182..210f925566 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -142,6 +142,12 @@ const std::string LLConversation::createTimestamp(const U64Seconds& utc_time) bool LLConversation::isOlderThan(U32Days days) const { U64Seconds now(time_corrected()); + if (mTime >= now) + { + // Stamped ahead of this clock, so no age at all; the unsigned + // difference would make it the oldest there is. + return false; + } U32Days age = now - mTime; return age > days; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 5d93c07f42..8111818662 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -422,7 +422,7 @@ void LLConversationItemSession::setParticipantIsModerator(const LLUUID& particip void LLConversationItemSession::setTimeNow(const LLUUID& participant_id) { - mLastActiveTime = LLFrameTimer::getElapsedSeconds(); + mLastActiveTime = LLFrameTimer::getUptimeSeconds(); mNeedsRefresh = true; LLConversationItemParticipant* participant = findParticipant(participant_id); if (participant) diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 93598083c0..234b1a2852 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -205,7 +205,7 @@ class LLConversationItemParticipant : public LLConversationItem bool isModerator() const { return mIsModerator; } void moderateVoice(bool mute_voice) { mIsModeratorMuted = mute_voice; } void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } - void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } + void setTimeNow() { mLastActiveTime = LLFrameTimer::getUptimeSeconds(); mNeedsRefresh = true; } void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } void buildContextMenu(LLMenuGL& menu, U32 flags); diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index 91ea36706e..83173b9706 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -272,7 +272,7 @@ void LLDebugVarMessageBox::draw() { if (mSlider1) { - F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); + F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getUptimeSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); mSlider1->setValue(animated_val); sliderChanged(LLSD()); if (mSlider2) diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index fbd04b5f81..006f27c4a2 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -274,10 +274,10 @@ bool LLDirPicker::getDir(std::string* filename, bool blocking) if (blocking) { send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); } - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); return success; } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 6aa6e81b93..ea2f33b846 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -172,7 +172,7 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) has_normal_mips ? ALSamplers::AnisoWrap : ALSamplers::PointWrap; LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); - F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; + F32 phase_time = (F32) LLFrameTimer::getUptimeSeconds() * 0.5f; LLGLSLShader *shader = nullptr; // One pass, one of two shaders. Void water and region water share state. diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 0b3c89dae9..6e924d3626 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -264,7 +264,7 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const // typical session never hits the wrap boundary (where the non-periodic // noise would show a one-frame jump), and short enough that 32-bit float // precision stays good for the scaled time term in the shader. - sStarTime = (F32)fmod(LLFrameTimer::getElapsedSeconds() * 0.5, 86400.0); + sStarTime = (F32)fmod(LLFrameTimer::getUptimeSeconds() * 0.5, 86400.0); gDeferredStarProgram.uniform1f(LLShaderMgr::WATER_TIME, sStarTime); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index c72e6d09c7..14e4472262 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -278,7 +278,7 @@ namespace LLSettingsBase::Seconds getAdjustedNow() const { - LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch()); + LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch() + gUTCOffset); return (now + mCycleOffset); } @@ -2924,7 +2924,8 @@ void LLEnvironment::DayInstance::setBlenders(const LLSettingsBlender::ptr_t &sky LLSettingsBase::TrackPosition LLEnvironment::DayInstance::getProgress() const { - LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch()); + // The region's day runs on the server's clock, not this machine's. + LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch() + gUTCOffset); now += mDayOffset; if ((mDayLength <= 0) || !mDayCycle) @@ -2940,7 +2941,7 @@ LLSettingsBase::TrackPosition LLEnvironment::DayInstance::secondsToKeyframe(LLSe void LLEnvironment::DayInstance::animate() { - LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch()); + LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch() + gUTCOffset); now += mDayOffset; diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 02bfd0045a..fdd1b5a37b 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -134,7 +134,7 @@ void LLEventNotifier::update() // Check our notifications again and send out updates // if they happen. - F64 alert_time = LLDate::now().secondsSinceEpoch() + 5 * 60; + F64 alert_time = (F64)time_corrected() + 5 * 60; en_map::iterator iter; for (iter = mEventNotifications.begin(); iter != mEventNotifications.end();) diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 836ff63429..09c99b319b 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -208,12 +208,12 @@ namespace Details || status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE) || status == LLCore::HttpStatus(HTTP_GATEWAY_TIME_OUT)) { - if (message_time.getElapsedSeconds() < MIN_SECONDS_PASSED) + if (message_time.getElapsedTimeF64() < MIN_SECONDS_PASSED) { // Server is supposed to hold request for 20 to 30 seconds. // If it didn't hold the request at least for 10s, treat as an error. LL_WARNS("LLEventPollImpl") << "Response arrived too early, status: " << status.toTerseString() - << ", time passed: " << message_time.getElapsedSeconds() << LL_ENDL; + << ", time passed: " << message_time.getElapsedTimeF64() << LL_ENDL; } else { diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index d270364a45..f304c8c8d2 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -784,10 +784,10 @@ bool LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking) if (blocking) { send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); } - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); return success; } @@ -1040,16 +1040,18 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, { LOG_UNHANDLED_EXCEPTION(""); } - gKeyboard->resetKeys(); } if (blocking) { + // Only here on the main thread: threaded, the keyboard belongs to the + // main thread, and the dialog taking focus has already reset it there. + gKeyboard->resetKeys(); send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); } - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); return success; } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index d9d5768faf..15576808ae 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -94,7 +94,7 @@ void LLVolumeImplFlexible::updateClass() { LL_PROFILE_ZONE_SCOPED; - U64 virtual_frame_num = (U64)(LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME); + U64 virtual_frame_num = (U64)(LLTimer::getUptimeSeconds() / SEC_PER_FLEXI_FRAME); for (std::vector::iterator iter = sInstanceList.begin(); iter != sInstanceList.end(); ++iter) @@ -362,7 +362,7 @@ void LLVolumeImplFlexible::doIdleUpdate() update_period = llclamp(update_period, 1U, 32U); // We control how fast flexies update, buy splitting updates among frames - U64 virtual_frame_num = (U64)(LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME); + U64 virtual_frame_num = (U64)(LLTimer::getUptimeSeconds() / SEC_PER_FLEXI_FRAME); if (visible) { diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index f994d0e0f2..2493c21664 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -396,11 +396,10 @@ void LLFloaterAvatarPicker::draw() static LLFrameTimer timer; if (timer.hasExpired()) { - timer.setTimerExpirySec(0.33f); // three times per second should be enough. + timer.resetWithExpiry(0.33f); // three times per second should be enough. // simulate list changes. onList(); - timer.start(); } LLFloater::draw(); diff --git a/indra/newview/llfloaterbanduration.cpp b/indra/newview/llfloaterbanduration.cpp index eb32e50901..fb94419545 100644 --- a/indra/newview/llfloaterbanduration.cpp +++ b/indra/newview/llfloaterbanduration.cpp @@ -82,7 +82,7 @@ void LLFloaterBanDuration::onClickBan() LLSpinCtrl* hours_spin = getChild("ban_hours"); if (hours_spin) { - time = (S32)(LLDate::now().secondsSinceEpoch() + (hours_spin->getValue().asInteger() * 3600)); + time = (S32)(time_corrected() + (hours_spin->getValue().asInteger() * 3600)); } } mSelectionCallback(mAvatar_ids, time); diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp index a07b50323b..0e5274768b 100644 --- a/indra/newview/llfloaterdisplayname.cpp +++ b/indra/newview/llfloaterdisplayname.cpp @@ -73,7 +73,7 @@ void LLFloaterDisplayName::onOpen(const LLSD& key) LLAvatarName av_name; LLAvatarNameCache::get(gAgent.getID(), &av_name); - F64 now_secs = LLDate::now().secondsSinceEpoch(); + F64 now_secs = (F64)time_corrected(); mIsLockedOut = now_secs < av_name.mNextUpdate; if (mIsLockedOut) { diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp index b15a32ce40..36df6a3a8c 100644 --- a/indra/newview/llfloaterimnearbychatlistener.cpp +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -52,7 +52,7 @@ LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener() : // "sendChat" command void LLFloaterIMNearbyChatListener::sendChat(LLSD const& chat_data) { - F64 cur_time = LLTimer::getElapsedSeconds(); + F64 cur_time = LLTimer::getUptimeSeconds(); if (cur_time < mLastThrottleTime + CHAT_THROTTLE_PERIOD) { diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 3d1c36a500..ee303ed728 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2500,7 +2500,7 @@ void LLPanelLandAccess::refresh() if (entry.mTime != 0) { LLStringUtil::format_map_t args; - S32 now = (S32)time(NULL); + S32 now = (S32)time_corrected(); S32 seconds = entry.mTime - now; if (seconds < 0) seconds = 0; prefix.assign(" ("); @@ -2549,7 +2549,7 @@ void LLPanelLandAccess::refresh() if (entry.mTime != 0) { LLStringUtil::format_map_t args; - S32 now = (S32)time(NULL); + S32 now = (S32)time_corrected(); seconds = entry.mTime - now; if (seconds < 0) seconds = 0; @@ -3063,7 +3063,7 @@ void LLPanelLandCovenant::refresh() } if (mLastRegionID != region->getRegionID() - || mNextUpdateTime < LLTimer::getElapsedSeconds()) + || mNextUpdateTime < LLTimer::getUptimeSeconds()) { // Request Covenant Info // Note: LLPanelLandCovenant doesn't change Covenant's content and any @@ -3076,7 +3076,7 @@ void LLPanelLandCovenant::refresh() msg->sendReliable(region->getHost()); mLastRegionID = region->getRegionID(); - mNextUpdateTime = LLTimer::getElapsedSeconds() + COVENANT_REFRESH_TIME_SEC; + mNextUpdateTime = LLTimer::getUptimeSeconds() + COVENANT_REFRESH_TIME_SEC; } } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 44208ba930..e1c2217fc3 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -641,7 +641,7 @@ void LLFloaterWorldMap::draw() { if (mCompletingRegionName != "") { - F64 seconds = LLTimer::getElapsedSeconds(); + F64 seconds = LLTimer::getUptimeSeconds(); double value = fmod(seconds, 2); value = 0.5 + 0.5*cos(value * F_PI); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index e363c9118e..becf7b56bd 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -229,7 +229,7 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : mRoleMemberDataComplete(false), mGroupPropertiesDataComplete(false), mPendingRoleMemberRequest(false), - mAccessTime(0.0f), + mAccessTime(0.0), mPendingBanRequest(false) { mMemberVersion.generate(); @@ -237,7 +237,7 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : void LLGroupMgrGroupData::setAccessed() { - mAccessTime = (F32)LLFrameTimer::getTotalSeconds(); + mAccessTime = LLFrameTimer::getTotalSeconds(); } bool LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_data) @@ -1555,7 +1555,7 @@ void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap) { // LRU: Remove the oldest un-observed group from cache until group size is small enough - F32 oldest_access = (F32)LLFrameTimer::getTotalSeconds(); + F64 oldest_access = LLFrameTimer::getTotalSeconds(); group_map_t::iterator oldest_gi = mGroups.end(); for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi ) diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 21cf4a62b6..b34edda513 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -265,7 +265,7 @@ friend class LLGroupMgr; bool isSingleMemberNotOwner(); - F32 getAccessTime() const { return mAccessTime; } + F64 getAccessTime() const { return mAccessTime; } void setAccessed(); const LLUUID& getMemberVersion() const { return mMemberVersion; } @@ -329,7 +329,7 @@ friend class LLGroupMgr; bool mGroupPropertiesDataComplete; bool mPendingRoleMemberRequest; - F32 mAccessTime; + F64 mAccessTime; // Generate a new ID every time mMembers LLUUID mMemberVersion; diff --git a/indra/newview/llhexeditor.cpp b/indra/newview/llhexeditor.cpp index 64ee84b5b7..181df954ac 100644 --- a/indra/newview/llhexeditor.cpp +++ b/indra/newview/llhexeditor.cpp @@ -908,7 +908,7 @@ void LLHexEditor::draw() // Cursor - if(has_focus && !mHasSelection && (U32(LLTimer::getElapsedSeconds() * 2.0f) & 0x1)) + if(has_focus && !mHasSelection && (U32(LLTimer::getUptimeSeconds() * 2.0f) & 0x1)) { U32 cursor_line = mCursorPos / mColumns; if((cursor_line >= first_line) && (cursor_line <= last_line)) diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp index bfef4860c4..7feec774eb 100644 --- a/indra/newview/llinspect.cpp +++ b/indra/newview/llinspect.cpp @@ -122,7 +122,12 @@ bool LLInspect::handleToolTip(S32 x, S32 y, MASK mask) // virtual void LLInspect::onMouseLeave(S32 x, S32 y, MASK mask) { - mOpenTimer.unpause(); + // Once focus is lost the open timer is stopped, not paused, and the + // fade has begun; unpausing it would restart the fade. + if (!mCloseTimer.getStarted()) + { + mOpenTimer.unpause(); + } } bool LLInspect::childHasVisiblePopupMenu() diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 4bcf754c9c..e2ca41010e 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -140,7 +140,7 @@ class LLLogChatTimeScanner: public LLSingleton { typedef boost::date_time::local_adjustor pst; typedef boost::date_time::local_adjustor pdt; - time_t t_time = time(NULL); + time_t t_time = time_corrected(); ptime p_time = LLStringOps::getPacificDaylightTime() ? pdt::utc_to_local(from_time_t(t_time)) : pst::utc_to_local(from_time_t(t_time)); diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp index 831ad7827a..74dab9dca7 100644 --- a/indra/newview/llpanelenvironment.cpp +++ b/indra/newview/llpanelenvironment.cpp @@ -932,7 +932,7 @@ void LLPanelEnvironmentInfo::udpateApparentTimeOfDay() } mLabelApparentTime->setVisible(true); - S32Seconds now((S32)LLDate::now().secondsSinceEpoch()); + S32Seconds now((S32)time_corrected()); now += mCurrentEnvironment->mDayOffset; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 6800fe462e..012703d9b3 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -222,8 +222,8 @@ class LLAvatarItemRecentArrivalComparator : public LLAvatarItemNameComparator virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const { - F32 arr_time1 = LLRecentPeople::instance().getArrivalTimeByID(item1->getAvatarId()); - F32 arr_time2 = LLRecentPeople::instance().getArrivalTimeByID(item2->getAvatarId()); + F64 arr_time1 = LLRecentPeople::instance().getArrivalTimeByID(item1->getAvatarId()); + F64 arr_time2 = LLRecentPeople::instance().getArrivalTimeByID(item2->getAvatarId()); if (arr_time1 == arr_time2) { diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 5dbd86a4b6..7addc44792 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -342,7 +342,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, return; if (mLastSelectedRegionID != region->getRegionID() - || mNextCovenantUpdateTime < LLTimer::getElapsedSeconds()) + || mNextCovenantUpdateTime < LLTimer::getUptimeSeconds()) { // send EstateCovenantInfo message // Note: LLPanelPlaceProfile doesn't change Covenant's content and any @@ -353,7 +353,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); msg->sendReliable(region->getHost()); - mNextCovenantUpdateTime = LLTimer::getElapsedSeconds() + COVENANT_REFRESH_TIME_SEC; + mNextCovenantUpdateTime = LLTimer::getUptimeSeconds() + COVENANT_REFRESH_TIME_SEC; } LLParcelData parcel_data; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index d0ea3af03b..1d4f1ae1b0 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1676,7 +1676,7 @@ void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " << LLDate(av_name.mNextUpdate) << LL_ENDL; - F64 now_secs = LLDate::now().secondsSinceEpoch(); + F64 now_secs = (F64)time_corrected(); if (now_secs < av_name.mNextUpdate) { diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp index d3599e00a8..f8e73367c2 100644 --- a/indra/newview/llrecentpeople.cpp +++ b/indra/newview/llrecentpeople.cpp @@ -126,15 +126,15 @@ void LLRecentPeople::updateAvatarsArrivalTime(uuid_vec_t& uuids) } } -F32 LLRecentPeople::getArrivalTimeByID(const LLUUID& id) +F64 LLRecentPeople::getArrivalTimeByID(const LLUUID& id) { id_to_time_map_t::const_iterator it = mAvatarsArrivalTime.find(id); if (it != mAvatarsArrivalTime.end()) { - return (F32)(it->second); + return it->second; } - return (F32)LLDate::now().secondsSinceEpoch(); + return LLDate::now().secondsSinceEpoch(); } bool LLRecentPeople::save() const diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index 2a41a56306..3db7c208ec 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -125,7 +125,7 @@ class LLRecentPeople final : public LLSingleton, public LLOldEve void clearHistory(); void updateAvatarsArrivalTime(uuid_vec_t& uuids); - F32 getArrivalTimeByID(const LLUUID& id); + F64 getArrivalTimeByID(const LLUUID& id); private: diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 11dd05bcf0..a8a9f147d6 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -213,6 +213,13 @@ void LLReflectionMap::syncToViewerObject() } } +void LLReflectionMap::orphan() +{ + mGroup = nullptr; + mViewerObject = nullptr; + mOrphaned = true; +} + bool LLReflectionMap::eclipses(const LLReflectionMap* other, F32 margin) const { if (!other || other == this || !mViewerObject || mViewerObject->isDead()) @@ -383,6 +390,11 @@ bool LLReflectionMap::isRelevant() const { static LLCachedControl RenderReflectionProbeLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + if (mOrphaned) + { // whatever it was registered for is gone; the manager deletes it on its next update + return false; + } + if (mViewerObject && RenderReflectionProbeLevel > 0) { // not an automatic probe return true; diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 3c20a23207..6e7b50b8da 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -70,6 +70,11 @@ class alignas(16) LLReflectionMap : public LLRefCount // sort order and influence volumes from these two values. void syncToViewerObject(); + // Called by the spatial group, viewer object or region this probe was registered for when it + // lets go of the probe. Clears any pointer back to it, and takes the probe out of relevance for + // the time the manager keeps it before deleting it. + void orphan(); + // True if this probe's influence volume has moved or resized enough since its neighbour // list was built that the list may no longer describe it. bool neighborsAreStale() const; @@ -125,6 +130,11 @@ class alignas(16) LLReflectionMap : public LLRefCount // longer affect any pixel (maintained by LLReflectionMapManager, consulted by isRelevant) bool mInsideManualProbe = false; + // whatever registered this probe has let go of it (see orphan). Without this a probe with + // neither a group nor a viewer object is indistinguishable from a live terrain probe, and + // would be treated as one until the manager deletes it. + bool mOrphaned = false; + // fade in parameter for this probe F32 mFadeIn = 0.f; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 5bde77948c..7ec2e97695 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -401,6 +401,15 @@ void LLReflectionMapManager::update() LLReflectionMap* oldestProbe = nullptr; LLReflectionMap* oldestOccluded = nullptr; + // A probe that stopped being relevant partway through its twelve passes is dropped rather than + // finished, by the same rule the scheduling loop below uses to skip one. Every remaining pass + // renders the whole scene for a probe that is about to lose its cube slot in the release pass, + // or, when whatever registered it is gone, to be deleted outright. + if (mUpdatingProbe != nullptr && mUpdatingProbe != mDefaultProbe && !mUpdatingProbe->isRelevant()) + { + abandonProbeUpdate(); + } + if (mUpdatingProbe != nullptr) { did_update = true; @@ -911,8 +920,7 @@ void LLReflectionMapManager::deleteProbe(U32 i) } if (mUpdatingProbe == probe) { - mUpdatingProbe = nullptr; - mUpdatingFace = 0; + abandonProbeUpdate(); } // remove from any Neighbors lists @@ -927,6 +935,18 @@ void LLReflectionMapManager::deleteProbe(U32 i) mProbes.erase(mProbes.begin() + i); } +void LLReflectionMapManager::abandonProbeUpdate() +{ + mUpdatingProbe = nullptr; + mUpdatingFace = 0; + + // The irradiance half runs first and the radiance half is what marks a probe complete. Left + // set, this would start the next probe on its radiance half: it would skip the irradiance + // projection altogether and be marked complete on whatever SH coefficients its slot's + // previous owner left behind. + mRadiancePass = false; +} + void LLReflectionMapManager::doProbeUpdate() { diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index bb5627ef20..85719d9b94 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -194,6 +194,9 @@ class alignas(16) LLReflectionMapManager // delete the probe with the given index in mProbes void deleteProbe(U32 i); + // stop generating mUpdatingProbe partway through, so the next probe starts from its first pass + void abandonProbeUpdate(); + // get a free cube index // returns -1 if allocation failed S32 allocateCubeIndex(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index db6dd78c29..665a607106 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -7601,7 +7601,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition(); silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()); } - F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); + F32 animationTime = (F32)LLFrameTimer::getUptimeSeconds(); F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index b6e80c42b7..a79e03831d 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -128,6 +128,13 @@ LLSpatialGroup::~LLSpatialGroup() sNodeCount--; + // unhook from the reflection probe, which the manager keeps until its next update + // notices nothing else holds it -- and autoAdjustOrigin dereferences mGroup until then + if (mReflectionProbe.notNull()) + { + mReflectionProbe->orphan(); + } + clearDrawMap(); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index c0c17db063..f8d09951ec 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2490,7 +2490,10 @@ bool idle_startup() LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL; gRenderStartTime.reset(); + gSimLastTime = 0.f; + gSimFrames = (F32)gFrameCount; gForegroundTime.reset(); + gForegroundFrameCount = 0; // HACK: Inform simulator of window size. // Do this here so it's less likely to race with RegisterNewAgent. diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index 7940754d71..2cb280250e 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -829,7 +829,7 @@ void LLToolBarView::updateAutoHide() S32 mouse_y = 0; LLUI::getInstance()->getMousePositionLocal(this, &mouse_x, &mouse_y); - const F64 now = LLFrameTimer::getElapsedSeconds(); + const F64 now = LLFrameTimer::getUptimeSeconds(); const F32 interp = LLSmoothInterpolation::getInterpolant(TOOLBAR_AUTO_HIDE_TIME_CONSTANT); const bool forced_visible = toolbars_forced_visible(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 8db9092bfa..66e09b299a 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -762,7 +762,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Geom"); - const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time + const F32 max_geom_update_time = llmin(0.005f*10.f*gFrameIntervalSeconds.value(), 0.005f); // 50 ms/second update time, max 5ms/frame gPipeline.createObjects(max_geom_update_time); gPipeline.processPartitionQ(); gPipeline.updateGeom(max_geom_update_time); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index db04600429..3fffbd9c66 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -768,7 +768,7 @@ void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchTyp if (fetching == FETCH_FAILED) { const F32 FETCH_FAILURE_EXPIRY = 60.0f; - mDescendentsRequested.setTimerExpirySec(FETCH_FAILURE_EXPIRY); + mDescendentsRequested.resetWithExpiry(FETCH_FAILURE_EXPIRY); mFetching = fetching; } else if (fetching > mFetching) // allow a switch from normal to recursive diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 224c264b93..ffd8e38d8b 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2519,7 +2519,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) msg->getU8Fast(_PREHASH_ChatData, _PREHASH_Audible, audible_temp); chat.mAudible = (EChatAudible)audible_temp; - chat.mTime = LLFrameTimer::getElapsedSeconds(); + chat.mTime = LLFrameTimer::getUptimeSeconds(); // IDEVO Correct for new-style "Resident" names if (chat.mSourceType == CHAT_SOURCE_AGENT) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1d354ba677..29ae8526b0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -335,7 +335,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe // Both clocks need it: an object whose first update is rejected before the timestamps are // stamped otherwise measures its update age from the start of the session, which is instantly // past every phase-out threshold. - mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); + mLastInterpUpdateSecs = LLFrameTimer::getUptimeSeconds(); mLastMessageUpdateSecs = mLastInterpUpdateSecs; mPositionRegion = LLVector3(0.f, 0.f, 0.f); @@ -356,7 +356,7 @@ LLViewerObject::~LLViewerObject() // unhook from reflection probe manager if (mReflectionProbe.notNull()) { - mReflectionProbe->mViewerObject = nullptr; + mReflectionProbe->orphan(); mReflectionProbe = nullptr; } @@ -537,7 +537,7 @@ void LLViewerObject::markDead() if (mReflectionProbe.notNull()) { - mReflectionProbe->mViewerObject = nullptr; + mReflectionProbe->orphan(); mReflectionProbe = nullptr; } @@ -568,7 +568,7 @@ void LLViewerObject::dump() const { LL_INFOS() << "Type: " << pCodeToString(mPrimitiveCode) << LL_ENDL; LL_INFOS() << "Drawable: " << (LLDrawable *)mDrawable << LL_ENDL; - LL_INFOS() << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << LL_ENDL; + LL_INFOS() << "Update Age: " << LLFrameTimer::getUptimeSeconds() - mLastMessageUpdateSecs << LL_ENDL; LL_INFOS() << "Parent: " << getParent() << LL_ENDL; LL_INFOS() << "ID: " << mID << LL_ENDL; @@ -2535,7 +2535,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // much jumping and hopping around... // U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay(); - const F64 update_time = LLFrameTimer::getElapsedSeconds(); + const F64 update_time = LLFrameTimer::getUptimeSeconds(); // Before the clocks move: how far the prediction had drifted by the time the real answer // arrived. This is the reading that settles the direction of the timestep correction in @@ -7255,7 +7255,7 @@ void LLViewerObject::updateRegion(LLViewerRegion *regionp) { // if (regionp) // { -// F64 now = LLFrameTimer::getElapsedSeconds(); +// F64 now = LLFrameTimer::getUptimeSeconds(); // LL_INFOS() << "Updating to region " << regionp->getName() // << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) // << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index ca1a6c852f..fc3d044d37 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -962,7 +962,7 @@ void LLViewerObjectList::update(LLAgent &agent) //clear avatar LOD change counter LLVOAvatar::sNumLODChangesThisFrame = 0; - const F64 frame_time = LLFrameTimer::getElapsedSeconds(); + const F64 frame_time = LLFrameTimer::getUptimeSeconds(); LLViewerObject *objectp = NULL; @@ -1073,6 +1073,7 @@ void LLViewerObjectList::update(LLAgent &agent) { LLViewerStats::getInstance()->updateFrameStats(time_diff); } + mWasPaused = false; /* // Debugging code for viewing orphans, and orphaned parents diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index c603838b86..4686de85cf 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -741,6 +741,15 @@ LLViewerRegion::~LLViewerRegion() gObjectList.killObjects(this); } + // the reflection probe manager keeps this region's terrain probes until its next update + for (auto& probe : mReflectionMaps) + { + if (probe.notNull()) + { + probe->orphan(); + } + } + delete mImpl->mCompositionp; delete mParcelOverlay; delete mImpl->mLandp; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 733b41f884..05cab6be66 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -551,7 +551,7 @@ void update_statistics() auto tot_frame_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FRAME); // cumulative avatar time (includes idle processing, attachments and base av) - auto tot_avatar_time_raw = LLPerfStats::us_to_raw(LLVOAvatar::getTotalGPURenderTime()); + auto tot_avatar_time_raw = LLPerfStats::ms_to_raw(LLVOAvatar::getTotalGPURenderTime()); // cumulative avatar render specific time (a bit arbitrary as the processing is too.) // auto tot_av_idle_time_raw = LLPerfStats::StatsRecorder::getSum(AvType, LLPerfStats::StatType_t::RENDER_IDLE); // auto tot_avatar_render_time_raw = tot_avatar_time_raw - tot_av_idle_time_raw; @@ -660,7 +660,7 @@ void send_viewer_stats(bool include_preferences) time_t ltime; time(<ime); - F32 run_time = F32(LLFrameTimer::getElapsedSeconds()); + F32 run_time = F32(LLFrameTimer::getUptimeSeconds()); agent["start_time"] = S32(ltime - S32(run_time)); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 172aa65084..69ccfe0883 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2944,7 +2944,7 @@ void LLViewerFetchedTexture::readbackRawImage() void LLViewerFetchedTexture::destroySavedRawImage() { - if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime) + if(getElapsedLastReferencedSavedRawImageTime() < mKeptSavedRawImageTime) { return; //keep the saved raw image. } diff --git a/indra/newview/llvisualeffect.cpp b/indra/newview/llvisualeffect.cpp index 9d9e3f2950..e19137f2fa 100644 --- a/indra/newview/llvisualeffect.cpp +++ b/indra/newview/llvisualeffect.cpp @@ -31,7 +31,7 @@ float LLTweenableValueLerp::get() { if (!m_CurValue) { - float curFactor = (F32)((LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration); + float curFactor = (F32)((LLTimer::getUptimeSeconds() - m_StartTime) / m_Duration); if (curFactor < 1.0f) return lerp(m_StartValue, m_EndValue, curFactor); m_CurValue = m_EndValue; @@ -44,7 +44,7 @@ LLColor3 LLTweenableValueLerp::get() { if (!m_CurValue) { - float curFactor = (F32)((LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration); + float curFactor = (F32)((LLTimer::getUptimeSeconds() - m_StartTime) / m_Duration); if (curFactor < 1.0f) return lerp(m_StartValue, m_EndValue, curFactor); m_CurValue = m_EndValue; @@ -57,7 +57,7 @@ LLVector4 LLTweenableValueLerp::get() { if (!m_CurValue) { - float curFactor = (F32)((LLTimer::getElapsedSeconds() - m_StartTime) / m_Duration); + float curFactor = (F32)((LLTimer::getUptimeSeconds() - m_StartTime) / m_Duration); if (curFactor < 1.0f) return lerp(m_StartValue, m_EndValue, curFactor); m_CurValue = m_EndValue; diff --git a/indra/newview/llvisualeffect.h b/indra/newview/llvisualeffect.h index 806d9dc638..ddc4598e8e 100644 --- a/indra/newview/llvisualeffect.h +++ b/indra/newview/llvisualeffect.h @@ -141,7 +141,7 @@ class LLTweenableValueLerp : public LLTweenableValue this->m_CurValue = boost::none; m_EndValue = endValue; - m_StartTime = LLTimer::getElapsedSeconds(); + m_StartTime = LLTimer::getUptimeSeconds(); m_Duration = duration; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c2c2603a0e..a87bbb331b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4011,7 +4011,7 @@ void LLVOAvatar::idleUpdateNameTagText(bool new_name) for(; chat_iter != mChats.end(); ++chat_iter) { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getUptimeSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); LLFontGL::StyleFlags style; switch(chat_iter->mChatType) { @@ -11342,7 +11342,7 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() // static, gets called once per frame from updateApparentAngles. void LLVOAvatar::cullAvatarsByPixelArea() { - F64 current_time = LLFrameTimer::getElapsedSeconds(); + F64 current_time = LLFrameTimer::getUptimeSeconds(); bool needs_resort = sAvatarCullNeedsUpdate || ((current_time - sLastCullUpdateTime) >= 1.0); if (needs_resort) diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 00c33e4ca2..8b1bda11fc 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -96,7 +96,7 @@ F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) : LLHUDEffect(type) { - mCurrentTime = mTimer.getTotalSeconds(); + mCurrentTime = LLFrameTimer::getTotalSeconds(); mPreviousTime = mCurrentTime; mStartTime = mCurrentTime; mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f ); @@ -108,8 +108,6 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) mSoundSymbol.mActive = true; mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f ); - mTimer.reset(); - const char* sound_level_img[] = { "voice_meter_dot.j2c", @@ -173,7 +171,7 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v ) //--------------------------------------------------- void LLVoiceVisualizer::setStartSpeaking() { - mStartTime = mTimer.getTotalSeconds(); + mStartTime = LLFrameTimer::getTotalSeconds(); mCurrentlySpeaking = true; mSoundSymbol.mActive = true; @@ -298,7 +296,7 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) } F32 transfer_aah = sAahPowerTransfer[transfer_index]; - F64 current_time = mTimer.getTotalSeconds(); + F64 current_time = LLFrameTimer::getTotalSeconds(); F64 elapsed_time = current_time - mStartTime; U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); U32 elapsed_oohs = elapsed_frames % sOohs; @@ -346,7 +344,7 @@ void LLVoiceVisualizer::render() if ( mSoundSymbol.mActive ) { mPreviousTime = mCurrentTime; - mCurrentTime = mTimer.getTotalSeconds(); + mCurrentTime = LLFrameTimer::getTotalSeconds(); //--------------------------------------------------------------- // set the sound symbol position over the source (avatar's head) diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index b788691a4f..af3611a86a 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -121,7 +121,6 @@ class LLVoiceVisualizer : public LLHUDEffect LLVector3 mPosition; }; - LLFrameTimer mTimer; // so I can ask the current time in seconds F64 mStartTime; // time in seconds when speaking started F64 mCurrentTime; // current time in seconds, captured every step F64 mPreviousTime; // copy of "current time" from last frame diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f15182ea96..f02dffc38c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4596,6 +4596,7 @@ void LLVOVolume::updateReflectionProbePtr() { if (mReflectionProbe.notNull()) { + mReflectionProbe->orphan(); mReflectionProbe = nullptr; } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 6248c831af..67d9e4213f 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -610,7 +610,7 @@ void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1) // Expire blocks requested more than BLOCK_UPDATE_TIMER ago so that they are // re-requested below and their sim info refreshed. - const F64 time_now = LLTimer::getElapsedSeconds(); + const F64 time_now = LLTimer::getUptimeSeconds(); for (auto it = mMapBlockLastUpdateOffsets.begin(); it != mMapBlockLastUpdateOffsets.end();) { if ((time_now - it->second) > BLOCK_UPDATE_TIMER) diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 5e60a17ed5..c5323104d1 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -374,7 +374,7 @@ void LLWorldMapView::draw() LLTextureView::clearDebugImages(); - F64 current_time = LLTimer::getElapsedSeconds(); + F64 current_time = LLTimer::getUptimeSeconds(); mVisibleRegions.clear(); diff --git a/indra/newview/rlvlocks.cpp b/indra/newview/rlvlocks.cpp index c3c59a14dd..8279421c6e 100644 --- a/indra/newview/rlvlocks.cpp +++ b/indra/newview/rlvlocks.cpp @@ -717,7 +717,7 @@ void RlvAttachmentLockWatchdog::onSavedAssetIntoInventory(const LLUUID& idItem) if ( (!itAttach->second.fAssetSaved) && (idItem == itAttach->second.idItem) ) { LLAttachmentsMgr::instance().addAttachmentRequest(itAttach->second.idItem, itAttach->first, true, true); - itAttach->second.tsAttach = LLFrameTimer::getElapsedSeconds(); + itAttach->second.tsAttach = LLFrameTimer::getUptimeSeconds(); } } } @@ -726,7 +726,7 @@ void RlvAttachmentLockWatchdog::onSavedAssetIntoInventory(const LLUUID& idItem) bool RlvAttachmentLockWatchdog::onTimer() { // RELEASE-RLVa: [SL-2.0.0] This will need rewriting for "ENABLE_MULTIATTACHMENTS" - F64 tsCurrent = LLFrameTimer::getElapsedSeconds(); + F64 tsCurrent = LLFrameTimer::getUptimeSeconds(); // Garbage collect (failed) wear requests older than 60 seconds rlv_wear_map_t::iterator itWear = m_PendingWear.begin(); diff --git a/indra/newview/rlvlocks.h b/indra/newview/rlvlocks.h index e0e73b6352..984d8566ed 100644 --- a/indra/newview/rlvlocks.h +++ b/indra/newview/rlvlocks.h @@ -177,7 +177,7 @@ class RlvAttachmentLockWatchdog : public LLSingleton struct RlvReattachInfo { RlvReattachInfo(const LLUUID& itemid) : idItem(itemid), fAssetSaved(false), tsAttach(0) - { tsDetach = LLFrameTimer::getElapsedSeconds(); } + { tsDetach = LLFrameTimer::getUptimeSeconds(); } LLUUID idItem; bool fAssetSaved; @@ -192,7 +192,7 @@ class RlvAttachmentLockWatchdog : public LLSingleton struct RlvWearInfo { RlvWearInfo(const LLUUID& itemid, ERlvWearMask wearaction) : idItem(itemid), eWearAction(wearaction) - { tsWear = LLFrameTimer::getElapsedSeconds(); } + { tsWear = LLFrameTimer::getUptimeSeconds(); } bool isAddLockedAttachPt(S32 idxAttachPt) const; void dumpInstance() const;