Bug 1761003 [wpt PR 33324] - Add comment pointing to followup bug, and fix typos...
[gecko.git] / widget / GfxDriverInfo.h
blob9b41a7ec150ec10c354102db409cd68eb7142bf4
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/. */
6 #ifndef __mozilla_widget_GfxDriverInfo_h__
7 #define __mozilla_widget_GfxDriverInfo_h__
9 #include "nsString.h"
10 #include "nsTArray.h"
12 // Macros for adding a blocklist item to the static list. _EXT variants
13 // allow one to specify all available parameters, including those available
14 // only on specific platforms (e.g. desktop environment and driver vendor
15 // for Linux.)
17 #define APPEND_TO_DRIVER_BLOCKLIST_EXT( \
18 os, screen, battery, desktopEnv, windowProtocol, driverVendor, devices, \
19 feature, featureStatus, driverComparator, driverVersion, ruleId, \
20 suggestedVersion) \
21 sDriverInfo->AppendElement(GfxDriverInfo( \
22 os, screen, battery, \
23 (nsAString&)GfxDriverInfo::GetDesktopEnvironment(desktopEnv), \
24 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
25 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
26 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
27 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
28 featureStatus, driverComparator, driverVersion, ruleId, \
29 suggestedVersion))
31 #define APPEND_TO_DRIVER_BLOCKLIST(os, devices, feature, featureStatus, \
32 driverComparator, driverVersion, ruleId, \
33 suggestedVersion) \
34 APPEND_TO_DRIVER_BLOCKLIST_EXT( \
35 os, ScreenSizeStatus::All, BatteryStatus::All, DesktopEnvironment::All, \
36 WindowProtocol::All, DriverVendor::All, devices, feature, featureStatus, \
37 driverComparator, driverVersion, ruleId, suggestedVersion)
39 #define APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
40 os, screen, battery, desktopEnv, windowProtocol, driverVendor, devices, \
41 feature, featureStatus, driverComparator, driverVersion, ruleId) \
42 sDriverInfo->AppendElement(GfxDriverInfo( \
43 os, screen, battery, \
44 (nsAString&)GfxDriverInfo::GetDesktopEnvironment(desktopEnv), \
45 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
46 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
47 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
48 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
49 featureStatus, driverComparator, driverVersion, ruleId))
51 #define APPEND_TO_DRIVER_BLOCKLIST2(os, devices, feature, featureStatus, \
52 driverComparator, driverVersion, ruleId) \
53 APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
54 os, ScreenSizeStatus::All, BatteryStatus::All, DesktopEnvironment::All, \
55 WindowProtocol::All, DriverVendor::All, devices, feature, featureStatus, \
56 driverComparator, driverVersion, ruleId)
58 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
59 os, screen, battery, desktopEnv, windowProtocol, driverVendor, devices, \
60 feature, featureStatus, driverComparator, driverVersion, driverVersionMax, \
61 ruleId, suggestedVersion) \
62 do { \
63 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
64 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
65 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
66 GfxDriverInfo info( \
67 os, screen, battery, \
68 (nsAString&)GfxDriverInfo::GetDesktopEnvironment(desktopEnv), \
69 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
70 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
71 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
72 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
73 featureStatus, driverComparator, driverVersion, ruleId, \
74 suggestedVersion); \
75 info.mDriverVersionMax = driverVersionMax; \
76 sDriverInfo->AppendElement(info); \
77 } while (false)
79 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE( \
80 os, devices, feature, featureStatus, driverComparator, driverVersion, \
81 driverVersionMax, ruleId, suggestedVersion) \
82 APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
83 os, ScreenSizeStatus::All, BatteryStatus::All, DesktopEnvironment::All, \
84 WindowProtocol::All, DriverVendor::All, devices, feature, featureStatus, \
85 driverComparator, driverVersion, driverVersionMax, ruleId, \
86 suggestedVersion)
88 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
89 os, screen, battery, desktopEnv, windowProtocol, driverVendor, devices, \
90 feature, featureStatus, driverComparator, driverVersion, driverVersionMax, \
91 ruleId, suggestedVersion) \
92 do { \
93 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
94 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
95 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
96 GfxDriverInfo info( \
97 os, screen, battery, \
98 (nsAString&)GfxDriverInfo::GetDesktopEnvironment(desktopEnv), \
99 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
100 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
101 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
102 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
103 featureStatus, driverComparator, driverVersion, ruleId, \
104 suggestedVersion, false, true); \
105 info.mDriverVersionMax = driverVersionMax; \
106 sDriverInfo->AppendElement(info); \
107 } while (false)
109 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2( \
110 os, devices, feature, featureStatus, driverComparator, driverVersion, \
111 driverVersionMax, ruleId, suggestedVersion) \
112 APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
113 os, ScreenSizeStatus::All, BatteryStatus::All, DesktopEnvironment::All, \
114 WindowProtocol::All, DriverVendor::All, devices, feature, featureStatus, \
115 driverComparator, driverVersion, driverVersionMax, ruleId, \
116 suggestedVersion)
118 namespace mozilla {
119 namespace widget {
121 enum class OperatingSystem : uint8_t {
122 Unknown,
123 Windows,
124 WindowsXP,
125 WindowsServer2003,
126 WindowsVista,
127 Windows7,
128 Windows8,
129 Windows8_1,
130 Windows10,
131 RecentWindows10,
132 NotRecentWindows10,
133 Linux,
134 OSX,
135 OSX10_5,
136 OSX10_6,
137 OSX10_7,
138 OSX10_8,
139 OSX10_9,
140 OSX10_10,
141 OSX10_11,
142 OSX10_12,
143 OSX10_13,
144 OSX10_14,
145 OSX10_15,
146 OSX11_0,
147 Android,
151 enum VersionComparisonOp {
152 DRIVER_LESS_THAN, // driver < version
153 DRIVER_BUILD_ID_LESS_THAN, // driver build id < version
154 DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
155 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, // driver build id <= version
156 DRIVER_GREATER_THAN, // driver > version
157 DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
158 DRIVER_EQUAL, // driver == version
159 DRIVER_NOT_EQUAL, // driver != version
160 DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
161 DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
162 DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
163 DRIVER_COMPARISON_IGNORED
166 enum class DeviceFamily : uint8_t {
167 All,
168 IntelAll,
169 NvidiaAll,
170 AtiAll,
171 MicrosoftAll,
172 ParallelsAll,
173 QualcommAll,
174 AppleAll,
175 AmazonAll,
176 IntelGMA500,
177 IntelGMA900,
178 IntelGMA950,
179 IntelGMA3150,
180 IntelGMAX3000,
181 IntelGMAX4500HD,
182 IntelHDGraphicsToIvyBridge,
183 IntelHDGraphicsToSandyBridge,
184 IntelHaswell,
185 IntelSandyBridge,
186 IntelGen7Baytrail,
187 IntelHD520,
188 IntelMobileHDGraphics,
189 NvidiaBlockD3D9Layers,
190 RadeonX1000,
191 RadeonCaicos,
192 Geforce7300GT,
193 Nvidia310M,
194 Nvidia8800GTS,
195 Bug1137716,
196 Bug1116812,
197 Bug1155608,
198 Bug1207665,
199 Bug1447141,
200 AmdR600,
201 NvidiaRolloutWebRender,
202 IntelRolloutWebRender,
203 IntelModernRolloutWebRender,
204 IntelWebRenderBlocked,
205 NvidiaWebRenderBlocked,
206 AtiRolloutWebRender,
211 enum class DeviceVendor : uint8_t {
212 All, // There is an assumption that this is the first enum
213 Intel,
214 NVIDIA,
215 ATI,
216 Microsoft,
217 Parallels,
218 VMWare,
219 VirtualBox,
220 Qualcomm,
221 MicrosoftBasic,
222 MicrosoftHyperV,
223 Apple,
224 Amazon,
229 enum DriverVendor : uint8_t {
230 All, // There is an assumption that this is the first enum
231 // Wildcard for all Mesa drivers.
232 MesaAll,
233 // Note that the following list of Mesa drivers is not comprehensive; we pull
234 // the DRI driver at runtime. These drivers are provided for convenience when
235 // populating the local blocklist.
236 MesaLLVMPipe,
237 MesaSoftPipe,
238 MesaSWRast,
239 MesaSWUnknown,
240 // AMD
241 MesaR600,
242 // Nouveau: Open-source nvidia
243 MesaNouveau,
244 // A generic ID to be provided when we can't determine the DRI driver on Mesa.
245 MesaUnknown,
246 // Wildcard for all non-Mesa drivers.
247 NonMesaAll,
248 // Wildcard for all hardware Mesa drivers.
249 HardwareMesaAll,
250 // Wildcard for all software Mesa drivers.
251 SoftwareMesaAll,
256 enum class DesktopEnvironment : uint8_t {
257 All, // There is an assumption that this is the first enum
258 GNOME,
259 KDE,
260 XFCE,
261 Cinnamon,
262 Enlightenment,
263 LXDE,
264 Openbox,
266 Mate,
267 Unity,
268 Pantheon,
269 LXQT,
270 Deepin,
271 Dwm,
272 Budgie,
273 Sway,
274 Unknown,
278 enum class WindowProtocol : uint8_t {
279 All, // There is an assumption that this is the first enum
280 X11,
281 XWayland,
282 Wayland,
283 WaylandDRM,
284 // Wildcard for all Wayland variants, excluding XWayland.
285 WaylandAll,
286 // Wildcard for all X11 variants, including XWayland.
287 X11All,
291 enum class BatteryStatus : uint8_t { All, Present, None };
293 enum class ScreenSizeStatus : uint8_t {
294 All,
295 Small, // <= 1900x1200
296 SmallAndMedium, // <= 3440x1440
297 Medium, // <= 3440x1440 && > 1900x1200
298 MediumAndLarge, // >1900x1200
299 Large // > 3440x1440
302 /* Array of devices to match, or an empty array for all devices */
303 class GfxDeviceFamily final {
304 public:
305 GfxDeviceFamily() = default;
307 void Append(const nsAString& aDeviceId);
308 void AppendRange(int32_t aBeginDeviceId, int32_t aEndDeviceId);
310 bool IsEmpty() const { return mIds.IsEmpty() && mRanges.IsEmpty(); }
312 nsresult Contains(nsAString& aDeviceId) const;
314 private:
315 struct DeviceRange {
316 int32_t mBegin;
317 int32_t mEnd;
320 CopyableTArray<nsString> mIds;
321 CopyableTArray<DeviceRange> mRanges;
324 struct GfxDriverInfo {
325 // If |ownDevices| is true, you are transferring ownership of the devices
326 // array, and it will be deleted when this GfxDriverInfo is destroyed.
327 GfxDriverInfo(OperatingSystem os, ScreenSizeStatus aScreen,
328 BatteryStatus aBattery, const nsAString& desktopEnv,
329 const nsAString& windowProtocol, const nsAString& vendor,
330 const nsAString& driverVendor, GfxDeviceFamily* devices,
331 int32_t feature, int32_t featureStatus, VersionComparisonOp op,
332 uint64_t driverVersion, const char* ruleId,
333 const char* suggestedVersion = nullptr, bool ownDevices = false,
334 bool gpu2 = false);
336 GfxDriverInfo();
337 GfxDriverInfo(const GfxDriverInfo&);
338 ~GfxDriverInfo();
340 OperatingSystem mOperatingSystem;
341 uint32_t mOperatingSystemVersion;
342 ScreenSizeStatus mScreen;
343 BatteryStatus mBattery;
344 nsString mDesktopEnvironment;
345 nsString mWindowProtocol;
347 nsString mAdapterVendor;
348 nsString mDriverVendor;
350 const GfxDeviceFamily* mDevices;
352 // Whether the mDevices array should be deleted when this structure is
353 // deallocated. False by default.
354 bool mDeleteDevices;
356 /* A feature from nsIGfxInfo, or all features */
357 int32_t mFeature;
358 static int32_t allFeatures;
360 /* A feature status from nsIGfxInfo */
361 int32_t mFeatureStatus;
363 VersionComparisonOp mComparisonOp;
365 /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
366 uint64_t mDriverVersion;
367 uint64_t mDriverVersionMax;
368 static uint64_t allDriverVersions;
370 const char* mSuggestedVersion;
371 nsCString mRuleId;
373 static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
374 static GfxDeviceFamily*
375 sDeviceFamilies[static_cast<size_t>(DeviceFamily::Max)];
377 static const nsAString& GetDesktopEnvironment(DesktopEnvironment id);
378 static nsAString*
379 sDesktopEnvironment[static_cast<size_t>(DesktopEnvironment::Max)];
381 static const nsAString& GetWindowProtocol(WindowProtocol id);
382 static nsAString* sWindowProtocol[static_cast<size_t>(WindowProtocol::Max)];
384 static const nsAString& GetDeviceVendor(DeviceVendor id);
385 static const nsAString& GetDeviceVendor(DeviceFamily id);
386 static nsAString* sDeviceVendors[static_cast<size_t>(DeviceVendor::Max)];
388 static const nsAString& GetDriverVendor(DriverVendor id);
389 static nsAString* sDriverVendors[static_cast<size_t>(DriverVendor::Max)];
391 nsString mModel, mHardware, mProduct, mManufacturer;
393 bool mGpu2;
396 inline uint64_t DriverVersion(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
397 return (uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) |
398 uint64_t(d);
401 inline uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
402 #ifdef XP_WIN
403 // We make sure every driver number is padded by 0s, this will allow us the
404 // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
405 // more extensive explanation of this approach.
406 while (b > 0 && b < 1000) {
407 b *= 10;
409 while (c > 0 && c < 1000) {
410 c *= 10;
412 while (d > 0 && d < 1000) {
413 d *= 10;
415 #endif
416 return DriverVersion(a, b, c, d);
419 // All destination string storage needs to have at least 5 bytes available.
420 inline bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr,
421 char* aCStr, char* aDStr) {
422 // sscanf doesn't do what we want here to we parse this manually.
423 int len = strlen(aSource);
425 // This "4" is hardcoded in a few places, including once as a 3.
426 char* dest[4] = {aAStr, aBStr, aCStr, aDStr};
427 unsigned destIdx = 0;
428 unsigned destPos = 0;
430 for (int i = 0; i < len; i++) {
431 if (destIdx >= 4) {
432 // Invalid format found. Ensure we don't access dest beyond bounds.
433 return false;
436 if (aSource[i] == '.') {
437 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
438 dest[destIdx++][destPos] = 0;
439 destPos = 0;
440 continue;
443 if (destPos > 3) {
444 // Ignore more than 4 chars. Ensure we never access dest[destIdx]
445 // beyond its bounds.
446 continue;
449 MOZ_ASSERT(destIdx < 4 && destPos < 4);
450 dest[destIdx][destPos++] = aSource[i];
453 // Take care of the trailing period
454 if (destIdx >= 4) {
455 return false;
458 // Add last terminator.
459 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
460 dest[destIdx][destPos] = 0;
462 if (destIdx != 3) {
463 return false;
465 return true;
468 // This allows us to pad driver version 'substrings' with 0s, this
469 // effectively allows us to treat the version numbers as 'decimals'. This is
470 // a little strange but this method seems to do the right thing for all
471 // different vendor's driver strings. i.e. .98 will become 9800, which is
472 // larger than .978 which would become 9780.
473 inline void PadDriverDecimal(char* aString) {
474 for (int i = 0; i < 4; i++) {
475 if (!aString[i]) {
476 for (int c = i; c < 4; c++) {
477 aString[c] = '0';
479 break;
482 aString[4] = 0;
485 inline bool ParseDriverVersion(const nsAString& aVersion,
486 uint64_t* aNumericVersion) {
487 *aNumericVersion = 0;
489 #ifndef ANDROID
490 int a, b, c, d;
491 char aStr[8], bStr[8], cStr[8], dStr[8];
492 /* honestly, why do I even bother */
493 if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr,
494 bStr, cStr, dStr))
495 return false;
497 # ifdef XP_WIN
498 PadDriverDecimal(bStr);
499 PadDriverDecimal(cStr);
500 PadDriverDecimal(dStr);
501 # endif
503 a = atoi(aStr);
504 b = atoi(bStr);
505 c = atoi(cStr);
506 d = atoi(dStr);
508 if (a < 0 || a > 0xffff) return false;
509 if (b < 0 || b > 0xffff) return false;
510 if (c < 0 || c > 0xffff) return false;
511 if (d < 0 || d > 0xffff) return false;
513 *aNumericVersion = DriverVersion(a, b, c, d);
514 #else
515 // Can't use aVersion.ToInteger() because that's not compiled into our code
516 // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
517 *aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
518 #endif
519 MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
520 return true;
523 } // namespace widget
524 } // namespace mozilla
526 #endif /*__mozilla_widget_GfxDriverInfo_h__ */