Bug 1643246 - Don't use attribute selectors for determining if a select is a drop...
[gecko.git] / widget / GfxDriverInfo.h
bloba5ee3bb25326e5dd0e1ca35fa9b2695a681103b8
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 Android,
150 enum VersionComparisonOp {
151 DRIVER_LESS_THAN, // driver < version
152 DRIVER_BUILD_ID_LESS_THAN, // driver build id < version
153 DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
154 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, // driver build id <= version
155 DRIVER_GREATER_THAN, // driver > version
156 DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
157 DRIVER_EQUAL, // driver == version
158 DRIVER_NOT_EQUAL, // driver != version
159 DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
160 DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
161 DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
162 DRIVER_COMPARISON_IGNORED
165 enum class DeviceFamily : uint8_t {
166 All,
167 IntelAll,
168 NvidiaAll,
169 AtiAll,
170 MicrosoftAll,
171 ParallelsAll,
172 QualcommAll,
173 IntelGMA500,
174 IntelGMA900,
175 IntelGMA950,
176 IntelGMA3150,
177 IntelGMAX3000,
178 IntelGMAX4500HD,
179 IntelHDGraphicsToIvyBridge,
180 IntelHDGraphicsToSandyBridge,
181 IntelHaswell,
182 IntelHD3000,
183 IntelHD520,
184 IntelMobileHDGraphics,
185 NvidiaBlockD3D9Layers,
186 RadeonX1000,
187 RadeonCaicos,
188 Geforce7300GT,
189 Nvidia310M,
190 Nvidia8800GTS,
191 Bug1137716,
192 Bug1116812,
193 Bug1155608,
194 Bug1207665,
195 Bug1447141,
196 NvidiaBlockWebRender,
197 NvidiaRolloutWebRender,
198 IntelRolloutWebRender,
199 IntelModernRolloutWebRender,
200 AtiRolloutWebRender,
205 enum class DeviceVendor : uint8_t {
206 All, // There is an assumption that this is the first enum
207 Intel,
208 NVIDIA,
209 ATI,
210 Microsoft,
211 Parallels,
212 VMWare,
213 VirtualBox,
214 Qualcomm,
215 MicrosoftBasic,
216 MicrosoftHyperV,
221 enum DriverVendor : uint8_t {
222 All, // There is an assumption that this is the first enum
223 // Wildcard for all Mesa drivers.
224 MesaAll,
225 // Note that the following list of Mesa drivers is not comprehensive; we pull
226 // the DRI driver at runtime. These drivers are provided for convenience when
227 // populating the local blocklist.
228 MesaLLVMPipe,
229 MesaSoftPipe,
230 MesaSWRast,
231 // A generic ID to be provided when we can't determine the DRI driver on Mesa.
232 MesaUnknown,
233 // Wildcard for all non-Mesa drivers.
234 NonMesaAll,
239 enum class DesktopEnvironment : uint8_t {
240 All, // There is an assumption that this is the first enum
241 GNOME,
242 KDE,
243 XFCE,
244 Cinnamon,
245 Enlightenment,
246 LXDE,
247 Openbox,
249 Mate,
250 Unity,
251 Pantheon,
252 LXQT,
253 Deepin,
254 Dwm,
255 Budgie,
256 Unknown,
260 enum class WindowProtocol : uint8_t {
261 All, // There is an assumption that this is the first enum
262 X11,
263 XWayland,
264 Wayland,
265 WaylandDRM,
266 // Wildcard for all Wayland variants, excluding XWayland.
267 WaylandAll,
268 // Wildcard for all X11 variants, including XWayland.
269 X11All,
273 enum class BatteryStatus : uint8_t { All, Present, None };
275 enum class ScreenSizeStatus : uint8_t {
276 All,
277 Small, // <= 1900x1200
278 SmallAndMedium, // <= 3440x1440
279 Medium, // <= 3440x1440 && > 1900x1200
280 MediumAndLarge, // >1900x1200
281 Large // > 3440x1440
284 /* Array of devices to match, or an empty array for all devices */
285 class GfxDeviceFamily final {
286 public:
287 GfxDeviceFamily() = default;
289 void Append(const nsAString& aDeviceId);
290 void AppendRange(int32_t aBeginDeviceId, int32_t aEndDeviceId);
292 bool IsEmpty() const { return mIds.IsEmpty() && mRanges.IsEmpty(); }
294 nsresult Contains(nsAString& aDeviceId) const;
296 private:
297 struct DeviceRange {
298 int32_t mBegin;
299 int32_t mEnd;
302 CopyableTArray<nsString> mIds;
303 CopyableTArray<DeviceRange> mRanges;
306 struct GfxDriverInfo {
307 // If |ownDevices| is true, you are transferring ownership of the devices
308 // array, and it will be deleted when this GfxDriverInfo is destroyed.
309 GfxDriverInfo(OperatingSystem os, ScreenSizeStatus aScreen,
310 BatteryStatus aBattery, const nsAString& desktopEnv,
311 const nsAString& windowProtocol, const nsAString& vendor,
312 const nsAString& driverVendor, GfxDeviceFamily* devices,
313 int32_t feature, int32_t featureStatus, VersionComparisonOp op,
314 uint64_t driverVersion, const char* ruleId,
315 const char* suggestedVersion = nullptr, bool ownDevices = false,
316 bool gpu2 = false);
318 GfxDriverInfo();
319 GfxDriverInfo(const GfxDriverInfo&);
320 ~GfxDriverInfo();
322 OperatingSystem mOperatingSystem;
323 uint32_t mOperatingSystemVersion;
324 ScreenSizeStatus mScreen;
325 BatteryStatus mBattery;
326 nsString mDesktopEnvironment;
327 nsString mWindowProtocol;
329 nsString mAdapterVendor;
330 nsString mDriverVendor;
332 const GfxDeviceFamily* mDevices;
334 // Whether the mDevices array should be deleted when this structure is
335 // deallocated. False by default.
336 bool mDeleteDevices;
338 /* A feature from nsIGfxInfo, or all features */
339 int32_t mFeature;
340 static int32_t allFeatures;
342 /* A feature status from nsIGfxInfo */
343 int32_t mFeatureStatus;
345 VersionComparisonOp mComparisonOp;
347 /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
348 uint64_t mDriverVersion;
349 uint64_t mDriverVersionMax;
350 static uint64_t allDriverVersions;
352 const char* mSuggestedVersion;
353 nsCString mRuleId;
355 static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
356 static GfxDeviceFamily*
357 sDeviceFamilies[static_cast<size_t>(DeviceFamily::Max)];
359 static const nsAString& GetDesktopEnvironment(DesktopEnvironment id);
360 static nsAString*
361 sDesktopEnvironment[static_cast<size_t>(DesktopEnvironment::Max)];
363 static const nsAString& GetWindowProtocol(WindowProtocol id);
364 static nsAString* sWindowProtocol[static_cast<size_t>(WindowProtocol::Max)];
366 static const nsAString& GetDeviceVendor(DeviceVendor id);
367 static const nsAString& GetDeviceVendor(DeviceFamily id);
368 static nsAString* sDeviceVendors[static_cast<size_t>(DeviceVendor::Max)];
370 static const nsAString& GetDriverVendor(DriverVendor id);
371 static nsAString* sDriverVendors[static_cast<size_t>(DriverVendor::Max)];
373 nsString mModel, mHardware, mProduct, mManufacturer;
375 bool mGpu2;
378 #define GFX_DRIVER_VERSION(a, b, c, d) \
379 ((uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) | \
380 uint64_t(d))
382 inline uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
383 // We make sure every driver number is padded by 0s, this will allow us the
384 // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
385 // more extensive explanation of this approach.
386 while (b > 0 && b < 1000) {
387 b *= 10;
389 while (c > 0 && c < 1000) {
390 c *= 10;
392 while (d > 0 && d < 1000) {
393 d *= 10;
395 return GFX_DRIVER_VERSION(a, b, c, d);
398 // All destination string storage needs to have at least 5 bytes available.
399 inline bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr,
400 char* aCStr, char* aDStr) {
401 // sscanf doesn't do what we want here to we parse this manually.
402 int len = strlen(aSource);
404 // This "4" is hardcoded in a few places, including once as a 3.
405 char* dest[4] = {aAStr, aBStr, aCStr, aDStr};
406 unsigned destIdx = 0;
407 unsigned destPos = 0;
409 for (int i = 0; i < len; i++) {
410 if (destIdx >= 4) {
411 // Invalid format found. Ensure we don't access dest beyond bounds.
412 return false;
415 if (aSource[i] == '.') {
416 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
417 dest[destIdx++][destPos] = 0;
418 destPos = 0;
419 continue;
422 if (destPos > 3) {
423 // Ignore more than 4 chars. Ensure we never access dest[destIdx]
424 // beyond its bounds.
425 continue;
428 MOZ_ASSERT(destIdx < 4 && destPos < 4);
429 dest[destIdx][destPos++] = aSource[i];
432 // Take care of the trailing period
433 if (destIdx >= 4) {
434 return false;
437 // Add last terminator.
438 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
439 dest[destIdx][destPos] = 0;
441 if (destIdx != 3) {
442 return false;
444 return true;
447 // This allows us to pad driver version 'substrings' with 0s, this
448 // effectively allows us to treat the version numbers as 'decimals'. This is
449 // a little strange but this method seems to do the right thing for all
450 // different vendor's driver strings. i.e. .98 will become 9800, which is
451 // larger than .978 which would become 9780.
452 inline void PadDriverDecimal(char* aString) {
453 for (int i = 0; i < 4; i++) {
454 if (!aString[i]) {
455 for (int c = i; c < 4; c++) {
456 aString[c] = '0';
458 break;
461 aString[4] = 0;
464 inline bool ParseDriverVersion(const nsAString& aVersion,
465 uint64_t* aNumericVersion) {
466 *aNumericVersion = 0;
468 #if defined(XP_WIN) || defined(MOZ_X11)
469 int a, b, c, d;
470 char aStr[8], bStr[8], cStr[8], dStr[8];
471 /* honestly, why do I even bother */
472 if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr,
473 bStr, cStr, dStr))
474 return false;
476 PadDriverDecimal(bStr);
477 PadDriverDecimal(cStr);
478 PadDriverDecimal(dStr);
480 a = atoi(aStr);
481 b = atoi(bStr);
482 c = atoi(cStr);
483 d = atoi(dStr);
485 if (a < 0 || a > 0xffff) return false;
486 if (b < 0 || b > 0xffff) return false;
487 if (c < 0 || c > 0xffff) return false;
488 if (d < 0 || d > 0xffff) return false;
490 *aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
491 MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
492 return true;
493 #elif defined(ANDROID)
494 // Can't use aVersion.ToInteger() because that's not compiled into our code
495 // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
496 *aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
497 MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
498 return true;
499 #else
500 return false;
501 #endif
504 } // namespace widget
505 } // namespace mozilla
507 #endif /*__mozilla_widget_GfxDriverInfo_h__ */