Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: content/gpu/gpu_info_collector_mac.mm

Issue 15745014: Move GPU device/driver info related code from content to gpu. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/gpu/gpu_info_collector_android.cc ('k') | content/gpu/gpu_info_collector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "content/gpu/gpu_info_collector.h"
6
7 #include <vector>
8
9 #include "base/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "base/mac/mac_util.h"
12 #include "base/mac/scoped_cftyperef.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/string_number_conversions.h"
15 #include "base/string_util.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "ui/gl/gl_bindings.h"
19 #include "ui/gl/gl_context.h"
20 #include "ui/gl/gl_implementation.h"
21 #include "ui/gl/gl_interface.h"
22
23 #import <Cocoa/Cocoa.h>
24 #import <Foundation/Foundation.h>
25 #import <IOKit/IOKitLib.h>
26
27 namespace {
28
29 const UInt32 kVendorIDIntel = 0x8086;
30 const UInt32 kVendorIDNVidia = 0x10de;
31 const UInt32 kVendorIDAMD = 0x1002;
32
33 // Return 0 if we couldn't find the property.
34 // The property values we use should not be 0, so it's OK to use 0 as failure.
35 UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
36 base::mac::ScopedCFTypeRef<CFDataRef> data_ref(static_cast<CFDataRef>(
37 IORegistryEntrySearchCFProperty(entry,
38 kIOServicePlane,
39 property_name,
40 kCFAllocatorDefault,
41 kIORegistryIterateRecursively |
42 kIORegistryIterateParents)));
43 if (!data_ref)
44 return 0;
45
46 UInt32 value = 0;
47 const UInt32* value_pointer =
48 reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref));
49 if (value_pointer != NULL)
50 value = *value_pointer;
51 return value;
52 }
53
54 // Find the info of the current GPU.
55 content::GPUInfo::GPUDevice GetActiveGPU() {
56 content::GPUInfo::GPUDevice gpu;
57 io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
58 gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
59 gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
60 return gpu;
61 }
62
63 // Scan IO registry for PCI video cards.
64 bool CollectPCIVideoCardInfo(content::GPUInfo* gpu_info) {
65 DCHECK(gpu_info);
66
67 // Collect all GPUs' info.
68 // match_dictionary will be consumed by IOServiceGetMatchingServices, no need
69 // to release it.
70 CFMutableDictionaryRef match_dictionary = IOServiceMatching("IOPCIDevice");
71 io_iterator_t entry_iterator;
72 std::vector<content::GPUInfo::GPUDevice> gpu_list;
73 if (IOServiceGetMatchingServices(kIOMasterPortDefault,
74 match_dictionary,
75 &entry_iterator) == kIOReturnSuccess) {
76 io_registry_entry_t entry;
77 while ((entry = IOIteratorNext(entry_iterator))) {
78 content::GPUInfo::GPUDevice gpu;
79 if (GetEntryProperty(entry, CFSTR("class-code")) != 0x30000) {
80 // 0x30000 : DISPLAY_VGA
81 continue;
82 }
83 gpu.vendor_id = GetEntryProperty(entry, CFSTR("vendor-id"));
84 gpu.device_id = GetEntryProperty(entry, CFSTR("device-id"));
85 if (gpu.vendor_id && gpu.device_id)
86 gpu_list.push_back(gpu);
87 }
88 IOObjectRelease(entry_iterator);
89 }
90
91 switch (gpu_list.size()) {
92 case 0:
93 return false;
94 case 1:
95 gpu_info->gpu = gpu_list[0];
96 break;
97 case 2:
98 {
99 int integrated = -1;
100 int discrete = -1;
101 if (gpu_list[0].vendor_id == kVendorIDIntel)
102 integrated = 0;
103 else if (gpu_list[1].vendor_id == kVendorIDIntel)
104 integrated = 1;
105 if (integrated >= 0) {
106 switch (gpu_list[1 - integrated].vendor_id) {
107 case kVendorIDAMD:
108 gpu_info->amd_switchable = true;
109 discrete = 1 - integrated;
110 break;
111 case kVendorIDNVidia:
112 gpu_info->optimus = true;
113 discrete = 1 - integrated;
114 break;
115 default:
116 break;
117 }
118 }
119 if (integrated >= 0 && discrete >= 0) {
120 // We always put discrete GPU as primary for blacklisting purpose.
121 gpu_info->gpu = gpu_list[discrete];
122 gpu_info->secondary_gpus.push_back(gpu_list[integrated]);
123 break;
124 }
125 // If it's not optimus or amd_switchable, we put the current GPU as
126 // primary. Fall through to default.
127 }
128 default:
129 {
130 content::GPUInfo::GPUDevice active_gpu = GetActiveGPU();
131 size_t current = gpu_list.size();
132 if (active_gpu.vendor_id && active_gpu.device_id) {
133 for (size_t i = 0; i < gpu_list.size(); ++i) {
134 if (gpu_list[i].vendor_id == active_gpu.vendor_id &&
135 gpu_list[i].device_id == active_gpu.device_id) {
136 current = i;
137 break;
138 }
139 }
140 }
141 if (current == gpu_list.size()) {
142 // If we fail to identify the current GPU, select any one as primary.
143 current = 0;
144 }
145 for (size_t i = 0; i < gpu_list.size(); ++i) {
146 if (i == current)
147 gpu_info->gpu = gpu_list[i];
148 else
149 gpu_info->secondary_gpus.push_back(gpu_list[i]);
150 }
151 }
152 break;
153 }
154 return (gpu_info->gpu.vendor_id && gpu_info->gpu.device_id);
155 }
156
157 } // namespace anonymous
158
159 namespace gpu_info_collector {
160
161 bool CollectContextGraphicsInfo(content::GPUInfo* gpu_info) {
162 DCHECK(gpu_info);
163
164 TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");
165
166 gpu_info->can_lose_context =
167 (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2);
168 gpu_info->finalized = true;
169 return CollectGraphicsInfoGL(gpu_info);
170 }
171
172 GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
173 DCHECK(vendor_id && device_id);
174 *vendor_id = 0;
175 *device_id = 0;
176
177 content::GPUInfo gpu_info;
178 if (CollectPCIVideoCardInfo(&gpu_info)) {
179 *vendor_id = gpu_info.gpu.vendor_id;
180 *device_id = gpu_info.gpu.device_id;
181 return kGpuIDSuccess;
182 }
183 return kGpuIDFailure;
184 }
185
186 bool CollectBasicGraphicsInfo(content::GPUInfo* gpu_info) {
187 DCHECK(gpu_info);
188
189 std::string model_name;
190 int32 model_major = 0, model_minor = 0;
191 base::mac::ParseModelIdentifier(base::mac::GetModelIdentifier(),
192 &model_name, &model_major, &model_minor);
193 ReplaceChars(model_name, " ", "_", &gpu_info->machine_model);
194 gpu_info->machine_model += " " + base::IntToString(model_major) +
195 "." + base::IntToString(model_minor);
196
197 return CollectPCIVideoCardInfo(gpu_info);
198 }
199
200 bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
201 DCHECK(gpu_info);
202
203 // Extract the OpenGL driver version string from the GL_VERSION string.
204 // Mac OpenGL drivers have the driver version
205 // at the end of the gl version string preceded by a dash.
206 // Use some jiggery-pokery to turn that utf8 string into a std::wstring.
207 std::string gl_version_string = gpu_info->gl_version_string;
208 size_t pos = gl_version_string.find_last_of('-');
209 if (pos == std::string::npos)
210 return false;
211 gpu_info->driver_version = gl_version_string.substr(pos + 1);
212 return true;
213 }
214
215 void MergeGPUInfo(content::GPUInfo* basic_gpu_info,
216 const content::GPUInfo& context_gpu_info) {
217 MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
218 }
219
220 } // namespace gpu_info_collector
OLDNEW
« no previous file with comments | « content/gpu/gpu_info_collector_android.cc ('k') | content/gpu/gpu_info_collector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698