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(&params);
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