// 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"

#include <vector>

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>

namespace gpu {

namespace {

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

// Return 0 if we couldn't find the property.
// The property values we use should not be 0, so it's OK to use 0 as failure.
UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
  base::ScopedCFTypeRef<CFDataRef> data_ref(
      static_cast<CFDataRef>(IORegistryEntrySearchCFProperty(
          entry,
          kIOServicePlane,
          property_name,
          kCFAllocatorDefault,
          kIORegistryIterateRecursively | kIORegistryIterateParents)));
  if (!data_ref)
    return 0;

  UInt32 value = 0;
  const UInt32* value_pointer =
      reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref));
  if (value_pointer != NULL)
    value = *value_pointer;
  return value;
}

// Find the info of the current GPU.
GPUInfo::GPUDevice GetActiveGPU() {
  GPUInfo::GPUDevice gpu;
  io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
  gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
  gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
  return gpu;
}

// Scan IO registry for PCI video cards.
bool CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
  DCHECK(gpu_info);
  GPUInfo::GPUDevice active_gpu = GetActiveGPU();

  // Collect all GPUs' info.
  // match_dictionary will be consumed by IOServiceGetMatchingServices, no need
  // to release it.
  CFMutableDictionaryRef match_dictionary = IOServiceMatching("IOPCIDevice");
  io_iterator_t entry_iterator;
  std::vector<GPUInfo::GPUDevice> gpu_list;
  if (IOServiceGetMatchingServices(kIOMasterPortDefault,
                                   match_dictionary,
                                   &entry_iterator) == kIOReturnSuccess) {
    io_registry_entry_t entry;
    while ((entry = IOIteratorNext(entry_iterator))) {
      GPUInfo::GPUDevice gpu;
      if (GetEntryProperty(entry, CFSTR("class-code")) != 0x30000) {
        // 0x30000 : DISPLAY_VGA
        continue;
      }
      gpu.vendor_id = GetEntryProperty(entry, CFSTR("vendor-id"));
      gpu.device_id = GetEntryProperty(entry, CFSTR("device-id"));
      if (gpu.vendor_id && gpu.device_id) {
        if (gpu.vendor_id == active_gpu.vendor_id &&
            gpu.device_id == active_gpu.device_id) {
          gpu.active = true;
        }
        gpu_list.push_back(gpu);
      }
    }
    IOObjectRelease(entry_iterator);
  }

  switch (gpu_list.size()) {
    case 0:
      return false;
    case 1:
      gpu_info->gpu = gpu_list[0];
      break;
    case 2:
      {
        int integrated = -1;
        int discrete = -1;
        if (gpu_list[0].vendor_id == kVendorIDIntel)
          integrated = 0;
        else if (gpu_list[1].vendor_id == kVendorIDIntel)
          integrated = 1;
        if (integrated >= 0) {
          switch (gpu_list[1 - integrated].vendor_id) {
            case kVendorIDAMD:
              gpu_info->amd_switchable = true;
              discrete = 1 - integrated;
              break;
            case kVendorIDNVidia:
              gpu_info->optimus = true;
              discrete = 1 - integrated;
              break;
            default:
              break;
          }
        }
        if (integrated >= 0 && discrete >= 0) {
          // We always put discrete GPU as primary for blacklisting purpose.
          gpu_info->gpu = gpu_list[discrete];
          gpu_info->secondary_gpus.push_back(gpu_list[integrated]);
          break;
        }
        // If it's not optimus or amd_switchable, we put the current GPU as
        // primary.  Fall through to default.
      }
    default:
      {
        size_t current = gpu_list.size();
        for (size_t i = 0; i < gpu_list.size(); ++i) {
          if (gpu_list[i].active) {
            current = i;
            break;
          }
        }
        if (current == gpu_list.size()) {
          // If we fail to identify the current GPU, select any one as primary.
          current = 0;
        }
        for (size_t i = 0; i < gpu_list.size(); ++i) {
          if (i == current)
            gpu_info->gpu = gpu_list[i];
          else
            gpu_info->secondary_gpus.push_back(gpu_list[i]);
        }
      }
      break;
  }
  return (gpu_info->gpu.vendor_id && gpu_info->gpu.device_id);
}

}  // namespace anonymous

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

  TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");

  gpu_info->can_lose_context =
      (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2);
  gpu_info->finalized = true;
  return CollectGraphicsInfoGL(gpu_info);
}

GpuIDResult 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 kGpuIDSuccess;
  return kGpuIDFailure;
}

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

  int32 model_major = 0, model_minor = 0;
  base::mac::ParseModelIdentifier(base::mac::GetModelIdentifier(),
                                  &gpu_info->machine_model_name,
                                  &model_major, &model_minor);
  gpu_info->machine_model_version =
      base::IntToString(model_major) + "." + base::IntToString(model_minor);

  bool result = CollectPCIVideoCardInfo(gpu_info);
  return result ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
}

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

  // Extract the OpenGL driver version string from the GL_VERSION string.
  // Mac OpenGL drivers have the driver version
  // at the end of the gl version string preceded by a dash.
  // Use some jiggery-pokery to turn that utf8 string into a std::wstring.
  size_t pos = gpu_info->gl_version.find_last_of('-');
  if (pos == std::string::npos)
    return kCollectInfoNonFatalFailure;
  gpu_info->driver_version = gpu_info->gl_version.substr(pos + 1);
  return kCollectInfoSuccess;
}

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

}  // namespace gpu
