00001
00032 #ifdef LL_WINDOWS
00033
00034
00035
00036 #include "linden_common.h"
00037
00038 #define INITGUID
00039 #include <dxdiag.h>
00040 #undef INITGUID
00041
00042 #include <boost/tokenizer.hpp>
00043
00044 #include "lldxhardware.h"
00045 #include "llerror.h"
00046
00047 #include "llstring.h"
00048 #include "llstl.h"
00049
00050 void (*gWriteDebug)(const char* msg) = NULL;
00051 LLDXHardware gDXHardware;
00052
00053
00054
00055
00056 #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
00057 #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
00058 #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
00059
00060 std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
00061 {
00062 HRESULT hr;
00063 VARIANT var;
00064 WCHAR wszPropValue[256];
00065
00066 VariantInit( &var );
00067 hr = containerp->GetProp(wszPropName, &var );
00068 if( SUCCEEDED(hr) )
00069 {
00070
00071 switch( var.vt )
00072 {
00073 case VT_UI4:
00074 swprintf( wszPropValue, L"%d", var.ulVal );
00075 break;
00076 case VT_I4:
00077 swprintf( wszPropValue, L"%d", var.lVal );
00078 break;
00079 case VT_BOOL:
00080 wcscpy( wszPropValue, (var.boolVal) ? L"true" : L"false" );
00081 break;
00082 case VT_BSTR:
00083 wcsncpy( wszPropValue, var.bstrVal, 255 );
00084 wszPropValue[255] = 0;
00085 break;
00086 }
00087 }
00088
00089 VariantClear( &var );
00090
00091 return utf16str_to_utf8str(wszPropValue);
00092 }
00093
00094
00095 LLVersion::LLVersion()
00096 {
00097 mValid = FALSE;
00098 S32 i;
00099 for (i = 0; i < 4; i++)
00100 {
00101 mFields[i] = 0;
00102 }
00103 }
00104
00105 BOOL LLVersion::set(const std::string &version_string)
00106 {
00107 S32 i;
00108 for (i = 0; i < 4; i++)
00109 {
00110 mFields[i] = 0;
00111 }
00112
00113 std::string str(version_string);
00114 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00115 boost::char_separator<char> sep(".", "", boost::keep_empty_tokens);
00116 tokenizer tokens(str, sep);
00117
00118 tokenizer::iterator iter = tokens.begin();
00119 S32 count = 0;
00120 for (;(iter != tokens.end()) && (count < 4);++iter)
00121 {
00122 mFields[count] = atoi(iter->c_str());
00123 count++;
00124 }
00125 if (count < 4)
00126 {
00127
00128 for (i = 0; i < 4; i++)
00129 {
00130 mFields[i] = 0;
00131 }
00132 mValid = FALSE;
00133 }
00134 else
00135 {
00136 mValid = TRUE;
00137 }
00138 return mValid;
00139 }
00140
00141 S32 LLVersion::getField(const S32 field_num)
00142 {
00143 if (!mValid)
00144 {
00145 return -1;
00146 }
00147 else
00148 {
00149 return mFields[field_num];
00150 }
00151 }
00152
00153 LLString LLDXDriverFile::dump()
00154 {
00155 if (gWriteDebug)
00156 {
00157 gWriteDebug("Filename:");
00158 gWriteDebug(mName.c_str());
00159 gWriteDebug("\n");
00160 gWriteDebug("Ver:");
00161 gWriteDebug(mVersionString.c_str());
00162 gWriteDebug("\n");
00163 gWriteDebug("Date:");
00164 gWriteDebug(mDateString.c_str());
00165 gWriteDebug("\n");
00166 }
00167 llinfos << mFilepath << llendl;
00168 llinfos << mName << llendl;
00169 llinfos << mVersionString << llendl;
00170 llinfos << mDateString << llendl;
00171
00172 return "";
00173 }
00174
00175 LLDXDevice::~LLDXDevice()
00176 {
00177 for_each(mDriverFiles.begin(), mDriverFiles.end(), DeletePairedPointer());
00178 }
00179
00180 std::string LLDXDevice::dump()
00181 {
00182 if (gWriteDebug)
00183 {
00184 gWriteDebug("StartDevice\n");
00185 gWriteDebug("DeviceName:");
00186 gWriteDebug(mName.c_str());
00187 gWriteDebug("\n");
00188 gWriteDebug("PCIString:");
00189 gWriteDebug(mPCIString.c_str());
00190 gWriteDebug("\n");
00191 }
00192 llinfos << llendl;
00193 llinfos << "DeviceName:" << mName << llendl;
00194 llinfos << "PCIString:" << mPCIString << llendl;
00195 llinfos << "Drivers" << llendl;
00196 llinfos << "-------" << llendl;
00197 for (driver_file_map_t::iterator iter = mDriverFiles.begin(),
00198 end = mDriverFiles.end();
00199 iter != end; iter++)
00200 {
00201 LLDXDriverFile *filep = iter->second;
00202 filep->dump();
00203 }
00204 if (gWriteDebug)
00205 {
00206 gWriteDebug("EndDevice\n");
00207 }
00208
00209 return "";
00210 }
00211
00212 LLDXDriverFile *LLDXDevice::findDriver(const std::string &driver)
00213 {
00214 for (driver_file_map_t::iterator iter = mDriverFiles.begin(),
00215 end = mDriverFiles.end();
00216 iter != end; iter++)
00217 {
00218 LLDXDriverFile *filep = iter->second;
00219 if (!utf8str_compare_insensitive(filep->mName,driver))
00220 {
00221 return filep;
00222 }
00223 }
00224
00225 return NULL;
00226 }
00227
00228 LLDXHardware::LLDXHardware()
00229 {
00230 mVRAM = 0;
00231 gWriteDebug = NULL;
00232 }
00233
00234 void LLDXHardware::cleanup()
00235 {
00236
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 BOOL LLDXHardware::getInfo(BOOL vram_only)
00291 {
00292 LLTimer hw_timer;
00293 BOOL ok = FALSE;
00294 HRESULT hr;
00295
00296 CoInitialize(NULL);
00297
00298 IDxDiagProvider *dx_diag_providerp = NULL;
00299 IDxDiagContainer *dx_diag_rootp = NULL;
00300 IDxDiagContainer *devices_containerp = NULL;
00301
00302 IDxDiagContainer *device_containerp = NULL;
00303 IDxDiagContainer *file_containerp = NULL;
00304 IDxDiagContainer *driver_containerp = NULL;
00305
00306
00307 LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL;
00308 hr = CoCreateInstance(CLSID_DxDiagProvider,
00309 NULL,
00310 CLSCTX_INPROC_SERVER,
00311 IID_IDxDiagProvider,
00312 (LPVOID*) &dx_diag_providerp);
00313
00314 if (FAILED(hr))
00315 {
00316 LL_WARNS("AppInit") << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL;
00317 gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n");
00318 goto LCleanup;
00319 }
00320 if (SUCCEEDED(hr))
00321 {
00322
00323
00324
00325
00326 DXDIAG_INIT_PARAMS dx_diag_init_params;
00327 ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS));
00328
00329 dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS);
00330 dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
00331 dx_diag_init_params.bAllowWHQLChecks = TRUE;
00332 dx_diag_init_params.pReserved = NULL;
00333
00334 LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL;
00335 hr = dx_diag_providerp->Initialize(&dx_diag_init_params);
00336 if(FAILED(hr))
00337 {
00338 goto LCleanup;
00339 }
00340
00341 LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL;
00342 hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp );
00343 if(FAILED(hr) || !dx_diag_rootp)
00344 {
00345 goto LCleanup;
00346 }
00347
00348 HRESULT hr;
00349
00350
00351 LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL;
00352 hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp);
00353 if(FAILED(hr) || !devices_containerp)
00354 {
00355 goto LCleanup;
00356 }
00357
00358
00359 LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL;
00360 hr = devices_containerp->GetChildContainer(L"0", &device_containerp);
00361 if(FAILED(hr) || !device_containerp)
00362 {
00363 goto LCleanup;
00364 }
00365
00366
00367 {
00368 std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish");
00369
00370
00371 SAFE_RELEASE(device_containerp);
00372
00373
00374 char *stopstring;
00375 mVRAM = strtol(ram_str.c_str(), &stopstring, 10);
00376 LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL;
00377 }
00378
00379 if (vram_only)
00380 {
00381 ok = TRUE;
00382 goto LCleanup;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 }
00518
00519
00520 ok = TRUE;
00521
00522 LCleanup:
00523 if (!ok)
00524 {
00525 LL_WARNS("AppInit") << "DX9 probe failed" << LL_ENDL;
00526 gWriteDebug("DX9 probe failed\n");
00527 }
00528
00529 SAFE_RELEASE(file_containerp);
00530 SAFE_RELEASE(driver_containerp);
00531 SAFE_RELEASE(device_containerp);
00532 SAFE_RELEASE(devices_containerp);
00533 SAFE_RELEASE(dx_diag_rootp);
00534 SAFE_RELEASE(dx_diag_providerp);
00535
00536 CoUninitialize();
00537
00538 return ok;
00539 }
00540
00541 LLSD LLDXHardware::getDisplayInfo()
00542 {
00543 LLTimer hw_timer;
00544 HRESULT hr;
00545 LLSD ret;
00546 CoInitialize(NULL);
00547
00548 IDxDiagProvider *dx_diag_providerp = NULL;
00549 IDxDiagContainer *dx_diag_rootp = NULL;
00550 IDxDiagContainer *devices_containerp = NULL;
00551 IDxDiagContainer *device_containerp = NULL;
00552 IDxDiagContainer *file_containerp = NULL;
00553 IDxDiagContainer *driver_containerp = NULL;
00554
00555
00556 llinfos << "CoCreateInstance IID_IDxDiagProvider" << llendl;
00557 hr = CoCreateInstance(CLSID_DxDiagProvider,
00558 NULL,
00559 CLSCTX_INPROC_SERVER,
00560 IID_IDxDiagProvider,
00561 (LPVOID*) &dx_diag_providerp);
00562
00563 if (FAILED(hr))
00564 {
00565 llwarns << "No DXDiag provider found! DirectX 9 not installed!" << llendl;
00566 gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n");
00567 goto LCleanup;
00568 }
00569 if (SUCCEEDED(hr))
00570 {
00571
00572
00573
00574
00575 DXDIAG_INIT_PARAMS dx_diag_init_params;
00576 ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS));
00577
00578 dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS);
00579 dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
00580 dx_diag_init_params.bAllowWHQLChecks = TRUE;
00581 dx_diag_init_params.pReserved = NULL;
00582
00583 llinfos << "dx_diag_providerp->Initialize" << llendl;
00584 hr = dx_diag_providerp->Initialize(&dx_diag_init_params);
00585 if(FAILED(hr))
00586 {
00587 goto LCleanup;
00588 }
00589
00590 llinfos << "dx_diag_providerp->GetRootContainer" << llendl;
00591 hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp );
00592 if(FAILED(hr) || !dx_diag_rootp)
00593 {
00594 goto LCleanup;
00595 }
00596
00597 HRESULT hr;
00598
00599
00600 llinfos << "dx_diag_rootp->GetChildContainer" << llendl;
00601 hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp);
00602 if(FAILED(hr) || !devices_containerp)
00603 {
00604 goto LCleanup;
00605 }
00606
00607
00608 llinfos << "devices_containerp->GetChildContainer" << llendl;
00609 hr = devices_containerp->GetChildContainer(L"0", &device_containerp);
00610 if(FAILED(hr) || !device_containerp)
00611 {
00612 goto LCleanup;
00613 }
00614
00615
00616 std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish");
00617
00618
00619
00620 char *stopstring;
00621 ret["VRAM"] = strtol(ram_str.c_str(), &stopstring, 10);
00622 std::string device_name = get_string(device_containerp, L"szDescription");
00623 ret["DeviceName"] = device_name;
00624 std::string device_driver= get_string(device_containerp, L"szDriverVersion");
00625 ret["DriverVersion"] = device_driver;
00626 }
00627 LCleanup:
00628 SAFE_RELEASE(file_containerp);
00629 SAFE_RELEASE(driver_containerp);
00630 SAFE_RELEASE(device_containerp);
00631 SAFE_RELEASE(devices_containerp);
00632 SAFE_RELEASE(dx_diag_rootp);
00633 SAFE_RELEASE(dx_diag_providerp);
00634
00635 CoUninitialize();
00636 return ret;
00637 }
00638
00639 void LLDXHardware::setWriteDebugFunc(void (*func)(const char*))
00640 {
00641 gWriteDebug = func;
00642 }
00643
00644 #endif