1 // Copyright (c) 2017 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 "gpu/config/gpu_switching.h"
6
7 #if defined(OS_MACOSX)
8 #include <OpenGL/OpenGL.h>
9 #endif
10
11 #include <algorithm>
12 #include <vector>
13
14 #include "base/command_line.h"
15 #include "base/logging.h"
16 #include "gpu/config/gpu_driver_bug_workaround_type.h"
17 #include "gpu/config/gpu_info.h"
18 #include "ui/gl/gl_context.h"
19 #include "ui/gl/gl_switches.h"
20 #include "ui/gl/gpu_preference.h"
21
22 namespace gpu {
23
24 namespace {
25
26 #if defined(OS_MACOSX)
27 typedef CGLPixelFormatObj PlatformPixelFormatObj;
28 #else
29 typedef void* PlatformPixelFormatObj;
30 #endif // OS_MACOSX
31
32 PlatformPixelFormatObj g_discrete_pixel_format_obj = nullptr;
33
ContainsWorkaround(const std::vector<int32_t> & workarounds,int32_t workaround)34 bool ContainsWorkaround(const std::vector<int32_t>& workarounds,
35 int32_t workaround) {
36 return (std::find(workarounds.begin(), workarounds.end(), workaround) !=
37 workarounds.end());
38 }
39
ForceDiscreteGPU()40 void ForceDiscreteGPU() {
41 if (g_discrete_pixel_format_obj)
42 return;
43 #if defined(OS_MACOSX)
44 CGLPixelFormatAttribute attribs[1];
45 attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
46 GLint num_pixel_formats = 0;
47 CGLChoosePixelFormat(attribs, &g_discrete_pixel_format_obj,
48 &num_pixel_formats);
49 #endif // OS_MACOSX
50 }
51
52 } // namespace anonymous
53
SwitchableGPUsSupported(const GPUInfo & gpu_info,const base::CommandLine & command_line)54 bool SwitchableGPUsSupported(const GPUInfo& gpu_info,
55 const base::CommandLine& command_line) {
56 #if defined(OS_MACOSX)
57 if (command_line.HasSwitch(switches::kUseGL) &&
58 command_line.GetSwitchValueASCII(switches::kUseGL) !=
59 gl::kGLImplementationDesktopName &&
60 command_line.GetSwitchValueASCII(switches::kUseGL) !=
61 gl::kGLImplementationCoreProfileName) {
62 return false;
63 }
64 if (gpu_info.secondary_gpus.size() != 1) {
65 return false;
66 }
67 // Only advertise that we have two GPUs to the rest of
68 // Chrome's code if we find an Intel GPU and some other
69 // vendor's GPU. Otherwise we don't understand the
70 // configuration and don't deal well with it (an example being
71 // the dual AMD GPUs in recent Mac Pros).
72 const uint32_t kVendorIntel = 0x8086;
73 return ((gpu_info.gpu.vendor_id == kVendorIntel &&
74 gpu_info.secondary_gpus[0].vendor_id != kVendorIntel) ||
75 (gpu_info.gpu.vendor_id != kVendorIntel &&
76 gpu_info.secondary_gpus[0].vendor_id == kVendorIntel));
77 #else
78 return false;
79 #endif // OS_MACOSX
80 }
81
InitializeSwitchableGPUs(const std::vector<int32_t> & driver_bug_workarounds)82 void InitializeSwitchableGPUs(
83 const std::vector<int32_t>& driver_bug_workarounds) {
84 gl::GLContext::SetSwitchableGPUsSupported();
85 if (ContainsWorkaround(driver_bug_workarounds, FORCE_HIGH_PERFORMANCE_GPU)) {
86 gl::GLContext::SetForcedGpuPreference(gl::GpuPreference::kHighPerformance);
87 ForceDiscreteGPU();
88 } else if (ContainsWorkaround(driver_bug_workarounds, FORCE_LOW_POWER_GPU)) {
89 gl::GLContext::SetForcedGpuPreference(gl::GpuPreference::kLowPower);
90 }
91 }
92
StopForceDiscreteGPU()93 void StopForceDiscreteGPU() {
94 #if defined(OS_MACOSX)
95 if (g_discrete_pixel_format_obj) {
96 CGLReleasePixelFormat(g_discrete_pixel_format_obj);
97 g_discrete_pixel_format_obj = nullptr;
98 }
99 #endif // OS_MACOSX
100 }
101
102 } // namespace gpu
103