// 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_test_config.h"

#include "gpu_info.h"
#include "gpu_test_expectations_parser.h"

#if defined(OS_LINUX)
extern "C" {
#   include <pci/pci.h>
}
#endif

#if defined(OS_MACOSX)
#include "gpu_test_config_mac.h"
#endif

using namespace gpu;

#if defined(OS_WIN)

namespace base {

namespace {

// Disable the deprecated function warning for GetVersionEx
#pragma warning(disable: 4996)

class SysInfo
{
  public:
    static void OperatingSystemVersionNumbers(
        int32 *major_version, int32 *minor_version, int32 *bugfix_version);
};

// static
void SysInfo::OperatingSystemVersionNumbers(
    int32 *major_version, int32 *minor_version, int32 *bugfix_version)
{
  OSVERSIONINFOEX version_info = { sizeof version_info };
  ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
  *major_version = version_info.dwMajorVersion;
  *minor_version = version_info.dwMinorVersion;
  *bugfix_version = version_info.dwBuildNumber;
}

} // anonymous namespace

} // namespace base

void DeviceIDToVendorAndDevice(const std::string& id,
                               uint32* vendor_id,
                               uint32* device_id) {
  *vendor_id = 0;
  *device_id = 0;
  if (id.length() < 21)
    return;
  std::string vendor_id_string = id.substr(8, 4);
  std::string device_id_string = id.substr(17, 4);
  base::HexStringToUInt(vendor_id_string, vendor_id);
  base::HexStringToUInt(device_id_string, device_id);
}

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_DEVICEA dd;
  dd.cb = sizeof(DISPLAY_DEVICEA);
  std::string id;
  for (int i = 0; EnumDisplayDevicesA(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;
}

#endif // defined(OS_WIN)

#if defined(OS_LINUX)

const uint32 kVendorIDIntel = 0x8086;
const uint32 kVendorIDNVidia = 0x10de;
const uint32 kVendorIDAMD = 0x1002;

CollectInfoResult CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
  DCHECK(gpu_info);

  struct pci_access* access = pci_alloc();
  DCHECK(access != NULL);
  pci_init(access);
  pci_scan_bus(access);

  bool primary_gpu_identified = false;
  for (pci_dev* device = access->devices;
       device != NULL; device = device->next) {
    pci_fill_info(device, 33);
    bool is_gpu = false;
    switch (device->device_class) {
      case PCI_CLASS_DISPLAY_VGA:
      case PCI_CLASS_DISPLAY_XGA:
      case PCI_CLASS_DISPLAY_3D:
        is_gpu = true;
        break;
      case PCI_CLASS_DISPLAY_OTHER:
      default:
        break;
    }
    if (!is_gpu)
      continue;
    if (device->vendor_id == 0 || device->device_id == 0)
      continue;

    GPUInfo::GPUDevice gpu;
    gpu.vendor_id = device->vendor_id;
    gpu.device_id = device->device_id;

    if (!primary_gpu_identified) {
      primary_gpu_identified = true;
      gpu_info->gpu = gpu;
    } else {
      // TODO(zmo): if there are multiple GPUs, we assume the non Intel
      // one is primary. Revisit this logic because we actually don't know
      // which GPU we are using at this point.
      if (gpu_info->gpu.vendor_id == kVendorIDIntel &&
          gpu.vendor_id != kVendorIDIntel) {
        gpu_info->secondary_gpus.push_back(gpu_info->gpu);
        gpu_info->gpu = gpu;
      } else {
        gpu_info->secondary_gpus.push_back(gpu);
      }
    }
  }

  // Detect Optimus or AMD Switchable GPU.
  if (gpu_info->secondary_gpus.size() == 1 &&
      gpu_info->secondary_gpus[0].vendor_id == kVendorIDIntel) {
    if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
      gpu_info->optimus = true;
    if (gpu_info->gpu.vendor_id == kVendorIDAMD)
      gpu_info->amd_switchable = true;
  }

  pci_cleanup(access);
  if (!primary_gpu_identified)
    return kCollectInfoNonFatalFailure;
  return kCollectInfoSuccess;
}

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

  GPUInfo gpu_info;
  CollectInfoResult result = CollectPCIVideoCardInfo(&gpu_info);
  if (result == kCollectInfoSuccess) {
    *vendor_id = gpu_info.gpu.vendor_id;
    *device_id = gpu_info.gpu.device_id;
  }
  return result;
}

#endif // defined(OS_LINUX)

