summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llappearance/llavatarappearance.h2
-rw-r--r--indra/llappearance/llpolymorph.cpp4
-rw-r--r--indra/llappearance/llpolymorph.h4
-rw-r--r--indra/llappearance/lltexlayer.cpp2
-rw-r--r--indra/llappearance/lltexlayer.h2
-rw-r--r--indra/llcommon/llapr.cpp2
-rw-r--r--indra/llcommon/llapr.h2
-rw-r--r--indra/llcommon/llmutex.cpp186
-rw-r--r--indra/llcommon/llmutex.h79
-rw-r--r--indra/llimage/llimage.cpp131
-rw-r--r--indra/llimage/llimage.h73
-rw-r--r--indra/llimage/llimagebmp.cpp20
-rw-r--r--indra/llimage/llimagebmp.h8
-rw-r--r--indra/llimage/llimagedxt.cpp15
-rw-r--r--indra/llimage/llimagefilter.cpp4
-rw-r--r--indra/llimage/llimagej2c.cpp35
-rw-r--r--indra/llimage/llimagejpeg.cpp12
-rw-r--r--indra/llimage/llimagejpeg.h2
-rw-r--r--indra/llimage/llimagepng.cpp8
-rw-r--r--indra/llimage/llimagetga.cpp15
-rw-r--r--indra/llimage/llimageworker.cpp13
-rw-r--r--indra/llimage/llpngwrapper.cpp2
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp8
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp10
-rw-r--r--indra/llrender/llcubemap.cpp3
-rw-r--r--indra/llrender/llfontfreetype.cpp1
-rw-r--r--indra/llrender/llimagegl.cpp2
-rw-r--r--indra/newview/lldrawpoolbump.cpp8
-rw-r--r--indra/newview/llfasttimerview.cpp2
-rw-r--r--indra/newview/llfloater360capture.cpp4
-rw-r--r--indra/newview/llfloaterauction.cpp2
-rw-r--r--indra/newview/llfloatercolorpicker.cpp2
-rw-r--r--indra/newview/llfloaterimagepreview.cpp1
-rw-r--r--indra/newview/llinventorygallerymenu.cpp2
-rw-r--r--indra/newview/llmaterialeditor.cpp2
-rw-r--r--indra/newview/llmeshrepository.cpp20
-rw-r--r--indra/newview/llnetmap.cpp2
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp10
-rw-r--r--indra/newview/lltexturecache.cpp11
-rw-r--r--indra/newview/lltexturecache.h2
-rw-r--r--indra/newview/lltexturefetch.cpp7
-rw-r--r--indra/newview/lltinygltfhelper.cpp9
-rw-r--r--indra/newview/llviewerassetupload.cpp2
-rwxr-xr-xindra/newview/llviewerparceloverlay.cpp2
-rw-r--r--indra/newview/llviewertexture.cpp3
-rw-r--r--indra/newview/llviewertexturelist.cpp4
-rw-r--r--indra/newview/llviewerwindow.cpp6
-rw-r--r--indra/newview/llvoavatar.cpp4
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvosky.cpp4
-rw-r--r--indra/newview/llvosky.h2
-rw-r--r--indra/newview/llvovolume.cpp6
-rw-r--r--indra/newview/llwebprofile.cpp4
53 files changed, 631 insertions, 137 deletions
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index e3444efcf6..787235b235 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -232,7 +232,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
** **
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index 965b999bd4..223b2b7f1c 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -659,7 +659,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;
@@ -780,7 +780,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;
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
index 29cd373636..954f01811a 100644
--- a/indra/llappearance/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -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()
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index ff894eeed3..e426615f1c 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -528,7 +528,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);
}
diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h
index 74b421d3ee..ff95d7f5e9 100644
--- a/indra/llappearance/lltexlayer.h
+++ b/indra/llappearance/lltexlayer.h
@@ -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();
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 575c524219..834b0e7a3a 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -571,7 +571,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;
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 565d7cfb63..f5717ea75e 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -193,7 +193,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
//*******************************************************************************************************************************
};
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index 0273dd5970..f56c2d08a6 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -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,185 @@ 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();
+ if (mLockingThreads.size() == 1 && mLockingThreads.begin()->first == current_thread)
+ {
+ mLockingThreads.begin()->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 +335,10 @@ void LLCondition::broadcast()
}
-
+//---------------------------------------------------------------------
+//
+// LLMutexTrylock
+//
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
: mMutex(mutex),
mLocked(false)
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 0d70da6178..077f810d61 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -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.
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 7ac80825b5..520d7b4fd9 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -614,7 +614,6 @@ const std::string& LLImage::getLastError()
//static
void LLImage::setLastError(const std::string& message)
{
- LLMutexLock m(sMutex);
sLastErrorMessage = message;
}
@@ -754,7 +753,7 @@ U8* LLImageBase::reallocateData(S32 size)
return mData;
}
-const U8* LLImageBase::getData() const
+const U8* LLImageBase::getData() const
{
if(mBadBufferAllocation)
{
@@ -765,7 +764,7 @@ const U8* LLImageBase::getData() const
return mData;
} // read only
-U8* LLImageBase::getData()
+U8* LLImageBase::getData()
{
if(mBadBufferAllocation)
{
@@ -778,7 +777,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)
@@ -854,6 +853,8 @@ LLImageRaw::~LLImageRaw()
// virtual
U8* LLImageRaw::allocateData(S32 size)
{
+ LLImageDataLock lock(this);
+
U8* res = LLImageBase::allocateData(size);
return res;
}
@@ -861,12 +862,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);
}
@@ -874,11 +879,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 ;
@@ -892,6 +901,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;
@@ -907,6 +918,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;
@@ -934,6 +947,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())
{
@@ -974,6 +990,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);
@@ -991,6 +1009,8 @@ void LLImageRaw::verticalFlip()
bool LLImageRaw::optimizeAwayAlpha()
{
+ LLImageDataLock lock(this);
+
if (getComponents() == 4)
{
U8* data = getData();
@@ -1028,6 +1048,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);
@@ -1037,6 +1059,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);
@@ -1086,6 +1110,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);
@@ -1093,6 +1119,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 )
{
@@ -1101,10 +1128,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;
@@ -1143,12 +1173,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();
@@ -1170,14 +1202,16 @@ 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);
+
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
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();
while( pixels-- )
@@ -1207,10 +1241,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;
@@ -1221,7 +1258,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++ )
{
@@ -1238,6 +1275,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;
@@ -1275,16 +1314,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;
@@ -1330,10 +1374,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()) );
@@ -1343,7 +1389,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()) );
@@ -1355,7 +1401,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()) );
@@ -1367,15 +1413,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++ )
{
@@ -1389,15 +1437,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++ )
{
@@ -1412,10 +1463,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;
@@ -1457,6 +1511,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)
{
@@ -1543,6 +1599,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)
{
@@ -1588,7 +1646,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 );
@@ -1615,7 +1673,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;
@@ -1703,7 +1761,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 );
@@ -1799,8 +1857,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: ";
@@ -2113,6 +2175,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()
sGlobalFormattedMemory += getDataSize();
return res;
@@ -2121,6 +2185,8 @@ U8* LLImageFormatted::allocateData(S32 size)
// virtual
U8* LLImageFormatted::reallocateData(S32 size)
{
+ LLImageDataLock lock(this);
+
sGlobalFormattedMemory -= getDataSize();
U8* res = LLImageBase::reallocateData(size);
sGlobalFormattedMemory += getDataSize();
@@ -2130,6 +2196,8 @@ U8* LLImageFormatted::reallocateData(S32 size)
// virtual
void LLImageFormatted::deleteData()
{
+ LLImageDataLock lock(this);
+
if (mDecoding)
{
LL_ERRS() << "LLImageFormatted::deleteData() is called during decoding" << LL_ENDL;
@@ -2159,6 +2227,8 @@ void LLImageFormatted::sanityCheck()
bool LLImageFormatted::copyData(U8 *data, S32 size)
{
+ LLImageDataLock lock(this);
+
if ( data && ((data != getData()) || (size != getDataSize())) )
{
deleteData();
@@ -2171,6 +2241,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();
@@ -2184,6 +2256,8 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
{
if (data)
{
+ LLImageDataLock lock(this);
+
if (!getData())
{
setData(data, size);
@@ -2225,6 +2299,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)
@@ -2262,8 +2339,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;
}
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 8f9e1b3c54..cc6a58f417 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -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,10 +171,27 @@ 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)
+ {
+ }
+ };
};
+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
{
@@ -231,51 +248,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 );
+ void composite( const LLImageRaw* src );
+protected:
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
- void compositeScaled4onto3( LLImageRaw* src );
+ void compositeScaled4onto3( const LLImageRaw* src );
// Src and dst are same size. Src has 4 components. Dst has 3 components.
- void compositeUnscaled4onto3( LLImageRaw* src );
+ 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 );
-protected:
// 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) ;
@@ -283,7 +300,7 @@ public:
static S32 sRawImageCount;
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.
@@ -356,7 +373,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;
};
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 90b7272efa..d26d160537 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -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;
diff --git a/indra/llimage/llimagebmp.h b/indra/llimage/llimagebmp.h
index 6a5fa4697d..295f96e541 100644
--- a/indra/llimage/llimagebmp.h
+++ b/indra/llimage/llimagebmp.h
@@ -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 );
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 36317a5ba8..f4bb3bb120 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -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();
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 41adc7be9a..61c2e1d742 100644
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -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)
{
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index a4957466d4..a06c461107 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -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))
{
@@ -158,22 +160,26 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
LLTimer elapsed;
resetLastError();
- mDecoding = true;
bool res;
- // 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);
+ LLImageDataLock lock(this);
+
+ mDecoding = true;
+ // 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)
@@ -414,9 +420,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();
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index 32a5472ec8..a35171601a 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -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);
self->allocateData(file_bytes);
@@ -484,6 +491,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:
diff --git a/indra/llimage/llimagejpeg.h b/indra/llimage/llimagejpeg.h
index 7a849a8421..d674b40b8f 100644
--- a/indra/llimage/llimagejpeg.h
+++ b/indra/llimage/llimagejpeg.h
@@ -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
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index c4b98d8260..5d956bfb4e 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -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());
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index 88bdae9b80..290c0da4bf 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -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()))
{
@@ -642,7 +647,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());
@@ -1061,6 +1069,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!");
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index c1ee052997..44749343e1 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -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())
@@ -177,7 +186,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)
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index cad7c00042..27e23b577b 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -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))
{
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 6c06c6de38..482d2a2c8a 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -489,6 +489,9 @@ public:
bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut)
{
+ LLImageDataSharedLock lockIn(&rawImageIn);
+ LLImageDataLock lockOut(&compressedImageOut);
+
setImage(rawImageIn);
encoder = opj_create_compress(OPJ_CODEC_J2K);
@@ -733,6 +736,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);
U32 image_channels = 0;
@@ -820,6 +826,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;
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index d96cd105dd..8b34592535 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -277,6 +277,8 @@ void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
// as well, when that still existed, with keep_codestream true and MODE_FAST.
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
{
+ LLImageDataLock lock(&base);
+
S32 data_size = base.getDataSize();
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
@@ -512,6 +514,10 @@ 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;
@@ -529,7 +535,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();
@@ -579,7 +585,7 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
mCodeStreamp.get()));
}
// Do the actual processing
- F32 remaining_time = limit_time ? static_cast<F32>(decode_time - decode_timer.getElapsedTimeF32()) : 0.0f;
+ 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, limit_time))
{
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 254288a86e..26bd925f03 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -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();
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index e964d1586f..11a379d70f 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -669,6 +669,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));
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index c6fd824c4e..bbedcf360c 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1887,6 +1887,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
}
//-----------------------------------------------------------------------------------------------
+ LLImageDataLock lock(imageraw);
+
if (is_compressed)
{
LLGLint glbytes;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index a0ce0ef6cf..77a196380b 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -849,11 +849,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();
@@ -911,6 +914,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);
@@ -933,7 +937,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();
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 5b8ca6c49c..9cf9f45bfb 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -448,6 +448,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());
diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index 2c638fa959..a0890b7f9d 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -360,6 +360,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
@@ -410,6 +412,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();
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 9813156bf2..6996224dcb 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -190,6 +190,8 @@ void LLFloaterAuction::onClickSnapshot(void* data)
if (success)
{
+ LLImageDataLock lock(raw);
+
self->mTransactionID.generate();
self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID());
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index ba91277c79..af96fdbcfd 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -135,6 +135,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 )
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index ba0f97e2e1..5e7978e224 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -789,6 +789,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);
}
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index c8ac73b838..e966514955 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -70,7 +70,7 @@ void modify_outfit(BOOL append, const LLUUID& cat_id, LLInventoryModel* model)
if (items.size() > max_items())
{
LLSD args;
- args["AMOUNT"] = llformat("%d", static_cast<U32>(max_items));
+ args["AMOUNT"] = llformat("%u", max_items());
LLNotificationsUtil::add("TooManyWearables", args);
return;
}
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 5e78e15c72..415543eb37 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -3424,6 +3424,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)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 01d6469010..2622c23314 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -2360,17 +2360,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 &&
@@ -2514,17 +2516,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 &&
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 0ba3c3d691..e7f9d0e5df 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -345,6 +345,7 @@ void LLNetMap::draw()
mObjectImageCenterGlobal = viewPosToGlobal(llfloor(new_center.mV[VX]), llfloor(new_center.mV[VY]));
// Create the base texture.
+ LLImageDataLock lock(mObjectRawImagep);
U8 *default_texture = mObjectRawImagep->getData();
memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
@@ -915,6 +916,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
return;
}
+ LLImageDataLock lock(mObjectRawImagep);
U8 *datap = mObjectRawImagep->getData();
S32 neg_radius = diameter / 2;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index b7a1832b17..bb7c73b59f 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -766,6 +766,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(),
@@ -825,13 +827,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
@@ -978,6 +982,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;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index a14d4f7a30..dfaeeaab62 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -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)
@@ -1961,7 +1961,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)
{
@@ -2047,6 +2047,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())
{
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 43e91b3e4c..cba45393f9 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -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);
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 38c9b3717d..4ecabf666b 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1699,7 +1699,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFormattedImage = new LLImageJ2C; // default
}
}
-
+
+ LLImageDataLock lock(mFormattedImage);
+
if (mHaveAllData) //the image file is fully loaded.
{
mFileSize = total_size;
@@ -1857,6 +1859,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.
{
diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp
index 999be07dba..cee18489f0 100644
--- a/indra/newview/lltinygltfhelper.cpp
+++ b/indra/newview/lltinygltfhelper.cpp
@@ -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);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index a2b0b04092..dcb14eb383 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -654,6 +654,8 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
{
setItemId(itemId);
+ LLImageDataSharedLock lock(image);
+
EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
switch (codec)
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 785c84c38d..e1f372d396 100755
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -344,6 +344,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;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index ec6f2c848f..820a051782 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -285,6 +285,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;
@@ -2905,6 +2906,8 @@ void LLViewerFetchedTexture::saveRawImage()
return;
}
+ LLImageDataSharedLock lock(mRawImage);
+
mSavedRawDiscardLevel = mRawDiscardLevel;
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index f898fb7142..7931b74b11 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1252,6 +1252,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(),
@@ -1357,6 +1359,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());
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ba2b6e1c7c..27ec8d9376 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4890,6 +4890,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
{
@@ -5008,6 +5009,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);
@@ -5266,6 +5270,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,
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index fee00eb6f4..8ab7cda28c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8894,7 +8894,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)
{
@@ -9770,6 +9770,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
{
if(aux_src && aux_src->getComponents() == 1)
{
+ LLImageDataSharedLock lock(aux_src);
+
if (!aux_src->getData())
{
LL_ERRS() << "No auxiliary source (morph mask) data for image id " << id << LL_ENDL;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 48bfd5293a..759d02959c 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -590,7 +590,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);
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 20621665fa..db197335f2 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -166,6 +166,7 @@ S32 LLSkyTex::getWhich(const BOOL curr)
void LLSkyTex::initEmpty(const S32 tex)
{
+ LLImageDataLock lock(mImageRaw[tex]);
U8* data = mImageRaw[tex]->getData();
for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
{
@@ -187,7 +188,8 @@ void LLSkyTex::initEmpty(const S32 tex)
void LLSkyTex::create()
{
- U8* data = mImageRaw[sCurrent]->getData();
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
+ const U8* data = mImageRaw[sCurrent]->getData();
for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
{
for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j)
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 5941ab6e3b..509ad97786 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -101,6 +101,7 @@ protected:
void setPixel(const LLColor4U &col, const S32 i, const S32 j)
{
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
*pix = col.asRGBA();
@@ -109,6 +110,7 @@ protected:
LLColor4U getPixel(const S32 i, const S32 j)
{
LLColor4U col;
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
col.fromRGBA( *pix );
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index ec2f490742..8846e30145 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1311,11 +1311,13 @@ void LLVOVolume::sculpt()
}
}
else
- {
+ {
+ LLImageDataSharedLock lock(raw_image);
+
sculpt_height = raw_image->getHeight();
sculpt_width = raw_image->getWidth();
sculpt_components = raw_image->getComponents();
-
+
sculpt_data = raw_image->getData();
if(LLViewerTextureManager::sTesterp)
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index f2d7e4585a..ade9bbd847 100644
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -239,10 +239,12 @@ LLCore::BufferArray::ptr_t LLWebProfile::buildPostData(const LLSD &data, LLPoint
<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
<< "Content-Type: image/png\r\n\r\n";
+ LLImageDataSharedLock lock(image);
+
// Insert the image data.
//char *datap = (char *)(image->getData());
//bas.write(datap, image->getDataSize());
- U8* image_data = image->getData();
+ const U8* image_data = image->getData();
for (S32 i = 0; i < image->getDataSize(); ++i)
{
bas << image_data[i];