1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // Functions to enumerate the Dx Diagnostic Tool hierarchy and build up 6 // a tree of nodes with name / value properties. 7 8 #define INITGUID 9 #include <dxdiag.h> 10 #include <windows.h> 11 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "base/win/scoped_com_initializer.h" 15 #include "gpu/config/gpu_info_collector.h" 16 17 namespace gpu { 18 19 namespace { 20 21 // Traverses the IDxDiagContainer tree and populates a tree of DxDiagNode 22 // structures that contains property name / value pairs and subtrees of DirectX 23 // diagnostic information. 24 void RecurseDiagnosticTree(DxDiagNode* output, 25 IDxDiagContainer* container, 26 int depth) { 27 HRESULT hr; 28 29 VARIANT variant; 30 VariantInit(&variant); 31 32 DWORD prop_count; 33 hr = container->GetNumberOfProps(&prop_count); 34 if (SUCCEEDED(hr)) { 35 for (DWORD i = 0; i < prop_count; i++) { 36 WCHAR prop_name16[256]; 37 hr = container->EnumPropNames(i, prop_name16, arraysize(prop_name16)); 38 if (SUCCEEDED(hr)) { 39 std::string prop_name8 = WideToUTF8(prop_name16); 40 41 hr = container->GetProp(prop_name16, &variant); 42 if (SUCCEEDED(hr)) { 43 switch (variant.vt) { 44 case VT_UI4: 45 output->values[prop_name8] = base::UintToString(variant.ulVal); 46 break; 47 case VT_I4: 48 output->values[prop_name8] = base::IntToString(variant.lVal); 49 break; 50 case VT_BOOL: 51 output->values[prop_name8] = variant.boolVal ? "true" : "false"; 52 break; 53 case VT_BSTR: 54 output->values[prop_name8] = WideToUTF8(variant.bstrVal); 55 break; 56 default: 57 break; 58 } 59 60 // Clear the variant (this is needed to free BSTR memory). 61 VariantClear(&variant); 62 } 63 } 64 } 65 } 66 67 if (depth > 0) { 68 DWORD child_count; 69 hr = container->GetNumberOfChildContainers(&child_count); 70 if (SUCCEEDED(hr)) { 71 for (DWORD i = 0; i < child_count; i++) { 72 WCHAR child_name16[256]; 73 hr = container->EnumChildContainerNames(i, 74 child_name16, 75 arraysize(child_name16)); 76 if (SUCCEEDED(hr)) { 77 std::string child_name8 = WideToUTF8(child_name16); 78 DxDiagNode* output_child = &output->children[child_name8]; 79 80 IDxDiagContainer* child_container = NULL; 81 hr = container->GetChildContainer(child_name16, &child_container); 82 if (SUCCEEDED(hr)) { 83 RecurseDiagnosticTree(output_child, child_container, depth - 1); 84 85 child_container->Release(); 86 } 87 } 88 } 89 } 90 } 91 } 92 } // namespace anonymous 93 94 bool GetDxDiagnostics(DxDiagNode* output) { 95 HRESULT hr; 96 bool success = false; 97 base::win::ScopedCOMInitializer com_initializer; 98 99 IDxDiagProvider* provider = NULL; 100 hr = CoCreateInstance(CLSID_DxDiagProvider, 101 NULL, 102 CLSCTX_INPROC_SERVER, 103 IID_IDxDiagProvider, 104 reinterpret_cast<void**>(&provider)); 105 if (SUCCEEDED(hr)) { 106 DXDIAG_INIT_PARAMS params = { sizeof(params) }; 107 params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; 108 params.bAllowWHQLChecks = FALSE; 109 params.pReserved = NULL; 110 111 hr = provider->Initialize(¶ms); 112 if (SUCCEEDED(hr)) { 113 IDxDiagContainer* root = NULL; 114 hr = provider->GetRootContainer(&root); 115 if (SUCCEEDED(hr)) { 116 // Limit to the DisplayDevices subtree. The tree in its entirity is 117 // enormous and only this branch contains useful information. 118 IDxDiagContainer* display_devices = NULL; 119 hr = root->GetChildContainer(L"DxDiag_DisplayDevices", 120 &display_devices); 121 if (SUCCEEDED(hr)) { 122 RecurseDiagnosticTree(output, display_devices, 1); 123 success = true; 124 display_devices->Release(); 125 } 126 127 root->Release(); 128 } 129 } 130 provider->Release(); 131 } 132 133 return success; 134 } 135 } // namespace gpu 136