Merge branch 'DRTVWR-600-maint-A' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/llimage/llimage.cpp
#	indra/llimage/llimage.h
#	indra/llkdu/llimagej2ckdu.cpp
#	indra/newview/app_settings/settings.xml
#	indra/newview/llfavoritesbar.cpp
#	indra/newview/llfloaterpreference.cpp
#	indra/newview/llfloaterpreference.h
#	scripts/messages/message_template.msg.sha1
master
Ansariel 2024-02-06 17:58:20 +01:00
commit a831237e29
109 changed files with 1952 additions and 772 deletions

View File

@ -5,7 +5,7 @@
#
# Platform variables:
#
# DARWIN - Mac OS X
# DARWIN - macOS
# LINUX - Linux
# WINDOWS - Windows

View File

@ -116,7 +116,7 @@ BASE_ARGUMENTS=[
dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE),
dict(name='buildtype', description='Build type (i.e. Debug, Release, RelWithDebInfo).', default=None),
dict(name='bundleid',
description="""The Mac OS X Bundle identifier.""",
description="""The macOS Bundle identifier.""",
default="com.secondlife.indra.viewer"),
dict(name='channel',
description="""The channel to use for updates, packaging, settings name, etc.""",
@ -146,7 +146,7 @@ BASE_ARGUMENTS=[
dict(name='signature',
description="""This specifies an identity to sign the viewer with, if any.
If no value is supplied, the default signature will be used, if any. Currently
only used on Mac OS X.""",
only used on macOS.""",
default=None),
dict(name='source',
description='Source directory.',

View File

@ -247,7 +247,7 @@ public:
//--------------------------------------------------------------------
public:
void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer);
virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0;
virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0;
/** Rendering
** **

View File

@ -661,7 +661,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
//-----------------------------------------------------------------------------
// applyMask()
//-----------------------------------------------------------------------------
void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
{
LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL;
@ -782,7 +782,7 @@ LLPolyVertexMask::~LLPolyVertexMask()
//-----------------------------------------------------------------------------
// generateMask()
//-----------------------------------------------------------------------------
void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights)
void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights)
{
// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
// BOOL debugImg = FALSE;

View File

@ -84,7 +84,7 @@ public:
LLPolyVertexMask(const LLPolyVertexMask& pOther);
~LLPolyVertexMask();
void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
F32* getMorphMaskWeights();
@ -170,7 +170,7 @@ public:
/*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
/*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
void addPendingMorphMask() { mNumMorphMasksPending++; }
void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton()

View File

@ -535,7 +535,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components)
{
mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
}

View File

@ -203,7 +203,7 @@ public:
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false);
BOOL isBodyRegion(const std::string& region) const;
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid() const;
virtual void requestUpdate() = 0;
void invalidateMorphMasks();

View File

@ -581,7 +581,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
}
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
LL_PROFILE_ZONE_SCOPED;
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;

View File

@ -199,7 +199,7 @@ public:
// Returns bytes read/written, 0 if read/write fails:
static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
static S32 writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
//*******************************************************************************************************************************
};

View File

@ -711,7 +711,7 @@ namespace
bool shouldLogToStderr()
{
#if LL_DARWIN
// On Mac OS X, stderr from apps launched from the Finder goes to the
// On macOS, stderr from apps launched from the Finder goes to the
// console log. It's generally considered bad form to spam too much
// there. That scenario can be detected by noticing that stderr is a
// character device (S_IFCHR).

View File

@ -29,19 +29,20 @@
#include "llthread.h"
#include "lltimer.h"
//============================================================================
//---------------------------------------------------------------------
//
// LLMutex
//
LLMutex::LLMutex() :
mCount(0)
{
}
LLMutex::~LLMutex()
{
}
void LLMutex::lock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
@ -112,7 +113,7 @@ LLThread::id_t LLMutex::lockingThread() const
bool LLMutex::trylock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
if(isSelfLocked())
if (isSelfLocked())
{ //redundant lock
mCount++;
return true;
@ -135,19 +136,194 @@ bool LLMutex::trylock()
return true;
}
//============================================================================
//---------------------------------------------------------------------
//
// LLSharedMutex
//
LLSharedMutex::LLSharedMutex()
: mLockingThreads(2) // Reserve 2 slots in the map hash table
, mIsShared(false)
{
}
bool LLSharedMutex::isLocked() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
std::lock_guard<std::mutex> lock(mLockMutex);
return !mLockingThreads.empty();
}
bool LLSharedMutex::isThreadLocked() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);
const_iterator it = mLockingThreads.find(current_thread);
return it != mLockingThreads.end();
}
void LLSharedMutex::lockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
mLockMutex.lock();
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
it->second++;
}
else
{
// Acquire the mutex immediately if the mutex is not locked exclusively
// or enter a locking state if the mutex is already locked exclusively
mLockMutex.unlock();
mSharedMutex.lock_shared();
mLockMutex.lock();
// Continue after acquiring the mutex
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = true;
}
mLockMutex.unlock();
}
void LLSharedMutex::lockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
mLockMutex.lock();
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
if (mIsShared)
{
// The mutex is already locked in the current thread
// but this lock is SHARED (not EXCLISIVE)
// We can't lock it again, the lock stays shared
// This can lead to a collision (theoretically)
llassert_always(!"The current thread is already locked SHARED and can't be locked EXCLUSIVE");
}
it->second++;
}
else
{
// Acquire the mutex immediately if mLockingThreads is empty
// or enter a locking state if mLockingThreads is not empty
mLockMutex.unlock();
mSharedMutex.lock();
mLockMutex.lock();
// Continue after acquiring the mutex (and possible quitting the locking state)
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = false;
}
mLockMutex.unlock();
}
bool LLSharedMutex::trylockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
it->second++;
}
else
{
if (!mSharedMutex.try_lock_shared())
return false;
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = true;
}
return true;
}
bool LLSharedMutex::trylockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);
if (mLockingThreads.size() == 1 && mLockingThreads.begin()->first == current_thread)
{
mLockingThreads.begin()->second++;
}
else
{
if (!mSharedMutex.try_lock())
return false;
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = false;
}
return true;
}
void LLSharedMutex::unlockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
if (it->second > 1)
{
it->second--;
}
else
{
mLockingThreads.erase(it);
mSharedMutex.unlock_shared();
}
}
}
void LLSharedMutex::unlockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
if (it->second > 1)
{
it->second--;
}
else
{
mLockingThreads.erase(it);
mSharedMutex.unlock();
}
}
}
//---------------------------------------------------------------------
//
// LLCondition
//
LLCondition::LLCondition() :
LLMutex()
{
}
LLCondition::~LLCondition()
{
}
void LLCondition::wait()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
@ -168,7 +344,10 @@ void LLCondition::broadcast()
}
//---------------------------------------------------------------------
//
// LLMutexTrylock
//
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
: mMutex(mutex),
mLocked(false)

View File

@ -32,6 +32,8 @@
#include <boost/noncopyable.hpp>
#include "mutex.h"
#include <shared_mutex>
#include <unordered_map>
#include <condition_variable>
//============================================================================
@ -66,6 +68,45 @@ protected:
#endif
};
//============================================================================
class LL_COMMON_API LLSharedMutex
{
public:
LLSharedMutex();
bool isLocked() const;
bool isThreadLocked() const;
bool isShared() const { return mIsShared; }
void lockShared();
void lockExclusive();
template<bool SHARED> void lock();
template<> void lock<true>() { lockShared(); }
template<> void lock<false>() { lockExclusive(); }
bool trylockShared();
bool trylockExclusive();
template<bool SHARED> bool trylock();
template<> bool trylock<true>() { return trylockShared(); }
template<> bool trylock<false>() { return trylockExclusive(); }
void unlockShared();
void unlockExclusive();
template<bool SHARED> void unlock();
template<> void unlock<true>() { unlockShared(); }
template<> void unlock<false>() { unlockExclusive(); }
private:
std::shared_mutex mSharedMutex;
mutable std::mutex mLockMutex;
std::unordered_map<LLThread::id_t, U32> mLockingThreads;
bool mIsShared;
using iterator = std::unordered_map<LLThread::id_t, U32>::iterator;
using const_iterator = std::unordered_map<LLThread::id_t, U32>::const_iterator;
};
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
class LL_COMMON_API LLCondition : public LLMutex
{
@ -81,27 +122,57 @@ protected:
std::condition_variable mCond;
};
//============================================================================
class LLMutexLock
{
public:
LLMutexLock(LLMutex* mutex)
{
mMutex = mutex;
if(mMutex)
if (mMutex)
mMutex->lock();
}
~LLMutexLock()
{
if(mMutex)
if (mMutex)
mMutex->unlock();
}
private:
LLMutex* mMutex;
};
//============================================================================
template<bool SHARED>
class LLSharedMutexLockTemplate
{
public:
LLSharedMutexLockTemplate(LLSharedMutex* mutex)
: mSharedMutex(mutex)
{
if (mSharedMutex)
mSharedMutex->lock<SHARED>();
}
~LLSharedMutexLockTemplate()
{
if (mSharedMutex)
mSharedMutex->unlock<SHARED>();
}
private:
LLSharedMutex* mSharedMutex;
};
using LLSharedMutexLock = LLSharedMutexLockTemplate<true>;
using LLExclusiveMutexLock = LLSharedMutexLockTemplate<false>;
//============================================================================
// Scoped locking class similar in function to LLMutexLock but uses
// the trylock() method to conditionally acquire lock without
// blocking. Caller resolves the resulting condition by calling
@ -127,6 +198,8 @@ private:
bool mLocked;
};
//============================================================================
/**
* @class LLScopedLock
* @brief Small class to help lock and unlock mutexes.

View File

@ -280,9 +280,9 @@ LLOSInfo::LLOSInfo() :
#elif LL_DARWIN
// Initialize mOSStringSimple to something like:
// "Mac OS X 10.6.7"
// "macOS 10.13.1"
{
const char * DARWIN_PRODUCT_NAME = "Mac OS X";
const char * DARWIN_PRODUCT_NAME = "macOS";
int64_t major_version, minor_version, bugfix_version = 0;
@ -305,7 +305,7 @@ LLOSInfo::LLOSInfo() :
}
// Initialize mOSString to something like:
// "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
// "macOS 10.13.1 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
struct utsname un;
if(uname(&un) != -1)
{

View File

@ -27,38 +27,12 @@
#import "llsys_objc.h"
#import <AppKit/AppKit.h>
static auto intAtStringIndex(NSArray *array, int index)
{
return [(NSString *)[array objectAtIndex:index] integerValue];
}
bool LLGetDarwinOSInfo(int64_t &major, int64_t &minor, int64_t &patch)
{
if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8)
{
NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
major = osVersion.majorVersion;
minor = osVersion.minorVersion;
patch = osVersion.patchVersion;
}
else
{
NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:
@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"];
NSArray* versions = [versionString componentsSeparatedByString:@"."];
NSUInteger count = [versions count];
if (count > 0)
{
major = intAtStringIndex(versions, 0);
if (count > 1)
{
minor = intAtStringIndex(versions, 1);
if (count > 2)
{
patch = intAtStringIndex(versions, 2);
}
}
}
}
return true;
}

View File

@ -512,7 +512,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
}
#elif LL_DARWIN
// Mac OS X version of the UUID generation code...
// macOS version of the UUID generation code...
/*
* Get an ethernet hardware address, if we can find it...
*/

View File

@ -1,6 +1,6 @@
/**
* @file lldir_mac.cpp
* @brief Implementation of directory utilities for Mac OS X
* @brief Implementation of directory utilities for macOS
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -1,6 +1,6 @@
/**
* @file lldir_mac.h
* @brief Definition of directory utilities class for Mac OS X
* @brief Definition of directory utilities class for macOS
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -1,6 +1,6 @@
/**
* @file lldir_utils_objc.h
* @brief Definition of directory utilities class for Mac OS X
* @brief Definition of directory utilities class for macOS
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -1,6 +1,6 @@
/**
* @file lldir_utils_objc.mm
* @brief Cocoa implementation of directory utilities for Mac OS X
* @brief Cocoa implementation of directory utilities for macOS
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -614,7 +614,6 @@ const std::string& LLImage::getLastError()
//static
void LLImage::setLastError(const std::string& message)
{
LLMutexLock m(sMutex);
sLastErrorMessage = message;
}
@ -759,7 +758,7 @@ U8* LLImageBase::reallocateData(S32 size)
return mData;
}
const U8* LLImageBase::getData() const
const U8* LLImageBase::getData() const
{
if(mBadBufferAllocation)
{
@ -770,7 +769,7 @@ const U8* LLImageBase::getData() const
return mData;
} // read only
U8* LLImageBase::getData()
U8* LLImageBase::getData()
{
if(mBadBufferAllocation)
{
@ -783,7 +782,7 @@ U8* LLImageBase::getData()
bool LLImageBase::isBufferInvalid() const
{
return mBadBufferAllocation || mData == NULL ;
return mBadBufferAllocation || mData == NULL;
}
void LLImageBase::setSize(S32 width, S32 height, S32 ncomponents)
@ -873,6 +872,8 @@ LLImageRaw::~LLImageRaw()
// virtual
U8* LLImageRaw::allocateData(S32 size)
{
LLImageDataLock lock(this);
U8* res = LLImageBase::allocateData(size);
return res;
}
@ -880,12 +881,16 @@ U8* LLImageRaw::allocateData(S32 size)
// virtual
U8* LLImageRaw::reallocateData(S32 size)
{
LLImageDataLock lock(this);
U8* res = LLImageBase::reallocateData(size);
return res;
}
void LLImageRaw::releaseData()
{
LLImageDataLock lock(this);
LLImageBase::setSize(0, 0, 0);
LLImageBase::setDataAndSize(nullptr, 0);
}
@ -893,11 +898,15 @@ void LLImageRaw::releaseData()
// virtual
void LLImageRaw::deleteData()
{
LLImageDataLock lock(this);
LLImageBase::deleteData();
}
void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
{
{
LLImageDataLock lock(this);
if(data == getData())
{
return ;
@ -911,6 +920,8 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
bool LLImageRaw::resize(U16 width, U16 height, S8 components)
{
LLImageDataLock lock(this);
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components) && !isBufferInvalid())
{
return true;
@ -926,6 +937,8 @@ bool LLImageRaw::resize(U16 width, U16 height, S8 components)
bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride, bool reverse_y)
{
LLImageDataLock lock(this);
if (!getData())
{
return false;
@ -953,6 +966,9 @@ bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
{
llassert( getComponents() <= 4 );
LLImageDataLock lock(this);
// This is fairly bogus, but it'll do for now.
if (isBufferInvalid())
{
@ -993,6 +1009,8 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
// Reverses the order of the rows in the image
void LLImageRaw::verticalFlip()
{
LLImageDataLock lock(this);
S32 row_bytes = getWidth() * getComponents();
llassert(row_bytes > 0);
std::vector<U8> line_buffer(row_bytes);
@ -1010,6 +1028,8 @@ void LLImageRaw::verticalFlip()
bool LLImageRaw::optimizeAwayAlpha()
{
LLImageDataLock lock(this);
if (getComponents() == 4)
{
U8* data = getData();
@ -1047,6 +1067,8 @@ bool LLImageRaw::optimizeAwayAlpha()
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
LLImageDataLock lock(this);
// Find new sizes
S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim);
@ -1056,6 +1078,8 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, bool scale_image)
{
LLImageDataLock lock(this);
// Find new sizes
S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE);
@ -1105,6 +1129,8 @@ S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim)
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
{
LLImageDataLock lock(this);
// Find new sizes
S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim);
S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim);
@ -1112,6 +1138,7 @@ void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
scale( new_width, new_height );
}
// static
// Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn!
inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
{
@ -1120,10 +1147,13 @@ inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
}
void LLImageRaw::composite( LLImageRaw* src )
void LLImageRaw::composite( const LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(this);
if (!validateSrcAndDst("LLImageRaw::composite", src, dst))
{
return;
@ -1163,12 +1193,14 @@ void LLImageRaw::composite( LLImageRaw* src )
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
void LLImageRaw::compositeScaled4onto3(const LLImageRaw* src)
{
LL_INFOS() << "compositeScaled4onto3" << LL_ENDL;
LLImageRaw* dst = this; // Just for clarity.
LLImageDataLock lock(this);
llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents();
@ -1190,17 +1222,19 @@ void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
// Src and dst are same size. Src has 4 components. Dst has 3 components.
void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
void LLImageRaw::compositeUnscaled4onto3( const LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataLock lock(this);
// <FS:Beq> Correct bad assertion
// llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (4 == src->getComponents()) || (3 == dst->getComponents()) );
// </FS:Beq>
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
U8* src_data = src->getData();
const U8* src_data = src->getData();
U8* dst_data = dst->getData();
S32 pixels = getWidth() * getHeight();
// <FS:Beq> suspicious crash avoid potential causes.
@ -1249,10 +1283,13 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
}
void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
void LLImageRaw::copyUnscaledAlphaMask( const LLImageRaw* src, const LLColor4U& fill)
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(this);
if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst))
{
return;
@ -1263,7 +1300,7 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
S32 pixels = getWidth() * getHeight();
U8* src_data = src->getData();
const U8* src_data = src->getData();
U8* dst_data = dst->getData();
for ( S32 i = 0; i < pixels; i++ )
{
@ -1280,6 +1317,8 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
// Fill the buffer with a constant color
void LLImageRaw::fill( const LLColor4U& color )
{
LLImageDataLock lock(this);
if (isBufferInvalid())
{
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
@ -1317,16 +1356,21 @@ LLPointer<LLImageRaw> LLImageRaw::duplicate()
return this; //nobody else refences to this image, no need to duplicate.
}
LLImageDataSharedLock lock(this);
//make a duplicate
LLPointer<LLImageRaw> dup = new LLImageRaw(getData(), getWidth(), getHeight(), getComponents());
return dup;
}
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
void LLImageRaw::copy(const LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(this);
if (!validateSrcAndDst("LLImageRaw::copy", src, dst))
{
return;
@ -1372,10 +1416,12 @@ void LLImageRaw::copy(LLImageRaw* src)
}
// Src and dst are same size. Src and dst have same number of components.
void LLImageRaw::copyUnscaled(LLImageRaw* src)
void LLImageRaw::copyUnscaled(const LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataLock lock(this);
llassert( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( src->getComponents() == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
@ -1385,7 +1431,7 @@ void LLImageRaw::copyUnscaled(LLImageRaw* src)
// Src and dst can be any size. Src has 3 components. Dst has 4 components.
void LLImageRaw::copyScaled3onto4(LLImageRaw* src)
void LLImageRaw::copyScaled3onto4(const LLImageRaw* src)
{
llassert( (3 == src->getComponents()) && (4 == getComponents()) );
@ -1397,7 +1443,7 @@ void LLImageRaw::copyScaled3onto4(LLImageRaw* src)
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void LLImageRaw::copyScaled4onto3(LLImageRaw* src)
void LLImageRaw::copyScaled4onto3(const LLImageRaw* src)
{
llassert( (4 == src->getComponents()) && (3 == getComponents()) );
@ -1409,15 +1455,17 @@ void LLImageRaw::copyScaled4onto3(LLImageRaw* src)
// Src and dst are same size. Src has 4 components. Dst has 3 components.
void LLImageRaw::copyUnscaled4onto3( LLImageRaw* src )
void LLImageRaw::copyUnscaled4onto3( const LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataLock lock(this);
llassert( (3 == dst->getComponents()) && (4 == src->getComponents()) );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
S32 pixels = getWidth() * getHeight();
U8* src_data = src->getData();
const U8* src_data = src->getData();
U8* dst_data = dst->getData();
for( S32 i=0; i<pixels; i++ )
{
@ -1431,15 +1479,18 @@ void LLImageRaw::copyUnscaled4onto3( LLImageRaw* src )
// Src and dst are same size. Src has 3 components. Dst has 4 components.
void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
void LLImageRaw::copyUnscaled3onto4( const LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataLock lock(this);
llassert( 3 == src->getComponents() );
llassert( 4 == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
S32 pixels = getWidth() * getHeight();
U8* src_data = src->getData();
const U8* src_data = src->getData();
U8* dst_data = dst->getData();
for( S32 i=0; i<pixels; i++ )
{
@ -1454,10 +1505,13 @@ void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
// Src and dst can be any size. Src and dst have same number of components.
void LLImageRaw::copyScaled( LLImageRaw* src )
void LLImageRaw::copyScaled( const LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(this);
if (!validateSrcAndDst("LLImageRaw::copyScaled", src, dst))
{
return;
@ -1499,6 +1553,8 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
LLImageDataLock lock(this);
S32 components = getComponents();
if (components != 1 && components != 3 && components != 4)
{
@ -1585,6 +1641,8 @@ LLPointer<LLImageRaw> LLImageRaw::scaled(S32 new_width, S32 new_height)
{
LLPointer<LLImageRaw> result;
LLImageDataLock lock(this);
S32 components = getComponents();
if (components != 1 && components != 3 && components != 4)
{
@ -1630,7 +1688,7 @@ LLPointer<LLImageRaw> LLImageRaw::scaled(S32 new_width, S32 new_height)
return result;
}
void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
void LLImageRaw::copyLineScaled( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
{
const S32 components = getComponents();
llassert( components >= 1 && components <= 4 );
@ -1657,7 +1715,7 @@ void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixe
S32 t0 = x * out_pixel_step * components;
S32 t1 = index0 * in_pixel_step * components;
U8* outp = out + t0;
U8* inp = in + t1;
const U8* inp = in + t1;
for (S32 i = 0; i < components; ++i)
{
*outp = *inp;
@ -1745,7 +1803,7 @@ void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixe
}
}
void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len )
void LLImageRaw::compositeRowScaled4onto3( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len )
{
llassert( getComponents() == 3 );
@ -1841,8 +1899,12 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
}
}
bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
// static
bool LLImageRaw::validateSrcAndDst(std::string func, const LLImageRaw* src, const LLImageRaw* dst)
{
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(dst);
if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
{
LL_WARNS() << func << ": Source: ";
@ -2155,6 +2217,8 @@ bool LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S3
// virtual
U8* LLImageFormatted::allocateData(S32 size)
{
LLImageDataLock lock(this);
U8* res = LLImageBase::allocateData(size); // calls deleteData()
if(res)
sGlobalFormattedMemory += getDataSize();
@ -2164,6 +2228,8 @@ U8* LLImageFormatted::allocateData(S32 size)
// virtual
U8* LLImageFormatted::reallocateData(S32 size)
{
LLImageDataLock lock(this);
sGlobalFormattedMemory -= getDataSize();
U8* res = LLImageBase::reallocateData(size);
if(res)
@ -2174,6 +2240,12 @@ U8* LLImageFormatted::reallocateData(S32 size)
// virtual
void LLImageFormatted::deleteData()
{
LLImageDataLock lock(this);
if (mDecoding)
{
LL_ERRS() << "LLImageFormatted::deleteData() is called during decoding" << LL_ENDL;
}
sGlobalFormattedMemory -= getDataSize();
LLImageBase::deleteData();
}
@ -2200,6 +2272,8 @@ void LLImageFormatted::sanityCheck()
bool LLImageFormatted::copyData(U8 *data, S32 size)
{
LLImageDataLock lock(this);
if ( data && ((data != getData()) || (size != getDataSize())) )
{
deleteData();
@ -2212,6 +2286,8 @@ bool LLImageFormatted::copyData(U8 *data, S32 size)
// LLImageFormatted becomes the owner of data
void LLImageFormatted::setData(U8 *data, S32 size)
{
LLImageDataLock lock(this);
if (data && data != getData())
{
deleteData();
@ -2225,6 +2301,8 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
{
if (data)
{
LLImageDataLock lock(this);
if (!getData())
{
setData(data, size);
@ -2271,6 +2349,9 @@ bool LLImageFormatted::load(const std::string &filename, int load_size)
{
load_size = file_size;
}
LLImageDataLock lock(this);
bool res;
U8 *data = allocateData(load_size);
if (data)
@ -2308,8 +2389,10 @@ bool LLImageFormatted::save(const std::string &filename)
setLastError("Unable to open file for writing", filename);
return false;
}
outfile.write(getData(), getDataSize());
LLImageDataSharedLock lock(this);
outfile.write(getData(), getDataSize());
outfile.close() ;
return true;
}

View File

@ -116,7 +116,11 @@ class LLImageBase
{
protected:
virtual ~LLImageBase();
virtual void deleteData();
virtual U8* allocateData(S32 size = -1);
virtual U8* reallocateData(S32 size = -1);
public:
LLImageBase();
@ -126,10 +130,6 @@ public:
TYPE_AVATAR_BAKE = 1,
};
virtual void deleteData();
virtual U8* allocateData(S32 size = -1);
virtual U8* reallocateData(S32 size = -1);
virtual void dump();
virtual void sanityCheck();
@ -171,8 +171,22 @@ private:
S8 mComponents;
bool mBadBufferAllocation ;
bool mAllowOverSize ;
bool mBadBufferAllocation;
bool mAllowOverSize;
private:
mutable LLSharedMutex mDataMutex;
public:
template<bool SHARED>
class DataLock : LLSharedMutexLockTemplate<SHARED>
{
public:
DataLock(const LLImageBase* image)
: LLSharedMutexLockTemplate<SHARED>(image ? &image->mDataMutex : nullptr)
{
}
};
public:
// <FS:ND> Report amount of failed buffer allocations
static void addAllocationError();
@ -182,6 +196,9 @@ private:
// </FS:ND>
};
using LLImageDataLock = LLImageBase::DataLock<false>;
using LLImageDataSharedLock = LLImageBase::DataLock<true>;
// Raw representation of an image (used for textures, and other uncompressed formats
class LLImageRaw : public LLImageBase
{
@ -238,51 +255,51 @@ public:
LLPointer<LLImageRaw> duplicate();
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void copy( LLImageRaw* src );
void copy( const LLImageRaw* src );
// Src and dst are same size. Src and dst have same number of components.
void copyUnscaled( LLImageRaw* src );
void copyUnscaled( const LLImageRaw* src );
// Src and dst are same size. Src has 4 components. Dst has 3 components.
void copyUnscaled4onto3( LLImageRaw* src );
void copyUnscaled4onto3( const LLImageRaw* src );
// Src and dst are same size. Src has 3 components. Dst has 4 components.
void copyUnscaled3onto4( LLImageRaw* src );
void copyUnscaled3onto4( const LLImageRaw* src );
// Src and dst are same size. Src has 1 component. Dst has 4 components.
// Alpha component is set to source alpha mask component.
// RGB components are set to fill color.
void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill);
void copyUnscaledAlphaMask( const LLImageRaw* src, const LLColor4U& fill);
// Src and dst can be any size. Src and dst have same number of components.
void copyScaled( LLImageRaw* src );
// Src and dst can be any size. Src has 3 components. Dst has 4 components.
void copyScaled3onto4( LLImageRaw* src );
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void copyScaled4onto3( LLImageRaw* src );
void copyScaled( const LLImageRaw* src );
// Composite operations
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void composite( LLImageRaw* src );
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void compositeScaled4onto3( LLImageRaw* src );
// Src and dst are same size. Src has 4 components. Dst has 3 components.
void compositeUnscaled4onto3( LLImageRaw* src );
void composite( const LLImageRaw* src );
protected:
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void compositeScaled4onto3( const LLImageRaw* src );
// Src and dst are same size. Src has 4 components. Dst has 3 components.
void compositeUnscaled4onto3( const LLImageRaw* src );
// Src and dst can be any size. Src has 3 components. Dst has 4 components.
void copyScaled3onto4( const LLImageRaw* src );
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void copyScaled4onto3( const LLImageRaw* src );
// Create an image from a local file (generally used in tools)
//bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false);
void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );
void copyLineScaled( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
void compositeRowScaled4onto3( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );
U8 fastFractionalMult(U8 a,U8 b);
static U8 fastFractionalMult(U8 a, U8 b);
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
@ -293,7 +310,7 @@ public:
// </FS:Techwolf Lupindo>
private:
bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst);
static bool validateSrcAndDst(std::string func, const LLImageRaw* src, const LLImageRaw* dst);
};
// Compressed representation of image.
@ -366,7 +383,7 @@ protected:
S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC
S8 mDiscardLevel; // Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc...
S8 mLevels; // Number of resolution levels in that image. Min is 1. 0 means unknown.
public:
static S32 sGlobalFormattedMemory;
};

View File

@ -96,6 +96,8 @@ bool LLImageBMP::updateData()
{
resetLastError();
LLImageDataLock lock(this);
// Check to make sure that this instance has been initialized with data
U8* mdata = getData();
if (!mdata || (0 == getDataSize()))
@ -336,8 +338,11 @@ bool LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
resetLastError();
LLImageDataLock lockIn(this);
LLImageDataLock lockOut(raw_image);
// Check to make sure that this instance has been initialized with data
U8* mdata = getData();
const U8* mdata = getData();
if (!mdata || (0 == getDataSize()))
{
setLastError("llimagebmp trying to decode an image with no data!");
@ -350,7 +355,7 @@ bool LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
return false;
}
U8* src = mdata + mBitmapOffset;
const U8* src = mdata + mBitmapOffset;
U8* dst = raw_image->getData();
bool success = false;
@ -397,7 +402,7 @@ U32 LLImageBMP::countTrailingZeros( U32 m )
}
bool LLImageBMP::decodeColorMask16( U8* dst, U8* src )
bool LLImageBMP::decodeColorMask16( U8* dst, const U8* src )
{
llassert( 16 == mBitsPerPixel );
@ -433,7 +438,7 @@ bool LLImageBMP::decodeColorMask16( U8* dst, U8* src )
return true;
}
bool LLImageBMP::decodeColorMask32( U8* dst, U8* src )
bool LLImageBMP::decodeColorMask32( U8* dst, const U8* src )
{
// Note: alpha is not supported
@ -477,7 +482,7 @@ bool LLImageBMP::decodeColorMask32( U8* dst, U8* src )
}
bool LLImageBMP::decodeColorTable8( U8* dst, U8* src )
bool LLImageBMP::decodeColorTable8( U8* dst, const U8* src )
{
llassert( (8 == mBitsPerPixel) && (mColorPaletteColors >= 256) );
@ -507,7 +512,7 @@ bool LLImageBMP::decodeColorTable8( U8* dst, U8* src )
}
bool LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
bool LLImageBMP::decodeTruecolor24( U8* dst, const U8* src )
{
llassert( 24 == mBitsPerPixel );
llassert( 3 == getComponents() );
@ -541,6 +546,9 @@ bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
resetLastError();
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
S32 src_components = raw_image->getComponents();
S32 dst_components = ( src_components < 3 ) ? 1 : 3;

View File

@ -45,10 +45,10 @@ public:
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
protected:
bool decodeColorTable8( U8* dst, U8* src );
bool decodeColorMask16( U8* dst, U8* src );
bool decodeTruecolor24( U8* dst, U8* src );
bool decodeColorMask32( U8* dst, U8* src );
bool decodeColorTable8( U8* dst, const U8* src );
bool decodeColorMask16( U8* dst, const U8* src );
bool decodeTruecolor24( U8* dst, const U8* src );
bool decodeColorMask32( U8* dst, const U8* src );
U32 countTrailingZeros( U32 m );

View File

@ -176,6 +176,8 @@ bool LLImageDXT::updateData()
{
resetLastError();
LLImageDataLock lock(this);
U8* data = getData();
S32 data_size = getDataSize();
@ -268,7 +270,10 @@ bool LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
LL_WARNS() << "Attempt to decode compressed LLImageDXT to Raw (unsupported)" << LL_ENDL;
return false;
}
LLImageDataSharedLock lockIn(this);
LLImageDataLock lockOut(raw_image);
S32 width = getWidth(), height = getHeight();
S32 ncomponents = getComponents();
U8* data = NULL;
@ -309,6 +314,9 @@ bool LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
{
LL_ERRS() << "Request for invalid discard level" << LL_ENDL;
}
LLImageDataSharedLock lock(this);
U8* data = getData() + getMipOffset(discard);
S32 width = 0;
S32 height = 0;
@ -339,6 +347,8 @@ bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
return 0;
}
LLImageDataLock lock(this);
S32 width = raw_image->getWidth();
S32 height = raw_image->getHeight();
@ -430,6 +440,9 @@ bool LLImageDXT::convertToDXR()
return false;
}
mFileFormat = newformat;
LLImageDataLock lock(this);
S32 width = getWidth(), height = getHeight();
S32 nmips = calcNumMips(width,height);
S32 total_bytes = getDataSize();

View File

@ -87,7 +87,9 @@ LLImageFilter::~LLImageFilter()
void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
{
mImage = raw_image;
LLImageDataLock lock(mImage);
//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
for (S32 i = 0; i < mFilterData.size(); ++i)
{

View File

@ -107,6 +107,8 @@ bool LLImageJ2C::updateData()
bool res = true;
resetLastError();
LLImageDataLock lock(this);
// Check to make sure that this instance has been initialized with data
if (!getData() || (getDataSize() < 16))
{
@ -157,36 +159,48 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTimer elapsed;
bool res = true;
resetLastError();
// Check to make sure that this instance has been initialized with data
if (!getData() || (getDataSize() < 16))
bool res;
{
setLastError("LLImageJ2C uninitialized");
res = true; // done
}
else
{
// Update the raw discard level
updateRawDiscardLevel();
LLImageDataLock lock(this);
mDecoding = true;
res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
// Check to make sure that this instance has been initialized with data
if (!getData() || (getDataSize() < 16))
{
setLastError("LLImageJ2C uninitialized");
res = true; // done
}
else
{
// Update the raw discard level
updateRawDiscardLevel();
res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
}
}
if (res)
{
if (!mDecoding)
{
// Failed
raw_imagep->deleteData();
res = false;
}
else
{
mDecoding = false;
}
}
else
{
if (mDecoding)
{
LL_WARNS() << "decodeImpl failed but mDecoding is TRUE" << LL_ENDL;
mDecoding = false;
}
}
if (!mLastError.empty())
{
@ -411,9 +425,10 @@ bool LLImageJ2C::loadAndValidate(const std::string &filename)
bool LLImageJ2C::validate(U8 *data, U32 file_size)
{
resetLastError();
LLImageDataLock lock(this);
setData(data, file_size);
bool res = updateData();

View File

@ -50,6 +50,8 @@ bool LLImageJPEG::updateData()
{
resetLastError();
LLImageDataLock lock(this);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -188,7 +190,10 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
llassert_always(raw_image);
resetLastError();
LLImageDataLock lockIn(this);
LLImageDataLock lockOut(raw_image);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -408,6 +413,8 @@ void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
{
LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
LLImageDataLock lock(self);
S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
if(self->allocateData(file_bytes))
memcpy( self->getData(), self->mOutputBuffer, file_bytes ); /* Flawfinder: ignore */
@ -485,6 +492,9 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
resetLastError();
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
switch( raw_image->getComponents() )
{
case 1:

View File

@ -73,8 +73,6 @@ public:
static void errorEmitMessage(j_common_ptr cinfo, int msg_level);
static void errorOutputMessage(j_common_ptr cinfo);
static bool decompress(LLImageJPEG* imagep);
protected:
U8* mOutputBuffer; // temp buffer used during encoding
S32 mOutputBufferSize; // bytes in mOuputBuffer

View File

@ -51,6 +51,8 @@ bool LLImagePNG::updateData()
{
resetLastError();
LLImageDataLock lock(this);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -87,6 +89,9 @@ bool LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
resetLastError();
LLImageDataSharedLock lockIn(this);
LLImageDataLock lockOut(raw_image);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -119,6 +124,9 @@ bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
resetLastError();
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
// Image logical size
setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());

View File

@ -108,6 +108,8 @@ bool LLImageTGA::updateData()
{
resetLastError();
LLImageDataLock lock(this);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -326,7 +328,10 @@ bool LLImageTGA::updateData()
bool LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
LLImageDataSharedLock lockIn(this);
LLImageDataLock lockOut(raw_image);
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@ -657,7 +662,10 @@ bool LLImageTGA::decodeColorMap( LLImageRaw* raw_image, bool rle, bool flipped )
bool LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
{
llassert_always(raw_image);
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
deleteData();
setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
@ -1076,6 +1084,9 @@ bool LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
// --+---Input--------------------------------
// |
LLImageDataSharedLock lockIn(this);
LLImageDataLock lockOut(raw_image);
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageTGA trying to decode an image with no data!");

View File

@ -149,9 +149,18 @@ ImageRequest::~ImageRequest()
bool ImageRequest::processRequest()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mFormattedImage.isNull())
return true;
const F32 decode_time_slice = 0.f; //disable time slicing
bool done = true;
if (!mDecodedRaw && mFormattedImage.notNull())
LLImageDataLock lockFormatted(mFormattedImage);
LLImageDataLock lockDecodedRaw(mDecodedImageRaw);
LLImageDataLock lockDecodedAux(mDecodedImageAux);
if (!mDecodedRaw)
{
// Decode primary channels
if (mDecodedImageRaw.isNull())
@ -189,7 +198,7 @@ bool ImageRequest::processRequest()
// some decoders are removing data when task is complete and there were errors
mDecodedRaw = done && mDecodedImageRaw->getData();
}
if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull())
if (done && mNeedsAux && !mDecodedAux)
{
// Decode aux channel
if (!mDecodedImageAux)

View File

@ -173,6 +173,8 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
// data space
if (rawImage != NULL)
{
LLImageDataLock lock(rawImage);
if (!rawImage->resize(static_cast<U16>(mWidth),
static_cast<U16>(mHeight), mChannels))
{

View File

@ -492,6 +492,9 @@ public:
bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut)
{
LLImageDataSharedLock lockIn(&rawImageIn);
LLImageDataLock lockOut(&compressedImageOut);
setImage(rawImageIn);
encoder = opj_create_compress(OPJ_CODEC_J2K);
@ -735,6 +738,9 @@ bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int block
bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
LLImageDataLock lockIn(&base);
LLImageDataLock lockOut(&raw_image);
JPEG2KDecode decoder(0);
// <FS:Techwolf Lupindo> texture comment metadata reader
@ -878,6 +884,8 @@ bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
{
LLImageDataLock lock(&base);
JPEG2KDecode decode(0);
S32 width = 0;

View File

@ -288,6 +288,8 @@ void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // <FS:Beq> instrument image decodes
LLImageDataLock lock(&base);
S32 data_size = base.getDataSize();
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
@ -528,8 +530,13 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageDataLock lockIn(&base);
LLImageDataLock lockOut(&raw_image);
ECodeStreamMode mode = MODE_FAST;
bool limit_time = decode_time > 0.0f;
LLTimer decode_timer;
if (!mCodeStreamp->exists())
@ -553,7 +560,7 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// These can probably be grabbed from what's saved in the class.
kdu_dims dims;
mCodeStreamp->get_dims(0,dims);
mCodeStreamp->get_dims(0, dims);
// Now we are ready to walk through the tiles processing them one-by-one.
kdu_byte *buffer = raw_image.getData();
@ -603,16 +610,18 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
mCodeStreamp.get()));
}
// Do the actual processing
F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32();
F32 remaining_time = limit_time ? decode_time - decode_timer.getElapsedTimeF32().value() : 0.0f;
// This is where we do the actual decode. If we run out of time, return false.
if (mDecodeState->processTileDecode(remaining_time, (decode_time > 0.0f)))
if (mDecodeState->processTileDecode(remaining_time, limit_time))
{
mDecodeState.reset();
}
else
{
// Not finished decoding yet.
// setLastError("Ran out of time while decoding");
base.setLastError("Ran out of time while decoding");
base.decodeFailed();
cleanupCodeStream();
return false;
}
}

View File

@ -310,12 +310,15 @@ void LLMessageSystem::loadTemplateFile(const std::string& filename, bool failure
LLTemplateTokenizer tokens(template_body);
LLTemplateParser parsed(tokens);
mMessageFileVersionNumber = parsed.getVersion();
S32 count = 0;
for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
iter != parsed.getMessagesEnd();
iter++)
{
addTemplate(*iter);
count++;
}
LL_INFOS("Messaging") << "Read " << count << " messages from " << filename << LL_ENDL;
}

View File

@ -77,7 +77,7 @@ const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
const char* BROADCAST_ADDRESS_STRING = "255.255.255.255";
#if LL_DARWIN
// Mac OS X returns an error when trying to set these to 400000. Smaller values succeed.
// 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

View File

@ -47,16 +47,49 @@ const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rota
// special UUID that indicates a null UUID in override data
const LLUUID LLGLTFMaterial::GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
LLGLTFMaterial::LLGLTFMaterial()
{
// IMPORTANT: since we use the hash of the member variables memory block of
// this class to detect changes, we must ensure that all its padding bytes
// have been zeroed out. But of course, we must leave the LLRefCount member
// variable untouched (and skip it when hashing), and we cannot either
// touch the local texture overrides map (else we destroy pointers, and
// sundry private data, which would lead to a crash when using that map).
// The variable members have therefore been arranged so that anything,
// starting at mLocalTexDataDigest and up to the end of the members, can be
// safely zeroed. HB
const size_t offset = intptr_t(&mLocalTexDataDigest) - intptr_t(this);
memset((void*)((const char*)this + offset), 0, sizeof(*this) - offset);
// Now that we zeroed out our member variables, we can set the ones that
// should not be zero to their default value. HB
mBaseColor.set(1.f, 1.f, 1.f, 1.f);
mMetallicFactor = mRoughnessFactor = 1.f;
mAlphaCutoff = 0.5f;
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
mTextureTransform[i].mScale.set(1.f, 1.f);
#if 0
mTextureTransform[i].mOffset.clear();
mTextureTransform[i].mRotation = 0.f;
#endif
}
#if 0
mLocalTexDataDigest = 0;
mAlphaMode = ALPHA_MODE_OPAQUE; // This is 0
mOverrideDoubleSided = mOverrideAlphaMode = false;
#endif
}
void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const
{
packed[0] = mScale.mV[VX];
packed[1] = mScale.mV[VY];
packed[2] = mRotation;
// packed[3] = unused
packed[4] = mOffset.mV[VX];
packed[5] = mOffset.mV[VY];
// packed[6] = unused
// packed[7] = unused
// Not used but nonetheless zeroed for proper hashing. HB
packed[3] = packed[6] = packed[7] = 0.f;
}
bool LLGLTFMaterial::TextureTransform::operator==(const TextureTransform& other) const
@ -89,13 +122,37 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
mOverrideDoubleSided = rhs.mOverrideDoubleSided;
mOverrideAlphaMode = rhs.mOverrideAlphaMode;
mTrackingIdToLocalTexture = rhs.mTrackingIdToLocalTexture;
updateTextureTracking();
if (rhs.mTrackingIdToLocalTexture.empty())
{
mTrackingIdToLocalTexture.clear();
mLocalTexDataDigest = 0;
}
else
{
mTrackingIdToLocalTexture = rhs.mTrackingIdToLocalTexture;
updateLocalTexDataDigest();
updateTextureTracking();
}
return *this;
}
void LLGLTFMaterial::updateLocalTexDataDigest()
{
mLocalTexDataDigest = 0;
if (!mTrackingIdToLocalTexture.empty())
{
for (local_tex_map_t::const_iterator
it = mTrackingIdToLocalTexture.begin(),
end = mTrackingIdToLocalTexture.end();
it != end; ++it)
{
mLocalTexDataDigest ^= it->first.getDigest64() ^
it->second.getDigest64();
}
}
}
bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
{
return mTextureId == rhs.mTextureId &&
@ -547,7 +604,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
{
LL_PROFILE_ZONE_SCOPED;
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
LLUUID& texture_id = mTextureId[i];
const LLUUID& override_texture_id = override_mat.mTextureId[i];
@ -588,7 +645,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
mDoubleSided = override_mat.mDoubleSided;
}
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset())
{
@ -606,9 +663,13 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
}
}
mTrackingIdToLocalTexture.insert(override_mat.mTrackingIdToLocalTexture.begin(), override_mat.mTrackingIdToLocalTexture.begin());
updateTextureTracking();
if (!override_mat.mTrackingIdToLocalTexture.empty())
{
auto it = override_mat.mTrackingIdToLocalTexture.begin();
mTrackingIdToLocalTexture.insert(it, it);
updateLocalTexDataDigest();
updateTextureTracking();
}
}
void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data)
@ -618,7 +679,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
// make every effort to shave bytes here
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
LLUUID& texture_id = mTextureId[i];
const LLUUID& override_texture_id = override_mat.mTextureId[i];
@ -663,7 +724,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
data["ds"] = override_mat.mDoubleSided;
}
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset())
{
@ -767,7 +828,7 @@ void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data)
const LLSD& ti = data["ti"];
if (ti.isArray())
{
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
const LLSD& o = ti[i]["o"];
if (o.isDefined())
@ -793,27 +854,36 @@ void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data)
LLUUID LLGLTFMaterial::getHash() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
// HACK - hash the bytes of this object but don't include the ref count
LLUUID hash;
HBXXH128::digest(hash, (unsigned char*)this + sizeof(LLRefCount), sizeof(*this) - sizeof(LLRefCount));
return hash;
// *HACK: hash the bytes of this object but do not include the ref count
// neither the local texture overrides (which is a map, with pointers to
// key/value pairs that would change from one LLGLTFMaterial instance to
// the other, even though the key/value pairs could be the same, and stored
// elsewhere in the memory heap or on the stack).
// Note: this does work properly to compare two LLGLTFMaterial instances
// only because the padding bytes between their member variables have been
// dutifully zeroed in the constructor. HB
const size_t offset = intptr_t(&mLocalTexDataDigest) - intptr_t(this);
return HBXXH128::digest((const void*)((const char*)this + offset),
sizeof(*this) - offset);
}
void LLGLTFMaterial::addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id)
{
mTrackingIdToLocalTexture[tracking_id] = tex_id;
updateLocalTexDataDigest();
}
void LLGLTFMaterial::removeLocalTextureTracking(const LLUUID& tracking_id)
{
mTrackingIdToLocalTexture.erase(tracking_id);
updateLocalTexDataDigest();
}
bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id)
{
bool res = false;
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (mTextureId[i] == old_id)
{
@ -834,6 +904,7 @@ bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID
{
mTrackingIdToLocalTexture.erase(tracking_id);
}
updateLocalTexDataDigest();
return res;
}

View File

@ -81,7 +81,7 @@ public:
ALPHA_MODE_MASK
};
LLGLTFMaterial() {}
LLGLTFMaterial();
LLGLTFMaterial(const LLGLTFMaterial& rhs);
LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs);
@ -110,25 +110,6 @@ public:
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION;
static const LLUUID GLTF_OVERRIDE_NULL_UUID;
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
// NOTE: initialize values to defaults according to the GLTF spec
// NOTE: these values should be in linear color space
LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
F32 mMetallicFactor = 1.f;
F32 mRoughnessFactor = 1.f;
F32 mAlphaCutoff = 0.5f;
bool mDoubleSided = false;
AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
// override specific flags for state that can't use off-by-epsilon or UUID hack
bool mOverrideDoubleSided = false;
bool mOverrideAlphaMode = false;
// get a UUID based on a hash of this LLGLTFMaterial
LLUUID getHash() const;
@ -229,10 +210,6 @@ public:
virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id);
virtual void updateTextureTracking();
// These fields are local to viewer and are a part of local bitmap support
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;
protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
@ -249,4 +226,41 @@ protected:
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
template<typename T>
static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false);
// Used to update the digest of the mTrackingIdToLocalTexture map each time
// it is changed; this way, that digest can be used by the fast getHash()
// method intsead of having to hash all individual keys and values. HB
void updateLocalTexDataDigest();
public:
// These fields are local to viewer and are a part of local bitmap support
// IMPORTANT: do not move this member down (and do not move
// mLocalTexDataDigest either): the getHash() method does rely on the
// current ordering. HB
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;
// Used to store a digest of mTrackingIdToLocalTexture when the latter is
// not empty, or zero otherwise. HB
U64 mLocalTexDataDigest;
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
// NOTE: initialize values to defaults according to the GLTF spec
// NOTE: these values should be in linear color space
LLColor4 mBaseColor;
LLColor3 mEmissiveColor;
F32 mMetallicFactor;
F32 mRoughnessFactor;
F32 mAlphaCutoff;
AlphaMode mAlphaMode;
bool mDoubleSided;
// Override specific flags for state that can't use off-by-epsilon or UUID
// hack
bool mOverrideDoubleSided;
bool mOverrideAlphaMode;
};

View File

@ -111,6 +111,9 @@ void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages
// Yes, I know that this is inefficient! - djs 08/08/02
for (int i = 0; i < 6; i++)
{
LLImageDataSharedLock lockIn(rawimages[i]);
LLImageDataLock lockOut(mRawImages[i]);
const U8 *sd = rawimages[i]->getData();
U8 *td = mRawImages[i]->getData();

View File

@ -772,6 +772,7 @@ U8 LLFontFreetype::getStyle() const
void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
{
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
LLImageDataLock lock(image_raw);
llassert(!mIsFallback);
llassert(image_raw && (image_raw->getComponents() == 2));

View File

@ -1214,7 +1214,7 @@ LLFontGL* LLFontGL::getFontDefault()
std::string LLFontGL::getFontPathSystem()
{
#if LL_DARWIN
// HACK for Mac OS X
// HACK for macOS
return "/System/Library/Fonts/";
#elif LL_WINDOWS

View File

@ -56,7 +56,7 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
U32 wpo2(U32 i);
// texture memory accounting (for OS X)
// texture memory accounting (for macOS)
static LLMutex sTexMemMutex;
static std::unordered_map<U32, U64> sTextureAllocs;
static U64 sTextureBytes = 0;
@ -1887,6 +1887,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
}
//-----------------------------------------------------------------------------------------------
LLImageDataLock lock(imageraw);
if (is_compressed)
{
LLGLint glbytes;

View File

@ -51,14 +51,6 @@ char LLResMgr::getDecimalPoint() const
{
char decimal = localeconv()->decimal_point[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
if(decimal == 0)
{
decimal = '.';
}
#endif
return decimal;
}
@ -66,14 +58,6 @@ char LLResMgr::getThousandsSeparator() const
{
char separator = localeconv()->thousands_sep[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
if(separator == 0)
{
separator = ',';
}
#endif
return separator;
}
@ -81,14 +65,6 @@ char LLResMgr::getMonetaryDecimalPoint() const
{
char decimal = localeconv()->mon_decimal_point[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
if(decimal == 0)
{
decimal = '.';
}
#endif
return decimal;
}
@ -96,14 +72,6 @@ char LLResMgr::getMonetaryThousandsSeparator() const
{
char separator = localeconv()->mon_thousands_sep[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
if(separator == 0)
{
separator = ',';
}
#endif
return separator;
}
@ -115,29 +83,6 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
LLLocale locale(LLLocale::USER_LOCALE);
struct lconv *conv = localeconv();
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
// Fake up a conv structure with some reasonable values for the fields this function uses.
struct lconv fakeconv;
char fake_neg[2] = "-";
char fake_mon_group[4] = "\x03\x03\x00"; // commas every 3 digits
if(conv->negative_sign[0] == 0) // Real locales all seem to have something here...
{
fakeconv = *conv; // start with what's there.
switch(mLocale)
{
default: // Unknown -- use the US defaults.
case LLLOCALE_USA:
case LLLOCALE_UK: // UK ends up being the same as US for the items used here.
fakeconv.negative_sign = fake_neg;
fakeconv.mon_grouping = fake_mon_group;
fakeconv.n_sign_posn = 1; // negative sign before the string
break;
}
conv = &fakeconv;
}
#endif
char* negative_sign = conv->negative_sign;
char separator = getMonetaryThousandsSeparator();

View File

@ -154,24 +154,24 @@ protected:
// We shouldn't ever need to set this directly
//virtual void setViewModel(const LLViewModelPtr&);
virtual BOOL postBuild();
/*virtual*/ BOOL postBuild() override;
public:
// LLView interface
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
/*virtual*/ BOOL isCtrl() const;
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL canFocusChildren() const;
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) override;
/*virtual*/ BOOL isCtrl() const override;
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask) override;
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL canFocusChildren() const override;
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ BOOL hasFocus() const;
/*virtual*/ void setFocus( BOOL b ) override;
/*virtual*/ BOOL hasFocus() const override;
// New virtuals
@ -334,7 +334,7 @@ protected:
static F32 sActiveControlTransparency;
static F32 sInactiveControlTransparency;
virtual void addInfo(LLSD & info);
/*virtual*/ void addInfo(LLSD & info) override;
private:

View File

@ -92,7 +92,7 @@ public:
// </FS:ND>
#ifdef LL_DARWIN
// We only actually use this for OS X.
// We only actually use this for macOS.
virtual void handleModifier(MASK mask) = 0;
#endif // LL_DARWIN

View File

@ -1259,7 +1259,7 @@ F32 LLWindowMacOSX::getNativeAspectRatio()
F32 LLWindowMacOSX::getPixelAspectRatio()
{
//OS X always enforces a 1:1 pixel aspect ratio, regardless of video mode
//macOS always enforces a 1:1 pixel aspect ratio, regardless of video mode
return 1.f;
}
@ -1291,7 +1291,7 @@ void LLWindowMacOSX::afterDialog()
void LLWindowMacOSX::flashIcon(F32 seconds)
{
// For consistency with OS X conventions, the number of seconds given is ignored and
// For consistency with macOS conventions, the number of seconds given is ignored and
// left up to the OS (which will actually bounce it for one second).
requestUserAttention();
}

View File

@ -1,6 +1,6 @@
/**
* @file mac_volume_catcher.cpp
* @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process.
* @brief A macOS specific hack to control the volume level of all audio channels opened by a process.
*
* @cond
* $LicenseInfo:firstyear=2010&license=viewerlgpl$

View File

@ -827,7 +827,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
S32 y = message_in.getValueS32("y");
// only even send left mouse button events to the CEF library
// (partially prompted by crash in OS X CEF when sending right button events)
// (partially prompted by crash in macOS CEF when sending right button events)
// we catch the right click in viewer and display our own context menu anyway
S32 button = message_in.getValueS32("button");
dullahan::EMouseButton btn = dullahan::MB_MOUSE_BUTTON_LEFT;

View File

@ -11959,7 +11959,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>RenderHiDPI</key>
<map>
<key>Comment</key>
<string>Enable support for HiDPI displays, like Retina (MacOS X ONLY, requires restart)</string>
<string>Enable support for HiDPI displays, like Retina (macOS ONLY, requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>

View File

@ -121,9 +121,9 @@ void FSPanelPrefs::apply()
}
}
void FSPanelPrefs::cancel()
void FSPanelPrefs::cancel(const std::vector<std::string> settings_to_skip)
{
LLPanelPreference::cancel();
LLPanelPreference::cancel(settings_to_skip);
}
void FSPanelPrefs::refreshBeamLists()

View File

@ -40,7 +40,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void apply();
/*virtual*/ void cancel();
/*virtual*/ void cancel(const std::vector<std::string> settings_to_skip = {});
void refreshBeamLists();

View File

@ -1679,8 +1679,9 @@ void LLAgent::pitch(F32 angle)
// after left-clicking the mouse on the avatar and dragging down
//
// The issue is observed on angle below 10 degrees
bool isMouseLookOn = mControlFlags & AGENT_CONTROL_MOUSELOOK;
const F32 look_down_limit = 179.f * DEG_TO_RAD;
const F32 look_up_limit = 10.f * DEG_TO_RAD;
const F32 look_up_limit = (isMouseLookOn ? 1.f : 10.f) * DEG_TO_RAD;
F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);

View File

@ -2740,6 +2740,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
// Set the log file to SecondLife.log
LLError::logToFile(log_file);
LL_INFOS() << "Started logging to " << log_file << LL_ENDL;
if (!duration_log_msg.empty())
{
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;

View File

@ -25,7 +25,7 @@
*/
#if !defined LL_DARWIN
#error "Use only with Mac OS X"
#error "Use only with macOS"
#endif
#import <Cocoa/Cocoa.h>

View File

@ -27,7 +27,7 @@
#include "llviewerprecompiledheaders.h"
#if !defined LL_DARWIN
#error "Use only with Mac OS X"
#error "Use only with macOS"
#endif
#define LL_CARBON_CRASH_HANDLER 1

View File

@ -852,11 +852,14 @@ void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTextu
void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image)
{
LLImageDataSharedLock lockIn(src);
LLImageDataLock lockOut(nrm_image);
U8* nrm_data = nrm_image->getData();
S32 resX = src->getWidth();
S32 resY = src->getHeight();
U8* src_data = src->getData();
const U8* src_data = src->getData();
S32 src_cmp = src->getComponents();
@ -918,6 +921,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLImageDataSharedLock lock(src);
bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
@ -940,7 +944,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
U8* dst_data = dst_image->getData();
S32 dst_data_size = dst_image->getDataSize();
U8* src_data = src->getData();
const U8* src_data = src->getData();
S32 src_data_size = src->getDataSize();
S32 src_components = src->getComponents();

View File

@ -472,6 +472,8 @@ void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch
// disable use of glReadPixels which messes up nVidia nSight graphics debugging
if (!LLRender::sNsightDebugSupport)
{
LLImageDataSharedLock lock(scratch);
//read result back into raw image
glReadPixels(0, 0, 1024, 512, GL_RGB, GL_UNSIGNED_BYTE, scratch->getData());

View File

@ -97,7 +97,7 @@ public:
}
void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
const LLUUID& getLandmarkId() const { return mLandmarkID; }
const LLUUID& getLandmarkID() const { return mLandmarkID; }
const std::string& getName()
{
@ -299,7 +299,7 @@ public:
}
void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
const LLUUID& getLandmarkId() const { return mLandmarkInfoGetter.getLandmarkId(); }
const LLUUID& getLandmarkID() const { return mLandmarkInfoGetter.getLandmarkID(); }
void onMouseEnter(S32 x, S32 y, MASK mask)
{
@ -363,7 +363,8 @@ public:
return TRUE;
}
void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
const LLUUID& getLandmarkID() const { return mLandmarkInfoGetter.getLandmarkID(); }
void setLandmarkID(const LLUUID& id) { mLandmarkInfoGetter.setLandmarkID(id); }
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
{
@ -411,15 +412,44 @@ private:
class LLFavoriteLandmarkToggleableMenu : public LLToggleableMenu
{
public:
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
*accept = ACCEPT_NO;
return TRUE;
}
// virtual
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type,
void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override
{
mToolbar->handleDragAndDropToMenu(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
return TRUE;
}
// virtual
BOOL handleHover(S32 x, S32 y, MASK mask) override
{
mIsHovering = true;
LLToggleableMenu::handleHover(x, y, mask);
mIsHovering = false;
return TRUE;
}
// virtual
void setVisible(BOOL visible) override
{
// Avoid of hiding the menu during hovering
if (visible || !mIsHovering)
{
LLToggleableMenu::setVisible(visible);
}
}
void setToolbar(LLFavoritesBarCtrl* toolbar)
{
mToolbar = toolbar;
}
~LLFavoriteLandmarkToggleableMenu()
{
// Enable subsequent setVisible(FALSE)
mIsHovering = false;
setVisible(FALSE);
}
protected:
LLFavoriteLandmarkToggleableMenu(const LLToggleableMenu::Params& p):
@ -427,6 +457,10 @@ protected:
{
}
private:
LLFavoritesBarCtrl* mToolbar { nullptr };
bool mIsHovering { false };
friend class LLUICtrlFactory;
};
@ -507,12 +541,12 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mOverflowMenuHandle(),
mContextMenuHandle(),
mImageDragIndication(p.image_drag_indication),
mShowDragMarker(FALSE),
mShowDragMarker(false),
mLandingTab(NULL),
mLastTab(NULL),
mTabsHighlightEnabled(TRUE),
mUpdateDropDownItems(true),
mRestoreOverflowMenu(false),
mDragToOverflowMenu(false),
mGetPrevItems(true),
mMouseX(0),
mMouseY(0),
@ -563,17 +597,16 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
LLFavoritesBarCtrl::~LLFavoritesBarCtrl()
{
gInventory.removeObserver(this);
gInventory.removeObserver(this);
if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die();
if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
if (mOverflowMenuHandle.get())
mOverflowMenuHandle.get()->die();
if (mContextMenuHandle.get())
mContextMenuHandle.get()->die();
}
BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
{
*accept = ACCEPT_NO;
@ -599,26 +632,52 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// Copy the item into the favorites folder (if it's not already there).
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
if (LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)))
if (mDragToOverflowMenu)
{
setLandingTab(dest);
LLView* overflow_menu = mOverflowMenuHandle.get();
if (overflow_menu && !overflow_menu->isDead() && overflow_menu->getVisible())
{
overflow_menu->handleHover(x, y, mask);
}
}
else if (mLastTab && (x >= mLastTab->getRect().mRight))
else // Drag to the toolbar itself
{
/*
* the condition dest == NULL can be satisfied not only in the case
* of dragging to the right from the last tab of the favbar. there is a
* small gap between each tab. if the user drags something exactly there
* then mLandingTab will be set to NULL and the dragged item will be pushed
* to the end of the favorites bar. this is incorrect behavior. that's why
* we need an additional check which excludes the case described previously
* making sure that the mouse pointer is beyond the last tab.
*/
setLandingTab(NULL);
// Drag to a landmark button?
if (LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)))
{
setLandingTab(dest);
}
else
{
// Drag to the "More" button?
if (mMoreCtrl && mMoreCtrl->getVisible() && mMoreCtrl->getRect().pointInRect(x, y))
{
LLView* overflow_menu = mOverflowMenuHandle.get();
if (!overflow_menu || overflow_menu->isDead() || !overflow_menu->getVisible())
{
showDropDownMenu();
}
}
// Drag to the right of the last landmark button?
if (mLastTab && (x >= mLastTab->getRect().mRight))
{
/*
* the condition dest == NULL can be satisfied not only in the case
* of dragging to the right from the last tab of the favbar. there is a
* small gap between each tab. if the user drags something exactly there
* then mLandingTab will be set to NULL and the dragged item will be pushed
* to the end of the favorites bar. this is incorrect behavior. that's why
* we need an additional check which excludes the case described previously
* making sure that the mouse pointer is beyond the last tab.
*/
setLandingTab(NULL);
}
}
}
// check if we are dragging an existing item from the favorites bar
bool existing_drop = false;
// Check whether we are dragging an existing item from the favorites bar
bool existing_item = false;
if (item && mDragItemId == item->getUUID())
{
// There is a chance of mDragItemId being obsolete
@ -626,21 +685,19 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// results in viewer not geting a 'mouse up' signal
for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i)
{
LLViewerInventoryItem* currItem = *i;
if (currItem->getUUID() == mDragItemId)
if ((*i)->getUUID() == mDragItemId)
{
existing_drop = true;
existing_item = true;
break;
}
}
}
if (existing_drop)
if (existing_item)
{
*accept = ACCEPT_YES_SINGLE;
showDragMarker(TRUE);
showDragMarker(true);
if (drop)
{
@ -658,14 +715,14 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
*accept = ACCEPT_YES_COPY_MULTI;
showDragMarker(TRUE);
showDragMarker(true);
if (drop)
{
if (mItems.empty())
{
setLandingTab(NULL);
mLastTab = NULL;
mLastTab = NULL;
}
handleNewFavoriteDragAndDrop(item, favorites_id, x, y);
}
@ -679,82 +736,56 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return TRUE;
}
bool LLFavoritesBarCtrl::handleDragAndDropToMenu(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
{
mDragToOverflowMenu = true;
BOOL handled = handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
mDragToOverflowMenu = false;
return handled;
}
void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
{
if (mItems.empty())
{
// Isn't supposed to be empty
if (LL_UNLIKELY(mItems.empty()))
return;
LLUUID target_id;
bool insert_before = false;
if (!findDragAndDropTarget(target_id, insert_before, x, y))
return;
// There is no need to handle if an item was dragged onto itself
if (target_id == mDragItemId)
return;
// Move the dragged item to the right place in the array
LLInventoryModel::updateItemsOrder(mItems, mDragItemId, target_id, insert_before);
LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);
LLView* menu = mOverflowMenuHandle.get();
if (menu && !menu->isDead() && menu->getVisible())
{
updateOverflowMenuItems();
positionAndShowOverflowMenu();
}
// Identify the button hovered and the side to drop
LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
bool insert_before = true;
if (!dest)
{
insert_before = false;
dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
}
// There is no need to handle if an item was dragged onto itself
if (dest && dest->getLandmarkId() == mDragItemId)
{
return;
}
// Insert the dragged item in the right place
if (dest)
{
LLInventoryModel::updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId(), insert_before);
}
else
{
// This can happen when the item list is empty
mItems.push_back(gInventory.getItem(mDragItemId));
}
LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);
LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get();
if (menu && menu->getVisible())
{
menu->setVisible(FALSE);
showDropDownMenu();
}
}
void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y)
{
// Identify the button hovered and the side to drop
LLFavoriteLandmarkButton* dest = NULL;
bool insert_before = true;
if (!mItems.empty())
{
// [MAINT-2386] When multiple landmarks are selected and dragged onto an empty favorites bar,
// the viewer would crash when casting mLastTab below, as mLastTab is still null when the
// second landmark is being added.
// To ensure mLastTab is valid, we need to call updateButtons() at the end of this function
dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
if (!dest)
{
insert_before = false;
dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
}
}
// There is no need to handle if an item was dragged onto itself
if (dest && dest->getLandmarkId() == mDragItemId)
{
return;
}
LLUUID target_id;
bool insert_before = false;
// There is no need to handle if an item was dragged onto itself
if (findDragAndDropTarget(target_id, insert_before, x, y) && (target_id == mDragItemId))
return;
LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
// Insert the dragged item in the right place
if (dest)
// Insert the dragged item to the right place
if (target_id.notNull())
{
insertItem(mItems, dest->getLandmarkId(), viewer_item, insert_before);
insertItem(mItems, target_id, viewer_item, insert_before);
}
else
{
@ -810,10 +841,75 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
// This also ensures that mLastTab will be valid when dropping multiple
// landmarks to an empty favorites bar.
updateButtons();
LLView* overflow_menu = mOverflowMenuHandle.get();
if (overflow_menu && !overflow_menu->isDead() && overflow_menu->getVisible())
{
updateOverflowMenuItems();
positionAndShowOverflowMenu();
}
LL_INFOS("FavoritesBar") << "Copied inventory item #" << item->getUUID() << " to favorites." << LL_ENDL;
}
bool LLFavoritesBarCtrl::findDragAndDropTarget(LLUUID& target_id, bool& insert_before, S32 x, S32 y)
{
if (mItems.empty())
return false;
if (mDragToOverflowMenu)
{
LLView* overflow_menu = mOverflowMenuHandle.get();
if (LL_UNLIKELY(!overflow_menu || overflow_menu->isDead() || !overflow_menu->getVisible()))
return false;
// Identify the menu item hovered and the side to drop
LLFavoriteLandmarkMenuItem* target_item = dynamic_cast<LLFavoriteLandmarkMenuItem*>(overflow_menu->childFromPoint(x, y));
if (target_item)
{
insert_before = true;
}
else
{
// Choose the bottom landmark menu item
auto begin = overflow_menu->getChildList()->begin();
auto end = overflow_menu->getChildList()->end();
auto check = [](const LLView* child) -> bool
{
return dynamic_cast<const LLFavoriteLandmarkMenuItem*>(child);
};
// Menu items are placed in the backward order, so the bottom goes first
auto it = std::find_if(begin, end, check);
if (LL_UNLIKELY(it == end))
return false;
target_item = (LLFavoriteLandmarkMenuItem*)*it;
insert_before = false;
}
target_id = target_item->getLandmarkID();
}
else
{
// Identify the button hovered and the side to drop
LLFavoriteLandmarkButton* hovered_button = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
if (hovered_button)
{
insert_before = true;
}
else
{
// Choose the right landmark button
hovered_button = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
if (LL_UNLIKELY(!hovered_button))
return false;
insert_before = false;
}
target_id = hovered_button->getLandmarkID();
}
return true;
}
//virtual
void LLFavoritesBarCtrl::changed(U32 mask)
{
@ -884,7 +980,7 @@ void LLFavoritesBarCtrl::draw()
mImageDragIndication->draw(rect.mRight, rect.getHeight(), w, h);
}
// Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again)
mShowDragMarker = FALSE;
mShowDragMarker = false;
}
if (mItemsChangedTimer.getStarted())
{
@ -980,7 +1076,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
if (item)
{
// an child's order and mItems should be same
if (button->getLandmarkId() != item->getUUID() // sort order has been changed
if (button->getLandmarkID() != item->getUUID() // sort order has been changed
|| button->getLabelSelected() != item->getName()) // favorite's name has been changed
{
break;
@ -1060,11 +1156,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
{
// mMoreTextBox was removed, so LLFavoriteLandmarkButtons
// should be the only ones in the list
LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (childs->back());
if (button)
{
mLastTab = button;
}
mLastTab = dynamic_cast<LLFavoriteLandmarkButton*>(childs->back());
}
mFirstDropDownItem = j;
@ -1072,23 +1164,20 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
if (mFirstDropDownItem < mItems.size())
{
// if updateButton had been called it means:
//or there are some new favorites, or width had been changed
// or there are some new favorites, or width had been changed
// so if we need to display chevron button, we must update dropdown items too.
mUpdateDropDownItems = true;
S32 buttonHGap = button_params.rect.left; // default value
LLRect rect;
// Chevron button should stay right aligned
// <FS:Ansariel> Allow V3 and FS style favorites bar
//rect.setOriginAndSize(getRect().mRight - mMoreTextBox->getRect().getWidth() - buttonHGap, 0,
// mMoreTextBox->getRect().getWidth(),
// mMoreTextBox->getRect().getHeight());
//LLRect rect(mMoreTextBox->getRect());
//rect.translate(getRect().mRight - rect.mRight - buttonHGap, 0);
//addChild(mMoreTextBox);
//mMoreTextBox->setRect(rect);
//mMoreTextBox->setVisible(TRUE);
rect.setOriginAndSize(getRect().mRight - mMoreCtrl->getRect().getWidth() - buttonHGap, 0,
mMoreCtrl->getRect().getWidth(),
mMoreCtrl->getRect().getHeight());
LLRect rect(mMoreCtrl->getRect());
rect.translate(getRect().mRight - rect.mRight - buttonHGap, 0);
addChild(mMoreCtrl);
mMoreCtrl->setRect(rect);
@ -1225,17 +1314,19 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
if (mUpdateDropDownItems)
{
updateMenuItems(menu);
updateOverflowMenuItems();
}
else
{
menu->buildDrawLabels();
}
menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
// <FS:Ansariel> Allow V3 and FS style favorites bar
//menu->setButtonRect(mMoreTextBox->getRect(), this);
menu->setButtonRect(mMoreCtrl->getRect(), this);
// </FS:Ansariel>
positionAndShowMenu(menu);
mDropDownItemsCount = menu->getItemCount();
positionAndShowOverflowMenu();
}
}
@ -1249,12 +1340,14 @@ void LLFavoritesBarCtrl::createOverflowMenu()
menu_p.max_scrollable_items = 10;
menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
LLToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
LLFavoriteLandmarkToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
menu->setToolbar(this);
mOverflowMenuHandle = menu->getHandle();
}
void LLFavoritesBarCtrl::updateMenuItems(LLToggleableMenu* menu)
void LLFavoritesBarCtrl::updateOverflowMenuItems()
{
LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get();
menu->empty();
U32 widest_item = 0;
@ -1283,6 +1376,8 @@ void LLFavoritesBarCtrl::updateMenuItems(LLToggleableMenu* menu)
menu->addChild(menu_item);
}
menu->buildDrawLabels();
mDropDownItemsCount = menu->getItemCount();
addOpenLandmarksMenuItem(menu);
mUpdateDropDownItems = false;
}
@ -1339,8 +1434,9 @@ void LLFavoritesBarCtrl::addOpenLandmarksMenuItem(LLToggleableMenu* menu)
menu->addChild(menu_item);
}
void LLFavoritesBarCtrl::positionAndShowMenu(LLToggleableMenu* menu)
void LLFavoritesBarCtrl::positionAndShowOverflowMenu()
{
LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get();
U32 max_width = llmin(DROP_DOWN_MENU_WIDTH, getRect().getWidth());
S32 menu_x = getRect().getWidth() - max_width;
@ -1631,7 +1727,7 @@ void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32
}
mDragItemId = id;
mStartDrag = TRUE;
mStartDrag = true;
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
@ -1641,7 +1737,7 @@ void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32
void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
mStartDrag = FALSE;
mStartDrag = false;
mDragItemId = LLUUID::null;
}
@ -1649,7 +1745,7 @@ void LLFavoritesBarCtrl::onEndDrag()
{
mEndDragConnection.disconnect();
showDragMarker(FALSE);
showDragMarker(false);
mDragItemId = LLUUID::null;
LLView::getWindow()->setCursor(UI_CURSOR_ARROW);
}
@ -1667,7 +1763,7 @@ BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask)
DAD_LANDMARK, mDragItemId,
LLToolDragAndDrop::SOURCE_LIBRARY);
mStartDrag = FALSE;
mStartDrag = false;
return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask);
}
@ -1696,6 +1792,7 @@ LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y)
}
}
}
return ctrl;
}
@ -2333,8 +2430,10 @@ bool LLFavoritesOrderStorage::isStorageUpdateNeeded()
void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
{
if (mTargetLandmarkId.isNull()) return;
LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
if (!mTargetLandmarkId.isNull())
{
LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
}
}
// EOF

View File

@ -59,22 +59,21 @@ protected:
public:
virtual ~LLFavoritesBarCtrl();
/*virtual*/ BOOL postBuild();
/*virtual*/ BOOL postBuild() override;
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override;
bool handleDragAndDropToMenu(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
// LLInventoryObserver observer trigger
virtual void changed(U32 mask);
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void draw();
/*virtual*/ void changed(U32 mask) override;
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
/*virtual*/ void draw() override;
void showDragMarker(BOOL show) { mShowDragMarker = show; }
void showDragMarker(bool show) { mShowDragMarker = show; }
void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }
protected:
@ -111,7 +110,7 @@ protected:
S32 mDropDownItemsCount;
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
bool mDragToOverflowMenu;
bool mGetPrevItems;
LLUUID mSelectedItemID;
@ -121,19 +120,21 @@ protected:
private:
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the existing favorites items on the favorites bar.
* operations of the existing favorites items to the favorites bar to on the overflow menu.
*/
void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the new landmark to the favorites bar.
* operations of the new landmark to the favorites bar or to the overflow menu.
*/
void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
// finds a control under the specified LOCAL point
LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
bool findDragAndDropTarget(LLUUID &target_id, bool &insert_before, S32 x, S32 y);
// checks if the current order of the favorites items must be saved
BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
@ -148,16 +149,16 @@ private:
void createOverflowMenu();
void updateMenuItems(LLToggleableMenu* menu);
void updateOverflowMenuItems();
// Fits menu item label width with favorites menu width
void fitLabelWidth(LLMenuItemCallGL* menu_item);
void addOpenLandmarksMenuItem(LLToggleableMenu* menu);
void positionAndShowMenu(LLToggleableMenu* menu);
void positionAndShowOverflowMenu();
BOOL mShowDragMarker;
bool mShowDragMarker;
LLUICtrl* mLandingTab;
LLUICtrl* mLastTab;
// <FS:Ansariel> Allow V3 and FS style favorites bar
@ -168,11 +169,9 @@ private:
LLTextBox* mBarLabel;
LLUUID mDragItemId;
BOOL mStartDrag;
bool mStartDrag;
LLInventoryModel::item_array_t mItems;
BOOL mTabsHighlightEnabled;
S32 mMouseX;
S32 mMouseY;

View File

@ -371,6 +371,8 @@ void LLFloater360Capture::encodeAndSave(LLPointer<LLImageRaw> raw_image, const s
int jpeg_encode_quality = gSavedSettings.getU32("360CaptureJPEGEncodeQuality");
LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG(jpeg_encode_quality);
LLImageDataSharedLock lock(raw_image);
// Actually encode the JPEG image. This is where a lot of time
// is spent now that the snapshot capture process has been
// optimized. The encode_time parameter doesn't appear to be
@ -421,6 +423,8 @@ void LLFloater360Capture::suspendForAFrame()
// Probably not needed anymore but saving here just in case.
void LLFloater360Capture::mockSnapShot(LLImageRaw* raw)
{
LLImageDataLock lock(raw);
unsigned int width = raw->getWidth();
unsigned int height = raw->getHeight();
unsigned int depth = raw->getComponents();

View File

@ -193,6 +193,8 @@ void LLFloaterAuction::onClickSnapshot(void* data)
if (success)
{
LLImageDataLock lock(raw);
self->mTransactionID.generate();
self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID());

View File

@ -138,6 +138,8 @@ void LLFloaterColorPicker::createUI ()
// create RGB type area (not really RGB but it's got R,G & B in it.,..
LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
LLImageDataLock lock(raw);
U8* bits = raw->getData();
S32 linesize = mRGBViewerImageWidth * mComponents;
for ( S32 y = 0; y < mRGBViewerImageHeight; ++y )

View File

@ -981,6 +981,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
if (imagep)
{
LLImageDataSharedLock lock(imagep);
mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false);
}

View File

@ -1050,7 +1050,7 @@ void LLFloaterPreference::apply()
saveGraphicsPreset(gSavedSettings.getString("PresetGraphicActive"));
}
void LLFloaterPreference::cancel()
void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip)
{
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
// Call cancel() on all panels that derive from LLPanelPreference
@ -1060,7 +1060,7 @@ void LLFloaterPreference::cancel()
LLView* view = *iter;
LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
if (panel)
panel->cancel();
panel->cancel(settings_to_skip);
}
// hide joystick pref floater
LLFloaterReg::hideInstance("pref_joystick");
@ -1627,14 +1627,16 @@ void LLFloaterPreference::onBtnCancel(const LLSD& userdata)
}
refresh();
}
cancel();
if (userdata.asString() == "closeadvanced")
{
cancel({"RenderQualityPerformance"});
LLFloaterReg::hideInstance("prefs_graphics_advanced");
updateMaxComplexity();
}
else
{
cancel();
closeFloater();
}
}
@ -3630,7 +3632,7 @@ void LLPanelPreference::onCheckContactListColumnMode()
}
// </FS:Ansariel>
void LLPanelPreference::cancel()
void LLPanelPreference::cancel(const std::vector<std::string> settings_to_skip)
{
LLPresetsManager::instance().setIsLoadingPreset(true); // <FS:Ansariel> Graphic preset controls independent from XUI
@ -3645,6 +3647,12 @@ void LLPanelPreference::cancel()
continue;
}
auto found = std::find(settings_to_skip.begin(), settings_to_skip.end(), control->getName());
if (found != settings_to_skip.end())
{
continue;
}
control->set(ctrl_value);
}
@ -4035,11 +4043,11 @@ void LLPanelPreferenceGraphics::resetDirtyChilds()
}
}
void LLPanelPreferenceGraphics::cancel()
void LLPanelPreferenceGraphics::cancel(const std::vector<std::string> settings_to_skip)
{
// <FS:Ansariel> Improved graphics preferences
resetDirtyChilds();
LLPanelPreference::cancel();
LLPanelPreference::cancel(settings_to_skip);
}
void LLPanelPreferenceGraphics::saveSettings()
{
@ -4331,7 +4339,7 @@ void LLPanelPreferenceControls::apply()
}
}
void LLPanelPreferenceControls::cancel()
void LLPanelPreferenceControls::cancel(const std::vector<std::string> settings_to_skip)
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
@ -5081,7 +5089,7 @@ void LLPanelPreferenceCrashReports::apply()
gCrashSettings.setBOOL("CrashSubmitName", pSendName->get());
}
void LLPanelPreferenceCrashReports::cancel()
void LLPanelPreferenceCrashReports::cancel(const std::vector<std::string> settings_to_skip)
{
}
// [/SL:KB]
@ -5204,7 +5212,7 @@ void LLPanelPreferenceSkins::callbackRestart(const LLSD& notification, const LLS
}
}
void LLPanelPreferenceSkins::cancel()
void LLPanelPreferenceSkins::cancel(const std::vector<std::string> settings_to_skip)
{
m_Skin = gSavedSettings.getString("SkinCurrent");
m_SkinTheme = gSavedSettings.getString("SkinCurrentTheme");
@ -6101,7 +6109,7 @@ void LLPanelPreferenceOpensim::apply()
FSPanelLogin::updateServer();
}
void LLPanelPreferenceOpensim::cancel()
void LLPanelPreferenceOpensim::cancel(const std::vector<std::string> settings_to_skip)
{
LLGridManager::getInstance()->resetGrids();
LLGridManager::getInstance()->setGridChoice(mCurrentGrid);

View File

@ -86,7 +86,7 @@ public:
~LLFloaterPreference();
void apply();
void cancel();
void cancel(const std::vector<std::string> settings_to_skip = {});
// <FS:Zi> FIRE-19539 - Include the alert messages in Prefs>Notifications>Alerts in preference Search.
// /*virtual*/ void draw();
// </FS:Zi>
@ -353,7 +353,7 @@ public:
virtual ~LLPanelPreference();
virtual void apply();
virtual void cancel();
virtual void cancel(const std::vector<std::string> settings_to_skip = {});
// void setControlFalse(const LLSD& user_data); //<FS:KC> Handled centrally now
virtual void setHardwareDefaults();
@ -416,14 +416,12 @@ class LLPanelPreferenceGraphics : public LLPanelPreference
public:
BOOL postBuild();
void draw();
void cancel();
void cancel(const std::vector<std::string> settings_to_skip = {});
void saveSettings();
void resetDirtyChilds();
void setHardwareDefaults();
void setPresetText();
static const std::string getPresetsPath();
protected:
bool hasDirtyChilds();
@ -443,7 +441,7 @@ public:
BOOL postBuild();
void apply();
void cancel();
void cancel(const std::vector<std::string> settings_to_skip = {});
void saveSettings();
void resetDirtyChilds();
@ -508,7 +506,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void apply();
/*virtual*/ void cancel();
/*virtual*/ void cancel(const std::vector<std::string> settings_to_skip = {});
void callbackRestart(const LLSD& notification, const LLSD& response); // <FS:CR> Callback for restart dialogs
protected:
void onSkinChanged();
@ -540,7 +538,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void apply();
/*virtual*/ void cancel();
/*virtual*/ void cancel(const std::vector<std::string> settings_to_skip = {});
void refresh();
@ -587,7 +585,7 @@ public:
#ifdef OPENSIM
/*virtual*/ void apply();
/*virtual*/ void cancel();
/*virtual*/ void cancel(const std::vector<std::string> settings_to_skip = {});
protected:
boost::signals2::connection mGridListChangedCallbackConnection;

View File

@ -94,7 +94,7 @@ void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting)
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
instance->cancel();
instance->cancel({"RenderQualityPerformance"});
}
updateMaxComplexity();
}

View File

@ -4804,12 +4804,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (!isInboxFolder() // don't allow creation in inbox
&& outfits_id != mUUID)
{
bool menu_items_added = false;
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
{
items.push_back(std::string("New Folder"));
menu_items_added = true;
}
// <FS:Ansariel> Fix "outfits" context menu
//if (!isMarketplaceListingsFolder())
@ -4829,10 +4827,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
{
disabled_items.push_back("New Settings");
}
}
if (menu_items_added)
{
items.push_back(std::string("Create Separator"));
}
}
getClipboardEntries(false, items, disabled_items, flags);

View File

@ -2028,6 +2028,39 @@ void LLInventoryGallery::pasteAsLink(const LLUUID& dest,
}
}
void LLInventoryGallery::doCreate(const LLUUID& dest, const LLSD& userdata)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(dest);
if (cat && mFolderID != dest)
{
menu_create_inventory_item(NULL, dest, userdata, LLUUID::null);
}
else
{
// todo: needs to reset current floater's filter,
// like reset_inventory_filter()
LLHandle<LLPanel> handle = getHandle();
std::function<void(const LLUUID&)> callback_cat_created =
[handle](const LLUUID& new_id)
{
gInventory.notifyObservers();
LLInventoryGallery* panel = static_cast<LLInventoryGallery*>(handle.get());
if (panel && new_id.notNull())
{
panel->clearSelection();
if (panel->mItemMap.count(new_id) != 0)
{
panel->addItemSelection(new_id, true);
}
}
};
menu_create_inventory_item(NULL, mFolderID, userdata, LLUUID::null, callback_cat_created);
}
}
void LLInventoryGallery::claimEditHandler()
{
gEditMenuHandler = this;

View File

@ -166,6 +166,7 @@ public:
void deleteSelection();
bool canDeleteSelection();
void pasteAsLink();
void doCreate(const LLUUID& dest, const LLSD& userdata);
void setSortOrder(U32 order, bool update = false);
U32 getSortOrder() { return mSortOrder; };

View File

@ -32,9 +32,11 @@
#include "llappearancemgr.h"
#include "llavataractions.h"
#include "llclipboard.h"
#include "llenvironment.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
#include "llfriendcard.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@ -48,6 +50,41 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
void modify_outfit(BOOL append, const LLUUID& cat_id, LLInventoryModel* model)
{
LLViewerInventoryCategory* cat = model->getCategory(cat_id);
if (!cat) return;
// checking amount of items to wear
static LLCachedControl<U32> max_items(gSavedSettings, "WearFolderLimit", 125);
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
model->collectDescendentsIf(cat_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
not_worn);
if (items.size() > max_items())
{
LLSD args;
args["AMOUNT"] = llformat("%u", max_items());
LLNotificationsUtil::add("TooManyWearables", args);
return;
}
if (model->isObjectDescendentOf(cat_id, gInventory.getRootFolderID()))
{
LLAppearanceMgr::instance().wearInventoryCategory(cat, FALSE, append);
}
else
{
// Library, we need to copy content first
LLAppearanceMgr::instance().wearInventoryCategory(cat, TRUE, append);
}
}
LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@ -57,11 +94,33 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2));
registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
registrar.add("Inventory.DoCreate", [this](LLUICtrl*, const LLSD& data)
{
if (mRootFolder)
{
mGallery->doCreate(mGallery->getRootFolder(), data);
}
else
{
mGallery->doCreate(mUUIDs.front(), data);
}
});
std::set<LLUUID> uuids(mUUIDs.begin(), mUUIDs.end());
registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery)));
enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2));
enable_registrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl*, const LLSD&)
{
return LLEnvironment::instance().isInventoryEnabled();
});
enable_registrar.add("Inventory.MaterialsEnabled", [](LLUICtrl*, const LLSD&)
{
std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory");
std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory");
return (!agent_url.empty() && !task_url.empty());
});
LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml");
@ -186,6 +245,22 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
{
ungroup_folder_items(mUUIDs.front());
}
else if ("replaceoutfit" == action)
{
modify_outfit(FALSE, mUUIDs.front(), &gInventory);
}
else if ("addtooutfit" == action)
{
modify_outfit(TRUE, mUUIDs.front(), &gInventory);
}
else if ("removefromoutfit" == action)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(mUUIDs.front());
if (cat)
{
LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID());
}
}
else if ("take_off" == action || "detach" == action)
{
for (LLUUID& selected_id : mUUIDs)
@ -307,6 +382,54 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
preview_texture->saveAs();
}
}
else if (("copy_to_marketplace_listings" == action)
|| ("move_to_marketplace_listings" == action))
{
LLViewerInventoryItem* itemp = gInventory.getItem(mUUIDs.front());
bool copy_operation = "copy_to_marketplace_listings" == action;
bool can_copy = itemp ? itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) : false;
if (can_copy)
{
const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
if (itemp)
{
move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation);
}
}
else
{
uuid_vec_t lamdba_list = mUUIDs;
LLNotificationsUtil::add(
"ConfirmCopyToMarketplace",
LLSD(),
LLSD(),
[lamdba_list](const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// option == 0 Move no copy item(s)
// option == 1 Don't move no copy item(s) (leave them behind)
bool copy_and_move = option == 0;
const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
// main inventory only allows one item?
LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front());
if (itemp)
{
if (itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
{
move_item_to_marketplacelistings(itemp, marketplacelistings_id, true);
}
else if (copy_and_move)
{
move_item_to_marketplacelistings(itemp, marketplacelistings_id, false);
}
}
}
);
}
}
}
void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id)
@ -400,6 +523,56 @@ bool is_inbox_folder(LLUUID item_id)
return gInventory.isObjectDescendentOf(item_id, inbox_id);
}
bool can_list_on_marketplace(const LLUUID &id)
{
const LLInventoryObject* obj = gInventory.getObject(id);
bool can_list = (obj != NULL);
if (can_list)
{
const LLUUID& object_id = obj->getLinkedUUID();
can_list = object_id.notNull();
if (can_list)
{
std::string error_msg;
const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
if (marketplacelistings_id.notNull())
{
LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id);
LLInventoryCategory* cat = gInventory.getCategory(id);
if (cat)
{
can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg);
}
else
{
LLInventoryItem* item = gInventory.getItem(id);
can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false);
}
}
else
{
can_list = false;
}
}
}
return can_list;
}
bool check_folder_for_contents_of_type(const LLUUID &id, LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
model->collectDescendentsIf(id,
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH,
is_type);
return item_array.size() > 0;
}
void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu)
{
LLUUID selected_id = mUUIDs.front();
@ -421,6 +594,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
//bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
bool is_system_folder = false;
@ -468,6 +642,49 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
items.push_back(std::string("open_in_new_window"));
items.push_back(std::string("Open Folder Separator"));
}
// wearables related functionality for folders.
LLFindWearables is_wearable;
LLIsType is_object(LLAssetType::AT_OBJECT);
LLIsType is_gesture(LLAssetType::AT_GESTURE);
if (check_folder_for_contents_of_type(selected_id, &gInventory, is_wearable)
|| check_folder_for_contents_of_type(selected_id, &gInventory, is_object)
|| check_folder_for_contents_of_type(selected_id, &gInventory, is_gesture))
{
// Only enable add/replace outfit for non-system folders.
if (!is_system_folder)
{
// Adding an outfit onto another (versus replacing) doesn't make sense.
if (folder_type != LLFolderType::FT_OUTFIT)
{
items.push_back(std::string("Add To Outfit"));
if (!LLAppearanceMgr::instance().getCanAddToCOF(selected_id))
{
disabled_items.push_back(std::string("Add To Outfit"));
}
}
items.push_back(std::string("Replace Outfit"));
if (!LLAppearanceMgr::instance().getCanReplaceCOF(selected_id))
{
disabled_items.push_back(std::string("Replace Outfit"));
}
}
if (is_agent_inventory)
{
items.push_back(std::string("Folder Wearables Separator"));
// Note: If user tries to unwear "My Inventory", it's going to deactivate everything including gestures
// Might be safer to disable this for "My Inventory"
items.push_back(std::string("Remove From Outfit"));
if (folder_type != LLFolderType::FT_ROOT_INVENTORY // Unless COF is empty, whih shouldn't be, warrantied to have worn items
&& !LLAppearanceMgr::getCanRemoveFromCOF(selected_id)) // expensive from root!
{
disabled_items.push_back(std::string("Remove From Outfit"));
}
}
items.push_back(std::string("Outfit Separator"));
}
}
else
{
@ -515,11 +732,30 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
else
{
if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits)
{
LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);
if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category))
{
items.push_back(std::string("New Folder"));
}
items.push_back(std::string("create_new"));
items.push_back(std::string("New Script"));
items.push_back(std::string("New Note"));
items.push_back(std::string("New Gesture"));
items.push_back(std::string("New Material"));
items.push_back(std::string("New Clothes"));
items.push_back(std::string("New Body Parts"));
items.push_back(std::string("New Settings"));
}
if(can_share_item(selected_id))
{
items.push_back(std::string("Share"));
}
if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id))
if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox)
{
items.push_back(std::string("Paste"));
@ -531,7 +767,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
if (is_folder && is_agent_inventory)
{
if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id))
if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox)
{
if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder())
{
@ -721,6 +957,54 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("upload_def"));
disabled_items.push_back(std::string("create_new"));
}
if (is_agent_inventory && !mRootFolder)
{
items.push_back(std::string("New folder from selected"));
items.push_back(std::string("Subfolder Separator"));
if (!is_only_items_selected(mUUIDs) && !is_only_cats_selected(mUUIDs))
{
disabled_items.push_back(std::string("New folder from selected"));
}
}
// Marketplace
bool can_list = false;
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType())
{
if (is_folder)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id);
if (cat
&& !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
&& gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID()))
{
can_list = true;
}
}
else if (selected_item
&& selected_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())
&& selected_item->getPermissions().getOwner() != ALEXANDRIA_LINDEN_ID
&& LLAssetType::AT_CALLINGCARD != selected_item->getType())
{
can_list = true;
}
}
if (can_list)
{
items.push_back(std::string("Marketplace Separator"));
items.push_back(std::string("Marketplace Copy"));
items.push_back(std::string("Marketplace Move"));
if (!can_list_on_marketplace(selected_id))
{
disabled_items.push_back(std::string("Marketplace Copy"));
disabled_items.push_back(std::string("Marketplace Move"));
}
}
}

View File

@ -2231,7 +2231,7 @@ bool LLMaterialEditor::canModifyObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
return can_use_objects_material(func, std::vector({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out);
return can_use_objects_material(func, std::vector<PermissionBit>({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out);
}
bool LLMaterialEditor::canSaveObjectsMaterial()
@ -2239,7 +2239,7 @@ bool LLMaterialEditor::canSaveObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out);
return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out);
}
bool LLMaterialEditor::canClipboardObjectsMaterial()
@ -2265,7 +2265,7 @@ bool LLMaterialEditor::canClipboardObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out);
return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out);
}
void LLMaterialEditor::saveObjectsMaterialAs()
@ -2273,7 +2273,7 @@ void LLMaterialEditor::saveObjectsMaterialAs()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item = nullptr;
bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item);
bool allowed = can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item);
if (!allowed)
{
LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL;
@ -3482,6 +3482,8 @@ void LLMaterialEditor::inventoryChanged(LLViewerObject* object,
void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb)
{
LLImageDataSharedLock lock(img);
if (asset_id.isNull()
|| img == nullptr
|| img->getDataSize() == 0)

View File

@ -2465,17 +2465,19 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::stringstream texture_str;
if (texture != NULL && include_textures && mUploadTextures)
{
if(texture->hasSavedRawImage())
{
if (texture->hasSavedRawImage())
{
LLImageDataLock lock(texture->getSavedRawImage());
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
if (!upload_file.isNull() && upload_file->getDataSize())
{
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
}
}
}
}
if (texture != NULL &&
mUploadTextures &&
@ -2619,17 +2621,19 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::stringstream texture_str;
if (texture != NULL && include_textures && mUploadTextures)
{
if(texture->hasSavedRawImage())
{
if (texture->hasSavedRawImage())
{
LLImageDataLock lock(texture->getSavedRawImage());
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
if (!upload_file.isNull() && upload_file->getDataSize())
{
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
}
}
}
}
if (texture != NULL &&
mUploadTextures &&

View File

@ -620,6 +620,7 @@ void LLNetMap::draw()
// [/SL:KB]
// Create the base texture.
LLImageDataLock lock(mObjectRawImagep);
U8 *default_texture = mObjectRawImagep->getData();
memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
@ -1469,6 +1470,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
return;
}
LLImageDataLock lock(mObjectRawImagep);
U8 *datap = mObjectRawImagep->getData();
S32 neg_radius = diameter / 2;

View File

@ -39,11 +39,6 @@ LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p)
mAgentID(p.agent_id)
{}
void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
{
LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL;
}
BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,

View File

@ -59,8 +59,6 @@ public:
LLProfileDropTarget(const Params&);
~LLProfileDropTarget() {}
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,

View File

@ -91,8 +91,6 @@ public:
LLGroupDropTarget(const Params&);
~LLGroupDropTarget() {};
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@ -116,11 +114,6 @@ LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p)
mGroupID(p.group_id)
{}
void LLGroupDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
{
LL_INFOS() << "LLGroupDropTarget::doDrop()" << LL_ENDL;
}
BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,

View File

@ -56,6 +56,7 @@
#include "lltrans.h"
#include "llviewermenu.h"
#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llsidepanelinventory.h"
#include "llfolderview.h"
#include "llradiogroup.h"

View File

@ -46,6 +46,7 @@
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lltoggleablemenu.h"
#include "lltooldraganddrop.h"
#include "llgrouplist.h"
#include "llurlaction.h"
@ -1142,6 +1143,51 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2));
}
BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
// Try children first
if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg)
&& *accept != ACCEPT_NO)
{
return TRUE;
}
// No point sharing with own profile
if (getSelfProfile())
{
return FALSE;
}
// Exclude fields that look like they are editable.
S32 child_x = 0;
S32 child_y = 0;
if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit)
&& mDescriptionEdit->pointInView(child_x, child_y))
{
return FALSE;
}
if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList)
&& mGroupList->pointInView(child_x, child_y))
{
return FALSE;
}
// Share
LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(),
LLUUID::null,
drop,
cargo_type,
cargo_data,
accept);
return TRUE;
}
void LLPanelProfileSecondLife::updateData()
{
LLUUID avatar_id = getAvatarId();

View File

@ -93,6 +93,12 @@ public:
void onOpen(const LLSD& key) override;
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg) override;
/**
* LLFriendObserver trigger
*/

View File

@ -881,6 +881,8 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
// Get the decoded version of the formatted image
getEncodedImage();
LLImageDataSharedLock lock(mPreviewImageEncoded);
// We need to scale that a bit for display...
LLPointer<LLImageRaw> scaled = new LLImageRaw(
mPreviewImageEncoded->getData(),
@ -940,13 +942,15 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
{
if (!mPreviewImageEncoded)
{
LLImageDataSharedLock lock(mPreviewImage);
mPreviewImageEncoded = new LLImageRaw;
mPreviewImageEncoded->resize(
mPreviewImage->getWidth(),
mPreviewImage->getHeight(),
mPreviewImage->getComponents());
if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
@ -1093,6 +1097,8 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
LLImageDataSharedLock lock(mPreviewImage);
LL_DEBUGS("Snapshot") << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
// gen a new uuid for this asset
LLTransactionID tid;

View File

@ -742,7 +742,6 @@ class LLControlAVBridge : public LLVolumeBridge
using super = LLVolumeBridge;
public:
LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
virtual void updateSpatialExtents();
};
class LLHUDBridge : public LLVolumeBridge

View File

@ -96,7 +96,7 @@ private:
public:
LLTextureCacheWorker(LLTextureCache* cache, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
const U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLTextureCache::Responder* responder)
: LLWorkerClass(cache, "LLTextureCacheWorker"),
@ -145,7 +145,7 @@ protected:
LLUUID mID;
U8* mReadData;
U8* mWriteData;
const U8* mWriteData;
S32 mDataSize;
S32 mOffset;
S32 mImageSize;
@ -239,7 +239,7 @@ class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
{
public:
LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
const U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLPointer<LLImageRaw> raw, S32 discardlevel,
LLTextureCache::Responder* responder)
@ -1993,7 +1993,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
}
LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id,
U8* data, S32 datasize, S32 imagesize,
const U8* data, S32 datasize, S32 imagesize,
LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder)
{
@ -2089,6 +2089,9 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageDataSharedLock lock(raw);
//rescale image if needed
if (raw.isNull() || raw->isBufferInvalid() || !raw->getData())
{

View File

@ -125,7 +125,7 @@ public:
handle_t readFromCache(const LLUUID& id, S32 offset, S32 size,
ReadResponder* responder);
bool readComplete(handle_t handle, bool abort);
handle_t writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
handle_t writeToCache(const LLUUID& id, const U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder);
LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);
bool writeComplete(handle_t handle, bool abort = false);

View File

@ -1860,7 +1860,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFormattedImage = new LLImageJ2C; // default
}
}
LLImageDataLock lock(mFormattedImage);
if (mHaveAllData) //the image file is fully loaded.
{
mFileSize = total_size;
@ -2018,6 +2020,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
//return false;
return doWork(param);
}
LLImageDataSharedLock lock(mFormattedImage);
S32 datasize = mFormattedImage->getDataSize();
if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed.
{

View File

@ -31,7 +31,7 @@
#include "llviewertexture.h"
#include "llviewertexturelist.h"
void strip_alpha_channel(LLPointer<LLImageRaw>& img)
static void strip_alpha_channel(LLPointer<LLImageRaw>& img)
{
if (img->getComponents() == 4)
{
@ -45,13 +45,13 @@ void strip_alpha_channel(LLPointer<LLImageRaw>& img)
// PRECONDITIONS:
// dst_img must be 3 component
// src_img and dst_image must have the same dimensions
void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
static void copy_red_channel(const LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
{
llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight());
llassert(dst_img->getComponents() == 3);
U32 pixel_count = dst_img->getWidth() * dst_img->getHeight();
U8* src = src_img->getData();
const U8* src = src_img->getData();
U8* dst = dst_img->getData();
S8 src_components = src_img->getComponents();
@ -95,6 +95,8 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,
int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index;
if (occlusion_idx != mr_idx)
{
LLImageDataLock lockIn(occlusion_img);
LLImageDataLock lockOut(mr_img);
//scale occlusion image to match resolution of mr image
occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight());
@ -104,6 +106,7 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,
}
else if (occlusion_img)
{
LLImageDataSharedLock lock(occlusion_img);
//no mr but occlusion exists, make a white mr_img and copy occlusion red channel over
mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3);
mr_img->clear(255, 255, 255);

View File

@ -47,6 +47,7 @@
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llpreviewnotecard.h"
#include "llrootview.h"
#include "llselectmgr.h"
@ -329,6 +330,16 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL;
return;
}
if (type != DAD_CATEGORY)
{
LLViewerInventoryItem* item = gInventory.getItem(cargo_id);
if (item && !item->isFinished())
{
LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
}
}
mCargoTypes.clear();
mCargoTypes.push_back(type);
mCargoIDs.clear();

View File

@ -683,6 +683,8 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
{
setItemId(itemId);
LLImageDataSharedLock lock(image);
EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
switch (codec)

View File

@ -541,6 +541,7 @@ static bool handleLogFileChanged(const LLSD& newvalue)
std::string log_filename = newvalue.asString();
LLFile::remove(log_filename);
LLError::logToFile(log_filename);
LL_INFOS() << "Logging switched to " << log_filename << LL_ENDL;
return true;
}

View File

@ -1474,7 +1474,7 @@ void LLViewerJoystick::setSNDefaults()
#if LL_DARWIN || LL_LINUX
const float platformScale = 20.f;
const float platformScaleAvXZ = 1.f;
// The SpaceNavigator doesn't act as a 3D cursor on OS X / Linux.
// The SpaceNavigator doesn't act as a 3D cursor on macOS / Linux.
const bool is_3d_cursor = false;
#else
const float platformScale = 1.f;

View File

@ -294,6 +294,7 @@ BOOL enable_take();
void handle_object_show_inspector();
void handle_avatar_show_inspector();
bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle);
bool confirm_take_separate(const LLSD &notification, const LLSD &response, LLObjectSelectionHandle selection_handle);
void handle_buy_object(LLSaleInfo sale_info);
void handle_buy_contents(LLSaleInfo sale_info);
@ -6075,6 +6076,24 @@ static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
derez_objects(dest, dest_id, first_region, error, NULL);
}
static void derez_objects_separate(EDeRezDestination dest, const LLUUID &dest_id)
{
std::vector<LLViewerObjectPtr> derez_object_list;
std::string error;
LLViewerRegion* first_region = NULL;
if (!get_derezzable_objects(dest, error, first_region, &derez_object_list, false))
{
LL_WARNS() << "No objects to derez" << LL_ENDL;
return;
}
for (LLViewerObject *opjectp : derez_object_list)
{
std::vector<LLViewerObjectPtr> buf_list;
buf_list.push_back(opjectp);
derez_objects(dest, dest_id, first_region, error, &buf_list);
}
}
void handle_take_copy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
@ -6094,6 +6113,15 @@ void handle_take_copy()
derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
}
void handle_take_separate_copy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
return;
const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
derez_objects_separate(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
}
void handle_link_objects()
{
// <FS:Ansariel> We don't use a shortcut for two completely different functions based on context
@ -6198,7 +6226,7 @@ void force_take_copy(void*)
derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
}
void handle_take()
void handle_take(bool take_separate)
{
// we want to use the folder this was derezzed from if it's
// available. Otherwise, derez to the normal place.
@ -6301,7 +6329,17 @@ void handle_take()
// MAINT-290
// Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez.
// Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened
params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection()));
params.functor.function([take_separate](const LLSD &notification, const LLSD &response)
{
if (take_separate)
{
confirm_take_separate(notification, response, LLSelectMgr::instance().getSelection());
}
else
{
confirm_take(notification, response, LLSelectMgr::instance().getSelection());
}
});
if(locked_but_takeable_object ||
!you_own_everything)
@ -6364,6 +6402,16 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect
return false;
}
bool confirm_take_separate(const LLSD &notification, const LLSD &response, LLObjectSelectionHandle selection_handle)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (enable_take() && (option == 0))
{
derez_objects_separate(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
}
return false;
}
// You can take an item when it is public and transferrable, or when
// you own it. We err on the side of enabling the item when at least
// one item selected can be copied to inventory.
@ -6449,6 +6497,11 @@ bool visible_take_object()
return !is_selection_buy_not_take() && enable_take();
}
bool visible_take_objects()
{
return visible_take_object() && (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1);
}
bool tools_visible_buy_object()
{
return is_selection_buy_not_take();
@ -10111,6 +10164,10 @@ bool enable_object_take_copy()
return all_valid;
}
bool visible_take_copy_objects()
{
return enable_object_take_copy() && (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1);
}
class LLHasAsset : public LLInventoryCollectFunctor
{
@ -12228,6 +12285,7 @@ void initialize_menus()
enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
enable.add("Tools.VisibleCopySeparate", boost::bind(&visible_take_copy_objects));
enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
@ -12536,6 +12594,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLEnableEditParticleSource(), "Object.EnableEditParticles");
enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
enable.add("Object.VisibleTakeMultiple", boost::bind(&visible_take_objects));
enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
commit.add("Object.Buy", boost::bind(&handle_buy));
@ -12544,7 +12603,9 @@ void initialize_menus()
commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material));
commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
commit.add("Object.Open", boost::bind(&handle_object_open));
commit.add("Object.Take", boost::bind(&handle_take));
commit.add("Object.Take", boost::bind(&handle_take, false));
commit.add("Object.TakeSeparate", boost::bind(&handle_take, true));
commit.add("Object.TakeSeparateCopy", boost::bind(&handle_take_separate_copy));
commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
enable.add("Object.EnableInspect", boost::bind(&enable_object_inspect));
enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));

View File

@ -113,7 +113,7 @@ bool enable_object_delete();
// Buy either contents or object itself
void handle_buy();
void handle_take();
void handle_take(bool take_separate = false);
void handle_take_copy();
void handle_look_at_selection(const LLSD& param);
void handle_script_info();

View File

@ -1213,6 +1213,20 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
LL_DEBUGS("ObjectUpdate") << " mesgsys " << mesgsys << " dp " << dp << " id " << getID() << " update_type " << (S32) update_type << LL_ENDL;
dumpStack("ObjectUpdateStack");
// The new OBJECTDATA_FIELD_SIZE_124, OBJECTDATA_FIELD_SIZE_140, OBJECTDATA_FIELD_SIZE_80
// and OBJECTDATA_FIELD_SIZE_64 lengths should be supported in the existing cases below.
// Each case should start at the beginning of the buffer and extract all known
// values, and ignore any unknown data at the end of the buffer.
// This allows new data in the future without breaking current viewers.
const S32 OBJECTDATA_FIELD_SIZE_140 = 140; // Full precision avatar update for future extended data
const S32 OBJECTDATA_FIELD_SIZE_124 = 124; // Full precision object update for future extended data
const S32 OBJECTDATA_FIELD_SIZE_76 = 76; // Full precision avatar update
const S32 OBJECTDATA_FIELD_SIZE_60 = 60; // Full precision object update
const S32 OBJECTDATA_FIELD_SIZE_80 = 80; // Terse avatar update, 16 bit precision for future extended data
const S32 OBJECTDATA_FIELD_SIZE_64 = 64; // Terse object update, 16 bit precision for future extended data
const S32 OBJECTDATA_FIELD_SIZE_48 = 48; // Terse avatar update, 16 bit precision
const S32 OBJECTDATA_FIELD_SIZE_32 = 32; // Terse object update, 16 bit precision
U32 retval = 0x0;
// If region is removed from the list it is also deleted.
@ -1260,7 +1274,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U32 x, y;
from_region_handle(region_handle, &x, &y);
LL_ERRS() << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL;
LL_WARNS("UpdateFail") << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL;
return retval;
}
@ -1290,8 +1304,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// </FS:CR> Aurora Sim
const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight();
const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight();
S32 length;
S32 count;
S32 length = 0;
S32 count = 0;
S32 this_update_precision = 32; // in bits
// Temporaries, because we need to compare w/ previous to set dirty flags...
@ -1352,6 +1366,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
length = llmin(length, MAX_OBJECT_BINARY_DATA_SIZE); // getBinaryDataFast() safely fills the buffer to max_size
mTotalCRC = crc;
// Might need to update mSourceMuted here to properly pick up new radius
@ -1371,20 +1386,22 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
setClickAction(click_action);
count = 0;
LLVector4 collision_plane;
count = 0;
LLVector4 collision_plane;
switch(length)
{
case (60 + 16):
case OBJECTDATA_FIELD_SIZE_140:
case OBJECTDATA_FIELD_SIZE_76:
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
case 60:
case OBJECTDATA_FIELD_SIZE_124:
case OBJECTDATA_FIELD_SIZE_60:
this_update_precision = 32;
// this is a terse update
// this is a full precision update
// pos
htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
@ -1409,117 +1426,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
resetRot();
}
setAngularVelocity(new_angv);
count += sizeof(LLVector3);
#if LL_DARWIN
if (length == 76)
if (length == OBJECTDATA_FIELD_SIZE_76 ||
length == OBJECTDATA_FIELD_SIZE_140)
{
setAngularVelocity(LLVector3::zero);
}
#endif
break;
case(32 + 16):
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
case 32:
this_update_precision = 16;
test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
// This is a terse 16 update, so treat data as an array of U16's.
#ifdef LL_BIG_ENDIAN
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
#endif
count += sizeof(U16)*3;
new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
#endif
count += sizeof(U16)*3;
setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
U16_to_F32(val[VY], -size, size),
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
#endif
count += sizeof(U16)*3;
setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
U16_to_F32(val[VY], -size, size),
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4);
val = valswizzle;
#else
val = (U16 *) &data[count];
#endif
count += sizeof(U16)*4;
new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
#ifdef LL_BIG_ENDIAN
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
#endif
new_angv.setVec(U16_to_F32(val[VX], -size, size),
U16_to_F32(val[VY], -size, size),
U16_to_F32(val[VZ], -size, size));
if (new_angv.isExactlyZero())
{
// reset rotation time
resetRot();
}
setAngularVelocity(new_angv);
break;
case 16:
this_update_precision = 8;
test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
// this is a terse 8 update
new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
setVelocity(U8_to_F32(data[3], -size, size),
U8_to_F32(data[4], -size, size),
U8_to_F32(data[5], -size, size) );
setAcceleration(U8_to_F32(data[6], -size, size),
U8_to_F32(data[7], -size, size),
U8_to_F32(data[8], -size, size) );
new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
new_angv.setVec(U8_to_F32(data[13], -size, size),
U8_to_F32(data[14], -size, size),
U8_to_F32(data[15], -size, size) );
if (new_angv.isExactlyZero())
{
// reset rotation time
resetRot();
}
setAngularVelocity(new_angv);
break;
// length values 48, 32 and 16 were once in viewer code but
// are never sent by the SL simulator
default:
LL_WARNS("UpdateFail") << "Unexpected ObjectData buffer size " << length
<< " for " << getID() << " with OUT_FULL message" << LL_ENDL;
}
////////////////////////////////////////////////////
@ -1553,20 +1474,45 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (mData)
{
delete [] mData;
}
mData = NULL;
}
// Check for appended generic data
S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
if (data_size <= 0)
{
mData = NULL;
}
else
{
// ...has generic data
mData = new U8[data_size];
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
}
// Dec 2023 new generic data:
// Trees work as before, this field contains genome data
// Not a tree: root objects send 1 byte with the number of
// total prims in the linkset
// If the generic data size is zero, then number of prims is 1
//
// Viewers should not check for specific data sizes exactly, but if
// the field has data, process it from the start and ignore the remainder.
// Check for appended generic data
const S32 GENERIC_DATA_BUFFER_SIZE = 16;
S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
if (data_size > 0)
{ // has generic data
if (getPCode() == LL_PCODE_LEGACY_TREE || getPCode() == LL_PCODE_TREE_NEW)
{
mData = new U8[data_size];
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
LL_DEBUGS("NewObjectData") << "Read " << data_size << " bytes tree genome data for " << getID() << ", pcode "
<< getPCodeString() << ", value " << (S32) mData[0] << LL_ENDL;
}
else
{ // Extract number of prims
U8 generic_data[GENERIC_DATA_BUFFER_SIZE];
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data,
&generic_data[0], llmin(data_size, GENERIC_DATA_BUFFER_SIZE), block_num);
// This is sample code to extract the number of prims
// Future viewers should use it for their own purposes
if (!isAvatar())
{
S32 num_prims = (S32) generic_data[0];
LL_DEBUGS("NewObjectData") << "Root prim " << getID() << " has "
<< num_prims << " prims in linkset" << LL_ENDL;
}
}
}
S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
if (text_size > 1)
@ -1668,60 +1614,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
#endif
length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
count = 0;
length = llmin(length, MAX_OBJECT_BINARY_DATA_SIZE); // getBinaryDataFast() safely fills the buffer to max_size
count = 0;
LLVector4 collision_plane;
switch(length)
{
case(60 + 16):
case OBJECTDATA_FIELD_SIZE_80:
case OBJECTDATA_FIELD_SIZE_48:
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
case 60:
// this is a terse 32 update
// pos
this_update_precision = 32;
htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// vel
htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// acc
htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// theta
{
LLVector3 vec;
htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
new_rot.unpackFromVector3(vec);
}
count += sizeof(LLVector3);
// omega
htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
if (new_angv.isExactlyZero())
{
// reset rotation time
resetRot();
}
setAngularVelocity(new_angv);
#if LL_DARWIN
if (length == 76)
{
setAngularVelocity(LLVector3::zero);
}
#endif
break;
case(32 + 16):
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
case 32:
// this is a terse 16 update
this_update_precision = 16;
case OBJECTDATA_FIELD_SIZE_64:
case OBJECTDATA_FIELD_SIZE_32:
// this is a terse 16 bit quantized update
this_update_precision = 16;
test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
@ -1781,33 +1690,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setAngularVelocity(new_angv);
break;
case 16:
// this is a terse 8 update
this_update_precision = 8;
test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
setVelocity(U8_to_F32(data[3], -size, size),
U8_to_F32(data[4], -size, size),
U8_to_F32(data[5], -size, size) );
setAcceleration(U8_to_F32(data[6], -size, size),
U8_to_F32(data[7], -size, size),
U8_to_F32(data[8], -size, size) );
new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
new_angv.set(U8_to_F32(data[13], -size, size),
U8_to_F32(data[14], -size, size),
U8_to_F32(data[15], -size, size) );
setAngularVelocity(new_angv);
break;
}
// Previous viewers had code for length 76, 60 or 16 byte length
// with full precision or 8 bit quanitzation, but the
// SL servers will never send those data formats. If you ever see this
// warning in Second Life, please file a bug report
default:
LL_WARNS("UpdateFail") << "Unexpected ObjectData buffer size " << length << " for " << getID()
<< " with OUT_FULL message" << LL_ENDL;
}
U8 state;
mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
@ -1816,13 +1706,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
default:
LL_WARNS("UpdateFail") << "Unknown uncompressed update type " << update_type << " for " << getID() << LL_ENDL;
break;
}
}
else
{
// handle the compressed case
// handle the compressed case - have dp datapacker
LLUUID sound_uuid;
LLUUID owner_id;
F32 gain = 0;
@ -2082,6 +1972,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
default:
LL_WARNS("UpdateFail") << "Unknown compressed update type " << update_type << " for " << getID() << LL_ENDL;
break;
}
}
@ -2129,7 +2020,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (sent_parentp && sent_parentp->getParent() == this)
{
// Try to recover if we attempt to attach a parent to its child
LL_WARNS() << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << LL_ENDL;
LL_WARNS("UpdateFail") << "Attempt to attach a parent to it's child: " << this->getID() << " to "
<< sent_parentp->getID() << LL_ENDL;
this->removeChild(sent_parentp);
sent_parentp->setDrawableParent(NULL);
}
@ -2153,7 +2045,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
if (mDrawable->isDead() || !mDrawable->getVObj())
{
LL_WARNS() << "Drawable is dead or no VObj!" << LL_ENDL;
LL_WARNS("UpdateFail") << "Drawable is dead or no VObj!" << LL_ENDL;
sent_parentp->addChild(this);
}
else
@ -2163,9 +2055,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// Bad, we got a cycle somehow.
// Kill both the parent and the child, and
// set cache misses for both of them.
LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL;
LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL;
LL_WARNS() << "Adding to cache miss list" << LL_ENDL;
LL_WARNS("UpdateFail") << "Attempting to recover from parenting cycle! "
<< "Killing " << sent_parentp->getID() << " and " << getID()
<< ", Adding to cache miss list" << LL_ENDL;
setParent(NULL);
sent_parentp->setParent(NULL);
getRegion()->addCacheMissFull(getLocalID());
@ -2868,22 +2760,6 @@ void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& frame_tim
BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
{
delete [] mData;
if (datap)
{
mData = new U8[data_size];
if (!mData)
{
return FALSE;
}
memcpy(mData, datap, data_size); /* Flawfinder: ignore */
}
return TRUE;
}
// delete an item in the inventory, but don't tell the server. This is
// used internally by remove, update, and savescript.
// This will only delete the first item with an item_id in the list

View File

@ -799,8 +799,6 @@ protected:
static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0);
BOOL setData(const U8 *datap, const U32 data_size);
// Hide or show HUD, icon and particles
void hideExtraDisplayItems( BOOL hidden );

View File

@ -351,6 +351,8 @@ void LLViewerParcelOverlay::updateOverlayTexture()
const LLColor4U for_sale = LLUIColorTable::instance().getColor("PropertyColorForSale").get();
const LLColor4U auction = LLUIColorTable::instance().getColor("PropertyColorAuction").get();
LLImageDataLock lock(mImageRaw);
// Create the base texture.
U8 *raw = mImageRaw->getData();
const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge;

View File

@ -299,6 +299,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps)
{
LLImageDataSharedLock lock(raw);
LLViewerFetchedTexture* ret = new LLViewerFetchedTexture(raw, type, usemipmaps);
gTextureList.addImage(ret, TEX_LIST_STANDARD);
return ret;
@ -2994,6 +2995,8 @@ void LLViewerFetchedTexture::saveRawImage()
return;
}
LLImageDataSharedLock lock(mRawImage);
mSavedRawDiscardLevel = mRawDiscardLevel;
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{

View File

@ -1269,6 +1269,8 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image,
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageDataSharedLock lock(raw_image);
// make a copy, since convertToUploadFile scales raw image
LLPointer<LLImageRaw> scale_image = new LLImageRaw(
raw_image->getData(),
@ -1374,6 +1376,8 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions, bool force_square, bool force_lossless)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageDataLock lock(raw_image);
if (force_square)
{
S32 biggest_side = llmax(raw_image->getWidth(), raw_image->getHeight());

View File

@ -6047,6 +6047,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
return FALSE;
}
//check if there is enough memory for the snapshot image
if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
{
@ -6175,6 +6176,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
image_buffer_x = llfloor(snapshot_width * scale_factor) ;
image_buffer_y = llfloor(snapshot_height * scale_factor) ;
}
LLImageDataLock lock(raw);
if ((image_buffer_x > 0) && (image_buffer_y > 0))
{
raw->resize(image_buffer_x, image_buffer_y, 3);
@ -6477,6 +6481,8 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
display(do_rebuild, zoom, subfield, for_snapshot);
}
LLImageDataSharedLock lock(raw);
glReadPixels(
0, 0,
image_width,

View File

@ -9857,7 +9857,7 @@ void LLVOAvatar::clearChat()
}
void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index)
void LLVOAvatar::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index)
{
if (index >= BAKED_NUM_INDICES)
{
@ -10254,7 +10254,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
//mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0);
}
// Parse the AppearanceData field, if any.
// Parse the AppearanceHover field, if any.
contents.mHoverOffsetWasSet = false;
if (mesgsys->has(_PREHASH_AppearanceHover))
{
@ -10264,7 +10264,24 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
contents.mHoverOffset = hover;
contents.mHoverOffsetWasSet = true;
}
// Get attachment info, if sent
LLUUID attachment_id;
U8 attach_point;
S32 attach_count = mesgsys->getNumberOfBlocksFast(_PREHASH_AttachmentBlock);
LL_DEBUGS("AVAppearanceAttachments") << "Agent " << getID() << " has "
<< attach_count << " attachments" << LL_ENDL;
for (S32 attach_i = 0; attach_i < attach_count; attach_i++)
{
mesgsys->getUUIDFast(_PREHASH_AttachmentBlock, _PREHASH_ID, attachment_id, attach_i);
mesgsys->getU8Fast(_PREHASH_AttachmentBlock, _PREHASH_AttachmentPoint, attach_point, attach_i);
LL_DEBUGS("AVAppearanceAttachments") << "AV " << getID() << " has attachment " << attach_i << " "
<< (attachment_id.isNull() ? "pending" : attachment_id.asString())
<< " on point " << (S32)attach_point << LL_ENDL;
// To do - store and use this information as needed
}
// Parse visual params, if any.
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams");
@ -10825,6 +10842,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
{
if(aux_src && aux_src->getComponents() == 1)
{
LLImageDataSharedLock lock(aux_src);
if (!aux_src->getData())
{
// <FS:Ansariel> FIRE-16122: Don't crash if we didn't receive any data

View File

@ -614,7 +614,7 @@ public:
// Morph masks
//--------------------------------------------------------------------
public:
/*virtual*/ void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
/*virtual*/ void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);

View File

@ -5476,7 +5476,7 @@ std::string LLVivoxVoiceClient::nameFromID(const LLUUID &uuid)
LLStringUtil::replaceChar(result, '+', '-');
LLStringUtil::replaceChar(result, '/', '_');
// If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
// If you need to transform a GUID to this form on the macOS command line, this will do so:
// echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
// The reverse transform can be done with:

Some files were not shown because too many files have changed in this diff Show More