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