diff options
Diffstat (limited to 'indra/llimage/llimageworker.cpp')
-rw-r--r-- | indra/llimage/llimageworker.cpp | 202 |
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(); } |