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.
5 #include "ui/gl/gpu_switching_manager.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "ui/gl/gl_switches.h"
11 #if defined(OS_MACOSX)
12 #include <OpenGL/OpenGL.h>
13 #include "base/mac/mac_util.h"
14 #include "ui/gl/gl_context_cgl.h"
19 struct GpuSwitchingManager::PlatformSpecific
{
20 #if defined(OS_MACOSX)
21 CGLPixelFormatObj discrete_pixel_format
;
26 GpuSwitchingManager
* GpuSwitchingManager::GetInstance() {
27 return Singleton
<GpuSwitchingManager
>::get();
30 GpuSwitchingManager::GpuSwitchingManager()
31 : gpu_switching_option_(gfx::PreferIntegratedGpu
),
32 gpu_switching_option_set_(false),
33 supports_dual_gpus_(false),
34 supports_dual_gpus_set_(false),
36 platform_specific_(new PlatformSpecific
) {
37 #if defined(OS_MACOSX)
38 platform_specific_
->discrete_pixel_format
= nullptr;
42 GpuSwitchingManager::~GpuSwitchingManager() {
43 #if defined(OS_MACOSX)
44 if (platform_specific_
->discrete_pixel_format
)
45 CGLReleasePixelFormat(platform_specific_
->discrete_pixel_format
);
49 void GpuSwitchingManager::ForceUseOfIntegratedGpu() {
50 DCHECK(SupportsDualGpus());
51 if (gpu_switching_option_set_
) {
52 DCHECK_EQ(gpu_switching_option_
, gfx::PreferIntegratedGpu
);
54 gpu_switching_option_
= gfx::PreferIntegratedGpu
;
55 gpu_switching_option_set_
= true;
59 void GpuSwitchingManager::ForceUseOfDiscreteGpu() {
60 DCHECK(SupportsDualGpus());
61 if (gpu_switching_option_set_
) {
62 DCHECK_EQ(gpu_switching_option_
, gfx::PreferDiscreteGpu
);
64 gpu_switching_option_
= gfx::PreferDiscreteGpu
;
65 gpu_switching_option_set_
= true;
66 #if defined(OS_MACOSX)
67 // Create a pixel format that lasts the lifespan of Chrome, so Chrome
68 // stays on the discrete GPU.
69 SwitchToDiscreteGpuMac();
74 bool GpuSwitchingManager::SupportsDualGpus() {
75 if (!supports_dual_gpus_set_
) {
76 const base::CommandLine
& command_line
=
77 *base::CommandLine::ForCurrentProcess();
79 if (command_line
.HasSwitch(switches::kSupportsDualGpus
)) {
80 // GPU process, flag is passed down from browser process.
81 std::string flag_string
= command_line
.GetSwitchValueASCII(
82 switches::kSupportsDualGpus
);
83 if (flag_string
== "true") {
85 } else if (flag_string
== "false") {
92 // We only compute this flag in the browser process.
93 #if defined(OS_MACOSX)
94 flag
= (gpu_count_
== 2);
95 if (flag
&& command_line
.HasSwitch(switches::kUseGL
) &&
96 command_line
.GetSwitchValueASCII(switches::kUseGL
) !=
97 gfx::kGLImplementationDesktopName
)
100 if (flag
&& !base::mac::IsOSLionOrLater())
104 supports_dual_gpus_
= flag
;
105 supports_dual_gpus_set_
= true;
107 return supports_dual_gpus_
;
110 void GpuSwitchingManager::SetGpuCount(size_t gpu_count
) {
111 gpu_count_
= gpu_count
;
114 void GpuSwitchingManager::AddObserver(GpuSwitchingObserver
* observer
) {
115 observer_list_
.AddObserver(observer
);
118 void GpuSwitchingManager::RemoveObserver(GpuSwitchingObserver
* observer
) {
119 observer_list_
.RemoveObserver(observer
);
122 void GpuSwitchingManager::NotifyGpuSwitched() {
123 FOR_EACH_OBSERVER(GpuSwitchingObserver
, observer_list_
, OnGpuSwitched());
126 gfx::GpuPreference
GpuSwitchingManager::AdjustGpuPreference(
127 gfx::GpuPreference gpu_preference
) {
128 if (!gpu_switching_option_set_
)
129 return gpu_preference
;
130 return gpu_switching_option_
;
133 #if defined(OS_MACOSX)
134 void GpuSwitchingManager::SwitchToDiscreteGpuMac() {
135 if (platform_specific_
->discrete_pixel_format
)
137 CGLPixelFormatAttribute attribs
[1];
138 attribs
[0] = static_cast<CGLPixelFormatAttribute
>(0);
139 GLint num_pixel_formats
= 0;
140 CGLChoosePixelFormat(attribs
, &platform_specific_
->discrete_pixel_format
,