1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/gl/gpu_switching_manager.h" 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "ui/gl/gl_switches.h" 10 11 #if defined(OS_MACOSX) 12 #include "base/mac/mac_util.h" 13 #include "ui/gl/gl_context_cgl.h" 14 #endif // OS_MACOSX 15 16 namespace ui { 17 18 // static 19 GpuSwitchingManager* GpuSwitchingManager::GetInstance() { 20 return Singleton<GpuSwitchingManager>::get(); 21 } 22 23 GpuSwitchingManager::GpuSwitchingManager() 24 : gpu_switching_option_(gfx::PreferIntegratedGpu), 25 gpu_switching_option_set_(false), 26 supports_dual_gpus_(false), 27 supports_dual_gpus_set_(false), 28 gpu_count_(0) { 29 #if defined(OS_MACOSX) 30 discrete_pixel_format_ = NULL; 31 #endif // OS_MACOSX 32 } 33 34 GpuSwitchingManager::~GpuSwitchingManager() { 35 #if defined(OS_MACOSX) 36 if (discrete_pixel_format_) 37 CGLReleasePixelFormat(discrete_pixel_format_); 38 #endif // OS_MACOSX 39 } 40 41 void GpuSwitchingManager::ForceUseOfIntegratedGpu() { 42 DCHECK(SupportsDualGpus()); 43 if (gpu_switching_option_set_) { 44 DCHECK_EQ(gpu_switching_option_, gfx::PreferIntegratedGpu); 45 } else { 46 gpu_switching_option_ = gfx::PreferIntegratedGpu; 47 gpu_switching_option_set_ = true; 48 } 49 } 50 51 void GpuSwitchingManager::ForceUseOfDiscreteGpu() { 52 DCHECK(SupportsDualGpus()); 53 if (gpu_switching_option_set_) { 54 DCHECK_EQ(gpu_switching_option_, gfx::PreferDiscreteGpu); 55 } else { 56 gpu_switching_option_ = gfx::PreferDiscreteGpu; 57 gpu_switching_option_set_ = true; 58 #if defined(OS_MACOSX) 59 // Create a pixel format that lasts the lifespan of Chrome, so Chrome 60 // stays on the discrete GPU. 61 SwitchToDiscreteGpuMac(); 62 #endif // OS_MACOSX 63 } 64 } 65 66 bool GpuSwitchingManager::SupportsDualGpus() { 67 if (!supports_dual_gpus_set_) { 68 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 69 bool flag = false; 70 if (command_line.HasSwitch(switches::kSupportsDualGpus)) { 71 // GPU process, flag is passed down from browser process. 72 std::string flag_string = command_line.GetSwitchValueASCII( 73 switches::kSupportsDualGpus); 74 if (flag_string == "true") { 75 flag = true; 76 } else if (flag_string == "false") { 77 flag = false; 78 } else { 79 NOTIMPLEMENTED(); 80 } 81 } else { 82 // Browser process. 83 // We only compute this flag in the browser process. 84 #if defined(OS_MACOSX) 85 flag = (gpu_count_ == 2); 86 if (flag && command_line.HasSwitch(switches::kUseGL) && 87 command_line.GetSwitchValueASCII(switches::kUseGL) != 88 gfx::kGLImplementationDesktopName) 89 flag = false; 90 91 if (flag && !base::mac::IsOSLionOrLater()) 92 flag = false; 93 #endif // OS_MACOSX 94 } 95 supports_dual_gpus_ = flag; 96 supports_dual_gpus_set_ = true; 97 } 98 return supports_dual_gpus_; 99 } 100 101 void GpuSwitchingManager::SetGpuCount(size_t gpu_count) { 102 gpu_count_ = gpu_count; 103 } 104 105 gfx::GpuPreference GpuSwitchingManager::AdjustGpuPreference( 106 gfx::GpuPreference gpu_preference) { 107 if (!gpu_switching_option_set_) 108 return gpu_preference; 109 return gpu_switching_option_; 110 } 111 112 #if defined(OS_MACOSX) 113 void GpuSwitchingManager::SwitchToDiscreteGpuMac() { 114 if (discrete_pixel_format_) 115 return; 116 CGLPixelFormatAttribute attribs[1]; 117 attribs[0] = static_cast<CGLPixelFormatAttribute>(0); 118 GLint num_pixel_formats = 0; 119 CGLChoosePixelFormat(attribs, &discrete_pixel_format_, &num_pixel_formats); 120 } 121 #endif // OS_MACOSX 122 123 } // namespace ui 124