15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gpu_switching_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_cgl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuSwitchingManager* GpuSwitchingManager::GetInstance() {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<GpuSwitchingManager>::get();
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuSwitchingManager::GpuSwitchingManager()
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : gpu_switching_option_(gfx::PreferIntegratedGpu),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gpu_switching_option_set_(false),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supports_dual_gpus_(false),
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      supports_dual_gpus_set_(false),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gpu_count_(0) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  discrete_pixel_format_ = NULL;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuSwitchingManager::~GpuSwitchingManager() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (discrete_pixel_format_)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CGLReleasePixelFormat(discrete_pixel_format_);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuSwitchingManager::ForceUseOfIntegratedGpu() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SupportsDualGpus());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gpu_switching_option_set_) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(gpu_switching_option_, gfx::PreferIntegratedGpu);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu_switching_option_ = gfx::PreferIntegratedGpu;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu_switching_option_set_ = true;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuSwitchingManager::ForceUseOfDiscreteGpu() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SupportsDualGpus());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gpu_switching_option_set_) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(gpu_switching_option_, gfx::PreferDiscreteGpu);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu_switching_option_ = gfx::PreferDiscreteGpu;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu_switching_option_set_ = true;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a pixel format that lasts the lifespan of Chrome, so Chrome
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // stays on the discrete GPU.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SwitchToDiscreteGpuMac();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuSwitchingManager::SupportsDualGpus() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!supports_dual_gpus_set_) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool flag = false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (command_line.HasSwitch(switches::kSupportsDualGpus)) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // GPU process, flag is passed down from browser process.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string flag_string = command_line.GetSwitchValueASCII(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kSupportsDualGpus);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (flag_string == "true") {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flag = true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (flag_string == "false") {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flag = false;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTIMPLEMENTED();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Browser process.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We only compute this flag in the browser process.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      flag = (gpu_count_ == 2);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (flag && command_line.HasSwitch(switches::kUseGL) &&
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          command_line.GetSwitchValueASCII(switches::kUseGL) !=
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            gfx::kGLImplementationDesktopName)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flag = false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (flag && !base::mac::IsOSLionOrLater())
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flag = false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supports_dual_gpus_ = flag;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supports_dual_gpus_set_ = true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return supports_dual_gpus_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuSwitchingManager::SetGpuCount(size_t gpu_count) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_count_ = gpu_count;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::GpuPreference GpuSwitchingManager::AdjustGpuPreference(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!gpu_switching_option_set_)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gpu_preference;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gpu_switching_option_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuSwitchingManager::SwitchToDiscreteGpuMac() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (discrete_pixel_format_)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CGLPixelFormatAttribute attribs[1];
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint num_pixel_formats = 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CGLChoosePixelFormat(attribs, &discrete_pixel_format_, &num_pixel_formats);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_MACOSX
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
124