#4604 Turn off cef preloading on low end hardware

1. Cef instances are fairly heavy in viewer's implementation, don't preload
them on systems <= 8GB
2. Move initialization into floaters where it belongs.
3. Minimal requirement is 8GB, drop gpu class to 1 on hardware under 8GB
4. Reduce cef instance count on systems under 8GB
master
Andrey Kleshchev 2025-10-28 21:11:54 +02:00
parent 5a0ba25d83
commit 0fd96e6247
8 changed files with 149 additions and 42 deletions

View File

@ -465,7 +465,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();

View File

@ -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;

View File

@ -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;
}

View File

@ -49,6 +49,13 @@ bool LLFloaterMarketplace::postBuild()
LLFloaterWebContent::postBuild();
mWebBrowser = getChild<LLMediaCtrl>("marketplace_contents");
mWebBrowser->addObserver(this);
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;
}

View File

@ -170,6 +170,12 @@ bool LLFloaterSearch::postBuild()
LLFloaterWebContent::postBuild();
mWebBrowser = getChild<LLMediaCtrl>("search_contents");
mWebBrowser->addObserver(this);
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);

View File

@ -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.
@ -1290,14 +1370,18 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
};
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);
}
}
}
}

View File

@ -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

View File

@ -2322,36 +2322,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");
}
}