#if defined(OS_MACOSX)

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

  GPUInfo::GPUDevice gpu = GetActiveGPU();
  *vendor_id = gpu.vendor_id;
  *device_id = gpu.device_id;

  if (*vendor_id != 0 && *device_id != 0)
    return kCollectInfoSuccess;
  return kCollectInfoNonFatalFailure;
}

#endif

#if defined(OS_ANDROID)
CollectInfoResult CollectGpuID(uint32 *vendor_id, uint32 *device_id)
{
    DCHECK(vendor_id && device_id);
    *vendor_id = 0;
    *device_id = 0;
    return kCollectInfoNonFatalFailure;
}
#endif  // defined(OS_ANDROID)

namespace gpu {

namespace {

GPUTestConfig::OS GetCurrentOS() {
#if defined(OS_CHROMEOS)
  return GPUTestConfig::kOsChromeOS;
#elif defined(OS_LINUX) || defined(OS_OPENBSD)
  return GPUTestConfig::kOsLinux;
#elif defined(OS_WIN)
  int32 major_version = 0;
  int32 minor_version = 0;
  int32 bugfix_version = 0;
  base::SysInfo::OperatingSystemVersionNumbers(
      &major_version, &minor_version, &bugfix_version);
  if (major_version == 5)
    return GPUTestConfig::kOsWinXP;
  if (major_version == 6 && minor_version == 0)
    return GPUTestConfig::kOsWinVista;
  if (major_version == 6 && minor_version == 1)
    return GPUTestConfig::kOsWin7;
  if (major_version == 6 && (minor_version == 2 || minor_version == 3))
    return GPUTestConfig::kOsWin8;
  if (major_version == 10)
    return GPUTestConfig::kOsWin10;
#elif defined(OS_MACOSX)
  int32 major_version = 0;
  int32 minor_version = 0;
  int32 bugfix_version = 0;
  base::SysInfo::OperatingSystemVersionNumbers(
      &major_version, &minor_version, &bugfix_version);
  if (major_version == 10) {
    switch (minor_version) {
      case 5:
        return GPUTestConfig::kOsMacLeopard;
      case 6:
        return GPUTestConfig::kOsMacSnowLeopard;
      case 7:
        return GPUTestConfig::kOsMacLion;
      case 8:
        return GPUTestConfig::kOsMacMountainLion;
      case 9:
        return GPUTestConfig::kOsMacMavericks;
      case 10:
        return GPUTestConfig::kOsMacYosemite;
      case 11:
        return GPUTestConfig::kOsMacElCapitan;
    }
  }
#elif defined(OS_ANDROID)
  return GPUTestConfig::kOsAndroid;
#endif
  return GPUTestConfig::kOsUnknown;
}

}  // namespace anonymous

GPUTestConfig::GPUTestConfig()
    : validate_gpu_info_(true),
      os_(kOsUnknown),
      gpu_device_id_(0),
      build_type_(kBuildTypeUnknown),
      api_(kAPIUnknown) {}

GPUTestConfig::~GPUTestConfig() {
}

void GPUTestConfig::set_os(int32 os) {
  DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS));
  os_ = os;
}

void GPUTestConfig::AddGPUVendor(uint32 gpu_vendor) {
  DCHECK_NE(0u, gpu_vendor);
  for (size_t i = 0; i < gpu_vendor_.size(); ++i)
    DCHECK_NE(gpu_vendor_[i], gpu_vendor);
  gpu_vendor_.push_back(gpu_vendor);
}

void GPUTestConfig::set_gpu_device_id(uint32 id) {
  gpu_device_id_ = id;
}

void GPUTestConfig::set_build_type(int32 build_type) {
  DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
  build_type_ = build_type;
}

void GPUTestConfig::set_api(int32 api) {
  DCHECK_EQ(0, api & ~(kAPID3D9 | kAPID3D11 | kAPIGLDesktop | kAPIGLES));
  api_ = api;
}

bool GPUTestConfig::IsValid() const {
  if (!validate_gpu_info_)
    return true;
  if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
    return false;
  return true;
}

bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const {
  DCHECK(IsValid());
  DCHECK(config.IsValid());
  if (config.os_ != kOsUnknown && os_ != kOsUnknown &&
      (os_ & config.os_) == 0)
    return false;
  if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) {
    bool shared = false;
    for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) {
      for (size_t j = 0; j < gpu_vendor_.size(); ++j) {
        if (config.gpu_vendor_[i] == gpu_vendor_[j]) {
          shared = true;
          break;
        }
      }
    }
    if (!shared)
      return false;
  }
  if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
      gpu_device_id_ != config.gpu_device_id_)
    return false;
  if (config.build_type_ != kBuildTypeUnknown &&
      build_type_ != kBuildTypeUnknown &&
      (build_type_ & config.build_type_) == 0)
    return false;
  return true;
}

