Merge branch 'main' into marchcat/maint-c-restore
# Conflicts: # indra/llcommon/lldate.h # indra/newview/llappviewer.cpp # indra/newview/llinventorybridge.cpp # indra/newview/llmaterialeditor.cpp # indra/newview/llviewerparceloverlay.cpp # indra/newview/llvoavatar.cppmaster
commit
ae93198735
|
|
@ -2039,11 +2039,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>191e4ef07a35f7147708415465191ce7622e3012</string>
|
||||
<string>a3cc405d48a48a474d05b3de3d28da2005d80037</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-darwin64-8979520327.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-darwin64-13245988487.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2053,11 +2053,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3bd8c9028ef42bdb43c7422e7d324e213fdb081e</string>
|
||||
<string>a2b63f0f85ca156c59ee1d34ef96c8e50b89153c</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-linux64-8979520327.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-linux64-13245988487.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -2067,11 +2067,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>4b849609abec790e89be5fad8ddee3717ee301c4</string>
|
||||
<string>8ad24fba1191c9cb0d2ab36e64b04b4648a99f43</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-windows64-8979520327.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-windows64-13245988487.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -2988,14 +2988,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>build</key>
|
||||
<map>
|
||||
<key>command</key>
|
||||
<string>xcodebuild</string>
|
||||
<string>cmake</string>
|
||||
<key>options</key>
|
||||
<array>
|
||||
<string>-configuration</string>
|
||||
<string>--build</string>
|
||||
<string>.</string>
|
||||
<string>--config</string>
|
||||
<string>RelWithDebInfo</string>
|
||||
<string>-project</string>
|
||||
<string>SecondLife.xcodeproj</string>
|
||||
<string>-parallelizeTargets</string>
|
||||
<string>--parallel</string>
|
||||
<string>$AUTOBUILD_CPU_COUNT</string>
|
||||
</array>
|
||||
</map>
|
||||
<key>default</key>
|
||||
|
|
@ -3016,14 +3017,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>build</key>
|
||||
<map>
|
||||
<key>command</key>
|
||||
<string>xcodebuild</string>
|
||||
<string>cmake</string>
|
||||
<key>options</key>
|
||||
<array>
|
||||
<string>-configuration</string>
|
||||
<string>--build</string>
|
||||
<string>.</string>
|
||||
<string>--config</string>
|
||||
<string>RelWithDebInfo</string>
|
||||
<string>-project</string>
|
||||
<string>SecondLife.xcodeproj</string>
|
||||
<string>-parallelizeTargets</string>
|
||||
<string>--parallel</string>
|
||||
<string>$AUTOBUILD_CPU_COUNT</string>
|
||||
</array>
|
||||
</map>
|
||||
<key>name</key>
|
||||
|
|
@ -3046,14 +3048,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>build</key>
|
||||
<map>
|
||||
<key>command</key>
|
||||
<string>xcodebuild</string>
|
||||
<string>cmake</string>
|
||||
<key>options</key>
|
||||
<array>
|
||||
<string>-configuration</string>
|
||||
<string>--build</string>
|
||||
<string>.</string>
|
||||
<string>--config</string>
|
||||
<string>Release</string>
|
||||
<string>-project</string>
|
||||
<string>SecondLife.xcodeproj</string>
|
||||
<string>-parallelizeTargets</string>
|
||||
<string>--parallel</string>
|
||||
<string>$AUTOBUILD_CPU_COUNT</string>
|
||||
</array>
|
||||
</map>
|
||||
<key>name</key>
|
||||
|
|
@ -3072,14 +3075,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>build</key>
|
||||
<map>
|
||||
<key>command</key>
|
||||
<string>xcodebuild</string>
|
||||
<string>cmake</string>
|
||||
<key>options</key>
|
||||
<array>
|
||||
<string>-configuration</string>
|
||||
<string>--build</string>
|
||||
<string>.</string>
|
||||
<string>--config</string>
|
||||
<string>Release</string>
|
||||
<string>-project</string>
|
||||
<string>SecondLife.xcodeproj</string>
|
||||
<string>-parallelizeTargets</string>
|
||||
<string>--parallel</string>
|
||||
<string>$AUTOBUILD_CPU_COUNT</string>
|
||||
</array>
|
||||
</map>
|
||||
<key>name</key>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ add_compile_definitions(BOOST_BIND_GLOBAL_PLACEHOLDERS)
|
|||
|
||||
# Force enable SSE2 instructions in GLM per the manual
|
||||
# https://github.com/g-truc/glm/blob/master/manual.md#section2_10
|
||||
add_compile_definitions(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES=1 GLM_FORCE_SSE2=1)
|
||||
add_compile_definitions(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES=1 GLM_FORCE_SSE2=1 GLM_ENABLE_EXPERIMENTAL=1)
|
||||
|
||||
# Configure crash reporting
|
||||
set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
|
||||
|
|
@ -48,6 +48,11 @@ if(NON_RELEASE_CRASH_REPORTING)
|
|||
add_compile_definitions( LL_SEND_CRASH_REPORTS=1)
|
||||
endif()
|
||||
|
||||
set(USE_LTO OFF CACHE BOOL "Enable Link Time Optimization")
|
||||
if(USE_LTO)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
endif()
|
||||
|
||||
# Don't bother with a MinSizeRel or Debug builds.
|
||||
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release" CACHE STRING "Supported build types." FORCE)
|
||||
|
||||
|
|
@ -101,7 +106,7 @@ if (WINDOWS)
|
|||
|
||||
#ND: When using something like buildcache (https://github.com/mbitsnbites/buildcache)
|
||||
# to make those wrappers work /Zi must be changed to /Z7, as /Zi due to it's nature is not compatible with caching
|
||||
if( ${CMAKE_CXX_COMPILER_LAUNCHER} MATCHES ".*cache.*")
|
||||
if(${CMAKE_CXX_COMPILER_LAUNCHER} MATCHES ".*cache.*")
|
||||
add_compile_options( /Z7 )
|
||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
|
|
|||
|
|
@ -799,7 +799,6 @@ void LLAvatarAppearance::buildCharacter()
|
|||
bool status = loadAvatar();
|
||||
stop_glerror();
|
||||
|
||||
// gPrintMessagesThisFrame = true;
|
||||
LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL;
|
||||
|
||||
if (!status)
|
||||
|
|
|
|||
|
|
@ -981,7 +981,7 @@ void LLPolyMesh::initializeForMorph()
|
|||
LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
|
||||
memcpy((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices)); // allocated in LLPolyMeshSharedData::allocateVertexData
|
||||
|
||||
for (S32 i = 0; i < mSharedData->mNumVertices; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -645,9 +645,10 @@ void LLWearable::addVisualParam(LLVisualParam *param)
|
|||
|
||||
void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
|
||||
{
|
||||
if( is_in_map(mVisualParamIndexMap, param_index ) )
|
||||
visual_param_index_map_t::iterator found = mVisualParamIndexMap.find(param_index);
|
||||
if(found != mVisualParamIndexMap.end())
|
||||
{
|
||||
LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
|
||||
LLVisualParam *wearable_param = found->second;
|
||||
wearable_param->setWeight(value);
|
||||
}
|
||||
else
|
||||
|
|
@ -658,10 +659,10 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
|
|||
|
||||
F32 LLWearable::getVisualParamWeight(S32 param_index) const
|
||||
{
|
||||
if( is_in_map(mVisualParamIndexMap, param_index ) )
|
||||
visual_param_index_map_t::const_iterator found = mVisualParamIndexMap.find(param_index);
|
||||
if(found != mVisualParamIndexMap.end())
|
||||
{
|
||||
const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second;
|
||||
return wearable_param->getWeight();
|
||||
return found->second->getWeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -726,7 +727,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
|
|||
if (!avatarp) return;
|
||||
|
||||
// Pull params
|
||||
for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() )
|
||||
for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() )
|
||||
{
|
||||
// cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the
|
||||
// avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way.
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ bool LLAudioEngine_OpenAL::init(void* userdata, const std::string &app_title)
|
|||
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
|
||||
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
|
||||
LL_INFOS() << "ALC version: " << major << "." << minor << LL_ENDL;
|
||||
|
||||
LL_INFOS() << "ALC default device: "
|
||||
|
|
@ -190,6 +190,8 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
|
|||
void LLAudioChannelOpenAL::cleanup()
|
||||
{
|
||||
alSourceStop(mALSource);
|
||||
alSourcei(mALSource, AL_BUFFER, AL_NONE);
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ public:
|
|||
LLRunner& getRunner() { return mRunner; }
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { }
|
||||
virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -310,25 +310,54 @@ namespace
|
|||
|
||||
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
|
||||
|
||||
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
|
||||
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
|
||||
{
|
||||
if (code == STATUS_MSC_EXCEPTION)
|
||||
if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
|
||||
{
|
||||
// Handled
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else if (code == STATUS_MSC_EXCEPTION)
|
||||
{
|
||||
// C++ exception, go on
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle it
|
||||
// handle it, convert to std::exception
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
void cpphandle(const LLCoros::callable_t& callable, const std::string& name)
|
||||
{
|
||||
// SE and C++ can not coexists, thus two handlers
|
||||
try
|
||||
{
|
||||
callable();
|
||||
}
|
||||
catch (const LLCoros::Stop& exc)
|
||||
{
|
||||
LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
|
||||
<< exc.what() << LL_ENDL;
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
// Any uncaught exception derived from LLContinueError will be caught
|
||||
// here and logged. This coroutine will terminate but the rest of the
|
||||
// viewer will carry on.
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
|
||||
}
|
||||
}
|
||||
|
||||
void sehandle(const LLCoros::callable_t& callable)
|
||||
void sehandle(const LLCoros::callable_t& callable, const std::string& name)
|
||||
{
|
||||
__try
|
||||
{
|
||||
callable();
|
||||
// handle stop and continue exceptions first
|
||||
cpphandle(callable, name);
|
||||
}
|
||||
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
|
||||
{
|
||||
|
|
@ -340,16 +369,7 @@ void sehandle(const LLCoros::callable_t& callable)
|
|||
throw std::exception(integer_string);
|
||||
}
|
||||
}
|
||||
|
||||
#else // ! LL_WINDOWS
|
||||
|
||||
inline void sehandle(const LLCoros::callable_t& callable)
|
||||
{
|
||||
callable();
|
||||
}
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
#endif // LL_WINDOWS
|
||||
} // anonymous namespace
|
||||
|
||||
// Top-level wrapper around caller's coroutine callable.
|
||||
|
|
@ -362,10 +382,14 @@ void LLCoros::toplevel(std::string name, callable_t callable)
|
|||
// set it as current
|
||||
mCurrent.reset(&corodata);
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
// can not use __try directly, toplevel requires unwinding, thus use of a wrapper
|
||||
sehandle(callable, name);
|
||||
#else // LL_WINDOWS
|
||||
// run the code the caller actually wants in the coroutine
|
||||
try
|
||||
{
|
||||
sehandle(callable);
|
||||
callable();
|
||||
}
|
||||
catch (const Stop& exc)
|
||||
{
|
||||
|
|
@ -387,6 +411,7 @@ void LLCoros::toplevel(std::string name, callable_t callable)
|
|||
<< name << LL_ENDL;
|
||||
LLCoros::instance().saveException(name, std::current_exception());
|
||||
}
|
||||
#endif // else LL_WINDOWS
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
std::string asRFC1123() const;
|
||||
void toStream(std::ostream&) const;
|
||||
bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
|
||||
std::string toLocalDateString (std::string fmt) const;
|
||||
std::string toLocalDateString(std::string fmt) const;
|
||||
std::string toHTTPDateString (std::string fmt) const;
|
||||
static std::string toHTTPDateString (tm * gmt, std::string fmt);
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llapp.h"
|
||||
#include "llcoros.h"
|
||||
#include LLCOROS_MUTEX_HEADER
|
||||
#include "llerror.h"
|
||||
|
|
@ -105,19 +106,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name)
|
|||
return STRINGIZE("WorkQueue" << num);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
|
||||
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
|
||||
|
||||
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
|
||||
{
|
||||
if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
|
||||
{
|
||||
// Handled
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else if (code == STATUS_MSC_EXCEPTION)
|
||||
{
|
||||
// C++ exception, go on
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle it, convert to std::exception
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
void cpphandle(const LL::WorkQueueBase::Work& work)
|
||||
{
|
||||
// SE and C++ can not coexists, thus two handlers
|
||||
try
|
||||
{
|
||||
work();
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
// Any uncaught exception derived from LLContinueError will be caught
|
||||
// here and logged. This coroutine will terminate but the rest of the
|
||||
// viewer will carry on.
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue"));
|
||||
}
|
||||
}
|
||||
|
||||
void sehandle(const LL::WorkQueueBase::Work& work)
|
||||
{
|
||||
__try
|
||||
{
|
||||
// handle stop and continue exceptions first
|
||||
cpphandle(work);
|
||||
}
|
||||
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
|
||||
{
|
||||
// convert to C++ styled exception
|
||||
char integer_string[512];
|
||||
sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
|
||||
throw std::exception(integer_string);
|
||||
}
|
||||
}
|
||||
#endif // LL_WINDOWS
|
||||
} // anonymous namespace
|
||||
|
||||
void LL::WorkQueueBase::callWork(const Work& work)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
// can not use __try directly, toplevel requires unwinding, thus use of a wrapper
|
||||
sehandle(work);
|
||||
#else // LL_WINDOWS
|
||||
try
|
||||
{
|
||||
work();
|
||||
}
|
||||
catch (...)
|
||||
catch (LLContinueError&)
|
||||
{
|
||||
// No matter what goes wrong with any individual work item, the worker
|
||||
// thread must go on! Log our own instance name with the exception.
|
||||
LOG_UNHANDLED_EXCEPTION(getKey());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Stash any other kind of uncaught exception to be rethrown by main thread.
|
||||
LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
|
||||
<< getKey() << LL_ENDL;
|
||||
|
||||
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); });
|
||||
}
|
||||
#endif // else LL_WINDOWS
|
||||
}
|
||||
|
||||
void LL::WorkQueueBase::error(const std::string& msg)
|
||||
|
|
|
|||
|
|
@ -130,17 +130,6 @@ void LLSettingsBase::saveValuesIfNeeded()
|
|||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLSettingsBase::lerpSettings(LLSettingsBase &other, F64 mix)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
saveValuesIfNeeded();
|
||||
stringset_t skip = getSkipInterpolateKeys();
|
||||
stringset_t slerps = getSlerpKeys();
|
||||
mSettings = interpolateSDMap(mSettings, other.getSettings(), other.getParameterMap(), mix, skip, slerps);
|
||||
setDirtyFlag(true);
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
void LLSettingsBase::lerpVector2(LLVector2& a, const LLVector2& b, F32 mix)
|
||||
{
|
||||
a.mV[0] = lerp(a.mV[0], b.mV[0], mix);
|
||||
|
|
|
|||
|
|
@ -348,13 +348,8 @@ protected:
|
|||
LLSettingsBase();
|
||||
LLSettingsBase(const LLSD setting);
|
||||
|
||||
static LLSD settingValidation(LLSD settings);
|
||||
|
||||
typedef std::set<std::string> stringset_t;
|
||||
|
||||
// combining settings objects. Customize for specific setting types
|
||||
virtual void lerpSettings(LLSettingsBase &other, BlendFactor mix);
|
||||
|
||||
// combining settings maps where it can based on mix rate
|
||||
// @settings initial value (mix==0)
|
||||
// @other target value (mix==1)
|
||||
|
|
|
|||
|
|
@ -279,103 +279,118 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
|
|||
{
|
||||
LLImageDataLock lock(&base);
|
||||
|
||||
S32 data_size = base.getDataSize();
|
||||
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
|
||||
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
mCodeStreamp.reset();
|
||||
|
||||
// It's not clear to nat under what circumstances we would reuse a
|
||||
// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
|
||||
// two U32s and a pointer, so it's not as if it would be a huge overhead
|
||||
// to allocate a new one every time.
|
||||
// Also -- why is base.getData() tested specifically here? If that returns
|
||||
// NULL, shouldn't we bail out of the whole method?
|
||||
if (!mInputp && base.getData())
|
||||
try
|
||||
{
|
||||
// The compressed data has been loaded
|
||||
// Setup the source for the codestream
|
||||
mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
|
||||
}
|
||||
|
||||
if (mInputp)
|
||||
{
|
||||
// This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
|
||||
mInputp->reset();
|
||||
}
|
||||
S32 data_size = base.getDataSize();
|
||||
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
|
||||
|
||||
mCodeStreamp->create(mInputp.get());
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
mCodeStreamp.reset();
|
||||
|
||||
// Set the maximum number of bytes to use from the codestream
|
||||
// *TODO: This seems to be wrong. The base class should have no idea of
|
||||
// how j2c compression works so no good way of computing what's the byte
|
||||
// range to be used.
|
||||
mCodeStreamp->set_max_bytes(max_bytes,true);
|
||||
|
||||
// If you want to flip or rotate the image for some reason, change
|
||||
// the resolution, or identify a restricted region of interest, this is
|
||||
// the place to do it. You may use "kdu_codestream::change_appearance"
|
||||
// and "kdu_codestream::apply_input_restrictions" for this purpose.
|
||||
// If you wish to truncate the code-stream prior to decompression, you
|
||||
// may use "kdu_codestream::set_max_bytes".
|
||||
// If you wish to retain all compressed data so that the material
|
||||
// can be decompressed multiple times, possibly with different appearance
|
||||
// parameters, you should call "kdu_codestream::set_persistent" here.
|
||||
// There are a variety of other features which must be enabled at
|
||||
// this point if you want to take advantage of them. See the
|
||||
// descriptions appearing with the "kdu_codestream" interface functions
|
||||
// in "kdu_compressed.h" for an itemized account of these capabilities.
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_FAST:
|
||||
mCodeStreamp->set_fast();
|
||||
break;
|
||||
case MODE_RESILIENT:
|
||||
mCodeStreamp->set_resilient();
|
||||
break;
|
||||
case MODE_FUSSY:
|
||||
mCodeStreamp->set_fussy();
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
mCodeStreamp->set_fast();
|
||||
}
|
||||
|
||||
kdu_dims dims;
|
||||
mCodeStreamp->get_dims(0,dims);
|
||||
|
||||
S32 components = mCodeStreamp->get_num_components();
|
||||
|
||||
// Check that components have consistent dimensions (for PPM file)
|
||||
for (int idx = 1; idx < components; ++idx)
|
||||
{
|
||||
kdu_dims other_dims;
|
||||
mCodeStreamp->get_dims(idx, other_dims);
|
||||
if (other_dims != dims)
|
||||
// It's not clear to nat under what circumstances we would reuse a
|
||||
// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
|
||||
// two U32s and a pointer, so it's not as if it would be a huge overhead
|
||||
// to allocate a new one every time.
|
||||
// Also -- why is base.getData() tested specifically here? If that returns
|
||||
// NULL, shouldn't we bail out of the whole method?
|
||||
if (!mInputp && base.getData())
|
||||
{
|
||||
// This method is only called from methods that catch KDUError.
|
||||
// We want to fail the image load, not crash the viewer.
|
||||
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
<< stringize(other_dims)
|
||||
<< " do not match component 0 dimensions "
|
||||
<< stringize(dims) << "!")));
|
||||
// The compressed data has been loaded
|
||||
// Setup the source for the codestream
|
||||
mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
|
||||
}
|
||||
|
||||
if (mInputp)
|
||||
{
|
||||
// This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
|
||||
mInputp->reset();
|
||||
}
|
||||
|
||||
mCodeStreamp->create(mInputp.get());
|
||||
|
||||
// Set the maximum number of bytes to use from the codestream
|
||||
// *TODO: This seems to be wrong. The base class should have no idea of
|
||||
// how j2c compression works so no good way of computing what's the byte
|
||||
// range to be used.
|
||||
mCodeStreamp->set_max_bytes(max_bytes, true);
|
||||
|
||||
// If you want to flip or rotate the image for some reason, change
|
||||
// the resolution, or identify a restricted region of interest, this is
|
||||
// the place to do it. You may use "kdu_codestream::change_appearance"
|
||||
// and "kdu_codestream::apply_input_restrictions" for this purpose.
|
||||
// If you wish to truncate the code-stream prior to decompression, you
|
||||
// may use "kdu_codestream::set_max_bytes".
|
||||
// If you wish to retain all compressed data so that the material
|
||||
// can be decompressed multiple times, possibly with different appearance
|
||||
// parameters, you should call "kdu_codestream::set_persistent" here.
|
||||
// There are a variety of other features which must be enabled at
|
||||
// this point if you want to take advantage of them. See the
|
||||
// descriptions appearing with the "kdu_codestream" interface functions
|
||||
// in "kdu_compressed.h" for an itemized account of these capabilities.
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_FAST:
|
||||
mCodeStreamp->set_fast();
|
||||
break;
|
||||
case MODE_RESILIENT:
|
||||
mCodeStreamp->set_resilient();
|
||||
break;
|
||||
case MODE_FUSSY:
|
||||
mCodeStreamp->set_fussy();
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
mCodeStreamp->set_fast();
|
||||
}
|
||||
|
||||
kdu_dims dims;
|
||||
mCodeStreamp->get_dims(0, dims);
|
||||
|
||||
S32 components = mCodeStreamp->get_num_components();
|
||||
|
||||
// Check that components have consistent dimensions (for PPM file)
|
||||
for (int idx = 1; idx < components; ++idx)
|
||||
{
|
||||
kdu_dims other_dims;
|
||||
mCodeStreamp->get_dims(idx, other_dims);
|
||||
if (other_dims != dims)
|
||||
{
|
||||
// This method is only called from methods that catch KDUError.
|
||||
// We want to fail the image load, not crash the viewer.
|
||||
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
<< stringize(other_dims)
|
||||
<< " do not match component 0 dimensions "
|
||||
<< stringize(dims) << "!")));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of resolution levels in that image
|
||||
mLevels = mCodeStreamp->get_min_dwt_levels();
|
||||
|
||||
// Set the base dimensions
|
||||
base.setSize(dims.size.x, dims.size.y, components);
|
||||
base.setLevels(mLevels);
|
||||
|
||||
if (!keep_codestream)
|
||||
{
|
||||
mCodeStreamp.reset();
|
||||
mInputp.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of resolution levels in that image
|
||||
mLevels = mCodeStreamp->get_min_dwt_levels();
|
||||
|
||||
// Set the base dimensions
|
||||
base.setSize(dims.size.x, dims.size.y, components);
|
||||
base.setLevels(mLevels);
|
||||
|
||||
if (!keep_codestream)
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
mCodeStreamp.reset();
|
||||
mInputp.reset();
|
||||
// we are in a thread, can't show an 'out of memory' here,
|
||||
// main thread will keep going
|
||||
throw;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LLTHROW(KDUError(STRINGIZE("Unknown J2C error : " +
|
||||
boost::current_exception_diagnostic_information() << "!")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
|
||||
static LL_ALIGN_16(const F32 M_IDENT_3A[12]) =
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include "llmatrix4a.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include "llrigginginfo.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmemory.h"
|
||||
#include "llmath.h"
|
||||
#include "llquantize.h"
|
||||
|
|
|
|||
|
|
@ -5586,14 +5586,22 @@ struct MikktData
|
|||
{
|
||||
U32 count = face->mNumIndices;
|
||||
|
||||
p.resize(count);
|
||||
n.resize(count);
|
||||
tc.resize(count);
|
||||
t.resize(count);
|
||||
|
||||
if (face->mWeights)
|
||||
try
|
||||
{
|
||||
w.resize(count);
|
||||
p.resize(count);
|
||||
n.resize(count);
|
||||
tc.resize(count);
|
||||
t.resize(count);
|
||||
|
||||
if (face->mWeights)
|
||||
{
|
||||
w.resize(count);
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS("LLCoros") << "Bad memory allocation in MikktData, elements count: " << count << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -5665,7 +5673,16 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
|
|||
// and is executed on a background thread
|
||||
MikktData data(this);
|
||||
mikk::Mikktspace ctx(data);
|
||||
ctx.genTangSpace();
|
||||
try
|
||||
{
|
||||
ctx.genTangSpace();
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
//re-weld
|
||||
meshopt_Stream mos[] =
|
||||
|
|
@ -5678,7 +5695,15 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
|
|||
};
|
||||
|
||||
std::vector<U32> remap;
|
||||
remap.resize(data.p.size());
|
||||
try
|
||||
{
|
||||
remap.resize(data.p.size());
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL;
|
||||
}
|
||||
|
||||
U32 stream_count = data.w.empty() ? 4 : 5;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llvolumeoctree.h"
|
||||
#include "llvector4a.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define LL_V3COLORUTIL_H
|
||||
|
||||
#include "v3color.h"
|
||||
#include "v4color.h"
|
||||
|
||||
inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -585,7 +585,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
// static
|
||||
void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
|
||||
const LLUUID& callback_id, LLAssetType::EType callback_type,
|
||||
S32 result_code, LLExtStat ext_status)
|
||||
S32 result_code, LLExtStat ext_status,
|
||||
S32 bytes_fetched)
|
||||
{
|
||||
// find and callback ALL pending requests for this UUID
|
||||
// SJB: We process the callbacks in reverse order, I do not know if this is important,
|
||||
|
|
@ -598,6 +599,10 @@ void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LL
|
|||
LLAssetRequest* tmp = *curiter;
|
||||
if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type))
|
||||
{
|
||||
if (bytes_fetched > 0)
|
||||
{
|
||||
tmp->mBytesFetched = bytes_fetched;
|
||||
}
|
||||
requests.push_front(tmp);
|
||||
iter = gAssetStorage->mPendingDownloads.erase(curiter);
|
||||
}
|
||||
|
|
@ -664,6 +669,7 @@ void LLAssetStorage::downloadCompleteCallback(
|
|||
callback_type = req->getType();
|
||||
}
|
||||
|
||||
S32 bytes_fetched = 0;
|
||||
if (LL_ERR_NOERR == result)
|
||||
{
|
||||
// we might have gotten a zero-size file
|
||||
|
|
@ -677,21 +683,11 @@ void LLAssetStorage::downloadCompleteCallback(
|
|||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
|
||||
iter != gAssetStorage->mPendingDownloads.end(); ++iter )
|
||||
{
|
||||
LLAssetRequest* dlreq = *iter;
|
||||
if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type))
|
||||
{
|
||||
dlreq->mBytesFetched = vfile.getSize();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bytes_fetched = vfile.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status);
|
||||
removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status, bytes_fetched);
|
||||
}
|
||||
|
||||
void LLAssetStorage::getEstateAsset(
|
||||
|
|
|
|||
|
|
@ -324,7 +324,8 @@ public:
|
|||
|
||||
static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
|
||||
const LLUUID& callback_id, LLAssetType::EType callback_type,
|
||||
S32 result_code, LLExtStat ext_status);
|
||||
S32 result_code, LLExtStat ext_status,
|
||||
S32 bytes_fetched);
|
||||
|
||||
// download process callbacks
|
||||
static void downloadCompleteCallback(
|
||||
|
|
|
|||
|
|
@ -301,12 +301,12 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
|
|||
mPoolSize(size),
|
||||
mActiveCoprocsCount(0),
|
||||
mPending(0),
|
||||
mPendingCoprocs(std::make_shared<CoprocQueue_t>(LLCoprocedureManager::DEFAULT_QUEUE_SIZE)),
|
||||
mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mCoroMapping()
|
||||
{
|
||||
try
|
||||
{
|
||||
mPendingCoprocs = std::make_shared<CoprocQueue_t>(LLCoprocedureManager::DEFAULT_QUEUE_SIZE);
|
||||
// store in our LLTempBoundListener so that when the LLCoprocedurePool is
|
||||
// destroyed, we implicitly disconnect from this LLEventPump
|
||||
// Monitores application status
|
||||
|
|
@ -339,6 +339,11 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
|
|||
|
||||
llassert(0); // Fix Me! Ignoring missing listener!
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS("CoProcMgr") << "Bad memory allocation in LLCoprocedurePool::LLCoprocedurePool!" << LL_ENDL;
|
||||
}
|
||||
|
||||
for (size_t count = 0; count < mPoolSize; ++count)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -295,7 +295,15 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
|
|||
}
|
||||
else
|
||||
{
|
||||
result = this->handleSuccess(response, status);
|
||||
try
|
||||
{
|
||||
result = this->handleSuccess(response, status);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
buildStatusEntry(response, status, result);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ LLExperienceCache::LLExperienceCache()
|
|||
|
||||
LLExperienceCache::~LLExperienceCache()
|
||||
{
|
||||
// can exit without cleanup()
|
||||
sShutdown = true;
|
||||
}
|
||||
|
||||
void LLExperienceCache::initSingleton()
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
#include "lltimer.h"
|
||||
#include "llhost.h"
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 size) : mHost(host)
|
||||
{
|
||||
mSize = 0;
|
||||
|
|
@ -41,7 +39,7 @@ LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32
|
|||
|
||||
if (size > NET_BUFFER_SIZE)
|
||||
{
|
||||
LL_ERRS() << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << LL_ENDL;
|
||||
LL_ERRS() << "Constructing packet with size=" << size << " > " << NET_BUFFER_SIZE << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -51,7 +49,6 @@ LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32
|
|||
mSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LLPacketBuffer::LLPacketBuffer (S32 hSocket)
|
||||
|
|
@ -59,18 +56,29 @@ LLPacketBuffer::LLPacketBuffer (S32 hSocket)
|
|||
init(hSocket);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
LLPacketBuffer::~LLPacketBuffer ()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
void LLPacketBuffer::init (S32 hSocket)
|
||||
void LLPacketBuffer::init(S32 hSocket)
|
||||
{
|
||||
mSize = receive_packet(hSocket, mData);
|
||||
mHost = ::get_sender();
|
||||
mReceivingIF = ::get_receiving_interface();
|
||||
}
|
||||
|
||||
void LLPacketBuffer::init(const char* buffer, S32 data_size, const LLHost& host)
|
||||
{
|
||||
if (data_size > NET_BUFFER_SIZE)
|
||||
{
|
||||
LL_ERRS() << "Initializing packet with size=" << data_size << " > " << NET_BUFFER_SIZE << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(mData, buffer, data_size);
|
||||
mSize = data_size;
|
||||
mHost = host;
|
||||
mReceivingIF = ::get_receiving_interface();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,20 +35,22 @@ class LLPacketBuffer
|
|||
{
|
||||
public:
|
||||
LLPacketBuffer(const LLHost &host, const char *datap, const S32 size);
|
||||
LLPacketBuffer(S32 hSocket); // receive a packet
|
||||
LLPacketBuffer(S32 hSocket); // receive a packet
|
||||
~LLPacketBuffer();
|
||||
|
||||
S32 getSize() const { return mSize; }
|
||||
const char *getData() const { return mData; }
|
||||
LLHost getHost() const { return mHost; }
|
||||
LLHost getReceivingInterface() const { return mReceivingIF; }
|
||||
|
||||
void init(S32 hSocket);
|
||||
void init(const char* buffer, S32 data_size, const LLHost& host);
|
||||
|
||||
protected:
|
||||
char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */
|
||||
S32 mSize; // size of buffer in bytes
|
||||
LLHost mHost; // source/dest IP and port
|
||||
LLHost mReceivingIF; // source/dest IP and port
|
||||
char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */
|
||||
S32 mSize; // size of buffer in bytes
|
||||
LLHost mHost; // source/dest IP and port
|
||||
LLHost mReceivingIF; // source/dest IP and port
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file llpacketring.cpp
|
||||
* @brief implementation of LLPacketRing class for a packet.
|
||||
* @brief implementation of LLPacketRing class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -43,313 +43,44 @@
|
|||
#include "message.h"
|
||||
#include "u64.h"
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
LLPacketRing::LLPacketRing () :
|
||||
mUseInThrottle(false),
|
||||
mUseOutThrottle(false),
|
||||
mInThrottle(256000.f),
|
||||
mOutThrottle(64000.f),
|
||||
mActualBitsIn(0),
|
||||
mActualBitsOut(0),
|
||||
mMaxBufferLength(64000),
|
||||
mInBufferLength(0),
|
||||
mOutBufferLength(0),
|
||||
mDropPercentage(0.0f),
|
||||
mPacketsToDrop(0x0)
|
||||
constexpr S16 MAX_BUFFER_RING_SIZE = 1024;
|
||||
constexpr S16 DEFAULT_BUFFER_RING_SIZE = 256;
|
||||
|
||||
LLPacketRing::LLPacketRing ()
|
||||
: mPacketRing(DEFAULT_BUFFER_RING_SIZE, nullptr)
|
||||
{
|
||||
LLHost invalid_host;
|
||||
for (size_t i = 0; i < mPacketRing.size(); ++i)
|
||||
{
|
||||
mPacketRing[i] = new LLPacketBuffer(invalid_host, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
LLPacketRing::~LLPacketRing ()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
void LLPacketRing::cleanup ()
|
||||
{
|
||||
LLPacketBuffer *packetp;
|
||||
|
||||
while (!mReceiveQueue.empty())
|
||||
for (auto packet : mPacketRing)
|
||||
{
|
||||
packetp = mReceiveQueue.front();
|
||||
delete packetp;
|
||||
mReceiveQueue.pop();
|
||||
}
|
||||
|
||||
while (!mSendQueue.empty())
|
||||
{
|
||||
packetp = mSendQueue.front();
|
||||
delete packetp;
|
||||
mSendQueue.pop();
|
||||
delete packet;
|
||||
}
|
||||
mPacketRing.clear();
|
||||
mNumBufferedPackets = 0;
|
||||
mNumBufferedBytes = 0;
|
||||
mHeadIndex = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
void LLPacketRing::dropPackets (U32 num_to_drop)
|
||||
{
|
||||
mPacketsToDrop += num_to_drop;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
void LLPacketRing::setDropPercentage (F32 percent_to_drop)
|
||||
{
|
||||
mDropPercentage = percent_to_drop;
|
||||
}
|
||||
|
||||
void LLPacketRing::setUseInThrottle(const bool use_throttle)
|
||||
{
|
||||
mUseInThrottle = use_throttle;
|
||||
}
|
||||
|
||||
void LLPacketRing::setUseOutThrottle(const bool use_throttle)
|
||||
{
|
||||
mUseOutThrottle = use_throttle;
|
||||
}
|
||||
|
||||
void LLPacketRing::setInBandwidth(const F32 bps)
|
||||
{
|
||||
mInThrottle.setRate(bps);
|
||||
}
|
||||
|
||||
void LLPacketRing::setOutBandwidth(const F32 bps)
|
||||
{
|
||||
mOutThrottle.setRate(bps);
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
|
||||
{
|
||||
|
||||
if (mInThrottle.checkOverflow(0))
|
||||
{
|
||||
// We don't have enough bandwidth, don't give them a packet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
LLPacketBuffer *packetp = NULL;
|
||||
if (mReceiveQueue.empty())
|
||||
{
|
||||
// No packets on the queue, don't give them any.
|
||||
return 0;
|
||||
}
|
||||
|
||||
S32 packet_size = 0;
|
||||
packetp = mReceiveQueue.front();
|
||||
mReceiveQueue.pop();
|
||||
packet_size = packetp->getSize();
|
||||
if (packetp->getData() != NULL)
|
||||
{
|
||||
memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
|
||||
}
|
||||
// need to set sender IP/port!!
|
||||
mLastSender = packetp->getHost();
|
||||
mLastReceivingIF = packetp->getReceivingInterface();
|
||||
delete packetp;
|
||||
|
||||
this->mInBufferLength -= packet_size;
|
||||
|
||||
// Adjust the throttle
|
||||
mInThrottle.throttleOverflow(packet_size * 8.f);
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
S32 LLPacketRing::receivePacket (S32 socket, char *datap)
|
||||
{
|
||||
S32 packet_size = 0;
|
||||
|
||||
// If using the throttle, simulate a limited size input buffer.
|
||||
if (mUseInThrottle)
|
||||
{
|
||||
bool done = false;
|
||||
|
||||
// push any current net packet (if any) onto delay ring
|
||||
while (!done)
|
||||
{
|
||||
LLPacketBuffer *packetp;
|
||||
packetp = new LLPacketBuffer(socket);
|
||||
|
||||
if (packetp->getSize())
|
||||
{
|
||||
mActualBitsIn += packetp->getSize() * 8;
|
||||
|
||||
// Fake packet loss
|
||||
if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
|
||||
{
|
||||
mPacketsToDrop++;
|
||||
}
|
||||
|
||||
if (mPacketsToDrop)
|
||||
{
|
||||
delete packetp;
|
||||
packetp = NULL;
|
||||
packet_size = 0;
|
||||
mPacketsToDrop--;
|
||||
}
|
||||
}
|
||||
|
||||
// If we faked packet loss, then we don't have a packet
|
||||
// to use for buffer overflow testing
|
||||
if (packetp)
|
||||
{
|
||||
if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
|
||||
{
|
||||
// Toss it.
|
||||
LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL;
|
||||
delete packetp;
|
||||
packetp = NULL;
|
||||
}
|
||||
else if (packetp->getSize())
|
||||
{
|
||||
mReceiveQueue.push(packetp);
|
||||
mInBufferLength += packetp->getSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete packetp;
|
||||
packetp = NULL;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No packetp, keep going? - no packetp == faked packet loss
|
||||
}
|
||||
}
|
||||
|
||||
// Now, grab data off of the receive queue according to our
|
||||
// throttled bandwidth settings.
|
||||
packet_size = receiveFromRing(socket, datap);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no delay, pull straight from net
|
||||
if (LLProxy::isSOCKSProxyEnabled())
|
||||
{
|
||||
U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
|
||||
packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
|
||||
|
||||
if (packet_size > SOCKS_HEADER_SIZE)
|
||||
{
|
||||
// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
|
||||
memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
|
||||
proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
|
||||
mLastSender.setAddress(header->addr);
|
||||
mLastSender.setPort(ntohs(header->port));
|
||||
|
||||
packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = receive_packet(socket, datap);
|
||||
mLastSender = ::get_sender();
|
||||
}
|
||||
|
||||
mLastReceivingIF = ::get_receiving_interface();
|
||||
|
||||
if (packet_size) // did we actually get a packet?
|
||||
{
|
||||
if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
|
||||
{
|
||||
mPacketsToDrop++;
|
||||
}
|
||||
|
||||
if (mPacketsToDrop)
|
||||
{
|
||||
packet_size = 0;
|
||||
mPacketsToDrop--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return packet_size;
|
||||
bool drop = computeDrop();
|
||||
return (mNumBufferedPackets > 0) ?
|
||||
receiveOrDropBufferedPacket(datap, drop) :
|
||||
receiveOrDropPacket(socket, datap, drop);
|
||||
}
|
||||
|
||||
bool LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
|
||||
bool send_packet_helper(int socket, const char * datap, S32 data_size, LLHost host)
|
||||
{
|
||||
bool status = true;
|
||||
if (!mUseOutThrottle)
|
||||
{
|
||||
return sendPacketImpl(h_socket, send_buffer, buf_size, host );
|
||||
}
|
||||
else
|
||||
{
|
||||
mActualBitsOut += buf_size * 8;
|
||||
LLPacketBuffer *packetp = NULL;
|
||||
// See if we've got enough throttle to send a packet.
|
||||
while (!mOutThrottle.checkOverflow(0.f))
|
||||
{
|
||||
// While we have enough bandwidth, send a packet from the queue or the current packet
|
||||
|
||||
S32 packet_size = 0;
|
||||
if (!mSendQueue.empty())
|
||||
{
|
||||
// Send a packet off of the queue
|
||||
LLPacketBuffer *packetp = mSendQueue.front();
|
||||
mSendQueue.pop();
|
||||
|
||||
mOutBufferLength -= packetp->getSize();
|
||||
packet_size = packetp->getSize();
|
||||
|
||||
status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());
|
||||
|
||||
delete packetp;
|
||||
// Update the throttle
|
||||
mOutThrottle.throttleOverflow(packet_size * 8.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the queue's empty, we can just send this packet right away.
|
||||
status = sendPacketImpl(h_socket, send_buffer, buf_size, host );
|
||||
packet_size = buf_size;
|
||||
|
||||
// Update the throttle
|
||||
mOutThrottle.throttleOverflow(packet_size * 8.f);
|
||||
|
||||
// This was the packet we're sending now, there are no other packets
|
||||
// that we need to send
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We haven't sent the incoming packet, add it to the queue
|
||||
if (mOutBufferLength + buf_size > mMaxBufferLength)
|
||||
{
|
||||
// Nuke this packet, we overflowed the buffer.
|
||||
// Toss it.
|
||||
LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
static LLTimer queue_timer;
|
||||
if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
|
||||
{
|
||||
// Add it to the queue
|
||||
LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL;
|
||||
queue_timer.reset();
|
||||
}
|
||||
packetp = new LLPacketBuffer(host, send_buffer, buf_size);
|
||||
|
||||
mOutBufferLength += packetp->getSize();
|
||||
mSendQueue.push(packetp);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
|
||||
{
|
||||
|
||||
if (!LLProxy::isSOCKSProxyEnabled())
|
||||
{
|
||||
return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
|
||||
return send_packet(socket, datap, data_size, host.getAddress(), host.getPort());
|
||||
}
|
||||
|
||||
char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
|
||||
|
|
@ -361,11 +92,274 @@ bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 bu
|
|||
socks_header->atype = ADDRESS_IPV4;
|
||||
socks_header->frag = 0;
|
||||
|
||||
memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
|
||||
memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, datap, data_size);
|
||||
|
||||
return send_packet( h_socket,
|
||||
return send_packet( socket,
|
||||
headered_send_buffer,
|
||||
buf_size + SOCKS_HEADER_SIZE,
|
||||
data_size + SOCKS_HEADER_SIZE,
|
||||
LLProxy::getInstance()->getUDPProxy().getAddress(),
|
||||
LLProxy::getInstance()->getUDPProxy().getPort());
|
||||
}
|
||||
|
||||
bool LLPacketRing::sendPacket(int socket, const char * datap, S32 data_size, LLHost host)
|
||||
{
|
||||
mActualBytesOut += data_size;
|
||||
return send_packet_helper(socket, datap, data_size, host);
|
||||
}
|
||||
|
||||
void LLPacketRing::dropPackets (U32 num_to_drop)
|
||||
{
|
||||
mPacketsToDrop += num_to_drop;
|
||||
}
|
||||
|
||||
void LLPacketRing::setDropPercentage (F32 percent_to_drop)
|
||||
{
|
||||
mDropPercentage = percent_to_drop;
|
||||
}
|
||||
|
||||
bool LLPacketRing::computeDrop()
|
||||
{
|
||||
bool drop= (mDropPercentage > 0.0f && (ll_frand(100.f) < mDropPercentage));
|
||||
if (drop)
|
||||
{
|
||||
++mPacketsToDrop;
|
||||
}
|
||||
if (mPacketsToDrop > 0)
|
||||
{
|
||||
--mPacketsToDrop;
|
||||
drop = true;
|
||||
}
|
||||
return drop;
|
||||
}
|
||||
|
||||
S32 LLPacketRing::receiveOrDropPacket(S32 socket, char *datap, bool drop)
|
||||
{
|
||||
S32 packet_size = 0;
|
||||
|
||||
// pull straight from socket
|
||||
if (LLProxy::isSOCKSProxyEnabled())
|
||||
{
|
||||
char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */
|
||||
packet_size = receive_packet(socket, buffer);
|
||||
if (packet_size > 0)
|
||||
{
|
||||
mActualBytesIn += packet_size;
|
||||
}
|
||||
|
||||
if (packet_size > SOCKS_HEADER_SIZE)
|
||||
{
|
||||
if (drop)
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
|
||||
packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
|
||||
memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size);
|
||||
proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
|
||||
mLastSender.setAddress(header->addr);
|
||||
mLastSender.setPort(ntohs(header->port));
|
||||
mLastReceivingIF = ::get_receiving_interface();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = receive_packet(socket, datap);
|
||||
if (packet_size > 0)
|
||||
{
|
||||
mActualBytesIn += packet_size;
|
||||
if (drop)
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLastSender = ::get_sender();
|
||||
mLastReceivingIF = ::get_receiving_interface();
|
||||
}
|
||||
}
|
||||
}
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
S32 LLPacketRing::receiveOrDropBufferedPacket(char *datap, bool drop)
|
||||
{
|
||||
assert(mNumBufferedPackets > 0);
|
||||
S32 packet_size = 0;
|
||||
|
||||
S16 ring_size = (S16)(mPacketRing.size());
|
||||
S16 packet_index = (mHeadIndex + ring_size - mNumBufferedPackets) % ring_size;
|
||||
LLPacketBuffer* packet = mPacketRing[packet_index];
|
||||
packet_size = packet->getSize();
|
||||
mLastSender = packet->getHost();
|
||||
mLastReceivingIF = packet->getReceivingInterface();
|
||||
|
||||
--mNumBufferedPackets;
|
||||
mNumBufferedBytes -= packet_size;
|
||||
if (mNumBufferedPackets == 0)
|
||||
{
|
||||
assert(mNumBufferedBytes == 0);
|
||||
}
|
||||
|
||||
if (!drop)
|
||||
{
|
||||
assert(packet_size > 0);
|
||||
memcpy(datap, packet->getData(), packet_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
S32 LLPacketRing::bufferInboundPacket(S32 socket)
|
||||
{
|
||||
if (mNumBufferedPackets == mPacketRing.size() && mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
|
||||
{
|
||||
expandRing();
|
||||
}
|
||||
|
||||
LLPacketBuffer* packet = mPacketRing[mHeadIndex];
|
||||
S32 old_packet_size = packet->getSize();
|
||||
S32 packet_size = 0;
|
||||
if (LLProxy::isSOCKSProxyEnabled())
|
||||
{
|
||||
char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */
|
||||
packet_size = receive_packet(socket, buffer);
|
||||
if (packet_size > 0)
|
||||
{
|
||||
mActualBytesIn += packet_size;
|
||||
if (packet_size > SOCKS_HEADER_SIZE)
|
||||
{
|
||||
// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
|
||||
|
||||
proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
|
||||
LLHost sender;
|
||||
sender.setAddress(header->addr);
|
||||
sender.setPort(ntohs(header->port));
|
||||
|
||||
packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
|
||||
packet->init(buffer + SOCKS_HEADER_SIZE, packet_size, sender);
|
||||
|
||||
mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size());
|
||||
if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
|
||||
{
|
||||
++mNumBufferedPackets;
|
||||
mNumBufferedBytes += packet_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we overwrote an older packet
|
||||
mNumBufferedBytes += packet_size - old_packet_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->init(socket);
|
||||
packet_size = packet->getSize();
|
||||
if (packet_size > 0)
|
||||
{
|
||||
mActualBytesIn += packet_size;
|
||||
|
||||
mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size());
|
||||
if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
|
||||
{
|
||||
++mNumBufferedPackets;
|
||||
mNumBufferedBytes += packet_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we overwrote an older packet
|
||||
mNumBufferedBytes += packet_size - old_packet_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
S32 LLPacketRing::drainSocket(S32 socket)
|
||||
{
|
||||
// drain into buffer
|
||||
S32 packet_size = 1;
|
||||
S32 num_loops = 0;
|
||||
S32 old_num_packets = mNumBufferedPackets;
|
||||
while (packet_size > 0)
|
||||
{
|
||||
packet_size = bufferInboundPacket(socket);
|
||||
++num_loops;
|
||||
}
|
||||
S32 num_dropped_packets = (num_loops - 1 + old_num_packets) - mNumBufferedPackets;
|
||||
if (num_dropped_packets > 0)
|
||||
{
|
||||
// It will eventually be accounted by mDroppedPackets
|
||||
// and mPacketsLost, but track it here for logging purposes.
|
||||
mNumDroppedPackets += num_dropped_packets;
|
||||
}
|
||||
return (S32)(mNumBufferedPackets);
|
||||
}
|
||||
|
||||
bool LLPacketRing::expandRing()
|
||||
{
|
||||
// compute larger size
|
||||
constexpr S16 BUFFER_RING_EXPANSION = 256;
|
||||
S16 old_size = (S16)(mPacketRing.size());
|
||||
S16 new_size = llmin(old_size + BUFFER_RING_EXPANSION, MAX_BUFFER_RING_SIZE);
|
||||
if (new_size == old_size)
|
||||
{
|
||||
// mPacketRing is already maxed out
|
||||
return false;
|
||||
}
|
||||
|
||||
// make a larger ring and copy packet pointers
|
||||
std::vector<LLPacketBuffer*> new_ring(new_size, nullptr);
|
||||
for (S16 i = 0; i < old_size; ++i)
|
||||
{
|
||||
S16 j = (mHeadIndex + i) % old_size;
|
||||
new_ring[i] = mPacketRing[j];
|
||||
}
|
||||
|
||||
// allocate new packets for the remainder of new_ring
|
||||
LLHost invalid_host;
|
||||
for (S16 i = old_size; i < new_size; ++i)
|
||||
{
|
||||
new_ring[i] = new LLPacketBuffer(invalid_host, nullptr, 0);
|
||||
}
|
||||
|
||||
// swap the rings and reset mHeadIndex
|
||||
mPacketRing.swap(new_ring);
|
||||
mHeadIndex = mNumBufferedPackets;
|
||||
return true;
|
||||
}
|
||||
|
||||
F32 LLPacketRing::getBufferLoadRate() const
|
||||
{
|
||||
// goes up to MAX_BUFFER_RING_SIZE
|
||||
return (F32)mNumBufferedPackets / (F32)DEFAULT_BUFFER_RING_SIZE;
|
||||
}
|
||||
|
||||
void LLPacketRing::dumpPacketRingStats()
|
||||
{
|
||||
mNumDroppedPacketsTotal += mNumDroppedPackets;
|
||||
LL_INFOS("Messaging") << "Packet ring stats: " << std::endl
|
||||
<< "Buffered packets: " << mNumBufferedPackets << std::endl
|
||||
<< "Buffered bytes: " << mNumBufferedBytes << std::endl
|
||||
<< "Dropped packets current: " << mNumDroppedPackets << std::endl
|
||||
<< "Dropped packets total: " << mNumDroppedPacketsTotal << std::endl
|
||||
<< "Dropped packets percentage: " << mDropPercentage << "%" << std::endl
|
||||
<< "Actual in bytes: " << mActualBytesIn << std::endl
|
||||
<< "Actual out bytes: " << mActualBytesOut << LL_ENDL;
|
||||
mNumDroppedPackets = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,16 +25,14 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLPACKETRING_H
|
||||
#define LL_LLPACKETRING_H
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "llhost.h"
|
||||
#include "llpacketbuffer.h"
|
||||
#include "llproxy.h"
|
||||
#include "llthrottle.h"
|
||||
#include "net.h"
|
||||
|
||||
|
||||
class LLPacketRing
|
||||
{
|
||||
|
|
@ -42,60 +40,71 @@ public:
|
|||
LLPacketRing();
|
||||
~LLPacketRing();
|
||||
|
||||
void cleanup();
|
||||
// receive one packet: either buffered or from the socket
|
||||
S32 receivePacket (S32 socket, char *datap);
|
||||
|
||||
// send one packet
|
||||
bool sendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
|
||||
|
||||
// drains packets from socket and returns final mNumBufferedPackets
|
||||
S32 drainSocket(S32 socket);
|
||||
|
||||
void dropPackets(U32);
|
||||
void setDropPercentage (F32 percent_to_drop);
|
||||
void setUseInThrottle(const bool use_throttle);
|
||||
void setUseOutThrottle(const bool use_throttle);
|
||||
void setInBandwidth(const F32 bps);
|
||||
void setOutBandwidth(const F32 bps);
|
||||
S32 receivePacket (S32 socket, char *datap);
|
||||
S32 receiveFromRing (S32 socket, char *datap);
|
||||
|
||||
bool sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host);
|
||||
inline LLHost getLastSender() const;
|
||||
inline LLHost getLastReceivingInterface() const;
|
||||
|
||||
inline LLHost getLastSender();
|
||||
inline LLHost getLastReceivingInterface();
|
||||
S32 getActualInBytes() const { return mActualBytesIn; }
|
||||
S32 getActualOutBytes() const { return mActualBytesOut; }
|
||||
S32 getAndResetActualInBits() { S32 bits = mActualBytesIn * 8; mActualBytesIn = 0; return bits;}
|
||||
S32 getAndResetActualOutBits() { S32 bits = mActualBytesOut * 8; mActualBytesOut = 0; return bits;}
|
||||
|
||||
S32 getAndResetActualInBits() { S32 bits = mActualBitsIn; mActualBitsIn = 0; return bits;}
|
||||
S32 getAndResetActualOutBits() { S32 bits = mActualBitsOut; mActualBitsOut = 0; return bits;}
|
||||
S32 getNumBufferedPackets() const { return (S32)(mNumBufferedPackets); }
|
||||
S32 getNumBufferedBytes() const { return mNumBufferedBytes; }
|
||||
S32 getNumDroppedPackets() const { return mNumDroppedPacketsTotal + mNumDroppedPackets; }
|
||||
|
||||
F32 getBufferLoadRate() const; // from 0 to 4 (0 - empty, 1 - default size is full)
|
||||
void dumpPacketRingStats();
|
||||
protected:
|
||||
bool mUseInThrottle;
|
||||
bool mUseOutThrottle;
|
||||
// returns 'true' if we should intentionally drop a packet
|
||||
bool computeDrop();
|
||||
|
||||
// For simulating a lower-bandwidth connection - BPS
|
||||
LLThrottle mInThrottle;
|
||||
LLThrottle mOutThrottle;
|
||||
// returns packet_size of received packet, zero or less if no packet found
|
||||
S32 receiveOrDropPacket(S32 socket, char *datap, bool drop);
|
||||
S32 receiveOrDropBufferedPacket(char *datap, bool drop);
|
||||
|
||||
S32 mActualBitsIn;
|
||||
S32 mActualBitsOut;
|
||||
S32 mMaxBufferLength; // How much data can we queue up before dropping data.
|
||||
S32 mInBufferLength; // Current incoming buffer length
|
||||
S32 mOutBufferLength; // Current outgoing buffer length
|
||||
// returns packet_size of packet buffered
|
||||
S32 bufferInboundPacket(S32 socket);
|
||||
|
||||
F32 mDropPercentage; // % of packets to drop
|
||||
U32 mPacketsToDrop; // drop next n packets
|
||||
// returns 'true' if ring was expanded
|
||||
bool expandRing();
|
||||
|
||||
std::queue<LLPacketBuffer *> mReceiveQueue;
|
||||
std::queue<LLPacketBuffer *> mSendQueue;
|
||||
protected:
|
||||
std::vector<LLPacketBuffer*> mPacketRing;
|
||||
S16 mHeadIndex { 0 };
|
||||
S16 mNumBufferedPackets { 0 };
|
||||
S32 mNumDroppedPackets { 0 };
|
||||
S32 mNumDroppedPacketsTotal { 0 };
|
||||
S32 mNumBufferedBytes { 0 };
|
||||
|
||||
S32 mActualBytesIn { 0 };
|
||||
S32 mActualBytesOut { 0 };
|
||||
F32 mDropPercentage { 0.0f }; // % of inbound packets to drop
|
||||
U32 mPacketsToDrop { 0 }; // drop next inbound n packets
|
||||
|
||||
// These are the sender and receiving_interface for the last packet delivered by receivePacket()
|
||||
LLHost mLastSender;
|
||||
LLHost mLastReceivingIF;
|
||||
|
||||
private:
|
||||
bool sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
|
||||
};
|
||||
|
||||
|
||||
inline LLHost LLPacketRing::getLastSender()
|
||||
inline LLHost LLPacketRing::getLastSender() const
|
||||
{
|
||||
return mLastSender;
|
||||
}
|
||||
|
||||
inline LLHost LLPacketRing::getLastReceivingInterface()
|
||||
inline LLHost LLPacketRing::getLastReceivingInterface() const
|
||||
{
|
||||
return mLastReceivingIF;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ void LLProxy::applyProxySettings(CURL* handle)
|
|||
/**
|
||||
* @brief Send one TCP packet and receive one in return.
|
||||
*
|
||||
* This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking
|
||||
* This operation is done synchronously with a 100ms timeout. Therefore, it should not be used when a blocking
|
||||
* operation would impact the operation of the viewer.
|
||||
*
|
||||
* @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP.
|
||||
|
|
@ -482,7 +482,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
|||
|
||||
apr_size_t expected_len = outlen;
|
||||
|
||||
handle->setBlocking(1000);
|
||||
handle->setBlocking(100000); // 100ms, 100000us. Should be sufficient for localhost, nearby network
|
||||
|
||||
rv = apr_socket_send(apr_socket, dataout, &outlen);
|
||||
if (APR_SUCCESS != rv)
|
||||
|
|
|
|||
|
|
@ -656,8 +656,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
|
|||
|
||||
// UseCircuitCode is allowed in even from an invalid circuit, so that
|
||||
// we can toss circuits around.
|
||||
if(
|
||||
valid_packet &&
|
||||
else if (
|
||||
!cdp &&
|
||||
(mTemplateMessageReader->getMessageName() !=
|
||||
_PREHASH_UseCircuitCode))
|
||||
|
|
@ -667,8 +666,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
|
|||
valid_packet = false;
|
||||
}
|
||||
|
||||
if(
|
||||
valid_packet &&
|
||||
if ( valid_packet &&
|
||||
cdp &&
|
||||
!cdp->getTrusted() &&
|
||||
mTemplateMessageReader->isTrusted())
|
||||
|
|
@ -680,7 +678,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
|
|||
valid_packet = false;
|
||||
}
|
||||
|
||||
if( valid_packet )
|
||||
if ( valid_packet )
|
||||
{
|
||||
logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 );
|
||||
valid_packet = mTemplateMessageReader->readMessage(buffer, host);
|
||||
|
|
@ -726,6 +724,7 @@ bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
|
|||
// Check to see if we need to print debug info
|
||||
if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
|
||||
{
|
||||
mPacketRing.dumpPacketRingStats();
|
||||
dumpCircuitInfo();
|
||||
mCircuitPrintTime = mt_sec;
|
||||
}
|
||||
|
|
@ -821,6 +820,11 @@ void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time)
|
|||
}
|
||||
}
|
||||
|
||||
S32 LLMessageSystem::drainUdpSocket()
|
||||
{
|
||||
return mPacketRing.drainSocket(mSocket);
|
||||
}
|
||||
|
||||
void LLMessageSystem::copyMessageReceivedToSend()
|
||||
{
|
||||
// NOTE: babbage: switch builder to match reader to avoid
|
||||
|
|
|
|||
|
|
@ -417,6 +417,9 @@ public:
|
|||
bool checkMessages(LockMessageChecker&, S64 frame_count = 0 );
|
||||
void processAcks(LockMessageChecker&, F32 collect_time = 0.f);
|
||||
|
||||
// returns total number of buffered packets after the drain
|
||||
S32 drainUdpSocket();
|
||||
|
||||
bool isMessageFast(const char *msg);
|
||||
bool isMessage(const char *msg)
|
||||
{
|
||||
|
|
@ -535,7 +538,6 @@ public:
|
|||
|
||||
//void buildMessage();
|
||||
|
||||
S32 zeroCode(U8 **data, S32 *data_size);
|
||||
S32 zeroCodeExpand(U8 **data, S32 *data_size);
|
||||
S32 zeroCodeAdjustCurrentSendTotal();
|
||||
|
||||
|
|
@ -752,6 +754,7 @@ public:
|
|||
S32 getReceiveBytes() const;
|
||||
|
||||
S32 getUnackedListSize() const { return mUnackedListSize; }
|
||||
F32 getBufferLoadRate() const { return mPacketRing.getBufferLoadRate(); }
|
||||
|
||||
//const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
|
||||
//const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
|
||||
|
|
@ -839,12 +842,10 @@ private:
|
|||
LLUUID mSessionID;
|
||||
|
||||
void addTemplate(LLMessageTemplate *templatep);
|
||||
bool decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
|
||||
|
||||
void logMsgFromInvalidCircuit( const LLHost& sender, bool recv_reliable );
|
||||
void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
|
||||
void logValidMsg(LLCircuitData *cdp, const LLHost& sender, bool recv_reliable, bool recv_resent, bool recv_acks );
|
||||
void logRanOffEndOfPacket( const LLHost& sender );
|
||||
|
||||
class LLMessageCountInfo
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,14 +76,8 @@ static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which dat
|
|||
const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
|
||||
const char* BROADCAST_ADDRESS_STRING = "255.255.255.255";
|
||||
|
||||
#if LL_DARWIN
|
||||
// macOS returns an error when trying to set these to 400000. Smaller values succeed.
|
||||
const int SEND_BUFFER_SIZE = 200000;
|
||||
const int RECEIVE_BUFFER_SIZE = 200000;
|
||||
#else // LL_DARWIN
|
||||
const int SEND_BUFFER_SIZE = 400000;
|
||||
const int RECEIVE_BUFFER_SIZE = 400000;
|
||||
#endif // LL_DARWIN
|
||||
const int SEND_BUFFER_SIZE = 200000;
|
||||
const int RECEIVE_BUFFER_SIZE = 800000;
|
||||
|
||||
// universal functions (cross-platform)
|
||||
|
||||
|
|
|
|||
|
|
@ -400,9 +400,14 @@ void LLPluginProcessParent::idle(void)
|
|||
apr_sockaddr_t* addr = NULL;
|
||||
mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
|
||||
mBoundPort = 0;
|
||||
if (!mListenSocket)
|
||||
{
|
||||
killSockets();
|
||||
errorState();
|
||||
break;
|
||||
}
|
||||
|
||||
// This code is based on parts of LLSocket::create() in lliosocket.cpp.
|
||||
|
||||
status = apr_sockaddr_info_get(
|
||||
&addr,
|
||||
"127.0.0.1",
|
||||
|
|
|
|||
|
|
@ -105,6 +105,36 @@ LLCubeMapArray::LLCubeMapArray()
|
|||
|
||||
}
|
||||
|
||||
LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0)
|
||||
{
|
||||
mWidth = width;
|
||||
mCount = count;
|
||||
|
||||
// Allocate a new cubemap array with the same criteria as the incoming cubemap array
|
||||
allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR);
|
||||
|
||||
// Copy each cubemap from the incoming array to the new array
|
||||
U32 min_count = std::min(count, lhs.mCount);
|
||||
for (U32 i = 0; i < min_count * 6; ++i)
|
||||
{
|
||||
U32 src_resolution = lhs.mWidth;
|
||||
U32 dst_resolution = mWidth;
|
||||
{
|
||||
GLint components = GL_RGB;
|
||||
if (mImage->getComponents() == 4)
|
||||
components = GL_RGBA;
|
||||
GLint format = GL_RGB;
|
||||
|
||||
// Handle different resolutions by scaling the image
|
||||
LLPointer<LLImageRaw> src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents());
|
||||
glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData());
|
||||
|
||||
LLPointer<LLImageRaw> scaled_image = src_image->scaled(mWidth, mWidth);
|
||||
glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLCubeMapArray::~LLCubeMapArray()
|
||||
{
|
||||
}
|
||||
|
|
@ -115,6 +145,8 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us
|
|||
mWidth = resolution;
|
||||
mCount = count;
|
||||
|
||||
mHDR = hdr;
|
||||
|
||||
LLImageGL::generateTextures(1, &texname);
|
||||
|
||||
mImage = new LLImageGL(resolution, resolution, components, use_mips);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class LLCubeMapArray : public LLRefCount
|
|||
{
|
||||
public:
|
||||
LLCubeMapArray();
|
||||
LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count);
|
||||
|
||||
static GLenum sTargets[6];
|
||||
|
||||
|
|
@ -73,4 +74,5 @@ protected:
|
|||
U32 mWidth = 0;
|
||||
U32 mCount = 0;
|
||||
S32 mTextureStage;
|
||||
bool mHDR;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -725,11 +725,11 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
|
|||
|| FT_Err_Invalid_Composite == error
|
||||
|| (FT_Err_Ok != error && LLStringOps::isEmoji(wch)))
|
||||
{
|
||||
glyph_index = FT_Get_Char_Index(mFTFace, '?');
|
||||
// if '?' is not present, potentially can use last index, that's supposed to be null glyph
|
||||
if (glyph_index > 0)
|
||||
// value~0 always corresponds to the 'missing glyph'
|
||||
error = FT_Load_Glyph(mFTFace, 0, FT_LOAD_FORCE_AUTOHINT);
|
||||
if (FT_Err_Ok != error)
|
||||
{
|
||||
error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR);
|
||||
LL_ERRS() << "Loading fallback for char '" << (U32)wch << "', glyph " << glyph_index << " failed with error : " << (S32)error << LL_ENDL;
|
||||
}
|
||||
}
|
||||
llassert_always_msg(FT_Err_Ok == error, message.c_str());
|
||||
|
|
|
|||
|
|
@ -2458,12 +2458,15 @@ void LLGLState::checkStates(GLboolean writeAlpha)
|
|||
return;
|
||||
}
|
||||
|
||||
GLint src;
|
||||
GLint dst;
|
||||
glGetIntegerv(GL_BLEND_SRC, &src);
|
||||
glGetIntegerv(GL_BLEND_DST, &dst);
|
||||
llassert_always(src == GL_SRC_ALPHA);
|
||||
llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLint srcRGB, dstRGB, srcAlpha, dstAlpha;
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB);
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB);
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcAlpha);
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &dstAlpha);
|
||||
llassert_always(srcRGB == GL_SRC_ALPHA);
|
||||
llassert_always(srcAlpha == GL_SRC_ALPHA);
|
||||
llassert_always(dstRGB == GL_ONE_MINUS_SRC_ALPHA);
|
||||
llassert_always(dstAlpha == GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// disable for now until usage is consistent
|
||||
//GLboolean colorMask[4];
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ void LLButton::draw()
|
|||
|
||||
// Highlight if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
label_color = ll::ui::SearchableControl::getHighlightColor();
|
||||
label_color = ll::ui::SearchableControl::getHighlightFontColor();
|
||||
|
||||
// overlay with keyboard focus border
|
||||
if (hasFocus())
|
||||
|
|
|
|||
|
|
@ -170,12 +170,14 @@ bool LLCommandManager::load()
|
|||
|
||||
if (!parser.readXUI(commands_file, commandsParams))
|
||||
{
|
||||
LLError::LLUserWarningMsg::showMissingFiles();
|
||||
LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!commandsParams.validateBlock())
|
||||
{
|
||||
LLError::LLUserWarningMsg::showMissingFiles();
|
||||
LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "../newview/llviewerprecompiledheaders.h"
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llflashtimer.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ void LLMenuItemGL::draw( void )
|
|||
|
||||
// Highlight if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
color = ll::ui::SearchableControl::getHighlightColor();
|
||||
color = ll::ui::SearchableControl::getHighlightFontColor();
|
||||
|
||||
// Draw the text on top.
|
||||
if (mBriefItem)
|
||||
|
|
|
|||
|
|
@ -614,6 +614,13 @@ void LLNotification::cancel()
|
|||
LLSD LLNotification::getResponseTemplate(EResponseTemplateType type)
|
||||
{
|
||||
LLSD response = LLSD::emptyMap();
|
||||
|
||||
if (!mForm)
|
||||
{
|
||||
LL_WARNS("Notifications") << "Null form when getting response template for notification " << getName() << LL_ENDL;
|
||||
return response;
|
||||
}
|
||||
|
||||
for (S32 element_idx = 0;
|
||||
element_idx < mForm->getNumElements();
|
||||
++element_idx)
|
||||
|
|
@ -1249,9 +1256,26 @@ LLNotifications::LLNotifications()
|
|||
LLInstanceTracker<LLNotificationChannel, std::string>::instanceCount();
|
||||
}
|
||||
|
||||
|
||||
LLNotifications::~LLNotifications()
|
||||
{
|
||||
// Clear explicitly, something in ~LLNotifications() crashes so narrowing down suspects
|
||||
pHistoryChannel = nullptr;
|
||||
pExpirationChannel = nullptr;
|
||||
mGlobalStrings.clear();
|
||||
mTemplates.clear();
|
||||
mVisibilityRules.clear();
|
||||
mUniqueNotifications.clear();
|
||||
mListener = nullptr;
|
||||
}
|
||||
|
||||
void LLNotifications::clear()
|
||||
{
|
||||
mDefaultChannels.clear();
|
||||
mDefaultChannels.clear();
|
||||
// At this point mTemplates still gets used by lingering notifications
|
||||
// to do responses (ex: group notice will call forceResponse()), but
|
||||
// since network should be down and everything save, it's questionable
|
||||
// whether it should stay that way
|
||||
}
|
||||
|
||||
// The expiration channel gets all notifications that are cancelled
|
||||
|
|
@ -1464,6 +1488,13 @@ bool LLNotifications::templateExists(std::string_view name)
|
|||
void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option)
|
||||
{
|
||||
LLNotificationPtr temp_notify(new LLNotification(params));
|
||||
|
||||
if (!temp_notify->getForm())
|
||||
{
|
||||
LL_WARNS("Notifications") << "Cannot force response for notification with null form: " << (std::string)params.name << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD response = temp_notify->getResponseTemplate();
|
||||
LLSD selected_item = temp_notify->getForm()->getElement(option);
|
||||
|
||||
|
|
|
|||
|
|
@ -887,7 +887,7 @@ class LLNotifications :
|
|||
{
|
||||
LLSINGLETON(LLNotifications);
|
||||
LOG_CLASS(LLNotifications);
|
||||
virtual ~LLNotifications() {}
|
||||
virtual ~LLNotifications();
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -3394,7 +3394,7 @@ bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str)
|
|||
|
||||
bool res = false;
|
||||
|
||||
setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red));
|
||||
setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4));
|
||||
|
||||
std::string filter_str_lc(filter_str);
|
||||
LLStringUtil::toLower(filter_str_lc);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,15 @@ namespace ll
|
|||
virtual ~SearchableControl()
|
||||
{ }
|
||||
|
||||
const LLColor4& getHighlightColor( ) const
|
||||
const LLColor4& getHighlightBgColor( ) const
|
||||
{
|
||||
static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red);
|
||||
static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4);
|
||||
return highlight_color.get();
|
||||
}
|
||||
|
||||
const LLColor4& getHighlightFontColor() const
|
||||
{
|
||||
static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightFontColor", LLColor4::red4);
|
||||
return highlight_color.get();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1378,7 +1378,7 @@ void LLTextBase::draw()
|
|||
// Draw highlighted if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
{
|
||||
const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightColor();
|
||||
const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightBgColor();
|
||||
LLRect bg_rect = mVisibleTextRect;
|
||||
if( mScroller )
|
||||
bg_rect.intersectWith( text_rect );
|
||||
|
|
|
|||
|
|
@ -76,6 +76,12 @@ protected:
|
|||
LLUIString mText;
|
||||
callback_t mClickedCallback;
|
||||
bool mShowCursorHand;
|
||||
|
||||
protected:
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
return LLTextBase::_getSearchText() + mText.getString();
|
||||
}
|
||||
};
|
||||
|
||||
// Build time optimization, generate once in .cpp file
|
||||
|
|
|
|||
|
|
@ -209,8 +209,15 @@ public:
|
|||
}
|
||||
virtual bool execute( LLTextBase* editor, S32* delta )
|
||||
{
|
||||
mWString = editor->getWText().substr(getPosition(), mLen);
|
||||
*delta = remove(editor, getPosition(), mLen );
|
||||
try
|
||||
{
|
||||
mWString = editor->getWText().substr(getPosition(), mLen);
|
||||
*delta = remove(editor, getPosition(), mLen);
|
||||
}
|
||||
catch (std::out_of_range&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (*delta != 0);
|
||||
}
|
||||
virtual S32 undo( LLTextBase* editor )
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
#include "llrect.h"
|
||||
#include "llcoord.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llcoord.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llinitparam.h"
|
||||
#include "llregistry.h"
|
||||
#include "llrender2dutils.h"
|
||||
|
|
|
|||
|
|
@ -279,6 +279,10 @@ void callResetKeys()
|
|||
|
||||
bool callUnicodeCallback(wchar_t character, unsigned int mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NativeKeyEventData eventData;
|
||||
|
||||
memset(&eventData, 0, sizeof(NativeKeyEventData));
|
||||
|
|
@ -300,7 +304,7 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask)
|
|||
|
||||
void callFocus()
|
||||
{
|
||||
if (gWindowImplementation)
|
||||
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
||||
{
|
||||
gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
|
||||
}
|
||||
|
|
@ -308,7 +312,7 @@ void callFocus()
|
|||
|
||||
void callFocusLost()
|
||||
{
|
||||
if (gWindowImplementation)
|
||||
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
||||
{
|
||||
gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
|
||||
}
|
||||
|
|
@ -316,6 +320,10 @@ void callFocusLost()
|
|||
|
||||
void callRightMouseDown(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (gWindowImplementation->allowsLanguageInput())
|
||||
{
|
||||
gWindowImplementation->interruptLanguageTextInput();
|
||||
|
|
@ -329,6 +337,10 @@ void callRightMouseDown(float *pos, MASK mask)
|
|||
|
||||
void callRightMouseUp(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (gWindowImplementation->allowsLanguageInput())
|
||||
{
|
||||
gWindowImplementation->interruptLanguageTextInput();
|
||||
|
|
@ -342,6 +354,10 @@ void callRightMouseUp(float *pos, MASK mask)
|
|||
|
||||
void callLeftMouseDown(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (gWindowImplementation->allowsLanguageInput())
|
||||
{
|
||||
gWindowImplementation->interruptLanguageTextInput();
|
||||
|
|
@ -355,6 +371,10 @@ void callLeftMouseDown(float *pos, MASK mask)
|
|||
|
||||
void callLeftMouseUp(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (gWindowImplementation->allowsLanguageInput())
|
||||
{
|
||||
gWindowImplementation->interruptLanguageTextInput();
|
||||
|
|
@ -369,6 +389,10 @@ void callLeftMouseUp(float *pos, MASK mask)
|
|||
|
||||
void callDoubleClick(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (gWindowImplementation->allowsLanguageInput())
|
||||
{
|
||||
gWindowImplementation->interruptLanguageTextInput();
|
||||
|
|
@ -382,7 +406,7 @@ void callDoubleClick(float *pos, MASK mask)
|
|||
|
||||
void callResize(unsigned int width, unsigned int height)
|
||||
{
|
||||
if (gWindowImplementation != NULL)
|
||||
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
||||
{
|
||||
gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height);
|
||||
}
|
||||
|
|
@ -390,6 +414,10 @@ void callResize(unsigned int width, unsigned int height)
|
|||
|
||||
void callMouseMoved(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLCoordGL outCoords;
|
||||
outCoords.mX = ll_round(pos[0]);
|
||||
outCoords.mY = ll_round(pos[1]);
|
||||
|
|
@ -403,6 +431,10 @@ void callMouseMoved(float *pos, MASK mask)
|
|||
|
||||
void callMouseDragged(float *pos, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLCoordGL outCoords;
|
||||
outCoords.mX = ll_round(pos[0]);
|
||||
outCoords.mY = ll_round(pos[1]);
|
||||
|
|
@ -424,6 +456,10 @@ void callScrollMoved(float deltaX, float deltaY)
|
|||
|
||||
void callMouseExit()
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation);
|
||||
}
|
||||
|
||||
|
|
@ -475,11 +511,19 @@ void callWindowDidChangeScreen()
|
|||
|
||||
void callDeltaUpdate(float *delta, MASK mask)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->updateMouseDeltas(delta);
|
||||
}
|
||||
|
||||
void callOtherMouseDown(float *pos, MASK mask, int button)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLCoordGL outCoords;
|
||||
outCoords.mX = ll_round(pos[0]);
|
||||
outCoords.mY = ll_round(pos[1]);
|
||||
|
|
@ -500,6 +544,10 @@ void callOtherMouseDown(float *pos, MASK mask, int button)
|
|||
|
||||
void callOtherMouseUp(float *pos, MASK mask, int button)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLCoordGL outCoords;
|
||||
outCoords.mX = ll_round(pos[0]);
|
||||
outCoords.mY = ll_round(pos[1]);
|
||||
|
|
@ -524,27 +572,43 @@ void callModifier(MASK mask)
|
|||
|
||||
void callHandleDragEntered(std::string url)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
|
||||
}
|
||||
|
||||
void callHandleDragExited(std::string url)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
|
||||
}
|
||||
|
||||
void callHandleDragUpdated(std::string url)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
|
||||
}
|
||||
|
||||
void callHandleDragDropped(std::string url)
|
||||
{
|
||||
if (!gWindowImplementation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
|
||||
}
|
||||
|
||||
void callQuitHandler()
|
||||
{
|
||||
if (gWindowImplementation)
|
||||
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
||||
{
|
||||
if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
|
||||
{
|
||||
|
|
@ -555,7 +619,7 @@ void callQuitHandler()
|
|||
|
||||
void getPreeditSelectionRange(int *position, int *length)
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
gWindowImplementation->getPreeditor()->getSelectionRange(position, length);
|
||||
}
|
||||
|
|
@ -563,7 +627,7 @@ void getPreeditSelectionRange(int *position, int *length)
|
|||
|
||||
void getPreeditMarkedRange(int *position, int *length)
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
gWindowImplementation->getPreeditor()->getPreeditRange(position, length);
|
||||
}
|
||||
|
|
@ -571,7 +635,7 @@ void getPreeditMarkedRange(int *position, int *length)
|
|||
|
||||
void setPreeditMarkedRange(int position, int length)
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
gWindowImplementation->getPreeditor()->markAsPreedit(position, length);
|
||||
}
|
||||
|
|
@ -580,7 +644,7 @@ void setPreeditMarkedRange(int position, int length)
|
|||
bool handleUnicodeCharacter(wchar_t c)
|
||||
{
|
||||
bool success = false;
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c);
|
||||
}
|
||||
|
|
@ -590,7 +654,7 @@ bool handleUnicodeCharacter(wchar_t c)
|
|||
|
||||
void resetPreedit()
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
gWindowImplementation->getPreeditor()->resetPreedit();
|
||||
}
|
||||
|
|
@ -600,7 +664,7 @@ void resetPreedit()
|
|||
// This largely mirrors the old implementation, only sans the carbon parameters.
|
||||
void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments)
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
|
||||
preeditor->resetPreedit();
|
||||
|
|
@ -623,7 +687,7 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne
|
|||
|
||||
void getPreeditLocation(float *location, unsigned int length)
|
||||
{
|
||||
if (gWindowImplementation->getPreeditor())
|
||||
if (gWindowImplementation && gWindowImplementation->getPreeditor())
|
||||
{
|
||||
LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
|
||||
LLCoordGL coord;
|
||||
|
|
|
|||
|
|
@ -4055,7 +4055,15 @@ void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
|
|||
break;
|
||||
}
|
||||
|
||||
logfont->lfHeight = mPreeditor->getPreeditFontSize();
|
||||
if (mPreeditor)
|
||||
{
|
||||
logfont->lfHeight = mPreeditor->getPreeditFontSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: extract from some font * LLUI::getScaleFactor() intead
|
||||
logfont->lfHeight = 10;
|
||||
}
|
||||
logfont->lfWeight = FW_NORMAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ void LLXMLNode::addChild(LLXMLNodePtr& new_child)
|
|||
// virtual
|
||||
LLXMLNodePtr LLXMLNode::createChild(const char* name, bool is_attribute)
|
||||
{
|
||||
// Todo: validate to make sure node name is valid? (no spaces, etc)
|
||||
return createChild(gStringTable.addStringEntry(name), is_attribute);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,12 +108,15 @@ LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LL
|
|||
|
||||
LLXmlTreeNode::~LLXmlTreeNode()
|
||||
{
|
||||
attribute_map_t::iterator iter;
|
||||
for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
|
||||
delete iter->second;
|
||||
for(LLXmlTreeNode* node : mChildren)
|
||||
for (auto& attr : mAttributes)
|
||||
{
|
||||
delete node;
|
||||
delete attr.second;
|
||||
}
|
||||
mAttributes.clear();
|
||||
|
||||
for (auto& child : mChildren)
|
||||
{
|
||||
delete child;
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloatersettingscolor.cpp
|
||||
llfloatersettingsdebug.cpp
|
||||
llfloatersidepanelcontainer.cpp
|
||||
llfloaterslapptest.cpp
|
||||
llfloatersnapshot.cpp
|
||||
llfloatersounddevices.cpp
|
||||
llfloaterspellchecksettings.cpp
|
||||
|
|
@ -963,6 +964,7 @@ set(viewer_HEADER_FILES
|
|||
llfloatersettingscolor.h
|
||||
llfloatersettingsdebug.h
|
||||
llfloatersidepanelcontainer.h
|
||||
llfloaterslapptest.h
|
||||
llfloatersnapshot.h
|
||||
llfloatersounddevices.h
|
||||
llfloaterspellchecksettings.h
|
||||
|
|
@ -1419,11 +1421,24 @@ if (DARWIN)
|
|||
LIST(APPEND viewer_SOURCE_FILES llfilepicker_mac.mm)
|
||||
LIST(APPEND viewer_HEADER_FILES llfilepicker_mac.h)
|
||||
|
||||
set_source_files_properties(
|
||||
llappviewermacosx-objc.mm
|
||||
PROPERTIES
|
||||
SKIP_PRECOMPILE_HEADERS TRUE
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
llfilepicker_mac.mm
|
||||
PROPERTIES
|
||||
SKIP_PRECOMPILE_HEADERS TRUE
|
||||
)
|
||||
|
||||
# This should be compiled with the viewer.
|
||||
LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm)
|
||||
set_source_files_properties(
|
||||
llappdelegate-objc.mm
|
||||
PROPERTIES
|
||||
SKIP_PRECOMPILE_HEADERS TRUE
|
||||
COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
|
||||
# BugsplatMac is a module, imported with @import. That language feature
|
||||
# demands these -f switches.
|
||||
|
|
@ -1707,6 +1722,10 @@ list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST})
|
|||
set(PACKAGE ON CACHE BOOL
|
||||
"Add a package target that builds an installer package.")
|
||||
|
||||
if(USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers( ${VIEWER_BINARY_NAME} PRIVATE llviewerprecompiledheaders.h )
|
||||
endif(USE_PRECOMPILED_HEADERS)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(${VIEWER_BINARY_NAME}
|
||||
PROPERTIES
|
||||
|
|
@ -1717,10 +1736,6 @@ if (WINDOWS)
|
|||
)
|
||||
target_compile_options(${VIEWER_BINARY_NAME} PRIVATE /bigobj)
|
||||
|
||||
if(USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers( ${VIEWER_BINARY_NAME} PRIVATE llviewerprecompiledheaders.h )
|
||||
endif(USE_PRECOMPILED_HEADERS)
|
||||
|
||||
# If adding a file to viewer_manifest.py in the WindowsManifest.construct() method, be sure to add the dependency
|
||||
# here.
|
||||
# *NOTE:Mani - This is a crappy hack to have important dependencies for the viewer_manifest copy action
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
7.1.12
|
||||
7.1.13
|
||||
|
|
|
|||
|
|
@ -3687,6 +3687,17 @@
|
|||
<key>Value</key>
|
||||
<integer>5000</integer>
|
||||
</map>
|
||||
<key>InventoryExposeFolderID</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Allows copying folder id from context menu</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MarketplaceListingsSortOrder</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -7805,6 +7816,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderTextureVRAMDivisor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Divisor for maximum amount of VRAM the viewer will use for textures. 1 = all the VRAM. Used in conjunction with RenderMaxVRAMBudget.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderMinFreeMainMemoryThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -9076,6 +9098,28 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderReflectionProbeDynamicAllocation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable dynamic allocation of reflection probes. -1 means no dynamic allocation. Sets a buffer to allocate when a dynamic allocation occurs otherwise.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>RenderReflectionProbeCount</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Number of probes to render. Maximum of 256. Clamps to the nearest power of 2.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>256</integer>
|
||||
</map>
|
||||
<key>RenderReflectionProbeResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -11629,7 +11673,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.04</real>
|
||||
<real>0.0095</real>
|
||||
</map>
|
||||
<key>TextureScaleMaxAreaFactor</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -80,6 +80,18 @@ vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
|
|||
|
||||
vec4 decodeNormal(vec4 norm);
|
||||
|
||||
vec3 clampHDRRange(vec3 color)
|
||||
{
|
||||
// Why do this?
|
||||
// There are situations where the color range will go to something insane - potentially producing infs and NaNs even.
|
||||
// This is a safety measure to prevent that.
|
||||
// As to the specific number there - allegedly some HDR displays expect values to be in the 0-11.2 range. Citation needed.
|
||||
// -Geenz 2025-03-05
|
||||
color = mix(color, vec3(1), isinf(color));
|
||||
color = mix(color, vec3(0.0), isnan(color));
|
||||
return clamp(color, vec3(0.0), vec3(11.2));
|
||||
}
|
||||
|
||||
float calcLegacyDistanceAttenuation(float distance, float falloff)
|
||||
{
|
||||
float dist_atten = 1.0 - clamp((distance + falloff)/(1.0 + falloff), 0.0, 1.0);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc)
|
|||
w += wg;
|
||||
}
|
||||
|
||||
vec3 clampHDRRange(vec3 color);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy;
|
||||
|
|
@ -120,5 +122,6 @@ void main()
|
|||
diff /= w;
|
||||
}
|
||||
|
||||
diff.rgb = clampHDRRange(diff.rgb);
|
||||
frag_color = diff;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ vec3 legacyGamma(vec3 color)
|
|||
return c;
|
||||
}
|
||||
|
||||
vec3 clampHDRRange(vec3 color);
|
||||
|
||||
void main()
|
||||
{
|
||||
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
|
||||
|
|
@ -53,6 +55,7 @@ void main()
|
|||
diff.rgb = legacyGamma(diff.rgb);
|
||||
#endif
|
||||
|
||||
frag_color = max(diff, vec4(0));
|
||||
diff.rgb = clampHDRRange(diff.rgb);
|
||||
frag_color = diff;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ float noise(vec2 x) {
|
|||
|
||||
//=============================
|
||||
|
||||
vec3 clampHDRRange(vec3 color);
|
||||
|
||||
|
||||
void main()
|
||||
|
|
@ -84,6 +85,7 @@ void main()
|
|||
diff.rgb += nz*0.003;
|
||||
#endif
|
||||
|
||||
diff.rgb = clampHDRRange(diff.rgb);
|
||||
frag_color = diff;
|
||||
|
||||
gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ in vec2 vary_fragcoord;
|
|||
vec3 linear_to_srgb(vec3 cl);
|
||||
vec3 toneMap(vec3 color);
|
||||
|
||||
vec3 clampHDRRange(vec3 color);
|
||||
|
||||
void main()
|
||||
{
|
||||
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
|
||||
|
|
@ -45,6 +47,7 @@ void main()
|
|||
diff.rgb = clamp(diff.rgb, vec3(0.0), vec3(1.0));
|
||||
#endif
|
||||
|
||||
diff.rgb = clampHDRRange(diff.rgb);
|
||||
//debugExposure(diff.rgb);
|
||||
frag_color = max(diff, vec4(0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, ou
|
|||
if (classic_mode < 1)
|
||||
{
|
||||
amblit = srgb_to_linear(amblit);
|
||||
amblit = vec3(dot(amblit, vec3(0.2126, 0.7152, 0.0722)));
|
||||
sunlit = srgb_to_linear(sunlit);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ vec3 pbrBaseLight(vec3 diffuseColor,
|
|||
vec3 atten);
|
||||
|
||||
GBufferInfo getGBuffer(vec2 screenpos);
|
||||
vec3 clampHDRRange(vec3 color);
|
||||
|
||||
void adjustIrradiance(inout vec3 irradiance, float ambocc)
|
||||
{
|
||||
|
|
@ -278,6 +279,7 @@ void main()
|
|||
float final_scale = 1;
|
||||
if (classic_mode > 0)
|
||||
final_scale = 1.1;
|
||||
frag_color.rgb = max(color.rgb * final_scale, vec3(0)); //output linear since local lights will be added to this shader's results
|
||||
|
||||
frag_color.rgb = clampHDRRange(color.rgb * final_scale); //output linear since local lights will be added to this shader's results
|
||||
frag_color.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,7 +263,12 @@ void main()
|
|||
vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0));
|
||||
|
||||
// Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect".
|
||||
fade = max(0,min(1, (pos.z - refPos.z) / 10)) * water_mask;
|
||||
#ifdef SHORELINE_FADE
|
||||
fade = max(0,min(1, (pos.z - refPos.z) / 10));
|
||||
#else
|
||||
fade = 1;
|
||||
#endif
|
||||
fade *= water_mask;
|
||||
distort2 = mix(distort, distort2, min(1, fade * 10));
|
||||
depth = texture(depthMap, distort2).r;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version 73
|
||||
version 74
|
||||
// The version number above should be incremented IF AND ONLY IF some
|
||||
// change has been made that is sufficiently important to justify
|
||||
// resetting the graphics preferences of all users to the recommended
|
||||
|
|
@ -86,6 +86,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 1
|
||||
RenderDisableVintageMode 1 1
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Low Graphics Settings
|
||||
|
|
@ -128,6 +129,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 512
|
||||
RenderReflectionProbeCount 1 1
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -170,6 +172,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 1024
|
||||
RenderReflectionProbeCount 1 32
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -211,6 +214,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 64
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -241,7 +245,7 @@ RenderFSAASamples 1 1
|
|||
RenderReflectionsEnabled 1 1
|
||||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 2
|
||||
RenderReflectionProbeLevel 1 1
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
|
|
@ -252,6 +256,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 64
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -282,7 +287,7 @@ RenderFSAASamples 1 2
|
|||
RenderReflectionsEnabled 1 1
|
||||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderReflectionProbeLevel 1 2
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 8
|
||||
|
|
@ -293,6 +298,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 128
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
|
||||
|
|
@ -334,6 +340,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -375,6 +382,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -408,6 +416,7 @@ RenderReflectionProbeDetail 0 -1
|
|||
RenderMirrors 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 0 0
|
||||
|
||||
list Intel
|
||||
RenderAnisotropic 1 0
|
||||
|
|
@ -429,6 +438,7 @@ RenderMirrors 0 0
|
|||
RenderGLMultiThreadedTextures 0 0
|
||||
RenderGLMultiThreadedMedia 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderReflectionProbeCount 0 0
|
||||
|
||||
list TexUnit16orLess
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version 72
|
||||
version 73
|
||||
// The version number above should be incremented IF AND ONLY IF some
|
||||
// change has been made that is sufficiently important to justify
|
||||
// resetting the graphics preferences of all users to the recommended
|
||||
|
|
@ -86,6 +86,7 @@ RenderTonemapMix 1 1
|
|||
RenderDisableVintageMode 1 1
|
||||
RenderDownScaleMethod 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Low Graphics Settings
|
||||
|
|
@ -128,6 +129,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 512
|
||||
RenderReflectionProbeCount 1 1
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -170,6 +172,7 @@ RenderTonemapType 1 1
|
|||
RenderTonemapMix 1 0.7
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 1024
|
||||
RenderReflectionProbeCount 1 32
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -211,6 +214,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 64
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -252,6 +256,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 64
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -293,6 +298,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 128
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (SSAO + all shadows)
|
||||
|
|
@ -334,6 +340,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -375,6 +382,7 @@ RenderExposure 1 1
|
|||
RenderTonemapType 1 1
|
||||
RenderTonemapMix 1 0.7
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 1 256
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -407,6 +415,7 @@ RenderShadowDetail 0 0
|
|||
RenderMirrors 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderMaxTextureResolution 1 2048
|
||||
RenderReflectionProbeCount 0 0
|
||||
|
||||
list TexUnit8orLess
|
||||
RenderDeferredSSAO 0 0
|
||||
|
|
@ -447,6 +456,7 @@ RenderReflectionProbeDetail 0 0
|
|||
RenderReflectionsEnabled 0 0
|
||||
RenderMirrors 0 0
|
||||
RenderDisableVintageMode 1 0
|
||||
RenderReflectionProbeCount 0 0
|
||||
|
||||
list VaryingVectors16orLess
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
|
||||
#include "glm/vec2.hpp"
|
||||
#include "glm/vec3.hpp"
|
||||
#include "glm/vec4.hpp"
|
||||
|
|
|
|||
|
|
@ -69,9 +69,16 @@ void GLTFSceneManager::load()
|
|||
{
|
||||
return;
|
||||
}
|
||||
if (filenames.size() > 0)
|
||||
try
|
||||
{
|
||||
GLTFSceneManager::instance().load(filenames[0]);
|
||||
if (filenames.size() > 0)
|
||||
{
|
||||
GLTFSceneManager::instance().load(filenames[0]);
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLNotificationsUtil::add("CannotOpenFileTooBig");
|
||||
}
|
||||
},
|
||||
LLFilePicker::FFLOAD_GLTF,
|
||||
|
|
|
|||
|
|
@ -2466,7 +2466,10 @@ void LLAgent::endAnimationUpdateUI()
|
|||
gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
|
||||
}
|
||||
|
||||
gFloaterTools->dirty();
|
||||
if (gFloaterTools)
|
||||
{
|
||||
gFloaterTools->dirty();
|
||||
}
|
||||
|
||||
// Don't let this be called more than once if the camera
|
||||
// mode hasn't changed. --JC
|
||||
|
|
@ -4278,9 +4281,14 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
|
|||
|
||||
void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id)
|
||||
{
|
||||
bool is_local(false);
|
||||
LLViewerRegion* regionp = getRegion();
|
||||
LLViewerRegion* regionp = getRegion();
|
||||
if (!regionp)
|
||||
{
|
||||
LL_WARNS("Teleport") << "called when agent region is null" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_local(false);
|
||||
if (LLLandmark* landmark = gLandmarkList.getAsset(landmark_asset_id, NULL))
|
||||
{
|
||||
LLVector3d pos_global;
|
||||
|
|
|
|||
|
|
@ -1385,8 +1385,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth)
|
|||
&& curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN
|
||||
&& version > curr_cat->getVersion())
|
||||
{
|
||||
// Potentially should new_cat->setVersion(unknown) here,
|
||||
// but might be waiting for a callback that would increment
|
||||
LL_DEBUGS("Inventory") << "Category " << category_id
|
||||
<< " is stale. Known version: " << curr_cat->getVersion()
|
||||
<< " server version: " << version << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -301,7 +301,8 @@ struct AttachmentInfo
|
|||
AttachmentInfo(metadata.logFilePathname, "text/plain"),
|
||||
AttachmentInfo(metadata.userSettingsPathname, "text/xml"),
|
||||
AttachmentInfo(metadata.accountSettingsPathname, "text/xml"),
|
||||
AttachmentInfo(metadata.staticDebugPathname, "text/xml")
|
||||
AttachmentInfo(metadata.staticDebugPathname, "text/xml"),
|
||||
AttachmentInfo(metadata.attributesPathname, "text/xml")
|
||||
};
|
||||
|
||||
secondLogPath = metadata.secondLogFilePathname;
|
||||
|
|
|
|||
|
|
@ -4725,48 +4725,64 @@ void wear_multiple(const uuid_vec_t& ids, bool replace)
|
|||
LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb);
|
||||
}
|
||||
|
||||
// SLapp for easy-wearing of a stock (library) avatar
|
||||
//
|
||||
bool wear_category(const LLSD& query_map, bool append)
|
||||
{
|
||||
LLUUID folder_uuid;
|
||||
|
||||
if (query_map.has("folder_name"))
|
||||
{
|
||||
std::string outfit_folder_name = query_map["folder_name"];
|
||||
folder_uuid = findDescendentCategoryIDByName(gInventory.getLibraryRootFolderID(), outfit_folder_name);
|
||||
if (folder_uuid.isNull())
|
||||
LL_WARNS() << "Couldn't find " << std::quoted(outfit_folder_name) << " in the Library" << LL_ENDL;
|
||||
}
|
||||
if (folder_uuid.isNull() && query_map.has("folder_id"))
|
||||
{
|
||||
folder_uuid = query_map["folder_id"].asUUID();
|
||||
}
|
||||
|
||||
if (folder_uuid.notNull())
|
||||
{
|
||||
if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_uuid))
|
||||
{
|
||||
if (bool is_library = gInventory.isObjectDescendentOf(folder_uuid, gInventory.getRootFolderID()))
|
||||
{
|
||||
LLPointer<LLInventoryCategory> new_category = new LLInventoryCategory(folder_uuid, LLUUID::null, LLFolderType::FT_CLOTHING, "Quick Appearance");
|
||||
LLAppearanceMgr::getInstance()->wearInventoryCategory(new_category, true, append);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLAppearanceMgr::getInstance()->wearInventoryCategory(cat, true, append);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Couldn't find folder id" << folder_uuid << " in Inventory" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
class LLWearFolderHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// not allowed from outside the app
|
||||
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { }
|
||||
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) {}
|
||||
|
||||
bool handle(const LLSD& tokens,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
LLSD::UUID folder_uuid;
|
||||
|
||||
if (folder_uuid.isNull() && query_map.has("folder_name"))
|
||||
if (wear_category(query_map, false))
|
||||
{
|
||||
std::string outfit_folder_name = query_map["folder_name"];
|
||||
folder_uuid = findDescendentCategoryIDByName(
|
||||
gInventory.getLibraryRootFolderID(),
|
||||
outfit_folder_name);
|
||||
}
|
||||
if (folder_uuid.isNull() && query_map.has("folder_id"))
|
||||
{
|
||||
folder_uuid = query_map["folder_id"].asUUID();
|
||||
}
|
||||
// Assume this is coming from the predefined avatars web floater
|
||||
LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance");
|
||||
|
||||
if (folder_uuid.notNull())
|
||||
{
|
||||
LLPointer<LLInventoryCategory> category = new LLInventoryCategory(folder_uuid,
|
||||
LLUUID::null,
|
||||
LLFolderType::FT_CLOTHING,
|
||||
"Quick Appearance");
|
||||
if ( gInventory.getCategory( folder_uuid ) != NULL )
|
||||
{
|
||||
// Assume this is coming from the predefined avatars web floater
|
||||
LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance");
|
||||
LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);
|
||||
|
||||
// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
|
||||
gAgent.setOutfitChosen(true);
|
||||
}
|
||||
// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
|
||||
gAgent.setOutfitChosen(true);
|
||||
}
|
||||
|
||||
// release avatar picker keyboard focus
|
||||
|
|
@ -4776,4 +4792,46 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class LLAddFolderHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// not allowed from outside the app
|
||||
LLAddFolderHandler() : LLCommandHandler("add_folder", UNTRUSTED_BLOCK) {}
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
wear_category(query_map, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLRemoveFolderHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLRemoveFolderHandler() : LLCommandHandler("remove_folder", UNTRUSTED_BLOCK) {}
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (query_map.has("folder_id"))
|
||||
{
|
||||
LLUUID folder_id = query_map["folder_id"].asUUID();
|
||||
if (folder_id.notNull())
|
||||
{
|
||||
if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id))
|
||||
{
|
||||
LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Couldn't find folder id" << folder_id << " in Inventory" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
LLWearFolderHandler gWearFolderHandler;
|
||||
LLAddFolderHandler gAddFolderHandler;
|
||||
LLRemoveFolderHandler gRemoveFolderHandler;
|
||||
|
|
|
|||
|
|
@ -349,10 +349,6 @@ std::string gLastVersionChannel;
|
|||
LLVector3 gWindVec(3.0, 3.0, 0.0);
|
||||
LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
|
||||
|
||||
U32 gPacketsIn = 0;
|
||||
|
||||
bool gPrintMessagesThisFrame = false;
|
||||
|
||||
bool gRandomizeFramerate = false;
|
||||
bool gPeriodicSlowFrame = false;
|
||||
|
||||
|
|
@ -361,6 +357,7 @@ bool gLLErrorActivated = false;
|
|||
bool gLogoutInProgress = false;
|
||||
|
||||
bool gSimulateMemLeak = false;
|
||||
bool gDoDisconnect = false;
|
||||
|
||||
// We don't want anyone, especially threads working on the graphics pipeline,
|
||||
// to have to block due to this WorkQueue being full.
|
||||
|
|
@ -374,7 +371,6 @@ const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
|
|||
const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
|
||||
const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
|
||||
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
|
||||
static bool gDoDisconnect = false;
|
||||
static std::string gLaunchFileOnQuit;
|
||||
|
||||
// Used on Win32 for other apps to identify our window (eg, win_setup)
|
||||
|
|
@ -455,7 +451,7 @@ void idle_afk_check()
|
|||
|
||||
// check idle timers
|
||||
F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
|
||||
LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
|
||||
static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
|
||||
if (afk_timeout() && (current_idle > afk_timeout()))
|
||||
{
|
||||
if (!gAgent.getAFK())
|
||||
|
|
@ -1510,9 +1506,9 @@ bool LLAppViewer::doFrame()
|
|||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout");
|
||||
pingMainloopTimeout("Main:Sleep");
|
||||
pingMainloopTimeout("Main:Sleep");
|
||||
|
||||
pauseMainloopTimeout();
|
||||
pauseMainloopTimeout();
|
||||
}
|
||||
|
||||
// Sleep and run background threads
|
||||
|
|
@ -2369,6 +2365,14 @@ void LLAppViewer::initLoggingAndGetLastDuration()
|
|||
{
|
||||
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
|
||||
}
|
||||
|
||||
std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log");
|
||||
if (gDirUtilp->fileExists(user_data_path_cef_log))
|
||||
{
|
||||
std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
|
||||
LLFile::remove(user_data_path_cef_old, ENOENT);
|
||||
LLFile::rename(user_data_path_cef_log, user_data_path_cef_old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2996,9 +3000,10 @@ void LLAppViewer::initStrings()
|
|||
std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
|
||||
if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
|
||||
{
|
||||
std::string crash_reason;
|
||||
if (strings_path_full.empty())
|
||||
{
|
||||
LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL;
|
||||
crash_reason = "The file '" + strings_file + "' is not found";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3006,24 +3011,23 @@ void LLAppViewer::initStrings()
|
|||
int rc = LLFile::stat(strings_path_full, &st);
|
||||
if (rc != 0)
|
||||
{
|
||||
LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL;
|
||||
crash_reason = "The file '" + strings_path_full + "' failed to get status. Error code: " + std::to_string(rc);
|
||||
}
|
||||
else if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL;
|
||||
crash_reason = "The filename '" + strings_path_full + "' is a directory name";
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL;
|
||||
crash_reason = "The filename '" + strings_path_full + "' doesn't seem to be a regular file name";
|
||||
}
|
||||
}
|
||||
|
||||
// initial check to make sure files are there failed
|
||||
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LLError::LLUserWarningMsg::showMissingFiles();
|
||||
LL_ERRS() << "Viewer failed to find localization and UI files."
|
||||
<< " Please reinstall viewer from https://secondlife.com/support/downloads"
|
||||
<< " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
LL_ERRS() << "Viewer failed to open some of localization and UI files."
|
||||
<< " " << crash_reason << "." << LL_ENDL;
|
||||
}
|
||||
LLTransUtil::parseStrings(strings_file, default_trans_args);
|
||||
LLTransUtil::parseLanguageStrings("language_settings.xml");
|
||||
|
|
@ -4259,7 +4263,7 @@ U32 LLAppViewer::getTextureCacheVersion()
|
|||
U32 LLAppViewer::getDiskCacheVersion()
|
||||
{
|
||||
// Viewer disk cache version intorduced in Simple Cache Viewer, change if the cache format changes.
|
||||
const U32 DISK_CACHE_VERSION = 1;
|
||||
const U32 DISK_CACHE_VERSION = 2;
|
||||
|
||||
return DISK_CACHE_VERSION ;
|
||||
}
|
||||
|
|
@ -4578,11 +4582,32 @@ void LLAppViewer::saveFinalSnapshot()
|
|||
}
|
||||
}
|
||||
|
||||
static const char PRODUCTION_CACHE_FORMAT_STRING[] = "%s.%s";
|
||||
static const char GRID_CACHE_FORMAT_STRING[] = "%s.%s.%s";
|
||||
std::string get_name_cache_filename(const std::string &base_file, const std::string& extention)
|
||||
{
|
||||
std::string filename;
|
||||
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, base_file));
|
||||
if (LLGridManager::getInstance()->isInProductionGrid())
|
||||
{
|
||||
filename = llformat(PRODUCTION_CACHE_FORMAT_STRING, path.c_str(), extention.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: The inventory cache filenames now include the grid name.
|
||||
// Add controls against directory traversal or problematic pathname lengths
|
||||
// if your viewer uses grid names from an untrusted source.
|
||||
const std::string& grid_id_str = LLGridManager::getInstance()->getGridId();
|
||||
const std::string& grid_id_lower = utf8str_tolower(grid_id_str);
|
||||
filename = llformat(GRID_CACHE_FORMAT_STRING, path.c_str(), grid_id_lower.c_str(), extention.c_str());
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
void LLAppViewer::loadNameCache()
|
||||
{
|
||||
// display names cache
|
||||
std::string filename =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
|
||||
std::string filename = get_name_cache_filename("avatar_name_cache", "xml");
|
||||
LL_INFOS("AvNameCache") << filename << LL_ENDL;
|
||||
llifstream name_cache_stream(filename.c_str());
|
||||
if(name_cache_stream.is_open())
|
||||
|
|
@ -4597,8 +4622,8 @@ void LLAppViewer::loadNameCache()
|
|||
|
||||
if (!gCacheName) return;
|
||||
|
||||
std::string name_cache;
|
||||
name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
|
||||
// is there a reason for the "cache" extention?
|
||||
std::string name_cache = get_name_cache_filename("name", "cache");
|
||||
llifstream cache_file(name_cache.c_str());
|
||||
if(cache_file.is_open())
|
||||
{
|
||||
|
|
@ -4609,8 +4634,7 @@ void LLAppViewer::loadNameCache()
|
|||
void LLAppViewer::saveNameCache()
|
||||
{
|
||||
// display names cache
|
||||
std::string filename =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
|
||||
std::string filename = get_name_cache_filename("avatar_name_cache", "xml");
|
||||
llofstream name_cache_stream(filename.c_str());
|
||||
if(name_cache_stream.is_open())
|
||||
{
|
||||
|
|
@ -4620,8 +4644,7 @@ void LLAppViewer::saveNameCache()
|
|||
// real names cache
|
||||
if (gCacheName)
|
||||
{
|
||||
std::string name_cache;
|
||||
name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
|
||||
std::string name_cache = get_name_cache_filename("name", "cache");
|
||||
llofstream cache_file(name_cache.c_str());
|
||||
if(cache_file.is_open())
|
||||
{
|
||||
|
|
@ -4899,6 +4922,20 @@ void LLAppViewer::idle()
|
|||
|
||||
if (gTeleportDisplay)
|
||||
{
|
||||
if (gAgent.getTeleportState() == LLAgent::TELEPORT_ARRIVING)
|
||||
{
|
||||
// Teleported, but waiting for things to load, start processing surface data
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_NETWORK);
|
||||
gVLManager.unpackData();
|
||||
}
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE);
|
||||
const F32 max_region_update_time = .001f; // 1ms
|
||||
LLWorld::getInstance()->updateRegions(max_region_update_time);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -5194,15 +5231,28 @@ void LLAppViewer::sendLogoutRequest()
|
|||
gLogoutInProgress = true;
|
||||
if (!mSecondInstance)
|
||||
{
|
||||
mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
|
||||
|
||||
mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
|
||||
if (mLogoutMarkerFile.getFileHandle())
|
||||
mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
|
||||
try
|
||||
{
|
||||
LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
|
||||
recordMarkerVersion(mLogoutMarkerFile);
|
||||
if (!mLogoutMarkerFile.getFileHandle())
|
||||
{
|
||||
mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
|
||||
if (mLogoutMarkerFile.getFileHandle())
|
||||
{
|
||||
LL_INFOS("MarkerFile") << "Created logout marker file '" << mLogoutMarkerFileName << "' " << LL_ENDL;
|
||||
recordMarkerVersion(mLogoutMarkerFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "Atempted to reopen file '" << mLogoutMarkerFileName << "' " << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (...)
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
|
||||
}
|
||||
|
|
@ -5335,12 +5385,9 @@ void LLAppViewer::idleNameCache()
|
|||
// Handle messages, and all message related stuff
|
||||
//
|
||||
|
||||
#define TIME_THROTTLE_MESSAGES
|
||||
|
||||
#ifdef TIME_THROTTLE_MESSAGES
|
||||
#define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
|
||||
constexpr F32 CHECK_MESSAGES_DEFAULT_MAX_TIME = 0.020f; // 50 ms = 50 fps (just for messages!)
|
||||
static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
|
||||
#endif
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_IDLE_NETWORK("Idle Network");
|
||||
static LLTrace::BlockTimerStatHandle FTM_MESSAGE_ACKS("Message Acks");
|
||||
|
|
@ -5357,7 +5404,8 @@ void LLAppViewer::idleNetwork()
|
|||
gObjectList.mNumNewObjects = 0;
|
||||
S32 total_decoded = 0;
|
||||
|
||||
if (!gSavedSettings.getBOOL("SpeedTest"))
|
||||
static LLCachedControl<bool> speed_test(gSavedSettings, "SpeedTest", false);
|
||||
if (!speed_test())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode
|
||||
|
||||
|
|
@ -5367,6 +5415,7 @@ void LLAppViewer::idleNetwork()
|
|||
F32 total_time = 0.0f;
|
||||
|
||||
{
|
||||
bool needs_drain = false;
|
||||
LockMessageChecker lmc(gMessageSystem);
|
||||
while (lmc.checkAllMessages(frame_count, gServicePump))
|
||||
{
|
||||
|
|
@ -5379,53 +5428,45 @@ void LLAppViewer::idleNetwork()
|
|||
}
|
||||
|
||||
total_decoded++;
|
||||
gPacketsIn++;
|
||||
|
||||
if (total_decoded > MESSAGE_MAX_PER_FRAME)
|
||||
{
|
||||
needs_drain = true;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TIME_THROTTLE_MESSAGES
|
||||
// Prevent slow packets from completely destroying the frame rate.
|
||||
// This usually happens due to clumps of avatars taking huge amount
|
||||
// of network processing time (which needs to be fixed, but this is
|
||||
// a good limit anyway).
|
||||
total_time = check_message_timer.getElapsedTimeF32();
|
||||
if (total_time >= CheckMessagesMaxTime)
|
||||
{
|
||||
needs_drain = true;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (needs_drain || gMessageSystem->mPacketRing.getNumBufferedPackets() > 0)
|
||||
{
|
||||
// Rather than allow packets to silently backup on the socket
|
||||
// we drain them into our own buffer so we know how many exist.
|
||||
S32 num_buffered_packets = gMessageSystem->drainUdpSocket();
|
||||
if (num_buffered_packets > 0)
|
||||
{
|
||||
// Increase CheckMessagesMaxTime so that we will eventually catch up
|
||||
CheckMessagesMaxTime *= 1.035f; // 3.5% ~= 2x in 20 frames, ~8x in 60 frames
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset CheckMessagesMaxTime to default value
|
||||
CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
|
||||
}
|
||||
|
||||
// Handle per-frame message system processing.
|
||||
lmc.processAcks(gSavedSettings.getF32("AckCollectTime"));
|
||||
}
|
||||
|
||||
#ifdef TIME_THROTTLE_MESSAGES
|
||||
if (total_time >= CheckMessagesMaxTime)
|
||||
{
|
||||
// Increase CheckMessagesMaxTime so that we will eventually catch up
|
||||
CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset CheckMessagesMaxTime to default value
|
||||
CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Decode enqueued messages...
|
||||
S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
|
||||
|
||||
if( remaining_possible_decodes <= 0 )
|
||||
{
|
||||
LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL;
|
||||
}
|
||||
|
||||
if (gPrintMessagesThisFrame)
|
||||
{
|
||||
LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL;
|
||||
gPrintMessagesThisFrame = false;
|
||||
static LLCachedControl<F32> ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f);
|
||||
lmc.processAcks(ack_collection_time());
|
||||
}
|
||||
}
|
||||
add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects);
|
||||
|
|
@ -5433,6 +5474,7 @@ void LLAppViewer::idleNetwork()
|
|||
// Retransmit unacknowledged packets.
|
||||
gXferManager->retransmitUnackedPackets();
|
||||
gAssetStorage->checkForTimeouts();
|
||||
gViewerThrottle.setBufferLoadRate(gMessageSystem->getBufferLoadRate());
|
||||
gViewerThrottle.updateDynamicThrottle();
|
||||
|
||||
// Check that the circuit between the viewer and the agent's current
|
||||
|
|
@ -5607,6 +5649,27 @@ void LLAppViewer::forceErrorCoroutineCrash()
|
|||
LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw LLException("A deliberate crash from LLCoros"); });
|
||||
}
|
||||
|
||||
void LLAppViewer::forceErrorCoroprocedureCrash()
|
||||
{
|
||||
LL_WARNS() << "Forcing a crash in LLCoprocedureManager" << LL_ENDL;
|
||||
LLCoprocedureManager::instance().enqueueCoprocedure("Upload", "DeliberateCrash",
|
||||
[](LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t&, const LLUUID&)
|
||||
{
|
||||
LL_WARNS() << "Forcing a deliberate bad memory access from LLCoprocedureManager" << LL_ENDL;
|
||||
S32* crash = NULL;
|
||||
*crash = 0xDEADBEEF;
|
||||
});
|
||||
}
|
||||
|
||||
void LLAppViewer::forceErrorWorkQueueCrash()
|
||||
{
|
||||
LL::WorkQueue::ptr_t workqueue = LL::WorkQueue::getInstance("General");
|
||||
if (workqueue)
|
||||
{
|
||||
workqueue->post([]() { throw LLException("This is a deliberate crash from General Queue"); });
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppViewer::forceErrorThreadCrash()
|
||||
{
|
||||
class LLCrashTestThread : public LLThread
|
||||
|
|
|
|||
|
|
@ -157,9 +157,6 @@ public:
|
|||
void loadNameCache();
|
||||
void saveNameCache();
|
||||
|
||||
void loadExperienceCache();
|
||||
void saveExperienceCache();
|
||||
|
||||
void removeMarkerFiles();
|
||||
void recordSessionToMarker();
|
||||
|
||||
|
|
@ -175,6 +172,8 @@ public:
|
|||
virtual void forceErrorOSSpecificException();
|
||||
virtual void forceErrorDriverCrash();
|
||||
virtual void forceErrorCoroutineCrash();
|
||||
virtual void forceErrorCoroprocedureCrash();
|
||||
virtual void forceErrorWorkQueueCrash();
|
||||
virtual void forceErrorThreadCrash();
|
||||
|
||||
// The list is found in app_settings/settings_files.xml
|
||||
|
|
@ -411,11 +410,10 @@ extern std::string gLastVersionChannel;
|
|||
|
||||
extern LLVector3 gWindVec;
|
||||
extern LLVector3 gRelativeWindVec;
|
||||
extern U32 gPacketsIn;
|
||||
extern bool gPrintMessagesThisFrame;
|
||||
|
||||
extern bool gRandomizeFramerate;
|
||||
extern bool gPeriodicSlowFrame;
|
||||
extern bool gDoDisconnect;
|
||||
|
||||
extern bool gSimulateMemLeak;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ void clearDumpLogsDir();
|
|||
struct CrashMetadata
|
||||
{
|
||||
std::string logFilePathname;
|
||||
std::string attributesPathname;
|
||||
std::string userSettingsPathname;
|
||||
std::string accountSettingsPathname;
|
||||
std::string staticDebugPathname;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,8 @@ CrashMetadataSingleton::CrashMetadataSingleton()
|
|||
// Note: we depend on being able to read the static_debug_info.log file
|
||||
// from the *previous* run before we overwrite it with the new one for
|
||||
// *this* run. LLAppViewer initialization must happen in the Right Order.
|
||||
|
||||
// Todo: consider converting static file into bugspalt attributes file
|
||||
staticDebugPathname = *gViewerAppPtr->getStaticDebugFile();
|
||||
std::ifstream static_file(staticDebugPathname);
|
||||
LLSD info;
|
||||
|
|
@ -215,7 +217,32 @@ CrashMetadataSingleton::CrashMetadataSingleton()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate bugsplat attributes
|
||||
LLXMLNodePtr out_node = new LLXMLNode("XmlCrashContext", false);
|
||||
|
||||
out_node->createChild("OS", false)->setValue(OSInfo);
|
||||
out_node->createChild("AppState", false)->setValue(info["StartupState"].asString());
|
||||
out_node->createChild("GraphicsCard", false)->setValue(info["GraphicsCard"].asString());
|
||||
out_node->createChild("GLVersion", false)->setValue(info["GLInfo"]["GLVersion"].asString());
|
||||
out_node->createChild("GLRenderer", false)->setValue(info["GLInfo"]["GLRenderer"].asString());
|
||||
out_node->createChild("RAM", false)->setValue(info["RAMInfo"]["Physical"].asString());
|
||||
|
||||
if (!out_node->isNull())
|
||||
{
|
||||
attributesPathname = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "CrashContext.xml");
|
||||
LLFILE* fp = LLFile::fopen(attributesPathname, "w");
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
LLXMLNode::writeHeaderToFile(fp);
|
||||
out_node->writeToFile(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// else Todo: consider fillig at least some values, like OS
|
||||
}
|
||||
|
||||
// Avoid having to compile all of our LLSingleton machinery in Objective-C++.
|
||||
|
|
|
|||
|
|
@ -155,10 +155,10 @@ namespace
|
|||
|
||||
sBugSplatSender->setAttribute(WCSTR(L"OS"), WCSTR(LLOSInfo::instance().getOSStringSimple())); // In case we ever stop using email for this
|
||||
sBugSplatSender->setAttribute(WCSTR(L"AppState"), WCSTR(LLStartUp::getStartupStateString()));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GL Vendor"), WCSTR(gGLManager.mGLVendor));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GL Version"), WCSTR(gGLManager.mGLVersionString));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GPU Version"), WCSTR(gGLManager.mDriverVersionVendorString));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GL Renderer"), WCSTR(gGLManager.mGLRenderer));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GLVendor"), WCSTR(gGLManager.mGLVendor));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GLVersion"), WCSTR(gGLManager.mGLVersionString));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GPUVersion"), WCSTR(gGLManager.mDriverVersionVendorString));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"GLRenderer"), WCSTR(gGLManager.mGLRenderer));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"VRAM"), WCSTR(STRINGIZE(gGLManager.mVRAM)));
|
||||
sBugSplatSender->setAttribute(WCSTR(L"RAM"), WCSTR(STRINGIZE(gSysMemory.getPhysicalMemoryKB().value())));
|
||||
|
||||
|
|
@ -804,14 +804,16 @@ bool LLAppViewerWin32::cleanup()
|
|||
return result;
|
||||
}
|
||||
|
||||
void LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
|
||||
bool LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
|
||||
{
|
||||
#if defined(LL_BUGSPLAT)
|
||||
if (sBugSplatSender)
|
||||
{
|
||||
sBugSplatSender->createReport((EXCEPTION_POINTERS*)pExcepInfo);
|
||||
return true;
|
||||
}
|
||||
#endif // LL_BUGSPLAT
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLAppViewerWin32::initLoggingAndGetLastDuration()
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public:
|
|||
bool init() override; // Override to do application initialization
|
||||
bool cleanup() override;
|
||||
|
||||
void reportCrashToBugsplat(void* pExcepInfo) override;
|
||||
bool reportCrashToBugsplat(void* pExcepInfo) override;
|
||||
|
||||
protected:
|
||||
void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info.
|
||||
|
|
|
|||
|
|
@ -669,6 +669,7 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassif
|
|||
|
||||
void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id)
|
||||
{
|
||||
LL_DEBUGS("PickInfo") << " Requiesting pick info for " << pick_id << LL_ENDL;
|
||||
// Must ask for a pick based on the creator id because
|
||||
// the pick database is distributed to the inventory cluster. JC
|
||||
std::vector<std::string> request_params{ creator_id.asString(), pick_id.asString() };
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "llinventorymodel.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llslurl.h"
|
||||
#include "llstartup.h"
|
||||
#include "llimview.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
|
@ -271,6 +272,22 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
|
|||
<< "]" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// It's possible that the buddy list getting propagated from the inventory may have happened after we actually got the buddy list.
|
||||
// Any buddies that we got prior will reside in a special queue that we must process and update statuses accordingly with.
|
||||
// Do that here.
|
||||
// -Geenz 2025-03-12
|
||||
while (!mBuddyStatusQueue.empty())
|
||||
{
|
||||
auto buddyStatus = mBuddyStatusQueue.front();
|
||||
mBuddyStatusQueue.pop();
|
||||
|
||||
if (mBuddyInfo.find(buddyStatus.first) != mBuddyInfo.end())
|
||||
{
|
||||
setBuddyOnline(buddyStatus.first, buddyStatus.second);
|
||||
}
|
||||
}
|
||||
|
||||
// do not notify observers here - list can be large so let it be done on idle.
|
||||
|
||||
return new_buddy_count;
|
||||
|
|
@ -335,6 +352,8 @@ void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
|
|||
{
|
||||
LL_WARNS() << "!! No buddy info found for " << id
|
||||
<< ", setting to " << (is_online ? "Online" : "Offline") << LL_ENDL;
|
||||
LL_WARNS() << "Did we receive a buddy status update before the buddy info?" << LL_ENDL;
|
||||
mBuddyStatusQueue.push(std::make_pair(id, is_online));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,7 +504,7 @@ void LLAvatarTracker::idleNotifyObservers()
|
|||
|
||||
void LLAvatarTracker::notifyObservers()
|
||||
{
|
||||
if (mIsNotifyObservers)
|
||||
if (mIsNotifyObservers || (LLStartUp::getStartupState() <= STATE_INVENTORY_CALLBACKS))
|
||||
{
|
||||
// Don't allow multiple calls.
|
||||
// new masks and ids will be processed later from idle.
|
||||
|
|
@ -706,6 +725,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
|
|||
{
|
||||
LL_WARNS() << "Received online notification for unknown buddy: "
|
||||
<< agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << LL_ENDL;
|
||||
LL_WARNS() << "Adding buddy to buddy queue." << LL_ENDL;
|
||||
mBuddyStatusQueue.push(std::make_pair(agent_id, true));
|
||||
}
|
||||
|
||||
if(tracking_id == agent_id)
|
||||
|
|
@ -723,7 +744,11 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
|
|||
|
||||
mModifyMask |= LLFriendObserver::ONLINE;
|
||||
instance().notifyObservers();
|
||||
gInventory.notifyObservers();
|
||||
// Skip if we had received the friends list before the inventory callbacks were properly initialized
|
||||
if (LLStartUp::getStartupState() > STATE_INVENTORY_CALLBACKS)
|
||||
{
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ public:
|
|||
// add or remove agents from buddy list. Each method takes a set
|
||||
// of buddies and returns how many were actually added or removed.
|
||||
typedef std::map<LLUUID, LLRelationship*> buddy_map_t;
|
||||
typedef std::queue<std::pair<LLUUID, bool>> buddy_status_queue_t;
|
||||
|
||||
S32 addBuddyList(const buddy_map_t& buddies);
|
||||
//S32 removeBuddyList(const buddy_list_t& exes);
|
||||
|
|
@ -194,6 +195,7 @@ protected:
|
|||
//LLInventoryObserver* mInventoryObserver;
|
||||
|
||||
buddy_map_t mBuddyInfo;
|
||||
buddy_status_queue_t mBuddyStatusQueue;
|
||||
|
||||
typedef std::set<LLUUID> changed_buddy_t;
|
||||
changed_buddy_t mChangedBuddyIDs;
|
||||
|
|
|
|||
|
|
@ -240,10 +240,11 @@ void LLNotificationChiclet::setCounter(S32 counter)
|
|||
bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )
|
||||
{
|
||||
bool displayNotification;
|
||||
LLFloaterNotificationsTabbed* floater = LLFloaterNotificationsTabbed::getInstance();
|
||||
if ( (notification->getName() == "ScriptDialog") // special case for scripts
|
||||
// if there is no toast window for the notification, filter it
|
||||
//|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
|
||||
|| (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID(), notification->getName()))
|
||||
|| (floater && !floater->findItemByID(notification->getID(), notification->getName()))
|
||||
)
|
||||
{
|
||||
displayNotification = false;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
// viewer includes
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llcriticaldamp.h"
|
||||
#include "llface.h"
|
||||
#include "lllightconstants.h"
|
||||
|
|
@ -252,7 +253,15 @@ void LLDrawable::cleanupReferences()
|
|||
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
|
||||
mFaces.clear();
|
||||
|
||||
gPipeline.unlinkDrawable(this);
|
||||
if (gPipeline.mInitialized)
|
||||
{
|
||||
gPipeline.unlinkDrawable(this);
|
||||
}
|
||||
else if (getSpatialGroup())
|
||||
{
|
||||
// Not supposed to happen?
|
||||
getSpatialGroup()->getSpatialPartition()->remove(this, getSpatialGroup());
|
||||
}
|
||||
|
||||
removeFromOctree();
|
||||
|
||||
|
|
@ -778,6 +787,14 @@ bool LLDrawable::updateMove()
|
|||
|
||||
makeActive();
|
||||
|
||||
// #3256 force undampened movement for attached objects in mouselook
|
||||
// to prevent animation bork for linkset with animated parts
|
||||
if (!isRoot() && gAgentCamera.cameraMouselook() &&
|
||||
!mVObjp->isRiggedMesh() && mVObjp->getAvatar() && mVObjp->getAvatar()->isSelf())
|
||||
{
|
||||
return updateMoveUndamped();
|
||||
}
|
||||
|
||||
return isState(MOVE_UNDAMPED) ? updateMoveUndamped() : updateMoveDamped();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,8 +108,9 @@ void LLDrawPoolTree::beginShadowPass(S32 pass)
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"),
|
||||
gSavedSettings.getF32("RenderDeferredTreeShadowBias"));
|
||||
static LLCachedControl<F32> shadow_offset(gSavedSettings, "RenderDeferredTreeShadowOffset");
|
||||
static LLCachedControl<F32> shadow_bias(gSavedSettings, "RenderDeferredTreeShadowBias");
|
||||
glPolygonOffset(shadow_offset(), shadow_bias());
|
||||
|
||||
LLEnvironment& environment = LLEnvironment::instance();
|
||||
|
||||
|
|
|
|||
|
|
@ -101,10 +101,18 @@ namespace Details
|
|||
void LLEventPollImpl::handleMessage(const LLSD& content)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
|
||||
std::string msg_name = content["message"];
|
||||
std::string msg_name = content["message"].asString();
|
||||
LLSD message;
|
||||
message["sender"] = mSenderIp;
|
||||
message["body"] = content["body"];
|
||||
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;
|
||||
}
|
||||
|
||||
LLMessageSystem::dispatch(msg_name, message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2218,7 +2218,7 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
|
|||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged");
|
||||
//override with joint volume face joint bounding boxes
|
||||
LLVOAvatar* avatar = mVObjp->getAvatar();
|
||||
LLVOAvatar* avatar = mVObjp.notNull() ? mVObjp->getAvatar() : nullptr;
|
||||
bool hasRiggedExtents = false;
|
||||
|
||||
if (avatar && avatar->mDrawable)
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const
|
|||
{
|
||||
mTrackingIdToLocalTexture.erase(tracking_id);
|
||||
}
|
||||
updateLocalTexDataDigest();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -670,6 +670,7 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
|
|||
break;
|
||||
case FFLOAD_HDRI:
|
||||
allowedv->push_back("exr");
|
||||
case FFLOAD_MODEL:
|
||||
case FFLOAD_COLLADA:
|
||||
allowedv->push_back("dae");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -693,7 +693,15 @@ void LLFloater360Capture::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
|
|||
);
|
||||
|
||||
// execute the command on the page
|
||||
mWebBrowser->getMediaPlugin()->executeJavaScript(cmd);
|
||||
LLPluginClassMedia* plugin = mWebBrowser->getMediaPlugin();
|
||||
if (plugin)
|
||||
{
|
||||
plugin->executeJavaScript(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("360Capture") << "No media plugin found" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -774,7 +782,15 @@ void LLFloater360Capture::onSaveLocalBtn()
|
|||
|
||||
// send it to the browser instance, triggering the equirectangular capture
|
||||
// process and complimentary offer to save the image
|
||||
mWebBrowser->getMediaPlugin()->executeJavaScript(cmd);
|
||||
LLPluginClassMedia* plugin = mWebBrowser->getMediaPlugin();
|
||||
if (plugin)
|
||||
{
|
||||
plugin->executeJavaScript(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("360Capture") << "No media plugin found" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// We capture all 6 images sequentially and if parts of the world are moving
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llagent.h"
|
||||
#include "llagentui.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "lllandmarkactions.h"
|
||||
|
|
@ -389,6 +390,7 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items)
|
|||
{
|
||||
mItem = item;
|
||||
mAssetID = mItem->getAssetUUID();
|
||||
mParentID = mItem->getParentUUID();
|
||||
setVisibleAndFrontmost(true);
|
||||
break;
|
||||
}
|
||||
|
|
@ -418,8 +420,7 @@ void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask)
|
|||
closeFloater();
|
||||
}
|
||||
|
||||
LLUUID folder_id = mFolderCombo->getValue().asUUID();
|
||||
if (folder_id != mItem->getParentUUID())
|
||||
if (mParentID != mItem->getParentUUID())
|
||||
{
|
||||
// user moved landmark in inventory,
|
||||
// assume that we are done all other changes should already be commited
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ private:
|
|||
LLTextEditor* mNotesEditor;
|
||||
LLUUID mLandmarksID;
|
||||
LLUUID mAssetID;
|
||||
LLUUID mParentID;
|
||||
|
||||
LLLandmarksInventoryObserver* mInventoryObserver;
|
||||
LLPointer<LLInventoryItem> mItem;
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@ static const S32 USED_EMOJIS_IMAGE_INDEX = 0x23F2;
|
|||
// https://www.compart.com/en/unicode/U+1F6D1
|
||||
static const S32 EMPTY_LIST_IMAGE_INDEX = 0x1F6D1;
|
||||
// The following categories should follow the required alphabetic order
|
||||
static const std::string RECENTLY_USED_CATEGORY = "1 recently used";
|
||||
static const std::string FREQUENTLY_USED_CATEGORY = "2 frequently used";
|
||||
static const std::string FREQUENTLY_USED_CATEGORY = "frequently used";
|
||||
|
||||
// Floater state related variables
|
||||
static std::list<llwchar> sRecentlyUsed;
|
||||
|
|
@ -445,11 +444,10 @@ void LLFloaterEmojiPicker::fillGroups()
|
|||
params.name = "all_categories";
|
||||
createGroupButton(params, rect, ALL_EMOJIS_IMAGE_INDEX);
|
||||
|
||||
// Create group and button for "Recently used" and/or "Frequently used"
|
||||
if (!sRecentlyUsed.empty() || !sFrequentlyUsed.empty())
|
||||
// Create group and button for "Frequently used"
|
||||
if (!sFrequentlyUsed.empty())
|
||||
{
|
||||
std::map<std::string, std::vector<LLEmojiSearchResult>> cats;
|
||||
fillCategoryRecentlyUsed(cats);
|
||||
fillCategoryFrequentlyUsed(cats);
|
||||
|
||||
if (!cats.empty())
|
||||
|
|
@ -482,40 +480,6 @@ void LLFloaterEmojiPicker::fillGroups()
|
|||
resizeGroupButtons();
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats)
|
||||
{
|
||||
if (sRecentlyUsed.empty())
|
||||
return;
|
||||
|
||||
std::vector<LLEmojiSearchResult> emojis;
|
||||
|
||||
// In case of empty mFilterPattern we'd use sRecentlyUsed directly
|
||||
if (!mFilterPattern.empty())
|
||||
{
|
||||
// List all emojis in "Recently used"
|
||||
const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
|
||||
std::size_t begin, end;
|
||||
for (llwchar emoji : sRecentlyUsed)
|
||||
{
|
||||
auto e2d = emoji2descr.find(emoji);
|
||||
if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty())
|
||||
{
|
||||
for (const std::string& shortcode : e2d->second->ShortCodes)
|
||||
{
|
||||
if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern))
|
||||
{
|
||||
emojis.emplace_back(emoji, shortcode, begin, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (emojis.empty())
|
||||
return;
|
||||
}
|
||||
|
||||
cats.emplace(std::make_pair(RECENTLY_USED_CATEGORY, emojis));
|
||||
}
|
||||
|
||||
void LLFloaterEmojiPicker::fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats)
|
||||
{
|
||||
if (sFrequentlyUsed.empty())
|
||||
|
|
@ -756,7 +720,6 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes
|
|||
{
|
||||
// Place the category title
|
||||
std::string title =
|
||||
category == RECENTLY_USED_CATEGORY ? getString("title_for_recently_used") :
|
||||
category == FREQUENTLY_USED_CATEGORY ? getString("title_for_frequently_used") :
|
||||
isupper(category.front()) ? category : LLStringUtil::capitalize(category);
|
||||
LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, title);
|
||||
|
|
@ -769,21 +732,7 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes
|
|||
{
|
||||
const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
|
||||
LLEmojiSearchResult emoji { 0, "", 0, 0 };
|
||||
if (category == RECENTLY_USED_CATEGORY)
|
||||
{
|
||||
for (llwchar code : sRecentlyUsed)
|
||||
{
|
||||
const LLEmojiDictionary::emoji2descr_map_t::const_iterator& e2d = emoji2descr.find(code);
|
||||
if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty())
|
||||
{
|
||||
emoji.Character = code;
|
||||
emoji.String = e2d->second->ShortCodes.front();
|
||||
createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params,
|
||||
icon_rect, max_icons, bg, row, icon_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (category == FREQUENTLY_USED_CATEGORY)
|
||||
if (category == FREQUENTLY_USED_CATEGORY)
|
||||
{
|
||||
for (const auto& code : sFrequentlyUsed)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ public:
|
|||
private:
|
||||
void initialize();
|
||||
void fillGroups();
|
||||
void fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
|
||||
void fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
|
||||
void fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index);
|
||||
void createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji);
|
||||
|
|
|
|||
|
|
@ -1939,7 +1939,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
|
|||
mConversationEventQueue.erase(uuid);
|
||||
|
||||
// Don't let the focus fall IW, select and refocus on the first conversation in the list
|
||||
if (change_focus)
|
||||
if (change_focus && isInVisibleChain())
|
||||
{
|
||||
setFocus(true);
|
||||
if (new_selection)
|
||||
|
|
@ -1959,6 +1959,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Conversation widgets: " << (S32)mConversationsWidgets.size() << LL_ENDL;
|
||||
}
|
||||
return is_widget_selected;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ void LLFloaterLagMeter::determineNetwork()
|
|||
// the network handlers are de-synched from the rendering.
|
||||
F32Milliseconds client_frame_time = frame_recording.getPeriodMean(LLStatViewer::FRAME_STACKTIME);
|
||||
|
||||
// Todo: account for LLPacketRing dropped packets? viewer drops those when it can't keep up
|
||||
if(packet_loss >= mNetworkPacketLossCritical)
|
||||
{
|
||||
mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME));
|
||||
|
|
|
|||
|
|
@ -115,12 +115,12 @@ bool LLFloaterPerformance::postBuild()
|
|||
mHUDList = mHUDsPanel->getChild<LLNameListCtrl>("hud_list");
|
||||
mHUDList->setNameListType(LLNameListCtrl::SPECIAL);
|
||||
mHUDList->setHoverIconName("StopReload_Off");
|
||||
mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1));
|
||||
mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1));
|
||||
|
||||
mObjectList = mComplexityPanel->getChild<LLNameListCtrl>("obj_list");
|
||||
mObjectList->setNameListType(LLNameListCtrl::SPECIAL);
|
||||
mObjectList->setHoverIconName("StopReload_Off");
|
||||
mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1));
|
||||
mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1));
|
||||
|
||||
mSettingsPanel->getChild<LLButton>("advanced_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickAdvanced, this));
|
||||
mSettingsPanel->getChild<LLButton>("defaults_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickDefaults, this));
|
||||
|
|
@ -527,9 +527,13 @@ void LLFloaterPerformance::setFPSText()
|
|||
mTextFPSLabel->setValue(fps_text);
|
||||
}
|
||||
|
||||
void LLFloaterPerformance::detachItem(const LLUUID& item_id)
|
||||
void LLFloaterPerformance::detachObject(const LLUUID& obj_id)
|
||||
{
|
||||
LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
|
||||
LLViewerObject* obj = gObjectList.findObject(obj_id);
|
||||
if (obj)
|
||||
{
|
||||
LLAppearanceMgr::instance().removeItemFromAvatar(obj->getAttachmentItemID());
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPerformance::onClickAdvanced()
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public:
|
|||
void hidePanels();
|
||||
void showAutoadjustmentsPanel();
|
||||
|
||||
void detachItem(const LLUUID& item_id);
|
||||
void detachObject(const LLUUID& obj_id);
|
||||
|
||||
void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
|
||||
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
mCommitCallbackRegistrar.add("Pref.AutoAdjustments", boost::bind(&LLFloaterPreference::onClickAutoAdjustments, this));
|
||||
mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
|
||||
mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable", boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this));
|
||||
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreference::updateMaxNonImpostors, this));
|
||||
mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreference::updateMaxComplexity, this));
|
||||
mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreference::onRenderOptionEnable, this));
|
||||
mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
|
||||
|
|
@ -360,6 +361,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
|
||||
|
||||
mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::updateComplexityText, this));
|
||||
mImpostorsChangedSignal = gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreference::updateIndirectMaxNonImpostors, this, _2));
|
||||
|
||||
mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
|
||||
mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
|
||||
|
|
@ -542,7 +544,12 @@ void LLFloaterPreference::onDoNotDisturbResponseChanged()
|
|||
LLFloaterPreference::~LLFloaterPreference()
|
||||
{
|
||||
LLConversationLog::instance().removeObserver(this);
|
||||
if (LLAvatarPropertiesProcessor::instanceExists())
|
||||
{
|
||||
LLAvatarPropertiesProcessor::getInstance()->removeObserver(gAgent.getID(), this);
|
||||
}
|
||||
mComplexityChangedSignal.disconnect();
|
||||
mImpostorsChangedSignal.disconnect();
|
||||
}
|
||||
|
||||
void LLFloaterPreference::draw()
|
||||
|
|
@ -1287,6 +1294,9 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
|
|||
void LLFloaterPreference::refresh()
|
||||
{
|
||||
LLPanel::refresh();
|
||||
setMaxNonImpostorsText(
|
||||
gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
|
||||
getChild<LLTextBox>("IndirectMaxNonImpostorsText", true));
|
||||
LLAvatarComplexityControls::setText(
|
||||
gSavedSettings.getU32("RenderAvatarMaxComplexity"),
|
||||
getChild<LLTextBox>("IndirectMaxComplexityText", true));
|
||||
|
|
@ -1561,6 +1571,44 @@ void LLAvatarComplexityControls::setRenderTimeText(F32 value, LLTextBox* text_bo
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloaterPreference::updateMaxNonImpostors()
|
||||
{
|
||||
// Called when the IndirectMaxNonImpostors control changes
|
||||
// Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors
|
||||
LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors", true);
|
||||
U32 value = ctrl->getValue().asInteger();
|
||||
|
||||
if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value);
|
||||
LLVOAvatar::updateImpostorRendering(value); // make it effective immediately
|
||||
setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
|
||||
}
|
||||
|
||||
void LLFloaterPreference::updateIndirectMaxNonImpostors(const LLSD& newvalue)
|
||||
{
|
||||
U32 value = newvalue.asInteger();
|
||||
if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors")))
|
||||
{
|
||||
gSavedSettings.setU32("IndirectMaxNonImpostors", value);
|
||||
}
|
||||
setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
|
||||
}
|
||||
|
||||
void LLFloaterPreference::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
|
||||
{
|
||||
if (0 == value)
|
||||
{
|
||||
text_box->setText(LLTrans::getString("no_limit"));
|
||||
}
|
||||
else
|
||||
{
|
||||
text_box->setText(llformat("%d", value));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPreference::updateMaxComplexity()
|
||||
{
|
||||
// Called when the IndirectMaxComplexity control changes
|
||||
|
|
|
|||
|
|
@ -206,6 +206,9 @@ private:
|
|||
void onDeleteTranscripts();
|
||||
void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response);
|
||||
void updateDeleteTranscriptsButton();
|
||||
void updateMaxNonImpostors();
|
||||
void updateIndirectMaxNonImpostors(const LLSD& newvalue);
|
||||
void setMaxNonImpostorsText(U32 value, LLTextBox* text_box);
|
||||
void updateMaxComplexity();
|
||||
void updateComplexityText();
|
||||
static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map);
|
||||
|
|
@ -234,6 +237,7 @@ private:
|
|||
std::unique_ptr< ll::prefs::SearchData > mSearchData;
|
||||
bool mSearchDataDirty;
|
||||
|
||||
boost::signals2::connection mImpostorsChangedSignal;
|
||||
boost::signals2::connection mComplexityChangedSignal;
|
||||
|
||||
void onUpdateFilterTerm( bool force = false );
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue