// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/config/gpu_info_collector.h"

// This has to be included before windows.h.
#include "third_party/re2/re2/re2.h"

#include <windows.h>
#include <cfgmgr32.h>
#include <d3d9.h>
#include <d3d11.h>
#include <dxgi.h>
#include <setupapi.h>

#include "base/command_line.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/scoped_native_library.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/worker_pool.h"
#include "base/trace_event/trace_event.h"
#include "base/win/registry.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "third_party/libxml/chromium/libxml_utils.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_egl.h"

namespace gpu {

namespace {

// This must be kept in sync with histograms.xml.
enum DisplayLinkInstallationStatus {
  DISPLAY_LINK_NOT_INSTALLED,
  DISPLAY_LINK_7_1_OR_EARLIER,
  DISPLAY_LINK_7_2_OR_LATER,
  DISPLAY_LINK_INSTALLATION_STATUS_MAX
};

float ReadXMLFloatValue(XmlReader* reader) {
  std::string score_string;
  if (!reader->ReadElementContent(&score_string))
    return 0.0;

  double score;
  if (!base::StringToDouble(score_string, &score))
    return 0.0;

  return static_cast<float>(score);
}

GpuPerformanceStats RetrieveGpuPerformanceStats() {
  TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats");

  // If the user re-runs the assessment without restarting, the COM API
  // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and
  // http://crbug.com/124325, read the assessment result files directly.
  GpuPerformanceStats stats;

  // Get path to WinSAT results files.
  wchar_t winsat_results_path[MAX_PATH];
  DWORD size = ExpandEnvironmentStrings(
      L"%WinDir%\\Performance\\WinSAT\\DataStore\\",
      winsat_results_path, MAX_PATH);
  if (size == 0 || size > MAX_PATH) {
    LOG(ERROR) << "The path to the WinSAT results is too long: "
               << size << " chars.";
    return stats;
  }

  // Find most recent formal assessment results.
  base::FileEnumerator file_enumerator(
      base::FilePath(winsat_results_path),
      false,  // not recursive
      base::FileEnumerator::FILES,
      FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml"));

  base::FilePath current_results;
  for (base::FilePath results = file_enumerator.Next(); !results.empty();
       results = file_enumerator.Next()) {
    // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx,
    // so the greatest file lexicographically is also the most recent file.
    if (base::FilePath::CompareLessIgnoreCase(current_results.value(),
                                              results.value()))
      current_results = results;
  }

  std::string current_results_string = current_results.MaybeAsASCII();
  if (current_results_string.empty())
    return stats;

  // Get relevant scores from results file. XML schema at:
  // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx
  XmlReader reader;
  if (!reader.LoadFile(current_results_string)) {
    LOG(ERROR) << "Could not open WinSAT results file.";
    return stats;
  }
  // Descend into <WinSAT> root element.
  if (!reader.SkipToElement() || !reader.Read()) {
    LOG(ERROR) << "Could not read WinSAT results file.";
    return stats;
  }

  // Search for <WinSPR> element containing the results.
  do {
    if (reader.NodeName() == "WinSPR")
      break;
  } while (reader.Next());
  // Descend into <WinSPR> element.
  if (!reader.Read()) {
    LOG(ERROR) << "Could not find WinSPR element in results file.";
    return stats;
  }

  // Read scores.
  for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) {
    std::string node_name = reader.NodeName();
    if (node_name == "SystemScore")
      stats.overall = ReadXMLFloatValue(&reader);
    else if (node_name == "GraphicsScore")
      stats.graphics = ReadXMLFloatValue(&reader);
    else if (node_name == "GamingScore")
      stats.gaming = ReadXMLFloatValue(&reader);
  }

  if (stats.overall == 0.0)
    LOG(ERROR) << "Could not read overall score from assessment results.";
  if (stats.graphics == 0.0)
    LOG(ERROR) << "Could not read graphics score from assessment results.";
  if (stats.gaming == 0.0)
    LOG(ERROR) << "Could not read gaming score from assessment results.";

  return stats;
}

GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() {
  base::TimeTicks start_time = base::TimeTicks::Now();

  GpuPerformanceStats stats = RetrieveGpuPerformanceStats();

  UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime",
                      base::TimeTicks::Now() - start_time);
  UMA_HISTOGRAM_CUSTOM_COUNTS(
      "GPU.WinSAT.OverallScore2",
      static_cast<base::HistogramBase::Sample>(stats.overall * 10), 10, 200,
      50);
  UMA_HISTOGRAM_CUSTOM_COUNTS(
      "GPU.WinSAT.GraphicsScore2",
      static_cast<base::HistogramBase::Sample>(stats.graphics * 10), 10, 200,
      50);
  UMA_HISTOGRAM_CUSTOM_COUNTS(
      "GPU.WinSAT.GamingScore2",
      static_cast<base::HistogramBase::Sample>(stats.gaming * 10), 10, 200, 50);
  UMA_HISTOGRAM_BOOLEAN(
      "GPU.WinSAT.HasResults",
      stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0);

