mirror of
https://github.com/FirestormViewer/phoenix-firestorm.git
synced 2026-08-14 00:48:30 +00:00
Merge branch 'release/2026.01' into project/one-click
This commit is contained in:
+7
-7
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
|
||||
@@ -84,6 +84,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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>(); }
|
||||
|
||||
|
||||
@@ -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--;
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1860,7 +1860,14 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
{
|
||||
LLVector3d global_pos;
|
||||
landmark->getGlobalPos(global_pos);
|
||||
LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback_inv, true);
|
||||
if (!global_pos.isExactlyZero())
|
||||
{
|
||||
LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback_inv, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("LandmarkLocationUnknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,©_slurl_to_clipboard_callback,true);
|
||||
if (!global_pos.isExactlyZero())
|
||||
{
|
||||
LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("LandmarkLocationUnknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL;
|
||||
//LLNotificationsUtil::add("LandmarkMissing");
|
||||
// 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 " << 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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user