| Index: content/gpu/gpu_info_collector_win.cc
 | 
| ===================================================================
 | 
| --- content/gpu/gpu_info_collector_win.cc	(revision 173244)
 | 
| +++ content/gpu/gpu_info_collector_win.cc	(working copy)
 | 
| @@ -157,10 +157,15 @@
 | 
|    return stats;
 | 
|  }
 | 
|  
 | 
| -}  // namespace anonymous
 | 
| +// Advanced Micro Devices has interesting configurations on laptops were
 | 
| +// there are two videocards that can alternatively a given process output.
 | 
| +enum AMDVideoCardType {
 | 
| +  UNKNOWN,
 | 
| +  STANDALONE,
 | 
| +  INTEGRATED,
 | 
| +  SWITCHABLE
 | 
| +};
 | 
|  
 | 
| -namespace gpu_info_collector {
 | 
| -
 | 
|  #if !defined(GOOGLE_CHROME_BUILD)
 | 
|  AMDVideoCardType GetAMDVideocardType() {
 | 
|    return UNKNOWN;
 | 
| @@ -171,14 +176,95 @@
 | 
|  AMDVideoCardType GetAMDVideocardType();
 | 
|  #endif
 | 
|  
 | 
| -bool CollectGraphicsInfo(content::GPUInfo* gpu_info) {
 | 
| +bool CollectDriverInfoD3D(const std::wstring& device_id,
 | 
| +                          content::GPUInfo* gpu_info) {
 | 
| +  TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
 | 
| +
 | 
| +  // create device info for the display device
 | 
| +  HDEVINFO device_info = SetupDiGetClassDevsW(
 | 
| +      NULL, device_id.c_str(), NULL,
 | 
| +      DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
 | 
| +  if (device_info == INVALID_HANDLE_VALUE) {
 | 
| +    LOG(ERROR) << "Creating device info failed";
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  DWORD index = 0;
 | 
| +  bool found = false;
 | 
| +  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 = WideToASCII(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 = WideToASCII(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 = WideToASCII(std::wstring(value));
 | 
| +          if (driver_vendor == "Advanced Micro Devices, Inc." ||
 | 
| +              driver_vendor == "ATI Technologies Inc.") {
 | 
| +            // We are conservative and assume that in the absence of a clear
 | 
| +            // signal the videocard is assumed to be switchable. Additionally,
 | 
| +            // some switchable systems with Intel GPUs aren't correctly
 | 
| +            // detected, so always count them.
 | 
| +            AMDVideoCardType amd_card_type = GetAMDVideocardType();
 | 
| +            gpu_info->amd_switchable = (gpu_info->gpu.vendor_id == 0x8086) ||
 | 
| +                                       (amd_card_type != STANDALONE);
 | 
| +          }
 | 
| +        }
 | 
| +
 | 
| +        gpu_info->driver_vendor = driver_vendor;
 | 
| +        gpu_info->driver_version = driver_version;
 | 
| +        gpu_info->driver_date = driver_date;
 | 
| +        found = true;
 | 
| +        RegCloseKey(key);
 | 
| +        break;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  SetupDiDestroyDeviceInfoList(device_info);
 | 
| +  return found;
 | 
| +}
 | 
| +
 | 
| +}  // namespace anonymous
 | 
| +
 | 
| +namespace gpu_info_collector {
 | 
| +
 | 
| +bool CollectContextGraphicsInfo(content::GPUInfo* gpu_info) {
 | 
|    TRACE_EVENT0("gpu", "CollectGraphicsInfo");
 | 
|  
 | 
|    DCHECK(gpu_info);
 | 
| -  *gpu_info = content::GPUInfo();
 | 
|  
 | 
| -  gpu_info->performance_stats = RetrieveGpuPerformanceStats();
 | 
| -
 | 
|    if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
 | 
|      std::string requested_implementation_name =
 | 
|          CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
 | 
| @@ -215,36 +301,13 @@
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| -  if (!CollectGraphicsInfoD3D(d3d, gpu_info))
 | 
| -    return false;
 | 
| +  // Get can_lose_context
 | 
| +  base::win::ScopedComPtr<IDirect3D9Ex> d3dex;
 | 
| +  if (SUCCEEDED(d3dex.QueryFrom(d3d)))
 | 
| +    gpu_info->can_lose_context = false;
 | 
| +  else
 | 
| +    gpu_info->can_lose_context = true;
 | 
|  
 | 
| -  // DirectX diagnostics are collected asynchronously because it takes a
 | 
| -  // couple of seconds. Do not mark gpu_info as complete until that is done.
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -bool CollectPreliminaryGraphicsInfo(content::GPUInfo* gpu_info) {
 | 
| -  TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");
 | 
| -
 | 
| -  DCHECK(gpu_info);
 | 
| -
 | 
| -  bool rt = true;
 | 
| -  if (!CollectVideoCardInfo(gpu_info))
 | 
| -    rt = false;
 | 
| -
 | 
| -  gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms();
 | 
| -
 | 
| -  return rt;
 | 
| -}
 | 
| -
 | 
| -bool CollectGraphicsInfoD3D(IDirect3D9* d3d, content::GPUInfo* gpu_info) {
 | 
| -  TRACE_EVENT0("gpu", "CollectGraphicsInfoD3D");
 | 
| -
 | 
| -  DCHECK(d3d);
 | 
| -  DCHECK(gpu_info);
 | 
| -
 | 
| -  bool succeed = CollectVideoCardInfo(gpu_info);
 | 
| -
 | 
|    // Get version information
 | 
|    D3DCAPS9 d3d_caps;
 | 
|    if (d3d->GetDeviceCaps(D3DADAPTER_DEFAULT,
 | 
| @@ -256,24 +319,21 @@
 | 
|          VersionNumberToString(d3d_caps.VertexShaderVersion);
 | 
|    } else {
 | 
|      LOG(ERROR) << "d3d->GetDeviceCaps() failed";
 | 
| -    succeed = false;
 | 
| +    return false;
 | 
|    }
 | 
|  
 | 
| -  // Get can_lose_context
 | 
| -  base::win::ScopedComPtr<IDirect3D9Ex> d3dex;
 | 
| -  if (SUCCEEDED(d3dex.QueryFrom(d3d)))
 | 
| -    gpu_info->can_lose_context = false;
 | 
| -  else
 | 
| -    gpu_info->can_lose_context = true;
 | 
| -
 | 
| +  // DirectX diagnostics are collected asynchronously because it takes a
 | 
| +  // couple of seconds. Do not mark gpu_info as complete until that is done.
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| -bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
 | 
| -  TRACE_EVENT0("gpu", "CollectVideoCardInfo");
 | 
| +bool CollectBasicGraphicsInfo(content::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;
 | 
| @@ -304,86 +364,6 @@
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| -bool CollectDriverInfoD3D(const std::wstring& device_id,
 | 
| -                          content::GPUInfo* gpu_info) {
 | 
| -  TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
 | 
| -
 | 
| -  // create device info for the display device
 | 
| -  HDEVINFO device_info = SetupDiGetClassDevsW(
 | 
| -      NULL, device_id.c_str(), NULL,
 | 
| -      DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
 | 
| -  if (device_info == INVALID_HANDLE_VALUE) {
 | 
| -    LOG(ERROR) << "Creating device info failed";
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  DWORD index = 0;
 | 
| -  bool found = false;
 | 
| -  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 = WideToASCII(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 = WideToASCII(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 = WideToASCII(std::wstring(value));
 | 
| -          if (driver_vendor == "Advanced Micro Devices, Inc." ||
 | 
| -              driver_vendor == "ATI Technologies Inc.") {
 | 
| -            // We are conservative and assume that in the absence of a clear
 | 
| -            // signal the videocard is assumed to be switchable. Additionally,
 | 
| -            // some switchable systems with Intel GPUs aren't correctly
 | 
| -            // detected, so always count them.
 | 
| -            AMDVideoCardType amd_card_type = GetAMDVideocardType();
 | 
| -            gpu_info->amd_switchable = (gpu_info->gpu.vendor_id == 0x8086) ||
 | 
| -                                       (amd_card_type != STANDALONE);
 | 
| -          }
 | 
| -        }
 | 
| -
 | 
| -        gpu_info->driver_vendor = driver_vendor;
 | 
| -        gpu_info->driver_version = driver_version;
 | 
| -        gpu_info->driver_date = driver_date;
 | 
| -        found = true;
 | 
| -        RegCloseKey(key);
 | 
| -        break;
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -  SetupDiDestroyDeviceInfoList(device_info);
 | 
| -  return found;
 | 
| -}
 | 
| -
 | 
|  bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
 | 
|    TRACE_EVENT0("gpu", "CollectDriverInfoGL");
 | 
|  
 | 
| @@ -402,4 +382,32 @@
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| +void MergeGPUInfo(content::GPUInfo* basic_gpu_info,
 | 
| +                  const content::GPUInfo& context_gpu_info) {
 | 
| +  DCHECK(basic_gpu_info);
 | 
| +
 | 
| +  if (context_gpu_info.software_rendering) {
 | 
| +    basic_gpu_info->software_rendering = true;
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  if (!context_gpu_info.gl_vendor.empty()) {
 | 
| +    MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  basic_gpu_info->pixel_shader_version =
 | 
| +      context_gpu_info.pixel_shader_version;
 | 
| +  basic_gpu_info->vertex_shader_version =
 | 
| +      context_gpu_info.vertex_shader_version;
 | 
| +
 | 
| +  basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
 | 
| +
 | 
| +  basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context;
 | 
| +  basic_gpu_info->sandboxed = context_gpu_info.sandboxed;
 | 
| +  basic_gpu_info->gpu_accessible = context_gpu_info.gpu_accessible;
 | 
| +  basic_gpu_info->finalized = context_gpu_info.finalized;
 | 
| +  basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
 | 
| +}
 | 
| +
 | 
|  }  // namespace gpu_info_collector
 | 
| 
 |