aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfeaturemanager.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llfeaturemanager.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llfeaturemanager.cpp348
1 files changed, 207 insertions, 141 deletions
diff --git a/linden/indra/newview/llfeaturemanager.cpp b/linden/indra/newview/llfeaturemanager.cpp
index 56e0469..f96b2db 100644
--- a/linden/indra/newview/llfeaturemanager.cpp
+++ b/linden/indra/newview/llfeaturemanager.cpp
@@ -34,6 +34,8 @@
34 34
35#include "llviewerprecompiledheaders.h" 35#include "llviewerprecompiledheaders.h"
36 36
37#include <boost/regex.hpp>
38
37#include "llfeaturemanager.h" 39#include "llfeaturemanager.h"
38#include "lldir.h" 40#include "lldir.h"
39 41
@@ -43,11 +45,13 @@
43 45
44#include "llviewercontrol.h" 46#include "llviewercontrol.h"
45#include "llworld.h" 47#include "llworld.h"
46#include "pipeline.h"
47#include "lldrawpoolterrain.h" 48#include "lldrawpoolterrain.h"
48#include "llviewerimagelist.h" 49#include "llviewerimagelist.h"
49#include "llwindow.h" 50#include "llwindow.h"
50#include "llui.h" 51#include "llui.h"
52#include "llcontrol.h"
53#include "llboost.h"
54#include "llweb.h"
51 55
52#if LL_WINDOWS 56#if LL_WINDOWS
53#include "lldxhardware.h" 57#include "lldxhardware.h"
@@ -73,7 +77,7 @@ const char GPU_TABLE_FILENAME[] = "gpu_table.txt";
73 77
74LLFeatureManager *gFeatureManagerp = NULL; 78LLFeatureManager *gFeatureManagerp = NULL;
75 79
76LLFeatureInfo::LLFeatureInfo(const char *name, const BOOL available, const S32 level) : mValid(TRUE) 80LLFeatureInfo::LLFeatureInfo(const char *name, const BOOL available, const F32 level) : mValid(TRUE)
77{ 81{
78 mName = name; 82 mName = name;
79 mAvailable = available; 83 mAvailable = available;
@@ -89,7 +93,7 @@ LLFeatureList::~LLFeatureList()
89{ 93{
90} 94}
91 95
92void LLFeatureList::addFeature(const char *name, const BOOL available, const S32 level) 96void LLFeatureList::addFeature(const char *name, const BOOL available, const F32 level)
93{ 97{
94 if (mFeatures.count(name)) 98 if (mFeatures.count(name))
95 { 99 {
@@ -108,18 +112,21 @@ BOOL LLFeatureList::isFeatureAvailable(const char *name)
108 } 112 }
109 113
110 llwarns << "Feature " << name << " not on feature list!" << llendl; 114 llwarns << "Feature " << name << " not on feature list!" << llendl;
111 return FALSE; 115
116 // changing this to TRUE so you have to explicitly disable
117 // something for it to be disabled
118 return TRUE;
112} 119}
113 120
114S32 LLFeatureList::getRecommendedLevel(const char *name) 121F32 LLFeatureList::getRecommendedValue(const char *name)
115{ 122{
116 if (mFeatures.count(name)) 123 if (mFeatures.count(name) && isFeatureAvailable(name))
117 { 124 {
118 return mFeatures[name].mRecommendedLevel; 125 return mFeatures[name].mRecommendedLevel;
119 } 126 }
120 127
121 llwarns << "Feature " << name << " not on feature list!" << llendl; 128 llwarns << "Feature " << name << " not on feature list or not available!" << llendl;
122 return -1; 129 return 0;
123} 130}
124 131
125BOOL LLFeatureList::maskList(LLFeatureList &mask) 132BOOL LLFeatureList::maskList(LLFeatureList &mask)
@@ -207,6 +214,14 @@ BOOL LLFeatureManager::maskFeatures(const char *name)
207 214
208BOOL LLFeatureManager::loadFeatureTables() 215BOOL LLFeatureManager::loadFeatureTables()
209{ 216{
217 // *TODO - if I or anyone else adds something else to the skipped list
218 // make this data driven. Put it in the feature table and parse it
219 // correctly
220 mSkippedFeatures.insert("RenderAnisotropic");
221 mSkippedFeatures.insert("RenderGamma");
222 mSkippedFeatures.insert("RenderVBOEnable");
223 mSkippedFeatures.insert("RenderFogRatio");
224
210 std::string data_path = gDirUtilp->getAppRODataDir(); 225 std::string data_path = gDirUtilp->getAppRODataDir();
211 226
212 data_path += gDirUtilp->getDirDelimiter(); 227 data_path += gDirUtilp->getDirDelimiter();
@@ -275,19 +290,8 @@ BOOL LLFeatureManager::loadFeatureTables()
275 llerrs << "Overriding mask " << name << ", this is invalid!" << llendl; 290 llerrs << "Overriding mask " << name << ", this is invalid!" << llendl;
276 } 291 }
277 292
278 if (!flp) 293 flp = new LLFeatureList(name);
279 { 294 mMaskList[name] = flp;
280 //
281 // The first one is always the default
282 //
283 flp = this;
284 }
285 else
286 {
287 flp = new LLFeatureList(name);
288 mMaskList[name] = flp;
289 }
290
291 } 295 }
292 else 296 else
293 { 297 {
@@ -295,7 +299,8 @@ BOOL LLFeatureManager::loadFeatureTables()
295 { 299 {
296 llerrs << "Specified parameter before <list> keyword!" << llendl; 300 llerrs << "Specified parameter before <list> keyword!" << llendl;
297 } 301 }
298 S32 available, recommended; 302 S32 available;
303 F32 recommended;
299 file >> available >> recommended; 304 file >> available >> recommended;
300 flp->addFeature(name, available, recommended); 305 flp->addFeature(name, available, recommended);
301 } 306 }
@@ -314,9 +319,10 @@ void LLFeatureManager::loadGPUClass()
314 data_path += GPU_TABLE_FILENAME; 319 data_path += GPU_TABLE_FILENAME;
315 320
316 // defaults 321 // defaults
317 mGPUClass = 0; 322 mGPUClass = GPU_CLASS_UNKNOWN;
318 mGPUString = gGLManager.getRawGLString(); 323 mGPUString = gGLManager.getRawGLString();
319 324 mGPUSupported = FALSE;
325
320 llifstream file; 326 llifstream file;
321 327
322 file.open(data_path.c_str()); /*Flawfinder: ignore*/ 328 file.open(data_path.c_str()); /*Flawfinder: ignore*/
@@ -354,41 +360,50 @@ void LLFeatureManager::loadGPUClass()
354 continue; 360 continue;
355 } 361 }
356 362
357 char* cls, *label, *expr; 363 // setup the tokenizer
358 364 std::string buf(buffer);
359 label = strtok(buffer, "\t"); 365 std::string cls, label, expr, supported;
360 expr = strtok(NULL, "\t"); 366 boost_tokenizer tokens(buf, boost::char_separator<char>("\t\n"));
361 cls = strtok(NULL, "\t"); 367 boost_tokenizer::iterator token_iter = tokens.begin();
362 368
363 if (label == NULL || expr == NULL || cls == NULL) 369 // grab the label, pseudo regular expression, and class
370 if(token_iter != tokens.end())
371 {
372 label = *token_iter++;
373 }
374 if(token_iter != tokens.end())
375 {
376 expr = *token_iter++;
377 }
378 if(token_iter != tokens.end())
379 {
380 cls = *token_iter++;
381 }
382 if(token_iter != tokens.end())
383 {
384 supported = *token_iter++;
385 }
386
387 if (label.empty() || expr.empty() || cls.empty() || supported.empty())
364 { 388 {
365 continue; 389 continue;
366 } 390 }
367 391
368 for (U32 i = 0; i < strlen(expr); i++) /*Flawfinder: ignore*/ 392 for (U32 i = 0; i < expr.length(); i++) /*Flawfinder: ignore*/
369 { 393 {
370 expr[i] = tolower(expr[i]); 394 expr[i] = tolower(expr[i]);
371 } 395 }
372
373 char* ex = strtok(expr, ".*");
374 char* rnd = (char*) renderer.c_str();
375 396
376 while (ex != NULL && rnd != NULL) 397 // run the regular expression against the renderer
377 { 398 boost::regex re(expr.c_str());
378 rnd = strstr(rnd, ex); 399 if(boost::regex_search(renderer, re))
379 if (rnd != NULL)
380 {
381 rnd += strlen(ex);
382 }
383 ex = strtok(NULL, ".*");
384 }
385
386 if (rnd != NULL)
387 { 400 {
401 // if we found it, stop!
388 file.close(); 402 file.close();
389 llinfos << "GPU is " << label << llendl; 403 llinfos << "GPU is " << label << llendl;
390 mGPUString = label; 404 mGPUString = label;
391 mGPUClass = (S32) strtol(cls, NULL, 10); 405 mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10);
406 mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10);
392 file.close(); 407 file.close();
393 return; 408 return;
394 } 409 }
@@ -404,33 +419,142 @@ void LLFeatureManager::cleanupFeatureTables()
404 mMaskList.clear(); 419 mMaskList.clear();
405} 420}
406 421
422void LLFeatureManager::init()
423{
424 // load the tables
425 loadFeatureTables();
426
427 // get the gpu class
428 loadGPUClass();
429
430 // apply the base masks, so we know if anything is disabled
431 applyBaseMasks();
432}
407 433
408void LLFeatureManager::initCPUFeatureMasks() 434void LLFeatureManager::applyRecommendedSettings()
409{ 435{
410 if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024) 436 // apply saved settings
437 // cap the level at 2 (high)
438 S32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_2));
439
440 llinfos << "Applying Recommended Features" << llendl;
441
442 setGraphicsLevel(level, false);
443 gSavedSettings.setU32("RenderQualityPerformance", level);
444 gSavedSettings.setBOOL("RenderCustomSettings", FALSE);
445
446 // now apply the tweaks to draw distance
447 // these are double negatives, because feature masks only work by
448 // downgrading values, so i needed to make a true value go to false
449 // for certain cards, thus the awkward name, "Disregard..."
450 if(!gSavedSettings.getBOOL("Disregard96DefaultDrawDistance"))
411 { 451 {
412 maskFeatures("RAM256MB"); 452 gSavedSettings.setF32("RenderFarClip", 96.0f);
413 } 453 }
414 454 else if(!gSavedSettings.getBOOL("Disregard128DefaultDrawDistance"))
415#if LL_SOLARIS && defined(__sparc) // even low MHz SPARCs are fast 455 {
416#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here? 456 gSavedSettings.setF32("RenderFarClip", 128.0f);
417 if (gSysCPU.getMhz() < 800) 457 }
418#else 458
419 if (gSysCPU.getMhz() < 1100) 459
460}
461
462void LLFeatureManager::applyFeatures(bool skipFeatures)
463{
464 // see featuretable.txt / featuretable_linux.txt / featuretable_mac.txt
465
466#ifndef LL_RELEASE_FOR_DOWNLOAD
467 dump();
420#endif 468#endif
469
470 // scroll through all of these and set their corresponding control value
471 for(feature_map_t::iterator mIt = mFeatures.begin();
472 mIt != mFeatures.end();
473 ++mIt)
421 { 474 {
422 maskFeatures("CPUSlow"); 475 // skip features you want to skip
476 // do this for when you don't want to change certain settings
477 if(skipFeatures)
478 {
479 if(mSkippedFeatures.find(mIt->first) != mSkippedFeatures.end())
480 {
481 continue;
482 }
483 }
484
485 // get the control setting
486 LLControlBase* ctrl = gSavedSettings.getControl(mIt->first);
487 if(ctrl == NULL)
488 {
489 llwarns << "AHHH! Control setting " << mIt->first << " does not exist!" << llendl;
490 continue;
491 }
492
493 // handle all the different types
494 if(ctrl->isType(TYPE_BOOLEAN))
495 {
496 gSavedSettings.setBOOL(mIt->first, (BOOL)getRecommendedValue(mIt->first.c_str()));
497 }
498 else if (ctrl->isType(TYPE_S32))
499 {
500 gSavedSettings.setS32(mIt->first, (S32)getRecommendedValue(mIt->first.c_str()));
501 }
502 else if (ctrl->isType(TYPE_U32))
503 {
504 gSavedSettings.setU32(mIt->first, (U32)getRecommendedValue(mIt->first.c_str()));
505 }
506 else if (ctrl->isType(TYPE_F32))
507 {
508 gSavedSettings.setF32(mIt->first, (F32)getRecommendedValue(mIt->first.c_str()));
509 }
510 else
511 {
512 llwarns << "AHHH! Control variable is not a numeric type!" << llendl;
513 }
423 } 514 }
424 if (isSafe()) 515}
516
517void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures)
518{
519 applyBaseMasks();
520
521 switch (level)
425 { 522 {
426 maskFeatures("safe"); 523 case 0:
524 maskFeatures("Low");
525 break;
526 case 1:
527 maskFeatures("Mid");
528 break;
529 case 2:
530 maskFeatures("High");
531 break;
532 case 3:
533 maskFeatures("Ultra");
534 break;
535 default:
536 maskFeatures("Low");
537 break;
427 } 538 }
539
540 applyFeatures(skipFeatures);
428} 541}
429 542
430void LLFeatureManager::initGraphicsFeatureMasks() 543void LLFeatureManager::applyBaseMasks()
431{ 544{
432 loadGPUClass(); 545 // reapply masks
433 546 mFeatures.clear();
547
548 LLFeatureList* maskp = findMask("all");
549 if(maskp == NULL)
550 {
551 llwarns << "AHH! No \"all\" in feature table!" << llendl;
552 return;
553 }
554
555 mFeatures = maskp->getFeatures();
556
557 // mask class
434 if (mGPUClass >= 0 && mGPUClass < 4) 558 if (mGPUClass >= 0 && mGPUClass < 4)
435 { 559 {
436 const char* class_table[] = 560 const char* class_table[] =
@@ -444,7 +568,13 @@ void LLFeatureManager::initGraphicsFeatureMasks()
444 llinfos << "Setting GPU Class to " << class_table[mGPUClass] << llendl; 568 llinfos << "Setting GPU Class to " << class_table[mGPUClass] << llendl;
445 maskFeatures(class_table[mGPUClass]); 569 maskFeatures(class_table[mGPUClass]);
446 } 570 }
447 571 else
572 {
573 llinfos << "Setting GPU Class to Unknown" << llendl;
574 maskFeatures("Unknown");
575 }
576
577 // now all those wacky ones
448 if (!gGLManager.mHasFragmentShader) 578 if (!gGLManager.mHasFragmentShader)
449 { 579 {
450 maskFeatures("NoPixelShaders"); 580 maskFeatures("NoPixelShaders");
@@ -477,6 +607,8 @@ void LLFeatureManager::initGraphicsFeatureMasks()
477 { 607 {
478 maskFeatures("OpenGLPre15"); 608 maskFeatures("OpenGLPre15");
479 } 609 }
610
611 // now mask by gpu string
480 // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces 612 // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces
481 std::string gpustr = mGPUString; 613 std::string gpustr = mGPUString;
482 for (std::string::iterator iter = gpustr.begin(); iter != gpustr.end(); ++iter) 614 for (std::string::iterator iter = gpustr.begin(); iter != gpustr.end(); ++iter)
@@ -486,94 +618,28 @@ void LLFeatureManager::initGraphicsFeatureMasks()
486 *iter = '_'; 618 *iter = '_';
487 } 619 }
488 } 620 }
489// llinfos << "Masking features from gpu table match: " << gpustr << llendl; 621
622 //llinfos << "Masking features from gpu table match: " << gpustr << llendl;
490 maskFeatures(gpustr.c_str()); 623 maskFeatures(gpustr.c_str());
491 624
492 if (isSafe()) 625 // now mask cpu type ones
626 if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024)
493 { 627 {
494 maskFeatures("safe"); 628 maskFeatures("RAM256MB");
495 } 629 }
496}
497
498void LLFeatureManager::applyRecommendedFeatures()
499{
500 // see featuretable.txt / featuretable_linux.txt / featuretable_mac.txt
501
502 llinfos << "Applying Recommended Features" << llendl;
503#ifndef LL_RELEASE_FOR_DOWNLOAD
504 dump();
505#endif
506 630
507 // Enabling VBO 631#if LL_SOLARIS && defined(__sparc) // even low MHz SPARCs are fast
508 if (getRecommendedLevel("RenderVBO")) 632#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here?
509 { 633 if (gSysCPU.getMhz() < 800)
510 gSavedSettings.setBOOL("RenderVBOEnable", TRUE); 634#else
511 } 635 if (gSysCPU.getMhz() < 1100)
512 else 636#endif
513 { 637 {
514 gSavedSettings.setBOOL("RenderVBOEnable", FALSE); 638 maskFeatures("CPUSlow");
515 } 639 }
516 640
517 // Anisotropic rendering
518 BOOL aniso = getRecommendedLevel("RenderAniso");
519 LLImageGL::sGlobalUseAnisotropic = aniso;
520 gSavedSettings.setBOOL("RenderAnisotropic", LLImageGL::sGlobalUseAnisotropic);
521
522 // Render Avatar Mode
523 BOOL avatar_vp = getRecommendedLevel("RenderAvatarVP");
524 S32 avatar_mode = getRecommendedLevel("RenderAvatarMode");
525 if (avatar_vp == FALSE)
526 avatar_mode = 0;
527 gSavedSettings.setBOOL("RenderAvatarVP", avatar_vp);
528 gSavedSettings.setS32("RenderAvatarMode", avatar_mode);
529
530 // Render Distance
531 S32 far_clip = getRecommendedLevel("RenderDistance");
532 gSavedSettings.setF32("RenderFarClip", (F32)far_clip);
533
534 // Lighting
535 S32 lighting = getRecommendedLevel("RenderLighting");
536 gSavedSettings.setS32("RenderLightingDetail", lighting);
537
538 // ObjectBump
539 BOOL bump = getRecommendedLevel("RenderObjectBump");
540 gSavedSettings.setBOOL("RenderObjectBump", bump);
541
542 // Particle Count
543 S32 max_parts = getRecommendedLevel("RenderParticleCount");
544 gSavedSettings.setS32("RenderMaxPartCount", max_parts);
545 LLViewerPartSim::setMaxPartCount(max_parts);
546
547 // RippleWater
548 BOOL ripple = getRecommendedLevel("RenderRippleWater");
549 gSavedSettings.setBOOL("RenderRippleWater", ripple);
550
551 // Occlusion Culling
552 BOOL occlusion = getRecommendedLevel("UseOcclusion");
553 gSavedSettings.setBOOL("UseOcclusion", occlusion);
554
555 // Vertex Shaders
556 S32 shaders = getRecommendedLevel("VertexShaderEnable");
557 gSavedSettings.setBOOL("VertexShaderEnable", shaders);
558
559 // Terrain
560 S32 terrain = getRecommendedLevel("RenderTerrainDetail");
561 gSavedSettings.setS32("RenderTerrainDetail", terrain);
562 LLDrawPoolTerrain::sDetailMode = terrain;
563
564 // Set the amount of VRAM we have available
565 if (isSafe()) 641 if (isSafe())
566 { 642 {
567 gSavedSettings.setS32("GraphicsCardMemorySetting", 1); // 32 MB in 'safe' mode 643 maskFeatures("safe");
568 }
569 else
570 {
571 S32 idx = gSavedSettings.getS32("GraphicsCardMemorySetting");
572 // -1 indicates use default (max), don't change
573 if (idx != -1)
574 {
575 idx = LLViewerImageList::getMaxVideoRamSetting(-2); // get max recommended setting
576 gSavedSettings.setS32("GraphicsCardMemorySetting", idx);
577 }
578 } 644 }
579} 645}