diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfeaturemanager.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 861 |
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 | // | ||
55 | extern LLMemoryInfo gSysMemory; | ||
56 | extern LLCPUInfo gSysCPU; | ||
57 | extern void write_debug(const char *str); | ||
58 | extern void write_debug(const std::string& str); | ||
59 | |||
60 | #if LL_DARWIN | ||
61 | const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; | ||
62 | #else | ||
63 | const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; | ||
64 | #endif | ||
65 | |||
66 | const char GPU_TABLE_FILENAME[] = "gpu_table.txt"; | ||
67 | |||
68 | LLFeatureManager *gFeatureManagerp = NULL; | ||
69 | |||
70 | LLFeatureInfo::LLFeatureInfo(const char *name, const BOOL available, const S32 level) : mValid(TRUE) | ||
71 | { | ||
72 | mName = name; | ||
73 | mAvailable = available; | ||
74 | mRecommendedLevel = level; | ||
75 | } | ||
76 | |||
77 | LLFeatureList::LLFeatureList(const char *name) | ||
78 | { | ||
79 | mName = name; | ||
80 | } | ||
81 | |||
82 | LLFeatureList::~LLFeatureList() | ||
83 | { | ||
84 | } | ||
85 | |||
86 | void 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 | |||
97 | BOOL 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 | |||
108 | S32 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 | |||
119 | BOOL 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 | |||
165 | void 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 | |||
180 | LLFeatureList *LLFeatureManager::findMask(const char *name) | ||
181 | { | ||
182 | if (mMaskList.count(name)) | ||
183 | { | ||
184 | return mMaskList[name]; | ||
185 | } | ||
186 | |||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | BOOL 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 | |||
202 | BOOL 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 | |||
303 | S32 LLFeatureManager::getGPUClass() | ||
304 | { | ||
305 | return mGPUClass; | ||
306 | } | ||
307 | |||
308 | S32 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 | |||
392 | void LLFeatureManager::cleanupFeatureTables() | ||
393 | { | ||
394 | std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer()); | ||
395 | mMaskList.clear(); | ||
396 | } | ||
397 | |||
398 | |||
399 | void 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 | |||
420 | void 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 | |||
485 | extern LLOSInfo gSysOS; | ||
486 | |||
487 | |||
488 | BOOL 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 | |||
525 | BOOL 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 | |||
784 | void 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 | } | ||