Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 "mozilla/ArrayUtils.h" // ArrayLength
10 #include "nsString.h"
12 // Macros for adding a blocklist item to the static list.
13 #define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, suggestedVersion) \
14 mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, suggestedVersion))
15 #define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion) \
16 mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion))
18 #define APPEND_TO_DRIVER_BLOCKLIST_RANGE(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, driverVersionMax, suggestedVersion) \
19 do { \
20 MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
21 driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
22 driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
23 GfxDriverInfo info(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, suggestedVersion); \
24 info.mDriverVersionMax = driverVersionMax; \
25 mDriverInfo->AppendElement(info); \
26 } while (false)
28 namespace mozilla {
29 namespace widget {
31 enum OperatingSystem {
32 DRIVER_OS_UNKNOWN = 0,
33 DRIVER_OS_WINDOWS_XP,
34 DRIVER_OS_WINDOWS_SERVER_2003,
35 DRIVER_OS_WINDOWS_VISTA,
36 DRIVER_OS_WINDOWS_7,
37 DRIVER_OS_WINDOWS_8,
38 DRIVER_OS_WINDOWS_8_1,
39 DRIVER_OS_LINUX,
40 DRIVER_OS_OS_X_10_5,
41 DRIVER_OS_OS_X_10_6,
42 DRIVER_OS_OS_X_10_7,
43 DRIVER_OS_OS_X_10_8,
44 DRIVER_OS_ANDROID,
45 DRIVER_OS_ALL
46 };
48 enum VersionComparisonOp {
49 DRIVER_LESS_THAN, // driver < version
50 DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
51 DRIVER_GREATER_THAN, // driver > version
52 DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
53 DRIVER_EQUAL, // driver == version
54 DRIVER_NOT_EQUAL, // driver != version
55 DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
56 DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
57 DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
58 DRIVER_COMPARISON_IGNORED
59 };
61 enum DeviceFamily {
62 IntelGMA500,
63 IntelGMA900,
64 IntelGMA950,
65 IntelGMA3150,
66 IntelGMAX3000,
67 IntelGMAX4500HD,
68 IntelMobileHDGraphics,
69 NvidiaBlockD3D9Layers,
70 RadeonX1000,
71 Geforce7300GT,
72 DeviceFamilyMax
73 };
75 enum DeviceVendor {
76 VendorAll,
77 VendorIntel,
78 VendorNVIDIA,
79 VendorAMD,
80 VendorATI,
81 VendorMicrosoft,
82 DeviceVendorMax
83 };
85 /* Array of devices to match, or an empty array for all devices */
86 typedef nsTArray<nsString> GfxDeviceFamily;
88 struct GfxDriverInfo
89 {
90 // If |ownDevices| is true, you are transferring ownership of the devices
91 // array, and it will be deleted when this GfxDriverInfo is destroyed.
92 GfxDriverInfo(OperatingSystem os, nsAString& vendor, GfxDeviceFamily* devices,
93 int32_t feature, int32_t featureStatus, VersionComparisonOp op,
94 uint64_t driverVersion, const char *suggestedVersion = nullptr,
95 bool ownDevices = false);
97 GfxDriverInfo();
98 GfxDriverInfo(const GfxDriverInfo&);
99 ~GfxDriverInfo();
101 OperatingSystem mOperatingSystem;
102 uint32_t mOperatingSystemVersion;
104 nsString mAdapterVendor;
106 static GfxDeviceFamily* const allDevices;
107 GfxDeviceFamily* mDevices;
109 // Whether the mDevices array should be deleted when this structure is
110 // deallocated. False by default.
111 bool mDeleteDevices;
113 /* A feature from nsIGfxInfo, or all features */
114 int32_t mFeature;
115 static int32_t allFeatures;
117 /* A feature status from nsIGfxInfo */
118 int32_t mFeatureStatus;
120 VersionComparisonOp mComparisonOp;
122 /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
123 uint64_t mDriverVersion;
124 uint64_t mDriverVersionMax;
125 static uint64_t allDriverVersions;
127 const char *mSuggestedVersion;
129 static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
130 static GfxDeviceFamily* mDeviceFamilies[DeviceFamilyMax];
132 static const nsAString& GetDeviceVendor(DeviceVendor id);
133 static nsAString* mDeviceVendors[DeviceVendorMax];
135 nsString mModel, mHardware, mProduct, mManufacturer;
136 };
138 #define GFX_DRIVER_VERSION(a,b,c,d) \
139 ((uint64_t(a)<<48) | (uint64_t(b)<<32) | (uint64_t(c)<<16) | uint64_t(d))
141 inline uint64_t
142 V(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
143 {
144 // We make sure every driver number is padded by 0s, this will allow us the
145 // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
146 // more extensive explanation of this approach.
147 while (b > 0 && b < 1000) {
148 b *= 10;
149 }
150 while (c > 0 && c < 1000) {
151 c *= 10;
152 }
153 while (d > 0 && d < 1000) {
154 d *= 10;
155 }
156 return GFX_DRIVER_VERSION(a, b, c, d);
157 }
159 // All destination string storage needs to have at least 5 bytes available.
160 inline bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCStr, char *aDStr)
161 {
162 // sscanf doesn't do what we want here to we parse this manually.
163 int len = strlen(aSource);
164 char *dest[4] = { aAStr, aBStr, aCStr, aDStr };
165 unsigned destIdx = 0;
166 unsigned destPos = 0;
168 for (int i = 0; i < len; i++) {
169 if (destIdx > ArrayLength(dest)) {
170 // Invalid format found. Ensure we don't access dest beyond bounds.
171 return false;
172 }
174 if (aSource[i] == '.') {
175 dest[destIdx++][destPos] = 0;
176 destPos = 0;
177 continue;
178 }
180 if (destPos > 3) {
181 // Ignore more than 4 chars. Ensure we never access dest[destIdx]
182 // beyond its bounds.
183 continue;
184 }
186 dest[destIdx][destPos++] = aSource[i];
187 }
189 // Add last terminator.
190 dest[destIdx][destPos] = 0;
192 if (destIdx != ArrayLength(dest) - 1) {
193 return false;
194 }
195 return true;
196 }
198 // This allows us to pad driver version 'substrings' with 0s, this
199 // effectively allows us to treat the version numbers as 'decimals'. This is
200 // a little strange but this method seems to do the right thing for all
201 // different vendor's driver strings. i.e. .98 will become 9800, which is
202 // larger than .978 which would become 9780.
203 inline void PadDriverDecimal(char *aString)
204 {
205 for (int i = 0; i < 4; i++) {
206 if (!aString[i]) {
207 for (int c = i; c < 4; c++) {
208 aString[c] = '0';
209 }
210 break;
211 }
212 }
213 aString[4] = 0;
214 }
216 inline bool
217 ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
218 {
219 *aNumericVersion = 0;
221 #if defined(XP_WIN)
222 int a, b, c, d;
223 char aStr[8], bStr[8], cStr[8], dStr[8];
224 /* honestly, why do I even bother */
225 if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr, bStr, cStr, dStr))
226 return false;
228 PadDriverDecimal(bStr);
229 PadDriverDecimal(cStr);
230 PadDriverDecimal(dStr);
232 a = atoi(aStr);
233 b = atoi(bStr);
234 c = atoi(cStr);
235 d = atoi(dStr);
237 if (a < 0 || a > 0xffff) return false;
238 if (b < 0 || b > 0xffff) return false;
239 if (c < 0 || c > 0xffff) return false;
240 if (d < 0 || d > 0xffff) return false;
242 *aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
243 return true;
244 #elif defined(ANDROID)
245 // Can't use aVersion.ToInteger() because that's not compiled into our code
246 // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
247 *aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
248 return true;
249 #else
250 return false;
251 #endif
252 }
254 }
255 }
257 #endif /*__mozilla_widget_GfxDriverInfo_h__ */