summaryrefslogtreecommitdiff
path: root/indra/llimage/llimageworker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llimage/llimageworker.cpp')
-rw-r--r--indra/llimage/llimageworker.cpp202
1 files changed, 94 insertions, 108 deletions
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 532e996188..86d41515e7 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -37,152 +37,138 @@
//----------------------------------------------------------------------------
-//static
-LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
-S32 LLImageWorker::sCount = 0;
+// MAIN THREAD
+LLImageDecodeThread::LLImageDecodeThread(bool threaded)
+ : LLQueuedThread("imagedecode", threaded)
+{
+ mCreationMutex = new LLMutex(getAPRPool());
+}
-//static
-void LLImageWorker::initImageWorker(LLWorkerThread* workerthread)
+// MAIN THREAD
+// virtual
+S32 LLImageDecodeThread::update(U32 max_time_ms)
{
- sWorkerThread = workerthread;
+ LLMutexLock lock(mCreationMutex);
+ for (creation_list_t::iterator iter = mCreationList.begin();
+ iter != mCreationList.end(); ++iter)
+ {
+ creation_info& info = *iter;
+ ImageRequest* req = new ImageRequest(info.handle, info.image,
+ info.priority, info.discard, info.needs_aux,
+ info.responder);
+ addRequest(req);
+ }
+ mCreationList.clear();
+ S32 res = LLQueuedThread::update(max_time_ms);
+ return res;
}
-//static
-void LLImageWorker::cleanupImageWorker()
+LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
+{
+ LLMutexLock lock(mCreationMutex);
+ handle_t handle = generateHandle();
+ mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
+ return handle;
+}
+
+// Used by unit test only
+// Returns the size of the mutex guarded list as an indication of sanity
+S32 LLImageDecodeThread::tut_size()
+{
+ LLMutexLock lock(mCreationMutex);
+ S32 res = mCreationList.size();
+ return res;
+}
+
+LLImageDecodeThread::Responder::~Responder()
{
}
//----------------------------------------------------------------------------
-LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority,
- S32 discard,
- LLPointer<LLResponder> responder)
- : LLWorkerClass(sWorkerThread, "Image"),
+LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux,
+ LLImageDecodeThread::Responder* responder)
+ : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
mFormattedImage(image),
- mDecodedType(-1),
mDiscardLevel(discard),
- mPriority(priority),
+ mNeedsAux(needs_aux),
+ mDecodedRaw(FALSE),
+ mDecodedAux(FALSE),
mResponder(responder)
{
- ++sCount;
}
-LLImageWorker::~LLImageWorker()
+LLImageDecodeThread::ImageRequest::~ImageRequest()
{
- mDecodedImage = NULL;
+ mDecodedImageRaw = NULL;
+ mDecodedImageAux = NULL;
mFormattedImage = NULL;
- --sCount;
}
//----------------------------------------------------------------------------
-//virtual, main thread
-void LLImageWorker::startWork(S32 param)
-{
- llassert_always(mDecodedImage.isNull());
- mDecodedType = -1;
-}
-bool LLImageWorker::doWork(S32 param)
+// Returns true when done, whether or not decode was successful.
+bool LLImageDecodeThread::ImageRequest::processRequest()
{
- bool decoded = false;
- if(mDecodedImage.isNull())
+ const F32 decode_time_slice = .1f;
+ bool done = true;
+ if (!mDecodedRaw && mFormattedImage.notNull())
{
- if (!mFormattedImage->updateData())
- {
- mDecodedType = -2; // failed
- return true;
- }
- if (mDiscardLevel >= 0)
+ // Decode primary channels
+ if (mDecodedImageRaw.isNull())
{
- mFormattedImage->setDiscardLevel(mDiscardLevel);
- }
- if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
- {
- decoded = true; // failed
- }
- else
- {
- mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding
+ // parse formatted header
+ if (!mFormattedImage->updateData())
+ {
+ return true; // done (failed)
+ }
+ if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ {
+ return true; // done (failed)
+ }
+ if (mDiscardLevel >= 0)
+ {
+ mFormattedImage->setDiscardLevel(mDiscardLevel);
+ }
+ mDecodedImageRaw = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ mFormattedImage->getComponents());
}
+ done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms
+ mDecodedRaw = done;
}
- if (!decoded)
+ if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull())
{
- if (param == 0)
- {
- // Decode primary channels
- decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
- }
- else
+ // Decode aux channel
+ if (!mDecodedImageAux)
{
- // Decode aux channel
- decoded = mFormattedImage->decodeChannels(mDecodedImage, .1f, param, param); // 1ms
+ mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ 1);
}
+ done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms
+ mDecodedAux = done;
}
- 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;
- }
+ return done;
}
-//----------------------------------------------------------------------------
-
-
-BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
+void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
{
- // 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)
+ if (mResponder.notNull())
{
- 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 success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
+ mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux);
}
+ // Will automatically be deleted
}
-BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
+// Used by unit test only
+// Checks that a responder exists for this instance so that something can happen when completion is reached
+bool LLImageDecodeThread::ImageRequest::tut_isOK()
{
- if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
- {
- // special case
- LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
- return imagedxt->getMipData(raw, discard);
- }
- else
- {
- return requestDecodedAuxData(raw, 0, discard);
- }
+ return mResponder.notNull();
}