From 0b6c9c50c3049eb75a0305376d067bf8982e184d Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 21 Aug 2023 23:55:00 +0300 Subject: SL-20173 show warning notification when trying to add invalid files as local texture --- indra/llimage/llimagedimensionsinfo.cpp | 3 +++ indra/llimage/llimagedimensionsinfo.h | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'indra/llimage') diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index 97b543f3b6..5756ddb32b 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -90,6 +90,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp() if (signature[0] != 'B' || signature[1] != 'M') { LL_WARNS() << "Not a BMP" << LL_ENDL; + mWarning = "IncorrectFormat"; return false; } @@ -140,6 +141,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng() if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a PNG" << LL_ENDL; + mWarning = "IncorrectFormat"; return false; } @@ -183,6 +185,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a JPEG" << LL_ENDL; + mWarning = "IncorrectFormat"; return false; } fseek(fp, 0, SEEK_SET); // go back to start of the file diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h index 8f716c5d02..ade283bb85 100644 --- a/indra/llimage/llimagedimensionsinfo.h +++ b/indra/llimage/llimagedimensionsinfo.h @@ -55,6 +55,12 @@ public: { return mLastError; } + + const std::string& getWarningName() + { + return mWarning; + } + protected: void clean() @@ -129,6 +135,7 @@ protected: std::string mSrcFilename; std::string mLastError; + std::string mWarning; U8* mData; -- cgit v1.3 From 87f496cf7c1c71510e4cb995661f8da5691746da Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 12 Sep 2023 15:01:56 +0300 Subject: SL-20173 show notification when file is empty --- indra/llimage/llimagedimensionsinfo.cpp | 7 ++++--- indra/newview/lllocalbitmaps.cpp | 7 ++++++- indra/newview/skins/default/xui/en/notifications.xml | 10 +--------- indra/newview/skins/default/xui/en/strings.xml | 2 ++ 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index 5756ddb32b..9dd69ff132 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -50,6 +50,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec) if (file_size == 0) { + mWarning = "texture_load_empty_file"; setLastError("File is empty",src_filename); return false; } @@ -90,7 +91,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp() if (signature[0] != 'B' || signature[1] != 'M') { LL_WARNS() << "Not a BMP" << LL_ENDL; - mWarning = "IncorrectFormat"; + mWarning = "texture_load_format_error"; return false; } @@ -141,7 +142,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng() if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a PNG" << LL_ENDL; - mWarning = "IncorrectFormat"; + mWarning = "texture_load_format_error"; return false; } @@ -185,7 +186,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a JPEG" << LL_ENDL; - mWarning = "IncorrectFormat"; + mWarning = "texture_load_format_error"; return false; } fseek(fp, 0, SEEK_SET); // go back to start of the file diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 72ef365a6d..f435506cff 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -984,7 +984,11 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename) { LLSD args; args["NAME"] = gDirUtilp->getBaseFileName(filename); - LLNotificationsUtil::add(image_info.getWarningName(), args); + if (!image_info.getWarningName().empty()) + { + args["REASON"] = LLTrans::getString(image_info.getWarningName()); + } + LLNotificationsUtil::add("CannotUploadTexture", args); return false; } @@ -1000,6 +1004,7 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename) LLSD notif_args; notif_args["REASON"] = mImageLoadError; + notif_args["NAME"] = gDirUtilp->getBaseFileName(filename); LLNotificationsUtil::add("CannotUploadTexture", notif_args); return false; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a4b73879b8..8f79794006 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9102,7 +9102,7 @@ You locally updated a [RESOLUTION] baked texture for '[BODYREGION]' after [TIME] icon="alertmodal.tga" name="CannotUploadTexture" type="alertmodal"> -Unable to upload texture. +Unable to upload texture: '[NAME]' [REASON] fail @@ -11987,12 +11987,4 @@ Would you like to save them first? yestext="Yes"/> - -Unable to upload '[NAME]' due to the following reason: incorrect image format. - - diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0b19ad1473..a23af740fe 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3932,6 +3932,8 @@ Abuse Report none/none Can't load images larger than [WIDTH]*[HEIGHT] + Incorrect image format. + File is empty. Max outfit photo size is [WIDTH]*[HEIGHT]. Please resize or use another image Max outfit photo size is [WIDTH]*[HEIGHT]. Please select another texture Cannot verify photo dimensions. Please wait until photo size is displayed in picker -- cgit v1.3 From da48bd943923958952ea77eed858ba8372d58d9a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 23 Jan 2024 02:23:28 +0200 Subject: SL-18721 Shutdown fixes #2 Set DONE if decode thread is down instead of waiting for an update. Decodes can't be canceled, so fix potential situation where we get two responses --- indra/llimage/llimageworker.cpp | 31 ++++++++++++++++++------------- indra/llimage/llimageworker.h | 4 +++- indra/newview/lltexturefetch.cpp | 36 +++++++++++++++++++++++++++++------- 3 files changed, 50 insertions(+), 21 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index c1ee052997..fd59daad3d 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -35,8 +35,10 @@ class ImageRequest { public: ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, - const LLPointer& responder); + S32 discard, + BOOL needs_aux, + const LLPointer& responder, + U32 request_id); virtual ~ImageRequest(); /*virtual*/ bool processRequest(); @@ -48,6 +50,7 @@ private: // input LLPointer mFormattedImage; S32 mDiscardLevel; + U32 mRequestId; BOOL mNeedsAux; // output LLPointer mDecodedImageRaw; @@ -62,6 +65,7 @@ private: // MAIN THREAD LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/) + : mDecodeCount(0) { mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8)); mThreadPool->start(); @@ -92,9 +96,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + U32 decode_id = ++mDecodeCount; // Instantiate the ImageRequest right in the lambda, why not? bool posted = mThreadPool->getQueue().post( - [req = ImageRequest(image, discard, needs_aux, responder)] + [req = ImageRequest(image, discard, needs_aux, responder, decode_id)] () mutable { auto done = req.processRequest(); @@ -103,13 +108,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( if (! posted) { LL_DEBUGS() << "Tried to start decoding on shutdown" << LL_ENDL; - // should this return 0? + return 0; } - // It's important to our consumer (LLTextureFetchWorker) that we return a - // nonzero handle. It is NOT important that the nonzero handle be unique: - // nothing is ever done with it except to compare it to zero, or zero it. - return 17; + return decode_id; } void LLImageDecodeThread::shutdown() @@ -123,15 +125,18 @@ LLImageDecodeThread::Responder::~Responder() //---------------------------------------------------------------------------- -ImageRequest::ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, - const LLPointer& responder) +ImageRequest::ImageRequest(const LLPointer& image, + S32 discard, + BOOL needs_aux, + const LLPointer& responder, + U32 request_id) : mFormattedImage(image), mDiscardLevel(discard), mNeedsAux(needs_aux), mDecodedRaw(FALSE), mDecodedAux(FALSE), - mResponder(responder) + mResponder(responder), + mRequestId(request_id) { } @@ -199,7 +204,7 @@ void ImageRequest::finishRequest(bool completed) if (mResponder.notNull()) { bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); - mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); + mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux, mRequestId); } // Will automatically be deleted } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index ca4c0d93d0..b4ab9432e6 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -39,7 +39,7 @@ public: protected: virtual ~Responder(); public: - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0; }; public: @@ -53,6 +53,7 @@ public: const LLPointer& responder); size_t getPending(); size_t update(F32 max_time_ms); + S32 getTotalDecodeCount() { return mDecodeCount; } void shutdown(); private: @@ -60,6 +61,7 @@ private: // LLQueuedThread - instead this is the API by which we submit work to the // "ImageDecode" ThreadPool. std::unique_ptr mThreadPool; + LLAtomicU32 mDecodeCount; }; #endif diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 38c9b3717d..40bbe2b934 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -348,13 +348,13 @@ private: } // Threads: Tid - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success, raw, aux); + worker->callbackDecoded(success, raw, aux, request_id); } } private: @@ -398,7 +398,7 @@ public: void callbackCacheWrite(bool success); // Threads: Tid - void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id); // Threads: T* void setGetStatus(LLCore::HttpStatus status, const std::string& reason) @@ -1800,8 +1800,22 @@ bool LLTextureFetchWorker::doWork(S32 param) setState(DECODE_IMAGE_UPDATE); LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; - mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux, - new DecodeResponder(mFetcher, mID, this)); + + // In case worked manages to request decode, be shut down, + // then init and request decode again with first decode + // still in progress, assign a sufficiently unique id + mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, + discard, + mNeedsAux, + new DecodeResponder(mFetcher, mID, this)); + if (mDecodeHandle == 0) + { + // Abort, failed to put into queue. + // Happens if viewer is shutting down + setState(DONE); + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: failed to post for decoding" << LL_ENDL; + return true; + } // fall though } @@ -2305,16 +2319,24 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// // Threads: Tid -void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) +void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id) { LLMutexLock lock(&mWorkMutex); // +Mw if (mDecodeHandle == 0) { return; // aborted, ignore } + if (mDecodeHandle != decode_id) + { + // Queue doesn't support canceling old requests. + // This shouldn't normally happen, but in case it's possible that a worked + // will request decode, be aborted, reinited then start a new decode + LL_DEBUGS(LOG_TXT) << mID << " received obsolete decode's callback" << LL_ENDL; + return; // ignore + } if (mState != DECODE_IMAGE_UPDATE) { -// LL_WARNS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; mDecodeHandle = 0; return; } -- cgit v1.3