blob: 43562b097250eb3d8421982eb080b42e7ac86481 [file] [log] [blame]
[email protected]623c0bd2011-03-12 01:00:411// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]81f85b32010-10-08 18:03:212// 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
Avi Drissman6fc2408c2018-12-25 21:29:0812#include "base/stl_util.h"
[email protected]f4390962013-06-11 07:29:2213#include "base/strings/string_number_conversions.h"
[email protected]906265872013-06-07 22:40:4514#include "base/strings/utf_string_conversions.h"
Robert Liao1214b5e2017-07-29 02:48:5815#include "base/win/com_init_util.h"
[email protected]d7b5cc72013-05-23 20:05:0016#include "gpu/config/gpu_info_collector.h"
[email protected]81f85b32010-10-08 18:03:2117
[email protected]d7b5cc72013-05-23 20:05:0018namespace gpu {
19
[email protected]81f85b32010-10-08 18:03:2120namespace {
21
22// Traverses the IDxDiagContainer tree and populates a tree of DxDiagNode
23// structures that contains property name / value pairs and subtrees of DirectX
24// diagnostic information.
[email protected]d7b5cc72013-05-23 20:05:0025void RecurseDiagnosticTree(DxDiagNode* output,
[email protected]206c5b02010-10-11 19:54:4426 IDxDiagContainer* container,
27 int depth) {
[email protected]81f85b32010-10-08 18:03:2128 HRESULT hr;
29
30 VARIANT variant;
31 VariantInit(&variant);
32
33 DWORD prop_count;
34 hr = container->GetNumberOfProps(&prop_count);
35 if (SUCCEEDED(hr)) {
36 for (DWORD i = 0; i < prop_count; i++) {
37 WCHAR prop_name16[256];
Avi Drissman6fc2408c2018-12-25 21:29:0838 hr = container->EnumPropNames(i, prop_name16, base::size(prop_name16));
[email protected]81f85b32010-10-08 18:03:2139 if (SUCCEEDED(hr)) {
[email protected]ad65a3e2013-12-25 18:18:0140 std::string prop_name8 = base::WideToUTF8(prop_name16);
[email protected]81f85b32010-10-08 18:03:2141
42 hr = container->GetProp(prop_name16, &variant);
43 if (SUCCEEDED(hr)) {
44 switch (variant.vt) {
45 case VT_UI4:
Raul Tambre36584542019-02-07 23:42:0846 output->values[prop_name8] = base::NumberToString(variant.ulVal);
[email protected]81f85b32010-10-08 18:03:2147 break;
48 case VT_I4:
Raul Tambre36584542019-02-07 23:42:0849 output->values[prop_name8] = base::NumberToString(variant.lVal);
[email protected]81f85b32010-10-08 18:03:2150 break;
51 case VT_BOOL:
52 output->values[prop_name8] = variant.boolVal ? "true" : "false";
53 break;
54 case VT_BSTR:
[email protected]ad65a3e2013-12-25 18:18:0155 output->values[prop_name8] = base::WideToUTF8(variant.bstrVal);
[email protected]81f85b32010-10-08 18:03:2156 break;
57 default:
58 break;
59 }
60
61 // Clear the variant (this is needed to free BSTR memory).
62 VariantClear(&variant);
63 }
64 }
65 }
66 }
67
[email protected]206c5b02010-10-11 19:54:4468 if (depth > 0) {
69 DWORD child_count;
70 hr = container->GetNumberOfChildContainers(&child_count);
71 if (SUCCEEDED(hr)) {
72 for (DWORD i = 0; i < child_count; i++) {
73 WCHAR child_name16[256];
Avi Drissman6fc2408c2018-12-25 21:29:0874 hr = container->EnumChildContainerNames(i, child_name16,
75 base::size(child_name16));
[email protected]81f85b32010-10-08 18:03:2176 if (SUCCEEDED(hr)) {
[email protected]ad65a3e2013-12-25 18:18:0177 std::string child_name8 = base::WideToUTF8(child_name16);
[email protected]d7b5cc72013-05-23 20:05:0078 DxDiagNode* output_child = &output->children[child_name8];
[email protected]81f85b32010-10-08 18:03:2179
tzikddef02182018-08-14 07:08:3380 IDxDiagContainer* child_container = nullptr;
[email protected]206c5b02010-10-11 19:54:4481 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 }
[email protected]81f85b32010-10-08 18:03:2187 }
88 }
89 }
90 }
91}
92} // namespace anonymous
93
[email protected]d7b5cc72013-05-23 20:05:0094bool GetDxDiagnostics(DxDiagNode* output) {
Robert Liao1214b5e2017-07-29 02:48:5895 // CLSID_DxDiagProvider is configured as an STA only object.
96 base::win::AssertComApartmentType(base::win::ComApartmentType::STA);
97
[email protected]81f85b32010-10-08 18:03:2198 HRESULT hr;
99 bool success = false;
tzikddef02182018-08-14 07:08:33100 IDxDiagProvider* provider = nullptr;
101 hr = CoCreateInstance(CLSID_DxDiagProvider, nullptr, CLSCTX_INPROC_SERVER,
Robert Liao1214b5e2017-07-29 02:48:58102 IID_IDxDiagProvider,
103 reinterpret_cast<void**>(&provider));
[email protected]81f85b32010-10-08 18:03:21104 if (SUCCEEDED(hr)) {
105 DXDIAG_INIT_PARAMS params = { sizeof(params) };
106 params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION;
107 params.bAllowWHQLChecks = FALSE;
tzikddef02182018-08-14 07:08:33108 params.pReserved = nullptr;
[email protected]81f85b32010-10-08 18:03:21109
110 hr = provider->Initialize(&params);
111 if (SUCCEEDED(hr)) {
tzikddef02182018-08-14 07:08:33112 IDxDiagContainer* root = nullptr;
[email protected]81f85b32010-10-08 18:03:21113 hr = provider->GetRootContainer(&root);
114 if (SUCCEEDED(hr)) {
115 // Limit to the DisplayDevices subtree. The tree in its entirity is
116 // enormous and only this branch contains useful information.
tzikddef02182018-08-14 07:08:33117 IDxDiagContainer* display_devices = nullptr;
[email protected]81f85b32010-10-08 18:03:21118 hr = root->GetChildContainer(L"DxDiag_DisplayDevices",
119 &display_devices);
120 if (SUCCEEDED(hr)) {
[email protected]206c5b02010-10-11 19:54:44121 RecurseDiagnosticTree(output, display_devices, 1);
[email protected]81f85b32010-10-08 18:03:21122 success = true;
123 display_devices->Release();
124 }
125
126 root->Release();
127 }
128 }
129 provider->Release();
130 }
131
132 return success;
133}
[email protected]d7b5cc72013-05-23 20:05:00134} // namespace gpu