  return stats;
}

// Returns the display link driver version or an invalid version if it is
// not installed.
Version DisplayLinkVersion() {
  base::win::RegKey key;

  if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
    return Version();

  if (key.OpenKey(L"DisplayLink", KEY_READ | KEY_WOW64_64KEY))
    return Version();

  if (key.OpenKey(L"Core", KEY_READ | KEY_WOW64_64KEY))
    return Version();

  base::string16 version;
  if (key.ReadValue(L"Version", &version))
    return Version();

  return Version(base::UTF16ToASCII(version));
}

// Returns whether Lenovo dCute is installed.
bool IsLenovoDCuteInstalled() {
  base::win::RegKey key;

  if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
    return false;

  if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))
    return false;

  if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))
    return false;

  return true;
}

// Determines whether D3D11 won't work, either because it is not supported on
// the machine or because it is known it is likely to crash.
bool D3D11ShouldWork(const GPUInfo& gpu_info) {
  // TODO(apatrick): This is a temporary change to see what impact disabling
  // D3D11 stats collection has on Canary.
#if 1
  return false;
#else
  // Windows XP never supports D3D11. It seems to be less stable that D3D9 on
  // Vista.
  if (base::win::GetVersion() <= base::win::VERSION_VISTA)
    return false;

  // http://crbug.com/175525.
  if (gpu_info.display_link_version.IsValid())
    return false;

  return true;
#endif
}

