blob: f6ee3c09aa7e9cb347d0aa5c9cbdc2b380e09ecd [file] [log] [blame]
[email protected]81f85b32010-10-08 18:03:211// Copyright (c) 2010 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 "chrome/gpu/gpu_info_collector.h"
13
14#include "base/string_number_conversions.h"
15#include "base/utf_string_conversions.h"
16
17namespace {
18
19// Traverses the IDxDiagContainer tree and populates a tree of DxDiagNode
20// structures that contains property name / value pairs and subtrees of DirectX
21// diagnostic information.
22void RecurseDiagnosticTree(DxDiagNode* output,
23 IDxDiagContainer* container) {
24 HRESULT hr;
25
26 VARIANT variant;
27 VariantInit(&variant);
28
29 DWORD prop_count;
30 hr = container->GetNumberOfProps(&prop_count);
31 if (SUCCEEDED(hr)) {
32 for (DWORD i = 0; i < prop_count; i++) {
33 WCHAR prop_name16[256];
34 hr = container->EnumPropNames(i, prop_name16, arraysize(prop_name16));
35 if (SUCCEEDED(hr)) {
36 std::string prop_name8 = WideToUTF8(prop_name16);
37
38 hr = container->GetProp(prop_name16, &variant);
39 if (SUCCEEDED(hr)) {
40 switch (variant.vt) {
41 case VT_UI4:
42 output->values[prop_name8] = base::UintToString(variant.ulVal);
43 break;
44 case VT_I4:
45 output->values[prop_name8] = base::IntToString(variant.lVal);
46 break;
47 case VT_BOOL:
48 output->values[prop_name8] = variant.boolVal ? "true" : "false";
49 break;
50 case VT_BSTR:
51 output->values[prop_name8] = WideToUTF8(variant.bstrVal);
52 break;
53 default:
54 break;
55 }
56
57 // Clear the variant (this is needed to free BSTR memory).
58 VariantClear(&variant);
59 }
60 }
61 }
62 }
63
64 DWORD child_count;
65 hr = container->GetNumberOfChildContainers(&child_count);
66 if (SUCCEEDED(hr)) {
67 for (DWORD i = 0; i < child_count; i++) {
68 WCHAR child_name16[256];
69 hr = container->EnumChildContainerNames(i,
70 child_name16,
71 arraysize(child_name16));
72 if (SUCCEEDED(hr)) {
73 std::string child_name8 = WideToUTF8(child_name16);
74 DxDiagNode* output_child =
75 &output->children[child_name8];
76
77 IDxDiagContainer* child_container = NULL;
78 hr = container->GetChildContainer(child_name16, &child_container);
79 if (SUCCEEDED(hr)) {
80 RecurseDiagnosticTree(output_child, child_container);
81
82 child_container->Release();
83 }
84 }
85 }
86 }
87}
88} // namespace anonymous
89
90namespace gpu_info_collector {
91
92bool GetDxDiagnostics(DxDiagNode* output) {
93 HRESULT hr;
94 bool success = false;
95
96 IDxDiagProvider* provider = NULL;
97 hr = CoCreateInstance(CLSID_DxDiagProvider,
98 NULL,
99 CLSCTX_INPROC_SERVER,
100 IID_IDxDiagProvider,
101 reinterpret_cast<void**>(&provider));
102 if (SUCCEEDED(hr)) {
103 DXDIAG_INIT_PARAMS params = { sizeof(params) };
104 params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
105 params.bAllowWHQLChecks = FALSE;
106 params.pReserved = NULL;
107
108 hr = provider->Initialize(&params);
109 if (SUCCEEDED(hr)) {
110 IDxDiagContainer* root = NULL;
111 hr = provider->GetRootContainer(&root);
112 if (SUCCEEDED(hr)) {
113 // Limit to the DisplayDevices subtree. The tree in its entirity is
114 // enormous and only this branch contains useful information.
115 IDxDiagContainer* display_devices = NULL;
116 hr = root->GetChildContainer(L"DxDiag_DisplayDevices",
117 &display_devices);
118 if (SUCCEEDED(hr)) {
119 RecurseDiagnosticTree(output, display_devices);
120 success = true;
121 display_devices->Release();
122 }
123
124 root->Release();
125 }
126 }
127 provider->Release();
128 }
129
130 return success;
131}
132} // namespace gpu_info_collector