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__
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
17 #define APPEND_TO_DRIVER_BLOCKLIST_EXT( \
18 os, screen, battery, desktopEnv, windowProtocol, driverVendor, devices, \
19 feature, featureStatus, driverComparator, driverVersion, ruleId, \
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, \
31 #define APPEND_TO_DRIVER_BLOCKLIST(os, devices, feature, featureStatus, \
32 driverComparator, driverVersion, ruleId, \
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) \
63 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
64 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
65 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
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, \
75 info.mDriverVersionMax = driverVersionMax; \
76 sDriverInfo->AppendElement(info); \
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, \
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) \
93 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
94 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
95 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
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); \
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, \
121 enum class OperatingSystem
: uint8_t {
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 {
182 IntelHDGraphicsToIvyBridge
,
183 IntelHDGraphicsToSandyBridge
,
187 IntelMobileHDGraphics
,
188 NvidiaBlockD3D9Layers
,
200 NvidiaBlockWebRender
,
201 NvidiaRolloutWebRender
,
202 IntelRolloutWebRender
,
203 IntelModernRolloutWebRender
,
209 enum class DeviceVendor
: uint8_t {
210 All
, // There is an assumption that this is the first enum
227 enum DriverVendor
: uint8_t {
228 All
, // There is an assumption that this is the first enum
229 // Wildcard for all Mesa drivers.
231 // Note that the following list of Mesa drivers is not comprehensive; we pull
232 // the DRI driver at runtime. These drivers are provided for convenience when
233 // populating the local blocklist.
239 // Nouveau: Open-source nvidia
241 // A generic ID to be provided when we can't determine the DRI driver on Mesa.
243 // Wildcard for all non-Mesa drivers.
245 // Wildcard for all hardware Mesa drivers.
247 // Wildcard for all software Mesa drivers.
253 enum class DesktopEnvironment
: uint8_t {
254 All
, // There is an assumption that this is the first enum
274 enum class WindowProtocol
: uint8_t {
275 All
, // There is an assumption that this is the first enum
280 // Wildcard for all Wayland variants, excluding XWayland.
282 // Wildcard for all X11 variants, including XWayland.
287 enum class BatteryStatus
: uint8_t { All
, Present
, None
};
289 enum class ScreenSizeStatus
: uint8_t {
291 Small
, // <= 1900x1200
292 SmallAndMedium
, // <= 3440x1440
293 Medium
, // <= 3440x1440 && > 1900x1200
294 MediumAndLarge
, // >1900x1200
298 /* Array of devices to match, or an empty array for all devices */
299 class GfxDeviceFamily final
{
301 GfxDeviceFamily() = default;
303 void Append(const nsAString
& aDeviceId
);
304 void AppendRange(int32_t aBeginDeviceId
, int32_t aEndDeviceId
);
306 bool IsEmpty() const { return mIds
.IsEmpty() && mRanges
.IsEmpty(); }
308 nsresult
Contains(nsAString
& aDeviceId
) const;
316 CopyableTArray
<nsString
> mIds
;
317 CopyableTArray
<DeviceRange
> mRanges
;
320 struct GfxDriverInfo
{
321 // If |ownDevices| is true, you are transferring ownership of the devices
322 // array, and it will be deleted when this GfxDriverInfo is destroyed.
323 GfxDriverInfo(OperatingSystem os
, ScreenSizeStatus aScreen
,
324 BatteryStatus aBattery
, const nsAString
& desktopEnv
,
325 const nsAString
& windowProtocol
, const nsAString
& vendor
,
326 const nsAString
& driverVendor
, GfxDeviceFamily
* devices
,
327 int32_t feature
, int32_t featureStatus
, VersionComparisonOp op
,
328 uint64_t driverVersion
, const char* ruleId
,
329 const char* suggestedVersion
= nullptr, bool ownDevices
= false,
333 GfxDriverInfo(const GfxDriverInfo
&);
336 OperatingSystem mOperatingSystem
;
337 uint32_t mOperatingSystemVersion
;
338 ScreenSizeStatus mScreen
;
339 BatteryStatus mBattery
;
340 nsString mDesktopEnvironment
;
341 nsString mWindowProtocol
;
343 nsString mAdapterVendor
;
344 nsString mDriverVendor
;
346 const GfxDeviceFamily
* mDevices
;
348 // Whether the mDevices array should be deleted when this structure is
349 // deallocated. False by default.
352 /* A feature from nsIGfxInfo, or all features */
354 static int32_t allFeatures
;
356 /* A feature status from nsIGfxInfo */
357 int32_t mFeatureStatus
;
359 VersionComparisonOp mComparisonOp
;
361 /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
362 uint64_t mDriverVersion
;
363 uint64_t mDriverVersionMax
;
364 static uint64_t allDriverVersions
;
366 const char* mSuggestedVersion
;
369 static const GfxDeviceFamily
* GetDeviceFamily(DeviceFamily id
);
370 static GfxDeviceFamily
*
371 sDeviceFamilies
[static_cast<size_t>(DeviceFamily::Max
)];
373 static const nsAString
& GetDesktopEnvironment(DesktopEnvironment id
);
375 sDesktopEnvironment
[static_cast<size_t>(DesktopEnvironment::Max
)];
377 static const nsAString
& GetWindowProtocol(WindowProtocol id
);
378 static nsAString
* sWindowProtocol
[static_cast<size_t>(WindowProtocol::Max
)];
380 static const nsAString
& GetDeviceVendor(DeviceVendor id
);
381 static const nsAString
& GetDeviceVendor(DeviceFamily id
);
382 static nsAString
* sDeviceVendors
[static_cast<size_t>(DeviceVendor::Max
)];
384 static const nsAString
& GetDriverVendor(DriverVendor id
);
385 static nsAString
* sDriverVendors
[static_cast<size_t>(DriverVendor::Max
)];
387 nsString mModel
, mHardware
, mProduct
, mManufacturer
;
392 #define GFX_DRIVER_VERSION(a, b, c, d) \
393 ((uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) | \
396 inline uint64_t V(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t d
) {
397 // We make sure every driver number is padded by 0s, this will allow us the
398 // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
399 // more extensive explanation of this approach.
400 while (b
> 0 && b
< 1000) {
403 while (c
> 0 && c
< 1000) {
406 while (d
> 0 && d
< 1000) {
409 return GFX_DRIVER_VERSION(a
, b
, c
, d
);
412 // All destination string storage needs to have at least 5 bytes available.
413 inline bool SplitDriverVersion(const char* aSource
, char* aAStr
, char* aBStr
,
414 char* aCStr
, char* aDStr
) {
415 // sscanf doesn't do what we want here to we parse this manually.
416 int len
= strlen(aSource
);
418 // This "4" is hardcoded in a few places, including once as a 3.
419 char* dest
[4] = {aAStr
, aBStr
, aCStr
, aDStr
};
420 unsigned destIdx
= 0;
421 unsigned destPos
= 0;
423 for (int i
= 0; i
< len
; i
++) {
425 // Invalid format found. Ensure we don't access dest beyond bounds.
429 if (aSource
[i
] == '.') {
430 MOZ_ASSERT(destIdx
< 4 && destPos
<= 4);
431 dest
[destIdx
++][destPos
] = 0;
437 // Ignore more than 4 chars. Ensure we never access dest[destIdx]
438 // beyond its bounds.
442 MOZ_ASSERT(destIdx
< 4 && destPos
< 4);
443 dest
[destIdx
][destPos
++] = aSource
[i
];
446 // Take care of the trailing period
451 // Add last terminator.
452 MOZ_ASSERT(destIdx
< 4 && destPos
<= 4);
453 dest
[destIdx
][destPos
] = 0;
461 // This allows us to pad driver version 'substrings' with 0s, this
462 // effectively allows us to treat the version numbers as 'decimals'. This is
463 // a little strange but this method seems to do the right thing for all
464 // different vendor's driver strings. i.e. .98 will become 9800, which is
465 // larger than .978 which would become 9780.
466 inline void PadDriverDecimal(char* aString
) {
467 for (int i
= 0; i
< 4; i
++) {
469 for (int c
= i
; c
< 4; c
++) {
478 inline bool ParseDriverVersion(const nsAString
& aVersion
,
479 uint64_t* aNumericVersion
) {
480 *aNumericVersion
= 0;
482 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
484 char aStr
[8], bStr
[8], cStr
[8], dStr
[8];
485 /* honestly, why do I even bother */
486 if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion
).get(), aStr
,
490 PadDriverDecimal(bStr
);
491 PadDriverDecimal(cStr
);
492 PadDriverDecimal(dStr
);
499 if (a
< 0 || a
> 0xffff) return false;
500 if (b
< 0 || b
> 0xffff) return false;
501 if (c
< 0 || c
> 0xffff) return false;
502 if (d
< 0 || d
> 0xffff) return false;
504 *aNumericVersion
= GFX_DRIVER_VERSION(a
, b
, c
, d
);
505 MOZ_ASSERT(*aNumericVersion
!= GfxDriverInfo::allDriverVersions
);
507 #elif defined(ANDROID)
508 // Can't use aVersion.ToInteger() because that's not compiled into our code
509 // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
510 *aNumericVersion
= atoi(NS_LossyConvertUTF16toASCII(aVersion
).get());
511 MOZ_ASSERT(*aNumericVersion
!= GfxDriverInfo::allDriverVersions
);
518 } // namespace widget
519 } // namespace mozilla
521 #endif /*__mozilla_widget_GfxDriverInfo_h__ */