summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml14
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/lleventcoro.cpp12
-rw-r--r--indra/llcommon/lleventcoro.h5
-rw-r--r--indra/llcommon/llthread.cpp6
-rw-r--r--indra/llcommon/llwatchdog.cpp (renamed from indra/newview/llwatchdog.cpp)36
-rw-r--r--indra/llcommon/llwatchdog.h (renamed from indra/newview/llwatchdog.h)25
-rw-r--r--indra/llcommon/workqueue.cpp7
-rw-r--r--indra/llcommon/workqueue.h6
-rw-r--r--indra/llmessage/llassetstorage.cpp3
-rw-r--r--indra/llmessage/llassetstorage.h1
-rw-r--r--indra/llui/llmenugl.cpp14
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llwebrtc/llwebrtc.cpp3
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp65
-rw-r--r--indra/llwindow/llwindowwin32.h141
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml20
-rw-r--r--indra/newview/llaisapi.cpp7
-rw-r--r--indra/newview/llappviewer.cpp68
-rw-r--r--indra/newview/lleventpoll.cpp58
-rw-r--r--indra/newview/llexternaleditor.cpp8
-rw-r--r--indra/newview/llfeaturemanager.cpp4
-rw-r--r--indra/newview/llfloaterpreference.cpp16
-rw-r--r--indra/newview/llglsandbox.cpp66
-rw-r--r--indra/newview/llinventorybridge.cpp9
-rw-r--r--indra/newview/llinventorygallerymenu.cpp21
-rw-r--r--indra/newview/lllandmarkactions.cpp96
-rw-r--r--indra/newview/lllandmarklist.cpp49
-rw-r--r--indra/newview/lllandmarklist.h1
-rw-r--r--indra/newview/llmutelist.cpp8
-rw-r--r--indra/newview/llpaneldirbrowser.cpp24
-rw-r--r--indra/newview/llpaneldirevents.cpp11
-rw-r--r--indra/newview/llpaneldirland.cpp14
-rw-r--r--indra/newview/llpaneldirplaces.cpp11
-rw-r--r--indra/newview/llpanelface.cpp32
-rw-r--r--indra/newview/llpanelface.h2
-rw-r--r--indra/newview/llviewerassetstorage.cpp71
-rw-r--r--indra/newview/llviewermenu.cpp13
-rw-r--r--indra/newview/llvoicewebrtc.cpp14
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml2
-rwxr-xr-xindra/newview/viewer_manifest.py5
43 files changed, 704 insertions, 272 deletions
diff --git a/autobuild.xml b/autobuild.xml
index c71d93d6d8..1abb87ec22 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2633,11 +2633,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>43c5f93517794aeade550e4266b959d1f0cfcb7f</string>
+ <string>72ed1f6d469a8ffaffd69be39b7af186d7c3b1d7</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
- <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-darwin64-17630578914.tar.zst</string>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.22/webrtc-m137.7151.04.22.21966754211-darwin64-21966754211.tar.zst</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -2647,11 +2647,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>efc5b176d878cfc16b8f82445d82ddb96815b6ab</string>
+ <string>b4d0c836d99491841c3816ff93bb2655a2817bd3</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
- <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-linux64-17630578914.tar.zst</string>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.22/webrtc-m137.7151.04.22.21966754211-linux64-21966754211.tar.zst</string>
</map>
<key>name</key>
<string>linux64</string>
@@ -2661,11 +2661,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>1e36f100de32c7c71325497a672fb1659b3f206d</string>
+ <string>ab2bddd77b1568b22b50ead13c1c33da94f4d59a</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
- <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-windows64-17630578914.tar.zst</string>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.22/webrtc-m137.7151.04.22.21966754211-windows64-21966754211.tar.zst</string>
</map>
<key>name</key>
<string>windows64</string>
@@ -2678,7 +2678,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>copyright</key>
<string>Copyright (c) 2011, The WebRTC project authors. All rights reserved.</string>
<key>version</key>
- <string>m137.7151.04.20-universal.17630578914</string>
+ <string>m137.7151.04.22.21966754211</string>
<key>name</key>
<string>webrtc</string>
<key>vcs_branch</key>
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2de9deea70..4d04c2c119 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -101,6 +101,7 @@ set(llcommon_SOURCE_FILES
lluri.cpp
lluriparser.cpp
lluuid.cpp
+ llwatchdog.cpp
llworkerthread.cpp
hbxxh.cpp
u64.cpp
@@ -240,6 +241,7 @@ set(llcommon_HEADER_FILES
lluri.h
lluriparser.h
lluuid.h
+ llwatchdog.h
llwin32headers.h
llworkerthread.h
hbxxh.h
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index e1fc4764f6..bb2cd4fb2e 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -137,6 +137,18 @@ void llcoro::suspendUntilTimeout(float seconds)
suspendUntilEventOnWithTimeout(bogus, seconds, timedout);
}
+void llcoro::suspendUntilNextFrame()
+{
+ LLCoros::checkStop();
+ LLCoros::TempStatus st("waiting for next frame");
+
+ // Listen for the next event on the "mainloop" event pump.
+ // Once per frame we get mainloop.post(newFrame);
+ LLEventPumpOrPumpName mainloop_pump("mainloop");
+ // Wait for the next event (the event data is ignored).
+ suspendUntilEventOn(mainloop_pump);
+}
+
namespace
{
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index 492563bb98..25a8a98e36 100644
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -85,6 +85,11 @@ void suspend();
void suspendUntilTimeout(float seconds);
/**
+ * Yield control from a coroutine until the next mainloop's newFrame event.
+ */
+void suspendUntilNextFrame();
+
+/**
* Post specified LLSD event on the specified LLEventPump, then suspend for a
* response on specified other LLEventPump. This is more than mere
* convenience: the difference between this function and the sequence
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 692941a892..8c12ee7f12 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -240,7 +240,11 @@ void LLThread::tryRun()
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
main_queue->post(
// Bind the current exception, rethrow it in main loop.
- [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ [exc = std::current_exception(), name = mName]()
+ {
+ LL_INFOS("THREAD") << "Rethrowing exception from thread " << name << LL_ENDL;
+ std::rethrow_exception(exc);
+ });
}
#endif // else LL_WINDOWS
}
diff --git a/indra/newview/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp
index 614d1afc2a..fa240a9ed7 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/llcommon/llwatchdog.cpp
@@ -24,11 +24,11 @@
* $/LicenseInfo$
*/
+// Precompiled header
+#include "linden_common.h"
-#include "llviewerprecompiledheaders.h"
#include "llwatchdog.h"
#include "llthread.h"
-#include "llappviewer.h"
constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U;
@@ -67,7 +67,9 @@ private:
};
// LLWatchdogEntry
-LLWatchdogEntry::LLWatchdogEntry()
+LLWatchdogEntry::LLWatchdogEntry(const std::string& thread_name)
+ : mThreadName(thread_name)
+ , mThreadID(LLThread::currentID())
{
}
@@ -89,11 +91,16 @@ void LLWatchdogEntry::stop()
LLWatchdog::getInstance()->remove(this);
}
}
+std::string LLWatchdogEntry::getThreadName() const
+{
+ return mThreadName + llformat(": %d", mThreadID);
+}
// LLWatchdogTimeout
const std::string UNINIT_STRING = "uninitialized";
-LLWatchdogTimeout::LLWatchdogTimeout() :
+LLWatchdogTimeout::LLWatchdogTimeout(const std::string& thread_name) :
+ LLWatchdogEntry(thread_name),
mTimeout(0.0f),
mPingState(UNINIT_STRING)
{
@@ -175,7 +182,7 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
unlockThread();
}
-void LLWatchdog::init()
+void LLWatchdog::init(func_t set_error_state_callback)
{
if (!mSuspectsAccessMutex && !mTimer)
{
@@ -188,6 +195,7 @@ void LLWatchdog::init()
// start needs to use the mSuspectsAccessMutex
mTimer->start();
}
+ mCreateMarkerFnc = set_error_state_callback;
}
void LLWatchdog::cleanup()
@@ -241,17 +249,23 @@ void LLWatchdog::run()
{
mTimer->stop();
}
- if (LLAppViewer::instance()->logoutRequestSent())
+
+ // Sets error marker file
+ mCreateMarkerFnc();
+ // Todo1: Warn user?
+ // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'.
+ std::string last_state = (*result)->getLastState();
+ if (last_state.empty())
{
- LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
+ LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
+ << " expired; assuming viewer is hung and crashing" << LL_ENDL;
}
else
{
- LLAppViewer::instance()->createErrorMarker(LAST_EXEC_FROZE);
+ LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName()
+ << " expired with state: " << last_state
+ << "; assuming viewer is hung and crashing" << LL_ENDL;
}
- // Todo1: warn user?
- // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'.
- LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL;
}
}
diff --git a/indra/newview/llwatchdog.h b/indra/llcommon/llwatchdog.h
index b7dd55577e..fded881bb8 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/llcommon/llwatchdog.h
@@ -30,13 +30,17 @@
#ifndef LL_TIMER_H
#include "lltimer.h"
#endif
+#include "llmutex.h"
+#include "llsingleton.h"
+
+#include <functional>
// LLWatchdogEntry is the interface used by the tasks that
// need to be watched.
class LLWatchdogEntry
{
public:
- LLWatchdogEntry();
+ LLWatchdogEntry(const std::string &thread_name);
virtual ~LLWatchdogEntry();
// isAlive is accessed by the watchdog thread.
@@ -46,12 +50,19 @@ public:
virtual void reset() = 0;
virtual void start();
virtual void stop();
+ virtual std::string getLastState() const { return std::string(); }
+ typedef std::thread::id id_t;
+ std::string getThreadName() const;
+
+private:
+ id_t mThreadID; // ID of the thread being watched
+ std::string mThreadName;
};
class LLWatchdogTimeout : public LLWatchdogEntry
{
public:
- LLWatchdogTimeout();
+ LLWatchdogTimeout(const std::string& thread_name);
virtual ~LLWatchdogTimeout();
bool isAlive() const override;
@@ -63,6 +74,7 @@ public:
void setTimeout(F32 d);
void ping(std::string_view state);
const std::string& getState() {return mPingState; }
+ std::string getLastState() const override { return mPingState; }
private:
LLTimer mTimer;
@@ -81,10 +93,12 @@ public:
void add(LLWatchdogEntry* e);
void remove(LLWatchdogEntry* e);
- void init();
+ typedef std::function<void()> func_t;
+ void init(func_t set_error_state_callback);
void run();
void cleanup();
+
private:
void lockThread();
void unlockThread();
@@ -94,6 +108,11 @@ private:
LLMutex* mSuspectsAccessMutex;
LLWatchdogTimerThread* mTimer;
U64 mLastClockCount;
+
+ // At the moment watchdog expects app to set markers in mCreateMarkerFnc,
+ // but technically can be used to set any error states or do some cleanup
+ // or show warnings.
+ func_t mCreateMarkerFnc;
};
#endif // LL_LLTHREADWATCHDOG_H
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 7efaebd569..0407d6c3e9 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -216,10 +216,15 @@ void LL::WorkQueueBase::callWork(const Work& work)
LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
<< getKey() << LL_ENDL;
+ std::string name = getKey();
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
main_queue->post(
// Bind the current exception, rethrow it in main loop.
- [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ [exc = std::current_exception(), name]()
+ {
+ LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::callWork " << name << LL_ENDL;
+ std::rethrow_exception(exc);
+ });
}
else
{
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 735ad38a26..573203a5b3 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -530,7 +530,11 @@ namespace LL
reply,
// Bind the current exception to transport back to the
// originating WorkQueue. Once there, rethrow it.
- [exc = std::current_exception()](){ std::rethrow_exception(exc); });
+ [exc = std::current_exception()]()
+ {
+ LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::postTo" << LL_ENDL;
+ std::rethrow_exception(exc);
+ });
}
},
// if caller passed a TimePoint, pass it along to post()
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 10fd56a68e..4c3acb27f4 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -1316,6 +1316,9 @@ const char* LLAssetStorage::getErrorString(S32 status)
case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
return "Asset request: asset not found in database";
+ case LL_ERR_NO_CAP:
+ return "Asset request: region or asset capability not available";
+
case LL_ERR_EOF:
return "End of file";
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 6d6526757d..d5daa0cb8f 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -57,6 +57,7 @@ const int LL_ERR_ASSET_REQUEST_FAILED = -1;
const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
+const int LL_ERR_NO_CAP = -6;
const int LL_ERR_PRICE_MISMATCH = -23018;
// *TODO: these typedefs are passed into the cache via a legacy C function pointer
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 2ca2454040..6ba31c251e 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -4404,3 +4404,17 @@ bool LLContextMenu::addChild(LLView* view, S32 tab_group)
return addContextChild(view, tab_group);
}
+void LLContextMenu::deleteAllChildren()
+{
+ mHoverItem = nullptr;
+ LLMenuGL::deleteAllChildren();
+}
+
+void LLContextMenu::removeChild(LLView* ctrl)
+{
+ if (ctrl == mHoverItem)
+ {
+ mHoverItem = nullptr;
+ }
+ LLMenuGL::removeChild(ctrl);
+}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index eacf2c59d4..bca0a731fc 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -730,6 +730,8 @@ public:
virtual bool handleRightMouseUp ( S32 x, S32 y, MASK mask );
virtual bool addChild (LLView* view, S32 tab_group = 0);
+ /*virtual*/ void deleteAllChildren();
+ /*virtual*/ void removeChild(LLView* ctrl);
LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); }
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index d1bae49784..8e08239ee6 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -814,6 +814,7 @@ LLWebRTCPeerConnectionImpl::~LLWebRTCPeerConnectionImpl()
{
mSignalingObserverList.clear();
mDataObserverList.clear();
+ mPeerConnectionFactory.release();
if (mPendingJobs > 0)
{
RTC_LOG(LS_ERROR) << __FUNCTION__ << "Destroying a connection that has " << std::to_string(mPendingJobs) << " unfinished jobs that might cause workers to crash";
@@ -877,7 +878,6 @@ void LLWebRTCPeerConnectionImpl::terminate()
}
mPendingJobs--;
});
- mPeerConnectionFactory.release();
}
void LLWebRTCPeerConnectionImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); }
@@ -1004,6 +1004,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti
}
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions;
+ this->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called.
mPeerConnection->CreateOffer(this, offerOptions);
mPendingJobs--;
});
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 7a5404e615..185940e32d 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -205,6 +205,8 @@ public:
};
virtual S32 getRefreshRate() { return mRefreshRate; }
+
+ virtual void initWatchdog() {} // windows runs window as a thread and it needs a watchdog
protected:
LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags);
virtual ~LLWindow();
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f826a60ddd..2bd9dd053c 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -49,6 +49,7 @@
#include "llthreadsafequeue.h"
#include "stringize.h"
#include "llframetimer.h"
+#include "llwatchdog.h"
// System includes
#include <commdlg.h>
@@ -364,7 +365,8 @@ static LLMonitorInfo sMonitorInfo;
// the containing class a friend.
struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
{
- static const int MAX_QUEUE_SIZE = 2048;
+ static constexpr int MAX_QUEUE_SIZE = 2048;
+ static constexpr F32 WINDOW_TIMEOUT_SEC = 90.f;
LLThreadSafeQueue<MSG> mMessageQueue;
@@ -426,6 +428,50 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
PostMessage(windowHandle, WM_POST_FUNCTION_, wparam, LPARAM(ptr));
}
+ // Call from main thread.
+ void initTimeout()
+ {
+ // post into thread's queue to avoid threading issues
+ post([this]()
+ {
+ if (!mWindowTimeout)
+ {
+ mWindowTimeout = std::make_unique<LLWatchdogTimeout>("WindowThread");
+ // supposed to be executed within run(),
+ // so no point checking if thread is alive
+ resumeTimeout("TimeoutInit");
+ }
+ });
+ }
+private:
+ // These timeout related functions are strictly for the thread.
+ void resumeTimeout(std::string_view state)
+ {
+ if (mWindowTimeout)
+ {
+ mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC);
+ mWindowTimeout->start(state);
+ }
+ }
+
+ void pauseTimeout()
+ {
+ if (mWindowTimeout)
+ {
+ mWindowTimeout->stop();
+ }
+ }
+
+ void pingTimeout(std::string_view state)
+ {
+ if (mWindowTimeout)
+ {
+ mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC);
+ mWindowTimeout->ping(state);
+ }
+ }
+
+public:
using FuncType = std::function<void()>;
// call GetMessage() and pull enqueue messages for later processing
HWND mWindowHandleThrd = NULL;
@@ -436,6 +482,8 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
bool mGLReady = false;
bool mGotGLBuffer = false;
LLAtomicBool mDeleteOnExit = false;
+private:
+ std::unique_ptr<LLWatchdogTimeout> mWindowTimeout;
};
@@ -4595,6 +4643,11 @@ bool LLWindowWin32::getInputDevices(U32 device_type_filter,
return false;
}
+void LLWindowWin32::initWatchdog()
+{
+ mWindowThread->initTimeout();
+}
+
F32 LLWindowWin32::getSystemUISize()
{
F32 scale_value = 1.f;
@@ -4732,6 +4785,8 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem()
return;
}
+ pauseTimeout();
+
IDXGIFactory4* p_factory = nullptr;
HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&p_factory);
@@ -4835,6 +4890,8 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem()
}
mGotGLBuffer = true;
+
+ resumeTimeout("checkDXMem");
}
void LLWindowWin32::LLWindowWin32Thread::run()
@@ -4850,6 +4907,9 @@ void LLWindowWin32::LLWindowWin32Thread::run()
timeBeginPeriod(llclamp((U32) 1, tc.wPeriodMin, tc.wPeriodMax));
}
+ // Normally won't exist yet, but in case of re-init, make sure it's cleaned up
+ resumeTimeout("WindowThread");
+
while (! getQueue().done())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
@@ -4859,6 +4919,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
if (mWindowHandleThrd != 0)
{
+ pingTimeout("messages");
MSG msg;
BOOL status;
if (mhDCThrd == 0)
@@ -4886,6 +4947,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Function Queue");
+ pingTimeout("queue");
logger.onChange("runPending()");
//process any pending functions
getQueue().runPending();
@@ -4900,6 +4962,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
#endif
}
+ pauseTimeout();
destroyWindow();
if (mDeleteOnExit)
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 0fc93ad0b1..8159092794 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -45,83 +45,82 @@ typedef void (*LLW32MsgCallback)(const MSG &msg);
class LLWindowWin32 : public LLWindow
{
public:
- /*virtual*/ void show();
- /*virtual*/ void hide();
- /*virtual*/ void close();
- /*virtual*/ bool getVisible();
- /*virtual*/ bool getMinimized();
- /*virtual*/ bool getMaximized();
- /*virtual*/ bool maximize();
- /*virtual*/ void minimize();
- /*virtual*/ void restore();
- /*virtual*/ bool getFullscreen();
- /*virtual*/ bool getPosition(LLCoordScreen *position);
- /*virtual*/ bool getSize(LLCoordScreen *size);
- /*virtual*/ bool getSize(LLCoordWindow *size);
- /*virtual*/ bool setPosition(LLCoordScreen position);
- /*virtual*/ bool setSizeImpl(LLCoordScreen size);
- /*virtual*/ bool setSizeImpl(LLCoordWindow size);
- /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL);
- /*virtual*/ void setTitle(const std::string title);
+ void show() override;
+ void hide() override;
+ void close() override;
+ bool getVisible() override;
+ bool getMinimized() override;
+ bool getMaximized() override;
+ bool maximize() override;
+ void minimize() override;
+ void restore() override;
+ bool getFullscreen();
+ bool getPosition(LLCoordScreen *position) override;
+ bool getSize(LLCoordScreen *size) override;
+ bool getSize(LLCoordWindow *size) override;
+ bool setPosition(LLCoordScreen position) override;
+ bool setSizeImpl(LLCoordScreen size) override;
+ bool setSizeImpl(LLCoordWindow size) override;
+ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override;
+ void setTitle(const std::string title) override;
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
- /*virtual*/ void toggleVSync(bool enable_vsync);
- /*virtual*/ bool setCursorPosition(LLCoordWindow position);
- /*virtual*/ bool getCursorPosition(LLCoordWindow *position);
- /*virtual*/ bool getCursorDelta(LLCoordCommon* delta);
- /*virtual*/ bool isWrapMouse() const override { return !mAbsoluteCursorPosition; };
- /*virtual*/ void showCursor();
- /*virtual*/ void hideCursor();
- /*virtual*/ void showCursorFromMouseMove();
- /*virtual*/ void hideCursorUntilMouseMove();
- /*virtual*/ bool isCursorHidden();
- /*virtual*/ void updateCursor();
- /*virtual*/ ECursorType getCursor() const;
- /*virtual*/ void captureMouse();
- /*virtual*/ void releaseMouse();
- /*virtual*/ void setMouseClipping( bool b );
- /*virtual*/ bool isClipboardTextAvailable();
- /*virtual*/ bool pasteTextFromClipboard(LLWString &dst);
- /*virtual*/ bool copyTextToClipboard(const LLWString &src);
- /*virtual*/ void flashIcon(F32 seconds);
- /*virtual*/ F32 getGamma();
- /*virtual*/ bool setGamma(const F32 gamma); // Set the gamma
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples);
- /*virtual*/ U32 getFSAASamples();
- /*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma)
- /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void gatherInput();
- /*virtual*/ void delayInputProcessing();
- /*virtual*/ void swapBuffers();
- /*virtual*/ void restoreGLContext() {};
+ void toggleVSync(bool enable_vsync) override;
+ bool setCursorPosition(LLCoordWindow position) override;
+ bool getCursorPosition(LLCoordWindow *position) override;
+ bool getCursorDelta(LLCoordCommon* delta) override;
+ bool isWrapMouse() const override { return !mAbsoluteCursorPosition; };
+ void showCursor() override;
+ void hideCursor() override;
+ void showCursorFromMouseMove() override;
+ void hideCursorUntilMouseMove() override;
+ bool isCursorHidden() override;
+ void updateCursor() override;
+ ECursorType getCursor() const override;
+ void captureMouse() override;
+ void releaseMouse() override;
+ void setMouseClipping( bool b ) override;
+ bool isClipboardTextAvailable() override;
+ bool pasteTextFromClipboard(LLWString &dst) override;
+ bool copyTextToClipboard(const LLWString &src) override;
+ void flashIcon(F32 seconds) override;
+ F32 getGamma() override;
+ bool setGamma(const F32 gamma) override; // Set the gamma
+ void setFSAASamples(const U32 fsaa_samples) override;
+ U32 getFSAASamples() override;
+ bool restoreGamma() override; // Restore original gamma table (before updating gamma)
+ ESwapMethod getSwapMethod() override { return mSwapMethod; }
+ void gatherInput() override;
+ void delayInputProcessing() override;
+ void swapBuffers() override;
// handy coordinate space conversion routines
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to);
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to);
- /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to);
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to);
- /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to);
- /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to);
+ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
+ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
+ bool convertCoords(LLCoordWindow from, LLCoordGL *to) override;
+ bool convertCoords(LLCoordGL from, LLCoordWindow *to) override;
+ bool convertCoords(LLCoordScreen from, LLCoordGL *to) override;
+ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override;
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
+ F32 getNativeAspectRatio() override;
+ F32 getPixelAspectRatio() override;
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
- /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b );
+ bool dialogColorPicker(F32 *r, F32 *g, F32 *b ) override;
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
- /*virtual*/ void focusClient();
+ void *getPlatformWindow() override;
+ void bringToFront() override;
+ void focusClient() override;
- /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, bool b);
- /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos );
- /*virtual*/ void updateLanguageTextInputArea();
- /*virtual*/ void interruptLanguageTextInput();
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override;
+ void setLanguageTextInput( const LLCoordGL & pos ) override;
+ void updateLanguageTextInputArea() override;
+ void interruptLanguageTextInput() override;
+ void spawnWebBrowser(const std::string& escaped_url, bool async) override;
- /*virtual*/ F32 getSystemUISize();
+ F32 getSystemUISize() override;
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
@@ -129,14 +128,16 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
- /*virtual*/ void* getDirectInput8();
- /*virtual*/ bool getInputDevices(U32 device_type_filter,
+ void* getDirectInput8() override;
+ bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
- void* userdata);
+ void* userdata) override;
U32 getRawWParam() { return mRawWParam; }
+ void initWatchdog() override;
+
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index ed3fbed594..670450fd6b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -738,7 +738,6 @@ set(viewer_SOURCE_FILES
llvovolume.cpp
llvowater.cpp
llvowlsky.cpp
- llwatchdog.cpp
llwearableitemslist.cpp
llwearablelist.cpp
llweb.cpp
@@ -1417,7 +1416,6 @@ set(viewer_HEADER_FILES
llvovolume.h
llvowater.h
llvowlsky.h
- llwatchdog.h
llwearableitemslist.h
llwearablelist.h
llweb.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2f2d9f3ece..3e85a5afe2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -641,7 +641,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html</string>
+ <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html</string>
</map>
<!--AvatarBakedTextureUploadTimeout is in use by QA-->
<key>AvatarBakedTextureUploadTimeout</key>
@@ -2467,7 +2467,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string>
+ <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string>
</map>
<key>DisableCameraConstraints</key>
<map>
@@ -2775,7 +2775,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://events.[GRID]/viewer/embed/event/[EVENT_ID]</string>
+ <string>https://events.[GRID]/viewer/embed/event/[EVENT_ID]</string>
</map>
<key>MainWorkTime</key>
<map>
@@ -3432,7 +3432,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE]</string>
+ <string>https://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE]</string>
</map>
<key>HowToHelpURL</key>
<map>
@@ -3443,7 +3443,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string>
+ <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string>
</map>
<key>HomeSidePanelURL</key>
<map>
@@ -4059,7 +4059,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string>
+ <string>https://wiki.secondlife.com/wiki/[LSL_STRING]</string>
</map>
<key>LSLFontSizeName</key>
<map>
@@ -4511,7 +4511,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>30.0</real>
+ <real>60.0</real>
</map>
<key>MapScale</key>
<map>
@@ -7345,7 +7345,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>32.0</real>
+ <real>48.0</real>
</map>
<key>RenderCPUBasis</key>
<map>
@@ -9068,7 +9068,7 @@
<key>Comment</key>
<string>Show reflection probes in the transparency debug view</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
@@ -14720,7 +14720,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/404.html</string>
+ <string>https://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/404.html</string>
</map>
<key>OpenIMOnVoice</key>
<map>
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 1da1647fe8..9c76f56ef3 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -1060,7 +1060,12 @@ void AISUpdate::checkTimeout()
{
if (mTimer.hasExpired())
{
- llcoro::suspend();
+ // If we are taking too long, don't starve other tasks,
+ // yield to mainloop.
+ // If we use normal suspend(), there will be a chance of
+ // waking up from other suspends, before main coro had
+ // a chance, so wait for a frame tick instead.
+ llcoro::suspendUntilNextFrame();
LLCoros::checkStop();
mTimer.setTimerExpirySec(AIS_EXPIRY_SECONDS);
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 701ae189bd..47c517eb5b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1194,7 +1194,7 @@ bool LLAppViewer::init()
/*----------------------------------------------------------------------*/
// nat 2016-06-29 moved the following here from the former mainLoop().
- mMainloopTimeout = new LLWatchdogTimeout();
+ mMainloopTimeout = new LLWatchdogTimeout("mainloop");
// Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp);
@@ -1301,6 +1301,7 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
+ resumeMainloopTimeout("Main:doFrameStart");
#ifdef LL_DISCORD
{
LL_PROFILE_ZONE_NAMED("discord_callbacks");
@@ -1384,12 +1385,14 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df mainloop");
+ pingMainloopTimeout("df mainloop");
// canonical per-frame event
mainloop.post(newFrame);
}
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend");
+ pingMainloopTimeout("df suspend");
// give listeners a chance to run
llcoro::suspend();
// if one of our coroutines threw an uncaught exception, rethrow it now
@@ -1425,6 +1428,7 @@ bool LLAppViewer::doFrame()
{
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout");
+ pingMainloopTimeout("df idle"); // So that it will be aware of last state.
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
}
@@ -1436,7 +1440,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout");
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df idle");
}
}
@@ -1451,7 +1455,7 @@ bool LLAppViewer::doFrame()
}
disconnectViewer();
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df snapshot n disconnect");
}
// Render scene.
@@ -1592,17 +1596,20 @@ bool LLAppViewer::doFrame()
if (LLApp::isExiting())
{
+ pingMainloopTimeout("Main:qSnapshot");
// Save snapshot for next time, if we made it through initialization
if (STATE_STARTED == LLStartUp::getStartupState())
{
saveFinalSnapshot();
}
+ pingMainloopTimeout("Main:TerminateVoice");
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->terminate();
}
+ pingMainloopTimeout("Main:TerminatePump");
delete gServicePump;
gServicePump = NULL;
@@ -1611,6 +1618,11 @@ bool LLAppViewer::doFrame()
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
}LLPerfStats::StatsRecorder::endFrame();
+
+ // Not viewer's fault if something outside frame
+ // pauses viewer (ex: macOS doesn't call oneFrame),
+ // so stop tracking on exit.
+ pauseMainloopTimeout();
LL_PROFILER_FRAME_END;
return ! LLApp::isRunning();
@@ -2265,7 +2277,22 @@ void errorHandler(const std::string& title_string, const std::string& message_st
}
if (!message_string.empty())
{
- OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ if (on_main_thread())
+ {
+ // Prevent watchdog from killing us while dialog is up.
+ // Can't do pauseMainloopTimeout, since this may be called
+ // from threads and we are not going to need watchdog now.
+ LLAppViewer::instance()->pauseMainloopTimeout();
+
+ // todo: might want to have non-crashing timeout for OOM cases
+ // and needs a way to pause main loop.
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ LLAppViewer::instance()->resumeMainloopTimeout();
+ }
+ else
+ {
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ }
}
}
@@ -3128,7 +3155,18 @@ bool LLAppViewer::initWindow()
if (use_watchdog)
{
- LLWatchdog::getInstance()->init();
+ LLWatchdog::getInstance()->init([]()
+ {
+ LLAppViewer* app = LLAppViewer::instance();
+ if (app->logoutRequestSent())
+ {
+ app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
+ }
+ else
+ {
+ app->createErrorMarker(LAST_EXEC_FROZE);
+ }
+ });
}
LLNotificationsUI::LLNotificationManager::getInstance();
@@ -4108,6 +4146,7 @@ void LLAppViewer::requestQuit()
return;
}
+ pingMainloopTimeout("Main:qMetrics");
// Try to send metrics back to the grid
metricsSend(!gDisconnected);
@@ -4123,6 +4162,7 @@ void LLAppViewer::requestQuit()
LLHUDManager::getInstance()->sendEffects();
effectp->markDead() ;//remove it.
+ pingMainloopTimeout("Main:qFloaters");
// Attempt to close all floaters that might be
// editing things.
if (gFloaterView)
@@ -4131,6 +4171,7 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
mClosingFloaters = true;
}
+ pingMainloopTimeout("Main:qStats");
// Send preferences once, when exiting
bool include_preferences = true;
@@ -4138,6 +4179,7 @@ void LLAppViewer::requestQuit()
gLogoutTimer.reset();
mQuitRequested = true;
+ pingMainloopTimeout("Main:LoggingOut");
}
static bool finish_quit(const LLSD& notification, const LLSD& response)
@@ -5418,6 +5460,7 @@ void LLAppViewer::outOfMemorySoftQuit()
LLLFSThread::sLocal->pause();
gLogoutTimer.reset();
mQuitRequested = true;
+ destroyMainloopTimeout();
LLError::LLUserWarningMsg::showOutOfMemory();
}
@@ -5789,7 +5832,7 @@ void LLAppViewer::initMainloopTimeout(std::string_view state)
{
if (!mMainloopTimeout)
{
- mMainloopTimeout = new LLWatchdogTimeout();
+ mMainloopTimeout = new LLWatchdogTimeout("mainloop");
resumeMainloopTimeout(state);
}
}
@@ -5834,10 +5877,16 @@ void LLAppViewer::pingMainloopTimeout(std::string_view state)
F32 LLAppViewer::getMainloopTimeoutSec() const
{
+ if (isQuitting() || mQuitRequested)
+ {
+ constexpr F32 QUITTING_SECONDS = 240.f;
+ return QUITTING_SECONDS;
+ }
if (LLStartUp::getStartupState() == STATE_STARTED
&& gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)
{
- static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 30.f);
+ // consider making this value match 'disconnected' timout.
+ static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 60.f);
return mainloop_started();
}
else
@@ -5851,6 +5900,11 @@ void LLAppViewer::handleLoginComplete()
{
gLoggedInTime.start();
initMainloopTimeout("Mainloop Init");
+ LLWindow* viewer_window = gViewerWindow->getWindow();
+ if (viewer_window) // in case of a headless client
+ {
+ viewer_window->initWatchdog();
+ }
// Store some data to DebugInfo in case of a freeze.
gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index de3752d879..f1b46f0533 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -56,6 +56,7 @@ namespace Details
private:
void eventPollCoro(std::string url);
+ void handleMessage(const std::string& msg_name, const LLSD& body);
void handleMessage(const LLSD &content);
bool mDone;
@@ -95,21 +96,23 @@ namespace Details
mSenderIp = sender.getIPandPort();
}
+ void LLEventPollImpl::handleMessage(const std::string &msg_name, const LLSD &body)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
+ LLSD message;
+ message["sender"] = mSenderIp;
+ message["body"] = body;
+
+ LLMessageSystem::dispatch(msg_name, message);
+ }
+
void LLEventPollImpl::handleMessage(const LLSD& content)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
std::string msg_name = content["message"].asString();
LLSD message;
- try
- {
- message["sender"] = mSenderIp;
- message["body"] = content["body"];
- }
- catch (std::bad_alloc&)
- {
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS("LLCoros") << "Bad memory allocation on message: " << msg_name << LL_ENDL;
- }
+ message["sender"] = mSenderIp;
+ message["body"] = content["body"];
LLMessageSystem::dispatch(msg_name, message);
}
@@ -194,7 +197,7 @@ namespace Details
break;
}
- LLSD httpResults = result["http_result"];
+ LLSD &httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
@@ -299,7 +302,7 @@ namespace Details
}
acknowledge = result["id"];
- LLSD events = result["events"];
+ LLSD &events = result["events"];
if (acknowledge.isUndefined())
{
@@ -310,20 +313,37 @@ namespace Details
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << acknowledge << ")" << LL_ENDL;
- LLSD::array_const_iterator i = events.beginArray();
- LLSD::array_const_iterator end = events.endArray();
+ LLSD::array_iterator i = events.beginArray();
+ LLSD::array_iterator end = events.endArray();
for (; i != end; ++i)
{
if (i->has("message"))
{
if (main_queue)
- { // shuttle to a sensible spot in the main thread instead
+ {
+ // Shuttle copy to a sensible spot in the main thread instead
// of wherever this coroutine happens to be executing
- const LLSD& msg = *i;
- main_queue->post([this, msg]()
+
+ LL::WorkQueue::Work work;
+ {
+ // LLSD is too smart for it's own good and may act like a smart
+ // pointer for the content of (*i), so instead of passing (*i)
+ // pass a prepared name and move ownership of "body",
+ // as we are not going to need "body" anywhere else.
+ std::string msg_name = (*i)["message"].asString();
+
+ // WARNING: This is a shallow copy!
+ // If something still retains the data (like in httpAdapter?) this might still
+ // result in a crash, if it does appear to be the case, make a deep copy or
+ // convert data to string and pass that string.
+ const LLSD body = (*i)["body"];
+ (*i)["body"].clear();
+ work = [this, msg_name, body]()
{
- handleMessage(msg);
- });
+ handleMessage(msg_name, body);
+ };
+ }
+ main_queue->post(work);
}
else
{
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
index 193a42f9f6..c3aad4ee65 100644
--- a/indra/newview/llexternaleditor.cpp
+++ b/indra/newview/llexternaleditor.cpp
@@ -46,9 +46,13 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env
{
LL_INFOS() << "Editor command is empty or not set, falling back to OS open handler" << LL_ENDL;
#if LL_WINDOWS
- static const std::string os_cmd = "%SystemRoot%\\explorer.exe \"%s\"";
+ std::string os_cmd = LLStringUtil::getenv("SystemRoot", "");
+ if (!os_cmd.empty())
+ {
+ os_cmd.append("\\explorer.exe \"%s\"");
+ }
#elif LL_DARWIN
- static const std::string os_cmd = "/usr/bin/open \"%s\"";
+ static const std::string os_cmd = "/usr/bin/open -t \"%s\"";
#elif LL_LINUX
static const std::string os_cmd = "/usr/bin/xdg-open \"%s\"";
#endif
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index e9bee93a19..c8692224f1 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -495,7 +495,9 @@ bool LLFeatureManager::loadGPUClass()
{
mGPUClass = GPU_CLASS_2;
}
- else if (gbps <= class1_gbps*4.f)
+ else if ((gbps <= class1_gbps*4.f)
+ // Cap silicon's GPUs at med+ as they have high throughput, low capability
+ || gGLManager.mIsApple)
{
mGPUClass = GPU_CLASS_3;
}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index c5c1e01538..6e27fd694a 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1735,6 +1735,22 @@ void LLFloaterPreference::onChangeMaturity()
|| sim_access == SIM_ACCESS_ADULT);
getChild<LLIconCtrl>("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT);
+
+ // Update Legacy Search maturity settings
+ bool can_access_mature = gAgent.canAccessMature();
+ bool can_access_adult = gAgent.canAccessAdult();
+ if (!can_access_mature)
+ {
+ gSavedSettings.setBOOL("ShowMatureSims", false);
+ gSavedSettings.setBOOL("ShowMatureLand", false);
+ gSavedSettings.setBOOL("ShowMatureClassifieds", false);
+ }
+ if (!can_access_adult)
+ {
+ gSavedSettings.setBOOL("ShowAdultSims", false);
+ gSavedSettings.setBOOL("ShowAdultLand", false);
+ gSavedSettings.setBOOL("ShowAdultClassifieds", false);
+ }
}
void LLFloaterPreference::onChangeComplexityMode(const LLSD& newvalue)
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 112008172e..5484ce6276 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -903,6 +903,39 @@ private:
};
+F32 shader_timer_benchmark(std::vector<LLRenderTarget> & dest, TextureHolder & texHolder, U32 textures_count, LLVertexBuffer * buff, F32 &seconds)
+{
+ // run GPU timer benchmark
+
+ //number of samples to take
+ const S32 samples = 64;
+
+ {
+ ShaderProfileHelper initProfile;
+ dest[0].bindTarget();
+ gBenchmarkProgram.bind();
+ for (S32 c = 0; c < samples; ++c)
+ {
+ for (U32 i = 0; i < textures_count; ++i)
+ {
+ texHolder.bind(i);
+ buff->setBuffer();
+ buff->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+ }
+ gBenchmarkProgram.unbind();
+ dest[0].flush();
+ }
+
+ F32 ms = gBenchmarkProgram.mTimeElapsed / 1000000.f;
+ seconds = ms / 1000.f;
+
+ F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn;
+ F64 gpixels_drawn = samples_drawn / 1000000000.0;
+ F32 samples_sec = (F32)(gpixels_drawn / seconds);
+ return samples_sec * 4; // 4 bytes per sample
+}
+
//-----------------------------------------------------------------------------
// gpu_benchmark()
// returns measured memory bandwidth of GPU in gigabytes per second
@@ -944,9 +977,6 @@ F32 gpu_benchmark()
//number of textures
const U32 count = 32;
- //number of samples to take
- const S32 samples = 64;
-
//time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark.
const F32 time_limit = 30;
@@ -1036,33 +1066,15 @@ F32 gpu_benchmark()
LLGLSLShader::unbind();
- // run GPU timer benchmark
- {
- ShaderProfileHelper initProfile;
- dest[0].bindTarget();
- gBenchmarkProgram.bind();
- for (S32 c = 0; c < samples; ++c)
- {
- for (U32 i = 0; i < count; ++i)
- {
- texHolder.bind(i);
- buff->setBuffer();
- buff->drawArrays(LLRender::TRIANGLES, 0, 3);
- }
- }
- gBenchmarkProgram.unbind();
- dest[0].flush();
- }
+ // run GPU timer benchmark twice
+ F32 seconds = 0;
+ F32 gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds);
- F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f;
- F32 seconds = ms/1000.f;
+ LL_INFOS("Benchmark") << "Memory bandwidth, 1st run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
- F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn;
- F64 gpixels_drawn = samples_drawn / 1000000000.0;
- F32 samples_sec = (F32)(gpixels_drawn/seconds);
- F32 gbps = samples_sec*4; // 4 bytes per sample
+ gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds);
- LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
+ LL_INFOS("Benchmark") << "Memory bandwidth, final run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
return gbps;
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 848f28f933..aa884b8e9f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1860,7 +1860,14 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
{
LLVector3d global_pos;
landmark->getGlobalPos(global_pos);
- LLLandmarkActions::getSLURLfromPosGlobal(global_pos, &copy_slurl_to_clipboard_callback_inv, true);
+ if (!global_pos.isExactlyZero())
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos, &copy_slurl_to_clipboard_callback_inv, true);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ }
}
}
}
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index fe007a78cd..2576da0a75 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -338,14 +338,21 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
{
LLVector3d global_pos;
landmark->getGlobalPos(global_pos);
- boost::function<void(std::string& slurl)> copy_slurl_to_clipboard_cb = [](const std::string& slurl)
+ if (!global_pos.isExactlyZero())
{
- gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
- LLSD args;
- args["SLURL"] = slurl;
- LLNotificationsUtil::add("CopySLURL", args);
- };
- LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true);
+ boost::function<void(std::string& slurl)> copy_slurl_to_clipboard_cb = [](const std::string& slurl)
+ {
+ gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotificationsUtil::add("CopySLURL", args);
+ };
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ }
};
LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), copy_slurl_cb);
if (landmark)
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 73425e9f4c..b9d1c7ba18 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -80,6 +80,40 @@ public:
}
};
+class LLFetchFirstLandmarkByPos : public LLInventoryCollectFunctor
+{
+private:
+ LLVector3d mPos;
+ bool mFound = false;
+public:
+ LLFetchFirstLandmarkByPos(const LLVector3d& pos) :
+ mPos(pos), mFound(false)
+ {
+ }
+
+ /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (mFound || !item || item->getType() != LLAssetType::AT_LANDMARK)
+ return false;
+
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+ if (!landmark) // the landmark not been loaded yet
+ return false;
+
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return false;
+ //we have to round off each coordinates to compare positions properly
+ mFound = ll_round(mPos.mdV[VX]) == ll_round(landmark_global_pos.mdV[VX])
+ && ll_round(mPos.mdV[VY]) == ll_round(landmark_global_pos.mdV[VY])
+ && ll_round(mPos.mdV[VZ]) == ll_round(landmark_global_pos.mdV[VZ]);
+ return mFound;
+ }
+
+ // only care about first found landmark, so stop when found
+ /*virtual*/ bool exceedsLimit() { return mFound; }
+};
+
class LLFetchLandmarksByName : public LLInventoryCollectFunctor
{
private:
@@ -155,6 +189,9 @@ public:
mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos);
return mFounded;
}
+
+ // only care about first found landmark, so stop when found
+ /*virtual*/ bool exceedsLimit() { return mFounded; }
};
static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
@@ -197,23 +234,61 @@ bool LLLandmarkActions::landmarkAlreadyExists()
//static
bool LLLandmarkActions::hasParcelLandmark()
{
+ static LLUUID sLastItemID;
+ static S32 sLastFrame = -1;
+ if (sLastItemID.notNull())
+ {
+ LLInventoryItem* item = gInventory.getItem(sLastItemID);
+ if (item)
+ {
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+ if (landmark)
+ {
+ LLVector3d landmark_global_pos;
+ if (landmark->getGlobalPos(landmark_global_pos)
+ && LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos))
+ {
+ return true;
+ }
+ }
+ }
+ // Cached landmark does not match current parcel anymore,
+ // repeat inventory search to find a replacement landmark
+ // or to make sure there are none.
+ sLastItemID.setNull();
+ sLastFrame = -1;
+ }
+
+ if (sLastFrame == LLFrameTimer::getFrameCount())
+ {
+ // Ideally this should also check parcel change and landmark additions,
+ // not just frame change.
+ // But should be sufficient to check only frame as this is used
+ // after inventory and parcel operations.
+ return false;
+ }
+ sLastFrame = LLFrameTimer::getFrameCount();
+
LLFirstAgentParcelLandmark get_first_agent_landmark;
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
fetch_landmarks(cats, items, get_first_agent_landmark);
- return !items.empty();
-
+ if (!items.empty())
+ {
+ sLastItemID = items[0]->getUUID();
+ return true;
+ }
+ return false;
}
-// *TODO: This could be made more efficient by only fetching the FIRST
-// landmark that meets the criteria
LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos)
{
// Determine whether there are landmarks pointing to the current parcel.
+ // Will stop after first found landmark.
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
- LLFetchlLandmarkByPos is_current_pos_landmark(pos);
- fetch_landmarks(cats, items, is_current_pos_landmark);
+ LLFetchFirstLandmarkByPos get_landmark_from_pos(pos);
+ fetch_landmarks(cats, items, get_landmark_from_pos);
if(items.empty())
{
@@ -385,7 +460,14 @@ void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItem
{
LLVector3d global_pos;
landmark->getGlobalPos(global_pos);
- LLLandmarkActions::getSLURLfromPosGlobal(global_pos,&copy_slurl_to_clipboard_callback,true);
+ if (!global_pos.isExactlyZero())
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos, &copy_slurl_to_clipboard_callback, true);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LandmarkLocationUnknown");
+ }
}
}
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 3fa0ab99f3..b25a42a938 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -147,29 +147,66 @@ void LLLandmarkList::processGetAssetReply(
else
{
// failed to parse, shouldn't happen
+ LL_WARNS("Landmarks") << "Failed to parse landmark " << uuid << LL_ENDL;
gLandmarkList.eraseCallbacks(uuid);
}
}
else
{
// got a good status, but no file, shouldn't happen
+ LL_WARNS("Landmarks") << "Empty buffer for landmark " << uuid << LL_ENDL;
gLandmarkList.eraseCallbacks(uuid);
}
+
+ // We got this asset, remove it from retry and bad lists.
+ gLandmarkList.mRetryList.erase(uuid);
+ gLandmarkList.mBadList.erase(uuid);
}
else
{
- // SJB: No use case for a notification here. Use LL_DEBUGS() instead
- if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
+ if (LL_ERR_NO_CAP == status)
+ {
+ // A problem with asset cap, always allow retrying.
+ // Todo: should this reschedule?
+ gLandmarkList.mRequestedList.erase(uuid);
+ gLandmarkList.eraseCallbacks(uuid);
+ // If there was a previous request, it likely failed due to an obsolete cap
+ // so clear the retry marker to allow multiple retries.
+ gLandmarkList.mRetryList.erase(uuid);
+ return;
+ }
+ if (gLandmarkList.mBadList.find(uuid) != gLandmarkList.mBadList.end())
+ {
+ // Already on the 'bad' list, ignore
+ gLandmarkList.mRequestedList.erase(uuid);
+ gLandmarkList.eraseCallbacks(uuid);
+ return;
+ }
+ if (LL_ERR_ASSET_REQUEST_FAILED == status
+ && gLandmarkList.mRetryList.find(uuid) == gLandmarkList.mRetryList.end())
+ {
+ // There is a number of reasons why an asset request can fail,
+ // like a cap being obsolete due to user teleporting.
+ // Let viewer rerequest at least once more.
+ // Todo: should this reshchedule?
+ gLandmarkList.mRetryList.emplace(uuid);
+ gLandmarkList.mRequestedList.erase(uuid);
+ gLandmarkList.eraseCallbacks(uuid);
+ return;
+ }
+
+ if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status)
{
- LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL;
- //LLNotificationsUtil::add("LandmarkMissing");
+ LL_WARNS("Landmarks") << "Missing Landmark " << uuid << LL_ENDL;
}
else
{
- LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL;
- //LLNotificationsUtil::add("UnableToLoadLandmark");
+ LL_WARNS("Landmarks") << "Unable to load Landmark " << uuid
+ << ". asset status: " << status
+ << ". Extended status: " << (S64)ext_status << LL_ENDL;
}
+ gLandmarkList.mRetryList.erase(uuid);
gLandmarkList.mBadList.insert(uuid);
gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests
gLandmarkList.eraseCallbacks(uuid);
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index fb8b5a1960..76b5b97211 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -72,6 +72,7 @@ protected:
typedef std::set<LLUUID> landmark_uuid_list_t;
landmark_uuid_list_t mBadList;
+ landmark_uuid_list_t mRetryList;
typedef std::map<LLUUID,F32> landmark_requested_list_t;
landmark_requested_list_t mRequestedList;
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 9157e34833..f47a8cd241 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -803,6 +803,10 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
std::string unclean_filename;
msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, unclean_filename);
std::string filename = LLDir::getScrubbedFileName(unclean_filename);
+ if (filename.empty())
+ {
+ LL_WARNS() << "Received empty mute list filename." << LL_ENDL;
+ }
LLMuteList* mute_list = getInstance();
mute_list->mLoadState = ML_REQUESTED;
@@ -835,16 +839,16 @@ void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**)
void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_status)
{
- LL_INFOS() << "LLMuteList::processMuteListFile()" << LL_ENDL;
-
std::string* local_filename_and_path = (std::string*)user_data;
if(local_filename_and_path && !local_filename_and_path->empty() && (error_code == 0))
{
+ LL_INFOS() << "Received mute list from server" << LL_ENDL;
LLMuteList::getInstance()->loadFromFile(*local_filename_and_path);
LLFile::remove(*local_filename_and_path);
}
else
{
+ LL_INFOS() << "LLMuteList xfer failed with code " << error_code << LL_ENDL;
LLMuteList::getInstance()->mLoadState = ML_FAILED;
}
delete local_filename_and_path;
diff --git a/indra/newview/llpaneldirbrowser.cpp b/indra/newview/llpaneldirbrowser.cpp
index 8c981cad55..69329c4ea4 100644
--- a/indra/newview/llpaneldirbrowser.cpp
+++ b/indra/newview/llpaneldirbrowser.cpp
@@ -559,9 +559,6 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**)
LLUUID owner_id;
std::string name;
std::string date;
- bool show_pg = gSavedSettings.getBOOL("ShowPGEvents");
- bool show_mature = gSavedSettings.getBOOL("ShowMatureEvents");
- bool show_adult = gSavedSettings.getBOOL("ShowAdultEvents");
msg->getUUID("AgentData", "AgentID", agent_id);
msg->getUUID("QueryData", "QueryID", query_id );
@@ -618,27 +615,6 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**)
LL_WARNS() << "skipped event due to owner_id null, event_id " << event_id << LL_ENDL;
continue;
}
-
- // skip events that don't match the flags
- // there's no PG flag, so we make sure neither adult nor mature is set
- if (((event_flags & (EVENT_FLAG_ADULT | EVENT_FLAG_MATURE)) == EVENT_FLAG_NONE) && !show_pg)
- {
- //llwarns << "Skipped pg event because we're not showing pg, event_id " << event_id << llendl;
- continue;
- }
-
- if ((event_flags & EVENT_FLAG_MATURE) && !show_mature)
- {
- //llwarns << "Skipped mature event because we're not showing mature, event_id " << event_id << llendl;
- continue;
- }
-
- if ((event_flags & EVENT_FLAG_ADULT) && !show_adult)
- {
- //llwarns << "Skipped adult event because we're not showing adult, event_id " << event_id << llendl;
- continue;
- }
-
LLSD content;
content["type"] = EVENT_CODE;
diff --git a/indra/newview/llpaneldirevents.cpp b/indra/newview/llpaneldirevents.cpp
index 227ed877cd..7ac1229637 100644
--- a/indra/newview/llpaneldirevents.cpp
+++ b/indra/newview/llpaneldirevents.cpp
@@ -143,18 +143,17 @@ void LLPanelDirEvents::performQueryOrDelete(U32 event_id)
static LLUICachedControl<bool> incpg("ShowPGEvents", true);
static LLUICachedControl<bool> incmature("ShowMatureEvents", false);
static LLUICachedControl<bool> incadult("ShowAdultEvents", false);
+ if (!(incpg || incmature || incadult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
U32 scope = DFQ_DATE_EVENTS;
if (incpg) scope |= DFQ_INC_PG;
if (incmature && gAgent.canAccessMature()) scope |= DFQ_INC_MATURE;
if (incadult && gAgent.canAccessAdult()) scope |= DFQ_INC_ADULT;
- if ( !( scope & (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT )))
- {
- LLNotificationsUtil::add("NoContentToSearch");
- return;
- }
-
setupNewSearch();
std::ostringstream params;
diff --git a/indra/newview/llpaneldirland.cpp b/indra/newview/llpaneldirland.cpp
index 53c58d8fa9..f85a8b948e 100644
--- a/indra/newview/llpaneldirland.cpp
+++ b/indra/newview/llpaneldirland.cpp
@@ -62,20 +62,6 @@ bool LLPanelDirLand::postBuild()
childSetValue("type", gSavedSettings.getString("FindLandType"));
- bool adult_enabled = gAgent.canAccessAdult();
- bool mature_enabled = gAgent.canAccessMature();
- childSetVisible("incpg", true);
- if (!mature_enabled)
- {
- childSetValue("incmature", false);
- childDisable("incmature");
- }
- if (!adult_enabled)
- {
- childSetValue("incadult", false);
- childDisable("incadult");
- }
-
childSetCommitCallback("pricecheck", onCommitPrice, this);
childSetCommitCallback("areacheck", onCommitArea, this);
diff --git a/indra/newview/llpaneldirplaces.cpp b/indra/newview/llpaneldirplaces.cpp
index 2d54566038..3501baf697 100644
--- a/indra/newview/llpaneldirplaces.cpp
+++ b/indra/newview/llpaneldirplaces.cpp
@@ -121,6 +121,11 @@ void LLPanelDirPlaces::performQuery()
static LLUICachedControl<bool> inc_pg("ShowPGSims", true);
static LLUICachedControl<bool> inc_mature("ShowMatureSims", false);
static LLUICachedControl<bool> inc_adult("ShowAdultSims", false);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
if (inc_pg)
{
@@ -137,12 +142,6 @@ void LLPanelDirPlaces::performQuery()
flags |= DFQ_INC_ADULT;
}
- if (0x0 == flags)
- {
- LLNotificationsUtil::add("NoContentToSearch");
- return;
- }
-
queryCore(query_string, category, flags);
}
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index de8ab95dee..bcb51b22ca 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1201,7 +1201,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
// See if that's been overridden by a material setting for same...
//
- LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha);
+ LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode);
// it is invalid to have any alpha mode other than blend if transparency is greater than zero ...
// Want masking? Want emissive? Tough! You get BLEND!
@@ -1211,6 +1211,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
mComboAlphaMode->getSelectionInterface()->selectNthItem(alpha_mode);
+ mComboAlphaMode->setTentative(!identical_alpha_mode);
+ if (!identical_alpha_mode)
+ {
+ std::string multiple = LLTrans::getString("multiple_textures");
+ mComboAlphaMode->setLabel(multiple);
+ }
updateAlphaControls();
mExcludeWater &= (LLMaterial::DIFFUSE_ALPHA_MODE_BLEND == alpha_mode);
@@ -5484,32 +5490,40 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool&
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats);
}
-void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha)
+void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical)
{
struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor<U8>
{
- LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {}
- LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {}
+ LLSelectedTEGetDiffuseAlphaMode() {}
virtual ~LLSelectedTEGetDiffuseAlphaMode() {}
U8 get(LLViewerObject* object, S32 face)
{
- U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
-
LLTextureEntry* tep = object->getTE(face);
if (tep)
{
LLMaterial* mat = tep->getMaterialParams().get();
if (mat)
{
- diffuse_mode = mat->getDiffuseAlphaMode();
+ return mat->getDiffuseAlphaMode();
+ }
+ }
+
+ bool has_alpha = false;
+ LLViewerTexture* image = object->getTEImage(face);
+ if (image)
+ {
+ LLGLenum format = image->getPrimaryFormat();
+ if (format == GL_RGBA || format == GL_ALPHA)
+ {
+ has_alpha = true;
}
}
+ U8 diffuse_mode = has_alpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
return diffuse_mode;
}
- bool _isAlpha; // whether or not the diffuse texture selected contains alpha information
- } get_diff_mode(diffuse_texture_has_alpha);
+ } get_diff_mode;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode);
}
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 63fee6bab8..82790ac54b 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -652,7 +652,7 @@ public:
static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material);
static void getMaxSpecularRepeats(F32& repeats, bool& identical);
static void getMaxNormalRepeats(F32& repeats, bool& identical);
- static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha);
+ static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical);
static void selectionNormalScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter);
static void selectionSpecularScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter);
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 141f370ecb..fd462fb225 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -42,6 +42,7 @@
#include "llcoproceduremanager.h"
#include "lleventcoro.h"
#include "llsdutil.h"
+#include "llstartup.h"
#include "llworld.h"
///----------------------------------------------------------------------------
@@ -460,28 +461,78 @@ void LLViewerAssetStorage::assetRequestCoro(
if (!gAgent.getRegion())
{
- LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL;
- result_code = LL_ERR_ASSET_REQUEST_FAILED;
- ext_status = LLExtStat::NONE;
- removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0);
- return;
+ if (STATE_WORLD_INIT <= LLStartUp::getStartupState())
+ {
+ // Viewer isn't ready, wait for region to become available
+ LL_INFOS_ONCE("ViewerAsset") << "Waiting for agent region to be set" << LL_ENDL;
+
+ LLEventStream region_init("waitForRegion", true);
+ std::string pump_name = region_init.getName();
+
+ boost::signals2::connection region_conn =
+ gAgent.addRegionChangedCallback([pump_name]()
+ {
+ LLEventPumps::instance().obtain(pump_name).post(LLSD());
+ });
+ F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT);
+ llcoro::suspendUntilEventOnWithTimeout(region_init, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true)));
+ gAgent.removeRegionChangedCallback(region_conn);
+ region_conn.disconnect();
+
+ if (LLApp::isExiting() || !gAssetStorage)
+ {
+ return;
+ }
+
+ // recheck region whether suspend ended on timeout or not
+ if (!gAgent.getRegion())
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: timeout reached while waiting for region" << LL_ENDL;
+ result_code = LL_ERR_NO_CAP;
+ ext_status = LLExtStat::NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0);
+ return;
+ }
+ }
+ else
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL;
+ result_code = LL_ERR_NO_CAP;
+ ext_status = LLExtStat::NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0);
+ return;
+ }
}
- else if (!gAgent.getRegion()->capabilitiesReceived())
+
+ if (!gAgent.getRegion()->capabilitiesReceived())
{
LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL;
LLEventStream capsRecv("waitForCaps", true);
- gAgent.getRegion()->setCapabilitiesReceivedCallback(
- boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName()));
+ boost::signals2::connection caps_conn =
+ gAgent.getRegion()->setCapabilitiesReceivedCallback(
+ boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName()));
- llcoro::suspendUntilEventOn(capsRecv);
+ F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT); // from minutes to seconds, by default 5 minutes
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(capsRecv, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true)));
+ caps_conn.disconnect();
if (LLApp::isExiting() || !gAssetStorage)
{
return;
}
+ if (result.has("timeout"))
+ {
+ // Caps failed to arrive in 5 minutes
+ LL_WARNS_ONCE("ViewerAsset") << "Asset " << uuid << " request fails : capabilities took too long to arrive" << LL_ENDL;
+ result_code = LL_ERR_NO_CAP;
+ ext_status = LLExtStat::NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0);
+ return;
+ }
+
LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL;
LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL;
}
@@ -492,7 +543,7 @@ void LLViewerAssetStorage::assetRequestCoro(
if (mViewerAssetUrl.empty())
{
LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL;
- result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ result_code = LL_ERR_NO_CAP;
ext_status = LLExtStat::NONE;
removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0);
return;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index abaf813530..c9f10d845f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6666,11 +6666,8 @@ class LLAvatarEnableResetSkeleton : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()))
- {
- return true;
- }
- return false;
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ return obj && obj->getAvatar();
}
};
@@ -8715,6 +8712,12 @@ LLVOAvatar* find_avatar_from_object(LLViewerObject* object)
}
else if( !object->isAvatar() )
{
+ // Check for animesh objects (animated objects with a control avatar)
+ LLVOAvatar* avatar = object->getAvatar();
+ if (avatar)
+ {
+ return avatar;
+ }
object = NULL;
}
}
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 3efcd763e3..80a0e3e5c0 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -2549,10 +2549,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded()
LL::WorkQueue::postMaybe(mMainQueue,
[=, this] {
LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL;
- if (!mShutDown)
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
- }
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
mCurrentStatus = LLVoiceClientStatusObserver::ERROR_UNKNOWN;
});
}
@@ -2898,9 +2895,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
// this connection.
// For spatial this connection will come up as muted, but will be set to the appropriate
// value later on when we determine the regions we connect to.
- if (!isSpatial())
+ if (isSpatial())
{
- mWebRTCAudioInterface->setMute(mMuted);
+ // we'll determine primary state later and set mute accordinly
+ mPrimary = false;
}
mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume);
LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID);
@@ -2924,6 +2922,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
LLWebRTCVoiceClient::getInstance()->updatePosition();
LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true);
}
+ else
+ {
+ mWebRTCAudioInterface->setMute(mMuted);
+ }
}
break;
}
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fe77fbb5c5..9b1d47ac9d 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2483,7 +2483,7 @@ You already have a landmark for this location.
icon="alert.tga"
name="LandmarkLocationUnknown"
type="alert">
-Viewer wasn't able to get region's location. Region might be temporarily unavailable or was removed.
+Viewer wasn't able to get region's location. Region might be temporarily unavailable, was removed or landmark failed to load.
<usetemplate
name="okbutton"
yestext="OK"/>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 648860553c..32ec7a3e5b 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -259,9 +259,10 @@ class ViewerManifest(LLManifest):
global CHANNEL_VENDOR_BASE
channel_type=self.channel_type()
if channel_type == 'release':
- return CHANNEL_VENDOR_BASE
+ app_suffix='Viewer'
else:
- return CHANNEL_VENDOR_BASE + ' ' + self.channel_variant()
+ app_suffix=self.channel_variant()
+ return CHANNEL_VENDOR_BASE + ' ' + app_suffix
def exec_name(self):
return "SecondLifeViewer"