void GPUTestConfig::DisableGPUInfoValidation() {
  validate_gpu_info_ = false;
}

void GPUTestConfig::ClearGPUVendor() {
  gpu_vendor_.clear();
}

GPUTestBotConfig::~GPUTestBotConfig() {
}

void GPUTestBotConfig::AddGPUVendor(uint32 gpu_vendor) {
  DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
  GPUTestConfig::AddGPUVendor(gpu_vendor);
}

bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) {
  DCHECK(validate_gpu_info_);
  if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0)
    return false;
  ClearGPUVendor();
  AddGPUVendor(gpu_info.gpu.vendor_id);
  set_gpu_device_id(gpu_info.gpu.device_id);
  return true;
}

bool GPUTestBotConfig::IsValid() const {
  switch (os()) {
    case kOsWinXP:
    case kOsWinVista:
    case kOsWin7:
    case kOsWin8:
    case kOsWin10:
    case kOsMacLeopard:
    case kOsMacSnowLeopard:
    case kOsMacLion:
    case kOsMacMountainLion:
    case kOsMacMavericks:
    case kOsMacYosemite:
    case kOsMacElCapitan:
    case kOsLinux:
    case kOsChromeOS:
    case kOsAndroid:
      break;
    default:
      return false;
  }
  if (validate_gpu_info_) {
    if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
      return false;
    if (gpu_device_id() == 0)
      return false;
  }
  switch (build_type()) {
    case kBuildTypeRelease:
    case kBuildTypeDebug:
      break;
    default:
      return false;
  }
  return true;
}

bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const {
  DCHECK(IsValid());
  DCHECK(config.IsValid());
  if (config.os() != kOsUnknown && (os() & config.os()) == 0)
    return false;
  if (config.gpu_vendor().size() > 0) {
    bool contained = false;
    for (size_t i = 0; i < config.gpu_vendor().size(); ++i) {
      if (config.gpu_vendor()[i] == gpu_vendor()[0]) {
        contained = true;
        break;
      }
    }
    if (!contained)
      return false;
  }
  if (config.gpu_device_id() != 0 &&
      gpu_device_id() != config.gpu_device_id())
    return false;
  if (config.build_type() != kBuildTypeUnknown &&
      (build_type() & config.build_type()) == 0)
    return false;
  if (config.api() != 0 && (api() & config.api()) == 0)
    return false;
  return true;
}

bool GPUTestBotConfig::Matches(const std::string& config_data) const {
  GPUTestExpectationsParser parser;
  GPUTestConfig config;

  if (!parser.ParseConfig(config_data, &config))
    return false;
  return Matches(config);
}

bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo *gpu_info)
{
    bool rt;
    if (gpu_info == NULL)
    {
        GPUInfo my_gpu_info;
        CollectInfoResult result =
            CollectGpuID(&my_gpu_info.gpu.vendor_id, &my_gpu_info.gpu.device_id);
        if (result != kCollectInfoSuccess)
        {
            LOG(ERROR) << "Fail to identify GPU\n";
            DisableGPUInfoValidation();
            rt = true;
        }
        else
        {
            rt = SetGPUInfo(my_gpu_info);
        }
    }
    else
    {
        rt = SetGPUInfo(*gpu_info);
    }
    set_os(GetCurrentOS());
    if (os() == kOsUnknown)
    {
        LOG(ERROR) << "Unknown OS\n";
        rt = false;
    }
#if defined(NDEBUG)
    set_build_type(kBuildTypeRelease);
#else
    set_build_type(kBuildTypeDebug);
#endif
    return rt;
}

// static
bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) {
  GPUTestBotConfig my_config;
  if (!my_config.LoadCurrentConfig(NULL))
    return false;
  return my_config.Matches(config_data);
}

// static
bool GPUTestBotConfig::CurrentConfigMatches(
    const std::vector<std::string>& configs) {
  GPUTestBotConfig my_config;
  if (!my_config.LoadCurrentConfig(NULL))
    return false;
  for (size_t i = 0 ; i < configs.size(); ++i) {
    if (my_config.Matches(configs[i]))
      return true;
  }
  return false;
}

}  // namespace gpu

