15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions to enumerate the Dx Diagnostic Tool hierarchy and build up 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a tree of nodes with name / value properties. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INITGUID 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dxdiag.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_info_collector.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace gpu { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Traverses the IDxDiagContainer tree and populates a tree of DxDiagNode 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// structures that contains property name / value pairs and subtrees of DirectX 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// diagnostic information. 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void RecurseDiagnosticTree(DxDiagNode* output, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDxDiagContainer* container, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int depth) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VARIANT variant; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VariantInit(&variant); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD prop_count; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->GetNumberOfProps(&prop_count); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (DWORD i = 0; i < prop_count; i++) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR prop_name16[256]; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->EnumPropNames(i, prop_name16, arraysize(prop_name16)); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string prop_name8 = base::WideToUTF8(prop_name16); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->GetProp(prop_name16, &variant); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (variant.vt) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VT_UI4: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->values[prop_name8] = base::UintToString(variant.ulVal); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VT_I4: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->values[prop_name8] = base::IntToString(variant.lVal); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VT_BOOL: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->values[prop_name8] = variant.boolVal ? "true" : "false"; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VT_BSTR: 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output->values[prop_name8] = base::WideToUTF8(variant.bstrVal); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the variant (this is needed to free BSTR memory). 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VariantClear(&variant); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (depth > 0) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD child_count; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->GetNumberOfChildContainers(&child_count); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (DWORD i = 0; i < child_count; i++) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR child_name16[256]; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->EnumChildContainerNames(i, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_name16, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(child_name16)); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string child_name8 = base::WideToUTF8(child_name16); 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DxDiagNode* output_child = &output->children[child_name8]; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDxDiagContainer* child_container = NULL; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = container->GetChildContainer(child_name16, &child_container); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecurseDiagnosticTree(output_child, child_container, depth - 1); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_container->Release(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace anonymous 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool GetDxDiagnostics(DxDiagNode* output) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedCOMInitializer com_initializer; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDxDiagProvider* provider = NULL; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CoCreateInstance(CLSID_DxDiagProvider, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLSCTX_INPROC_SERVER, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IID_IDxDiagProvider, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>(&provider)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DXDIAG_INIT_PARAMS params = { sizeof(params) }; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.bAllowWHQLChecks = FALSE; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.pReserved = NULL; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = provider->Initialize(¶ms); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDxDiagContainer* root = NULL; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = provider->GetRootContainer(&root); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the DisplayDevices subtree. The tree in its entirity is 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enormous and only this branch contains useful information. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDxDiagContainer* display_devices = NULL; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = root->GetChildContainer(L"DxDiag_DisplayDevices", 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &display_devices); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecurseDiagnosticTree(output, display_devices, 1); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = true; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_devices->Release(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root->Release(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->Release(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace gpu 136