Home | History | Annotate | Download | only in config
      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 = base::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] = base::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 = base::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(&params);
    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