diff options
59 files changed, 942 insertions, 205 deletions
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 60ad7e8fe5..50b0cf02bc 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,8 +42,8 @@ jobs: needs: setup strategy: matrix: - runner: [windows-large, macos-15-xlarge] - configuration: ${{ fromJSON(needs.setup.outputs.configurations) }} + runner: ${{ fromJson((github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/Second_Life')) && '["windows-large","macos-15-xlarge"]' || '["windows-latest","macos-15"]') }} + configuration: ${{ fromJson(needs.setup.outputs.configurations) }} runs-on: ${{ matrix.runner }} outputs: viewer_channel: ${{ steps.build.outputs.viewer_channel }} diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index f30c147b91..4acb0ef3d4 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -645,9 +645,10 @@ void LLWearable::addVisualParam(LLVisualParam *param) void LLWearable::setVisualParamWeight(S32 param_index, F32 value) { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + LLVisualParam *wearable_param = found->second; wearable_param->setWeight(value); } else @@ -658,10 +659,10 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value) F32 LLWearable::getVisualParamWeight(S32 param_index) const { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::const_iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; - return wearable_param->getWeight(); + return found->second->getWeight(); } else { @@ -726,7 +727,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) if (!avatarp) return; // Pull params - for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) { // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 6066e74fb5..c8ece616b2 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -17,6 +17,7 @@ // std headers // external library headers // other Linden headers +#include "llapp.h" #include "llcoros.h" #include LLCOROS_MUTEX_HEADER #include "llerror.h" @@ -102,19 +103,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name) return STRINGIZE("WorkQueue" << num); } +namespace +{ +#if LL_WINDOWS + + static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + + U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) + { + if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + { + // Handled + return EXCEPTION_CONTINUE_SEARCH; + } + else if (code == STATUS_MSC_EXCEPTION) + { + // C++ exception, go on + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + // handle it, convert to std::exception + return EXCEPTION_EXECUTE_HANDLER; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void cpphandle(const LL::WorkQueueBase::Work& work) + { + // SE and C++ can not coexists, thus two handlers + try + { + work(); + } + catch (const LLContinueError&) + { + // Any uncaught exception derived from LLContinueError will be caught + // here and logged. This coroutine will terminate but the rest of the + // viewer will carry on. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue")); + } + } + + void sehandle(const LL::WorkQueueBase::Work& work) + { + __try + { + // handle stop and continue exceptions first + cpphandle(work); + } + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + { + // convert to C++ styled exception + char integer_string[512]; + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + throw std::exception(integer_string); + } + } +#endif // LL_WINDOWS +} // anonymous namespace + void LL::WorkQueueBase::callWork(const Work& work) { LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + +#ifdef LL_WINDOWS + // can not use __try directly, toplevel requires unwinding, thus use of a wrapper + sehandle(work); +#else // LL_WINDOWS try { work(); } - catch (...) + catch (LLContinueError&) { - // No matter what goes wrong with any individual work item, the worker - // thread must go on! Log our own instance name with the exception. LOG_UNHANDLED_EXCEPTION(getKey()); } + catch (...) + { + // Stash any other kind of uncaught exception to be rethrown by main thread. + LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase " + << getKey() << LL_ENDL; + + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + main_queue->post( + // Bind the current exception, rethrow it in main loop. + [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + } +#endif // else LL_WINDOWS } void LL::WorkQueueBase::error(const std::string& msg) diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 44b6e7923b..76e5e3aae9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5586,14 +5586,22 @@ struct MikktData { U32 count = face->mNumIndices; - p.resize(count); - n.resize(count); - tc.resize(count); - t.resize(count); + try + { + p.resize(count); + n.resize(count); + tc.resize(count); + t.resize(count); - if (face->mWeights) + if (face->mWeights) + { + w.resize(count); + } + } + catch (std::bad_alloc&) { - w.resize(count); + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in MikktData, elements count: " << count << LL_ENDL; } @@ -5665,7 +5673,16 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) // and is executed on a background thread MikktData data(this); mikk::Mikktspace ctx(data); - ctx.genTangSpace(); + try + { + ctx.genTangSpace(); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + } + //re-weld meshopt_Stream mos[] = @@ -5678,7 +5695,15 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) }; std::vector<U32> remap; - remap.resize(data.p.size()); + try + { + remap.resize(data.p.size()); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; + } U32 stream_count = data.w.empty() ? 4 : 5; diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 2de59c1b6a..10fd56a68e 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -585,7 +585,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, // static void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status) + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched) { // find and callback ALL pending requests for this UUID // SJB: We process the callbacks in reverse order, I do not know if this is important, @@ -598,6 +599,10 @@ void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LL LLAssetRequest* tmp = *curiter; if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) { + if (bytes_fetched > 0) + { + tmp->mBytesFetched = bytes_fetched; + } requests.push_front(tmp); iter = gAssetStorage->mPendingDownloads.erase(curiter); } @@ -664,6 +669,7 @@ void LLAssetStorage::downloadCompleteCallback( callback_type = req->getType(); } + S32 bytes_fetched = 0; if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file @@ -677,21 +683,11 @@ void LLAssetStorage::downloadCompleteCallback( } else { -#if 1 - for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); - iter != gAssetStorage->mPendingDownloads.end(); ++iter ) - { - LLAssetRequest* dlreq = *iter; - if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type)) - { - dlreq->mBytesFetched = vfile.getSize(); - } - } -#endif + bytes_fetched = vfile.getSize(); } } - removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status); + removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status, bytes_fetched); } void LLAssetStorage::getEstateAsset( diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 88fa572092..6d6526757d 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -324,7 +324,8 @@ public: static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status); + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched); // download process callbacks static void downloadCompleteCallback( diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index d0a97dc2c6..998b57217d 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -105,6 +105,36 @@ LLCubeMapArray::LLCubeMapArray() } +LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0) +{ + mWidth = width; + mCount = count; + + // Allocate a new cubemap array with the same criteria as the incoming cubemap array + allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); + + // Copy each cubemap from the incoming array to the new array + U32 min_count = std::min(count, lhs.mCount); + for (U32 i = 0; i < min_count * 6; ++i) + { + U32 src_resolution = lhs.mWidth; + U32 dst_resolution = mWidth; + { + GLint components = GL_RGB; + if (mImage->getComponents() == 4) + components = GL_RGBA; + GLint format = GL_RGB; + + // Handle different resolutions by scaling the image + LLPointer<LLImageRaw> src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents()); + glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData()); + + LLPointer<LLImageRaw> scaled_image = src_image->scaled(mWidth, mWidth); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); + } + } +} + LLCubeMapArray::~LLCubeMapArray() { } @@ -115,6 +145,8 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us mWidth = resolution; mCount = count; + mHDR = hdr; + LLImageGL::generateTextures(1, &texname); mImage = new LLImageGL(resolution, resolution, components, use_mips); diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index bfc72a321d..6b4288cb23 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -36,6 +36,7 @@ class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); + LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count); static GLenum sTargets[6]; @@ -73,4 +74,5 @@ protected: U32 mWidth = 0; U32 mCount = 0; S32 mTextureStage; + bool mHDR; }; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 1bce31edb1..d2534b3939 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -837,7 +837,7 @@ void LLButton::draw() // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - label_color = ll::ui::SearchableControl::getHighlightColor(); + label_color = ll::ui::SearchableControl::getHighlightFontColor(); // overlay with keyboard focus border if (hasFocus()) diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 03717da80b..b10ec51f18 100644 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -170,12 +170,14 @@ bool LLCommandManager::load() if (!parser.readXUI(commands_file, commandsParams)) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL; return false; } if (!commandsParams.validateBlock()) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL; return false; } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 69ffa9a94f..c11b42a348 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -508,7 +508,7 @@ void LLMenuItemGL::draw( void ) // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - color = ll::ui::SearchableControl::getHighlightColor(); + color = ll::ui::SearchableControl::getHighlightFontColor(); // Draw the text on top. if (mBriefItem) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7405413a3d..a05feab1d9 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -614,6 +614,13 @@ void LLNotification::cancel() LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) { LLSD response = LLSD::emptyMap(); + + if (!mForm) + { + LL_WARNS("Notifications") << "Null form when getting response template for notification " << getName() << LL_ENDL; + return response; + } + for (S32 element_idx = 0; element_idx < mForm->getNumElements(); ++element_idx) @@ -1249,9 +1256,26 @@ LLNotifications::LLNotifications() LLInstanceTracker<LLNotificationChannel, std::string>::instanceCount(); } + +LLNotifications::~LLNotifications() +{ + // Clear explicitly, something in ~LLNotifications() crashes so narrowing down suspects + pHistoryChannel = nullptr; + pExpirationChannel = nullptr; + mGlobalStrings.clear(); + mTemplates.clear(); + mVisibilityRules.clear(); + mUniqueNotifications.clear(); + mListener = nullptr; +} + void LLNotifications::clear() { - mDefaultChannels.clear(); + mDefaultChannels.clear(); + // At this point mTemplates still gets used by lingering notifications + // to do responses (ex: group notice will call forceResponse()), but + // since network should be down and everything save, it's questionable + // whether it should stay that way } // The expiration channel gets all notifications that are cancelled @@ -1464,6 +1488,13 @@ bool LLNotifications::templateExists(std::string_view name) void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) { LLNotificationPtr temp_notify(new LLNotification(params)); + + if (!temp_notify->getForm()) + { + LL_WARNS("Notifications") << "Cannot force response for notification with null form: " << (std::string)params.name << LL_ENDL; + return; + } + LLSD response = temp_notify->getResponseTemplate(); LLSD selected_item = temp_notify->getForm()->getElement(option); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 46286457cf..138f1969d5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -887,7 +887,7 @@ class LLNotifications : { LLSINGLETON(LLNotifications); LOG_CLASS(LLNotifications); - virtual ~LLNotifications() {} + virtual ~LLNotifications(); public: diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 943aff1ca1..245339b107 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3394,7 +3394,7 @@ bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str) bool res = false; - setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red4)); + setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4)); std::string filter_str_lc(filter_str); LLStringUtil::toLower(filter_str_lc); diff --git a/indra/llui/llsearchablecontrol.h b/indra/llui/llsearchablecontrol.h index 7f1421dd19..bae85fe9a5 100644 --- a/indra/llui/llsearchablecontrol.h +++ b/indra/llui/llsearchablecontrol.h @@ -43,9 +43,15 @@ namespace ll virtual ~SearchableControl() { } - const LLColor4& getHighlightColor( ) const + const LLColor4& getHighlightBgColor( ) const { - static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red4); + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4); + return highlight_color.get(); + } + + const LLColor4& getHighlightFontColor() const + { + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightFontColor", LLColor4::red4); return highlight_color.get(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index fae22fd248..41e7094163 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1378,7 +1378,7 @@ void LLTextBase::draw() // Draw highlighted if needed if( ll::ui::SearchableControl::getHighlighted() ) { - const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightColor(); + const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightBgColor(); LLRect bg_rect = mVisibleTextRect; if( mScroller ) bg_rect.intersectWith( text_rect ); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 6c59ed0fd9..fe4cce29ab 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -209,8 +209,15 @@ public: } virtual bool execute( LLTextBase* editor, S32* delta ) { - mWString = editor->getWText().substr(getPosition(), mLen); - *delta = remove(editor, getPosition(), mLen ); + try + { + mWString = editor->getWText().substr(getPosition(), mLen); + *delta = remove(editor, getPosition(), mLen); + } + catch (std::out_of_range&) + { + return false; + } return (*delta != 0); } virtual S32 undo( LLTextBase* editor ) diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 6c3be3eef8..dadbc83f45 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -279,6 +279,10 @@ void callResetKeys() bool callUnicodeCallback(wchar_t character, unsigned int mask) { + if (!gWindowImplementation) + { + return false; + } NativeKeyEventData eventData; memset(&eventData, 0, sizeof(NativeKeyEventData)); @@ -300,7 +304,7 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask) void callFocus() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); } @@ -308,7 +312,7 @@ void callFocus() void callFocusLost() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); } @@ -316,6 +320,10 @@ void callFocusLost() void callRightMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -329,6 +337,10 @@ void callRightMouseDown(float *pos, MASK mask) void callRightMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -342,6 +354,10 @@ void callRightMouseUp(float *pos, MASK mask) void callLeftMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -355,6 +371,10 @@ void callLeftMouseDown(float *pos, MASK mask) void callLeftMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -369,6 +389,10 @@ void callLeftMouseUp(float *pos, MASK mask) void callDoubleClick(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -382,7 +406,7 @@ void callDoubleClick(float *pos, MASK mask) void callResize(unsigned int width, unsigned int height) { - if (gWindowImplementation != NULL) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); } @@ -390,6 +414,10 @@ void callResize(unsigned int width, unsigned int height) void callMouseMoved(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -403,6 +431,10 @@ void callMouseMoved(float *pos, MASK mask) void callMouseDragged(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -424,6 +456,10 @@ void callScrollMoved(float deltaX, float deltaY) void callMouseExit() { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); } @@ -475,11 +511,19 @@ void callWindowDidChangeScreen() void callDeltaUpdate(float *delta, MASK mask) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->updateMouseDeltas(delta); } void callOtherMouseDown(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -500,6 +544,10 @@ void callOtherMouseDown(float *pos, MASK mask, int button) void callOtherMouseUp(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -524,27 +572,43 @@ void callModifier(MASK mask) void callHandleDragEntered(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); } void callHandleDragExited(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); } void callHandleDragUpdated(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); } void callHandleDragDropped(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); } void callQuitHandler() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) { @@ -555,7 +619,7 @@ void callQuitHandler() void getPreeditSelectionRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getSelectionRange(position, length); } @@ -563,7 +627,7 @@ void getPreeditSelectionRange(int *position, int *length) void getPreeditMarkedRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getPreeditRange(position, length); } @@ -571,7 +635,7 @@ void getPreeditMarkedRange(int *position, int *length) void setPreeditMarkedRange(int position, int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->markAsPreedit(position, length); } @@ -580,7 +644,7 @@ void setPreeditMarkedRange(int position, int length) bool handleUnicodeCharacter(wchar_t c) { bool success = false; - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } @@ -590,7 +654,7 @@ bool handleUnicodeCharacter(wchar_t c) void resetPreedit() { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->resetPreedit(); } @@ -600,7 +664,7 @@ void resetPreedit() // This largely mirrors the old implementation, only sans the carbon parameters. void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); preeditor->resetPreedit(); @@ -623,7 +687,7 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne void getPreeditLocation(float *location, unsigned int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); LLCoordGL coord; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3210b76649..ed29911a43 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -291,6 +291,7 @@ set(viewer_SOURCE_FILES llfloatersettingscolor.cpp llfloatersettingsdebug.cpp llfloatersidepanelcontainer.cpp + llfloaterslapptest.cpp llfloatersnapshot.cpp llfloatersounddevices.cpp llfloaterspellchecksettings.cpp @@ -962,6 +963,7 @@ set(viewer_HEADER_FILES llfloatersettingscolor.h llfloatersettingsdebug.h llfloatersidepanelcontainer.h + llfloaterslapptest.h llfloatersnapshot.h llfloatersounddevices.h llfloaterspellchecksettings.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 86d36b3f29..a2a6744722 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3676,6 +3676,17 @@ <key>Value</key> <integer>5000</integer> </map> + <key>InventoryExposeFolderID</key> + <map> + <key>Comment</key> + <string>Allows copying folder id from context menu</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MarketplaceListingsSortOrder</key> <map> <key>Comment</key> @@ -7803,7 +7814,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>2</integer> + <integer>1</integer> </map> <key>RenderMinFreeMainMemoryThreshold</key> <map> @@ -9076,6 +9087,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderReflectionProbeDynamicAllocation</key> + <map> + <key>Comment</key> + <string>Enable dynamic allocation of reflection probes. -1 means no dynamic allocation. Sets a buffer to allocate when a dynamic allocation occurs otherwise.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>-1</integer> + </map> <key>RenderReflectionProbeCount</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 205d4bff6d..5089b9e31e 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -154,6 +154,7 @@ void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, ou if (classic_mode < 1) { amblit = srgb_to_linear(amblit); + amblit = vec3(dot(amblit, vec3(0.2126, 0.7152, 0.0722))); sunlit = srgb_to_linear(sunlit); } diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 1b7b0c1937..349f3b9a67 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -264,11 +264,11 @@ void main() // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". #ifdef SHORELINE_FADE - fade = max(0,min(1, (pos.z - refPos.z) / 10)) + fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else - fade = 1 * water_mask; + fade = 1; #endif - + fade *= water_mask; distort2 = mix(distort, distort2, min(1, fade * 10)); depth = texture(depthMap, distort2).r; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 883963d558..c0009d24ee 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -172,7 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 -RenderReflectionProbeCount 1 16 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -214,7 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 32 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings @@ -245,7 +245,7 @@ RenderFSAASamples 1 1 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 -RenderReflectionProbeLevel 1 2 +RenderReflectionProbeLevel 1 1 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 6 @@ -287,7 +287,7 @@ RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 -RenderReflectionProbeLevel 1 3 +RenderReflectionProbeLevel 1 2 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 8 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 103d24a26d..5940d1ec12 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -172,7 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 -RenderReflectionProbeCount 1 16 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -214,7 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 32 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3f7aaf9557..dfe4a0c197 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -445,8 +445,8 @@ void idle_afk_check() { // check idle timers F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); - F32 afk_timeout = (F32)gSavedSettings.getS32("AFKTimeout"); - if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK()) + static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300); + if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK()) { LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; gAgent.setAFK(); @@ -5217,15 +5217,28 @@ void LLAppViewer::sendLogoutRequest() gLogoutInProgress = true; if (!mSecondInstance) { - mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); - if (mLogoutMarkerFile.getFileHandle()) + mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); + try { - LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL; - recordMarkerVersion(mLogoutMarkerFile); + if (!mLogoutMarkerFile.getFileHandle()) + { + mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); + if (mLogoutMarkerFile.getFileHandle()) + { + LL_INFOS("MarkerFile") << "Created logout marker file '" << mLogoutMarkerFileName << "' " << LL_ENDL; + recordMarkerVersion(mLogoutMarkerFile); + } + else + { + LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; + } + } + else + { + LL_WARNS("MarkerFile") << "Atempted to reopen file '" << mLogoutMarkerFileName << "' " << LL_ENDL; + } } - else + catch (...) { LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; } @@ -5377,7 +5390,8 @@ void LLAppViewer::idleNetwork() gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; - if (!gSavedSettings.getBOOL("SpeedTest")) + static LLCachedControl<bool> speed_test(gSavedSettings, "SpeedTest", false); + if (!speed_test()) { LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode @@ -5436,7 +5450,9 @@ void LLAppViewer::idleNetwork() } // Handle per-frame message system processing. - lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); + + static LLCachedControl<F32> ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f); + lmc.processAcks(ack_collection_time()); } } add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index b4a2479520..aaf2a7ea3e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -155,10 +155,10 @@ namespace sBugSplatSender->setAttribute(WCSTR(L"OS"), WCSTR(LLOSInfo::instance().getOSStringSimple())); // In case we ever stop using email for this sBugSplatSender->setAttribute(WCSTR(L"AppState"), WCSTR(LLStartUp::getStartupStateString())); - sBugSplatSender->setAttribute(WCSTR(L"GL Vendor"), WCSTR(gGLManager.mGLVendor)); - sBugSplatSender->setAttribute(WCSTR(L"GL Version"), WCSTR(gGLManager.mGLVersionString)); - sBugSplatSender->setAttribute(WCSTR(L"GPU Version"), WCSTR(gGLManager.mDriverVersionVendorString)); - sBugSplatSender->setAttribute(WCSTR(L"GL Renderer"), WCSTR(gGLManager.mGLRenderer)); + sBugSplatSender->setAttribute(WCSTR(L"GLVendor"), WCSTR(gGLManager.mGLVendor)); + sBugSplatSender->setAttribute(WCSTR(L"GLVersion"), WCSTR(gGLManager.mGLVersionString)); + sBugSplatSender->setAttribute(WCSTR(L"GPUVersion"), WCSTR(gGLManager.mDriverVersionVendorString)); + sBugSplatSender->setAttribute(WCSTR(L"GLRenderer"), WCSTR(gGLManager.mGLRenderer)); sBugSplatSender->setAttribute(WCSTR(L"VRAM"), WCSTR(STRINGIZE(gGLManager.mVRAM))); sBugSplatSender->setAttribute(WCSTR(L"RAM"), WCSTR(STRINGIZE(gSysMemory.getPhysicalMemoryKB().value()))); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 6efd503574..26ef190fbb 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -108,8 +108,9 @@ void LLDrawPoolTree::beginShadowPass(S32 pass) { LL_PROFILE_ZONE_SCOPED; - glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), - gSavedSettings.getF32("RenderDeferredTreeShadowBias")); + static LLCachedControl<F32> shadow_offset(gSavedSettings, "RenderDeferredTreeShadowOffset"); + static LLCachedControl<F32> shadow_bias(gSavedSettings, "RenderDeferredTreeShadowBias"); + glPolygonOffset(shadow_offset(), shadow_bias()); LLEnvironment& environment = LLEnvironment::instance(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 811aacb2ed..373a556f86 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2218,7 +2218,7 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged"); //override with joint volume face joint bounding boxes - LLVOAvatar* avatar = mVObjp->getAvatar(); + LLVOAvatar* avatar = mVObjp.notNull() ? mVObjp->getAvatar() : nullptr; bool hasRiggedExtents = false; if (avatar && avatar->mDrawable) diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index c2821d56d6..558fc92018 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -199,6 +199,7 @@ bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const { mTrackingIdToLocalTexture.erase(tracking_id); } + updateLocalTexDataDigest(); return res; } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index e55bf50724..e4b14d8df6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1939,7 +1939,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c mConversationEventQueue.erase(uuid); // Don't let the focus fall IW, select and refocus on the first conversation in the list - if (change_focus) + if (change_focus && isInVisibleChain()) { setFocus(true); if (new_selection) @@ -1959,6 +1959,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c } } } + else + { + LL_INFOS() << "Conversation widgets: " << (S32)mConversationsWidgets.size() << LL_ENDL; + } return is_widget_selected; } diff --git a/indra/newview/llfloaterslapptest.cpp b/indra/newview/llfloaterslapptest.cpp new file mode 100644 index 0000000000..0075379529 --- /dev/null +++ b/indra/newview/llfloaterslapptest.cpp @@ -0,0 +1,51 @@ +/** + * @file llfloaterslapptest.cpp + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterslapptest.h" +#include "lluictrlfactory.h" + +#include "lllineeditor.h" +#include "lltextbox.h" + +LLFloaterSLappTest::LLFloaterSLappTest(const LLSD& key) + : LLFloater("floater_test_slapp") +{ +} + +LLFloaterSLappTest::~LLFloaterSLappTest() +{} + +bool LLFloaterSLappTest::postBuild() +{ + getChild<LLLineEditor>("remove_folder_id")->setKeystrokeCallback([this](LLLineEditor* editor, void*) + { + std::string slapp(getString("remove_folder_slapp")); + getChild<LLTextBox>("remove_folder_txt")->setValue(slapp + editor->getValue().asString()); + }, NULL); + + return true; +} diff --git a/indra/newview/llfloaterslapptest.h b/indra/newview/llfloaterslapptest.h new file mode 100644 index 0000000000..ec727cb629 --- /dev/null +++ b/indra/newview/llfloaterslapptest.h @@ -0,0 +1,42 @@ +/** + * @file llfloaterslapptest.h + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERSLAPPTEST_H +#define LL_LLFLOATERSLAPPTEST_H + +#include "llfloater.h" + +class LLFloaterSLappTest: + public LLFloater +{ + friend class LLFloaterReg; + virtual bool postBuild() override; + +private: + LLFloaterSLappTest(const LLSD& key); + ~LLFloaterSLappTest(); +}; + +#endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 479b7c19ac..ce91f9a1f3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3599,6 +3599,13 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } + else if ("copy_folder_uuid" == action) + { + LLInventoryCategory* cat = gInventory.getCategory(mUUID); + if (!cat) return; + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(mUUID.asString())); + return; + } } void LLFolderBridge::gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level) @@ -4466,6 +4473,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { disabled_items.push_back(std::string("Delete System Folder")); } + else + { + static LLCachedControl<bool> show_copy_id(gSavedSettings, "InventoryExposeFolderID", false); + if (show_copy_id()) + { + items.push_back(std::string("Copy UUID")); + } + } if (isAgentInventory() && !isMarketplaceListingsFolder()) { diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 72a7fe8814..75c77e9301 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -298,8 +298,9 @@ void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat) return; } - mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + mat->addLocalTextureTracking(getTrackingID(), getWorldID()); + + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != mGLTFMaterialWithLocalTextures.end();) { if (it->get() == mat) { @@ -309,15 +310,12 @@ void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat) if ((*it)->getNumRefs() == 1) { it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } else { it++; } } - - mat->addLocalTextureTracking(getTrackingID(), getWorldID()); mGLTFMaterialWithLocalTextures.push_back(mat); } @@ -648,16 +646,16 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) { // Might be a better idea to hold this in LLGLTFMaterialList - mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != mGLTFMaterialWithLocalTextures.end();) { if ((*it)->getNumRefs() == 1) { // render and override materials are often recreated, // clean up any remains it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } + // Render material consists of base and override materials, make sure replaceLocalTexture + // gets called for base and override before applyOverride else if ((*it)->replaceLocalTexture(mTrackingID, old_id, new_id)) { it++; @@ -667,43 +665,47 @@ void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) // Matching id not found, no longer in use // material would clean itself, remove from the list it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } } - // Render material consists of base and override materials, make sure replaceLocalTexture - // gets called for base and override before applyOverride - end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + // Updating render materials calls updateTextureTracking which can modify + // mGLTFMaterialWithLocalTextures, so precollect all entries that need to be updated + std::set<LLTextureEntry*> update_entries; + for (LLGLTFMaterial* mat : mGLTFMaterialWithLocalTextures) { - LLFetchedGLTFMaterial* fetched_mat = dynamic_cast<LLFetchedGLTFMaterial*>((*it).get()); + // mGLTFMaterialWithLocalTextures includes overrides that are not 'fetched' + // and don't have texture entries (they don't need to since render material does). + LLFetchedGLTFMaterial* fetched_mat = dynamic_cast<LLFetchedGLTFMaterial*>(mat); if (fetched_mat) { for (LLTextureEntry* entry : fetched_mat->mTextureEntires) { - // Normally a change in applied material id is supposed to - // drop overrides thus reset material, but local materials - // currently reuse their existing asset id, and purpose is - // to preview how material will work in-world, overrides - // included, so do an override to render update instead. - LLGLTFMaterial* override_mat = entry->getGLTFMaterialOverride(); - if (override_mat) - { - // do not create a new material, reuse existing pointer - LLFetchedGLTFMaterial* render_mat = dynamic_cast<LLFetchedGLTFMaterial*>(entry->getGLTFRenderMaterial()); - if (render_mat) - { - *render_mat = *fetched_mat; - render_mat->applyOverride(*override_mat); - } - else - { - LL_WARNS_ONCE() << "Failed to apply local material override, render material not found" << LL_ENDL; - } - } + update_entries.insert(entry); + } + } + } + + + for (LLTextureEntry* entry : update_entries) + { + // Normally a change in applied material id is supposed to + // drop overrides thus reset material, but local materials + // currently reuse their existing asset id, and purpose is + // to preview how material will work in-world, overrides + // included, so do an override to render update instead. + LLGLTFMaterial* override_mat = entry->getGLTFMaterialOverride(); + LLGLTFMaterial* mat = entry->getGLTFMaterial(); + if (override_mat && mat) + { + // do not create a new material, reuse existing pointer + // so that mTextureEntires remains untouched + LLGLTFMaterial* render_mat = entry->getGLTFRenderMaterial(); + if (render_mat) + { + *render_mat = *mat; + render_mat->applyOverride(*override_mat); // can update mGLTFMaterialWithLocalTextures } } - ++it; } } diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index 06770334e4..6c9d65e3b6 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -107,7 +107,7 @@ class LLLocalBitmap // Store a list of accosiated materials // Might be a better idea to hold this in LLGLTFMaterialList - typedef std::vector<LLPointer<LLGLTFMaterial> > mat_list_t; + typedef std::list<LLPointer<LLGLTFMaterial> > mat_list_t; mat_list_t mGLTFMaterialWithLocalTextures; }; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index e1fa84b4d8..a8c6f69425 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4573,6 +4573,8 @@ void LLMeshRepository::notifyLoadedMeshes() std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count, mPendingRequests.end(), PendingRequestBase::CompareScoreGreater()); } + LLMutexTrylock lock3(mThread->mHeaderMutex); + LLMutexTrylock lock4(mThread->mPendingMutex); while (!mPendingRequests.empty() && push_count > 0) { std::unique_ptr<PendingRequestBase>& req_p = mPendingRequests.front(); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index f491cccaf8..b7d9df6ea6 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3075,8 +3075,7 @@ void LLPanelFace::onCommitHideWater() } else { - // reset texture to default plywood - LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + LLSelectMgr::getInstance()->clearWaterExclusion(); } } diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f3adb52d5e..910509928d 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -52,6 +52,9 @@ LLReflectionMap::~LLReflectionMap() void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + if (!mCubeArray.notNull()) + return; + mLastUpdateTime = gFrameTimeSeconds; llassert(mCubeArray.notNull()); llassert(mCubeIndex != -1); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 48b73531ea..f2abc7b8b7 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -144,13 +144,14 @@ static void touch_default_probe(LLReflectionMap* probe) LLReflectionMapManager::LLReflectionMapManager() { + mDynamicProbeCount = LL_MAX_REFLECTION_PROBE_COUNT; initCubeFree(); } void LLReflectionMapManager::initCubeFree() { // start at 1 because index 0 is reserved for mDefaultProbe - for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) + for (U32 i = 1; i < mDynamicProbeCount; ++i) { mCubeFree.push_back(i); } @@ -221,12 +222,53 @@ void LLReflectionMapManager::update() resume(); } - static LLCachedControl<U32> probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - bool countReset = mReflectionProbeCount != probe_count; + static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); + static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + static LLCachedControl<U32> sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U); + static LLCachedControl<S32> sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); - if (countReset) { - mResetFade = -0.5f; + U32 probe_count_temp = mDynamicProbeCount; + if (sProbeDynamicAllocation > -1) + { + if (sLevel == 0) + { + mDynamicProbeCount = 1; + } + else if (sLevel == 1) + { + mDynamicProbeCount = (U32)mProbes.size(); + } + else if (sLevel == 2) + { + mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + } + else + { + mDynamicProbeCount = 256; + } + + if (sProbeDynamicAllocation > 1) + { + // Round mDynamicProbeCount to the nearest increment of 16 + mDynamicProbeCount = ((mDynamicProbeCount + sProbeDynamicAllocation / 2) / sProbeDynamicAllocation) * 16; + mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, sReflectionProbeCount); + } + else + { + mDynamicProbeCount = llclamp(mDynamicProbeCount + sProbeDynamicAllocation, 1, sReflectionProbeCount); + } + } + else + { + mDynamicProbeCount = sReflectionProbeCount; + } + + mDynamicProbeCount = llmin(mDynamicProbeCount, LL_MAX_REFLECTION_PROBE_COUNT); + + if (mDynamicProbeCount != probe_count_temp) + mResetFade = 1.f; } initReflectionMaps(); @@ -286,9 +328,6 @@ void LLReflectionMapManager::update() bool did_update = false; - static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); - static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME; LLReflectionMap* closestDynamic = nullptr; @@ -323,6 +362,7 @@ void LLReflectionMapManager::update() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mComplete = false; + probe->mFadeIn = 0; } } @@ -343,12 +383,7 @@ void LLReflectionMapManager::update() } } - if (countReset) - { - mResetFade = -0.5f; - } - - mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds), 1.f); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); for (unsigned int i = 0; i < mProbes.size(); ++i) { @@ -520,6 +555,16 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) return probe; } +U32 LLReflectionMapManager::probeCount() +{ + return mDynamicProbeCount; +} + +U32 LLReflectionMapManager::probeMemory() +{ + return (mDynamicProbeCount * 6 * (mProbeResolution * mProbeResolution) * 4) / 1024 / 1024 + (mDynamicProbeCount * 6 * (LL_IRRADIANCE_MAP_RESOLUTION * LL_IRRADIANCE_MAP_RESOLUTION) * 4) / 1024 / 1024; +} + struct CompareProbeDepth { bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) @@ -1058,7 +1103,11 @@ void LLReflectionMapManager::updateUniforms() bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); F32 ambscale = is_ambiance_pass ? 0.f : 1.f; + ambscale *= mResetFade; + ambscale = llmax(0, ambscale); F32 radscale = is_ambiance_pass ? 0.5f : 1.f; + radscale *= mResetFade; + radscale = llmax(0, radscale); for (auto* refmap : mReflectionMaps) { @@ -1129,8 +1178,8 @@ void LLReflectionMapManager::updateUniforms() } mProbeData.refParams[count].set( - llmax(minimum_ambiance, refmap->getAmbiance())*ambscale * llmax(mResetFade, 0.f), // ambiance scale - radscale * llmax(mResetFade, 0.f), // radiance scale + llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale + radscale, // radiance scale refmap->mFadeIn, // fade in weight oa.getF32ptr()[2] - refmap->mRadius); // z near @@ -1365,12 +1414,9 @@ void LLReflectionMapManager::renderDebug() void LLReflectionMapManager::initReflectionMaps() { - static LLCachedControl<U32> probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - U32 count = probe_count(); - static LLCachedControl<U32> ref_probe_res(gSavedSettings, "RenderReflectionProbeResolution", 128U); U32 probe_resolution = nhpo2(llclamp(ref_probe_res(), (U32)64, (U32)512)); - if (mTexture.isNull() || mReflectionProbeCount != count || mProbeResolution != probe_resolution || mReset) + if (mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset) { if(mProbeResolution != probe_resolution) { @@ -1379,9 +1425,8 @@ void LLReflectionMapManager::initReflectionMaps() } gEXRImage = nullptr; - mReset = false; - mReflectionProbeCount = count; + mReflectionProbeCount = mDynamicProbeCount; mProbeResolution = probe_resolution; mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1 @@ -1389,15 +1434,25 @@ void LLReflectionMapManager::initReflectionMaps() mTexture->getWidth() != mProbeResolution || mReflectionProbeCount + 2 != mTexture->getCount()) { - mTexture = new LLCubeMapArray(); + if (mTexture) + { + mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2); - static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true); + mIrradianceMaps = new LLCubeMapArray(*mIrradianceMaps, LL_IRRADIANCE_MAP_RESOLUTION, mReflectionProbeCount); + } + else + { + mTexture = new LLCubeMapArray(); - // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); + static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation + // source) + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + } } // reset probe state @@ -1417,6 +1472,7 @@ void LLReflectionMapManager::initReflectionMaps() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mNeighbors.clear(); + probe->mFadeIn = 0; } mCubeFree.clear(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 9f88776ac2..0719c28134 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -38,7 +38,7 @@ class LLViewerObject; #define LL_MAX_REFLECTION_PROBE_COUNT 256 // reflection probe resolution -#define LL_IRRADIANCE_MAP_RESOLUTION 64 +#define LL_IRRADIANCE_MAP_RESOLUTION 16 // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; @@ -159,6 +159,9 @@ public: // with false when done. void forceDefaultProbeAndUpdateUniforms(bool force = true); + U32 probeCount(); + U32 probeMemory(); + private: friend class LLPipeline; friend class LLHeroProbeManager; @@ -166,6 +169,9 @@ private: // initialize mCubeFree array to default values void initCubeFree(); + // Just does a bulk clear of all of the cubemaps. + void clearCubeMaps(); + // delete the probe with the given index in mProbes void deleteProbe(U32 i); @@ -240,6 +246,8 @@ private: // number of reflection probes to use for rendering U32 mReflectionProbeCount; + U32 mDynamicProbeCount; + // resolution of reflection probes U32 mProbeResolution = 128; @@ -253,6 +261,7 @@ private: bool mReset = false; float mResetFade = 1.f; + float mGlobalFadeTarget = 1.f; // if true, only update the default probe bool mPaused = false; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b2f30dd966..3d17446186 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1995,7 +1995,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) asset_id = BLANK_MATERIAL_ASSET_ID; } } - + objectp->clearTEWaterExclusion(te); // Blank out most override data on the object and send to server objectp->setRenderMaterialID(te, asset_id); @@ -2477,6 +2477,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) } else { // Add/update media + object->clearTEWaterExclusion(te); object->setTEMediaFlags(te, mMediaFlags); LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object); llassert(NULL != vo); @@ -7751,6 +7752,14 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) gAgentCamera.mHUDCurZoom = current_zoom; } +void LLSelectMgr::clearWaterExclusion() +{ + // reset texture to default plywood + LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + // reset texture repeats, that might be altered by invisiprim script from wiki + LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); +} + ///////////////////////////////////////////////////////////////////////////// // Object selection iterator helpers ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index e4613bb3e7..792a37297f 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -838,6 +838,7 @@ public: void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; void updatePointAt(); + void clearWaterExclusion(); // Internal list maintenance functions. TODO: Make these private! void remove(std::vector<LLViewerObject*>& objects); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 78d930c05c..8560a01c4b 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -559,10 +559,12 @@ void LLGLTexMemBar::draw() gGL.color4f(0.f, 0.f, 0.f, 0.25f); gl_rect_2d(-10, getRect().getHeight() + line_height*2 + 1, getRect().getWidth()+2, getRect().getHeight()+2); - text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", + text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Probe#: %d Probe Mem: %d MB Bias: %.2f Cache: %.1f/%.1f MB", (S32)LLViewerTexture::sFreeVRAMMegabytes, LLMemory::getAvailableMemKB()/1024, LLRenderTarget::sBytesAllocated/(1024*1024), + gPipeline.mReflectionMapManager.probeCount(), + gPipeline.mReflectionMapManager.probeMemory(), discard_bias, cache_usage, cache_max_usage); diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 5ab9f76e47..255cfc998a 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -402,10 +402,10 @@ void LLViewerAssetStorage::queueRequestHttp( manager->enqueueCoprocedure( VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro", - [this, req, uuid, atype, callback, user_data] + [this, uuid, atype, callback, user_data] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t&, const LLUUID&) { - assetRequestCoro(req, uuid, atype, callback, user_data); + assetRequestCoro(uuid, atype, callback, user_data); }); } } @@ -440,7 +440,6 @@ struct LLScopedIncrement }; void LLViewerAssetStorage::assetRequestCoro( - LLViewerAssetRequest *req, const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, @@ -464,7 +463,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } else if (!gAgent.getRegion()->capabilitiesReceived()) @@ -495,7 +494,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } std::string url = getAssetURL(mViewerAssetUrl, uuid,atype); @@ -517,6 +516,7 @@ void LLViewerAssetStorage::assetRequestCoro( mCountCompleted++; + S32 bytes_fetched = 0; LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) @@ -554,7 +554,7 @@ void LLViewerAssetStorage::assetRequestCoro( LLUUID temp_id; temp_id.generate(); LLFileSystem vf(temp_id, atype, LLFileSystem::WRITE); - req->mBytesFetched = size; + bytes_fetched = size; if (!vf.write(raw.data(),size)) { // TODO asset-http: handle error @@ -583,7 +583,7 @@ void LLViewerAssetStorage::assetRequestCoro( } // Clean up pending downloads and trigger callbacks - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, bytes_fetched); } std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype) diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index fdb8af7457..42dd9d1dd8 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -82,8 +82,7 @@ protected: void capsRecvForRegion(const LLUUID& region_id, std::string pumpname); - void assetRequestCoro(LLViewerAssetRequest *req, - const LLUUID uuid, + void assetRequestCoro(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, void *user_data); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index ef68609182..95c2a77ba8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -137,6 +137,7 @@ #include "llfloatersettingscolor.h" #include "llfloatersettingsdebug.h" #include "llfloatersidepanelcontainer.h" +#include "llfloaterslapptest.h" #include "llfloatersnapshot.h" #include "llfloatersounddevices.h" #include "llfloaterspellchecksettings.h" @@ -278,7 +279,8 @@ public: "upload_model", "upload_script", "upload_sound", - "bulk_upload" + "bulk_upload", + "slapp_test" }; return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end(); } @@ -499,6 +501,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>); + LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSLappTest>); LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1caa5c61ae..8d90187e91 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4826,6 +4826,18 @@ void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, bool damped) else { setPositionRegion(pos_parent, damped); + + // #1964 mark reflection probe in the linkset to update position after moving via script + for (LLViewerObject* child : mChildList) + { + if (child && child->isReflectionProbe()) + { + if (LLDrawable* drawablep = child->mDrawable) + { + gPipeline.markMoved(drawablep); + } + } + } } } @@ -7676,6 +7688,31 @@ void LLViewerObject::setGLTFAsset(const LLUUID& id) updateVolume(volume_params); } +void LLViewerObject::clearTEWaterExclusion(const U8 te) +{ + if (permModify()) + { + LLViewerTexture* image = getTEImage(te); + if (image && (IMG_ALPHA_GRAD == image->getID())) + { + // reset texture to default plywood + setTEImage(te, LLViewerTextureManager::getFetchedTexture(DEFAULT_OBJECT_TEXTURE, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + // reset texture repeats, that might be altered by invisiprim script from wiki + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return; + } + F32 DEFAULT_REPEATS = 2.f; + F32 new_s = getScale().mV[s_axis] * DEFAULT_REPEATS; + F32 new_t = getScale().mV[t_axis] * DEFAULT_REPEATS; + + setTEScale(te, new_s, new_t); + sendTEUpdate(); + } + } +} class ObjectPhysicsProperties : public LLHTTPNode { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 63458e60ea..2b52ea2076 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -405,6 +405,8 @@ public: LLViewerTexture *getTENormalMap(const U8 te) const; LLViewerTexture *getTESpecularMap(const U8 te) const; + void clearTEWaterExclusion(const U8 te); + bool isImageAlphaBlended(const U8 te) const; void fitFaceTexture(const U8 face); diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 2e9b5de72b..da03d3b015 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -581,7 +581,7 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 outside_y += dy * (dy - LINE_WIDTH); // Middle part, full width - const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); + const S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS; for (S32 i = 1; i < GRID_STEP; i++) { inside_z = land.resolveHeightRegion( inside_x, inside_y ); @@ -666,7 +666,9 @@ void LLViewerParcelOverlay::renderPropertyLines() return; LLSurface& land = mRegion->getLand(); - F32 water_z = land.getWaterHeight() + 0.01f; + + bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); + F32 water_z = render_water ? land.getWaterHeight() + 0.01f : 0; LLGLSUIDefault gls_ui; // called from pipeline gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a0723db479..4a9dd1c1b6 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -504,8 +504,11 @@ void LLViewerTexture::updateClass() // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); - F32 budget = max_vram_budget == 0 ? (F32)gGLManager.mVRAM : (F32)max_vram_budget; - budget /= tex_vram_divisor; + // For debugging purposes, it's useful to be able to set the VRAM budget manually. + // But when manual control is not enabled, use the VRAM divisor. + // While we're at it, assume we have 1024 to play with at minimum when the divisor is in use. Works more elegantly with the logic below this. + // -Geenz 2025-03-21 + F32 budget = max_vram_budget == 0 ? llmax(1024, (F32)gGLManager.mVRAM / tex_vram_divisor) : (F32)max_vram_budget; // Try to leave at least half a GB for everyone else and for bias, // but keep at least 768MB for ourselves @@ -519,7 +522,6 @@ void LLViewerTexture::updateClass() bool is_sys_low = isSystemMemoryLow(); bool is_low = is_sys_low || over_pct > 0.f; - F32 discard_bias = sDesiredDiscardBias; static bool was_low = false; static bool was_sys_low = false; @@ -571,6 +573,7 @@ void LLViewerTexture::updateClass() // set to max discard bias if the window has been backgrounded for a while static F32 last_desired_discard_bias = 1.f; + static F32 last_texture_update_count_bias = 1.f; static bool was_backgrounded = false; static LLFrameTimer backgrounded_timer; static LLCachedControl<F32> minimized_discard_time(gSavedSettings, "TextureDiscardMinimizedTime", 1.f); @@ -606,12 +609,21 @@ void LLViewerTexture::updateClass() } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); - if (discard_bias != sDesiredDiscardBias) + if (last_texture_update_count_bias < sDesiredDiscardBias) { - // bias changed, reset texture update counter to + // bias increased, reset texture update counter to // let updates happen at an increased rate. + last_texture_update_count_bias = sDesiredDiscardBias; sBiasTexturesUpdated = 0; } + else if (last_texture_update_count_bias > sDesiredDiscardBias + 0.1f) + { + // bias decreased, 0.1f is there to filter out small fluctuations + // and not reset sBiasTexturesUpdated too often. + // Bias jumps to 1.5 at low memory, so getting stuck at 1.1 is not + // a problem. + last_texture_update_count_bias = sDesiredDiscardBias; + } LLViewerTexture::sFreezeImageUpdates = false; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 9f23d39506..0d02dc034e 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -899,6 +899,9 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag { llassert(!gCubeSnapshot); + constexpr F32 BIAS_TRS_OUT_OF_SCREEN = 1.5f; + constexpr F32 BIAS_TRS_ON_SCREEN = 1.f; + if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures { static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.0095f); @@ -940,7 +943,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 vsize = face->getPixelArea(); - on_screen = face->mInFrustum; + on_screen |= face->mInFrustum; // Scale desired texture resolution higher or lower depending on texture scale // @@ -958,7 +961,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag vsize /= min_scale; // apply bias to offscreen faces all the time, but only to onscreen faces when bias is large - if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 2.f) + // use mImportanceToCamera to make bias switch a bit more gradual + if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 1.9f + face->mImportanceToCamera / 2.f) { vsize /= bias; } @@ -971,14 +975,28 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag } max_vsize = llmax(max_vsize, vsize); + + // addTextureStats limits size to sMaxVirtualSize + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } } + + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } if (face_count > 1024) { // this texture is used in so many places we should just boost it and not bother checking its vsize // this is especially important because the above is not time sliced and can hit multiple ms for a single texture imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_HIGH); + // Do we ever remove it? This also sets texture nodelete! } if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) @@ -986,8 +1004,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // this is an alternative to decaying mMaxVirtualSize over time // that keeps textures from continously downrezzing and uprezzing in the background - if (LLViewerTexture::sDesiredDiscardBias > 1.5f || - (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + if (LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_OUT_OF_SCREEN || + (!on_screen && LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_ON_SCREEN)) { imagep->mMaxVirtualSize = 0.f; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a133febb85..d2685bcc48 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -489,7 +489,8 @@ public: clearText(); - if (gSavedSettings.getBOOL("DebugShowTime")) + static LLCachedControl<bool> debug_show_time(gSavedSettings, "DebugShowTime", false); + if (debug_show_time()) { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); @@ -498,7 +499,8 @@ public: addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowMemory")) + static LLCachedControl<bool> debug_show_memory(gSavedSettings, "DebugShowMemory", false); + if (debug_show_memory()) { addText(xpos, ypos, STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); @@ -591,7 +593,8 @@ public: ypos += y_inc; }*/ - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + static LLCachedControl<bool> debug_show_render_info(gSavedSettings, "DebugShowRenderInfo", false); + if (debug_show_render_info()) { LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); @@ -730,7 +733,8 @@ public: gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } - if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) + static LLCachedControl<bool> debug_show_avatar_render_info(gSavedSettings, "DebugShowAvatarRenderInfo", false); + if (debug_show_avatar_render_info()) { std::map<std::string, LLVOAvatar*> sorted_avs; { @@ -763,7 +767,8 @@ public: av_iter++; } } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + static LLCachedControl<bool> debug_show_render_matrices(gSavedSettings, "DebugShowRenderMatrices", false); + if (debug_show_render_matrices()) { char camera_lines[8][32]; memset(camera_lines, ' ', sizeof(camera_lines)); @@ -789,7 +794,8 @@ public: ypos += y_inc; } // disable use of glReadPixels which messes up nVidia nSight graphics debugging - if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) + static LLCachedControl<bool> debug_show_color(gSavedSettings, "DebugShowColor", false); + if (debug_show_color() && !LLRender::sNsightDebugSupport) { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); @@ -881,7 +887,8 @@ public: } } - if (gSavedSettings.getBOOL("DebugShowTextureInfo")) + static LLCachedControl<bool> debug_show_texture_info(gSavedSettings, "DebugShowTextureInfo", false); + if (debug_show_texture_info()) { LLViewerObject* objectp = NULL ; @@ -1450,10 +1457,13 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window) bool LLViewerWindow::handleCloseRequest(LLWindow *window) { - // User has indicated they want to close, but we may need to ask - // about modified documents. - LLAppViewer::instance()->userQuit(); - // Don't quit immediately + if (!LLApp::isExiting() && !LLApp::isStopped()) + { + // User has indicated they want to close, but we may need to ask + // about modified documents. + LLAppViewer::instance()->userQuit(); + // Don't quit immediately + } return false; } @@ -1597,7 +1607,8 @@ bool LLViewerWindow::handleActivate(LLWindow *window, bool activated) mActive = false; // if the user has chosen to go Away automatically after some time, then go Away when minimizing - if (gSavedSettings.getS32("AFKTimeout")) + static LLCachedControl<S32> afk_time(gSavedSettings, "AFKTimeout", 300); + if (afk_time()) { gAgent.setAFK(); } diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 93c217a7ba..08fcec86ac 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -3024,7 +3024,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b { root["ug"] = user_gain; } - if (root.size() > 0) + if (root.size() > 0 && mWebRTCDataInterface) { std::string json_data = boost::json::serialize(root); mWebRTCDataInterface->sendData(json_data, false); @@ -3067,7 +3067,10 @@ void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface void LLVoiceWebRTCConnection::sendJoin() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE; - + if (!mWebRTCDataInterface) + { + return; + } boost::json::object root; boost::json::object join_obj; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index e17321e698..f0af4acf20 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -759,7 +759,10 @@ name="SelectedOutfitTextColor" reference="EmphasisColor" /> <color - name="SearchableControlHighlightColor" + name="SearchableControlHighlightFontColor" + value="1 0 0 1" /> + <color + name="SearchableControlHighlightBgColor" value="0.5 0.1 0.1 1" /> <color name="SilhouetteChildColor" diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 34ed3fa80d..6877ce6411 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -858,22 +858,50 @@ value="3"/> </combo_box> - <slider - control_name="RenderReflectionProbeCount" - decimal_digits="0" - follows="left|top" - height="16" - increment="1" - initial_value="256" - label="Max. Reflection Probes:" - label_width="145" - layout="topleft" - left="420" - min_val="1" - max_val="256" - name="MaxProbes" - top_delta="24" - width="260" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="420" + name="ReflectionProbeCount" + text_readonly_color="LabelDisabledColor" + top_delta="22" + width="128"> + Max Reflection Probes: + </text> + + <combo_box + control_name="RenderReflectionProbeCount" + height="18" + layout="topleft" + label="Max. Reflection Probes:" + left_delta="130" + top_delta="0" + name="ProbeCount" + width="150"> + <combo_box.item + label="None" + name="1" + value="1"/> + <combo_box.item + label="Low" + name="32" + value="32"/> + <combo_box.item + label="Medium" + name="64" + value="64"/> + <combo_box.item + label="High" + name="128" + value="128"/> + <combo_box.item + label="Ultra" + name="256" + value="256"/> + </combo_box> <slider control_name="RenderExposure" diff --git a/indra/newview/skins/default/xui/en/floater_test_slapp.xml b/indra/newview/skins/default/xui/en/floater_test_slapp.xml new file mode 100644 index 0000000000..dd2720816a --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_slapp.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater + legacy_header_height="18" + height="300" + layout="topleft" + name="slapp_test" + title="SLAPP TEST" + width="500"> + <floater.string + name="remove_folder_slapp"> + secondlife://app/remove_folder/?folder_id= + </floater.string> + <text + type="string" + length="1" + top="20" + follows="left|top|right" + height="16" + name="trusted_txt" + font="SansSerifMedium" + text_color="white" + layout="topleft" + left="16"> + Trusted source + </text> + <text + type="string" + length="1" + top_pad="8" + follows="left|top|right" + height="16" + layout="topleft" + left="16"> + /wear_folder + </text> + <text + type="string" + length="1" + top_pad="5" + follows="left|top|right" + height="16" + width="450" + layout="topleft" + left="16"> + secondlife://app/wear_folder/?folder_name=Daisy + </text> + <text + type="string" + length="1" + top_pad="8 " + follows="left|top|right" + height="16" + layout="topleft" + left="16"> + /add_folder + </text> + <text + type="string" + length="1" + top_pad="5" + follows="left|top|right" + height="16" + width="450" + layout="topleft" + left="16"> + secondlife://app/add_folder/?folder_name=Cardboard%20Boxbot + </text> + <text + type="string" + length="1" + top_pad="5" + follows="left|top|right" + height="16" + width="450" + layout="topleft"> + secondlife://app/add_folder/?folder_id=59219db2-c260-87d3-213d-bb3bc298a3d8 + </text> + <text + type="string" + length="1" + top_pad="8 " + follows="left|top|right" + height="16" + layout="topleft" + left="16"> + /remove_folder + </text> + <text + type="string" + length="1" + top_pad="5" + follows="left|top|right" + height="16" + layout="topleft" + left="16"> + Folder ID: + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top" + font="SansSerif" + height="18" + layout="topleft" + left="75" + max_length_bytes="50" + prevalidate_callback="ascii" + name="remove_folder_id" + top_delta="-2" + width="270" /> + <text + type="string" + length="1" + top_pad="5" + follows="left|top|right" + height="16" + width="450" + name="remove_folder_txt" + layout="topleft" + left="16"> + secondlife://app/remove_folder/?folder_id= + </text> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index d8aac71dd5..e57e3b0750 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -371,6 +371,14 @@ parameter="copy_uuid" /> </menu_item_call> <menu_item_call + label="Copy UUID" + layout="topleft" + name="Copy UUID"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copy_folder_uuid" /> + </menu_item_call> + <menu_item_call label="Show in Main Panel" layout="topleft" name="Show in Main Panel"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 6fb92f7b99..343f0c0059 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3889,6 +3889,13 @@ function="World.EnvPreset" function="Floater.Show" parameter="font_test" /> </menu_item_call> + <menu_item_call + label="Show SLapps Test" + name="Show SLapps Test"> + <menu_item_call.on_click + function="Floater.Show" + parameter="slapp_test" /> + </menu_item_call> <menu_item_check label="Show XUI Names" name="Show XUI Names"> diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml index c906e2f96c..d6ac71db94 100644 --- a/indra/newview/skins/default/xui/en/panel_login_first.xml +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -179,7 +179,6 @@ control_name="RememberPassword" follows="left|top" font="SansSerifLarge" - text_color="EmphasisColor" height="24" left="262" bottom_delta="0" |