From 7f9438ed2b1e91aff615673ca2d97a3f300910f6 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Thu, 14 Dec 2023 23:25:11 +0100 Subject: SL-3508 Crash in LLKDUDecodeState::processTileDecode --- indra/llimage/llimage.cpp | 4 ++++ indra/llimage/llimagej2c.cpp | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 031471d1fe..7ac80825b5 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -2130,6 +2130,10 @@ U8* LLImageFormatted::reallocateData(S32 size) // virtual void LLImageFormatted::deleteData() { + if (mDecoding) + { + LL_ERRS() << "LLImageFormatted::deleteData() is called during decoding" << LL_ENDL; + } sGlobalFormattedMemory -= getDataSize(); LLImageBase::deleteData(); } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 8dba1641a6..a4957466d4 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -157,10 +157,10 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLTimer elapsed; - bool res = true; - resetLastError(); + mDecoding = true; + bool res; // Check to make sure that this instance has been initialized with data if (!getData() || (getDataSize() < 16)) { @@ -171,7 +171,6 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir { // Update the raw discard level updateRawDiscardLevel(); - mDecoding = true; res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count); } @@ -181,12 +180,21 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir { // 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()) { -- cgit v1.2.3 From 74c8b028d42a8c5b080bb861e427f38cedd4ad7c Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 15 Dec 2023 18:26:14 +0100 Subject: SL-20743 Use LLMutex in LLImageBase for internal data thread-safety --- indra/llimage/llimage.cpp | 131 ++++++++++++++++++++++++++++++++-------- indra/llimage/llimage.h | 73 +++++++++++++--------- indra/llimage/llimagebmp.cpp | 20 ++++-- indra/llimage/llimagebmp.h | 8 +-- indra/llimage/llimagedxt.cpp | 15 ++++- indra/llimage/llimagefilter.cpp | 4 +- indra/llimage/llimagej2c.cpp | 35 ++++++----- indra/llimage/llimagejpeg.cpp | 12 +++- indra/llimage/llimagejpeg.h | 2 - indra/llimage/llimagepng.cpp | 8 +++ indra/llimage/llimagetga.cpp | 15 ++++- indra/llimage/llimageworker.cpp | 13 +++- indra/llimage/llpngwrapper.cpp | 2 + 13 files changed, 251 insertions(+), 87 deletions(-) (limited to 'indra/llimage') 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 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::duplicate() return this; //nobody else refences to this image, no need to duplicate. } + LLImageDataSharedLock lock(this); + //make a duplicate LLPointer 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; igetComponents() ); 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 LLImageRaw::scaled(S32 new_width, S32 new_height) { LLPointer result; + LLImageDataLock lock(this); + S32 components = getComponents(); if (components != 1 && components != 3 && components != 4) { @@ -1588,7 +1646,7 @@ LLPointer 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 + class DataLock : LLSharedMutexLockTemplate + { + public: + DataLock(const LLImageBase* image) + : LLSharedMutexLockTemplate(image ? &image->mDataMutex : nullptr) + { + } + }; }; +using LLImageDataLock = LLImageBase::DataLock; +using LLImageDataSharedLock = LLImageBase::DataLock; + // Raw representation of an image (used for textures, and other uncompressed formats class LLImageRaw : public LLImageBase { @@ -231,51 +248,51 @@ public: LLPointer 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& 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 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(mWidth), static_cast(mHeight), mChannels)) { -- cgit v1.2.3 From 981470e0a1f4d3157d6528b3966922d825e77fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 9 Feb 2024 01:56:54 +0100 Subject: llimage: BOOL (int) to real bool --- indra/llimage/llimagedimensionsinfo.cpp | 2 +- indra/llimage/llimageworker.cpp | 16 ++++++++-------- indra/llimage/llimageworker.h | 2 +- indra/llimage/llpngwrapper.cpp | 20 ++++++++++---------- indra/llimage/llpngwrapper.h | 6 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index 97b543f3b6..234a504a14 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -197,7 +197,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() jpeg_create_decompress (&cinfo); jpeg_stdio_src (&cinfo, fp); - jpeg_read_header (&cinfo, TRUE); + jpeg_read_header (&cinfo, true); cinfo.out_color_space = JCS_RGB; jpeg_start_decompress (&cinfo); diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 44749343e1..dc99b34c57 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -35,7 +35,7 @@ class ImageRequest { public: ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, + S32 discard, bool needs_aux, const LLPointer& responder); virtual ~ImageRequest(); @@ -48,12 +48,12 @@ private: // input LLPointer mFormattedImage; S32 mDiscardLevel; - BOOL mNeedsAux; + bool mNeedsAux; // output LLPointer mDecodedImageRaw; LLPointer mDecodedImageAux; - BOOL mDecodedRaw; - BOOL mDecodedAux; + bool mDecodedRaw; + bool mDecodedAux; LLPointer mResponder; }; @@ -87,7 +87,7 @@ size_t LLImageDecodeThread::getPending() LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( const LLPointer& image, S32 discard, - BOOL needs_aux, + bool needs_aux, const LLPointer& responder) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -124,13 +124,13 @@ LLImageDecodeThread::Responder::~Responder() //---------------------------------------------------------------------------- ImageRequest::ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, + S32 discard, bool needs_aux, const LLPointer& responder) : mFormattedImage(image), mDiscardLevel(discard), mNeedsAux(needs_aux), - mDecodedRaw(FALSE), - mDecodedAux(FALSE), + mDecodedRaw(false), + mDecodedAux(false), mResponder(responder) { } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index ca4c0d93d0..c24fd31f0f 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -49,7 +49,7 @@ public: // meant to resemble LLQueuedThread::handle_t typedef U32 handle_t; handle_t decodeImage(const LLPointer& image, - S32 discard, BOOL needs_aux, + S32 discard, bool needs_aux, const LLPointer& responder); size_t getPending(); size_t update(F32 max_time_ms); diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 27e23b577b..baf1330011 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -70,7 +70,7 @@ LLPngWrapper::~LLPngWrapper() } // Checks the src for a valid PNG header -BOOL LLPngWrapper::isValidPng(U8* src) +bool LLPngWrapper::isValidPng(U8* src) { const int PNG_BYTES_TO_CHECK = 8; @@ -78,10 +78,10 @@ BOOL LLPngWrapper::isValidPng(U8* src) if (sig != 0) { mErrorMessage = "Invalid or corrupt PNG file"; - return FALSE; + return false; } - return TRUE; + return true; } // Called by the libpng library when a fatal encoding or decoding error @@ -134,7 +134,7 @@ void LLPngWrapper::writeFlush(png_structp png_ptr) // The scanline also begins at the bottom of // the image (per SecondLife conventions) instead of at the top, so we // must assign row-pointers in "reverse" order. -BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop) +bool LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop) { try { @@ -210,18 +210,18 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf { mErrorMessage = msg.what(); releaseResources(); - return (FALSE); + return (false); } catch (std::bad_alloc&) { mErrorMessage = "LLPngWrapper"; releaseResources(); - return (FALSE); + return (false); } // Clean up and return releaseResources(); - return (TRUE); + return (true); } // Do transformations to normalize the input to 8-bpp RGBA @@ -283,7 +283,7 @@ void LLPngWrapper::updateMetaData() // Method to write raw image into PNG at dest. The raw scanline begins // at the bottom of the image per SecondLife conventions. -BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSize) +bool LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSize) { try { @@ -364,11 +364,11 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSiz { mErrorMessage = msg.what(); releaseResources(); - return (FALSE); + return (false); } releaseResources(); - return TRUE; + return true; } // Cleanup various internal structures diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index 8d42317b0f..b17e8d1f40 100644 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -43,9 +43,9 @@ public: S8 mComponents; }; - BOOL isValidPng(U8* src); - BOOL readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL); - BOOL writePng(const LLImageRaw* rawImage, U8* dst, size_t destSize); + bool isValidPng(U8* src); + bool readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL); + bool writePng(const LLImageRaw* rawImage, U8* dst, size_t destSize); U32 getFinalSize(); const std::string& getErrorMessage(); -- cgit v1.2.3 From e160758b5c32f7b4b9622a5c25c7c53070395c7d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Fri, 1 Mar 2024 13:48:46 +0100 Subject: Convert remaining TRUE/FALSE to true/false --- indra/llimage/tests/llimageworker_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llimage') diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 0a97b739b0..b0212af66e 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -150,7 +150,7 @@ namespace tut ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL); // Insert something in the queue bool done = false; - LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done)); + LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, false, new responder_test(&done)); // Verifies we get back a valid handle ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0); // Wait till the thread has time to handle the work order (though it doesn't do much per work order...) -- cgit v1.2.3