// 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 "ui/gl/gpu_switching_manager.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "ui/gl/gl_switches.h"

#if defined(OS_MACOSX)
#include <OpenGL/OpenGL.h>
#include "ui/gl/gl_context_cgl.h"
#endif  // OS_MACOSX

namespace ui {

struct GpuSwitchingManager::PlatformSpecific {
#if defined(OS_MACOSX)
  CGLPixelFormatObj discrete_pixel_format;
#endif  // OS_MACOSX
};

// static
GpuSwitchingManager* GpuSwitchingManager::GetInstance() {
  return base::Singleton<GpuSwitchingManager>::get();
}

GpuSwitchingManager::GpuSwitchingManager()
    : gpu_switching_option_(gl::PreferIntegratedGpu),
      gpu_switching_option_set_(false),
      supports_dual_gpus_(false),
      supports_dual_gpus_set_(false),
      platform_specific_(new PlatformSpecific) {
#if defined(OS_MACOSX)
  platform_specific_->discrete_pixel_format = nullptr;
#endif  // OS_MACOSX
}

GpuSwitchingManager::~GpuSwitchingManager() {
#if defined(OS_MACOSX)
  if (platform_specific_->discrete_pixel_format)
    CGLReleasePixelFormat(platform_specific_->discrete_pixel_format);
#endif  // OS_MACOSX
}

void GpuSwitchingManager::ForceUseOfIntegratedGpu() {
  DCHECK(SupportsDualGpus());
  if (gpu_switching_option_set_) {
    DCHECK_EQ(gpu_switching_option_, gl::PreferIntegratedGpu);
  } else {
    gpu_switching_option_ = gl::PreferIntegratedGpu;
    gpu_switching_option_set_ = true;
  }
}

void GpuSwitchingManager::ForceUseOfDiscreteGpu() {
  DCHECK(SupportsDualGpus());
  if (gpu_switching_option_set_) {
    DCHECK_EQ(gpu_switching_option_, gl::PreferDiscreteGpu);
  } else {
    gpu_switching_option_ = gl::PreferDiscreteGpu;
    gpu_switching_option_set_ = true;
#if defined(OS_MACOSX)
    // Create a pixel format that lasts the lifespan of Chrome, so Chrome
    // stays on the discrete GPU.
    SwitchToDiscreteGpuMac();
#endif  // OS_MACOSX
  }
}

bool GpuSwitchingManager::SupportsDualGpus() {
  if (!supports_dual_gpus_set_) {
    const base::CommandLine& command_line =
        *base::CommandLine::ForCurrentProcess();
    bool flag = false;
    if (command_line.HasSwitch(switches::kSupportsDualGpus)) {
      // GPU process, flag is passed down from browser process.
      std::string flag_string = command_line.GetSwitchValueASCII(
          switches::kSupportsDualGpus);
      if (flag_string == "true") {
        flag = true;
      } else if (flag_string == "false") {
        flag = false;
      } else {
        NOTIMPLEMENTED();
      }
    } else {
      // Browser process.
      // We only compute this flag in the browser process.
#if defined(OS_MACOSX)
      flag = (vendor_ids_.size() == 2);
      if (flag && command_line.HasSwitch(switches::kUseGL) &&
          command_line.GetSwitchValueASCII(switches::kUseGL) !=
              gl::kGLImplementationDesktopName)
        flag = false;

      if (flag) {
        // Only advertise that we have two GPUs to the rest of
        // Chrome's code if we find an Intel GPU and some other
        // vendor's GPU. Otherwise we don't understand the
        // configuration and don't deal well with it (an example being
        // the dual AMD GPUs in recent Mac Pros).
        const uint32_t intel = 0x8086;
        flag = ((vendor_ids_[0] == intel && vendor_ids_[1] != intel) ||
                (vendor_ids_[0] != intel && vendor_ids_[1] == intel));
      }
#endif  // OS_MACOSX
    }
    supports_dual_gpus_ = flag;
    supports_dual_gpus_set_ = true;
  }
  return supports_dual_gpus_;
}

void GpuSwitchingManager::SetGpuVendorIds(
    const std::vector<uint32_t>& vendor_ids) {
  vendor_ids_ = vendor_ids;
}

void GpuSwitchingManager::AddObserver(GpuSwitchingObserver* observer) {
  observer_list_.AddObserver(observer);
}

void GpuSwitchingManager::RemoveObserver(GpuSwitchingObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

void GpuSwitchingManager::NotifyGpuSwitched() {
  FOR_EACH_OBSERVER(GpuSwitchingObserver, observer_list_, OnGpuSwitched());
}

gl::GpuPreference GpuSwitchingManager::AdjustGpuPreference(
    gl::GpuPreference gpu_preference) {
  if (!gpu_switching_option_set_)
    return gpu_preference;
  return gpu_switching_option_;
}

#if defined(OS_MACOSX)
void GpuSwitchingManager::SwitchToDiscreteGpuMac() {
  if (platform_specific_->discrete_pixel_format)
    return;
  CGLPixelFormatAttribute attribs[1];
  attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
  GLint num_pixel_formats = 0;
  CGLChoosePixelFormat(attribs, &platform_specific_->discrete_pixel_format,
                       &num_pixel_formats);
}
#endif  // OS_MACOSX

}  // namespace ui
