|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <OpenGL/OpenGL.h> |
|
7 #include <OpenGL/CGLRenderers.h> |
|
8 |
|
9 #include "mozilla/ArrayUtils.h" |
|
10 |
|
11 #include "GfxInfo.h" |
|
12 #include "nsUnicharUtils.h" |
|
13 #include "nsCocoaFeatures.h" |
|
14 #include "mozilla/Preferences.h" |
|
15 #include <algorithm> |
|
16 |
|
17 #import <Foundation/Foundation.h> |
|
18 #import <IOKit/IOKitLib.h> |
|
19 #import <Cocoa/Cocoa.h> |
|
20 |
|
21 #if defined(MOZ_CRASHREPORTER) |
|
22 #include "nsExceptionHandler.h" |
|
23 #include "nsICrashReporter.h" |
|
24 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1" |
|
25 #endif |
|
26 |
|
27 #define MAC_OS_X_VERSION_MASK 0x0000FFFF |
|
28 #define MAC_OS_X_VERSION_MAJOR_MASK 0x0000FFF0 |
|
29 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060 |
|
30 #define MAC_OS_X_VERSION_10_7_HEX 0x00001070 |
|
31 #define MAC_OS_X_VERSION_10_8_HEX 0x00001080 |
|
32 |
|
33 using namespace mozilla; |
|
34 using namespace mozilla::widget; |
|
35 |
|
36 #ifdef DEBUG |
|
37 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) |
|
38 #endif |
|
39 |
|
40 GfxInfo::GfxInfo() |
|
41 { |
|
42 } |
|
43 |
|
44 static OperatingSystem |
|
45 OSXVersionToOperatingSystem(uint32_t aOSXVersion) |
|
46 { |
|
47 switch (aOSXVersion & MAC_OS_X_VERSION_MAJOR_MASK) { |
|
48 case MAC_OS_X_VERSION_10_6_HEX: |
|
49 return DRIVER_OS_OS_X_10_6; |
|
50 case MAC_OS_X_VERSION_10_7_HEX: |
|
51 return DRIVER_OS_OS_X_10_7; |
|
52 case MAC_OS_X_VERSION_10_8_HEX: |
|
53 return DRIVER_OS_OS_X_10_8; |
|
54 } |
|
55 |
|
56 return DRIVER_OS_UNKNOWN; |
|
57 } |
|
58 // The following three functions are derived from Chromium code |
|
59 static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, |
|
60 CFStringRef propertyName) |
|
61 { |
|
62 return IORegistryEntrySearchCFProperty(dspPort, |
|
63 kIOServicePlane, |
|
64 propertyName, |
|
65 kCFAllocatorDefault, |
|
66 kIORegistryIterateRecursively | |
|
67 kIORegistryIterateParents); |
|
68 } |
|
69 |
|
70 static uint32_t IntValueOfCFData(CFDataRef d) |
|
71 { |
|
72 uint32_t value = 0; |
|
73 |
|
74 if (d) { |
|
75 const uint32_t *vp = reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(d)); |
|
76 if (vp != NULL) |
|
77 value = *vp; |
|
78 } |
|
79 |
|
80 return value; |
|
81 } |
|
82 |
|
83 void |
|
84 GfxInfo::GetDeviceInfo() |
|
85 { |
|
86 io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay); |
|
87 CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id")); |
|
88 if (vendor_id_ref) { |
|
89 mAdapterVendorID.AppendPrintf("0x%4x", IntValueOfCFData((CFDataRef)vendor_id_ref)); |
|
90 CFRelease(vendor_id_ref); |
|
91 } |
|
92 CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id")); |
|
93 if (device_id_ref) { |
|
94 mAdapterDeviceID.AppendPrintf("0x%4x", IntValueOfCFData((CFDataRef)device_id_ref)); |
|
95 CFRelease(device_id_ref); |
|
96 } |
|
97 } |
|
98 |
|
99 nsresult |
|
100 GfxInfo::Init() |
|
101 { |
|
102 nsresult rv = GfxInfoBase::Init(); |
|
103 |
|
104 // Calling CGLQueryRendererInfo causes us to switch to the discrete GPU |
|
105 // even when we don't want to. We'll avoid doing so for now and just |
|
106 // use the device ids. |
|
107 |
|
108 GetDeviceInfo(); |
|
109 |
|
110 AddCrashReportAnnotations(); |
|
111 |
|
112 mOSXVersion = nsCocoaFeatures::OSXVersion(); |
|
113 |
|
114 return rv; |
|
115 } |
|
116 |
|
117 NS_IMETHODIMP |
|
118 GfxInfo::GetD2DEnabled(bool *aEnabled) |
|
119 { |
|
120 return NS_ERROR_FAILURE; |
|
121 } |
|
122 |
|
123 NS_IMETHODIMP |
|
124 GfxInfo::GetDWriteEnabled(bool *aEnabled) |
|
125 { |
|
126 return NS_ERROR_FAILURE; |
|
127 } |
|
128 |
|
129 /* readonly attribute DOMString DWriteVersion; */ |
|
130 NS_IMETHODIMP |
|
131 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) |
|
132 { |
|
133 return NS_ERROR_FAILURE; |
|
134 } |
|
135 |
|
136 /* readonly attribute DOMString cleartypeParameters; */ |
|
137 NS_IMETHODIMP |
|
138 GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams) |
|
139 { |
|
140 return NS_ERROR_FAILURE; |
|
141 } |
|
142 |
|
143 /* readonly attribute DOMString adapterDescription; */ |
|
144 NS_IMETHODIMP |
|
145 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription) |
|
146 { |
|
147 aAdapterDescription.AssignLiteral(""); |
|
148 return NS_OK; |
|
149 } |
|
150 |
|
151 /* readonly attribute DOMString adapterDescription2; */ |
|
152 NS_IMETHODIMP |
|
153 GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription) |
|
154 { |
|
155 return NS_ERROR_FAILURE; |
|
156 } |
|
157 |
|
158 /* readonly attribute DOMString adapterRAM; */ |
|
159 NS_IMETHODIMP |
|
160 GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM) |
|
161 { |
|
162 aAdapterRAM = mAdapterRAMString; |
|
163 return NS_OK; |
|
164 } |
|
165 |
|
166 /* readonly attribute DOMString adapterRAM2; */ |
|
167 NS_IMETHODIMP |
|
168 GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM) |
|
169 { |
|
170 return NS_ERROR_FAILURE; |
|
171 } |
|
172 |
|
173 /* readonly attribute DOMString adapterDriver; */ |
|
174 NS_IMETHODIMP |
|
175 GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver) |
|
176 { |
|
177 aAdapterDriver.AssignLiteral(""); |
|
178 return NS_OK; |
|
179 } |
|
180 |
|
181 /* readonly attribute DOMString adapterDriver2; */ |
|
182 NS_IMETHODIMP |
|
183 GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver) |
|
184 { |
|
185 return NS_ERROR_FAILURE; |
|
186 } |
|
187 |
|
188 /* readonly attribute DOMString adapterDriverVersion; */ |
|
189 NS_IMETHODIMP |
|
190 GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) |
|
191 { |
|
192 aAdapterDriverVersion.AssignLiteral(""); |
|
193 return NS_OK; |
|
194 } |
|
195 |
|
196 /* readonly attribute DOMString adapterDriverVersion2; */ |
|
197 NS_IMETHODIMP |
|
198 GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) |
|
199 { |
|
200 return NS_ERROR_FAILURE; |
|
201 } |
|
202 |
|
203 /* readonly attribute DOMString adapterDriverDate; */ |
|
204 NS_IMETHODIMP |
|
205 GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate) |
|
206 { |
|
207 aAdapterDriverDate.AssignLiteral(""); |
|
208 return NS_OK; |
|
209 } |
|
210 |
|
211 /* readonly attribute DOMString adapterDriverDate2; */ |
|
212 NS_IMETHODIMP |
|
213 GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate) |
|
214 { |
|
215 return NS_ERROR_FAILURE; |
|
216 } |
|
217 |
|
218 /* readonly attribute DOMString adapterVendorID; */ |
|
219 NS_IMETHODIMP |
|
220 GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID) |
|
221 { |
|
222 aAdapterVendorID = mAdapterVendorID; |
|
223 return NS_OK; |
|
224 } |
|
225 |
|
226 /* readonly attribute DOMString adapterVendorID2; */ |
|
227 NS_IMETHODIMP |
|
228 GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID) |
|
229 { |
|
230 return NS_ERROR_FAILURE; |
|
231 } |
|
232 |
|
233 /* readonly attribute DOMString adapterDeviceID; */ |
|
234 NS_IMETHODIMP |
|
235 GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID) |
|
236 { |
|
237 aAdapterDeviceID = mAdapterDeviceID; |
|
238 return NS_OK; |
|
239 } |
|
240 |
|
241 /* readonly attribute DOMString adapterDeviceID2; */ |
|
242 NS_IMETHODIMP |
|
243 GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID) |
|
244 { |
|
245 return NS_ERROR_FAILURE; |
|
246 } |
|
247 |
|
248 /* readonly attribute boolean isGPU2Active; */ |
|
249 NS_IMETHODIMP |
|
250 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) |
|
251 { |
|
252 return NS_ERROR_FAILURE; |
|
253 } |
|
254 |
|
255 void |
|
256 GfxInfo::AddCrashReportAnnotations() |
|
257 { |
|
258 #if defined(MOZ_CRASHREPORTER) |
|
259 nsString deviceID, vendorID; |
|
260 nsAutoCString narrowDeviceID, narrowVendorID; |
|
261 |
|
262 GetAdapterDeviceID(deviceID); |
|
263 CopyUTF16toUTF8(deviceID, narrowDeviceID); |
|
264 GetAdapterVendorID(vendorID); |
|
265 CopyUTF16toUTF8(vendorID, narrowVendorID); |
|
266 |
|
267 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"), |
|
268 narrowVendorID); |
|
269 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"), |
|
270 narrowDeviceID); |
|
271 /* Add an App Note for now so that we get the data immediately. These |
|
272 * can go away after we store the above in the socorro db */ |
|
273 nsAutoCString note; |
|
274 /* AppendPrintf only supports 32 character strings, mrghh. */ |
|
275 note.Append("AdapterVendorID: "); |
|
276 note.Append(narrowVendorID); |
|
277 note.Append(", AdapterDeviceID: "); |
|
278 note.Append(narrowDeviceID); |
|
279 CrashReporter::AppendAppNotesToCrashReport(note); |
|
280 #endif |
|
281 } |
|
282 |
|
283 // We don't support checking driver versions on Mac. |
|
284 #define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn) \ |
|
285 APPEND_TO_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn, \ |
|
286 DRIVER_COMPARISON_IGNORED, V(0,0,0,0), "") |
|
287 |
|
288 |
|
289 const nsTArray<GfxDriverInfo>& |
|
290 GfxInfo::GetGfxDriverInfo() |
|
291 { |
|
292 if (!mDriverInfo->Length()) { |
|
293 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL, |
|
294 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, |
|
295 nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION); |
|
296 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL, |
|
297 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(RadeonX1000), |
|
298 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE); |
|
299 IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL, |
|
300 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(Geforce7300GT), |
|
301 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_BLOCKED_DEVICE); |
|
302 } |
|
303 return *mDriverInfo; |
|
304 } |
|
305 |
|
306 nsresult |
|
307 GfxInfo::GetFeatureStatusImpl(int32_t aFeature, |
|
308 int32_t* aStatus, |
|
309 nsAString& aSuggestedDriverVersion, |
|
310 const nsTArray<GfxDriverInfo>& aDriverInfo, |
|
311 OperatingSystem* aOS /* = nullptr */) |
|
312 { |
|
313 NS_ENSURE_ARG_POINTER(aStatus); |
|
314 aSuggestedDriverVersion.SetIsVoid(true); |
|
315 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; |
|
316 OperatingSystem os = OSXVersionToOperatingSystem(mOSXVersion); |
|
317 if (aOS) |
|
318 *aOS = os; |
|
319 |
|
320 // Don't evaluate special cases when we're evaluating the downloaded blocklist. |
|
321 if (!aDriverInfo.Length()) { |
|
322 if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) { |
|
323 // Blacklist all ATI cards on OSX, except for |
|
324 // 0x6760 and 0x9488 |
|
325 if (mAdapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) && |
|
326 (mAdapterDeviceID.LowerCaseEqualsLiteral("0x6760") || |
|
327 mAdapterDeviceID.LowerCaseEqualsLiteral("0x9488"))) { |
|
328 *aStatus = nsIGfxInfo::FEATURE_NO_INFO; |
|
329 return NS_OK; |
|
330 } |
|
331 } |
|
332 } |
|
333 |
|
334 return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os); |
|
335 } |
|
336 |
|
337 #ifdef DEBUG |
|
338 |
|
339 // Implement nsIGfxInfoDebug |
|
340 |
|
341 /* void spoofVendorID (in DOMString aVendorID); */ |
|
342 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) |
|
343 { |
|
344 mAdapterVendorID = aVendorID; |
|
345 return NS_OK; |
|
346 } |
|
347 |
|
348 /* void spoofDeviceID (in unsigned long aDeviceID); */ |
|
349 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) |
|
350 { |
|
351 mAdapterDeviceID = aDeviceID; |
|
352 return NS_OK; |
|
353 } |
|
354 |
|
355 /* void spoofDriverVersion (in DOMString aDriverVersion); */ |
|
356 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) |
|
357 { |
|
358 mDriverVersion = aDriverVersion; |
|
359 return NS_OK; |
|
360 } |
|
361 |
|
362 /* void spoofOSVersion (in unsigned long aVersion); */ |
|
363 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) |
|
364 { |
|
365 mOSXVersion = aVersion; |
|
366 return NS_OK; |
|
367 } |
|
368 |
|
369 #endif |