1#include "blocklist_driver.h"
2
3#include <base/system.h>
4
5#include <cstddef>
6
7#define VERSION_PARTS 4
8
9struct SVersion
10{
11 int m_aParts[VERSION_PARTS];
12
13 bool operator<=(const SVersion &Other) const
14 {
15 for(int i = 0; i < VERSION_PARTS; i++)
16 {
17 if(m_aParts[i] < Other.m_aParts[i])
18 return true;
19 if(m_aParts[i] > Other.m_aParts[i])
20 return false;
21 }
22 return true;
23 }
24};
25
26enum EBackendDriverBlockListType
27{
28 BACKEND_DRIVER_BLOCKLIST_TYPE_VERSION = 0,
29 BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR,
30};
31
32/* TODO: generalize it more for other drivers / vendors */
33struct SBackEndDriverBlockList
34{
35 EBackendDriverBlockListType m_BlockListType;
36
37 SVersion m_VersionMin;
38 SVersion m_VersionMax;
39
40 const char *m_pVendorName;
41
42 // the OpenGL version, that is supported
43 int m_AllowedMajor;
44 int m_AllowedMinor;
45 int m_AllowedPatch;
46
47 const char *m_pReason;
48
49 bool m_DisplayReason;
50 const char *m_pOSName;
51};
52
53static SBackEndDriverBlockList gs_aBlockList[] = {
54 {.m_BlockListType: BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR, .m_VersionMin: {26, 20, 100, 7800}, .m_VersionMax: {27, 20, 100, 8853}, .m_pVendorName: "Intel", .m_AllowedMajor: 2, .m_AllowedMinor: 0, .m_AllowedPatch: 0, .m_pReason: "This Intel driver version can cause crashes, please update it to a newer version.", .m_DisplayReason: false, .m_pOSName: "windows"}};
55
56const char *ParseBlocklistDriverVersions(const char *pVendorStr, const char *pVersionStr, int &BlocklistMajor, int &BlocklistMinor, int &BlocklistPatch, bool &RequiresWarning)
57{
58 if(str_find_nocase(haystack: pVendorStr, needle: "Intel") == NULL)
59 return NULL;
60
61 const char *pVersionStrStart = str_find_nocase(haystack: pVersionStr, needle: "Build ");
62 if(pVersionStrStart == NULL)
63 return NULL;
64
65 // ignore "Build ", after that, it should directly start with the driver version
66 pVersionStrStart += (ptrdiff_t)str_length(str: "Build ");
67
68 char aVersionStrHelper[512]; // the size is random, but shouldn't be too small probably
69
70 SVersion Version;
71 for(int &VersionPart : Version.m_aParts)
72 {
73 pVersionStrStart = str_next_token(str: pVersionStrStart, delim: ".", buffer: aVersionStrHelper, buffer_size: sizeof(aVersionStrHelper));
74 if(pVersionStrStart == NULL)
75 return NULL;
76
77 VersionPart = str_toint(str: aVersionStrHelper);
78 }
79
80 for(const auto &BlockListItem : gs_aBlockList)
81 {
82 if(str_comp(a: BlockListItem.m_pOSName, CONF_FAMILY_STRING) == 0)
83 {
84 bool DriverBlocked = false;
85 if(BlockListItem.m_BlockListType == BACKEND_DRIVER_BLOCKLIST_TYPE_VENDOR)
86 {
87 if(str_find_nocase(haystack: pVendorStr, needle: BlockListItem.m_pVendorName) != NULL)
88 {
89 DriverBlocked = true;
90 }
91 }
92 else if(BlockListItem.m_BlockListType == BACKEND_DRIVER_BLOCKLIST_TYPE_VERSION)
93 {
94 if(BlockListItem.m_VersionMin <= Version && Version <= BlockListItem.m_VersionMax)
95 {
96 DriverBlocked = true;
97 }
98 }
99
100 if(DriverBlocked)
101 {
102 RequiresWarning = BlockListItem.m_DisplayReason;
103 BlocklistMajor = BlockListItem.m_AllowedMajor;
104 BlocklistMinor = BlockListItem.m_AllowedMinor;
105 BlocklistPatch = BlockListItem.m_AllowedPatch;
106 return BlockListItem.m_pReason;
107 }
108 }
109 }
110
111 return NULL;
112}
113