GfxDriverInfo.h 8.5 KB

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