aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfeaturemanager.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfeaturemanager.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llfeaturemanager.cpp861
1 files changed, 861 insertions, 0 deletions
diff --git a/linden/indra/newview/llfeaturemanager.cpp b/linden/indra/newview/llfeaturemanager.cpp
new file mode 100644
index 0000000..d3b0dbb
--- /dev/null
+++ b/linden/indra/newview/llfeaturemanager.cpp
@@ -0,0 +1,861 @@
1/**
2 * @file llfeaturemanager.cpp
3 * @brief LLFeatureManager class implementation
4 *
5 * Copyright (c) 2003-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include <iostream>
29#include <fstream>
30
31#include "llviewerprecompiledheaders.h"
32
33#include "llfeaturemanager.h"
34#include "lldir.h"
35
36#include "llsys.h"
37#include "llgl.h"
38#include "llsecondlifeurls.h"
39
40#include "llviewercontrol.h"
41#include "llworld.h"
42#include "pipeline.h"
43#include "lldrawpoolterrain.h"
44#include "llviewerimagelist.h"
45#include "llwindow.h"
46#include "llui.h"
47
48#if LL_WINDOWS
49#include "lldxhardware.h"
50#endif
51
52//
53// externs
54//
55extern LLMemoryInfo gSysMemory;
56extern LLCPUInfo gSysCPU;
57extern void write_debug(const char *str);
58extern void write_debug(const std::string& str);
59
60#if LL_DARWIN
61const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt";
62#else
63const char FEATURE_TABLE_FILENAME[] = "featuretable.txt";
64#endif
65
66const char GPU_TABLE_FILENAME[] = "gpu_table.txt";
67
68LLFeatureManager *gFeatureManagerp = NULL;
69
70LLFeatureInfo::LLFeatureInfo(const char *name, const BOOL available, const S32 level) : mValid(TRUE)
71{
72 mName = name;
73 mAvailable = available;
74 mRecommendedLevel = level;
75}
76
77LLFeatureList::LLFeatureList(const char *name)
78{
79 mName = name;
80}
81
82LLFeatureList::~LLFeatureList()
83{
84}
85
86void LLFeatureList::addFeature(const char *name, const BOOL available, const S32 level)
87{
88 if (mFeatures.count(name))
89 {
90 llwarns << "LLFeatureList::Attempting to add preexisting feature " << name << llendl;
91 }
92
93 LLFeatureInfo fi(name, available, level);
94 mFeatures[name] = fi;
95}
96
97BOOL LLFeatureList::isFeatureAvailable(const char *name)
98{
99 if (mFeatures.count(name))
100 {
101 return mFeatures[name].mAvailable;
102 }
103
104 llwarns << "Feature " << name << " not on feature list!" << llendl;
105 return FALSE;
106}
107
108S32 LLFeatureList::getRecommendedLevel(const char *name)
109{
110 if (mFeatures.count(name))
111 {
112 return mFeatures[name].mRecommendedLevel;
113 }
114
115 llwarns << "Feature " << name << " not on feature list!" << llendl;
116 return -1;
117}
118
119BOOL LLFeatureList::maskList(LLFeatureList &mask)
120{
121 //llinfos << "Masking with " << mask.mName << llendl;
122 //
123 // Lookup the specified feature mask, and overlay it on top of the
124 // current feature mask.
125 //
126
127 LLFeatureInfo mask_fi;
128
129 feature_map_t::iterator feature_it;
130 for (feature_it = mask.mFeatures.begin(); feature_it != mask.mFeatures.end(); ++feature_it)
131 {
132 mask_fi = feature_it->second;
133 //
134 // Look for the corresponding feature
135 //
136 if (!mFeatures.count(mask_fi.mName))
137 {
138 llwarns << "Feature " << mask_fi.mName << " in mask not in top level!" << llendl;
139 continue;
140 }
141
142 LLFeatureInfo &cur_fi = mFeatures[mask_fi.mName];
143 if (mask_fi.mAvailable && !cur_fi.mAvailable)
144 {
145 llwarns << "Mask attempting to reenabling disabled feature, ignoring " << cur_fi.mName << llendl;
146 continue;
147 }
148 cur_fi.mAvailable = mask_fi.mAvailable;
149 cur_fi.mRecommendedLevel = llmin(cur_fi.mRecommendedLevel, mask_fi.mRecommendedLevel);
150#ifndef LL_RELEASE_FOR_DOWNLOAD
151 llinfos << "Feature mask " << mask.mName
152 << " Feature " << mask_fi.mName
153 << " Mask: " << mask_fi.mRecommendedLevel
154 << " Now: " << cur_fi.mRecommendedLevel << llendl;
155#endif
156 }
157
158#if 0 && !LL_RELEASE_FOR_DOWNLOAD
159 llinfos << "After appling mask " << mask.mName << llendl;
160 dump();
161#endif
162 return TRUE;
163}
164
165void LLFeatureList::dump()
166{
167 llinfos << "Feature list: " << mName << llendl;
168 llinfos << "--------------" << llendl;
169
170 LLFeatureInfo fi;
171 feature_map_t::iterator feature_it;
172 for (feature_it = mFeatures.begin(); feature_it != mFeatures.end(); ++feature_it)
173 {
174 fi = feature_it->second;
175 llinfos << fi.mName << "\t\t" << fi.mAvailable << ":" << fi.mRecommendedLevel << llendl;
176 }
177 llinfos << llendl;
178}
179
180LLFeatureList *LLFeatureManager::findMask(const char *name)
181{
182 if (mMaskList.count(name))
183 {
184 return mMaskList[name];
185 }
186
187 return NULL;
188}
189
190BOOL LLFeatureManager::maskFeatures(const char *name)
191{
192 LLFeatureList *maskp = findMask(name);
193 if (!maskp)
194 {
195 llwarns << "Unknown feature mask " << name << llendl;
196 return FALSE;
197 }
198 llinfos << "Applying Feature Mask: " << name << llendl;
199 return maskList(*maskp);
200}
201
202BOOL LLFeatureManager::loadFeatureTables()
203{
204 std::string data_path = gDirUtilp->getAppRODataDir();
205
206 data_path += gDirUtilp->getDirDelimiter();
207
208 data_path += FEATURE_TABLE_FILENAME;
209
210
211 char name[MAX_STRING+1];
212
213 llifstream file;
214 U32 version;
215
216 file.open(data_path.c_str());
217
218 if (!file)
219 {
220 llwarns << "Unable to open feature table!" << llendl;
221 return FALSE;
222 }
223
224 // Check file version
225 file >> name;
226 file >> version;
227 if (strcmp(name, "version"))
228 {
229 llwarns << data_path << " does not appear to be a valid feature table!" << llendl;
230 return FALSE;
231 }
232
233 mTableVersion = version;
234
235 LLFeatureList *flp = NULL;
236 while (!file.eof())
237 {
238 char buffer[MAX_STRING];
239 name[0] = 0;
240
241 file >> name;
242
243 if (strlen(name) >= 2 &&
244 name[0] == '/' &&
245 name[1] == '/')
246 {
247 // This is a comment.
248 file.getline(buffer, MAX_STRING);
249 continue;
250 }
251
252 if (strlen(name) == 0)
253 {
254 // This is a blank line
255 file.getline(buffer, MAX_STRING);
256 continue;
257 }
258
259 if (!strcmp(name, "list"))
260 {
261 if (flp)
262 {
263 //flp->dump();
264 }
265 // It's a new mask, create it.
266 file >> name;
267 if (mMaskList.count(name))
268 {
269 llerrs << "Overriding mask " << name << ", this is invalid!" << llendl;
270 }
271
272 if (!flp)
273 {
274 //
275 // The first one is always the default
276 //
277 flp = this;
278 }
279 else
280 {
281 flp = new LLFeatureList(name);
282 mMaskList[name] = flp;
283 }
284
285 }
286 else
287 {
288 if (!flp)
289 {
290 llerrs << "Specified parameter before <list> keyword!" << llendl;
291 }
292 S32 available, recommended;
293 file >> available >> recommended;
294 flp->addFeature(name, available, recommended);
295 }
296 }
297 file.close();
298 //flp->dump();
299
300 return TRUE;
301}
302
303S32 LLFeatureManager::getGPUClass()
304{
305 return mGPUClass;
306}
307
308S32 LLFeatureManager::loadGPUClass()
309{
310 std::string data_path = gDirUtilp->getAppRODataDir();
311
312 data_path += gDirUtilp->getDirDelimiter();
313
314 data_path += GPU_TABLE_FILENAME;
315
316 llifstream file;
317
318 file.open(data_path.c_str());
319
320 if (!file)
321 {
322 llwarns << "Unable to open GPU table: " << data_path << "!" << llendl;
323 return 0;
324 }
325
326 std::string renderer = gGLManager.getRawGLString();
327 for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i)
328 {
329 *i = tolower(*i);
330 }
331
332 while (!file.eof())
333 {
334 char buffer[MAX_STRING];
335 buffer[0] = 0;
336
337 file.getline(buffer, MAX_STRING);
338
339 if (strlen(buffer) >= 2 &&
340 buffer[0] == '/' &&
341 buffer[1] == '/')
342 {
343 // This is a comment.
344 continue;
345 }
346
347 if (strlen(buffer) == 0)
348 {
349 // This is a blank line
350 continue;
351 }
352
353 char* cls, *label, *expr;
354
355 label = strtok(buffer, "\t");
356 expr = strtok(NULL, "\t");
357 cls = strtok(NULL, "\t");
358
359 if (label == NULL || expr == NULL || cls == NULL)
360 {
361 continue;
362 }
363
364 for (U32 i = 0; i < strlen(expr); i++)
365 {
366 expr[i] = tolower(expr[i]);
367 }
368
369 char* ex = strtok(expr, ".*");
370 char* rnd = (char*) renderer.c_str();
371
372 while (ex != NULL && rnd != NULL)
373 {
374 rnd = strstr(rnd, ex);
375 ex = strtok(NULL, ".*");
376 }
377
378 if (rnd != NULL)
379 {
380 file.close();
381 llinfos << "GPU is " << label << llendl;
382 return (S32) strtol(cls, NULL, 10);
383 }
384 }
385 file.close();
386 //flp->dump();
387
388 llwarns << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << llendl;
389 return 0;
390}
391
392void LLFeatureManager::cleanupFeatureTables()
393{
394 std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer());
395 mMaskList.clear();
396}
397
398
399void LLFeatureManager::initCPUFeatureMasks()
400{
401 if (gSysMemory.getPhysicalMemory() <= 256*1024*1024)
402 {
403 maskFeatures("RAM256MB");
404 }
405 else if (gSysMemory.getPhysicalMemory() <= 512*1024*1024)
406 {
407 //maskFeatures("RAM512MB");
408 }
409
410 if (gSysCPU.getMhz() < 1100)
411 {
412 maskFeatures("CPUSlow");
413 }
414 if (isSafe())
415 {
416 maskFeatures("safe");
417 }
418}
419
420void LLFeatureManager::initGraphicsFeatureMasks()
421{
422 mGPUClass = loadGPUClass();
423
424 if (mGPUClass >= 0 && mGPUClass < 4)
425 {
426 const char* class_table[] =
427 {
428 "Class0",
429 "Class1",
430 "Class2",
431 "Class3"
432 };
433
434 llinfos << "Setting GPU Class to " << class_table[mGPUClass] << llendl;
435 maskFeatures(class_table[mGPUClass]);
436 }
437
438 if (!gGLManager.mHasFragmentShader)
439 {
440 maskFeatures("NoPixelShaders");
441 }
442 if (!gGLManager.mHasVertexShader)
443 {
444 maskFeatures("NoVertexShaders");
445 }
446 if (gGLManager.mIsNVIDIA)
447 {
448 maskFeatures("NVIDIA");
449 }
450 if (gGLManager.mIsGF2or4MX)
451 {
452 maskFeatures("GeForce2");
453 }
454 if (gGLManager.mIsATI)
455 {
456 maskFeatures("ATI");
457 }
458 if (gGLManager.mIsRadeon8500)
459 {
460 maskFeatures("Radeon8500");
461 }
462 if (gGLManager.mIsRadeon9700)
463 {
464 maskFeatures("Radeon9700");
465 }
466 if (gGLManager.mIsGFFX)
467 {
468 maskFeatures("GeForceFX");
469 }
470 if (gGLManager.mIsIntel)
471 {
472 maskFeatures("Brookdale");
473 }
474
475 if (gGLManager.mIsMobilityRadeon9000)
476 {
477 maskFeatures("MobilityRadeon9000");
478 }
479 if (isSafe())
480 {
481 maskFeatures("safe");
482 }
483}
484
485extern LLOSInfo gSysOS;
486
487
488BOOL bad_hardware_dialog(const LLString &info_str, const LLString &url)
489{
490 if (!gSavedSettings.getWarning("AboutBadPCI"))
491 {
492 return FALSE;
493 }
494
495 // XUI:translate
496 std::string msg = llformat(
497 "[SECOND_LIFE] has detected that there may be a problem with.\n"
498 "hardware or drivers on your computer. Often resolving these\n"
499 "issues can result in enhanced stability and performance.\n"
500 " \n"
501 "%s\n"
502 " \n"
503 "Would you like to view a web page with more detailed\n"
504 "information on this problem?\n", info_str.c_str());
505
506 // Warn them that runnin without DirectX 9 will
507 // not allow us to tell them about driver issues
508 S32 button = OSMessageBox(msg.c_str(),
509 "Warning",
510 OSMB_YESNO);
511 if (OSBTN_YES== button)
512 {
513 llinfos << "User quitting after detecting bad drivers" << llendl;
514 spawn_web_browser(url.c_str());
515 return TRUE;
516 }
517 else
518 {
519 // Don't warn about bad PCI stuff again, they've clicked past it.
520 gSavedSettings.setWarning("AboutBadPCI", FALSE);
521 }
522 return FALSE;
523}
524
525BOOL LLFeatureManager::initPCIFeatureMasks()
526{
527#if LL_WINDOWS
528 BOOL exit_after_bad = FALSE;
529
530 BOOL is_2000 = FALSE;
531 BOOL is_xp = FALSE;
532
533 if (gSysOS.mMajorVer != 5)
534 {
535 // Unknown windows version number, exit!"
536 llwarns << "Unknown Windows major version " << gSysOS.mMajorVer << ", aborting detection!" << llendl;
537 return FALSE;
538 }
539 if (gSysOS.mMinorVer == 0)
540 {
541 is_2000 = TRUE;
542 }
543 else if (gSysOS.mMinorVer == 1)
544 {
545 is_xp = TRUE;
546 }
547 else
548 {
549 llwarns << "Unknown Windows minor version " << gSysOS.mMinorVer << ", aborting detection!" << llendl;
550 return FALSE;
551 }
552
553 // This only works on Win32, as it relies on DX9 hardware detection
554 // The PCI masks are actually the inverse of the normal masks
555 // We actually look through the masks,and see if any hardware matches it.
556 // This is because the masks encode logic about
557
558 // Check for the broken AMD AGP controllers (751, 761, 762)
559
560 // Horrible cruddy fixed lookup table.
561 // Figure out what OS we're on, the version numbers are different. Sigh...
562
563 LLDXDriverFile *dfilep = NULL;
564 LLDXDevice *devp = NULL;
565
566 // AMD(1022) AGP controllers
567 // 7007 AMD-751 AGP Controller
568 // 700F AMD-761 AGP Controller
569 // 700D AMD-762 AGP Controller
570 devp = gDXHardware.findDevice("VEN_1022", "DEV_7007|DEV_700F|DEV_700D");
571 if (devp)
572 {
573 // We're just pretty much screwed here, there are big problems with this hardware
574 // We've got trouble with the most recent nVidia drivers. Check for this and warn.
575
576 // Note: Need to detect that we're running with older nVidia hardware, probably
577 exit_after_bad |= bad_hardware_dialog("AMD AGP Controller",
578 AMD_AGP_URL);
579 }
580
581 // VIA(1106) AGP Controllers
582 // These need upgrading on both Win2K and WinXP
583 //
584 // 8305 VT8363/8365 CPU to AGP - Apollo KT133/KM133
585 // 8598 VT82C598MVP/694X CPU to AGP - Apollo MVP3/Pro133A
586 // 8605 VT8605 CPU to AGP - Apollo PM133
587 // B091 VT8633 CPU to AGP - Apollo Pro 266
588 // B099 VT8366/A/T CPU to AGP - Apollo KT266/A/333
589 // B168 VT8235 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X333 chipset
590 // B188 VT8237 CPU to AGP (AGP 2.0/3.0) - K8T800
591 // B198 VT8237 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X600 chipset
592
593 devp = gDXHardware.findDevice("VEN_1106",
594 "DEV_8305|DEV_8598|DEV_8605|DEV_B091|"
595 "DEV_B099|DEV_B168|DEV_B188|DEV_B198");
596 if (devp)
597 {
598 BOOL out_of_date = FALSE;
599 // Wanted driver: VIAAGP1.SYS
600 // Version Format: M.mm.0000.vvvv
601 // M.mm - Major/minor OS version (5.0 for Win2000, 5.1 for WinXP)
602 // vvvv - driver version number
603 //
604 // Notes:
605 // 3442 is most recent as of 2/25/04, probably want at least 3430 (seems to be a common version)
606
607 // These are DELIBERATE assignments inside if statements, blech.
608 if (dfilep = devp->findDriver("pci.sys"))
609 {
610 // Old driver: pci.sys
611 // Version: 5.01.2600.xxxx
612 //
613 // Notes:
614 // Default WinXP driver for B168, B198?
615
616 // Old driver: pci.sys
617 // Version: 5.01.2195.xxxx
618 //
619 // Notes:
620 // Default Win2K driver for 8305?
621
622 llwarns << "Detected pci.sys" << llendl;
623 write_debug("Old driver (pci.sys) for VIA detected!");
624 out_of_date = TRUE;
625 }
626 else if (dfilep = devp->findDriver("VIAAGP.SYS"))
627 {
628 // Old driver: VIAAGP.SYS
629 // Version: 5.01.2600.xxxx
630 //
631 // Notes:
632 // Default WinXP driver for B09x?
633
634 llwarns << "Detected VIAAGP.SYS" << llendl;
635 write_debug("Old driver (VIAAGP.SYS) for VIA detected!");
636 out_of_date = TRUE;
637 }
638 else if (dfilep = devp->findDriver("VIAAGP1.SYS"))
639 {
640 if (dfilep->mVersion.getField(3) < 3430)
641 {
642 // They're using a pretty old version of the VIA AGP drivers
643 // Maybe they want to upgrade?
644 llwarns << "Detected VIAAGP1.SYS" << llendl;
645 write_debug("Old driver (VIAAGP1.SYS) for VIA detected!");
646 out_of_date = TRUE;
647 }
648 }
649 if (out_of_date)
650 {
651 exit_after_bad |= bad_hardware_dialog("Out of date VIA AGP chipset driver",
652 VIA_URL);
653 }
654 }
655
656 // Intel(8086) AGP controllers (Win2K)
657 // These particular controllers only may need drivers on Win2K
658 //
659 // 1A31 82845[MP|MZ] Processor to AGP Controller
660 // 2532 82850/860 Processor to AGP Controller
661 if (is_2000)
662 {
663 devp = gDXHardware.findDevice("VEN_8086",
664 "DEV_1A31");
665 if (devp)
666 {
667 if (dfilep = devp->findDriver("pci.sys"))
668 {
669 // Old driver: pci.sys
670 // Version 5.01.21[9|6]5.xxxx
671 //
672 // Notes:
673 // Default driver for Win2K? Not sure what the "correct" driver is -
674 // maybe some variant of AGP440.SYS?
675 llwarns << "Detected pci.sys" << llendl;
676 write_debug("Old driver (pci.sys) for Intel 82845/850 on Win2K detected!");
677 exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver",
678 INTEL_CHIPSET_URL);
679 }
680 }
681 }
682
683 /* Removed 4/3/2006 by JC
684 After talking with Doug, we don't know what the proper driver
685 and/or version number should be for Intel 865. Regardless, this
686 code would _always_ complain if you had that chipset.
687
688 // Intel(8086) AGP controllers (All)
689 // These particular controllers may need drivers on both Win2K and WinXP
690 //
691 // 2561 82845G/GL/GE/PE/GV Processor to AGP Controller
692 // 2571 82865G/PE/P/GV/28248P Processor to AGP Controller
693 devp = gDXHardware.findDevice("VEN_8086",
694 "DEV_2571");
695 if (devp)
696 {
697 // Wanted driver: AGP440.SYS(?)
698 //
699 // Notes:
700 // Not sure, need to verify with an actual 82865/75 (Dell 8300?)
701
702 // Old driver: pci.sys
703 // Version 5.01.21[9|6]5.xxxx
704 //
705 // Notes:
706 // Default driver for Win2K? Not sure what the "correct" driver is -
707 // maybe some variant of AGP440.SYS?
708 exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver",
709 INTEL_CHIPSET_URL);
710 }
711 */
712
713
714 // SiS(1039) AGP controllers (All)
715 // These particular controllers may need drivers on both Win2K and WinXP
716 //
717 // 0001 SiS 530
718 // 0002 SiS SG86C202(???)
719 // 0003 SiS 648FX
720 devp = gDXHardware.findDevice("VEN_1039",
721 "DEV_0001|DEV_0002|DEV_0003");
722 if (devp)
723 {
724 BOOL out_of_date = FALSE;
725 // Wanted driver: SISAGPX.SYS
726 //
727 // Notes:
728 // Not sure, need to verify with an actual 82865/75 (Dell 8300?)
729
730 // Old driver: pci.sys
731 // Version 5.01.21[9|6]5.xxxx
732 //
733 // Notes:
734 // Default driver for Win2K? Not sure what the "correct" driver is -
735 // maybe some variant of AGP440.SYS?
736 if (dfilep = devp->findDriver("pci.sys"))
737 {
738 // Old driver: pci.sys
739 // Version 5.01.21[9|6]5.xxxx
740 //
741 llwarns << "Detected pci.sys" << llendl;
742 write_debug("Old driver (pci.sys) for SiS detected!");
743 out_of_date = TRUE;
744 }
745
746 if (dfilep = devp->findDriver("sisagp.sys"))
747 {
748 // Old driver: pci.sys
749 // Version 5.01.21[9|6]5.xxxx
750 //
751 llwarns << "Detected sisagp.sys" << llendl;
752 write_debug("Old driver (sisagp.sys) for SiS detected!");
753 out_of_date = TRUE;
754 }
755
756 if (dfilep = devp->findDriver("sisagpx.sys"))
757 {
758 // Old driver: pci.sys
759 // Version 7.02.0000.xxxx
760 //
761 // Notes:
762 // Default driver for Win2K? Not sure what the "correct" driver is -
763 // maybe some variant of AGP440.SYS?
764 if (dfilep->mVersion.getField(3) < 1160)
765 {
766 out_of_date = TRUE;
767 llwarns << "Detected sisagpx.sys" << llendl;
768 write_debug("Old driver (sisagpx.sys) for SiS detected!");
769 }
770 }
771 if (out_of_date)
772 {
773 exit_after_bad |= bad_hardware_dialog("Out of date SiS chipset driver",
774 SIS_CHIPSET_URL);
775 }
776 }
777
778 return exit_after_bad;
779#else
780 return TRUE;
781#endif
782}
783
784void LLFeatureManager::applyRecommendedFeatures()
785{
786 // see featuretable.txt
787
788 llinfos << "Applying Recommended Features" << llendl;
789#ifndef LL_RELEASE_FOR_DOWNLOAD
790 dump();
791#endif
792
793 // Enabling AGP
794 if (getRecommendedLevel("RenderAGP"))
795 {
796 gSavedSettings.setBOOL("RenderUseAGP", TRUE);
797 }
798 else
799 {
800 gSavedSettings.setBOOL("RenderUseAGP", FALSE);
801 }
802
803 // Anisotropic rendering
804 BOOL aniso = getRecommendedLevel("RenderAniso");
805 LLImageGL::sGlobalUseAnisotropic = aniso;
806 gSavedSettings.setBOOL("RenderAnisotropic", LLImageGL::sGlobalUseAnisotropic);
807
808 // Render Avatar Mode
809 BOOL avatar_vp = getRecommendedLevel("RenderAvatarVP");
810 S32 avatar_mode = getRecommendedLevel("RenderAvatarMode");
811 if (avatar_vp == FALSE)
812 avatar_mode = 0;
813 gSavedSettings.setBOOL("RenderAvatarVP", avatar_vp);
814 gSavedSettings.setS32("RenderAvatarMode", avatar_mode);
815
816 // Render Distance
817 S32 far_clip = getRecommendedLevel("RenderDistance");
818 gSavedSettings.setF32("RenderFarClip", (F32)far_clip);
819
820 // Lighting
821 S32 lighting = getRecommendedLevel("RenderLighting");
822 gSavedSettings.setS32("RenderLightingDetail", lighting);
823
824 // ObjectBump
825 BOOL bump = getRecommendedLevel("RenderObjectBump");
826 gSavedSettings.setBOOL("RenderObjectBump", bump);
827
828 // Particle Count
829 S32 max_parts = getRecommendedLevel("RenderParticleCount");
830 gSavedSettings.setS32("RenderMaxPartCount", max_parts);
831 LLViewerPartSim::setMaxPartCount(max_parts);
832
833 // RippleWater
834 BOOL ripple = getRecommendedLevel("RenderRippleWater");
835 gSavedSettings.setBOOL("RenderRippleWater", ripple);
836
837 // Vertex Shaders
838 S32 shaders = getRecommendedLevel("VertexShaderEnable");
839 gSavedSettings.setBOOL("VertexShaderEnable", shaders);
840
841 // Terrain
842 S32 terrain = getRecommendedLevel("RenderTerrainDetail");
843 gSavedSettings.setS32("RenderTerrainDetail", terrain);
844 LLDrawPoolTerrain::sDetailMode = terrain;
845
846 // Set the amount of VRAM we have available
847 if (isSafe())
848 {
849 gSavedSettings.setS32("GraphicsCardMemorySetting", 1); // 32 MB in 'safe' mode
850 }
851 else
852 {
853 S32 idx = gSavedSettings.getS32("GraphicsCardMemorySetting");
854 // -1 indicates use default (max), don't change
855 if (idx != -1)
856 {
857 idx = LLViewerImageList::getMaxVideoRamSetting(-2); // get max recommended setting
858 gSavedSettings.setS32("GraphicsCardMemorySetting", idx);
859 }
860 }
861}