summaryrefslogtreecommitdiff
path: root/indra/newview/llfeaturemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfeaturemanager.cpp')
-rw-r--r--indra/newview/llfeaturemanager.cpp349
1 files changed, 248 insertions, 101 deletions
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index e6fcfb6d40..ca2ef5f5b8 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -2,38 +2,33 @@
* @file llfeaturemanager.cpp
* @brief LLFeatureManager class implementation
*
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- *
- * Copyright (c) 2003-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
+#include "llviewerprecompiledheaders.h"
+
#include <iostream>
#include <fstream>
-#include "llviewerprecompiledheaders.h"
-
#include <boost/regex.hpp>
#include "llfeaturemanager.h"
@@ -43,10 +38,14 @@
#include "llgl.h"
#include "llsecondlifeurls.h"
+#include "llappviewer.h"
+#include "llhttpclient.h"
+#include "llnotificationsutil.h"
#include "llviewercontrol.h"
#include "llworld.h"
#include "lldrawpoolterrain.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
+#include "llversioninfo.h"
#include "llwindow.h"
#include "llui.h"
#include "llcontrol.h"
@@ -57,75 +56,71 @@
#include "lldxhardware.h"
#endif
-//
-// externs
-//
-extern LLMemoryInfo gSysMemory;
-extern LLCPUInfo gSysCPU;
#if LL_DARWIN
const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt";
+const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_mac.%s.txt";
#elif LL_LINUX
const char FEATURE_TABLE_FILENAME[] = "featuretable_linux.txt";
+const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_linux.%s.txt";
#elif LL_SOLARIS
const char FEATURE_TABLE_FILENAME[] = "featuretable_solaris.txt";
+const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_solaris.%s.txt";
#else
-const char FEATURE_TABLE_FILENAME[] = "featuretable.txt";
+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";
-LLFeatureManager *gFeatureManagerp = NULL;
-
-LLFeatureInfo::LLFeatureInfo(const char *name, const BOOL available, const F32 level) : mValid(TRUE)
+LLFeatureInfo::LLFeatureInfo(const std::string& name, const BOOL available, const F32 level)
+ : mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level)
{
- mName = name;
- mAvailable = available;
- mRecommendedLevel = level;
}
-LLFeatureList::LLFeatureList(const char *name)
+LLFeatureList::LLFeatureList(const std::string& name)
+ : mName(name)
{
- mName = name;
}
LLFeatureList::~LLFeatureList()
{
}
-void LLFeatureList::addFeature(const char *name, const BOOL available, const F32 level)
+void LLFeatureList::addFeature(const std::string& name, const BOOL available, const F32 level)
{
if (mFeatures.count(name))
{
- llwarns << "LLFeatureList::Attempting to add preexisting feature " << name << llendl;
+ LL_WARNS("RenderInit") << "LLFeatureList::Attempting to add preexisting feature " << name << LL_ENDL;
}
LLFeatureInfo fi(name, available, level);
mFeatures[name] = fi;
}
-BOOL LLFeatureList::isFeatureAvailable(const char *name)
+BOOL LLFeatureList::isFeatureAvailable(const std::string& name)
{
if (mFeatures.count(name))
{
return mFeatures[name].mAvailable;
}
- llwarns << "Feature " << name << " not on feature list!" << llendl;
+ LL_WARNS("RenderInit") << "Feature " << name << " not on feature list!" << LL_ENDL;
// changing this to TRUE so you have to explicitly disable
// something for it to be disabled
return TRUE;
}
-F32 LLFeatureList::getRecommendedValue(const char *name)
+F32 LLFeatureList::getRecommendedValue(const std::string& name)
{
if (mFeatures.count(name) && isFeatureAvailable(name))
{
return mFeatures[name].mRecommendedLevel;
}
- llwarns << "Feature " << name << " not on feature list or not available!" << llendl;
+ LL_WARNS("RenderInit") << "Feature " << name << " not on feature list or not available!" << LL_ENDL;
return 0;
}
@@ -148,49 +143,49 @@ BOOL LLFeatureList::maskList(LLFeatureList &mask)
//
if (!mFeatures.count(mask_fi.mName))
{
- llwarns << "Feature " << mask_fi.mName << " in mask not in top level!" << llendl;
+ LL_WARNS("RenderInit") << "Feature " << mask_fi.mName << " in mask not in top level!" << LL_ENDL;
continue;
}
LLFeatureInfo &cur_fi = mFeatures[mask_fi.mName];
if (mask_fi.mAvailable && !cur_fi.mAvailable)
{
- llwarns << "Mask attempting to reenabling disabled feature, ignoring " << cur_fi.mName << llendl;
+ LL_WARNS("RenderInit") << "Mask attempting to reenabling disabled feature, ignoring " << cur_fi.mName << LL_ENDL;
continue;
}
cur_fi.mAvailable = mask_fi.mAvailable;
cur_fi.mRecommendedLevel = llmin(cur_fi.mRecommendedLevel, mask_fi.mRecommendedLevel);
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- llinfos << "Feature mask " << mask.mName
+ LL_DEBUGS("RenderInit") << "Feature mask " << mask.mName
<< " Feature " << mask_fi.mName
<< " Mask: " << mask_fi.mRecommendedLevel
- << " Now: " << cur_fi.mRecommendedLevel << llendl;
-#endif
+ << " Now: " << cur_fi.mRecommendedLevel << LL_ENDL;
}
-#if 0 && !LL_RELEASE_FOR_DOWNLOAD
- llinfos << "After applying mask " << mask.mName << llendl;
- dump();
-#endif
+ LL_DEBUGS("RenderInit") << "After applying mask " << mask.mName << std::endl;
+ // Will conditionally call dump only if the above message will be logged, thanks
+ // to it being wrapped by the LL_DEBUGS and LL_ENDL macros.
+ dump();
+ LL_CONT << LL_ENDL;
+
return TRUE;
}
void LLFeatureList::dump()
{
- llinfos << "Feature list: " << mName << llendl;
- llinfos << "--------------" << llendl;
+ LL_DEBUGS("RenderInit") << "Feature list: " << mName << LL_ENDL;
+ LL_DEBUGS("RenderInit") << "--------------" << LL_ENDL;
LLFeatureInfo fi;
feature_map_t::iterator feature_it;
for (feature_it = mFeatures.begin(); feature_it != mFeatures.end(); ++feature_it)
{
fi = feature_it->second;
- llinfos << fi.mName << "\t\t" << fi.mAvailable << ":" << fi.mRecommendedLevel << llendl;
+ LL_DEBUGS("RenderInit") << fi.mName << "\t\t" << fi.mAvailable << ":" << fi.mRecommendedLevel << LL_ENDL;
}
- llinfos << llendl;
+ LL_DEBUGS("RenderInit") << LL_ENDL;
}
-LLFeatureList *LLFeatureManager::findMask(const char *name)
+LLFeatureList *LLFeatureManager::findMask(const std::string& name)
{
if (mMaskList.count(name))
{
@@ -200,15 +195,15 @@ LLFeatureList *LLFeatureManager::findMask(const char *name)
return NULL;
}
-BOOL LLFeatureManager::maskFeatures(const char *name)
+BOOL LLFeatureManager::maskFeatures(const std::string& name)
{
LLFeatureList *maskp = findMask(name);
if (!maskp)
{
-// llwarns << "Unknown feature mask " << name << llendl;
+ LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL;
return FALSE;
}
- llinfos << "Applying Feature Mask: " << name << llendl;
+ LL_DEBUGS("RenderInit") << "Applying Feature Mask: " << name << LL_ENDL;
return maskList(*maskp);
}
@@ -222,62 +217,100 @@ BOOL LLFeatureManager::loadFeatureTables()
mSkippedFeatures.insert("RenderVBOEnable");
mSkippedFeatures.insert("RenderFogRatio");
- std::string data_path = gDirUtilp->getAppRODataDir();
+ // first table is install with app
+ std::string app_path = gDirUtilp->getAppRODataDir();
+ app_path += gDirUtilp->getDirDelimiter();
- data_path += gDirUtilp->getDirDelimiter();
+ std::string filename;
+ std::string http_filename;
+#if LL_WINDOWS
+ std::string os_string = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
+ if (os_string.find("Microsoft Windows XP") == 0)
+ {
+ filename = llformat(FEATURE_TABLE_FILENAME, "_xp");
+ http_filename = llformat(FEATURE_TABLE_VER_FILENAME, "_xp", LLVersionInfo::getVersion().c_str());
+ }
+ else
+ {
+ filename = llformat(FEATURE_TABLE_FILENAME, "");
+ http_filename = llformat(FEATURE_TABLE_VER_FILENAME, "", LLVersionInfo::getVersion().c_str());
+ }
+#else
+ filename = FEATURE_TABLE_FILENAME;
+ http_filename = llformat(FEATURE_TABLE_VER_FILENAME, LLVersionInfo::getVersion().c_str());
+#endif
- data_path += FEATURE_TABLE_FILENAME;
+ app_path += filename;
+
+ // second table is downloaded with HTTP
+ 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
+ {
+ path = app_path;
+ }
+
+
+ return parseFeatureTable(path);
+}
- char name[MAX_STRING+1]; /*Flawfinder: ignore*/
+
+BOOL LLFeatureManager::parseFeatureTable(std::string filename)
+{
+ llinfos << "Looking for feature table in " << filename << llendl;
llifstream file;
+ std::string name;
U32 version;
- file.open(data_path.c_str()); /*Flawfinder: ignore*/
+ file.open(filename); /*Flawfinder: ignore*/
if (!file)
{
- llwarns << "Unable to open feature table!" << llendl;
+ LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL;
return FALSE;
}
// Check file version
file >> name;
file >> version;
- if (strcmp(name, "version"))
+ if (name != "version")
{
- llwarns << data_path << " does not appear to be a valid feature table!" << llendl;
+ LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL;
return FALSE;
}
mTableVersion = version;
LLFeatureList *flp = NULL;
- while (!file.eof())
+ while (!file.eof() && file.good())
{
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
- name[0] = 0;
file >> name;
- if (strlen(name) >= 2 && /*Flawfinder: ignore*/
- name[0] == '/' &&
- name[1] == '/')
+ if (name.substr(0,2) == "//")
{
// This is a comment.
file.getline(buffer, MAX_STRING);
continue;
}
- if (strlen(name) == 0) /*Flawfinder: ignore*/
+ if (name.empty())
{
// This is a blank line
file.getline(buffer, MAX_STRING);
continue;
}
- if (!strcmp(name, "list"))
+ if (name == "list")
{
if (flp)
{
@@ -287,7 +320,7 @@ BOOL LLFeatureManager::loadFeatureTables()
file >> name;
if (mMaskList.count(name))
{
- llerrs << "Overriding mask " << name << ", this is invalid!" << llendl;
+ LL_ERRS("RenderInit") << "Overriding mask " << name << ", this is invalid!" << LL_ENDL;
}
flp = new LLFeatureList(name);
@@ -297,7 +330,8 @@ BOOL LLFeatureManager::loadFeatureTables()
{
if (!flp)
{
- llerrs << "Specified parameter before <list> keyword!" << llendl;
+ LL_ERRS("RenderInit") << "Specified parameter before <list> keyword!" << LL_ENDL;
+ return FALSE;
}
S32 available;
F32 recommended;
@@ -312,24 +346,44 @@ BOOL LLFeatureManager::loadFeatureTables()
void LLFeatureManager::loadGPUClass()
{
- std::string data_path = gDirUtilp->getAppRODataDir();
-
- data_path += gDirUtilp->getDirDelimiter();
-
- data_path += GPU_TABLE_FILENAME;
-
// 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
+ {
+ path = app_path;
+ }
+
+ parseGPUTable(path);
+}
+
+
+void LLFeatureManager::parseGPUTable(std::string filename)
+{
llifstream file;
- file.open(data_path.c_str()); /*Flawfinder: ignore*/
+ file.open(filename);
if (!file)
{
- llwarns << "Unable to open GPU table: " << data_path << "!" << llendl;
+ LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL;
return;
}
@@ -400,7 +454,7 @@ void LLFeatureManager::loadGPUClass()
{
// if we found it, stop!
file.close();
- llinfos << "GPU is " << label << llendl;
+ LL_INFOS("RenderInit") << "GPU is " << label << llendl;
mGPUString = label;
mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10);
mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10);
@@ -410,9 +464,101 @@ void LLFeatureManager::loadGPUClass()
}
file.close();
- llwarns << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << llendl;
+ LL_WARNS("RenderInit") << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << LL_ENDL;
}
+// responder saves table into file
+class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
+{
+public:
+
+ LLHTTPFeatureTableResponder(std::string filename) :
+ mFilename(filename)
+ {
+ }
+
+
+ virtual void completedRaw(U32 status, const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ if (isGoodStatus(status))
+ {
+ // write to file
+
+ llinfos << "writing feature table to " << mFilename << llendl;
+
+ S32 file_size = buffer->countAfter(channels.in(), NULL);
+ if (file_size > 0)
+ {
+ // read from buffer
+ U8* copy_buffer = new U8[file_size];
+ buffer->readAfter(channels.in(), NULL, copy_buffer, file_size);
+
+ // write to file
+ LLAPRFile out(mFilename, LL_APR_WB);
+ out.write(copy_buffer, file_size);
+ out.close();
+ }
+ }
+
+ }
+
+private:
+ std::string mFilename;
+};
+
+void fetch_feature_table(std::string table)
+{
+ const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable");
+
+#if LL_WINDOWS
+ std::string os_string = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
+ std::string filename;
+ if (os_string.find("Microsoft Windows XP") == 0)
+ {
+ filename = llformat(table.c_str(), "_xp", LLVersionInfo::getVersion().c_str());
+ }
+ else
+ {
+ filename = llformat(table.c_str(), "", LLVersionInfo::getVersion().c_str());
+ }
+#else
+ const std::string filename = llformat(table.c_str(), LLVersionInfo::getVersion().c_str());
+#endif
+
+ 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));
+}
+
+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);
+}
+
+
void LLFeatureManager::cleanupFeatureTables()
{
std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer());
@@ -441,7 +587,6 @@ void LLFeatureManager::applyRecommendedSettings()
setGraphicsLevel(level, false);
gSavedSettings.setU32("RenderQualityPerformance", level);
- gSavedSettings.setBOOL("RenderCustomSettings", FALSE);
// now apply the tweaks to draw distance
// these are double negatives, because feature masks only work by
@@ -455,8 +600,6 @@ void LLFeatureManager::applyRecommendedSettings()
{
gSavedSettings.setF32("RenderFarClip", 128.0f);
}
-
-
}
void LLFeatureManager::applyFeatures(bool skipFeatures)
@@ -493,19 +636,19 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
// handle all the different types
if(ctrl->isType(TYPE_BOOLEAN))
{
- gSavedSettings.setBOOL(mIt->first, (BOOL)getRecommendedValue(mIt->first.c_str()));
+ gSavedSettings.setBOOL(mIt->first, (BOOL)getRecommendedValue(mIt->first));
}
else if (ctrl->isType(TYPE_S32))
{
- gSavedSettings.setS32(mIt->first, (S32)getRecommendedValue(mIt->first.c_str()));
+ gSavedSettings.setS32(mIt->first, (S32)getRecommendedValue(mIt->first));
}
else if (ctrl->isType(TYPE_U32))
{
- gSavedSettings.setU32(mIt->first, (U32)getRecommendedValue(mIt->first.c_str()));
+ gSavedSettings.setU32(mIt->first, (U32)getRecommendedValue(mIt->first));
}
else if (ctrl->isType(TYPE_F32))
{
- gSavedSettings.setF32(mIt->first, (F32)getRecommendedValue(mIt->first.c_str()));
+ gSavedSettings.setF32(mIt->first, (F32)getRecommendedValue(mIt->first));
}
else
{
@@ -548,7 +691,7 @@ void LLFeatureManager::applyBaseMasks()
LLFeatureList* maskp = findMask("all");
if(maskp == NULL)
{
- llwarns << "AHH! No \"all\" in feature table!" << llendl;
+ LL_WARNS("RenderInit") << "AHH! No \"all\" in feature table!" << LL_ENDL;
return;
}
@@ -565,12 +708,12 @@ void LLFeatureManager::applyBaseMasks()
"Class3"
};
- llinfos << "Setting GPU Class to " << class_table[mGPUClass] << llendl;
+ LL_INFOS("RenderInit") << "Setting GPU Class to " << class_table[mGPUClass] << LL_ENDL;
maskFeatures(class_table[mGPUClass]);
}
else
{
- llinfos << "Setting GPU Class to Unknown" << llendl;
+ LL_INFOS("RenderInit") << "Setting GPU Class to Unknown" << LL_ENDL;
maskFeatures("Unknown");
}
@@ -595,6 +738,10 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("ATI");
}
+ if (gGLManager.mATIOldDriver)
+ {
+ maskFeatures("ATIOldDriver");
+ }
if (gGLManager.mIsGFFX)
{
maskFeatures("GeForceFX");
@@ -620,7 +767,7 @@ void LLFeatureManager::applyBaseMasks()
}
//llinfos << "Masking features from gpu table match: " << gpustr << llendl;
- maskFeatures(gpustr.c_str());
+ maskFeatures(gpustr);
// now mask cpu type ones
if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024)
@@ -630,9 +777,9 @@ void LLFeatureManager::applyBaseMasks()
#if LL_SOLARIS && defined(__sparc) // even low MHz SPARCs are fast
#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here?
- if (gSysCPU.getMhz() < 800)
+ if (gSysCPU.getMHz() < 800)
#else
- if (gSysCPU.getMhz() < 1100)
+ if (gSysCPU.getMHz() < 1100)
#endif
{
maskFeatures("CPUSlow");