@@ -7,6 +7,7 @@ import 'package:process/process.dart';
7
7
import '../base/io.dart' ;
8
8
import '../base/user_messages.dart' ;
9
9
import '../base/version.dart' ;
10
+ import '../convert.dart' ;
10
11
import '../doctor_validator.dart' ;
11
12
12
13
/// A combination of version description and parsed version number.
@@ -29,6 +30,87 @@ class _VersionInfo {
29
30
Version ? number;
30
31
}
31
32
33
+ /// Information about graphics drivers.
34
+ class _DriverInformation {
35
+ _DriverInformation ({required ProcessManager processManager}) : _processManager = processManager;
36
+
37
+ final ProcessManager _processManager;
38
+ List <List <String >> _sections = < List <String >> [];
39
+
40
+ Future <bool > load () async {
41
+ ProcessResult ? result;
42
+ try {
43
+ result = await _processManager.run (< String > ['eglinfo' ], stdoutEncoding: utf8);
44
+ } on ArgumentError {
45
+ // ignore error.
46
+ }
47
+ if (result == null || result.exitCode != 0 ) {
48
+ return false ;
49
+ }
50
+
51
+ // Break into sections separated by an empty line.
52
+ final List <String > lines = (result.stdout as String ).split ('\n ' );
53
+ final List <List <String >> sections = < List <String >> [< String > []];
54
+ for (final String line in lines) {
55
+ if (line == '' ) {
56
+ if (sections.last.isNotEmpty) {
57
+ sections.add (< String > []);
58
+ }
59
+ } else {
60
+ sections.last.add (line);
61
+ }
62
+ }
63
+ if (sections.last.isEmpty) {
64
+ sections.removeLast ();
65
+ }
66
+ _sections = sections;
67
+
68
+ return true ;
69
+ }
70
+
71
+ List <String >? _getSection (String sectionName) {
72
+ for (final List <String > lines in _sections) {
73
+ if (lines[0 ] == '$sectionName :' ) {
74
+ return lines;
75
+ }
76
+ }
77
+
78
+ return null ;
79
+ }
80
+
81
+ // Extracts a variable from eglinfo output.
82
+ String ? getVariable (String sectionName, String name) {
83
+ final List <String >? lines = _getSection (sectionName);
84
+ if (lines == null ) {
85
+ return null ;
86
+ }
87
+
88
+ final String prefix = '$name :' ;
89
+ for (int i = 0 ; i < lines.length; i++ ) {
90
+ if (lines[i].startsWith (prefix)) {
91
+ String value = lines[i].substring (prefix.length).trim ();
92
+ // Combine multi-line indented values.
93
+ if (value == '' ) {
94
+ for (int j = i + 1 ; j < lines.length && lines[j].startsWith (' ' ); j++ ) {
95
+ if (value == '' ) {
96
+ value += ' ' ;
97
+ }
98
+ value += lines[j].trim ();
99
+ }
100
+ }
101
+ return value;
102
+ }
103
+ }
104
+
105
+ return null ;
106
+ }
107
+
108
+ // Extracts a comma separated list variable.
109
+ List <String >? getListVariable (String sectionName, String name) {
110
+ return getVariable (sectionName, name)? .split (',' ).map ((String s) => s.trim ()).toList ();
111
+ }
112
+ }
113
+
32
114
/// A validator that checks for Clang and Make build dependencies.
33
115
class LinuxDoctorValidator extends DoctorValidator {
34
116
LinuxDoctorValidator ({required ProcessManager processManager, required UserMessages userMessages})
@@ -160,6 +242,94 @@ class LinuxDoctorValidator extends DoctorValidator {
160
242
}
161
243
}
162
244
245
+ // Messages for drivers.
246
+ {
247
+ final _DriverInformation driverInfo = _DriverInformation (processManager: _processManager);
248
+ if (! await driverInfo.load ()) {
249
+ messages.add (ValidationMessage .hint (_userMessages.eglinfoMissing));
250
+ } else {
251
+ const String kWaylandPlatform = 'Wayland platform' ;
252
+ const String kX11Platform = 'X11 platform' ;
253
+ const String kOpenGLCoreProfileRenderer = 'OpenGL core profile renderer' ;
254
+ const String kOpenGLCoreProfileShadingLanguageVersion =
255
+ 'OpenGL core profile shading language version' ;
256
+ const String kOpenGLCoreProfileVersion = 'OpenGL core profile version' ;
257
+ const String kOpenGLCoreProfileExtensions = 'OpenGL core profile extensions' ;
258
+ const String kOpenGLESProfileRenderer = 'OpenGL ES profile renderer' ;
259
+ const String kOpenGLESProfileVersion = 'OpenGL ES profile version' ;
260
+ const String kOpenGLESProfileShadingLanguageVersion =
261
+ 'OpenGL ES profile shading language version' ;
262
+ const String kOpenGLESProfileExtensions = 'OpenGL ES profile extensions' ;
263
+
264
+ // Check both Wayland and X11 platforms for value.
265
+ String ? getPlatformVariable (String name) {
266
+ final String ? waylandValue = driverInfo.getVariable (kWaylandPlatform, name);
267
+ final String ? x11Value = driverInfo.getVariable (kX11Platform, name);
268
+ if (waylandValue == null && x11Value == null ) {
269
+ return null ;
270
+ }
271
+
272
+ if (waylandValue == null ) {
273
+ return '$x11Value (X11)' ;
274
+ } else if (x11Value == null ) {
275
+ return '$waylandValue (Wayland)' ;
276
+ } else if (waylandValue == x11Value) {
277
+ return waylandValue;
278
+ } else {
279
+ return '$waylandValue (Wayland) $x11Value (X11)' ;
280
+ }
281
+ }
282
+
283
+ // Check if has specified OpenGL extension.
284
+ ValidationMessage extensionStatus (String variableName, String extensionName) {
285
+ final List <String > waylandExtensions =
286
+ driverInfo.getListVariable (kWaylandPlatform, variableName) ?? < String > [];
287
+ final List <String > x11Extensions =
288
+ driverInfo.getListVariable (kX11Platform, variableName) ?? < String > [];
289
+
290
+ final bool hasWayland = waylandExtensions.contains (extensionName);
291
+ final bool hasX11 = x11Extensions.contains (extensionName);
292
+ String status;
293
+ if (! hasWayland && ! hasX11) {
294
+ status = 'no' ;
295
+ } else if (! hasWayland) {
296
+ status = 'yes (X11)' ;
297
+ } else if (! hasX11) {
298
+ status = 'yes (Wayland)' ;
299
+ } else {
300
+ status = 'yes' ;
301
+ }
302
+
303
+ return ValidationMessage ('$extensionName : $status ' );
304
+ }
305
+
306
+ final String ? renderer = getPlatformVariable (kOpenGLCoreProfileRenderer);
307
+ if (renderer != null ) {
308
+ messages.add (ValidationMessage ('OpenGL core renderer: $renderer ' ));
309
+ final String version = getPlatformVariable (kOpenGLCoreProfileVersion) ?? 'unknown' ;
310
+ messages.add (ValidationMessage ('OpenGL core version: $version ' ));
311
+ final String shadingLanguageVersion =
312
+ getPlatformVariable (kOpenGLCoreProfileShadingLanguageVersion) ?? 'unknown' ;
313
+ messages.add (
314
+ ValidationMessage ('OpenGL core shading language version: $shadingLanguageVersion ' ),
315
+ );
316
+ }
317
+ final String ? esRenderer = getPlatformVariable (kOpenGLESProfileRenderer);
318
+ if (esRenderer != null ) {
319
+ messages.add (ValidationMessage ('OpenGL ES renderer: $esRenderer ' ));
320
+ final String version = getPlatformVariable (kOpenGLESProfileVersion) ?? 'unknown' ;
321
+ messages.add (ValidationMessage ('OpenGL ES version: $version ' ));
322
+ final String shadingLanguageVersion =
323
+ getPlatformVariable (kOpenGLESProfileShadingLanguageVersion) ?? 'unknown' ;
324
+ messages.add (
325
+ ValidationMessage ('OpenGL ES shading language version: $shadingLanguageVersion ' ),
326
+ );
327
+ }
328
+ messages.add (extensionStatus (kOpenGLCoreProfileExtensions, 'GL_EXT_framebuffer_blit' ));
329
+ messages.add (extensionStatus (kOpenGLESProfileExtensions, 'GL_EXT_texture_format_BGRA8888' ));
330
+ }
331
+ }
332
+
163
333
return ValidationResult (validationType, messages);
164
334
}
165
335
0 commit comments