-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathDetectGLVendors.cpp
More file actions
365 lines (324 loc) · 11.9 KB
/
DetectGLVendors.cpp
File metadata and controls
365 lines (324 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2024 Daemon Developers
All rights reserved.
This file is part of the Daemon BSD Source Code (Daemon Source Code).
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Daemon developers nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/
#include "DetectGLVendors.h"
std::string GetGLHardwareVendorName( glHardwareVendor_t hardwareVendor )
{
static const std::string hardwareVendorNames[] = {
"Unknown",
"Software rasterizer",
"API Translator",
"Apple",
"Arm",
"AMD/ATI",
"Broadcom",
"Intel",
"Nvidia",
"Moore Threads",
"Imagination",
"OutOfRange",
};
int index = Util::ordinal( hardwareVendor );
static constexpr size_t lastNameIndex = ARRAY_LEN( hardwareVendorNames ) - 1;
static constexpr int lastEnumIndex = Util::ordinal( glHardwareVendor_t::NUM_HARDWARE_VENDORS );
static_assert( lastNameIndex == lastEnumIndex, "glHardwareVendor_t and hardwareVendorNames count mismatch" );
ASSERT_GE( index, 0 );
ASSERT_LT( index, lastEnumIndex );
index = ( index < 0 || index > lastEnumIndex ) ? lastNameIndex : index;
return hardwareVendorNames[ index ];
}
std::string GetGLDriverVendorName( glDriverVendor_t driverVendor )
{
static const std::string driverVendorNames[] = {
"Unknown",
"Apple",
"AMD/ATI",
"Intel",
"Mesa",
"Nvidia",
"Moore Threads",
"Imagination",
"GL4ES",
"OutOfRange",
};
int index = Util::ordinal( driverVendor );
static constexpr size_t lastNameIndex = ARRAY_LEN( driverVendorNames ) - 1;
static constexpr int lastEnumIndex = Util::ordinal( glDriverVendor_t::NUM_DRIVER_VENDORS );
static_assert( lastNameIndex == lastEnumIndex, "glDriverVendor_t and driverVendorNames count mismatch" );
ASSERT_GE( index, 0 );
ASSERT_LT( index, lastEnumIndex );
index = ( index < 0 || index > lastEnumIndex ) ? lastNameIndex : index;
return driverVendorNames[ index ];
}
static std::string StripPrefix( const std::string &prefix, const std::string &string )
{
if ( Str::IsPrefix( prefix, string ) )
{
size_t prefixLen = prefix.length();
size_t stringLen = string.length();
size_t subLen = stringLen - prefixLen;
return string.substr( prefixLen, subLen );
}
return string;
}
void DetectGLVendors(
const std::string& vendorString,
const std::string& versionString,
const std::string& rendererString,
glHardwareVendor_t& hardwareVendor,
glDriverVendor_t& driverVendor )
{
hardwareVendor = glHardwareVendor_t::UNKNOWN;
driverVendor = glDriverVendor_t::UNKNOWN;
// Those vendor strings are assumed to be unambiguous about both driver and hardware vendors.
static const std::unordered_map<std::string, std::pair<glDriverVendor_t, glHardwareVendor_t>>
vendorDriverHardware =
{
// Mesa AMD/ATI.
{ "AMD", { glDriverVendor_t::MESA, glHardwareVendor_t::ATI } },
{ "AMD inc.", { glDriverVendor_t::MESA, glHardwareVendor_t::ATI } },
{ "X.Org R300 Project", { glDriverVendor_t::MESA, glHardwareVendor_t::ATI } },
// Proprietary ATI or AMD drivers on all systems like Linux, Windows, and macOS: OGLP, Catalyst…
{ "ATI Technologies Inc.", { glDriverVendor_t::ATI, glHardwareVendor_t::ATI } },
// Proprietary Intel driver on macOS.
{ "Intel Inc.", { glDriverVendor_t::INTEL, glHardwareVendor_t::INTEL } },
// Mesa Intel.
{ "Intel Open Source Technology Center", { glDriverVendor_t::MESA, glHardwareVendor_t::INTEL } },
{ "Tungsten Graphics, Inc", { glDriverVendor_t::MESA, glHardwareVendor_t::INTEL } },
// Mesa V3D and VC4 (Raspberry Pi).
{ "Broadcom", { glDriverVendor_t::MESA, glHardwareVendor_t::BROADCOM } },
// Mesa Panfrost, newer Panfrost uses "Mesa" instead.
{ "Panfrost", { glDriverVendor_t::MESA, glHardwareVendor_t::ARM } },
// Mesa Nvidia for supported OpenGL 2+ hardware.
// Mesa Amber also provides "Nouveau", but this is for unsupported pre-OpenGL 2 Nvidia.
{ "nouveau", { glDriverVendor_t::MESA, glHardwareVendor_t::NVIDIA } },
// Proprietary Nvidia drivers on all systems like Linux, Windows, and macOS.
{ "NVIDIA Corporation", { glDriverVendor_t::NVIDIA, glHardwareVendor_t::NVIDIA } },
// Moore Threads drivers on Linux and Windows.
{ "Moore Threads", { glDriverVendor_t::MTHREADS, glHardwareVendor_t::MTHREADS } },
// Proprietary Imagination driver for PowerVR.
{ "Imagination Technologies", { glDriverVendor_t::IMAGINATION, glHardwareVendor_t::IMAGINATION } },
};
auto it = vendorDriverHardware.find( vendorString );
if ( it != vendorDriverHardware.end() )
{
driverVendor = it->second.first;
hardwareVendor = it->second.second;
return;
}
static const std::string appleVendors[] = {
"Apple",
"Apple Inc.",
"Apple Computer, Inc.",
};
for ( auto& s : appleVendors )
{
if ( vendorString == s )
{
driverVendor = glDriverVendor_t::APPLE;
break;
}
}
if ( driverVendor == glDriverVendor_t::APPLE )
{
if ( rendererString == "Apple Software Renderer" )
{
hardwareVendor = glHardwareVendor_t::SOFTWARE;
return;
}
hardwareVendor = glHardwareVendor_t::APPLE;
return;
}
// This vendor string is used by at least two different Intel drivers.
if ( vendorString == "Intel Corporation" )
{
if ( Str::IsPrefix( "SWR ", rendererString ) )
{
/* It is part of Mesa Amber, but was merged in Mesa lately after being an internal
Intel product for years. It doesn't share much things with Mesa, and we better
not assume it behaves the same as Mesa, it may even behave like Intel.
We keep driverVendor as glDriverVendor_t::UNKNOWN on purpose. */
hardwareVendor = glHardwareVendor_t::SOFTWARE;
return;
}
else
{
driverVendor = glDriverVendor_t::MESA;
hardwareVendor = glHardwareVendor_t::INTEL;
return;
}
}
// This vendor string is used by at least two different Microsoft drivers.
if ( vendorString == "Microsoft Corporation" )
{
/* The GL_VENDOR string can also be "Microsoft Corporation" with GL_RENDERER
set to "GDI Generic" which is not Mesa and isn't supported (OpenGL 1.1). */
if ( Str::IsPrefix( "DRD12 ", rendererString ) )
{
driverVendor = glDriverVendor_t::MESA;
// OpenGL over Direct3D12 translation.
hardwareVendor = glHardwareVendor_t::TRANSLATION;
return;
}
}
/* Those substrings at the beginning of a renderer string are assumed to be unambiguous about
both driver and hardware. */
static const std::pair<std::string, glHardwareVendor_t> rendererMesaStartStringHardware[] = {
// "Mesa DRI R200" exists for ATI but isn't supported.
{ "Mesa DRI nv", glHardwareVendor_t::NVIDIA },
{ "Mesa DRI Intel(R)", glHardwareVendor_t::INTEL },
};
for ( auto& p : rendererMesaStartStringHardware )
{
if ( Str::IsPrefix( p.first, rendererString ) )
{
driverVendor = glDriverVendor_t::MESA;
hardwareVendor = p.second;
return;
}
}
// Those vendor strings are assumed to be unambiguous about being from Mesa drivers.
static const std::string mesaVendors[] = {
// Mesa.
"Mesa",
"Mesa Project",
"Mesa/X.org",
"X.Org",
// Zink.
"Collabora Ltd",
// virgl.
"Red Hat",
// llvmpipe, softpipe, SVGA3D.
"VMware, Inc.",
};
for ( auto& s : mesaVendors )
{
if ( vendorString == s )
{
driverVendor = glDriverVendor_t::MESA;
break;
}
}
/* This substring in a version string is assumed to be unambiguous about being from Mesa
drivers. Mesa GL_VENDOR and GL_RENDERER strings are very fluid, but it is believed that
GL_VERSION always contains the " Mesa " substring and that substring always means Mesa. */
if ( driverVendor == glDriverVendor_t::UNKNOWN && versionString.find( " Mesa " ) != std::string::npos )
{
driverVendor = glDriverVendor_t::MESA;
}
if ( driverVendor == glDriverVendor_t::MESA )
{
// This vendor string for a Mesa driver is assumed to be unambiguous about the hardware.
if ( vendorString == "Intel" )
{
hardwareVendor = glHardwareVendor_t::INTEL;
return;
}
/* Those substrings at the beginning of a renderer string are assumed to be unambiguous about
the hardware or underlying technology. */
static const std::pair<std::string, glHardwareVendor_t> rendererStartStringHardware[] = {
{ "Apple ", glHardwareVendor_t::APPLE },
{ "ATI ", glHardwareVendor_t::ATI },
{ "AMD ", glHardwareVendor_t::ATI },
{ "i915 ", glHardwareVendor_t::INTEL },
{ "NV", glHardwareVendor_t::NVIDIA },
{ "Mali-", glHardwareVendor_t::ARM },
// OpenGL over Vulkan translation.
{ "zink ", glHardwareVendor_t::TRANSLATION },
// Virtualization.
{ "virgl", glHardwareVendor_t::TRANSLATION },
};
for ( auto& p : rendererStartStringHardware )
{
if ( Str::IsPrefix( p.first, rendererString ) )
{
hardwareVendor = p.second;
return;
}
}
/* Those substrings within a renderer string are assumed to be unambiguous about
the underlying technology. */
static const std::pair<std::string, glHardwareVendor_t> rendererSubStringHardware[] = {
{ "Panfrost", glHardwareVendor_t::ARM },
// Software rendering.
{ "llvmpipe", glHardwareVendor_t::SOFTWARE },
{ "softpipe", glHardwareVendor_t::SOFTWARE },
// Virtualization.
{ "SVGA3D", glHardwareVendor_t::TRANSLATION },
};
for ( auto& p : rendererSubStringHardware )
{
if ( rendererString.find( p.first ) != std::string::npos )
{
hardwareVendor = p.second;
return;
}
}
}
/* As both proprietary Intel driver on Windows and Mesa may report "Intel",
we rely on the fact Mesa is already detected to know it is the proprietary
Windows driver if not Mesa. */
if ( vendorString == "Intel" )
{
driverVendor = glDriverVendor_t::INTEL;
hardwareVendor = glHardwareVendor_t::INTEL;
return;
}
// Newer GL4ES strings disclosing the underlying technology.
if ( Str::IsPrefix( "GL4ES wrapping ", vendorString ) )
{
std::string subVendorString = StripPrefix( "GL4ES wrapping ", vendorString );
std::string subRendererString = StripPrefix( "GL4ES using ", rendererString );
DetectGLVendors( subVendorString, versionString, subRendererString, hardwareVendor, driverVendor );
driverVendor = glDriverVendor_t::GL4ES;
}
/* Older GL4ES string not disclosing the underlying technology,
also had “ptitSeb” as vendorString. */
if ( rendererString == "GL4ES wrapper" )
{
driverVendor = glDriverVendor_t::GL4ES;
// Older GL4ES doesn't disclose the underlying hardware.
if ( hardwareVendor == glHardwareVendor_t::UNKNOWN )
{
hardwareVendor = glHardwareVendor_t::TRANSLATION;
}
return;
}
/* GL4ES always use such kind of version string:
> 2.1 gl4es wrapper 1.1.7
And this is unlikely to change. */
if ( versionString.find( "gl4es wrapper" ) != std::string::npos )
{
driverVendor = glDriverVendor_t::GL4ES;
if ( hardwareVendor == glHardwareVendor_t::UNKNOWN )
{
hardwareVendor = glHardwareVendor_t::TRANSLATION;
}
return;
}
}