summaryrefslogtreecommitdiff
path: root/indra/llimage
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2024-07-27 15:17:57 +0800
committerErik Kundiman <erik@megapahit.org>2024-07-28 08:24:59 +0800
commit96a81b5ecbe3bffb582ded930752c0523df5e80a (patch)
treea87a0bd09fd980562e88150dbfea3819d28d9f12 /indra/llimage
parent06e8f0c443c1ba7858d000c6d695b7e988e02053 (diff)
parented73208eb96b862b97fa285036edea1e792ca3c6 (diff)
Merge remote-tracking branch 'secondlife/release/2024.06-atlasaurus' into 2024.06-atlasaurus
Diffstat (limited to 'indra/llimage')
-rw-r--r--indra/llimage/llimage.cpp181
-rw-r--r--indra/llimage/llimage.h78
-rw-r--r--indra/llimage/llimagebmp.cpp20
-rw-r--r--indra/llimage/llimagebmp.h8
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp2
-rw-r--r--indra/llimage/llimagedxt.cpp15
-rw-r--r--indra/llimage/llimagefilter.cpp30
-rw-r--r--indra/llimage/llimagej2c.cpp41
-rw-r--r--indra/llimage/llimagejpeg.cpp10
-rw-r--r--indra/llimage/llimagejpeg.h2
-rw-r--r--indra/llimage/llimagepng.cpp8
-rw-r--r--indra/llimage/llimagetga.cpp17
-rw-r--r--indra/llimage/llimageworker.cpp39
-rw-r--r--indra/llimage/llimageworker.h2
-rw-r--r--indra/llimage/llpngwrapper.cpp28
-rw-r--r--indra/llimage/llpngwrapper.h6
-rw-r--r--indra/llimage/tests/llimageworker_test.cpp2
17 files changed, 360 insertions, 129 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index da5b531857..ca8a4199e8 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -774,7 +774,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)
@@ -850,6 +850,8 @@ LLImageRaw::~LLImageRaw()
// virtual
U8* LLImageRaw::allocateData(S32 size)
{
+ LLImageDataLock lock(this);
+
U8* res = LLImageBase::allocateData(size);
return res;
}
@@ -857,12 +859,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);
}
@@ -870,11 +876,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 ;
@@ -888,6 +898,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;
@@ -903,6 +915,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;
@@ -930,6 +944,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())
{
@@ -970,6 +987,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);
@@ -1009,6 +1028,8 @@ bool LLImageRaw::checkHasTransparentPixels()
bool LLImageRaw::optimizeAwayAlpha()
{
+ LLImageDataLock lock(this);
+
if (getComponents() == 4)
{
U8* data = getData();
@@ -1074,6 +1095,8 @@ bool LLImageRaw::makeAlpha()
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);
@@ -1083,6 +1106,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);
@@ -1132,6 +1157,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);
@@ -1139,6 +1166,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 )
{
@@ -1147,10 +1175,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;
@@ -1189,12 +1220,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();
@@ -1216,14 +1249,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-- )
@@ -1253,10 +1288,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;
@@ -1267,7 +1305,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++ )
{
@@ -1284,6 +1322,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;
@@ -1345,16 +1385,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;
@@ -1400,10 +1445,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()) );
@@ -1413,7 +1460,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()) );
@@ -1425,7 +1472,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()) );
@@ -1437,15 +1484,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++ )
{
@@ -1459,15 +1508,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++ )
{
@@ -1482,10 +1534,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;
@@ -1527,6 +1582,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)
{
@@ -1613,6 +1670,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)
{
@@ -1658,7 +1717,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 );
@@ -1685,7 +1744,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;
@@ -1773,7 +1832,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 );
@@ -1869,7 +1928,6 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
}
}
-
void LLImageRaw::addEmissive(LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
@@ -1935,9 +1993,11 @@ void LLImageRaw::addEmissiveScaled(LLImageRaw* src)
dst->addEmissiveUnscaled(&temp);
}
-
-bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
+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: ";
@@ -2171,6 +2231,61 @@ LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
}
// static
+S8 LLImageFormatted::getCodecFromMimeType(std::string_view mimetype)
+{
+ if (mimetype == "image/bmp")
+ {
+ return IMG_CODEC_BMP;
+ }
+ else if (mimetype == "image/tga")
+ {
+ return IMG_CODEC_TGA;
+ }
+ else if (mimetype == "image/jpeg")
+ {
+ return IMG_CODEC_JPEG;
+ }
+ else if (mimetype == "image/png")
+ {
+ return IMG_CODEC_PNG;
+ }
+ else if (mimetype == "image/j2c")
+ {
+ return IMG_CODEC_J2C;
+ }
+ else if (mimetype == "image/dxt")
+ {
+ return IMG_CODEC_DXT;
+ }
+ return IMG_CODEC_INVALID;
+}
+
+// static
+LLImageFormatted* LLImageFormatted::createFromMimeType(std::string_view mimetype)
+{
+ S8 codec = getCodecFromMimeType(mimetype);
+ return createFromType(codec);
+}
+
+// static
+LLImageFormatted* LLImageFormatted::loadFromMemory(const U8* data_in, U32 size, std::string_view mimetype)
+{
+ LLImageFormatted* image = createFromMimeType(mimetype);
+ if (image)
+ {
+ U8* data = image->allocateData(size);
+ memcpy(data, data_in, size);
+
+ if (!image->updateData())
+ {
+ delete image;
+ image = NULL;
+ }
+ }
+ return image;
+}
+
+// static
LLImageFormatted* LLImageFormatted::createFromExtension(const std::string& instring)
{
std::string exten;
@@ -2250,6 +2365,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;
@@ -2258,6 +2375,8 @@ U8* LLImageFormatted::allocateData(S32 size)
// virtual
U8* LLImageFormatted::reallocateData(S32 size)
{
+ LLImageDataLock lock(this);
+
sGlobalFormattedMemory -= getDataSize();
U8* res = LLImageBase::reallocateData(size);
sGlobalFormattedMemory += getDataSize();
@@ -2267,6 +2386,12 @@ U8* LLImageFormatted::reallocateData(S32 size)
// virtual
void LLImageFormatted::deleteData()
{
+ LLImageDataLock lock(this);
+
+ if (mDecoding)
+ {
+ LL_ERRS() << "LLImageFormatted::deleteData() is called during decoding" << LL_ENDL;
+ }
sGlobalFormattedMemory -= getDataSize();
LLImageBase::deleteData();
}
@@ -2292,6 +2417,8 @@ void LLImageFormatted::sanityCheck()
bool LLImageFormatted::copyData(U8 *data, S32 size)
{
+ LLImageDataLock lock(this);
+
if ( data && ((data != getData()) || (size != getDataSize())) )
{
deleteData();
@@ -2304,6 +2431,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();
@@ -2317,6 +2446,8 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
{
if (data)
{
+ LLImageDataLock lock(this);
+
if (!getData())
{
setData(data, size);
@@ -2334,6 +2465,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
//----------------------------------------------------------------------------
+
bool LLImageFormatted::load(const std::string &filename, int load_size)
{
resetLastError();
@@ -2358,6 +2490,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)
@@ -2396,6 +2531,8 @@ bool LLImageFormatted::save(const std::string &filename)
return false;
}
+ LLImageDataSharedLock lock(this);
+
S32 result = outfile.write(getData(), getDataSize());
outfile.close() ;
return (result != 0);
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 9b16711b85..42eecbb97c 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -117,6 +117,10 @@ 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
{
@@ -238,42 +255,30 @@ public:
LLPointer<LLImageRaw> duplicate();
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
- void copy( LLImageRaw* src );
+ void copy( const LLImageRaw* src );
// Src and dst are same size. Src and dst have same number of components.
- void copyUnscaled( LLImageRaw* src );
+ void copyUnscaled( const LLImageRaw* src );
// Src and dst are same size. Src has 4 components. Dst has 3 components.
- void copyUnscaled4onto3( LLImageRaw* src );
+ void copyUnscaled4onto3( const LLImageRaw* src );
// Src and dst are same size. Src has 3 components. Dst has 4 components.
- void copyUnscaled3onto4( LLImageRaw* src );
+ void copyUnscaled3onto4( const LLImageRaw* src );
// Src and dst are same size. Src has 1 component. Dst has 4 components.
// Alpha component is set to source alpha mask component.
// RGB components are set to fill color.
- void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill);
+ void copyUnscaledAlphaMask( const LLImageRaw* src, const LLColor4U& fill);
// Src and dst can be any size. Src and dst have same number of components.
- void copyScaled( LLImageRaw* src );
-
- // Src and dst can be any size. Src has 3 components. Dst has 4 components.
- void copyScaled3onto4( LLImageRaw* src );
-
- // Src and dst can be any size. Src has 4 components. Dst has 3 components.
- void copyScaled4onto3( LLImageRaw* src );
+ void copyScaled( const LLImageRaw* src );
// Composite operations
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
- void composite( LLImageRaw* src );
-
- // Src and dst can be any size. Src has 4 components. Dst has 3 components.
- void compositeScaled4onto3( LLImageRaw* src );
-
- // Src and dst are same size. Src has 4 components. Dst has 3 components.
- void compositeUnscaled4onto3( LLImageRaw* src );
+ void composite( const LLImageRaw* src );
// Emissive operations used by minimap
// Roughly emulates GLTF emissive texture, but is not GLTF-compliant
@@ -282,13 +287,25 @@ public:
void addEmissiveScaled(LLImageRaw* src);
void addEmissiveUnscaled(LLImageRaw* src);
protected:
+ // Src and dst can be any size. Src has 4 components. Dst has 3 components.
+ void compositeScaled4onto3( const LLImageRaw* src );
+
+ // Src and dst are same size. Src has 4 components. Dst has 3 components.
+ void compositeUnscaled4onto3( const LLImageRaw* src );
+
+ // Src and dst can be any size. Src has 3 components. Dst has 4 components.
+ void copyScaled3onto4( const LLImageRaw* src );
+
+ // Src and dst can be any size. Src has 4 components. Dst has 3 components.
+ void copyScaled4onto3( const LLImageRaw* src );
+
// Create an image from a local file (generally used in tools)
//bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false);
- void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
- void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );
+ void copyLineScaled( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
+ void compositeRowScaled4onto3( const U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );
- U8 fastFractionalMult(U8 a,U8 b);
+ static U8 fastFractionalMult(U8 a, U8 b);
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
@@ -296,7 +313,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.
@@ -305,7 +322,10 @@ class LLImageFormatted : public LLImageBase
{
public:
static LLImageFormatted* createFromType(S8 codec);
+ static LLImageFormatted* loadFromMemory(const U8* data, U32 size, std::string_view mimetype);
static LLImageFormatted* createFromExtension(const std::string& instring);
+ static LLImageFormatted* createFromMimeType(std::string_view mimetype);
+ static S8 getCodecFromMimeType(std::string_view mimetype);
protected:
/*virtual*/ ~LLImageFormatted();
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 08fcdf39da..2a328675c2 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()))
@@ -337,8 +339,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!");
@@ -351,7 +356,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;
@@ -398,7 +403,7 @@ U32 LLImageBMP::countTrailingZeros( U32 m )
}
-bool LLImageBMP::decodeColorMask16( U8* dst, U8* src )
+bool LLImageBMP::decodeColorMask16( U8* dst, const U8* src )
{
llassert( 16 == mBitsPerPixel );
@@ -434,7 +439,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
@@ -478,7 +483,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) );
@@ -508,7 +513,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() );
@@ -542,6 +547,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 d2cbad1a49..237c3e8d53 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/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index 997406bb7b..d4efbcfad2 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -201,7 +201,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/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index f75b1a72df..6b960f9077 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();
@@ -269,6 +271,9 @@ bool LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
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();
@@ -463,7 +476,7 @@ bool LLImageDXT::convertToDXR()
// virtual
S32 LLImageDXT::calcHeaderSize()
{
- return llmax(sizeof(dxtfile_header_old_t), sizeof(dxtfile_header_t));
+ return static_cast<S32>(llmax(sizeof(dxtfile_header_old_t), sizeof(dxtfile_header_t)));
}
// virtual
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 1b7835a6ff..0d15906afd 100644
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -88,6 +88,8 @@ 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)
{
@@ -779,9 +781,9 @@ void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
// Compute min and max counts minus tail
tail = llclampf(tail);
- S32 total = cumulated_histo[255];
- S32 min_c = (S32)((F32)(total) * tail);
- S32 max_c = (S32)((F32)(total) * (1.0 - tail));
+ U32 total = cumulated_histo[255];
+ U32 min_c = (U32)((F32)(total) * tail);
+ U32 max_c = (U32)((F32)(total) * (1.0 - tail));
// Find min and max values
S32 min_v = 0;
@@ -796,9 +798,9 @@ void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
}
// Compute linear lookup table
- U8 linear_red_lut[256];
- U8 linear_green_lut[256];
- U8 linear_blue_lut[256];
+ U8 linear_red_lut[256]{};
+ U8 linear_green_lut[256]{};
+ U8 linear_blue_lut[256]{};
if (max_v == min_v)
{
// Degenerated binary split case
@@ -848,16 +850,16 @@ void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha)
}
// Compute deltas
- S32 total = cumulated_histo[255];
- S32 delta_count = total / nb_classes;
- S32 current_count = delta_count;
- S32 delta_value = 256 / (nb_classes - 1);
- S32 current_value = 0;
+ U32 total = cumulated_histo[255];
+ U32 delta_count = total / nb_classes;
+ U32 current_count = delta_count;
+ U32 delta_value = 256 / (nb_classes - 1);
+ U32 current_value = 0;
// Compute equalized lookup table
- U8 equalize_red_lut[256];
- U8 equalize_green_lut[256];
- U8 equalize_blue_lut[256];
+ U8 equalize_red_lut[256]{};
+ U8 equalize_green_lut[256]{};
+ U8 equalize_blue_lut[256]{};
for (S32 i = 0; i < 256; i++)
{
// Blend in current_value with alpha values
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 5175849ad8..0058b91b0f 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))
{
@@ -157,22 +159,25 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLTimer elapsed;
- bool res = true;
-
resetLastError();
- // Check to make sure that this instance has been initialized with data
- if (!getData() || (getDataSize() < 16))
+ bool res;
{
- setLastError("LLImageJ2C uninitialized");
- res = true; // done
- }
- else
- {
- // Update the raw discard level
- updateRawDiscardLevel();
+ LLImageDataLock lock(this);
+
mDecoding = true;
- res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ // Check to make sure that this instance has been initialized with data
+ if (!getData() || (getDataSize() < 16))
+ {
+ setLastError("LLImageJ2C uninitialized");
+ res = true; // done
+ }
+ else
+ {
+ // Update the raw discard level
+ updateRawDiscardLevel();
+ res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ }
}
if (res)
@@ -181,12 +186,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())
{
@@ -406,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 93f1d0cdc4..0e7ec365d4 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()))
{
@@ -189,6 +191,9 @@ bool LLImageJPEG::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
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 12249ad8c3..add6657117 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 4d081ce169..d75084cf08 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -54,6 +54,8 @@ bool LLImagePNG::updateData()
try
{
+ LLImageDataLock lock(this);
+
// Check to make sure that this instance has been initialized with data
if (!getData() || (0 == getDataSize()))
{
@@ -103,6 +105,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()))
{
@@ -135,6 +140,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 adc98cd81d..25232b77aa 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()))
{
@@ -328,6 +330,9 @@ 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()))
{
@@ -462,7 +467,7 @@ bool LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, bool &alpha_opaqu
S32 pixels = getWidth() * getHeight();
- if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset)
+ if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - (S32)mDataOffset)
{ //here we have situation when data size in src less than actually needed
return false;
}
@@ -644,6 +649,9 @@ 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());
@@ -1062,6 +1070,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!");
@@ -1168,7 +1179,7 @@ bool LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
// Reads a .tga file and creates an LLImageTGA with its data.
bool LLImageTGA::loadFile( const std::string& path )
{
- S32 len = path.size();
+ auto len = path.size();
if( len < 5 )
{
return false;
@@ -1195,7 +1206,7 @@ bool LLImageTGA::loadFile( const std::string& path )
}
U8* buffer = allocateData(file_size);
- S32 bytes_read = fread(buffer, 1, file_size, file);
+ S32 bytes_read = static_cast<S32>(fread(buffer, 1, file_size, file));
if( bytes_read != file_size )
{
deleteData();
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 8ce17b5753..bdaef0c653 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -36,7 +36,7 @@ class ImageRequest
public:
ImageRequest(const LLPointer<LLImageFormatted>& image,
S32 discard,
- BOOL needs_aux,
+ bool needs_aux,
const LLPointer<LLImageDecodeThread::Responder>& responder,
U32 request_id);
virtual ~ImageRequest();
@@ -51,15 +51,14 @@ private:
LLPointer<LLImageFormatted> mFormattedImage;
S32 mDiscardLevel;
U32 mRequestId;
- BOOL mNeedsAux;
+ bool mNeedsAux;
// output
LLPointer<LLImageRaw> mDecodedImageRaw;
LLPointer<LLImageRaw> mDecodedImageAux;
- BOOL mDecodedRaw;
- BOOL mDecodedAux;
+ bool mDecodedRaw;
+ bool mDecodedAux;
LLPointer<LLImageDecodeThread::Responder> mResponder;
- std::string mErrorString;
-};
+ std::string mErrorString;};
//----------------------------------------------------------------------------
@@ -92,12 +91,15 @@ size_t LLImageDecodeThread::getPending()
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(
const LLPointer<LLImageFormatted>& image,
S32 discard,
- BOOL needs_aux,
+ bool needs_aux,
const LLPointer<LLImageDecodeThread::Responder>& responder)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
U32 decode_id = ++mDecodeCount;
+ if (decode_id == 0)
+ decode_id = ++mDecodeCount;
+
// Instantiate the ImageRequest right in the lambda, why not?
bool posted = mThreadPool->getQueue().post(
[req = ImageRequest(image, discard, needs_aux, responder, decode_id)]
@@ -128,14 +130,14 @@ LLImageDecodeThread::Responder::~Responder()
ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image,
S32 discard,
- BOOL needs_aux,
+ bool needs_aux,
const LLPointer<LLImageDecodeThread::Responder>& responder,
U32 request_id)
: mFormattedImage(image),
mDiscardLevel(discard),
mNeedsAux(needs_aux),
- mDecodedRaw(FALSE),
- mDecodedAux(FALSE),
+ mDecodedRaw(false),
+ mDecodedAux(false),
mResponder(responder),
mRequestId(request_id)
{
@@ -155,10 +157,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;
- mErrorString.clear();
- if (!mDecodedRaw && mFormattedImage.notNull())
+
+ LLImageDataLock lockFormatted(mFormattedImage);
+ LLImageDataLock lockDecodedRaw(mDecodedImageRaw);
+ LLImageDataLock lockDecodedAux(mDecodedImageAux);
+
+ if (!mDecodedRaw)
{
// Decode primary channels
if (mDecodedImageRaw.isNull())
@@ -166,13 +176,10 @@ bool ImageRequest::processRequest()
// parse formatted header
if (!mFormattedImage->updateData())
{
- // Pick up errors from updateData
- mErrorString = LLImage::getLastThreadError();
return true; // done (failed)
}
- if (0 == (mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ if ((mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()) == 0)
{
- mErrorString = "Invalid image size";
return true; // done (failed)
}
if (mDiscardLevel >= 0)
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index 8c43a7c32c..9e01f0bacd 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<LLImageFormatted>& image,
- S32 discard, BOOL needs_aux,
+ S32 discard, bool needs_aux,
const LLPointer<Responder>& responder);
size_t getPending();
size_t update(F32 max_time_ms);
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index 24b6d34fe2..79c201b1f4 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
{
@@ -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))
{
@@ -208,25 +210,25 @@ 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);
}
catch (...)
{
mErrorMessage = "LLPngWrapper";
releaseResources();
LOG_UNHANDLED_EXCEPTION("");
- return (FALSE);
+ return (false);
}
// Clean up and return
releaseResources();
- return (TRUE);
+ return (true);
}
// Do transformations to normalize the input to 8-bpp RGBA
@@ -288,7 +290,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
{
@@ -326,10 +328,10 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSiz
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
// Setup write function
- PngDataInfo dataPtr;
+ PngDataInfo dataPtr{};
dataPtr.mData = dest;
dataPtr.mOffset = 0;
- dataPtr.mDataSize = destSize;
+ dataPtr.mDataSize = static_cast<S32>(destSize);
png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush);
// Setup image params
@@ -369,11 +371,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 f3c3d57f70..3ada8ac7c2 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();
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index 2568adf89e..36be885912 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -151,7 +151,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...)