Line data Source code
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 "nsString.h"
10 :
11 : // Macros for adding a blocklist item to the static list.
12 : #define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion) \
13 : mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion))
14 : #define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId) \
15 : mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId))
16 :
17 : #define APPEND_TO_DRIVER_BLOCKLIST_RANGE(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, suggestedVersion) \
18 : do { \
19 : MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
20 : driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
21 : driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
22 : GfxDriverInfo info(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion); \
23 : info.mDriverVersionMax = driverVersionMax; \
24 : mDriverInfo->AppendElement(info); \
25 : } while (false)
26 :
27 : #define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, suggestedVersion) \
28 : do { \
29 : MOZ_ASSERT(driverComparator == DRIVER_BETWEEN_EXCLUSIVE || \
30 : driverComparator == DRIVER_BETWEEN_INCLUSIVE || \
31 : driverComparator == DRIVER_BETWEEN_INCLUSIVE_START); \
32 : GfxDriverInfo info(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion, false, true); \
33 : info.mDriverVersionMax = driverVersionMax; \
34 : mDriverInfo->AppendElement(info); \
35 : } while (false)
36 :
37 :
38 : namespace mozilla {
39 : namespace widget {
40 :
41 : enum class OperatingSystem {
42 : Unknown,
43 : Windows,
44 : WindowsXP,
45 : WindowsServer2003,
46 : WindowsVista,
47 : Windows7,
48 : Windows8,
49 : Windows8_1,
50 : Windows10,
51 : Linux,
52 : OSX,
53 : OSX10_5,
54 : OSX10_6,
55 : OSX10_7,
56 : OSX10_8,
57 : OSX10_9,
58 : OSX10_10,
59 : OSX10_11,
60 : OSX10_12,
61 : Android,
62 : Ios
63 : };
64 :
65 : enum VersionComparisonOp {
66 : DRIVER_LESS_THAN, // driver < version
67 : DRIVER_BUILD_ID_LESS_THAN, // driver build id < version
68 : DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
69 : DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, // driver build id <= version
70 : DRIVER_GREATER_THAN, // driver > version
71 : DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
72 : DRIVER_EQUAL, // driver == version
73 : DRIVER_NOT_EQUAL, // driver != version
74 : DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
75 : DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
76 : DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
77 : DRIVER_COMPARISON_IGNORED
78 : };
79 :
80 : enum DeviceFamily {
81 : IntelGMA500,
82 : IntelGMA900,
83 : IntelGMA950,
84 : IntelGMA3150,
85 : IntelGMAX3000,
86 : IntelGMAX4500HD,
87 : IntelHDGraphicsToSandyBridge,
88 : IntelHD3000,
89 : IntelMobileHDGraphics,
90 : NvidiaBlockD3D9Layers,
91 : RadeonX1000,
92 : Geforce7300GT,
93 : Nvidia310M,
94 : Nvidia8800GTS,
95 : Bug1137716,
96 : Bug1116812,
97 : Bug1155608,
98 : Bug1207665,
99 : DeviceFamilyMax
100 : };
101 :
102 : enum DeviceVendor {
103 : VendorAll,
104 : VendorIntel,
105 : VendorNVIDIA,
106 : VendorAMD,
107 : VendorATI,
108 : VendorMicrosoft,
109 : DeviceVendorMax
110 : };
111 :
112 : /* Array of devices to match, or an empty array for all devices */
113 : typedef nsTArray<nsString> GfxDeviceFamily;
114 :
115 0 : struct GfxDriverInfo
116 : {
117 : // If |ownDevices| is true, you are transferring ownership of the devices
118 : // array, and it will be deleted when this GfxDriverInfo is destroyed.
119 : GfxDriverInfo(OperatingSystem os, nsAString& vendor, GfxDeviceFamily* devices,
120 : int32_t feature, int32_t featureStatus, VersionComparisonOp op,
121 : uint64_t driverVersion, const char *ruleId,
122 : const char *suggestedVersion = nullptr,
123 : bool ownDevices = false, bool gpu2 = false);
124 :
125 : GfxDriverInfo();
126 : GfxDriverInfo(const GfxDriverInfo&);
127 : ~GfxDriverInfo();
128 :
129 : OperatingSystem mOperatingSystem;
130 : uint32_t mOperatingSystemVersion;
131 :
132 : nsString mAdapterVendor;
133 :
134 : static GfxDeviceFamily* const allDevices;
135 : GfxDeviceFamily* mDevices;
136 :
137 : // Whether the mDevices array should be deleted when this structure is
138 : // deallocated. False by default.
139 : bool mDeleteDevices;
140 :
141 : /* A feature from nsIGfxInfo, or all features */
142 : int32_t mFeature;
143 : static int32_t allFeatures;
144 :
145 : /* A feature status from nsIGfxInfo */
146 : int32_t mFeatureStatus;
147 :
148 : VersionComparisonOp mComparisonOp;
149 :
150 : /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
151 : uint64_t mDriverVersion;
152 : uint64_t mDriverVersionMax;
153 : static uint64_t allDriverVersions;
154 :
155 : const char *mSuggestedVersion;
156 : nsCString mRuleId;
157 :
158 : static const GfxDeviceFamily* GetDeviceFamily(DeviceFamily id);
159 : static GfxDeviceFamily* mDeviceFamilies[DeviceFamilyMax];
160 :
161 : static const nsAString& GetDeviceVendor(DeviceVendor id);
162 : static nsAString* mDeviceVendors[DeviceVendorMax];
163 :
164 : nsString mModel, mHardware, mProduct, mManufacturer;
165 :
166 : bool mGpu2;
167 : };
168 :
169 : #define GFX_DRIVER_VERSION(a,b,c,d) \
170 : ((uint64_t(a)<<48) | (uint64_t(b)<<32) | (uint64_t(c)<<16) | uint64_t(d))
171 :
172 : inline uint64_t
173 : V(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
174 : {
175 : // We make sure every driver number is padded by 0s, this will allow us the
176 : // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
177 : // more extensive explanation of this approach.
178 : while (b > 0 && b < 1000) {
179 : b *= 10;
180 : }
181 : while (c > 0 && c < 1000) {
182 : c *= 10;
183 : }
184 : while (d > 0 && d < 1000) {
185 : d *= 10;
186 : }
187 : return GFX_DRIVER_VERSION(a, b, c, d);
188 : }
189 :
190 : // All destination string storage needs to have at least 5 bytes available.
191 : inline bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCStr, char *aDStr)
192 : {
193 : // sscanf doesn't do what we want here to we parse this manually.
194 : int len = strlen(aSource);
195 :
196 : // This "4" is hardcoded in a few places, including once as a 3.
197 : char *dest[4] = { aAStr, aBStr, aCStr, aDStr };
198 : unsigned destIdx = 0;
199 : unsigned destPos = 0;
200 :
201 : for (int i = 0; i < len; i++) {
202 : if (destIdx >= 4) {
203 : // Invalid format found. Ensure we don't access dest beyond bounds.
204 : return false;
205 : }
206 :
207 : if (aSource[i] == '.') {
208 : MOZ_ASSERT (destIdx < 4 && destPos <= 4);
209 : dest[destIdx++][destPos] = 0;
210 : destPos = 0;
211 : continue;
212 : }
213 :
214 : if (destPos > 3) {
215 : // Ignore more than 4 chars. Ensure we never access dest[destIdx]
216 : // beyond its bounds.
217 : continue;
218 : }
219 :
220 : MOZ_ASSERT (destIdx < 4 && destPos < 4);
221 : dest[destIdx][destPos++] = aSource[i];
222 : }
223 :
224 : // Take care of the trailing period
225 : if (destIdx >= 4) {
226 : return false;
227 : }
228 :
229 : // Add last terminator.
230 : MOZ_ASSERT (destIdx < 4 && destPos <= 4);
231 : dest[destIdx][destPos] = 0;
232 :
233 : if (destIdx != 3) {
234 : return false;
235 : }
236 : return true;
237 : }
238 :
239 : // This allows us to pad driver version 'substrings' with 0s, this
240 : // effectively allows us to treat the version numbers as 'decimals'. This is
241 : // a little strange but this method seems to do the right thing for all
242 : // different vendor's driver strings. i.e. .98 will become 9800, which is
243 : // larger than .978 which would become 9780.
244 : inline void PadDriverDecimal(char *aString)
245 : {
246 : for (int i = 0; i < 4; i++) {
247 : if (!aString[i]) {
248 : for (int c = i; c < 4; c++) {
249 : aString[c] = '0';
250 : }
251 : break;
252 : }
253 : }
254 : aString[4] = 0;
255 : }
256 :
257 : inline bool
258 0 : ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion)
259 : {
260 0 : *aNumericVersion = 0;
261 :
262 : #if defined(XP_WIN)
263 : int a, b, c, d;
264 : char aStr[8], bStr[8], cStr[8], dStr[8];
265 : /* honestly, why do I even bother */
266 : if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr, bStr, cStr, dStr))
267 : return false;
268 :
269 : PadDriverDecimal(bStr);
270 : PadDriverDecimal(cStr);
271 : PadDriverDecimal(dStr);
272 :
273 : a = atoi(aStr);
274 : b = atoi(bStr);
275 : c = atoi(cStr);
276 : d = atoi(dStr);
277 :
278 : if (a < 0 || a > 0xffff) return false;
279 : if (b < 0 || b > 0xffff) return false;
280 : if (c < 0 || c > 0xffff) return false;
281 : if (d < 0 || d > 0xffff) return false;
282 :
283 : *aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
284 : MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
285 : return true;
286 : #elif defined(ANDROID)
287 : // Can't use aVersion.ToInteger() because that's not compiled into our code
288 : // unless we have XPCOM_GLUE_AVOID_NSPR disabled.
289 : *aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
290 : MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
291 : return true;
292 : #else
293 0 : return false;
294 : #endif
295 : }
296 :
297 : } // namespace widget
298 : } // namespace mozilla
299 :
300 : #endif /*__mozilla_widget_GfxDriverInfo_h__ */
|