diff options
56 files changed, 551 insertions, 184 deletions
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index b3800e6981..7f7eaf1855 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1890,7 +1890,10 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); } - tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL); + if (!tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL)) + { + LL_WARNS() << "Failed to create GL texture for image: " << file_name << LL_ENDL; + } gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 30551c115d..dd2499cf37 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -338,7 +338,10 @@ bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Create the GL texture, and then hang onto it for future use. if (mNeedsCreateTexture) { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); + if (!mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw)) + { + LL_WARNS() << "Failed to create GL texture for image: " << mCachedProcessedTexture->getID() << LL_ENDL; + } mNeedsCreateTexture = false; gGL.getTexUnit(0)->bind(mCachedProcessedTexture); mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); 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) + { + has_active = true; + req->setFlags(FLAG_ABORT | FLAG_AUTO_COMPLETE); + continue; + } + if (req->getStatus() == STATUS_QUEUED) { - ++active_count; + ++queued_count; req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest } req->deleteRequest(); } - if (active_count) + unlockData(); + if (queued_count) + { + LL_WARNS() << "~LLQueuedThread() called with unpocessed requests: " << queued_count << LL_ENDL; + } + if (has_active) { - LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL; + 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 diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index 33a48d970d..1d246bb70e 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -33,7 +33,7 @@ LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedT { if (u.find("://") == std::string::npos) { - mNormalizedUri = "http://"; + mNormalizedUri = "https://"; mTmpScheme = true; } diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 149741b9f9..e4c7deb1c5 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -112,9 +112,7 @@ void LLExperienceCache::initSingleton() constexpr size_t CORO_QUEUE_SIZE = 2048; LLCoprocedureManager::instance().initializePool("ExpCache", CORO_QUEUE_SIZE); - LLCoros::instance().launch("LLExperienceCache::idleCoro", - boost::bind(&LLExperienceCache::idleCoro, this)); - + LLCoros::instance().launch("LLExperienceCache::idleCoro", LLExperienceCache::idleCoro); } void LLExperienceCache::cleanup() @@ -246,6 +244,7 @@ const LLExperienceCache::cache_t& LLExperienceCache::getCached() return mCache; } +// static because used by coroutine and can outlive the instance void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests) { LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>(); @@ -254,6 +253,13 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + if (sShutdown) + { + return; + } + + LLExperienceCache* self = LLExperienceCache::getInstance(); + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); @@ -265,7 +271,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap // build dummy entries for the failed requests for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) { - LLSD exp = get(*it); + LLSD exp = self->get(*it); //leave the properties alone if we already have a cache entry for this xp if (exp.isUndefined()) { @@ -278,7 +284,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap exp["error"] = (LLSD::Integer)status.getType(); exp[QUOTA] = DEFAULT_QUOTA; - processExperience(*it, exp); + self->processExperience(*it, exp); } return; } @@ -294,7 +300,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap LL_DEBUGS("ExperienceCache") << "Received result for " << public_key << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; - processExperience(public_key, row); + self->processExperience(public_key, row); } LLSD error_ids = result["error_ids"]; @@ -310,7 +316,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap exp[MISSING] = true; exp[QUOTA] = DEFAULT_QUOTA; - processExperience(id, exp); + self->processExperience(id, exp); LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; } @@ -361,7 +367,7 @@ void LLExperienceCache::requestExperiences() if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "RequestExperiences", - boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + boost::bind(&LLExperienceCache::requestExperiencesCoro, _1, ostr.str(), requests) ); ostr.str(std::string()); ostr << urlBase << "?page_size=" << PAGE_SIZE1; @@ -393,7 +399,7 @@ void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t mCapability = queryfn; } - +// static, because coro can outlive the instance void LLExperienceCache::idleCoro() { const F32 SECS_BETWEEN_REQUESTS = 0.5f; @@ -402,14 +408,15 @@ void LLExperienceCache::idleCoro() LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; do { - if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + LLExperienceCache* self = LLExperienceCache::getInstance(); + if (self->mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) { - eraseExpired(); + self->eraseExpired(); } - if (!mRequestQueue.empty()) + if (!self->mRequestQueue.empty()) { - requestExperiences(); + self->requestExperiences(); } llcoro::suspendUntilTimeout(SECS_BETWEEN_REQUESTS); diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 4b344347d5..9ecdb9efca 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -144,9 +144,9 @@ private: std::string mCacheFileName; static bool sShutdown; // control for coroutines, they exist out of LLExperienceCache's scope, so they need a static control - void idleCoro(); + static void idleCoro(); void eraseExpired(); - void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); + static void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); void requestExperiences(); void fetchAssociatedExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLUUID, LLUUID, std::string, ExperienceGetFn_t); 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; + } } } diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp index b5b17c53aa..48c6ba1fa5 100644 --- a/indra/llprimitive/llmediaentry.cpp +++ b/indra/llprimitive/llmediaentry.cpp @@ -74,7 +74,7 @@ const char* LLMediaEntry::WHITELIST_KEY = MEDIA_WHITELIST_KEY_STR; const char* LLMediaEntry::PERMS_INTERACT_KEY = MEDIA_PERMS_INTERACT_KEY_STR; const char* LLMediaEntry::PERMS_CONTROL_KEY = MEDIA_PERMS_CONTROL_KEY_STR; -#define DEFAULT_URL_PREFIX "http://" +#define DEFAULT_URL_PREFIX "https://" // Constructor(s) LLMediaEntry::LLMediaEntry() : diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 26e4aaad52..b15cec5804 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -86,7 +86,10 @@ void LLCubeMap::initGL() #endif mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4); - mImages[i]->createGLTexture(0, mRawImages[i], texname); + if (!mImages[i]->createGLTexture(0, mRawImages[i], texname)) + { + LL_WARNS() << "Failed to create GL texture for environment cubemap face " << i << LL_ENDL; + } gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -203,7 +206,10 @@ void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& ra mImages[i] = new LLImageGL(resolution, resolution, components, true); mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = rawimages[i]; - mImages[i]->createGLTexture(0, mRawImages[i], texname); + if (!mImages[i]->createGLTexture(0, mRawImages[i], texname)) + { + LL_WARNS() << "Failed to create GL texture for environment cubemap face " << i << LL_ENDL; + } gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); 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*> 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<LLGLSLShader*> sInstances; static bool sProfileEnabled; + static bool sCanProfile; LLGLSLShader(); ~LLGLSLShader(); diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 8dcc809dfe..ac8f7c2126 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -309,11 +309,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) 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 diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index d32b8c2d0e..3ab5e905e3 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -259,6 +259,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); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 95603d7ed5..bba80dd20e 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -234,7 +234,7 @@ bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const || label.find("www.") != std::string::npos) && label.find("://") == std::string::npos) { - label = "http://" + label; + label = "https://" + label; } return !LLUrlRegistry::instance().hasUrl(label); @@ -315,7 +315,7 @@ std::string LLUrlEntryHTTP::getUrl(const std::string &string) const { if (string.find("://") == std::string::npos) { - return "http://" + escapeUrl(string); + return "https://" + escapeUrl(string); } return escapeUrl(string); } diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index 1eb2d17807..4b7700ccab 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -572,14 +572,20 @@ void LLWebRTCImpl::workerDeployDevices() void LLWebRTCImpl::setCaptureDevice(const std::string &id) { - mRecordingDevice = id; - deployDevices(); + if (mRecordingDevice != id) + { + mRecordingDevice = id; + deployDevices(); + } } void LLWebRTCImpl::setRenderDevice(const std::string &id) { - mPlayoutDevice = id; - deployDevices(); + if (mPlayoutDevice != id) + { + mPlayoutDevice = id; + deployDevices(); + } } // updateDevices needs to happen on the worker thread. diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 429dc57af3..4703009f54 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.2.3 +2026.01.0 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b0558eac78..65fe211fe2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4484,13 +4484,24 @@ <key>MainloopTimeoutDefault</key> <map> <key>Comment</key> - <string>Timeout duration for mainloop lock detection, in seconds.</string> + <string>Timeout duration for mainloop lock detection during teleports, login and logout, in seconds.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>60.0</real> + <real>120.0</real> + </map> + <key>MainloopTimeoutStarted</key> + <map> + <key>Comment</key> + <string>Timeout duration for mainloop lock detection when logged in and not teleporting, in seconds.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>30.0</real> </map> <key>MapScale</key> <map> @@ -13895,13 +13906,13 @@ <key>WatchdogEnabled</key> <map> <key>Comment</key> - <string>Controls whether the thread watchdog timer is activated. Value is boolean. Set to -1 to defer to built-in default.</string> + <string>Controls whether the thread watchdog timer is activated. Value is S32. Set to -1 to defer to built-in default.</string> <key>Persist</key> <integer>0</integer> <key>Type</key> <string>S32</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>WaterGLFogDensityScale</key> <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 72bfdcf83c..569fd30b21 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3145,7 +3145,7 @@ bool LLAppViewer::initWindow() // Need to load feature table before cheking to start watchdog. bool use_watchdog = false; - int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); + S32 watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); if (watchdog_enabled_setting == -1) { use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); @@ -3950,7 +3950,7 @@ void LLAppViewer::processMarkerFiles() #if LL_WINDOWS && LL_BUGSPLAT // bugsplat will set correct state in bugsplatSendLog // Might be more accurate to rename this one into 'unknown' - gLastExecEvent = LAST_EXEC_FROZE; + gLastExecEvent = LAST_EXEC_UNKNOWN; #else gLastExecEvent = LAST_EXEC_OTHER_CRASH; #endif // LL_WINDOWS @@ -3996,7 +3996,8 @@ void LLAppViewer::processMarkerFiles() { if (markerIsSameVersion(logout_marker_file)) { - gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; + // Either froze, got killed or somehow crash was not caught + gLastExecEvent = LAST_EXEC_LOGOUT_UNKNOWN; LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; } else @@ -5820,12 +5821,12 @@ void LLAppViewer::forceExceptionThreadCrash() thread->start(); } -void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::initMainloopTimeout(std::string_view state) { if (!mMainloopTimeout) { mMainloopTimeout = new LLWatchdogTimeout(); - resumeMainloopTimeout(state, secs); + resumeMainloopTimeout(state); } } @@ -5838,17 +5839,11 @@ void LLAppViewer::destroyMainloopTimeout() } } -void LLAppViewer::resumeMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::resumeMainloopTimeout(std::string_view state) { if (mMainloopTimeout) { - if (secs < 0.0f) - { - static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60.f); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->setTimeout(getMainloopTimeoutSec()); mMainloopTimeout->start(state); } } @@ -5861,23 +5856,33 @@ void LLAppViewer::pauseMainloopTimeout() } } -void LLAppViewer::pingMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::pingMainloopTimeout(std::string_view state) { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; if (mMainloopTimeout) { - if (secs < 0.0f) - { - static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->setTimeout(getMainloopTimeoutSec()); mMainloopTimeout->ping(state); } } + +F32 LLAppViewer::getMainloopTimeoutSec() const +{ + if (LLStartUp::getStartupState() == STATE_STARTED + && gAgent.getTeleportState() == LLAgent::TELEPORT_NONE) + { + static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 30.f); + return mainloop_started(); + } + else + { + static LLCachedControl<F32> mainloop_default(gSavedSettings, "MainloopTimeoutDefault", 120.f); + return mainloop_default(); + } +} + void LLAppViewer::handleLoginComplete() { gLoggedInTime.start(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index c12b2e83ef..6b0d3e0b27 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -77,6 +77,8 @@ typedef enum LAST_EXEC_BAD_ALLOC, LAST_EXEC_MISSING_FILES, LAST_EXEC_GRAPHICS_INIT, + LAST_EXEC_UNKNOWN, + LAST_EXEC_LOGOUT_UNKNOWN, LAST_EXEC_COUNT } eLastExecEvent; @@ -204,11 +206,13 @@ public: // For thread debugging. // llstartup needs to control init. // llworld, send_agent_pause() also controls pause/resume. - void initMainloopTimeout(std::string_view state, F32 secs = -1.0f); + void initMainloopTimeout(std::string_view state); void destroyMainloopTimeout(); void pauseMainloopTimeout(); - void resumeMainloopTimeout(std::string_view state = "", F32 secs = -1.0f); - void pingMainloopTimeout(std::string_view state, F32 secs = -1.0f); + void resumeMainloopTimeout(std::string_view state = ""); + void pingMainloopTimeout(std::string_view state); + + F32 getMainloopTimeoutSec() const; // Handle the 'login completed' event. // *NOTE:Mani Fix this for login abstraction!! diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index a951338138..0620b625d9 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -176,10 +176,17 @@ namespace LLAppViewer* app = LLAppViewer::instance(); if (!app->isSecondInstance() && !app->errorMarkerExists()) { - // If marker doesn't exist, create a marker with 'other' code for next launch + // If marker doesn't exist, create a marker with 'other' or 'logout' 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 diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 0578072bb2..6c151351ff 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -798,7 +798,10 @@ void LLBumpImageList::onSourceStandardLoaded( bool success, LLViewerFetchedTextu } src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); { - src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image); + if (!src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image)) + { + LL_WARNS() << "Failed to create bump image texture for image " << src_vi->getID() << LL_ENDL; + } } } } @@ -892,7 +895,10 @@ void LLBumpImageList::onSourceUpdated(LLViewerTexture* src, EBumpEffect bump_cod LLImageGL* src_img = src->getGLTexture(); LLImageGL* dst_img = bump->getGLTexture(); - dst_img->setSize(src->getWidth(), src->getHeight(), 4, 0); + if (!dst_img->setSize(src->getWidth(), src->getHeight(), 4, 0)) + { + LL_WARNS() << "Failed to setSize for image " << bump->getID() << LL_ENDL; + } dst_img->setUseMipMaps(true); dst_img->setDiscardLevel(0); dst_img->createGLTexture(); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 377710c170..98b3ca820b 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1395,6 +1395,19 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata) { return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); } + else if (param == "copy_slurl" + || param == "show_on_map") + { + LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + if (nullptr == item) + return false; // shouldn't happen as it is selected from existing items + + const LLUUID& asset_id = item->getAssetUUID(); + + // Favorites are supposed to be loaded first, it should be here already + LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL /*callback*/); + return nullptr != landmark; + } return false; } @@ -1425,10 +1438,17 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity if (!posGlobal.isExactlyZero()) { LLLandmarkActions::getSLURLfromPosGlobal(posGlobal, copy_slurl_to_clipboard_cb); } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } else if (action == "show_on_map") { @@ -1437,10 +1457,20 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); - if (!posGlobal.isExactlyZero() && worldmap_instance) + if (worldmap_instance) { - worldmap_instance->trackLocation(posGlobal); - LLFloaterReg::showInstance("world_map", "center"); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity + if (!posGlobal.isExactlyZero()) + { + worldmap_instance->trackLocation(posGlobal); + LLFloaterReg::showInstance("world_map", "center"); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } } else if (action == "create_pick") diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 1bffe34b8f..e9bee93a19 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -403,8 +403,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<std::string, 7> 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 benchmark and occlusion culling to prevent freezes." << LL_ENDL; + gSavedSettings.setBOOL("SkipBenchmark", true); + gSavedSettings.setBOOL("UseOcclusion", false); + } + if (!gSavedSettings.getBOOL("SkipBenchmark")) { F32 class1_gbps = gSavedSettings.getF32("RenderClass1MemoryBandwidth"); @@ -464,7 +509,7 @@ bool LLFeatureManager::loadGPUClass() } #if LL_WINDOWS - const F32Gigabytes MIN_PHYSICAL_MEMORY(2); + const F32Gigabytes MIN_PHYSICAL_MEMORY(8); LLMemory::updateMemoryInfo(); F32Gigabytes physical_mem = LLMemory::getMaxMemKB(); 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 diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h index f0e9ce81dc..d0374c5a08 100644 --- a/indra/newview/llfilepicker_mac.h +++ b/indra/newview/llfilepicker_mac.h @@ -44,7 +44,7 @@ std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::st // doLoadDialogModeless if window does not exists creates a modeless // window, if it does exist, creates a 'sheet' that does not block -// thead but blocks window interractions +// thread but blocks window interractions void doLoadDialogModeless(const std::vector<std::string>* allowed_types, unsigned int flags, void (*callback)(bool, std::vector<std::string>&, void*), diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 25970f8a08..95e7b9af41 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -716,7 +716,7 @@ void LLFloater360Capture::onSaveLocalBtn() { // region name and URL std::string region_name; // no sensible default - std::string region_url("http://secondlife.com"); + std::string region_url("https://secondlife.com"); LLViewerRegion* region = gAgent.getRegion(); if (region) { diff --git a/indra/newview/llfloateravatarwelcomepack.cpp b/indra/newview/llfloateravatarwelcomepack.cpp index 82e44d1398..be384bf4d1 100644 --- a/indra/newview/llfloateravatarwelcomepack.cpp +++ b/indra/newview/llfloateravatarwelcomepack.cpp @@ -28,8 +28,10 @@ #include "llviewerprecompiledheaders.h" #include "llfloateravatarwelcomepack.h" -#include "lluictrlfactory.h" #include "llmediactrl.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llweb.h" LLFloaterAvatarWelcomePack::LLFloaterAvatarWelcomePack(const LLSD& key) : LLFloater(key) @@ -52,6 +54,10 @@ bool LLFloaterAvatarWelcomePack::postBuild() if (mAvatarPicker) { mAvatarPicker->clearCache(); + mAvatarPicker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("AvatarWelcomePack"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + mAvatarPicker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } return true; diff --git a/indra/newview/llfloaterdestinations.cpp b/indra/newview/llfloaterdestinations.cpp index fad9693e8f..84fc4afcdd 100644 --- a/indra/newview/llfloaterdestinations.cpp +++ b/indra/newview/llfloaterdestinations.cpp @@ -28,7 +28,10 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterdestinations.h" +#include "llmediactrl.h" #include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llweb.h" LLFloaterDestinations::LLFloaterDestinations(const LLSD& key) @@ -43,6 +46,15 @@ LLFloaterDestinations::~LLFloaterDestinations() bool LLFloaterDestinations::postBuild() { enableResizeCtrls(true, true, false); + LLMediaCtrl* destinations = getChild<LLMediaCtrl>("destination_guide_contents"); + destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("DestinationGuideURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + + // If cookie is there, will set it now. Otherwise will have to wait for login completion + // which will also update destinations instance if it already exists. + LLViewerMedia::getInstance()->getOpenIDCookie(destinations); return true; } diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp index 4abea64302..7316d7617d 100644 --- a/indra/newview/llfloatermarketplace.cpp +++ b/indra/newview/llfloatermarketplace.cpp @@ -46,9 +46,16 @@ void LLFloaterMarketplace::onClose(bool app_quitting) bool LLFloaterMarketplace::postBuild() { - LLFloaterWebContent::postBuild(); - mWebBrowser = getChild<LLMediaCtrl>("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); + + // If cookie is there, will set it now, Otherwise will have to wait for login completion + // which will also update marketplace instance if it already exists. + LLViewerMedia::getInstance()->getOpenIDCookie(mWebBrowser); return true; } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index bfce13affc..4cb6e7be96 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -269,10 +269,12 @@ bool LLFloaterRegionInfo::postBuild() static LLCachedControl<bool> 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); @@ -1489,6 +1491,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()) { @@ -1998,18 +2005,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); }); } @@ -2097,6 +2093,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; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 7ee1b88f05..9b7a4e5134 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -161,15 +161,20 @@ 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<LLMediaCtrl>("search_contents"); - search_browser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } bool LLFloaterSearch::postBuild() { - LLFloaterWebContent::postBuild(); - mWebBrowser = getChild<LLMediaCtrl>("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 + // which will also update search instance if it already exists. + LLViewerMedia::getInstance()->getOpenIDCookie(mWebBrowser); + getChildView("address")->setEnabled(false); getChildView("popexternal")->setEnabled(false); diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index fe567ac7ec..779ed725ac 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -202,9 +202,19 @@ void inventory_offer_handler(LLOfferInfo* info) auto indx = msg.find(" ( http://slurl.com/secondlife/"); if (indx == std::string::npos) { - // try to find new slurl host + // https + indx = msg.find(" ( https://slurl.com/secondlife/"); + } + if (indx == std::string::npos) + { + // try to find new slurl http host indx = msg.find(" ( http://maps.secondlife.com/secondlife/"); } + if (indx == std::string::npos) + { + // try to find new slurl https host + indx = msg.find(" ( https://maps.secondlife.com/secondlife/"); + } if (indx >= 0) { LLStringUtil::truncate(msg, indx); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index a99c9df0ff..6e56aac270 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -219,7 +219,10 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) LLPointer<LLViewerFetchedTexture> texture = new LLViewerFetchedTexture ("file://"+mFilename, FTT_LOCAL_FILE, mWorldID, LL_LOCAL_USE_MIPMAPS); - texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image); + if (!texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image)) + { + LL_WARNS() << "Failed to create GL texture for local bitmap: " << mFilename << " " << mWorldID << LL_ENDL; + } texture->ref(); gTextureList.addImage(texture, TEX_LIST_STANDARD); diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index 6e4e9f426d..68e2808a83 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -220,7 +220,7 @@ const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& if ( candidate_url.scheme().empty() ) { // build a URL comprised of default scheme and the original fragment - const std::string default_scheme( "http://" ); + const std::string default_scheme( "https://" ); return default_scheme + src_url; }; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 87f05f2028..c380b6860f 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -517,7 +517,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, std::string parcel_owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); - LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); mRegionGroupText->setText( getString("none_text")); } @@ -548,7 +548,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); if(auth_buyer_id.notNull()) { - LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); // Show sales info to a specific person or a group he belongs to. if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index f562be0f5d..0c161198f8 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -118,6 +118,8 @@ private: LLTextEditor* mResaleText; LLTextBox* mSaleToText; LLAccordionCtrl* mAccordionCtrl; + + boost::signals2::scoped_connection mAvatarNameCacheConnection; }; #endif // LL_LLPANELPLACEPROFILE_H diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp index de0ed645eb..871bf36ed3 100644 --- a/indra/newview/llurllineeditorctrl.cpp +++ b/indra/newview/llurllineeditorctrl.cpp @@ -84,7 +84,9 @@ void LLURLLineEditor::copyEscapedURLToClipboard() const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length)); LLWString text_to_copy; // *HACK: Because LLSLURL is currently broken we cannot use it to check if unescaped_text is a valid SLURL (see EXT-8335). - if (LLStringUtil::startsWith(unescaped_text, "http://") || LLStringUtil::startsWith(unescaped_text, "secondlife://")) // SLURL + if (LLStringUtil::startsWith(unescaped_text, "https://") + || LLStringUtil::startsWith(unescaped_text, "http://") + || LLStringUtil::startsWith(unescaped_text, "secondlife://")) // SLURL text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text)); else // human-readable location text_to_copy = utf8str_to_wstring(unescaped_text); 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/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index d5f63674e9..bb956d455f 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -83,6 +83,8 @@ extern bool gCubeSnapshot; // *TODO: Consider enabling mipmaps (they have been disabled for a long time). Likely has a significant performance impact for tiled/high texture repeat media. Mip generation in a shader may also be an option if necessary. constexpr bool USE_MIPMAPS = false; +constexpr S32 MAX_MEDIA_INSTANCES_DEFAULT = 8; +constexpr S32 MEDIA_INSTANCES_MIN_LIMIT = 6; // 4 'permanent' floaters plus reserve for dynamic ones void init_threaded_picker_load_dialog(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple) { @@ -214,6 +216,7 @@ static bool sViewerMediaMuteListObserverInitialized = false; LLViewerMedia::LLViewerMedia(): mAnyMediaShowing(false), mAnyMediaPlaying(false), +mMaxIntances(MAX_MEDIA_INSTANCES_DEFAULT), mSpareBrowserMediaSource(NULL) { } @@ -222,6 +225,7 @@ LLViewerMedia::~LLViewerMedia() { gIdleCallbacks.deleteFunction(LLViewerMedia::onIdle, NULL); mTeleportFinishConnection.disconnect(); + mMaxInstancesConnection.disconnect(); if (mSpareBrowserMediaSource != NULL) { delete mSpareBrowserMediaSource; @@ -235,6 +239,35 @@ void LLViewerMedia::initSingleton() gIdleCallbacks.addFunction(LLViewerMedia::onIdle, NULL); mTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished, this)); + + LLControlVariable* ctrl = gSavedSettings.getControl("PluginInstancesTotal"); + if (ctrl) + { + setMaxInstances(ctrl->getValue().asInteger()); + mMaxInstancesConnection = ctrl->getSignal()->connect([this](LLControlVariable* control, const LLSD& new_val, const LLSD& old_val) + { + setMaxInstances(new_val.asInteger()); + }); + } + else + { + setMaxInstances(MAX_MEDIA_INSTANCES_DEFAULT); + } +} + +void LLViewerMedia::setMaxInstances(S32 max_instances) +{ + const F32Gigabytes MIN_PHYSICAL_MEMORY(8); + LLMemory::updateMemoryInfo(); + F32Gigabytes physical_mem = LLMemory::getMaxMemKB(); + if (MIN_PHYSICAL_MEMORY > physical_mem) + { + mMaxIntances = llmax(max_instances - 2, MEDIA_INSTANCES_MIN_LIMIT); + } + else + { + mMaxIntances = llmax(max_instances, MEDIA_INSTANCES_MIN_LIMIT); + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -688,7 +721,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) static LLCachedControl<bool> inworld_media_enabled(gSavedSettings, "AudioStreamingMedia", true); static LLCachedControl<bool> inworld_audio_enabled(gSavedSettings, "AudioStreamingMusic", true); - static LLCachedControl<U32> max_instances(gSavedSettings, "PluginInstancesTotal", 8); static LLCachedControl<U32> max_normal(gSavedSettings, "PluginInstancesNormal", 2); static LLCachedControl<U32> max_low(gSavedSettings, "PluginInstancesLow", 4); static LLCachedControl<F32> max_cpu(gSavedSettings, "PluginInstancesCPULimit", 0.9); @@ -709,7 +741,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL; - if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances)) + if(pimpl->isForcedUnloaded() || (impl_count_total >= mMaxIntances)) { // Never load muted or failed impls. // Hard limit on the number of instances that will be loaded at one time @@ -869,7 +901,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) sLowestLoadableImplInterest = 0.0f; // Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data. - if(lowest_interest_loadable && (impl_count_total >= (int)max_instances)) + if(lowest_interest_loadable && (impl_count_total >= mMaxIntances)) { // Get the interest value of this impl's object for use by isInterestingEnough LLVOVolume *object = lowest_interest_loadable->getSomeObject(); @@ -1201,6 +1233,54 @@ LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders() return headers; } +bool LLViewerMedia::getOpenIDCookie(LLMediaCtrl* media_instance) const +{ + if (mOpenIDCookie.empty()) + { + return false; + } + + std::string authority = mOpenIDURL.mAuthority; + std::string::size_type hostStart = authority.find('@'); + if (hostStart == std::string::npos) + { + // no username/password + hostStart = 0; + } + else + { + // Hostname starts after the @. + // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) + ++hostStart; + } + std::string::size_type hostEnd = authority.rfind(':'); + if ((hostEnd == std::string::npos) || (hostEnd < hostStart)) + { + // no port + hostEnd = authority.size(); + } + + std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); + std::string cookie_name = ""; + std::string cookie_value = ""; + std::string cookie_path = ""; + bool httponly = true; + bool secure = true; + if (!parseRawCookie(mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure)) + { + return false; + } + std::string cefUrl(std::string(mOpenIDURL.mURI) + "://" + std::string(mOpenIDURL.mAuthority)); + if (media_instance && media_instance->getMediaPlugin()) + { + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, + cookie_path, httponly, secure); + + media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value, + cookie_host, cookie_path, httponly, secure); + } + return true; +} ///////////////////////////////////////////////////////////////////////////////////////// void LLViewerMedia::setOpenIDCookie(const std::string& url) @@ -1267,7 +1347,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) bool secure = true; LLViewerMedia* inst = getInstance(); - if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure)) + if (parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure)) { // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. @@ -1284,20 +1364,24 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) std::string browser_name; }; struct MediaCookieInstance media_cookie_instances[] = { - {"search", "search_contents" }, - {"marketplace", "marketplace_contents" }, + {"search", "webbrowser" }, + {"marketplace", "webbrowser" }, {"destinations", "destination_guide_contents" }, }; for (MediaCookieInstance mci : media_cookie_instances) { - LLMediaCtrl* media_instance = LLFloaterReg::getInstance(mci.floater_name)->getChild<LLMediaCtrl>(mci.browser_name); - if (media_instance && media_instance->getMediaPlugin()) + LLFloater *floaterp = LLFloaterReg::findInstance(mci.floater_name); + if (floaterp) { - media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, - cookie_path, httponly, secure); + LLMediaCtrl* media_instance = floaterp->getChild<LLMediaCtrl>(mci.browser_name); + if (media_instance && media_instance->getMediaPlugin()) + { + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, + cookie_path, httponly, secure); - media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value, - cookie_host, cookie_path, httponly, secure); + media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value, + cookie_host, cookie_path, httponly, secure); + } } } } @@ -3001,7 +3085,10 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da // -Cosmic,2023-04-04 // Allocate GL texture based on LLImageRaw but do NOT copy to GL LLGLuint tex_name = 0; - media_tex->createGLTexture(0, raw, 0, true, LLGLTexture::OTHER, true, &tex_name); + if (!media_tex->createGLTexture(0, raw, 0, true, LLGLTexture::OTHER, true, &tex_name)) + { + LL_WARNS("Media") << "Failed to create media texture" << LL_ENDL; + } // copy just the subimage covered by the image raw to GL media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); @@ -3070,7 +3157,10 @@ LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage() mMediaSource->getTextureFormatSwapBytes()); int discard_level = 0; - media_tex->createGLTexture(discard_level, raw); + if (!media_tex->createGLTexture(discard_level, raw)) + { + LL_WARNS("Media") << "Failed to create media texture" << LL_ENDL; + } // MEDIAOPT: set this dynamically on play/stop // FIXME diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index c17cf59815..1fc5bbc9e0 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -69,6 +69,7 @@ private: }; class LLViewerMediaImpl; +class LLMediaCtrl; class LLViewerMedia: public LLSingleton<LLViewerMedia> { @@ -162,22 +163,26 @@ public: LLSD getHeaders(); LLCore::HttpHeaders::ptr_t getHttpHeaders(); + bool getOpenIDCookie(LLMediaCtrl* media_instance) const; private: void onAuthSubmit(const LLSD& notification, const LLSD& response); - bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure); + static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure); void setOpenIDCookie(const std::string& url); void onTeleportFinished(); static void openIDSetupCoro(std::string openidUrl, std::string openidToken); static void getOpenIDCookieCoro(std::string url); + void setMaxInstances(S32 max_instances); bool mAnyMediaShowing; bool mAnyMediaPlaying; + S32 mMaxIntances = 8; LLURL mOpenIDURL; std::string mOpenIDCookie; LLPluginClassMedia* mSpareBrowserMediaSource; boost::signals2::connection mTeleportFinishConnection; + boost::signals2::connection mMaxInstancesConnection; }; // Implementation functions not exported into header file diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index f11fa09ce9..890580ddff 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -69,7 +69,7 @@ const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bi const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update"; -const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/"; +const std::string MAIN_GRID_SLURL_BASE = "https://maps.secondlife.com/secondlife/"; const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; const std::string MAIN_GRID_WEB_PROFILE_URL = "https://my.secondlife.com/"; @@ -281,7 +281,7 @@ bool LLGridManager::addGrid(LLSD& grid_data) // Populate to the default values if (!grid_data.has(GRID_LOGIN_PAGE_VALUE)) { - grid_data[GRID_LOGIN_PAGE_VALUE] = std::string("http://") + grid + "/app/login/"; + grid_data[GRID_LOGIN_PAGE_VALUE] = std::string("https://") + grid + "/app/login/"; } if (!grid_data.has(GRID_HELPER_URI_VALUE)) { diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 92e15bb74b..8ec0dd0024 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -229,8 +229,12 @@ extern LLTrace::EventStatHandle<F64Seconds > AVATAR_EDIT_TIME, extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT_RATE; +extern LLTrace::SampleStatHandle<F64> NOTRMALIZED_FRAMETIME_JITTER_SESSION; +extern LLTrace::SampleStatHandle<F64> NORMALIZED_FRAMTIME_JITTER_PERIOD; + extern LLTrace::SampleStatHandle<U32> WEBRTC_PACKETS_IN_LOST, WEBRTC_PACKETS_IN_RECEIVED, WEBRTC_PACKETS_OUT_SENT, WEBRTC_PACKETS_OUT_LOST; extern LLTrace::SampleStatHandle<F32> WEBRTC_JITTER_OUT, WEBRTC_JITTER_IN, WEBRTC_LATENCY, WEBRTC_UPLOAD_BANDWIDTH, WEBRTC_JITTER_BUFFER; + } class LLViewerStats : public LLSingleton<LLViewerStats> diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 6135e18840..1e83482752 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -406,7 +406,10 @@ void LLViewerTextureManager::init() } } } - imagep->createGLTexture(0, image_raw); + if (!imagep->createGLTexture(0, image_raw)) + { + LL_WARNS() << "Failed to create default texture " << IMG_DEFAULT << LL_ENDL; + } image_raw = NULL; #else LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, true, LLGLTexture::BOOST_UI); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c474bff2dc..187cfc9792 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2324,36 +2324,23 @@ void LLViewerWindow::initWorldUI() gToolBarView->setVisible(true); } - if (!gNonInteractive) + // Don't preload cef instances on low end hardware + const F32Gigabytes MIN_PHYSICAL_MEMORY(8); + F32Gigabytes physical_mem = LLMemory::getMaxMemKB(); + if (physical_mem <= 0) { - LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); - if (destinations) - { - destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("DestinationGuideURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* avatar_welcome_pack = LLFloaterReg::getInstance("avatar_welcome_pack")->findChild<LLMediaCtrl>("avatar_picker_contents"); - if (avatar_welcome_pack) - { - avatar_welcome_pack->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("AvatarWelcomePack"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_welcome_pack->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* search = LLFloaterReg::getInstance("search")->findChild<LLMediaCtrl>("search_contents"); - if (search) - { - search->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - } - LLMediaCtrl* marketplace = LLFloaterReg::getInstance("marketplace")->getChild<LLMediaCtrl>("marketplace_contents"); - if (marketplace) - { - marketplace->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("MarketplaceURL"); - marketplace->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } + LLMemory::updateMemoryInfo(); + physical_mem = LLMemory::getMaxMemKB(); + } + + if (!gNonInteractive && physical_mem > MIN_PHYSICAL_MEMORY) + { + LL_INFOS() << "Preloading cef instances" << LL_ENDL; + + LLFloaterReg::getInstance("destinations"); + LLFloaterReg::getInstance("avatar_welcome_pack"); + LLFloaterReg::getInstance("search"); + LLFloaterReg::getInstance("marketplace"); } } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 89cc05802d..9c0f4baf28 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2693,10 +2693,10 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) if (mep && impl) { std::string url = mep->getCurrentURL(); - // Look for a ":", if not there, assume "http://" + // Look for a ":", if not there, assume "https://" if (!url.empty() && std::string::npos == url.find(':')) { - url = "http://" + url; + url = "https://" + url; } // If the url we're trying to "bounce back" to is either empty or not // allowed by the whitelist, try the home url. If *that* doesn't work, @@ -2704,10 +2704,10 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) if (url.empty() || !mep->checkCandidateUrl(url)) { url = mep->getHomeURL(); - // Look for a ":", if not there, assume "http://" + // Look for a ":", if not there, assume "https://" if (!url.empty() && std::string::npos == url.find(':')) { - url = "http://" + url; + url = "https://" + url; } } if (url.empty() || !mep->checkCandidateUrl(url)) diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index bf171fe954..614d1afc2a 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llwatchdog.h" #include "llthread.h" +#include "llappviewer.h" constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U; @@ -240,7 +241,16 @@ void LLWatchdog::run() { mTimer->stop(); } - + if (LLAppViewer::instance()->logoutRequestSent()) + { + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LOGOUT_FROZE); + } + else + { + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_FROZE); + } + // Todo1: warn user? + // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'. LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL; } } diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index edaa44aa70..6d234a9a34 100644 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -54,7 +54,7 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter& "Given [\"keysym\"], [\"keycode\"] or [\"char\"], inject the specified "; std::string keyExplain = "(integer keycode values, or keysym string from any addKeyName() call in\n" - "http://bitbucket.org/lindenlab/viewer-release/src/tip/indra/llwindow/llkeyboard.cpp )\n"; + "https://github.com/secondlife/viewer/blob/develop/indra/llwindow/llkeyboard.cpp )\n"; std::string mask = "Specify optional [\"mask\"] as an array containing any of \"CTL\", \"ALT\",\n" "\"SHIFT\" or \"MAC_CONTROL\"; the corresponding modifier bits will be combined\n" @@ -69,7 +69,7 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter& "(button values \"LEFT\", \"MIDDLE\", \"RIGHT\")\n"; std::string paramsExplain = "[\"path\"] is as for LLUI::getInstance()->resolvePath(), described in\n" - "http://bitbucket.org/lindenlab/viewer-release/src/tip/indra/llui/llui.h\n" + "https://github.com/secondlife/viewer/blob/develop/indra/llui/llui.h\n" "If you omit [\"path\"], you must specify both [\"x\"] and [\"y\"].\n" "If you specify [\"path\"] without both [\"x\"] and [\"y\"], will synthesize (x, y)\n" "in the center of the LLView selected by [\"path\"].\n" 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"/> </layout_panel> <layout_panel name="status_bar" 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"/> </layout_panel> <layout_panel name="status_bar" diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml index 6345394b46..f82f705fb7 100644 --- a/indra/newview/skins/default/xui/en/menu_favorites.xml +++ b/indra/newview/skins/default/xui/en/menu_favorites.xml @@ -35,6 +35,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="show_on_map" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="show_on_map" /> </menu_item_call> <menu_item_call label="Copy SLurl" @@ -43,6 +46,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="copy_slurl" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="copy_slurl" /> </menu_item_call> <menu_item_call label="Create Pick" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 14e9211b9c..20a8fe1863 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2466,6 +2466,17 @@ You already have a landmark for this location. </notification> <notification + icon="alert.tga" + name="LandmarkLocationUnknown" + type="alert"> +Viewer wasn't able to get region's location. Region might be temporarily unavailable or was removed. + <usetemplate + name="okbutton" + yestext="OK"/> + <tag>fail</tag> + </notification> + + <notification icon="alertmodal.tga" name="CannotCreateLandmarkNotOwner" type="alertmodal"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index 3a5a8cbfec..2fc859f43e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -214,7 +214,7 @@ left_pad="10" top_delta="-6" name="mouse_warp_combo" - tooltip="Controls warping of the mouse to the center of the screen during alt-zoom and mouse look." + tool_tip="Controls warping of the mouse to the center of the screen during alt-zoom and mouse look." width="200"> <combo_box.item label="Automatic" diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index fc9f5b707a..3ff38ea372 100644 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -177,15 +177,15 @@ namespace tut LLSLURL slurl = LLSLURL(""); ensure_equals("null slurl", (int)slurl.getType(), LLSLURL::LAST_LOCATION); - slurl = LLSLURL("http://slurl.com/secondlife/myregion"); + slurl = LLSLURL("https://slurl.com/secondlife/myregion"); ensure_equals("slurl.com slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("slurl.com slurl, region only", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + "https://maps.secondlife.com/secondlife/myregion/128/128/0"); - slurl = LLSLURL("http://maps.secondlife.com/secondlife/myregion/1/2/3"); + slurl = LLSLURL("https://maps.secondlife.com/secondlife/myregion/1/2/3"); ensure_equals("maps.secondlife.com slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("maps.secondlife.com slurl, region + coords", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + "https://maps.secondlife.com/secondlife/myregion/1/2/3"); slurl = LLSLURL("secondlife://"); ensure_equals("secondlife: slurl, empty - type", slurl.getType(), LLSLURL::EMPTY); @@ -196,27 +196,27 @@ namespace tut slurl = LLSLURL("secondlife://myregion"); ensure_equals("secondlife: slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("secondlife: slurl, region only", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + "https://maps.secondlife.com/secondlife/myregion/128/128/0"); slurl = LLSLURL("secondlife://myregion/1/2/3"); ensure_equals("secondlife: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("secondlife slurl, region + coords", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + "https://maps.secondlife.com/secondlife/myregion/1/2/3"); slurl = LLSLURL("/myregion"); ensure_equals("/region slurl, region- type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("/region slurl, region ", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + "https://maps.secondlife.com/secondlife/myregion/128/128/0"); slurl = LLSLURL("/myregion/1/2/3"); ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals("/ slurl, region + coords", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + "https://maps.secondlife.com/secondlife/myregion/1/2/3"); slurl = LLSLURL("my region/1/2/3"); ensure_equals(" slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals(" slurl, region + coords", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/my%20region/1/2/3"); + "https://maps.secondlife.com/secondlife/my%20region/1/2/3"); LLGridManager::getInstance()->setGridChoice("my.grid.com"); slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); @@ -309,7 +309,7 @@ namespace tut slurl = LLSLURL("my region", LLVector3(1,2,3)); ensure_equals("default grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); ensure_equals(" default grid/region/vector", slurl.getSLURLString(), - "http://maps.secondlife.com/secondlife/my%20region/1/2/3"); + "https://maps.secondlife.com/secondlife/my%20region/1/2/3"); LLGridManager::getInstance()->setGridChoice("MyGrid"); slurl = LLSLURL("my region", LLVector3(1,2,3)); diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index d9cb9e7538..94cf0fcf10 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -391,7 +391,7 @@ namespace tut std::string("https://minimal.long.name/helpers/")); ensure_equals("minimal grid login page", LLGridManager::getInstance()->getLoginPage("minimal.long.name"), - std::string("http://minimal.long.name/app/login/")); + std::string("https://minimal.long.name/app/login/")); } |
