summaryrefslogtreecommitdiff
path: root/indra/newview/llfeaturemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfeaturemanager.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llfeaturemanager.cpp444
1 files changed, 211 insertions, 233 deletions
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index a4cadcd5dc..ea39f812fd 100644..100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -30,15 +30,16 @@
#include <fstream>
#include <boost/regex.hpp>
+#include <boost/assign/list_of.hpp>
#include "llfeaturemanager.h"
#include "lldir.h"
#include "llsys.h"
#include "llgl.h"
-#include "llsecondlifeurls.h"
#include "llappviewer.h"
+#include "llbufferstream.h"
#include "llhttpclient.h"
#include "llnotificationsutil.h"
#include "llviewercontrol.h"
@@ -52,6 +53,8 @@
#include "llboost.h"
#include "llweb.h"
#include "llviewershadermgr.h"
+#include "llstring.h"
+#include "stringize.h"
#if LL_WINDOWS
#include "lldxhardware.h"
@@ -73,9 +76,8 @@ const char FEATURE_TABLE_FILENAME[] = "featuretable%s.txt";
const char FEATURE_TABLE_VER_FILENAME[] = "featuretable%s.%s.txt";
#endif
-const char GPU_TABLE_FILENAME[] = "gpu_table.txt";
-const char GPU_TABLE_VER_FILENAME[] = "gpu_table.%s.txt";
-
+#if 0 // consuming code in #if 0 below
+#endif
LLFeatureInfo::LLFeatureInfo(const std::string& name, const BOOL available, const F32 level)
: mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level)
{
@@ -128,7 +130,7 @@ F32 LLFeatureList::getRecommendedValue(const std::string& name)
BOOL LLFeatureList::maskList(LLFeatureList &mask)
{
- //llinfos << "Masking with " << mask.mName << llendl;
+ //LL_INFOS() << "Masking with " << mask.mName << LL_ENDL;
//
// Lookup the specified feature mask, and overlay it on top of the
// current feature mask.
@@ -187,6 +189,55 @@ void LLFeatureList::dump()
LL_DEBUGS("RenderInit") << LL_ENDL;
}
+static const std::vector<std::string> sGraphicsLevelNames = boost::assign::list_of
+ ("Low")
+ ("LowMid")
+ ("Mid")
+ ("MidHigh")
+ ("High")
+ ("HighUltra")
+ ("Ultra")
+;
+
+U32 LLFeatureManager::getMaxGraphicsLevel() const
+{
+ return sGraphicsLevelNames.size() - 1;
+}
+
+bool LLFeatureManager::isValidGraphicsLevel(U32 level) const
+{
+ return (level <= getMaxGraphicsLevel());
+}
+
+std::string LLFeatureManager::getNameForGraphicsLevel(U32 level) const
+{
+ if (isValidGraphicsLevel(level))
+ {
+ return sGraphicsLevelNames[level];
+ }
+ return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. "
+ << getMaxGraphicsLevel());
+}
+
+S32 LLFeatureManager::getGraphicsLevelForName(const std::string& name) const
+{
+ const std::string FixedFunction("FixedFunction");
+ std::string rname(name);
+ if (LLStringUtil::endsWith(rname, FixedFunction))
+ {
+ // chop off any "FixedFunction" suffix
+ rname = rname.substr(0, rname.length() - FixedFunction.length());
+ }
+ for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i)
+ {
+ if (sGraphicsLevelNames[i] == rname)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
LLFeatureList *LLFeatureManager::findMask(const std::string& name)
{
if (mMaskList.count(name))
@@ -209,7 +260,7 @@ BOOL LLFeatureManager::maskFeatures(const std::string& name)
return maskList(*maskp);
}
-BOOL LLFeatureManager::loadFeatureTables()
+bool LLFeatureManager::loadFeatureTables()
{
// *TODO - if I or anyone else adds something else to the skipped list
// make this data driven. Put it in the feature table and parse it
@@ -250,29 +301,37 @@ BOOL LLFeatureManager::loadFeatureTables()
// use HTTP table if it exists
std::string path;
+ bool parse_ok = false;
if (gDirUtilp->fileExists(http_path))
{
- path = http_path;
+ parse_ok = parseFeatureTable(http_path);
+ if (!parse_ok)
+ {
+ // the HTTP table failed to parse, so delete it
+ LLFile::remove(http_path);
+ LL_WARNS("RenderInit") << "Removed invalid feature table '" << http_path << "'" << LL_ENDL;
+ }
}
- else
+
+ if (!parse_ok)
{
- path = app_path;
+ parse_ok = parseFeatureTable(app_path);
}
-
- return parseFeatureTable(path);
+ return parse_ok;
}
-BOOL LLFeatureManager::parseFeatureTable(std::string filename)
+bool LLFeatureManager::parseFeatureTable(std::string filename)
{
- llinfos << "Looking for feature table in " << filename << llendl;
+ LL_INFOS("RenderInit") << "Attempting to parse feature table from " << filename << LL_ENDL;
llifstream file;
std::string name;
U32 version;
- file.open(filename); /*Flawfinder: ignore*/
+ cleanupFeatureTables(); // in case an earlier attempt left partial results
+ file.open(filename.c_str()); /*Flawfinder: ignore*/
if (!file)
{
@@ -286,13 +345,14 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename)
if (name != "version")
{
LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL;
- return FALSE;
+ return false;
}
mTableVersion = version;
LLFeatureList *flp = NULL;
- while (file >> name)
+ bool parse_ok = true;
+ while (file >> name && parse_ok)
{
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
@@ -305,210 +365,138 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename)
if (name == "list")
{
+ LL_DEBUGS("RenderInit") << "Before new list" << std::endl;
if (flp)
{
- //flp->dump();
+ flp->dump();
}
+ else
+ {
+ LL_CONT << "No current list";
+ }
+ LL_CONT << LL_ENDL;
+
// It's a new mask, create it.
file >> name;
- if (mMaskList.count(name))
+ if (!mMaskList.count(name))
{
- LL_ERRS("RenderInit") << "Overriding mask " << name << ", this is invalid!" << LL_ENDL;
- }
-
flp = new LLFeatureList(name);
mMaskList[name] = flp;
}
else
{
- if (!flp)
- {
- LL_ERRS("RenderInit") << "Specified parameter before <list> keyword!" << LL_ENDL;
- return FALSE;
+ LL_WARNS("RenderInit") << "Overriding mask " << name << ", this is invalid!" << LL_ENDL;
+ parse_ok = false;
}
+ }
+ else
+ {
+ if (flp)
+ {
S32 available;
F32 recommended;
file >> available >> recommended;
flp->addFeature(name, available, recommended);
}
+ else
+ {
+ LL_WARNS("RenderInit") << "Specified parameter before <list> keyword!" << LL_ENDL;
+ parse_ok = false;
+ }
+ }
}
file.close();
- return TRUE;
-}
-
-void LLFeatureManager::loadGPUClass()
-{
- // defaults
- mGPUClass = GPU_CLASS_UNKNOWN;
- mGPUString = gGLManager.getRawGLString();
- mGPUSupported = FALSE;
-
- // first table is in the app dir
- std::string app_path = gDirUtilp->getAppRODataDir();
- app_path += gDirUtilp->getDirDelimiter();
- app_path += GPU_TABLE_FILENAME;
-
- // second table is downloaded with HTTP
- std::string http_filename = llformat(GPU_TABLE_VER_FILENAME, LLVersionInfo::getVersion().c_str());
- std::string http_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, http_filename);
-
- // use HTTP table if it exists
- std::string path;
- if (gDirUtilp->fileExists(http_path))
- {
- path = http_path;
- }
- else
+ if (!parse_ok)
{
- path = app_path;
+ LL_WARNS("RenderInit") << "Discarding feature table data from " << filename << LL_ENDL;
+ cleanupFeatureTables();
}
-
- parseGPUTable(path);
-}
-
-void LLFeatureManager::parseGPUTable(std::string filename)
-{
- llifstream file;
-
- file.open(filename);
-
- if (!file)
- {
- LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL;
- return;
- }
-
- std::string rawRenderer = gGLManager.getRawGLString();
- std::string renderer = rawRenderer;
- for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i)
- {
- *i = tolower(*i);
- }
-
-#if LL_EXPORT_GPU_TABLE
- llofstream json;
- json.open("gpu_table.json");
-
- json << "var gpu_table = [" << std::endl;
-#endif
-
- bool gpuFound;
- U32 lineNumber;
- for (gpuFound = false, lineNumber = 0; !gpuFound && !file.eof(); lineNumber++)
- {
- char buffer[MAX_STRING]; /*Flawfinder: ignore*/
- buffer[0] = 0;
-
- file.getline(buffer, MAX_STRING);
-
- if (strlen(buffer) >= 2 && /*Flawfinder: ignore*/
- buffer[0] == '/' &&
- buffer[1] == '/')
- {
- // This is a comment.
- continue;
- }
+ return parse_ok;
+}
- if (strlen(buffer) == 0) /*Flawfinder: ignore*/
- {
- // This is a blank line
- continue;
- }
+F32 gpu_benchmark();
- // setup the tokenizer
- std::string buf(buffer);
- std::string cls, label, expr, supported, stats_based, expected_gl_version;
- boost_tokenizer tokens(buf, boost::char_separator<char>("\t\n"));
- boost_tokenizer::iterator token_iter = tokens.begin();
+bool LLFeatureManager::loadGPUClass()
+{
+ //get memory bandwidth from benchmark
+ F32 gbps = gpu_benchmark();
- // grab the label, pseudo regular expression, and class
- if(token_iter != tokens.end())
- {
- label = *token_iter++;
- }
- if(token_iter != tokens.end())
- {
- expr = *token_iter++;
- }
- if(token_iter != tokens.end())
- {
- cls = *token_iter++;
- }
- if(token_iter != tokens.end())
+ if (gbps < 0.f)
+ { //couldn't bench, use GLVersion
+#if LL_DARWIN
+ //GLVersion is misleading on OSX, just default to class 3 if we can't bench
+ LL_WARNS() << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL;
+ mGPUClass = GPU_CLASS_3;
+#else
+ if (gGLManager.mGLVersion < 2.f)
{
- supported = *token_iter++;
+ mGPUClass = GPU_CLASS_0;
}
- if (token_iter != tokens.end())
+ else if (gGLManager.mGLVersion < 3.f)
{
- stats_based = *token_iter++;
+ mGPUClass = GPU_CLASS_1;
}
- if (token_iter != tokens.end())
+ else if (gGLManager.mGLVersion < 3.3f)
{
- expected_gl_version = *token_iter++;
+ mGPUClass = GPU_CLASS_2;
}
-
- if (label.empty() || expr.empty() || cls.empty() || supported.empty())
+ else if (gGLManager.mGLVersion < 4.f)
{
- LL_WARNS("RenderInit") << "invald gpu_table.txt:" << lineNumber << ": '" << buffer << "'" << LL_ENDL;
- continue;
+ mGPUClass = GPU_CLASS_3;
}
-#if LL_EXPORT_GPU_TABLE
- json << "{'label' : '" << label << "',\n" <<
- "'regexp' : '" << expr << "',\n" <<
- "'class' : '" << cls << "',\n" <<
- "'supported' : '" << supported << "',\n" <<
- "'stats_based' : " << stats_based << ",\n" <<
- "'gl_version' : " << expected_gl_version << "\n},\n";
-#endif
-
- for (U32 i = 0; i < expr.length(); i++) /*Flawfinder: ignore*/
+ else
{
- expr[i] = tolower(expr[i]);
+ mGPUClass = GPU_CLASS_4;
}
-
- // run the regular expression against the renderer
- boost::regex re(expr.c_str());
- if(boost::regex_search(renderer, re))
- {
- // if we found it, stop!
-#if !LL_EXPORT_GPU_TABLE
- gpuFound = true;
#endif
- mGPUString = label;
- mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10);
- mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10);
- sscanf(expected_gl_version.c_str(), "%f", &mExpectedGLVersion);
- }
}
-#if LL_EXPORT_GPU_TABLE
- json << "];\n\n";
- json.close();
-#endif
- file.close();
-
- if ( gpuFound )
+ else if (gGLManager.mGLVersion <= 2.f)
{
- LL_INFOS("RenderInit") << "GPU '" << rawRenderer << "' recognized as '" << mGPUString << "'" << LL_ENDL;
- if (!mGPUSupported)
- {
- LL_INFOS("RenderInit") << "GPU '" << mGPUString << "' is not supported." << LL_ENDL;
- }
+ mGPUClass = GPU_CLASS_0;
}
- else
+ else if (gGLManager.mGLVersion <= 3.f)
+ {
+ mGPUClass = GPU_CLASS_1;
+ }
+ else if (gbps <= 5.f)
+ {
+ mGPUClass = GPU_CLASS_0;
+ }
+ else if (gbps <= 8.f)
+ {
+ mGPUClass = GPU_CLASS_1;
+ }
+ else if (gbps <= 16.f)
+ {
+ mGPUClass = GPU_CLASS_2;
+ }
+ else if (gbps <= 40.f)
+ {
+ mGPUClass = GPU_CLASS_3;
+ }
+ else if (gbps <= 80.f)
{
- LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL;
+ mGPUClass = GPU_CLASS_4;
+ }
+ else
+ {
+ mGPUClass = GPU_CLASS_5;
}
-#if LL_DARWIN // never go over "Mid" settings by default on OS X
- mGPUClass = llmin(mGPUClass, GPU_CLASS_2);
-#endif
+ // defaults
+ mGPUString = gGLManager.getRawGLString();
+ mGPUSupported = TRUE;
+
+ return true; // indicates that a gpu value was established
}
+
// responder saves table into file
class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
{
+ LOG_CLASS(LLHTTPFeatureTableResponder);
public:
LLHTTPFeatureTableResponder(std::string filename) :
@@ -517,15 +505,14 @@ public:
}
- virtual void completedRaw(U32 status, const std::string& reason,
- const LLChannelDescriptors& channels,
+ virtual void completedRaw(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
{
- if (isGoodStatus(status))
+ if (isGoodStatus())
{
// write to file
- llinfos << "writing feature table to " << mFilename << llendl;
+ LL_INFOS() << "writing feature table to " << mFilename << LL_ENDL;
S32 file_size = buffer->countAfter(channels.in(), NULL);
if (file_size > 0)
@@ -540,7 +527,18 @@ public:
out.close();
}
}
-
+ else
+ {
+ char body[1025];
+ body[1024] = '\0';
+ LLBufferStream istr(channels, buffer.get());
+ istr.get(body,1024);
+ if (strlen(body) > 0)
+ {
+ mContent["body"] = body;
+ }
+ LL_WARNS() << dumpResponse() << LL_ENDL;
+ }
}
private:
@@ -570,31 +568,16 @@ void fetch_feature_table(std::string table)
const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename);
- llinfos << "LLFeatureManager fetching " << url << " into " << path << llendl;
+ LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL;
LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path));
}
-void fetch_gpu_table(std::string table)
-{
- const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable");
-
- const std::string filename = llformat(table.c_str(), LLVersionInfo::getVersion().c_str());
-
- const std::string url = base + "/" + filename;
-
- const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename);
-
- llinfos << "LLFeatureManager fetching " << url << " into " << path << llendl;
-
- LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path));
-}
// fetch table(s) from a website (S3)
void LLFeatureManager::fetchHTTPTables()
{
fetch_feature_table(FEATURE_TABLE_VER_FILENAME);
- fetch_gpu_table(GPU_TABLE_VER_FILENAME);
}
@@ -618,11 +601,12 @@ void LLFeatureManager::init()
void LLFeatureManager::applyRecommendedSettings()
{
+ loadGPUClass();
// apply saved settings
// cap the level at 2 (high)
- S32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));
+ U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5));
- llinfos << "Applying Recommended Features" << llendl;
+ LL_INFOS() << "Applying Recommended Features" << LL_ENDL;
setGraphicsLevel(level, false);
gSavedSettings.setU32("RenderQualityPerformance", level);
@@ -668,7 +652,7 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first);
if(ctrl == NULL)
{
- llwarns << "AHHH! Control setting " << mIt->first << " does not exist!" << llendl;
+ LL_WARNS() << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL;
continue;
}
@@ -691,52 +675,38 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
}
else
{
- llwarns << "AHHH! Control variable is not a numeric type!" << llendl;
+ LL_WARNS() << "AHHH! Control variable is not a numeric type!" << LL_ENDL;
}
}
}
-void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures)
+void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures)
{
LLViewerShaderMgr::sSkipReload = true;
applyBaseMasks();
-
- switch (level)
+
+ // if we're passed an invalid level, default to "Low"
+ std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low");
+ if (features == "Low")
{
- case 0:
- if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
- { //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
- maskFeatures("LowFixedFunction");
- }
- else
- { //same as low, but with "Basic Shaders" enabled
- maskFeatures("Low");
- }
- break;
- case 1:
- maskFeatures("LowMid");
- break;
- case 2:
- maskFeatures("Mid");
- break;
- case 3:
- maskFeatures("MidHigh");
- break;
- case 4:
- maskFeatures("High");
- break;
- case 5:
- maskFeatures("HighUltra");
- break;
- case 6:
- maskFeatures("Ultra");
- break;
- default:
- maskFeatures("Low");
- break;
+#if LL_DARWIN
+ // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac
+ // systems which support them instead of falling back to fixed-function unnecessarily
+ // MAINT-2157
+ if (gGLManager.mGLVersion < 2.1f)
+#else
+ // only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
+ if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
+#endif
+ {
+ // same as Low, but with "Basic Shaders" disabled
+ features = "LowFixedFunction";
+ }
}
+ maskFeatures(features);
+
applyFeatures(skipFeatures);
LLViewerShaderMgr::sSkipReload = false;
@@ -838,6 +808,14 @@ void LLFeatureManager::applyBaseMasks()
maskFeatures("VRAMGT512");
}
+#if LL_DARWIN
+ const LLOSInfo& osInfo = LLAppViewer::instance()->getOSInfo();
+ if (osInfo.mMajorVer == 10 && osInfo.mMinorVer < 7)
+ {
+ maskFeatures("OSX_10_6_8");
+ }
+#endif
+
// now mask by gpu string
// Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces
std::string gpustr = mGPUString;
@@ -849,11 +827,11 @@ void LLFeatureManager::applyBaseMasks()
}
}
- //llinfos << "Masking features from gpu table match: " << gpustr << llendl;
+ //LL_INFOS() << "Masking features from gpu table match: " << gpustr << LL_ENDL;
maskFeatures(gpustr);
// now mask cpu type ones
- if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024)
+ if (gSysMemory.getPhysicalMemoryClamped() <= U32Megabytes(256))
{
maskFeatures("RAM256MB");
}