|
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/. */ |
|
5 |
|
6 #ifndef __mozilla_widget_GfxDriverInfo_h__ |
|
7 #define __mozilla_widget_GfxDriverInfo_h__ |
|
8 |
|
9 #include "mozilla/ArrayUtils.h" // ArrayLength |
|
10 #include "nsString.h" |
|
11 |
|
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)) |
|
17 |
|
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) |
|
27 |
|
28 namespace mozilla { |
|
29 namespace widget { |
|
30 |
|
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 }; |
|
47 |
|
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 }; |
|
60 |
|
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 }; |
|
74 |
|
75 enum DeviceVendor { |
|
76 VendorAll, |
|
77 VendorIntel, |
|
78 VendorNVIDIA, |
|
79 VendorAMD, |
|
80 VendorATI, |
|
81 VendorMicrosoft, |
|
82 DeviceVendorMax |
|
83 }; |
|
84 |
|
85 /* Array of devices to match, or an empty array for all devices */ |
|
86 typedef nsTArray<nsString> GfxDeviceFamily; |
|
87 |
|
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); |
|
96 |
|
97 GfxDriverInfo(); |
|
98 GfxDriverInfo(const GfxDriverInfo&); |
|
99 ~GfxDriverInfo(); |
|
100 |
|
101 OperatingSystem mOperatingSystem; |
|
102 uint32_t mOperatingSystemVersion; |
|
103 |
|
104 nsString mAdapterVendor; |
|
105 |
|
106 static GfxDeviceFamily* const allDevices; |
|
107 GfxDeviceFamily* mDevices; |
|
108 |
|
109 // Whether the mDevices array should be deleted when this structure is |
|
110 // deallocated. False by default. |
|
111 bool mDeleteDevices; |
|
112 |
|
113 /* A feature from nsIGfxInfo, or all features */ |
|
114 int32_t mFeature; |
|
115 static int32_t allFeatures; |
|
116 |
|
117 /* A feature status from nsIGfxInfo */ |
|
118 int32_t mFeatureStatus; |
|
119 |
|
120 VersionComparisonOp mComparisonOp; |
|
121 |
|
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; |
|
126 |
|
127 const char *mSuggestedVersion; |
|
128 |
|
129 static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id); |
|
130 static GfxDeviceFamily* mDeviceFamilies[DeviceFamilyMax]; |
|
131 |
|
132 static const nsAString& GetDeviceVendor(DeviceVendor id); |
|
133 static nsAString* mDeviceVendors[DeviceVendorMax]; |
|
134 |
|
135 nsString mModel, mHardware, mProduct, mManufacturer; |
|
136 }; |
|
137 |
|
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)) |
|
140 |
|
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 } |
|
158 |
|
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; |
|
167 |
|
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 } |
|
173 |
|
174 if (aSource[i] == '.') { |
|
175 dest[destIdx++][destPos] = 0; |
|
176 destPos = 0; |
|
177 continue; |
|
178 } |
|
179 |
|
180 if (destPos > 3) { |
|
181 // Ignore more than 4 chars. Ensure we never access dest[destIdx] |
|
182 // beyond its bounds. |
|
183 continue; |
|
184 } |
|
185 |
|
186 dest[destIdx][destPos++] = aSource[i]; |
|
187 } |
|
188 |
|
189 // Add last terminator. |
|
190 dest[destIdx][destPos] = 0; |
|
191 |
|
192 if (destIdx != ArrayLength(dest) - 1) { |
|
193 return false; |
|
194 } |
|
195 return true; |
|
196 } |
|
197 |
|
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 } |
|
215 |
|
216 inline bool |
|
217 ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion) |
|
218 { |
|
219 *aNumericVersion = 0; |
|
220 |
|
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; |
|
227 |
|
228 PadDriverDecimal(bStr); |
|
229 PadDriverDecimal(cStr); |
|
230 PadDriverDecimal(dStr); |
|
231 |
|
232 a = atoi(aStr); |
|
233 b = atoi(bStr); |
|
234 c = atoi(cStr); |
|
235 d = atoi(dStr); |
|
236 |
|
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; |
|
241 |
|
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 } |
|
253 |
|
254 } |
|
255 } |
|
256 |
|
257 #endif /*__mozilla_widget_GfxDriverInfo_h__ */ |