From dab2fa75dd3ab599aecc18ace6c688b7e78dfaa0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 22 Oct 2025 16:57:04 +0300 Subject: [PATCH 01/17] #4876 Fix material not applying 1. Dupplicate call in llselectmgr can cause race conditions 2. lltooldragndrop wasn't updating server in one case --- indra/newview/llselectmgr.cpp | 1 - indra/newview/lltooldraganddrop.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index be4b449e2a..4762fc555d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2073,7 +2073,6 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) objectp->clearTEWaterExclusion(te); // Blank out most override data on the object and send to server - objectp->setRenderMaterialID(te, asset_id); if (should_preserve_transforms && preserved_override) { // Apply material with preserved transforms diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index d0c0bdb5ce..f78ff2226c 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1537,7 +1537,7 @@ void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj, } else { - hit_obj->setRenderMaterialID(te, asset_id, false, true); + hit_obj->setRenderMaterialID(te, asset_id); } } } From 1c393aed78753093e77fd5ca595d4e6108cf858c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:38:13 +0300 Subject: [PATCH 02/17] #4884 Crash at resetRegionCrossingTimer --- indra/newview/llviewermessage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 16b7ac33b8..e9f6d7175e 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3139,7 +3139,10 @@ void process_crossed_region(LLMessageSystem* msg, void**) return; } LL_INFOS("Messaging") << "process_crossed_region()" << LL_ENDL; - gAgentAvatarp->resetRegionCrossingTimer(); + if (isAgentAvatarValid()) + { + gAgentAvatarp->resetRegionCrossingTimer(); + } U32 sim_ip; msg->getIPAddrFast(_PREHASH_RegionData, _PREHASH_SimIP, sim_ip); From 1fc0eca1198c8a8fcfc17e94f2961c934d65bc69 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 23 Oct 2025 16:06:25 +0300 Subject: [PATCH 03/17] #4886 Crash on LLTeleportRequestViaLure::toOstream --- indra/newview/llagent.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 085155714a..e95d192f72 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -167,7 +167,7 @@ std::map LLTeleportRequest::sTeleportStatusName = { { kPending class LLTeleportRequestViaLandmark : public LLTeleportRequest { public: - LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); + LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId, bool log = true); virtual ~LLTeleportRequestViaLandmark(); virtual void toOstream(std::ostream& os) const; @@ -179,6 +179,7 @@ public: protected: inline const LLUUID &getLandmarkId() const {return mLandmarkId;}; + bool mLogOnDestruction = true; private: LLUUID mLandmarkId; @@ -5008,16 +5009,25 @@ void LLTeleportRequest::toOstream(std::ostream& os) const //----------------------------------------------------------------------------- // LLTeleportRequestViaLandmark //----------------------------------------------------------------------------- -LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId) - : LLTeleportRequest(), - mLandmarkId(pLandmarkId) +LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId, bool log) + : LLTeleportRequest() + , mLandmarkId(pLandmarkId) + , mLogOnDestruction(true) { - LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark created, " << *this << LL_ENDL; + if (log) + { + // Workaround to not log twice for LLTeleportRequestViaLure, besides this wouldn't have logged fully. + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark created, " << *this << LL_ENDL; + } } LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() { - LL_INFOS("Teleport") << "~LLTeleportRequestViaLandmark, " << *this << LL_ENDL; + if (mLogOnDestruction) + { + // Workaround to not crash on toOstream for derived classes and to not log twice. + LL_INFOS("Teleport") << "~LLTeleportRequestViaLandmark, " << *this << LL_ENDL; + } } void LLTeleportRequestViaLandmark::toOstream(std::ostream& os) const @@ -5047,16 +5057,20 @@ void LLTeleportRequestViaLandmark::restartTeleport() // LLTeleportRequestViaLure //----------------------------------------------------------------------------- -LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, bool pIsLureGodLike) - : LLTeleportRequestViaLandmark(pLureId), +LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID& pLureId, bool pIsLureGodLike) + : LLTeleportRequestViaLandmark(pLureId, false), mIsLureGodLike(pIsLureGodLike) { - LL_INFOS("Teleport") << "LLTeleportRequestViaLure created" << LL_ENDL; + LL_INFOS("Teleport") << "LLTeleportRequestViaLure created: " << *this << LL_ENDL; } LLTeleportRequestViaLure::~LLTeleportRequestViaLure() { - LL_INFOS("Teleport") << "~LLTeleportRequestViaLure" << LL_ENDL; + if (mLogOnDestruction) + { + LL_INFOS("Teleport") << "~LLTeleportRequestViaLure: " << *this << LL_ENDL; + mLogOnDestruction = false; + } } void LLTeleportRequestViaLure::toOstream(std::ostream& os) const From a12552408570e2e0e689cbdd4671f316568d0205 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 31 Oct 2025 15:29:07 +0200 Subject: [PATCH 04/17] #4847 log session_jitter and period_jitter with FPS info --- indra/newview/llviewerdisplay.cpp | 5 ++++- indra/newview/llviewerstats.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 4c408ec17d..35ac7919ac 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -240,8 +240,11 @@ void display_stats() if (gRecentFPSTime.getElapsedTimeF32() >= FPS_LOG_FREQUENCY) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - FPS"); + LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecording(); + F64 normalized_session_jitter = recording.getLastValue(LLStatViewer::NOTRMALIZED_FRAMETIME_JITTER_SESSION); + F64 normalized_period_jitter = recording.getLastValue(LLStatViewer::NORMALIZED_FRAMTIME_JITTER_PERIOD); F32 fps = gRecentFrameCount / FPS_LOG_FREQUENCY; - LL_INFOS() << llformat("FPS: %.02f", fps) << LL_ENDL; + LL_INFOS() << llformat("FPS: %.02f SESSION JITTER: %.4f PERIOD JITTER: %.4f", fps, normalized_session_jitter, normalized_period_jitter) << LL_ENDL; gRecentFrameCount = 0; gRecentFPSTime.reset(); } diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 011269d7ee..1ac8b2f66b 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -229,6 +229,9 @@ extern LLTrace::EventStatHandle AVATAR_EDIT_TIME, extern LLTrace::EventStatHandle > OBJECT_CACHE_HIT_RATE; +extern LLTrace::SampleStatHandle NOTRMALIZED_FRAMETIME_JITTER_SESSION; +extern LLTrace::SampleStatHandle NORMALIZED_FRAMTIME_JITTER_PERIOD; + } class LLViewerStats : public LLSingleton From f7516a463114e3982b7d4cbd86645fc4369ffce9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:47:01 +0200 Subject: [PATCH 05/17] #4918 Crash at LLPluginProcessParent::poll Bugsplat shows that mutex is null. It's possible that no instances exist thus mutex wasn't initialized. --- indra/llplugin/llpluginprocessparent.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 02c7d9507d..4f55d75e7d 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -982,15 +982,18 @@ void LLPluginProcessParent::poll(F64 timeout) } } - // Remove instances in the done state from the sInstances map. - LLCoros::LockType lock(*sInstancesMutex); - mapInstances_t::iterator itClean = sInstances.begin(); - while (itClean != sInstances.end()) + if (sInstancesMutex) { - if ((*itClean).second->isDone()) - itClean = sInstances.erase(itClean); - else - ++itClean; + // Remove instances in the done state from the sInstances map. + LLCoros::LockType lock(*sInstancesMutex); + mapInstances_t::iterator itClean = sInstances.begin(); + while (itClean != sInstances.end()) + { + if ((*itClean).second->isDone()) + itClean = sInstances.erase(itClean); + else + ++itClean; + } } } From 6979b1ff501d3db226d540475c17ef9c85fd15a0 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 3 Nov 2025 19:05:46 +0200 Subject: [PATCH 06/17] #4920 fix group categories not being displayed when one below is expanded --- indra/llui/llaccordionctrl.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 1a64c2699d..2cd394476e 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -303,11 +303,8 @@ void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S3 return; LLRect panel_rect = panel->getRect(); panel_rect.setLeftTopAndSize( left, top, width, height); - if (panel->getRect() != panel_rect) - { - panel->reshape( width, height, 1); - panel->setRect(panel_rect); - } + panel->reshape( width, height, 1); + panel->setRect(panel_rect); } void LLAccordionCtrl::ctrlShiftVertical(LLView* panel, S32 delta) From d23379939c73daa7236fd279458f6037f8baf57e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Mon, 27 Oct 2025 22:13:34 +0200 Subject: [PATCH 07/17] #4879 An Emoji in a display name can affect text in chat An emoji was spliting inlineview thus affecting displayed text. --- indra/llui/lltextbase.cpp | 30 ++++++++++++++++++++++++++++++ indra/llui/lltextbase.h | 2 ++ 2 files changed, 32 insertions(+) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 1de12896eb..44151a4355 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1038,8 +1038,37 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s { LLStyleSP emoji_style; LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL; + LLTextSegment* segmentp = nullptr; + segment_vec_t::iterator seg_iter; + if (segments && segments->size() > 0) + { + seg_iter = segments->begin(); + segmentp = *seg_iter; + } for (S32 text_kitty = 0, text_len = static_cast(wstr.size()); text_kitty < text_len; text_kitty++) { + if (segmentp) + { + if (segmentp->getEnd() <= pos + text_kitty) + { + seg_iter++; + if (seg_iter != segments->end()) + { + segmentp = *seg_iter; + } + else + { + segmentp = nullptr; + } + } + if (segmentp && !segmentp->getPermitsEmoji()) + { + // Some segments, like LLInlineViewSegment do not permit splitting + // and should not be interrupted by emoji segments + continue; + } + } + llwchar code = wstr[text_kitty]; bool isEmoji = ed ? ed->isEmoji(code) : LLStringOps::isEmoji(code); if (isEmoji) @@ -3448,6 +3477,7 @@ S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offs void LLTextSegment::updateLayout(const LLTextBase& editor) {} F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect) { return draw_rect.mLeft; } bool LLTextSegment::canEdit() const { return false; } +bool LLTextSegment::getPermitsEmoji() const { return true; } void LLTextSegment::unlinkFromDocument(LLTextBase*) {} void LLTextSegment::linkToDocument(LLTextBase*) {} const LLUIColor& LLTextSegment::getColor() const { static const LLUIColor white = LLUIColorTable::instance().getColor("White", LLColor4::white); return white; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 07cd9a1ee5..50767a35b3 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -87,6 +87,7 @@ public: virtual void updateLayout(const class LLTextBase& editor); virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); virtual bool canEdit() const; + virtual bool getPermitsEmoji() const; virtual void unlinkFromDocument(class LLTextBase* editor); virtual void linkToDocument(class LLTextBase* editor); @@ -255,6 +256,7 @@ public: /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); /*virtual*/ bool canEdit() const { return false; } + /*virtual*/ bool getPermitsEmoji() const { return false; } /*virtual*/ void unlinkFromDocument(class LLTextBase* editor); /*virtual*/ void linkToDocument(class LLTextBase* editor); From 11ccdb5e32f4c997c0dd65464c1c7c7b469aa4d2 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Fri, 31 Oct 2025 16:39:17 +0100 Subject: [PATCH 08/17] Fix XUI parser warnings: * LLFloaterMarketplace::postBuild calls parent method which already tries to find the webbrowser control with a different name and adds itself as observer * Incorrect attribute name "tooltip" in panel_preferences_move.xml --- indra/newview/llfloatermarketplace.cpp | 6 +++--- indra/newview/skins/default/xui/en/floater_marketplace.xml | 2 +- .../newview/skins/default/xui/en/panel_preferences_move.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp index d626786591..7316d7617d 100644 --- a/indra/newview/llfloatermarketplace.cpp +++ b/indra/newview/llfloatermarketplace.cpp @@ -46,9 +46,9 @@ void LLFloaterMarketplace::onClose(bool app_quitting) bool LLFloaterMarketplace::postBuild() { - LLFloaterWebContent::postBuild(); - mWebBrowser = getChild("marketplace_contents"); - mWebBrowser->addObserver(this); + if (!LLFloaterWebContent::postBuild()) + return false; + mWebBrowser->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); std::string url = gSavedSettings.getString("MarketplaceURL"); mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); diff --git a/indra/newview/skins/default/xui/en/floater_marketplace.xml b/indra/newview/skins/default/xui/en/floater_marketplace.xml index 99fb3a1ad8..40bf674d2d 100644 --- a/indra/newview/skins/default/xui/en/floater_marketplace.xml +++ b/indra/newview/skins/default/xui/en/floater_marketplace.xml @@ -169,7 +169,7 @@ follows="all" layout="topleft" left="0" - name="marketplace_contents" + name="webbrowser" top="0"/> Date: Tue, 4 Nov 2025 18:08:20 +0100 Subject: [PATCH 09/17] Use correct widget name for marketplace floater --- indra/newview/llviewermedia.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index ec8c00bebc..6930165aac 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1365,7 +1365,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) }; struct MediaCookieInstance media_cookie_instances[] = { {"search", "search_contents" }, - {"marketplace", "marketplace_contents" }, + {"marketplace", "webbrowser" }, {"destinations", "destination_guide_contents" }, }; for (MediaCookieInstance mci : media_cookie_instances) From 5e11448e4fccb56d03eb9a7b18774b8c550683b7 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 4 Nov 2025 18:43:51 +0100 Subject: [PATCH 10/17] Fix remaining cases of webbrowser-related XUI warnings --- indra/newview/llfloatersearch.cpp | 9 ++++----- indra/newview/llviewermedia.cpp | 2 +- indra/newview/skins/default/xui/en/floater_search.xml | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index ec9af865cf..9b7a4e5134 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -161,15 +161,14 @@ void LLFloaterSearch::initiateSearch(const LLSD& tokens) // Naviation to the calculated URL - we know it's HTML so we can // tell the media system not to bother with the MIME type check. - LLMediaCtrl* search_browser = findChild("search_contents"); - search_browser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } bool LLFloaterSearch::postBuild() { - LLFloaterWebContent::postBuild(); - mWebBrowser = getChild("search_contents"); - mWebBrowser->addObserver(this); + if (!LLFloaterWebContent::postBuild()) + return false; + mWebBrowser->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); // If cookie is there, will set it now, Otherwise will have to wait for login completion diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 6930165aac..8f229850c0 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1364,7 +1364,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) std::string browser_name; }; struct MediaCookieInstance media_cookie_instances[] = { - {"search", "search_contents" }, + {"search", "webbrowser" }, {"marketplace", "webbrowser" }, {"destinations", "destination_guide_contents" }, }; diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 43c4aa1b9d..8891ebcd87 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -170,7 +170,7 @@ layout="topleft" left="0" trusted_content="true" - name="search_contents" + name="webbrowser" top="0"/> Date: Wed, 5 Nov 2025 12:33:24 +0200 Subject: [PATCH 11/17] #4785 The Apply button is not activated after changing a Material --- indra/newview/llfloaterregioninfo.cpp | 34 +++++++++++++++++---------- indra/newview/llfloaterregioninfo.h | 1 + 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 334f32d051..2b243ef972 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -270,10 +270,12 @@ bool LLFloaterRegionInfo::postBuild() static LLCachedControl feature_pbr_terrain_transforms_enabled(gSavedSettings, "RenderTerrainPBRTransformsEnabled", false); if (!feature_pbr_terrain_transforms_enabled() || !feature_pbr_terrain_enabled()) { + LL_INFOS("Terrain") << "Building region terrain panel from panel_region_terrain.xml" << LL_ENDL; panel->buildFromFile("panel_region_terrain.xml"); } else { + LL_INFOS("Terrain") << "Building region terrain panel from panel_region_terrain_texture_transform.xml" << LL_ENDL; panel->buildFromFile("panel_region_terrain_texture_transform.xml"); } mTab->addTabPanel(panel); @@ -1999,18 +2001,7 @@ void LLPanelRegionTerrainInfo::initMaterialCtrl(LLTextureCtrl*& ctrl, const std: ctrl->setCommitCallback( [this, index](LLUICtrl* ctrl, const LLSD& param) { - if (!mMaterialScaleUCtrl[index] - || !mMaterialScaleVCtrl[index] - || !mMaterialRotationCtrl[index] - || !mMaterialOffsetUCtrl[index] - || !mMaterialOffsetVCtrl[index]) return; - - mMaterialScaleUCtrl[index]->setValue(1.f); - mMaterialScaleVCtrl[index]->setValue(1.f); - mMaterialRotationCtrl[index]->setValue(0.f); - mMaterialOffsetUCtrl[index]->setValue(0.f); - mMaterialOffsetVCtrl[index]->setValue(0.f); - onChangeAnything(); + callbackMaterialCommit(index); }); } @@ -2098,6 +2089,25 @@ bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, con return false; } +void LLPanelRegionTerrainInfo::callbackMaterialCommit(S32 index) +{ + // These can be null if 'transforms' panel was not inited + if (mMaterialScaleUCtrl[index] + && mMaterialScaleVCtrl[index] + && mMaterialRotationCtrl[index] + && mMaterialOffsetUCtrl[index] + && mMaterialOffsetVCtrl[index]) + { + mMaterialScaleUCtrl[index]->setValue(1.f); + mMaterialScaleVCtrl[index]->setValue(1.f); + mMaterialRotationCtrl[index]->setValue(0.f); + mMaterialOffsetUCtrl[index]->setValue(0.f); + mMaterialOffsetVCtrl[index]->setValue(0.f); + } + + onChangeAnything(); +} + ///////////////////////////////////////////////////////////////////////////// // LLPanelEstateInfo // diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index a8631c36ca..0036df9c3d 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -272,6 +272,7 @@ public: static void onClickBakeTerrain(void*); bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); bool callbackTextureHeights(const LLSD& notification, const LLSD& response); + void callbackMaterialCommit(S32 index); protected: bool sendUpdate() override; From 7a7215b85223aa8e8a1cd84478e1a7aa24b5307d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:22:09 +0200 Subject: [PATCH 12/17] #1006 Assume default material is valid for terrain assigment --- indra/newview/llfloaterregioninfo.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 2b243ef972..5ec7e94fcc 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1492,6 +1492,11 @@ bool LLPanelRegionTerrainInfo::validateMaterials() const LLUUID& material_asset_id = material_ctrl->getImageAssetID(); llassert(material_asset_id.notNull()); if (material_asset_id.isNull()) { return false; } + if (material_asset_id == BLANK_MATERIAL_ASSET_ID) + { + // Default/Blank material is valid by default + continue; + } const LLFetchedGLTFMaterial* material = gGLTFMaterialList.getMaterial(material_asset_id); if (!material->isLoaded()) { From 3694df79bf11cf9ad37ed74b7b9821d674f78730 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 6 Nov 2025 18:52:56 +0200 Subject: [PATCH 13/17] #4656 Don't scroll to a child that is already in view and can not fit --- indra/llui/llaccordionctrltab.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index bdf93348bb..828bfb289b 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -479,7 +479,34 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) // Translate to parent coordinatess to check if we are in visible rectangle rect.translate(getRect().mLeft, getRect().mBottom); - if (!getRect().contains(rect)) + bool needs_to_scroll = false; + const LLRect &acc_rect = getRect(); + if (!acc_rect.contains(rect)) + { + if (acc_rect.mTop < rect.mBottom || acc_rect.mBottom > rect.mTop) + { + // Content fully not in view + needs_to_scroll = true; + } + else if (acc_rect.getHeight() >= rect.getHeight()) + { + // Content can be displayed fully, but only partially in view + needs_to_scroll = true; + } + else if (acc_rect.mTop <= rect.mTop || acc_rect.mBottom >= rect.mBottom) + { + // Intersects, but too big to be displayed fully + S32 covered_height = acc_rect.mTop > rect.mTop ? rect.mTop - acc_rect.mBottom : acc_rect.mTop - rect.mBottom; + constexpr F32 covered_ratio = 0.7f; + if (covered_height < covered_ratio * acc_rect.getHeight()) + { + // Try to show bigger portion of the content + needs_to_scroll = true; + } + } + // else too big and in the middle of the view as is + } + if (needs_to_scroll) { // for accordition's scroll, height is in pixels // Back to local coords and calculate position for scroller From 4e78b4c9fe429f75f1ff99a8af59c277276c2bc1 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 6 Nov 2025 20:16:55 +0200 Subject: [PATCH 14/17] #4651 Distinguish logout crashes from other crashes --- indra/newview/llappviewerwin32.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index a951338138..64b506a335 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -179,7 +179,14 @@ namespace // If marker doesn't exist, create a marker with 'other' code for next launch // otherwise don't override existing file // Any unmarked crashes will be considered as freezes - app->createErrorMarker(LAST_EXEC_OTHER_CRASH); + if (app->logoutRequestSent()) + { + app->createErrorMarker(LAST_EXEC_LOGOUT_CRASH); + } + else + { + app->createErrorMarker(LAST_EXEC_OTHER_CRASH); + } } } // MDSCB_EXCEPTIONCODE From bcecb3dc10579c4403d92aeb040fc550b08457a9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:33:36 +0200 Subject: [PATCH 15/17] #4949 QueuedRequest destructor crash --- indra/llcommon/llqueuedthread.cpp | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 0196a24b18..efeeb1340e 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -80,7 +80,7 @@ void LLQueuedThread::shutdown() mRequestQueue.close(); } - S32 timeout = 100; + S32 timeout = 50; for ( ; timeout>0; timeout--) { if (isStopped()) @@ -101,19 +101,34 @@ void LLQueuedThread::shutdown() } QueuedRequest* req; - S32 active_count = 0; + S32 queued_count = 0; + bool has_active = false; + lockData(); while ( (req = (QueuedRequest*)mRequestHash.pop_element()) ) { - if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS) + if (req->getStatus() == STATUS_INPROGRESS) { - ++active_count; + has_active = true; + req->setFlags(FLAG_ABORT | FLAG_AUTO_COMPLETE); + continue; + } + if (req->getStatus() == STATUS_QUEUED) + { + ++queued_count; req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest } req->deleteRequest(); } - if (active_count) + unlockData(); + if (queued_count) { - LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL; + LL_WARNS() << "~LLQueuedThread() called with unpocessed requests: " << queued_count << LL_ENDL; + } + if (has_active) + { + LL_WARNS() << "~LLQueuedThread() called with active requests!" << LL_ENDL; + ms_sleep(100); // last chance for request to finish + printQueueStats(); } mRequestQueue.close(); @@ -570,7 +585,12 @@ LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U3 LLQueuedThread::QueuedRequest::~QueuedRequest() { - llassert_always(mStatus == STATUS_DELETE); + if (mStatus != STATUS_DELETE) + { + // The only method to delete a request is deleteRequest(), + // it should have set the status to STATUS_DELETE + LL_ERRS() << "LLQueuedThread::QueuedRequest deleted with status " << mStatus << LL_ENDL; + } } //virtual From 0ceefe6d270a4688720287f88b3bd5e2509909c1 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 12 Nov 2025 12:14:19 -0800 Subject: [PATCH 16/17] Disable shader profiles on RDNA3.5 to prevent freezes on startup. (#4992) * Disable shader profiling for certain AMD Radeon GPUs Added logic to detect AMD Radeon 8060 GPUs and disable shader profiling to prevent client freezes and instability. Introduced sCanProfile flag in LLGLSLShader and mSkipProfiling in LLFeatureManager to control profiling behavior based on detected hardware. * Add RDNA3.5 and check the vendor string for a known current family of bad drivers * Update llfeaturemanager.cpp * Make sure to check that this is a Radeon. --- indra/llrender/llglslshader.cpp | 3 +- indra/llrender/llglslshader.h | 1 + indra/newview/llfeaturemanager.cpp | 45 ++++++++++++++++++++++++++++++ indra/newview/llfeaturemanager.h | 2 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 9cd5dc8145..a268ea07bb 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -57,6 +57,7 @@ S32 LLGLSLShader::sIndexedTextureChannels = 0; U32 LLGLSLShader::sMaxGLTFMaterials = 0; U32 LLGLSLShader::sMaxGLTFNodes = 0; bool LLGLSLShader::sProfileEnabled = false; +bool LLGLSLShader::sCanProfile = true; std::set LLGLSLShader::sInstances; LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines; U64 LLGLSLShader::sTotalTimeElapsed = 0; @@ -267,7 +268,7 @@ void LLGLSLShader::placeProfileQuery(bool for_runtime) bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) { - if (sProfileEnabled || for_runtime) + if ((sProfileEnabled || for_runtime) && sCanProfile) { if (!mProfilePending) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 4702a27cc5..272a99aaa5 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -160,6 +160,7 @@ public: static std::set sInstances; static bool sProfileEnabled; + static bool sCanProfile; LLGLSLShader(); ~LLGLSLShader(); diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 052278f731..9f3df54b05 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -404,8 +404,53 @@ F32 logExceptionBenchmark() } #endif +bool checkRDNA35() +{ + // This checks if we're running on an RDNA3.5 GPU. You're only going to see these on AMD's APUs. + // As of driver version 25, we're seeing stalls in some of our queries. + // This appears to be a driver bug, and appears to be specific RDNA3.5 APUs. + // There's multiples of these guys, so we just use this function to check if that GPU is on the list of known RDNA3.5 APUs. + // - Geenz 11/12/2025 + std::array rdna35GPUs = { + "8060S", + "8050S", + "8040S", + "860M", + "840M", + "890M", + "880M" + }; + + for (const auto& gpu_name : rdna35GPUs) + { + if (gGLManager.getRawGLString().find(gpu_name) != std::string::npos) + { + LL_WARNS("RenderInit") << "Detected AMD RDNA3.5 GPU (" << gpu_name << ")." << LL_ENDL; + return true; + } + } + + return false; +} + bool LLFeatureManager::loadGPUClass() { + // This is a hack for certain AMD GPUs in newer driver versions on certain APUs. + // These GPUs will show inconsistent freezes when attempting to run shader profiles against them. + // This is extremely problematic as it can lead to: + // - Login freezes + // - Inability to start the client + // - Completely random avatars triggering a freeze + // As a result, we filter out these GPUs for shader profiling. + // - Geenz 11/11/2025 + + if (gGLManager.getRawGLString().find("Radeon") != std::string::npos && checkRDNA35() && gGLManager.mDriverVersionVendorString.find("25.") != std::string::npos) + { + LL_WARNS("RenderInit") << "Detected AMD RDNA3.5 GPU on a known bad driver; disabling shader profiling to prevent freezes." << LL_ENDL; + mSkipProfiling = true; + LLGLSLShader::sCanProfile = false; + } + if (!gSavedSettings.getBOOL("SkipBenchmark")) { F32 class1_gbps = gSavedSettings.getF32("RenderClass1MemoryBandwidth"); diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 22de6afbae..d04b89cb60 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -123,6 +123,7 @@ public: S32 getVersion() const { return mTableVersion; } void setSafe(const bool safe) { mSafe = safe; } bool isSafe() const { return mSafe; } + bool skipProfiling() const { return mSkipProfiling; } LLFeatureList *findMask(const std::string& name); bool maskFeatures(const std::string& name); @@ -170,6 +171,7 @@ protected: F32 mExpectedGLVersion; //expected GL version according to gpu table std::string mGPUString; bool mGPUSupported; + bool mSkipProfiling = false; }; inline From ad6008a5880dff8691f5fce56b7fbfc5ea8b1626 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 14 Nov 2025 11:40:05 -0800 Subject: [PATCH 17/17] Disable the benchmark & occlusion on RDNA3.5 (#4999) --- indra/newview/llfeaturemanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 9f3df54b05..bbf67ffb36 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -446,9 +446,9 @@ bool LLFeatureManager::loadGPUClass() if (gGLManager.getRawGLString().find("Radeon") != std::string::npos && checkRDNA35() && gGLManager.mDriverVersionVendorString.find("25.") != std::string::npos) { - LL_WARNS("RenderInit") << "Detected AMD RDNA3.5 GPU on a known bad driver; disabling shader profiling to prevent freezes." << LL_ENDL; - mSkipProfiling = true; - LLGLSLShader::sCanProfile = false; + LL_WARNS("RenderInit") << "Detected AMD RDNA3.5 GPU on a known bad driver; disabling benchmark and occlusion culling to prevent freezes." << LL_ENDL; + gSavedSettings.setBOOL("SkipBenchmark", true); + gSavedSettings.setBOOL("UseOcclusion", false); } if (!gSavedSettings.getBOOL("SkipBenchmark"))