summaryrefslogtreecommitdiff
path: root/indra/llimage/llimage.cpp
diff options
context:
space:
mode:
authorAlexander Gavriliuk <alexandrgproductengine@lindenlab.com>2023-12-15 18:26:14 +0100
committerGuru <alexandrgproductengine@lindenlab.com>2023-12-21 19:12:52 +0100
commit74c8b028d42a8c5b080bb861e427f38cedd4ad7c (patch)
tree067f8e85fd7b4f91903ad2aa32630b7dd0364099 /indra/llimage/llimage.cpp
parente104f7ce0291ed1f7ab170714e319408bf076221 (diff)
SL-20743 Use LLMutex in LLImageBase for internal data thread-safety
Diffstat (limited to 'indra/llimage/llimage.cpp')
-rw-r--r--indra/llimage/llimage.cpp131
1 files changed, 105 insertions, 26 deletions
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;
}