Bug 1931748. Fix some readability-else-after-return issues in layout code. r=jfkthame
[gecko.git] / widget / GfxDriverInfo.h
blobcd429d7126012a62d02200ba81b5e79c01f4add1
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, windowProtocol, driverVendor, devices, feature, \
19 featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion) \
20 sDriverInfo->AppendElement(GfxDriverInfo( \
21 os, screen, battery, \
22 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
23 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
24 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
25 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
26 featureStatus, driverComparator, driverVersion, ruleId, \
27 suggestedVersion))
29 #define APPEND_TO_DRIVER_BLOCKLIST(os, devices, feature, featureStatus, \
30 driverComparator, driverVersion, ruleId, \
31 suggestedVersion) \
32 APPEND_TO_DRIVER_BLOCKLIST_EXT( \
33 os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
34 DriverVendor::All, devices, feature, featureStatus, driverComparator, \
35 driverVersion, ruleId, suggestedVersion)
37 #define APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
38 os, screen, battery, windowProtocol, driverVendor, devices, feature, \
39 featureStatus, driverComparator, driverVersion, ruleId) \
40 sDriverInfo->AppendElement(GfxDriverInfo( \
41 os, screen, battery, \
42 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
43 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
44 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
45 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
46 featureStatus, driverComparator, driverVersion, ruleId))
48 #define APPEND_TO_DRIVER_BLOCKLIST2(os, devices, feature, featureStatus, \
49 driverComparator, driverVersion, ruleId) \
50 APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
51 os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
52 DriverVendor::All, devices, feature, featureStatus, driverComparator, \
53 driverVersion, ruleId)
55 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
56 os, screen, battery, windowProtocol, driverVendor, devices, feature, \
57 featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, \
58 suggestedVersion) \
59 do { \
60 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
61 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
62 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
63 GfxDriverInfo info( \
64 os, screen, battery, \
65 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
66 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
67 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
68 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
69 featureStatus, driverComparator, driverVersion, ruleId, \
70 suggestedVersion); \
71 info.mDriverVersionMax = driverVersionMax; \
72 sDriverInfo->AppendElement(info); \
73 } while (false)
75 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE( \
76 os, devices, feature, featureStatus, driverComparator, driverVersion, \
77 driverVersionMax, ruleId, suggestedVersion) \
78 APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
79 os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
80 DriverVendor::All, devices, feature, featureStatus, driverComparator, \
81 driverVersion, driverVersionMax, ruleId, suggestedVersion)
83 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
84 os, screen, battery, windowProtocol, driverVendor, devices, feature, \
85 featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, \
86 suggestedVersion) \
87 do { \
88 MOZ_ASSERT((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
89 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
90 (driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
91 GfxDriverInfo info( \
92 os, screen, battery, \
93 (nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
94 (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
95 (nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
96 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devices), feature, \
97 featureStatus, driverComparator, driverVersion, ruleId, \
98 suggestedVersion, false, true); \
99 info.mDriverVersionMax = driverVersionMax; \
100 sDriverInfo->AppendElement(info); \
101 } while (false)
103 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2( \
104 os, devices, feature, featureStatus, driverComparator, driverVersion, \
105 driverVersionMax, ruleId, suggestedVersion) \
106 APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
107 os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
108 DriverVendor::All, devices, feature, featureStatus, driverComparator, \
109 driverVersion, driverVersionMax, ruleId, suggestedVersion)
111 namespace mozilla {
112 namespace widget {
114 enum class OperatingSystem : uint8_t {
115 Unknown,
116 #define GFXINFO_OS(id, name) id,
117 #include "mozilla/widget/GfxInfoOperatingSystemDefs.h"
118 #undef GFXINFO_OS
119 Count
122 enum VersionComparisonOp {
123 #define GFXINFO_DRIVER_VERSION_CMP(id) DRIVER_##id,
124 #include "mozilla/widget/GfxInfoDriverVersionCmpDefs.h"
125 #undef GFXINFO_DRIVER_VERSION_CMP
126 DRIVER_COUNT
129 enum class DeviceFamily : uint8_t {
130 All,
131 IntelAll,
132 NvidiaAll,
133 AtiAll,
134 MicrosoftAll,
135 ParallelsAll,
136 QualcommAll,
137 AppleAll,
138 AmazonAll,
139 IntelGMA500,
140 IntelGMA900,
141 IntelGMA950,
142 IntelGMA3150,
143 IntelGMAX3000,
144 IntelGMAX4500HD,
145 IntelHDGraphicsToIvyBridge,
146 IntelHDGraphicsToSandyBridge,
147 IntelHaswell,
148 IntelSandyBridge,
149 IntelGen7Baytrail,
150 IntelSkylake,
151 IntelKabyLake,
152 IntelHD520,
153 IntelMobileHDGraphics,
154 IntelGen12,
155 NvidiaBlockD3D9Layers,
156 RadeonX1000,
157 RadeonCaicos,
158 RadeonBlockZeroVideoCopy,
159 Geforce7300GT,
160 Nvidia310M,
161 Nvidia8800GTS,
162 NvidiaPascal,
163 Bug1137716,
164 Bug1116812,
165 Bug1155608,
166 Bug1207665,
167 Bug1447141,
168 AmdR600,
169 IntelWebRenderBlocked,
170 NvidiaWebRenderBlocked,
175 enum class DeviceVendor : uint8_t {
176 #define GFXINFO_DEVICE_VENDOR(id, name) id,
177 #include "mozilla/widget/GfxInfoDeviceVendorDefs.h"
178 #undef GFXINFO_DEVICE_VENDOR
182 enum DriverVendor : uint8_t {
183 #define GFXINFO_DRIVER_VENDOR(id, name) id,
184 #include "mozilla/widget/GfxInfoDriverVendorDefs.h"
185 #undef GFXINFO_DRIVER_VENDOR
189 enum class WindowProtocol : uint8_t {
190 #define GFXINFO_WINDOW_PROTOCOL(id, name) id,
191 #include "mozilla/widget/GfxInfoWindowProtocolDefs.h"
192 #undef GFXINFO_WINDOW_PROTOCOL
196 enum class BatteryStatus : uint8_t { All, Present, None };
198 enum class ScreenSizeStatus : uint8_t {
199 All,
200 Small, // <= 1900x1200
201 SmallAndMedium, // <= 3440x1440
202 Medium, // <= 3440x1440 && > 1900x1200
203 MediumAndLarge, // >1900x1200
204 Large // > 3440x1440
207 /* Array of devices to match, or an empty array for all devices */
208 class GfxDeviceFamily final {
209 public:
210 GfxDeviceFamily() = default;
212 void Append(const nsAString& aDeviceId);
213 void AppendRange(int32_t aBeginDeviceId, int32_t aEndDeviceId);
215 bool IsEmpty() const { return mIds.IsEmpty() && mRanges.IsEmpty(); }
217 nsresult Contains(nsAString& aDeviceId) const;
219 private:
220 struct DeviceRange {
221 int32_t mBegin;
222 int32_t mEnd;
225 CopyableTArray<nsString> mIds;
226 CopyableTArray<DeviceRange> mRanges;
229 struct GfxDriverInfo {
230 // If |ownDevices| is true, you are transferring ownership of the devices
231 // array, and it will be deleted when this GfxDriverInfo is destroyed.
232 GfxDriverInfo(OperatingSystem os, ScreenSizeStatus aScreen,
233 BatteryStatus aBattery, const nsAString& windowProtocol,
234 const nsAString& vendor, const nsAString& driverVendor,
235 GfxDeviceFamily* devices, int32_t feature,
236 int32_t featureStatus, VersionComparisonOp op,
237 uint64_t driverVersion, const char* ruleId,
238 const char* suggestedVersion = nullptr, bool ownDevices = false,
239 bool gpu2 = false);
241 GfxDriverInfo();
242 GfxDriverInfo(const GfxDriverInfo&);
243 ~GfxDriverInfo();
245 OperatingSystem mOperatingSystem;
246 uint32_t mOperatingSystemVersion;
247 ScreenSizeStatus mScreen;
248 BatteryStatus mBattery;
249 nsString mWindowProtocol;
251 nsString mAdapterVendor;
252 nsString mDriverVendor;
254 const GfxDeviceFamily* mDevices;
256 // Whether the mDevices array should be deleted when this structure is
257 // deallocated. False by default.
258 bool mDeleteDevices;
260 /* A feature from nsIGfxInfo, or a wildcard set of features */
261 int32_t mFeature;
262 /* Block all features */
263 static constexpr int32_t allFeatures = -1;
264 /* Block all features not permitted by OnlyAllowFeatureOnKnownConfig */
265 static constexpr int32_t optionalFeatures = -2;
267 /* A feature status from nsIGfxInfo */
268 int32_t mFeatureStatus;
270 VersionComparisonOp mComparisonOp;
272 /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
273 uint64_t mDriverVersion;
274 uint64_t mDriverVersionMax;
275 static constexpr uint64_t allDriverVersions = ~(uint64_t(0));
277 const char* mSuggestedVersion;
278 nsCString mRuleId;
280 static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
281 static GfxDeviceFamily*
282 sDeviceFamilies[static_cast<size_t>(DeviceFamily::Max)];
284 static const nsAString& GetWindowProtocol(WindowProtocol id);
285 static nsString* sWindowProtocol[static_cast<size_t>(WindowProtocol::Max)];
287 static const nsAString& GetDeviceVendor(DeviceVendor id);
288 static const nsAString& GetDeviceVendor(DeviceFamily id);
289 static nsString* sDeviceVendors[static_cast<size_t>(DeviceVendor::Max)];
291 static const nsAString& GetDriverVendor(DriverVendor id);
292 static nsString* sDriverVendors[static_cast<size_t>(DriverVendor::Max)];
294 nsString mModel, mHardware, mProduct, mManufacturer;
296 bool mGpu2;
299 inline uint64_t DriverVersion(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
300 return (uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) |
301 uint64_t(d);
304 inline uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
305 #ifdef XP_WIN
306 // We make sure every driver number is padded by 0s, this will allow us the
307 // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
308 // more extensive explanation of this approach.
309 while (b > 0 && b < 1000) {
310 b *= 10;
312 while (c > 0 && c < 1000) {
313 c *= 10;
315 while (d > 0 && d < 1000) {
316 d *= 10;
318 #endif
319 return DriverVersion(a, b, c, d);
322 // All destination string storage needs to have at least 5 bytes available.
323 inline bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr,
324 char* aCStr, char* aDStr) {
325 // sscanf doesn't do what we want here to we parse this manually.
326 int len = strlen(aSource);
328 // This "4" is hardcoded in a few places, including once as a 3.
329 char* dest[4] = {aAStr, aBStr, aCStr, aDStr};
330 unsigned destIdx = 0;
331 unsigned destPos = 0;
333 for (int i = 0; i < len; i++) {
334 if (destIdx >= 4) {
335 // Invalid format found. Ensure we don't access dest beyond bounds.
336 return false;
339 if (aSource[i] == '.') {
340 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
341 dest[destIdx++][destPos] = 0;
342 destPos = 0;
343 continue;
346 if (destPos > 3) {
347 // Ignore more than 4 chars. Ensure we never access dest[destIdx]
348 // beyond its bounds.
349 continue;
352 MOZ_ASSERT(destIdx < 4 && destPos < 4);
353 dest[destIdx][destPos++] = aSource[i];
356 // Take care of the trailing period
357 if (destIdx >= 4) {
358 return false;
361 // Add last terminator.
362 MOZ_ASSERT(destIdx < 4 && destPos <= 4);
363 dest[destIdx][destPos] = 0;
364 for (int unusedDestIdx = destIdx + 1; unusedDestIdx < 4; unusedDestIdx++) {
365 dest[unusedDestIdx][0] = 0;
368 if (destIdx != 3) {
369 return false;
371 return true;
374 // This allows us to pad driver version 'substrings' with 0s, this
375 // effectively allows us to treat the version numbers as 'decimals'. This is
376 // a little strange but this method seems to do the right thing for all
377 // different vendor's driver strings. i.e. .98 will become 9800, which is
378 // larger than .978 which would become 9780.
379 inline void PadDriverDecimal(char* aString) {
380 for (int i = 0; i < 4; i++) {
381 if (!aString[i]) {
382 for (int c = i; c < 4; c++) {
383 aString[c] = '0';
385 break;
388 aString[4] = 0;
391 inline bool ParseDriverVersion(const nsAString& aVersion,
392 uint64_t* aNumericVersion) {
393 *aNumericVersion = 0;
395 #ifndef ANDROID
396 int a, b, c, d;
397 char aStr[8], bStr[8], cStr[8], dStr[8];
398 /* honestly, why do I even bother */
399 if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr,
400 bStr, cStr, dStr))
401 return false;
403 # ifdef XP_WIN
404 PadDriverDecimal(bStr);
405 PadDriverDecimal(cStr);
406 PadDriverDecimal(dStr);
407 # endif
409 a = atoi(aStr);
410 b = atoi(bStr);
411 c = atoi(cStr);
412 d = atoi(dStr);
414 if (a < 0 || a > 0xffff) return false;
415 if (b < 0 || b > 0xffff) return false;
416 if (c < 0 || c > 0xffff) return false;
417 if (d < 0 || d > 0xffff) return false;
419 *aNumericVersion = DriverVersion(a, b, c, d);
420 #else
421 // Can't use aVersion.ToInteger() because that's not compiled into our code
422 // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
423 *aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
424 #endif
425 MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
426 return true;
429 } // namespace widget
430 } // namespace mozilla
432 #endif /*__mozilla_widget_GfxDriverInfo_h__ */