summaryrefslogtreecommitdiff
path: root/indra/llimage
diff options
context:
space:
mode:
authorSteven Bennetts <steve@lindenlab.com>2007-03-02 21:25:50 +0000
committerSteven Bennetts <steve@lindenlab.com>2007-03-02 21:25:50 +0000
commit4dabd9c0472deb49573fdafef2fa413e59703f19 (patch)
tree06c680d6a2047e03838d6548bccd26c7baf9d652 /indra/llimage
parentd4462963c6ba5db2088723bbedc7b60f1184c594 (diff)
merge release@58699 beta-1-14-0@58707 -> release
Diffstat (limited to 'indra/llimage')
-rw-r--r--indra/llimage/llimage.cpp251
-rw-r--r--indra/llimage/llimage.h41
-rw-r--r--indra/llimage/llimagedxt.cpp9
-rw-r--r--indra/llimage/llimagedxt.h5
-rw-r--r--indra/llimage/llimagej2c.cpp28
-rw-r--r--indra/llimage/llimagej2c.h2
-rw-r--r--indra/llimage/llimageworker.cpp165
-rw-r--r--indra/llimage/llimageworker.h57
8 files changed, 303 insertions, 255 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index dc864aaf53..9b37cdade5 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -17,7 +17,7 @@
#include "llmath.h"
#include "stdtypes.h"
#include "v4coloru.h"
-#include "llmemory.h"
+#include "llmemtype.h"
#include "llimage.h"
#include "llimagebmp.h"
@@ -114,7 +114,7 @@ U8* LLImageBase::allocateData(S32 size)
llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
}
}
- else if ((size <= 0 || size > 4096*4096*16) && sSizeOverride == FALSE)
+ else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
{
llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
}
@@ -197,7 +197,8 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
: LLImageBase()
{
mMemType = LLMemType::MTYPE_IMAGERAW;
- copyData(data, width, height, components);
+ allocateDataSize(width, height, components);
+ memcpy(getData(), data, width*height*components);
++sRawImageCount;
}
@@ -239,20 +240,6 @@ void LLImageRaw::deleteData()
LLImageBase::deleteData();
}
-BOOL LLImageRaw::copyData(U8 *data, U16 width, U16 height, S8 components)
-{
- if (!resize(width, height, components))
- {
- return FALSE;
- }
- if (getData() == NULL || data == NULL)
- {
- return FALSE;
- }
- memcpy(getData(), data, width*height*components); /* Flawfinder: ignore */
- return TRUE;
-}
-
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@@ -1243,25 +1230,8 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
//static
S32 LLImageFormatted::sGlobalFormattedMemory = 0;
-//static
-LLWorkerThread* LLImageFormatted::sWorkerThread = NULL;
-
-//static
-void LLImageFormatted::initClass(bool threaded, bool run_always)
-{
- sWorkerThread = new LLWorkerThread(threaded, run_always);
-}
-
-//static
-void LLImageFormatted::cleanupClass()
-{
- delete sWorkerThread;
- sWorkerThread = NULL;
-}
-
-
LLImageFormatted::LLImageFormatted(S8 codec)
- : LLImageBase(), LLWorkerClass(sWorkerThread, "ImageFormatted"),
+ : LLImageBase(),
mCodec(codec),
mDecoding(0),
mDecoded(0),
@@ -1276,64 +1246,14 @@ LLImageFormatted::~LLImageFormatted()
// NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
// NOT LLImageFormatted::deleteData()
deleteData();
- releaseDecodedData();
-}
-
-//----------------------------------------------------------------------------
-
-//virtual
-void LLImageFormatted::startWork(S32 param)
-{
- if (mDecoding) llerrs << "WTF?" << llendl;
-}
-
-bool LLImageFormatted::doWork(S32 param)
-{
- if (!(isWorking())) llerrs << "WTF?" << llendl;
- llassert(mDecodedImage.notNull());
- if (param == 0)
- {
- // Decode primary channels
- mDecoded = decode(mDecodedImage, .001f); // 1ms
- }
- else
- {
- // Decode aux channel
- mDecoded = decode(mDecodedImage, .001f, param, param); // 1ms
- }
- if (mDecoded)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void LLImageFormatted::endWork(S32 param, bool aborted)
-{
- if (mDecoding) llerrs << "WTF?" << llendl;
- if (!mDecoded) llerrs << "WTF?" << llendl;
}
//----------------------------------------------------------------------------
// static
-LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
+LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
{
- LLString exten;
- size_t dotidx = instring.rfind('.');
- if (dotidx != LLString::npos)
- {
- exten = instring.substr(dotidx+1);
- }
- else
- {
- exten = instring;
- }
- S8 codec = get_codec(exten);
- LLPointer<LLImageFormatted> image;
+ LLImageFormatted* image;
switch(codec)
{
case IMG_CODEC_BMP:
@@ -1354,10 +1274,28 @@ LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring
image = new LLImageDXT();
break;
default:
+ image = NULL;
break;
}
return image;
}
+
+// static
+LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
+{
+ LLString exten;
+ size_t dotidx = instring.rfind('.');
+ if (dotidx != LLString::npos)
+ {
+ exten = instring.substr(dotidx+1);
+ }
+ else
+ {
+ exten = instring;
+ }
+ S8 codec = get_codec(exten);
+ return createFromType(codec);
+}
//----------------------------------------------------------------------------
// virtual
@@ -1374,15 +1312,6 @@ void LLImageFormatted::dump()
//----------------------------------------------------------------------------
-void LLImageFormatted::readHeader(U8* data, S32 size)
-{
- if (size <= 0)
- {
- size = calcHeaderSize();
- }
- copyData(data, size); // calls updateData()
-}
-
S32 LLImageFormatted::calcDataSize(S32 discard_level)
{
if (discard_level < 0)
@@ -1426,82 +1355,6 @@ BOOL LLImageFormatted::decode(LLImageRaw* raw_image,F32 decode_time, S32 first_
return decode( raw_image, decode_time ); // Loads first 4 channels by default.
}
-// virtual
-BOOL LLImageFormatted::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
-{
- llassert(getData() && getDataSize());
- // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
- if (discard >= 0 && discard != mDiscardLevel)
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- if (haveWork())
- {
- checkWork();
- }
- if (!mDecoded)
- {
- if (!haveWork())
- {
- llassert(!mDecoding);
- mDecodedImage = new LLImageRaw(getWidth(), getHeight(), getComponents());
- addWork(0);
- }
- return FALSE;
- }
- else
- {
- llassert(mDecodedImage.notNull());
- llassert(!mDecoding);
- raw = mDecodedImage;
- return TRUE;
- }
-}
-
-BOOL LLImageFormatted::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
- S32 discard, F32 decode_time)
-{
- llassert(getData() && getDataSize());
- // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
- if (discard >= 0 && discard != mDiscardLevel)
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- if (haveWork())
- {
- checkWork();
- }
- if (!mDecoded)
- {
- if (!haveWork())
- {
- llassert(!mDecoding);
- mDecodedImage = new LLImageRaw(getWidth(), getHeight(), 1);
- addWork(channel);
- }
- return FALSE;
- }
- else
- {
- llassert(mDecodedImage.notNull());
- llassert(!mDecoding);
- raw = mDecodedImage;
- return TRUE;
- }
-}
-
-
-// virtual
-void LLImageFormatted::releaseDecodedData()
-{
- if (mDecoded || mDecoding)
- {
- mDecodedImage = NULL; // deletes image
- mDecoded = FALSE;
- mDecoding = FALSE;
- }
-}
-
//----------------------------------------------------------------------------
// virtual
@@ -1549,52 +1402,42 @@ void LLImageFormatted::sanityCheck()
BOOL LLImageFormatted::copyData(U8 *data, S32 size)
{
- if (data && data != getData())
+ if ( (data && data != getData()) || (size != getDataSize()) )
{
deleteData();
allocateData(size);
memcpy(getData(), data, size); /* Flawfinder: ignore */
}
- updateData(); // virtual
-
return TRUE;
}
-BOOL LLImageFormatted::appendData(U8 *data, S32 size)
+// LLImageFormatted becomes the owner of data
+void LLImageFormatted::setData(U8 *data, S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
- S32 old_size = getDataSize();
- U8* old_data = getData();
- S32 new_size = old_size + size;
- U8* new_data = new U8[new_size];
- if (!new_data)
- {
- llerrs << "Out of memory in LLImageFormatted::appendData(U8 *data, S32 size)" << llendl;
- return FALSE;
- }
- // resize the image
- setDataAndSize(new_data, new_size);
- // copy the old data and delete it
- memcpy(new_data, old_data, old_size); /* Flawfinder: ignore */
- delete old_data;
- // if we have new data, copy it and call updateData()
- if (data)
+ if (data && data != getData())
{
- memcpy(new_data + old_size, data, size); /* Flawfinder: ignore */
- updateData(); // virtual
+ deleteData();
+ setDataAndSize(data, size); // Access private LLImageBase members
+ sGlobalFormattedMemory += getDataSize();
}
- return TRUE;
}
-BOOL LLImageFormatted::setData(U8 *data, S32 size)
+void LLImageFormatted::appendData(U8 *data, S32 size)
{
- if (data && data != getData())
+ if (data)
{
- deleteData();
- setDataAndSize(data, size); // Access private LLImageBase members
- sGlobalFormattedMemory += getDataSize();
+ if (!getData())
+ {
+ setData(data, size);
+ }
+ else
+ {
+ S32 cursize = getDataSize();
+ S32 newsize = cursize + size;
+ reallocateData(newsize);
+ memcpy(getData() + cursize, data, size);
+ }
}
- return updateData(); // virtual
}
//----------------------------------------------------------------------------
@@ -1667,8 +1510,6 @@ S8 LLImageFormatted::getCodec() const
//============================================================================
-//----------------------------------------------------------------------------
-
static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
{
dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
@@ -1794,3 +1635,5 @@ F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S3
return w_priority;
}
+
+//============================================================================
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 13ea916654..0e007c2c86 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -13,7 +13,7 @@
#include "lluuid.h"
#include "llstring.h"
#include "llmemory.h"
-#include "llworkerthread.h"
+#include "llthread.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
@@ -135,8 +135,6 @@ public:
/*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size);
- BOOL copyData(U8 *data, U16 width, U16 height, S8 components);
-
BOOL resize(U16 width, U16 height, S8 components);
U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
@@ -206,11 +204,10 @@ public:
// Compressed representation of image.
// Subclass from this class for the different representations (J2C, bmp)
-class LLImageFormatted : public LLImageBase, public LLWorkerClass
+class LLImageFormatted : public LLImageBase
{
public:
- static void initClass(bool threaded = true, bool run_always = true);
- static void cleanupClass();
+ static LLImageFormatted* createFromType(S8 codec);
static LLImageFormatted* createFromExtension(const LLString& instring);
protected:
@@ -228,22 +225,11 @@ public:
/*virtual*/ void dump();
/*virtual*/ void sanityCheck();
- // LLWorkerThread
-public:
- // called from WORKER THREAD, returns TRUE if done
- /*virtual*/ bool doWork(S32 param);
-private:
- // called from MAIN THREAD
- /*virtual*/ void startWork(S32 param); // called from addWork()
- /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
-
// New methods
public:
// calcHeaderSize() returns the maximum size of header;
// 0 indicates we don't know have a header and have to lead the entire file
virtual S32 calcHeaderSize() { return 0; };
- // readHeader() reads size bytes into mData, and sets width/height/ncomponents
- virtual void readHeader(U8* data, S32 size);
// calcDataSize() returns how many bytes to read to load discard_level (including header)
virtual S32 calcDataSize(S32 discard_level);
// calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
@@ -253,27 +239,16 @@ public:
BOOL load(const LLString& filename);
BOOL save(const LLString& filename);
-// BOOL save(LLVFS *vfs, const LLUUID &uuid, const LLAssetType::EType type);
-// Depricated to remove VFS dependency (see .cpp for replacement):
virtual BOOL updateData() = 0; // pure virtual
- BOOL copyData(U8 *data, S32 size); // calls updateData()
- BOOL setData(U8 *data, S32 size); // calls updateData()
- BOOL appendData(U8 *data, S32 size); // use if some data (e.g header) is already loaded, calls updateData()
+ void setData(U8 *data, S32 size);
+ void appendData(U8 *data, S32 size);
// Loads first 4 channels.
virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0) = 0;
// Subclasses that can handle more than 4 channels should override this function.
virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
- // Decode methods to return a pointer to raw data for purposes of passing to
- // opengl or such. This class tracks the decoded data and keeps it alive until
- // destroyed or releaseDecodedData() is called.
- virtual BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1, F32 decode_time=0.0);
- virtual BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
- S32 discard = -1, F32 decode_time=0.0);
- virtual void releaseDecodedData();
-
virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0) = 0;
S8 getCodec() const;
@@ -283,16 +258,16 @@ public:
S8 getDiscardLevel() const { return mDiscardLevel; }
protected:
+ BOOL copyData(U8 *data, S32 size); // calls updateData()
+
+protected:
S8 mCodec;
S8 mDecoding;
S8 mDecoded;
S8 mDiscardLevel;
- LLPointer<LLImageRaw> mDecodedImage;
-
public:
static S32 sGlobalFormattedMemory;
- static LLWorkerThread* sWorkerThread;
};
#endif
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index dfb5b957d3..1b6ce65274 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -265,8 +265,7 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
return TRUE;
}
-// virtual
-BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
+BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
{
if (discard < 0)
{
@@ -283,11 +282,6 @@ BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32
return TRUE;
}
-void LLImageDXT::releaseDecodedData()
-{
- // nothing to do
-}
-
BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
{
llassert_always(raw_image);
@@ -426,6 +420,7 @@ bool LLImageDXT::convertToDXR()
dxtfile_header_t* header = (dxtfile_header_t*)newdata;
header->pixel_fmt.fourcc = getFourCC(newformat);
setData(newdata, total_bytes);
+ updateData();
return true;
}
diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h
index 88d28a2958..e286d03e1e 100644
--- a/indra/llimage/llimagedxt.h
+++ b/indra/llimage/llimagedxt.h
@@ -82,12 +82,11 @@ public:
BOOL encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips);
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
- /*virtual*/ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard=-1, F32 decode_time=0.0);
- /*virtual*/ void releaseDecodedData();
-
/*virtual*/ S32 calcHeaderSize();
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
+ BOOL getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
+
void setFormat();
S32 getMipOffset(S32 discard);
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 32a8c60fac..398e7c9e32 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -11,7 +11,7 @@
#include "lldir.h"
#include "llimagej2c.h"
-#include "llmemory.h"
+#include "llmemtype.h"
typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -224,7 +224,22 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_chann
// Update the raw discard level
updateRawDiscardLevel();
- return mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ mDecoding = TRUE;
+ BOOL res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+ if (res)
+ {
+ if (!mDecoding)
+ {
+ // Failed
+ raw_imagep->deleteData();
+ }
+ else
+ {
+ mDecoding = FALSE;
+ }
+ return TRUE; // done
+ }
+ return FALSE;
}
@@ -334,7 +349,7 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
U8 *data = new U8[file_size];
apr_size_t bytes_read = file_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
- if (s != APR_SUCCESS || bytes_read != file_size)
+ if (s != APR_SUCCESS || (S32)bytes_read != file_size)
{
delete[] data;
setLastError("Unable to read entire file");
@@ -349,9 +364,9 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
{
LLMemType mt1((LLMemType::EMemType)mMemType);
- // Taken from setData()
- BOOL res = LLImageFormatted::setData(data, file_size);
+ setData(data, file_size);
+ BOOL res = updateData();
if ( !res )
{
return FALSE;
@@ -367,10 +382,9 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
return mImpl->getMetadata(*this);
}
-void LLImageJ2C::setDecodingDone(BOOL complete)
+void LLImageJ2C::decodeFailed()
{
mDecoding = FALSE;
- mDecoded = complete;
}
void LLImageJ2C::updateRawDiscardLevel()
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 4a3b017a55..1181ae2bb8 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -53,7 +53,7 @@ protected:
friend class LLImageJ2CImpl;
friend class LLImageJ2COJ;
friend class LLImageJ2CKDU;
- void setDecodingDone(BOOL complete = TRUE);
+ void decodeFailed();
void updateRawDiscardLevel();
S32 mMaxBytes; // Maximum number of bytes of data to use...
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
new file mode 100644
index 0000000000..b44bf19227
--- /dev/null
+++ b/indra/llimage/llimageworker.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file llimage.cpp
+ * @brief Base class for images.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llimageworker.h"
+#include "llimagedxt.h"
+
+//----------------------------------------------------------------------------
+
+//static
+LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
+S32 LLImageWorker::sCount = 0;
+
+//static
+void LLImageWorker::initClass(LLWorkerThread* workerthread)
+{
+ sWorkerThread = workerthread;
+}
+
+//static
+void LLImageWorker::cleanupClass()
+{
+}
+
+//----------------------------------------------------------------------------
+
+LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder)
+ : LLWorkerClass(sWorkerThread, "Image"),
+ mFormattedImage(image),
+ mDecodedType(-1),
+ mDiscardLevel(discard),
+ mPriority(priority),
+ mResponder(responder)
+{
+ ++sCount;
+}
+
+LLImageWorker::~LLImageWorker()
+{
+ mDecodedImage = NULL;
+ mFormattedImage = NULL;
+ --sCount;
+}
+
+//----------------------------------------------------------------------------
+
+//virtual, main thread
+void LLImageWorker::startWork(S32 param)
+{
+ llassert_always(mDecodedImage.isNull());
+ mDecodedType = -1;
+}
+
+bool LLImageWorker::doWork(S32 param)
+{
+ bool decoded = false;
+ if(mDecodedImage.isNull())
+ {
+ if (!mFormattedImage->updateData())
+ {
+ mDecodedType = -2; // failed
+ return true;
+ }
+ if (mDiscardLevel >= 0)
+ {
+ mFormattedImage->setDiscardLevel(mDiscardLevel);
+ }
+ if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ {
+ decoded = true; // failed
+ }
+ else
+ {
+ S32 nc = param ? 1 : mFormattedImage->getComponents();
+ mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ nc);
+ }
+ }
+ if (!decoded)
+ {
+ if (param == 0)
+ {
+ // Decode primary channels
+ decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
+ }
+ else
+ {
+ // Decode aux channel
+ decoded = mFormattedImage->decode(mDecodedImage, .1f, param, param); // 1ms
+ }
+ }
+ if (decoded)
+ {
+ // Call the callback immediately; endWork doesn't get called until ckeckWork
+ if (mResponder.notNull())
+ {
+ bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
+ mResponder->completed(success);
+ }
+ }
+ return decoded;
+}
+
+void LLImageWorker::endWork(S32 param, bool aborted)
+{
+ if (mDecodedType != -2)
+ {
+ mDecodedType = aborted ? -2 : param;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+
+BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
+{
+ // For most codecs, only mDiscardLevel data is available.
+ // (see LLImageDXT for exception)
+ if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
+ {
+ llerrs << "Request for invalid discard level" << llendl;
+ }
+ checkWork();
+ if (mDecodedType == -2)
+ {
+ return TRUE; // aborted, done
+ }
+ if (mDecodedType != channel)
+ {
+ if (!haveWork())
+ {
+ addWork(channel, mPriority);
+ }
+ return FALSE;
+ }
+ else
+ {
+ llassert_always(!haveWork());
+ llassert_always(mDecodedType == channel);
+ raw = mDecodedImage; // smart pointer acquires ownership of data
+ mDecodedImage = NULL;
+ return TRUE;
+ }
+}
+
+BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
+{
+ if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
+ {
+ // special case
+ LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
+ return imagedxt->getMipData(raw, discard);
+ }
+ else
+ {
+ return requestDecodedAuxData(raw, 0, discard);
+ }
+}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
new file mode 100644
index 0000000000..cdd30417ce
--- /dev/null
+++ b/indra/llimage/llimageworker.h
@@ -0,0 +1,57 @@
+/**
+ * @file llimageworker.h
+ * @brief Object for managing images and their textures.
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLIMAGEWORKER_H
+#define LL_LLIMAGEWORKER_H
+
+#include "llimage.h"
+#include "llworkerthread.h"
+
+class LLImageWorker : public LLWorkerClass
+{
+public:
+ static void initClass(LLWorkerThread* workerthread);
+ static void cleanupClass();
+ static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
+
+ // LLWorkerThread
+public:
+ LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder = NULL);
+ ~LLImageWorker();
+
+ // called from WORKER THREAD, returns TRUE if done
+ /*virtual*/ bool doWork(S32 param);
+
+ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
+ BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
+ void releaseDecodedData();
+ void cancelDecode();
+
+private:
+ // called from MAIN THREAD
+ /*virtual*/ void startWork(S32 param); // called from addWork()
+ /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
+
+protected:
+ LLPointer<LLImageFormatted> mFormattedImage;
+ LLPointer<LLImageRaw> mDecodedImage;
+ S32 mDecodedType;
+ S32 mDiscardLevel;
+
+private:
+ U32 mPriority;
+ LLPointer<LLResponder> mResponder;
+
+protected:
+ static LLWorkerThread* sWorkerThread;
+
+public:
+ static S32 sCount;
+};
+
+#endif