// Collects information about the level of D3D11 support and records it in
// the UMA stats. Records no stats when D3D11 in not supported at all.
void CollectD3D11SupportOnWorkerThread() {
  TRACE_EVENT0("gpu", "CollectD3D11Support");

  typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)(
      IDXGIAdapter* adapter,
      D3D_DRIVER_TYPE driver_type,
      HMODULE software,
      UINT flags,
      const D3D_FEATURE_LEVEL* feature_levels,
      UINT num_feature_levels,
      UINT sdk_version,
      ID3D11Device** device,
      D3D_FEATURE_LEVEL* feature_level,
      ID3D11DeviceContext** immediate_context);

  // This enumeration must be kept in sync with histograms.xml. Do not reorder
  // the members; always add to the end.
  enum FeatureLevel {
    FEATURE_LEVEL_UNKNOWN,
    FEATURE_LEVEL_NO_D3D11_DLL,
    FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT,
    FEATURE_LEVEL_DEVICE_CREATION_FAILED,
    FEATURE_LEVEL_9_1,
    FEATURE_LEVEL_9_2,
    FEATURE_LEVEL_9_3,
    FEATURE_LEVEL_10_0,
    FEATURE_LEVEL_10_1,
    FEATURE_LEVEL_11_0,
    NUM_FEATURE_LEVELS
  };

  FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN;
  UINT bgra_support = 0;

  // This module is leaked in case it is hooked by third party software.
  base::NativeLibrary d3d11_module = base::LoadNativeLibrary(
      base::FilePath(L"d3d11.dll"),
      NULL);

  if (!d3d11_module) {
    feature_level = FEATURE_LEVEL_NO_D3D11_DLL;
  } else {
    D3D11CreateDeviceFunc create_func =
        reinterpret_cast<D3D11CreateDeviceFunc>(
            base::GetFunctionPointerFromNativeLibrary(d3d11_module,
                                                      "D3D11CreateDevice"));
    if (!create_func) {
      feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT;
    } else {
      static const D3D_FEATURE_LEVEL d3d_feature_levels[] = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
      };

      base::win::ScopedComPtr<ID3D11Device> device;
      D3D_FEATURE_LEVEL d3d_feature_level;
      base::win::ScopedComPtr<ID3D11DeviceContext> device_context;
      HRESULT hr = create_func(NULL,
                               D3D_DRIVER_TYPE_HARDWARE,
                               NULL,
                               0,
                               d3d_feature_levels,
                               arraysize(d3d_feature_levels),
                               D3D11_SDK_VERSION,
                               device.Receive(),
                               &d3d_feature_level,
                               device_context.Receive());
      if (FAILED(hr)) {
        feature_level = FEATURE_LEVEL_DEVICE_CREATION_FAILED;
      } else {
        switch (d3d_feature_level) {
          case D3D_FEATURE_LEVEL_11_0:
            feature_level = FEATURE_LEVEL_11_0;
            break;
          case D3D_FEATURE_LEVEL_10_1:
            feature_level = FEATURE_LEVEL_10_1;
            break;
          case D3D_FEATURE_LEVEL_10_0:
            feature_level = FEATURE_LEVEL_10_0;
            break;
          case D3D_FEATURE_LEVEL_9_3:
            feature_level = FEATURE_LEVEL_9_3;
            break;
          case D3D_FEATURE_LEVEL_9_2:
            feature_level = FEATURE_LEVEL_9_2;
            break;
          case D3D_FEATURE_LEVEL_9_1:
            feature_level = FEATURE_LEVEL_9_1;
            break;
          default:
            NOTREACHED();
            break;
        }

        hr = device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM,
                                        &bgra_support);
        DCHECK(SUCCEEDED(hr));
      }
    }
  }

  UMA_HISTOGRAM_ENUMERATION("GPU.D3D11_FeatureLevel",
                            feature_level,
                            NUM_FEATURE_LEVELS);

  // ANGLE requires at least feature level 10.0. Do not record any further
  // stats if ANGLE would not work anyway.
  if (feature_level < FEATURE_LEVEL_10_0)
    return;

  UMA_HISTOGRAM_BOOLEAN(
      "GPU.D3D11_B8G8R8A8_Texture2DSupport",
      (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
  UMA_HISTOGRAM_BOOLEAN(
      "GPU.D3D11_B8G8R8A8_RenderTargetSupport",
      (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0);
}

// Collects information about the level of D3D11 support and records it in
// the UMA stats. Records no stats when D3D11 in not supported at all.
void CollectD3D11Support() {
  // D3D11 takes about 50ms to initialize so do this on a worker thread.
  base::WorkerPool::PostTask(
      FROM_HERE,
      base::Bind(CollectD3D11SupportOnWorkerThread),
      false);
}

void DeviceIDToVendorAndDevice(const std::wstring& id,
                               uint32* vendor_id,
                               uint32* device_id) {
  *vendor_id = 0;
  *device_id = 0;
  if (id.length() < 21)
    return;
  base::string16 vendor_id_string = id.substr(8, 4);
  base::string16 device_id_string = id.substr(17, 4);
  int vendor = 0;
  int device = 0;
  base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor);
  base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device);
  *vendor_id = vendor;
  *device_id = device;
}

}  // namespace anonymous

#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD)
// This function has a real implementation for official builds that can
// be found in src/third_party/amd.
void GetAMDVideocardInfo(GPUInfo* gpu_info);
#else
void GetAMDVideocardInfo(GPUInfo* gpu_info) {
  DCHECK(gpu_info);
  return;
}
#endif

CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id,
                                       GPUInfo* gpu_info) {
  TRACE_EVENT0("gpu", "CollectDriverInfoD3D");

  // Display adapter class GUID from
  // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
  GUID display_class = {0x4d36e968,
                        0xe325,
                        0x11ce,
                        {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};

  // create device info for the display device
  HDEVINFO device_info =
      SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT);
  if (device_info == INVALID_HANDLE_VALUE) {
    LOG(ERROR) << "Creating device info failed";
    return kCollectInfoNonFatalFailure;
  }

  struct GPUDriver {
    GPUInfo::GPUDevice device;
    std::string driver_vendor;
    std::string driver_version;
    std::string driver_date;
  };

  std::vector<GPUDriver> drivers;

  int primary_device = -1;
  bool found_amd = false;
  bool found_intel = false;

  DWORD index = 0;
  SP_DEVINFO_DATA device_info_data;
  device_info_data.cbSize = sizeof(device_info_data);
  while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
    WCHAR value[255];
    if (SetupDiGetDeviceRegistryPropertyW(device_info,
                                        &device_info_data,
                                        SPDRP_DRIVER,
                                        NULL,
                                        reinterpret_cast<PBYTE>(value),
                                        sizeof(value),
                                        NULL)) {
      HKEY key;
      std::wstring driver_key = L"System\\CurrentControlSet\\Control\\Class\\";
      driver_key += value;
      LONG result = RegOpenKeyExW(
          HKEY_LOCAL_MACHINE, driver_key.c_str(), 0, KEY_QUERY_VALUE, &key);
      if (result == ERROR_SUCCESS) {
        DWORD dwcb_data = sizeof(value);
        std::string driver_version;
        result = RegQueryValueExW(
            key, L"DriverVersion", NULL, NULL,
            reinterpret_cast<LPBYTE>(value), &dwcb_data);
        if (result == ERROR_SUCCESS)
          driver_version = base::UTF16ToASCII(std::wstring(value));

        std::string driver_date;
        dwcb_data = sizeof(value);
        result = RegQueryValueExW(
            key, L"DriverDate", NULL, NULL,
            reinterpret_cast<LPBYTE>(value), &dwcb_data);
        if (result == ERROR_SUCCESS)
          driver_date = base::UTF16ToASCII(std::wstring(value));

        std::string driver_vendor;
        dwcb_data = sizeof(value);
        result = RegQueryValueExW(
            key, L"ProviderName", NULL, NULL,
            reinterpret_cast<LPBYTE>(value), &dwcb_data);
        if (result == ERROR_SUCCESS)
          driver_vendor = base::UTF16ToASCII(std::wstring(value));

        wchar_t new_device_id[MAX_DEVICE_ID_LEN];
        CONFIGRET status = CM_Get_Device_ID(
            device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0);

        if (status == CR_SUCCESS) {
          GPUDriver driver;

          driver.driver_vendor = driver_vendor;
          driver.driver_version = driver_version;
          driver.driver_date = driver_date;
          std::wstring id = new_device_id;

          if (id.compare(0, device_id.size(), device_id) == 0)
            primary_device = drivers.size();

          uint32 vendor_id = 0, device_id = 0;
          DeviceIDToVendorAndDevice(id, &vendor_id, &device_id);
          driver.device.vendor_id = vendor_id;
          driver.device.device_id = device_id;
          drivers.push_back(driver);

          if (vendor_id == 0x8086)
            found_intel = true;
          if (vendor_id == 0x1002)
            found_amd = true;
        }

        RegCloseKey(key);
      }
    }
  }
  SetupDiDestroyDeviceInfoList(device_info);
  bool found = false;
  if (found_amd && found_intel) {
    // AMD Switchable system found.
    for (const auto& driver : drivers) {
      if (driver.device.vendor_id == 0x8086) {
        gpu_info->gpu = driver.device;
      }

      if (driver.device.vendor_id == 0x1002) {
        gpu_info->driver_vendor = driver.driver_vendor;
        gpu_info->driver_version = driver.driver_version;
        gpu_info->driver_date = driver.driver_date;
      }
    }
    GetAMDVideocardInfo(gpu_info);

    if (!gpu_info->amd_switchable) {
      // Some machines aren't properly detected as AMD switchable, but count
      // them anyway.
      gpu_info->amd_switchable = true;
      for (const auto& driver : drivers) {
        if (driver.device.vendor_id == 0x1002) {
          gpu_info->gpu = driver.device;
        } else {
          gpu_info->secondary_gpus.push_back(driver.device);
        }
      }
    }
    found = true;
  } else {
    for (size_t i = 0; i < drivers.size(); ++i) {
      const GPUDriver& driver = drivers[i];
      if (static_cast<int>(i) == primary_device) {
        found = true;
        gpu_info->gpu = driver.device;
        gpu_info->driver_vendor = driver.driver_vendor;
        gpu_info->driver_version = driver.driver_version;
        gpu_info->driver_date = driver.driver_date;
      } else {
        gpu_info->secondary_gpus.push_back(driver.device);
      }
    }
  }

  return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
}

CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
  TRACE_EVENT0("gpu", "CollectGraphicsInfo");

  DCHECK(gpu_info);

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
    std::string requested_implementation_name =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kUseGL);
    if (requested_implementation_name == "swiftshader") {
      gpu_info->software_rendering = true;
      gpu_info->context_info_state = kCollectInfoNonFatalFailure;
      return kCollectInfoNonFatalFailure;
    }
  }

  CollectInfoResult result = CollectGraphicsInfoGL(gpu_info);
  if (result != kCollectInfoSuccess) {
    gpu_info->context_info_state = result;
    return result;
  }

  // ANGLE's renderer strings are of the form:
  // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x)
  std::string direct3d_version;
  int vertex_shader_major_version = 0;
  int vertex_shader_minor_version = 0;
  int pixel_shader_major_version = 0;
  int pixel_shader_minor_version = 0;
  gpu_info->adapter_luid = 0;
  if (RE2::FullMatch(gpu_info->gl_renderer,
                     "ANGLE \\(.*\\)") &&
      RE2::PartialMatch(gpu_info->gl_renderer,
                        " Direct3D(\\w+)",
                        &direct3d_version) &&
      RE2::PartialMatch(gpu_info->gl_renderer,
                        " vs_(\\d+)_(\\d+)",
                        &vertex_shader_major_version,
                        &vertex_shader_minor_version) &&
      RE2::PartialMatch(gpu_info->gl_renderer,
                        " ps_(\\d+)_(\\d+)",
                        &pixel_shader_major_version,
                        &pixel_shader_minor_version)) {
    gpu_info->can_lose_context = direct3d_version == "9";
    gpu_info->vertex_shader_version =
        base::StringPrintf("%d.%d",
                           vertex_shader_major_version,
                           vertex_shader_minor_version);
    gpu_info->pixel_shader_version =
        base::StringPrintf("%d.%d",
                           pixel_shader_major_version,
                           pixel_shader_minor_version);

    // ANGLE's EGL vendor strings are of the form:
    // Google, Inc. (adapter LUID: 0123456789ABCDEF)
    // The LUID is optional and identifies the GPU adapter ANGLE is using.
    const char* egl_vendor = eglQueryString(
        gfx::GLSurfaceEGL::GetHardwareDisplay(),
        EGL_VENDOR);
    RE2::PartialMatch(egl_vendor,
                      " \\(adapter LUID: ([0-9A-Fa-f]{16})\\)",
                      RE2::Hex(&gpu_info->adapter_luid));

    // DirectX diagnostics are collected asynchronously because it takes a
    // couple of seconds.
  } else {
    gpu_info->dx_diagnostics_info_state = kCollectInfoNonFatalFailure;
  }

  gpu_info->context_info_state = kCollectInfoSuccess;
  return kCollectInfoSuccess;
}

CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
  DCHECK(vendor_id && device_id);
  *vendor_id = 0;
  *device_id = 0;

  // Taken from http://developer.nvidia.com/object/device_ids.html
  DISPLAY_DEVICE dd;
  dd.cb = sizeof(DISPLAY_DEVICE);
  std::wstring id;
  for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
    if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
      id = dd.DeviceID;
      break;
    }
  }

  if (id.length() > 20) {
    DeviceIDToVendorAndDevice(id, vendor_id, device_id);
    if (*vendor_id != 0 && *device_id != 0)
      return kCollectInfoSuccess;
  }
  return kCollectInfoNonFatalFailure;
}

CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
  TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");

  DCHECK(gpu_info);

  gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms();

  // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
  HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
  gpu_info->optimus = nvd3d9wrap != NULL;

  gpu_info->lenovo_dcute = IsLenovoDCuteInstalled();

  gpu_info->display_link_version = DisplayLinkVersion();

  if (!gpu_info->display_link_version .IsValid()) {
    UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
                              DISPLAY_LINK_NOT_INSTALLED,
                              DISPLAY_LINK_INSTALLATION_STATUS_MAX);
  } else if (gpu_info->display_link_version.IsOlderThan("7.2")) {
    UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
                              DISPLAY_LINK_7_1_OR_EARLIER,
                              DISPLAY_LINK_INSTALLATION_STATUS_MAX);
  } else {
    UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
                              DISPLAY_LINK_7_2_OR_LATER,
                              DISPLAY_LINK_INSTALLATION_STATUS_MAX);
  }

  // Taken from http://developer.nvidia.com/object/device_ids.html
  DISPLAY_DEVICE dd;
  dd.cb = sizeof(DISPLAY_DEVICE);
  std::wstring id;
  for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
    if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
      id = dd.DeviceID;
      break;
    }
  }

  if (id.length() <= 20) {
    gpu_info->basic_info_state = kCollectInfoNonFatalFailure;
    return kCollectInfoNonFatalFailure;
  }

  DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id,
                            &gpu_info->gpu.device_id);
  // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
  if (!CollectDriverInfoD3D(id, gpu_info)) {
    gpu_info->basic_info_state = kCollectInfoNonFatalFailure;
    return kCollectInfoNonFatalFailure;
  }

  // Collect basic information about supported D3D11 features. Delay for 45
  // seconds so as not to regress performance tests.
  if (D3D11ShouldWork(*gpu_info)) {
    // This is on a field trial so we can turn it off easily if it blows up
    // again in stable channel.
    scoped_refptr<base::FieldTrial> trial(
        base::FieldTrialList::FactoryGetFieldTrial(
            "D3D11Experiment", 100, "Disabled", 2015, 7, 8,
            base::FieldTrial::SESSION_RANDOMIZED, NULL));
    const int enabled_group =
        trial->AppendGroup("Enabled", 0);

    if (trial->group() == enabled_group) {
      base::MessageLoop::current()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&CollectD3D11Support),
          base::TimeDelta::FromSeconds(45));
    }
  }

  gpu_info->basic_info_state = kCollectInfoSuccess;
  return kCollectInfoSuccess;
}

CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
  TRACE_EVENT0("gpu", "CollectDriverInfoGL");

  if (!gpu_info->driver_version.empty())
    return kCollectInfoSuccess;

  bool parsed = RE2::PartialMatch(
      gpu_info->gl_version, "([\\d\\.]+)$", &gpu_info->driver_version);
  return parsed ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
}

void MergeGPUInfo(GPUInfo* basic_gpu_info,
                  const GPUInfo& context_gpu_info) {
  DCHECK(basic_gpu_info);

  if (context_gpu_info.software_rendering) {
    basic_gpu_info->software_rendering = true;
    return;
  }

  // Track D3D Shader Model (if available)
  const std::string& shader_version =
      context_gpu_info.vertex_shader_version;

  // Only gather if this is the first time we're seeing
  // a non-empty shader version string.
  if (!shader_version.empty() &&
      basic_gpu_info->vertex_shader_version.empty()) {

    // Note: do not reorder, used by UMA_HISTOGRAM below
    enum ShaderModel {
      SHADER_MODEL_UNKNOWN,
      SHADER_MODEL_2_0,
      SHADER_MODEL_3_0,
      SHADER_MODEL_4_0,
      SHADER_MODEL_4_1,
      SHADER_MODEL_5_0,
      NUM_SHADER_MODELS
    };

    ShaderModel shader_model = SHADER_MODEL_UNKNOWN;

    if (shader_version == "5.0") {
      shader_model = SHADER_MODEL_5_0;
    } else if (shader_version == "4.1") {
      shader_model = SHADER_MODEL_4_1;
    } else if (shader_version == "4.0") {
      shader_model = SHADER_MODEL_4_0;
    } else if (shader_version == "3.0") {
      shader_model = SHADER_MODEL_3_0;
    } else if (shader_version == "2.0") {
      shader_model = SHADER_MODEL_2_0;
    }

    UMA_HISTOGRAM_ENUMERATION("GPU.D3DShaderModel",
                              shader_model,
                              NUM_SHADER_MODELS);
  }

  MergeGPUInfoGL(basic_gpu_info, context_gpu_info);

  basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
}

}  // namespace gpu
