From c1c5275f20b48dee6c5477a9e1eb76fad3d5e789 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 5 Oct 2023 23:19:24 +0300 Subject: [PATCH 1/5] SL-20411 Thumbnail textures should have less of an impact on performance #1 scale thumbnail textures down to 256 when needed. As we do to chat icons. --- indra/llrender/llgltexture.cpp | 3 +- indra/llrender/llgltexture.h | 1 + indra/newview/llthumbnailctrl.cpp | 4 +- indra/newview/llthumbnailctrl.h | 1 - indra/newview/llviewertexture.cpp | 84 ++++++++++++++++++++++----- indra/newview/llviewertexturelist.cpp | 13 +++-- 6 files changed, 83 insertions(+), 23 deletions(-) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index e012eb9a62..17cc2b9834 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -113,7 +113,8 @@ void LLGLTexture::setBoostLevel(S32 level) { mBoostLevel = level ; if(mBoostLevel != LLGLTexture::BOOST_NONE - && mBoostLevel != LLGLTexture::BOOST_ICON) + && mBoostLevel != LLGLTexture::BOOST_ICON + && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL) { setNoDelete() ; } diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 8cfe7b62de..a5b666cdbd 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -64,6 +64,7 @@ public: BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. BOOST_HUD , BOOST_ICON , + BOOST_THUMBNAIL , BOOST_UI , BOOST_PREVIEW , BOOST_MAP , diff --git a/indra/newview/llthumbnailctrl.cpp b/indra/newview/llthumbnailctrl.cpp index 04130fc724..72818cf991 100644 --- a/indra/newview/llthumbnailctrl.cpp +++ b/indra/newview/llthumbnailctrl.cpp @@ -57,7 +57,6 @@ LLThumbnailCtrl::LLThumbnailCtrl(const LLThumbnailCtrl::Params& p) , mFallbackImagep(p.fallback_image) , mInteractable(p.interactable()) , mShowLoadingPlaceholder(p.show_loading()) -, mPriority(LLGLTexture::BOOST_PREVIEW) { mLoadingPlaceholderString = LLTrans::getString("texture_loading"); @@ -201,9 +200,8 @@ void LLThumbnailCtrl::setValue(const LLSD& value) if (mImageAssetID.notNull()) { // Should it support baked textures? - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_THUMBNAIL); - mTexturep->setBoostLevel(mPriority); mTexturep->forceToSaveRawImage(0); S32 desired_draw_width = mTexturep->getWidth(); diff --git a/indra/newview/llthumbnailctrl.h b/indra/newview/llthumbnailctrl.h index 686603b373..70f56c429c 100644 --- a/indra/newview/llthumbnailctrl.h +++ b/indra/newview/llthumbnailctrl.h @@ -71,7 +71,6 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; private: - S32 mPriority; bool mBorderVisible; bool mInteractable; bool mShowLoadingPlaceholder; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c458c75a40..64d69ae832 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -95,7 +95,8 @@ S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128; -const S32 DEFAULT_ICON_DIMENTIONS = 32; +const S32 DEFAULT_ICON_DIMENSIONS = 32; +const S32 DEFAULT_THUMBNAIL_DIMENSIONS = 256; U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256. U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA; bool LLViewerTexture::sFreezeImageUpdates = false; @@ -729,7 +730,8 @@ void LLViewerTexture::setBoostLevel(S32 level) if(mBoostLevel != LLViewerTexture::BOOST_NONE && mBoostLevel != LLViewerTexture::BOOST_ALM && mBoostLevel != LLViewerTexture::BOOST_SELECTED && - mBoostLevel != LLViewerTexture::BOOST_ICON) + mBoostLevel != LLViewerTexture::BOOST_ICON && + mBoostLevel != LLViewerTexture::BOOST_THUMBNAIL) { setNoDelete(); } @@ -1239,8 +1241,19 @@ void LLViewerFetchedTexture::loadFromFastCache() { // Shouldn't do anything usefull since texures in fast cache are 16x16, // it is here in case fast cache changes. - S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; - S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) + { + // scale oversized icon, no need to give more work to gl + mRawImage->scale(expected_width, expected_height); + } + } + + if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl @@ -1723,7 +1736,7 @@ void LLViewerFetchedTexture::processTextureStats() { mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; } - else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) + else if (mDontDiscard && (mBoostLevel == LLGLTexture::BOOST_ICON || mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)) { if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) { @@ -1826,7 +1839,10 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Don't decode anything we don't need priority = -4.0f; } - else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data) + else if ((mBoostLevel == LLGLTexture::BOOST_UI + || mBoostLevel == LLGLTexture::BOOST_ICON + || mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) + && !have_all_data) { priority = 1.f; } @@ -2173,8 +2189,20 @@ bool LLViewerFetchedTexture::updateFetch() if (mBoostLevel == LLGLTexture::BOOST_ICON) { - S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; - S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) + { + // scale oversized icon, no need to give more work to gl + // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy + mRawImage = mRawImage->scaled(expected_width, expected_height); + } + } + + if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl @@ -2920,7 +2948,9 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) { - if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON) + if (mSavedRawDiscardLevel != discard_level + && mBoostLevel != BOOST_ICON + && mBoostLevel != BOOST_THUMBNAIL) { mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); mRawImage->copy(getSavedRawImage()); @@ -3026,8 +3056,22 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im { if (mBoostLevel == LLGLTexture::BOOST_ICON) { - S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; - S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents()); + mCachedRawImage->copyScaled(imageraw); + } + else + { + mCachedRawImage = imageraw; + } + } + else if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) { mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents()); @@ -3132,8 +3176,22 @@ void LLViewerFetchedTexture::saveRawImage() mSavedRawDiscardLevel = mRawDiscardLevel; if (mBoostLevel == LLGLTexture::BOOST_ICON) { - S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; - S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; + if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + { + mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents()); + mSavedRawImage->copyScaled(mRawImage); + } + else + { + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); + } + } + else if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) + { + S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; + S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) { mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents()); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 0d34160bda..7935adb3e2 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -71,7 +71,7 @@ LLViewerTextureList gTextureList; ETexListType get_element_type(S32 priority) { - return (priority == LLViewerFetchedTexture::BOOST_ICON) ? TEX_LIST_SCALE : TEX_LIST_STANDARD; + return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD; } /////////////////////////////////////////////////////////////////////////////// @@ -498,7 +498,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& { imagep->dontDiscard(); } - if (boost_priority == LLViewerFetchedTexture::BOOST_ICON) + if (boost_priority == LLViewerFetchedTexture::BOOST_ICON + || boost_priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) { // Agent and group Icons are downloadable content, nothing manages // icon deletion yet, so they should not persist @@ -615,7 +616,8 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, { imagep->dontDiscard(); } - if (boost_priority == LLViewerFetchedTexture::BOOST_ICON) + if (boost_priority == LLViewerFetchedTexture::BOOST_ICON + || boost_priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) { // Agent and group Icons are downloadable content, nothing manages // icon deletion yet, so they should not persist. @@ -1696,8 +1698,9 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st LLUIImagePtr new_imagep = new LLUIImage(name, imagep); new_imagep->setScaleStyle(scale_style); - if (imagep->getBoostLevel() != LLGLTexture::BOOST_ICON && - imagep->getBoostLevel() != LLGLTexture::BOOST_PREVIEW) + if (imagep->getBoostLevel() != LLGLTexture::BOOST_ICON + && imagep->getBoostLevel() != LLGLTexture::BOOST_THUMBNAIL + && imagep->getBoostLevel() != LLGLTexture::BOOST_PREVIEW) { // Don't add downloadable content into this list // all UI images are non-deletable and list does not support deletion From 2968e8bea5cde5b27ae806cf4bb2d36b254e94d8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 6 Oct 2023 23:27:11 +0300 Subject: [PATCH 2/5] SL-20411 Don't load all thumnails at once for large folders #2 --- indra/newview/llinventorygallery.cpp | 26 +++++-- indra/newview/llinventorygallery.h | 4 ++ indra/newview/llthumbnailctrl.cpp | 101 ++++++++++++++++++--------- indra/newview/llthumbnailctrl.h | 8 +++ 4 files changed, 102 insertions(+), 37 deletions(-) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 0e4c64a641..d4ca58f778 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -58,6 +58,7 @@ static LLPanelInjector t_inventory_gallery("inventory_gallery"); const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; +const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately // Helper dnd functions BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL drop, std::string& tooltip_msg, BOOL is_link); @@ -106,6 +107,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), mRootDirty(false), + mLoadThumbnailsImmediately(true), mNeedsArrange(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) @@ -540,6 +542,12 @@ void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) int n_prev = n - 1; int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + // Avoid loading too many items. + // Intent is for small folders to display all content fast + // and for large folders to load content mostly as needed + // Todo: ideally needs to unload images outside visible area + mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD; + bool add_row = row_count != row_count_prev; int pos = 0; if (add_row) @@ -573,6 +581,8 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item, boo mItemsAddedCount--; mIndexToItemMap.erase(mItemsAddedCount); + mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD; + bool remove_row = row_count != row_count_prev; removeFromLastRow(mItems[mItemsAddedCount]); mItems.pop_back(); @@ -636,6 +646,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setUUID(item_id); gitem->setGallery(this); gitem->setType(type, inventory_type, flags, is_link); + gitem->setLoadImmediately(mLoadThumbnailsImmediately); gitem->setThumbnail(thumbnail_id); gitem->setWorn(is_worn); gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); @@ -997,6 +1008,7 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) if (mItemMap[item_id]) { + mItemMap[item_id]->setLoadImmediately(mLoadThumbnailsImmediately); mItemMap[item_id]->setThumbnail(thumbnail_id); bool passes_filter = checkAgainstFilters(mItemMap[item_id], mFilterSubString); @@ -2568,6 +2580,7 @@ BOOL LLInventoryGalleryItem::postBuild() { mNameText = getChild("item_name"); mTextBgPanel = getChild("text_bg_panel"); + mThumbnailCtrl = getChild("preview_thumbnail"); return TRUE; } @@ -2643,14 +2656,19 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id) mDefaultImage = id.isNull(); if(mDefaultImage) { - getChild("preview_thumbnail")->clearTexture(); + mThumbnailCtrl->clearTexture(); } else { - getChild("preview_thumbnail")->setValue(id); + mThumbnailCtrl->setValue(id); } } +void LLInventoryGalleryItem::setLoadImmediately(bool val) +{ + mThumbnailCtrl->setInitImmediately(val); +} + void LLInventoryGalleryItem::draw() { if (isFadeItem()) @@ -2665,7 +2683,7 @@ void LLInventoryGalleryItem::draw() // Draw border LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); - LLRect border = getChildView("preview_thumbnail")->getRect(); + LLRect border = mThumbnailCtrl->getRect(); border.mRight = border.mRight + 1; border.mTop = border.mTop + 1; gl_rect_2d(border, border_color.get(), FALSE); @@ -2887,7 +2905,7 @@ void LLInventoryGalleryItem::updateNameText() mNameText->setFont(getTextFont()); mNameText->setText(mItemName + mPermSuffix + mWornSuffix); mNameText->setToolTip(mItemName + mPermSuffix + mWornSuffix); - getChild("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix); + mThumbnailCtrl->setToolTip(mItemName + mPermSuffix + mWornSuffix); } bool LLInventoryGalleryItem::isFadeItem() diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 9b3f12701f..0c52e7b713 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -39,6 +39,7 @@ class LLInventoryGalleryItem; class LLScrollContainer; class LLTextBox; class LLThumbnailsObserver; +class LLThumbnailCtrl; class LLGalleryGestureObserver; class LLInventoryGalleryContextMenu; @@ -246,6 +247,7 @@ private: int mRowCount; int mItemsAddedCount; bool mGalleryCreated; + bool mLoadThumbnailsImmediately; bool mNeedsArrange; /* Params */ @@ -342,6 +344,7 @@ public: LLAssetType::EType getAssetType() { return mType; } void setThumbnail(LLUUID id); void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; } + void setLoadImmediately(bool val); bool isFolder() { return mIsFolder; } bool isLink() { return mIsLink; } EInventorySortGroup getSortGroup() { return mSortGroup; } @@ -354,6 +357,7 @@ private: LLUUID mUUID; LLTextBox* mNameText; LLPanel* mTextBgPanel; + LLThumbnailCtrl* mThumbnailCtrl; bool mSelected; bool mWorn; bool mDefaultImage; diff --git a/indra/newview/llthumbnailctrl.cpp b/indra/newview/llthumbnailctrl.cpp index 72818cf991..78204204af 100644 --- a/indra/newview/llthumbnailctrl.cpp +++ b/indra/newview/llthumbnailctrl.cpp @@ -57,6 +57,8 @@ LLThumbnailCtrl::LLThumbnailCtrl(const LLThumbnailCtrl::Params& p) , mFallbackImagep(p.fallback_image) , mInteractable(p.interactable()) , mShowLoadingPlaceholder(p.show_loading()) +, mInited(false) +, mInitImmediately(true) { mLoadingPlaceholderString = LLTrans::getString("texture_loading"); @@ -83,6 +85,10 @@ LLThumbnailCtrl::~LLThumbnailCtrl() void LLThumbnailCtrl::draw() { + if (!mInited) + { + initImage(); + } LLRect draw_rect = getLocalRect(); if (mBorderVisible) @@ -170,11 +176,19 @@ void LLThumbnailCtrl::draw() LLUICtrl::draw(); } +void LLThumbnailCtrl::setVisible(BOOL visible) +{ + if (!visible && mInited) + { + unloadImage(); + } + LLUICtrl::setVisible(visible); +} + void LLThumbnailCtrl::clearTexture() { - mImageAssetID = LLUUID::null; - mTexturep = nullptr; - mImagep = nullptr; + setValue(LLSD()); + mInited = true; // nothing to do } // virtual @@ -190,37 +204,11 @@ void LLThumbnailCtrl::setValue(const LLSD& value) LLUICtrl::setValue(tvalue); - mImageAssetID = LLUUID::null; - mTexturep = nullptr; - mImagep = nullptr; - - if (tvalue.isUUID()) - { - mImageAssetID = tvalue.asUUID(); - if (mImageAssetID.notNull()) - { - // Should it support baked textures? - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_THUMBNAIL); - - mTexturep->forceToSaveRawImage(0); - - S32 desired_draw_width = mTexturep->getWidth(); - S32 desired_draw_height = mTexturep->getHeight(); - - mTexturep->setKnownDrawSize(desired_draw_width, desired_draw_height); - } - } - else if (tvalue.isString()) + unloadImage(); + + if (mInitImmediately) { - mImagep = LLUI::getUIImage(tvalue.asString(), LLGLTexture::BOOST_UI); - if (mImagep) - { - LLViewerFetchedTexture* texture = dynamic_cast(mImagep->getImage().get()); - if(texture) - { - mImageAssetID = texture->getID(); - } - } + initImage(); } } @@ -234,4 +222,51 @@ BOOL LLThumbnailCtrl::handleHover(S32 x, S32 y, MASK mask) return LLUICtrl::handleHover(x, y, mask); } +void LLThumbnailCtrl::initImage() +{ + if (mInited) + { + return; + } + mInited = true; + LLSD tvalue = getValue(); + + if (tvalue.isUUID()) + { + mImageAssetID = tvalue.asUUID(); + if (mImageAssetID.notNull()) + { + // Should it support baked textures? + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_THUMBNAIL); + + mTexturep->forceToSaveRawImage(0); + + S32 desired_draw_width = mTexturep->getWidth(); + S32 desired_draw_height = mTexturep->getHeight(); + + mTexturep->setKnownDrawSize(desired_draw_width, desired_draw_height); + } + } + else if (tvalue.isString()) + { + mImagep = LLUI::getUIImage(tvalue.asString(), LLGLTexture::BOOST_UI); + if (mImagep) + { + LLViewerFetchedTexture* texture = dynamic_cast(mImagep->getImage().get()); + if (texture) + { + mImageAssetID = texture->getID(); + } + } + } +} + +void LLThumbnailCtrl::unloadImage() +{ + mImageAssetID = LLUUID::null; + mTexturep = nullptr; + mImagep = nullptr; + mInited = false; +} + diff --git a/indra/newview/llthumbnailctrl.h b/indra/newview/llthumbnailctrl.h index 70f56c429c..f84a583271 100644 --- a/indra/newview/llthumbnailctrl.h +++ b/indra/newview/llthumbnailctrl.h @@ -64,16 +64,24 @@ public: virtual ~LLThumbnailCtrl(); virtual void draw() override; + void setVisible(BOOL visible) override; virtual void setValue(const LLSD& value ) override; + void setInitImmediately(bool val) { mInitImmediately = val; } void clearTexture(); virtual BOOL handleHover(S32 x, S32 y, MASK mask) override; + +protected: + void initImage(); + void unloadImage(); private: bool mBorderVisible; bool mInteractable; bool mShowLoadingPlaceholder; + bool mInited; + bool mInitImmediately; std::string mLoadingPlaceholderString; LLUUID mImageAssetID; LLViewBorder* mBorder; From f2a1c44c63641bed0e80561ff9066fa8588eb86c Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Mon, 9 Oct 2023 20:33:26 +0300 Subject: [PATCH 3/5] SL-20377 Sort group notices by date --- indra/newview/llpanelgroupnotices.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index ab32ea3956..8e4c195013 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -249,6 +249,7 @@ BOOL LLPanelGroupNotices::postBuild() mNoticesList = getChild("notice_list",recurse); mNoticesList->setCommitOnSelectionChange(TRUE); mNoticesList->setCommitCallback(onSelectNotice, this); + mNoticesList->sortByColumn("date", false); mBtnNewMessage = getChild("create_new_notice",recurse); mBtnNewMessage->setClickedCallback(onClickNewMessage, this); From d60b28e4cb2c69acbbd01ca56b03c19c1df4041a Mon Sep 17 00:00:00 2001 From: PanteraPolnocy Date: Sun, 8 Oct 2023 02:21:16 +0200 Subject: [PATCH 4/5] Get rid of a duplicate notification InventoryLimitReachedAIS --- indra/newview/skins/default/xui/en/notifications.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 204fead7e0..ac63786b15 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6440,14 +6440,6 @@ Your trash is overflowing. This may cause problems logging in. yestext="Check trash folder"/> - -Your inventory is experiencing issues. Please, contact support. - fail - - Date: Mon, 9 Oct 2023 23:39:45 +0200 Subject: [PATCH 5/5] SL-20288 Lags in Appearance floater --- indra/newview/lloutfitslist.cpp | 89 +++++++++++++++++++++++++++------ indra/newview/lloutfitslist.h | 14 +++++- 2 files changed, 88 insertions(+), 15 deletions(-) diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 5c7792b0df..8042b87a44 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -835,7 +835,6 @@ void LLOutfitListBase::onOpen(const LLSD& info) // arrive. category->fetch(); refreshList(outfits); - highlightBaseOutfit(); mIsInitialized = true; } @@ -843,6 +842,9 @@ void LLOutfitListBase::onOpen(const LLSD& info) void LLOutfitListBase::refreshList(const LLUUID& category_id) { + bool wasNull = mRefreshListState.CategoryUUID.isNull(); + mRefreshListState.CategoryUUID.setNull(); + LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; @@ -855,27 +857,81 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) LLInventoryModel::EXCLUDE_TRASH, is_category); - uuid_vec_t vadded; - uuid_vec_t vremoved; + // Memorize item names for each UUID + std::map names; + for (const LLPointer& cat : cat_array) + { + names.emplace(std::make_pair(cat->getUUID(), cat->getName())); + } - // Create added and removed items vectors. - computeDifference(cat_array, vadded, vremoved); + // Fill added and removed items vectors. + mRefreshListState.Added.clear(); + mRefreshListState.Removed.clear(); + computeDifference(cat_array, mRefreshListState.Added, mRefreshListState.Removed); + // Sort added items vector by item name. + std::sort(mRefreshListState.Added.begin(), mRefreshListState.Added.end(), + [names](const LLUUID& a, const LLUUID& b) + { + return LLStringUtil::compareDict(names.at(a), names.at(b)) < 0; + }); + // Initialize iterators for added and removed items vectors. + mRefreshListState.AddedIterator = mRefreshListState.Added.begin(); + mRefreshListState.RemovedIterator = mRefreshListState.Removed.begin(); + + LL_INFOS() << "added: " << mRefreshListState.Added.size() << + ", removed: " << mRefreshListState.Removed.size() << + ", changed: " << gInventory.getChangedIDs().size() << + LL_ENDL; + + mRefreshListState.CategoryUUID = category_id; + if (wasNull) + { + gIdleCallbacks.addFunction(onIdle, this); + } +} + +// static +void LLOutfitListBase::onIdle(void* userdata) +{ + LLOutfitListBase* self = (LLOutfitListBase*)userdata; + + self->onIdleRefreshList(); +} + +void LLOutfitListBase::onIdleRefreshList() +{ + if (mRefreshListState.CategoryUUID.isNull()) + return; + + const F64 MAX_TIME = 0.05f; + F64 curent_time = LLTimer::getTotalSeconds(); + const F64 end_time = curent_time + MAX_TIME; // Handle added tabs. - for (uuid_vec_t::const_iterator iter = vadded.begin(); - iter != vadded.end(); - ++iter) + while (mRefreshListState.AddedIterator < mRefreshListState.Added.end()) { - const LLUUID cat_id = (*iter); + const LLUUID cat_id = (*mRefreshListState.AddedIterator++); updateAddedCategory(cat_id); + + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; } + mRefreshListState.Added.clear(); + mRefreshListState.AddedIterator = mRefreshListState.Added.end(); // Handle removed tabs. - for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + while (mRefreshListState.RemovedIterator < mRefreshListState.Removed.end()) { - const LLUUID cat_id = (*iter); + const LLUUID cat_id = (*mRefreshListState.RemovedIterator++); updateRemovedCategory(cat_id); + + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; } + mRefreshListState.Removed.clear(); + mRefreshListState.RemovedIterator = mRefreshListState.Removed.end(); // Get changed items from inventory model and update outfit tabs // which might have been renamed. @@ -888,9 +944,9 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) if (!cat) { LLInventoryObject* obj = gInventory.getObject(*items_iter); - if(!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) + if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) { - return; + break; } cat = (LLViewerInventoryCategory*)obj; } @@ -900,6 +956,12 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) } sortOutfits(); + highlightBaseOutfit(); + + gIdleCallbacks.deleteFunction(onIdle, this); + mRefreshListState.CategoryUUID.setNull(); + + LL_INFOS() << "done" << LL_ENDL; } void LLOutfitListBase::computeDifference( @@ -936,7 +998,6 @@ void LLOutfitListBase::highlightBaseOutfit() mHighlightedOutfitUUID = base_id; onHighlightBaseOutfit(base_id, prev_id); } - } void LLOutfitListBase::removeSelected() diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 66b3165169..7d212420a2 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -116,8 +116,20 @@ protected: void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0; + static void onIdle(void* userdata); + void onIdleRefreshList(); + + struct + { + LLUUID CategoryUUID; + uuid_vec_t Added; + uuid_vec_t Removed; + uuid_vec_t::const_iterator AddedIterator; + uuid_vec_t::const_iterator RemovedIterator; + } mRefreshListState; + bool mIsInitialized; - LLInventoryCategoriesObserver* mCategoriesObserver; + LLInventoryCategoriesObserver* mCategoriesObserver; LLUUID mSelectedOutfitUUID; // id of currently highlited outfit LLUUID mHighlightedOutfitUUID;