1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=8 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include "GfxInfo.h"
9
10 #include <cctype>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <string>
14 #include <sys/types.h>
15 #include <sys/utsname.h>
16 #include <sys/wait.h>
17
18 #include "mozilla/gfx/Logging.h"
19 #include "mozilla/SSE.h"
20 #include "mozilla/Telemetry.h"
21 #include "nsCRTGlue.h"
22 #include "nsExceptionHandler.h"
23 #include "nsPrintfCString.h"
24 #include "nsUnicharUtils.h"
25 #include "nsWhitespaceTokenizer.h"
26 #include "prenv.h"
27 #include "WidgetUtilsGtk.h"
28
29 #define EXIT_STATUS_BUFFER_TOO_SMALL 2
30 #ifdef DEBUG
31 bool fire_glxtest_process();
32 #endif
33
34 namespace mozilla::widget {
35
36 #ifdef DEBUG
37 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
38 #endif
39
40 // these global variables will be set when firing the glxtest process
41 int glxtest_pipe = -1;
42 pid_t glxtest_pid = 0;
43
Init()44 nsresult GfxInfo::Init() {
45 mGLMajorVersion = 0;
46 mGLMinorVersion = 0;
47 mHasTextureFromPixmap = false;
48 mIsMesa = false;
49 mIsAccelerated = true;
50 mIsWayland = false;
51 mIsXWayland = false;
52 mHasMultipleGPUs = false;
53 mGlxTestError = false;
54 return GfxInfoBase::Init();
55 }
56
AddCrashReportAnnotations()57 void GfxInfo::AddCrashReportAnnotations() {
58 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID,
59 mVendorId);
60 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID,
61 mDeviceId);
62 CrashReporter::AnnotateCrashReport(
63 CrashReporter::Annotation::AdapterDriverVendor, mDriverVendor);
64 CrashReporter::AnnotateCrashReport(
65 CrashReporter::Annotation::AdapterDriverVersion, mDriverVersion);
66 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWayland,
67 mIsWayland);
68 CrashReporter::AnnotateCrashReport(
69 CrashReporter::Annotation::DesktopEnvironment, mDesktopEnvironment);
70
71 if (mHasMultipleGPUs) {
72 nsAutoCString note;
73 note.AppendLiteral("Has dual GPUs.");
74 if (!mSecondaryVendorId.IsEmpty()) {
75 note.AppendLiteral(" GPU #2: AdapterVendorID2: ");
76 note.Append(mSecondaryVendorId);
77 note.AppendLiteral(", AdapterDeviceID2: ");
78 note.Append(mSecondaryDeviceId);
79 }
80 CrashReporter::AppendAppNotesToCrashReport(note);
81 }
82 }
83
GetData()84 void GfxInfo::GetData() {
85 GfxInfoBase::GetData();
86
87 // to understand this function, see bug 639842. We retrieve the OpenGL driver
88 // information in a separate process to protect against bad drivers.
89
90 // if glxtest_pipe == -1, that means that we already read the information
91 if (glxtest_pipe == -1) return;
92
93 enum { buf_size = 2048 };
94 char buf[buf_size];
95 ssize_t bytesread = read(glxtest_pipe, &buf,
96 buf_size - 1); // -1 because we'll append a zero
97 close(glxtest_pipe);
98 glxtest_pipe = -1;
99
100 // bytesread < 0 would mean that the above read() call failed.
101 // This should never happen. If it did, the outcome would be to blocklist
102 // anyway.
103 if (bytesread < 0) {
104 bytesread = 0;
105 } else if (bytesread == buf_size - 1) {
106 gfxCriticalNote << "glxtest: read from pipe exceeded buffer size";
107 }
108
109 // let buf be a zero-terminated string
110 buf[bytesread] = 0;
111
112 // Wait for the glxtest process to finish. This serves 2 purposes:
113 // * avoid having a zombie glxtest process laying around
114 // * get the glxtest process status info.
115 int glxtest_status = 0;
116 bool wait_for_glxtest_process = true;
117 bool waiting_for_glxtest_process_failed = false;
118 int waitpid_errno = 0;
119 while (wait_for_glxtest_process) {
120 wait_for_glxtest_process = false;
121 if (waitpid(glxtest_pid, &glxtest_status, 0) == -1) {
122 waitpid_errno = errno;
123 if (waitpid_errno == EINTR) {
124 wait_for_glxtest_process = true;
125 } else {
126 // Bug 718629
127 // ECHILD happens when the glxtest process got reaped got reaped after a
128 // PR_CreateProcess as per bug 227246. This shouldn't matter, as we
129 // still seem to get the data from the pipe, and if we didn't, the
130 // outcome would be to blocklist anyway.
131 waiting_for_glxtest_process_failed = (waitpid_errno != ECHILD);
132 }
133 }
134 }
135
136 int exit_code = EXIT_FAILURE;
137 bool exited_with_error_code = false;
138 if (!waiting_for_glxtest_process_failed && WIFEXITED(glxtest_status)) {
139 exit_code = WEXITSTATUS(glxtest_status);
140 exited_with_error_code = exit_code != EXIT_SUCCESS;
141 }
142
143 bool received_signal =
144 !waiting_for_glxtest_process_failed && WIFSIGNALED(glxtest_status);
145
146 bool error = waiting_for_glxtest_process_failed || exited_with_error_code ||
147 received_signal;
148 bool errorLog = false;
149
150 nsCString glVendor;
151 nsCString glRenderer;
152 nsCString glVersion;
153 nsCString textureFromPixmap;
154 nsCString testType;
155
156 // Available if GLX_MESA_query_renderer is supported.
157 nsCString mesaVendor;
158 nsCString mesaDevice;
159 nsCString mesaAccelerated;
160 // Available if using a DRI-based libGL stack.
161 nsCString driDriver;
162 nsCString screenInfo;
163 nsCString adapterRam;
164
165 nsCString drmRenderDevice;
166
167 nsCString ddxDriver;
168
169 AutoTArray<nsCString, 2> pciVendors;
170 AutoTArray<nsCString, 2> pciDevices;
171
172 nsCString* stringToFill = nullptr;
173 bool logString = false;
174
175 char* bufptr = buf;
176 while (true) {
177 char* line = NS_strtok("\n", &bufptr);
178 if (!line) break;
179 if (stringToFill) {
180 stringToFill->Assign(line);
181 stringToFill = nullptr;
182 } else if (logString) {
183 gfxCriticalNote << "glxtest: " << line;
184 logString = false;
185 } else if (!strcmp(line, "VENDOR")) {
186 stringToFill = &glVendor;
187 } else if (!strcmp(line, "RENDERER")) {
188 stringToFill = &glRenderer;
189 } else if (!strcmp(line, "VERSION")) {
190 stringToFill = &glVersion;
191 } else if (!strcmp(line, "TFP")) {
192 stringToFill = &textureFromPixmap;
193 } else if (!strcmp(line, "MESA_VENDOR_ID")) {
194 stringToFill = &mesaVendor;
195 } else if (!strcmp(line, "MESA_DEVICE_ID")) {
196 stringToFill = &mesaDevice;
197 } else if (!strcmp(line, "MESA_ACCELERATED")) {
198 stringToFill = &mesaAccelerated;
199 } else if (!strcmp(line, "MESA_VRAM")) {
200 stringToFill = &adapterRam;
201 } else if (!strcmp(line, "DDX_DRIVER")) {
202 stringToFill = &ddxDriver;
203 } else if (!strcmp(line, "DRI_DRIVER")) {
204 stringToFill = &driDriver;
205 } else if (!strcmp(line, "SCREEN_INFO")) {
206 stringToFill = &screenInfo;
207 } else if (!strcmp(line, "PCI_VENDOR_ID")) {
208 stringToFill = pciVendors.AppendElement();
209 } else if (!strcmp(line, "PCI_DEVICE_ID")) {
210 stringToFill = pciDevices.AppendElement();
211 } else if (!strcmp(line, "DRM_RENDERDEVICE")) {
212 stringToFill = &drmRenderDevice;
213 } else if (!strcmp(line, "TEST_TYPE")) {
214 stringToFill = &testType;
215 } else if (!strcmp(line, "WARNING")) {
216 logString = true;
217 } else if (!strcmp(line, "ERROR")) {
218 logString = true;
219 errorLog = true;
220 }
221 }
222
223 MOZ_ASSERT(pciDevices.Length() == pciVendors.Length(),
224 "Missing PCI vendors/devices");
225
226 size_t pciLen = std::min(pciVendors.Length(), pciDevices.Length());
227 mHasMultipleGPUs = pciLen > 1;
228
229 if (!strcmp(textureFromPixmap.get(), "TRUE")) mHasTextureFromPixmap = true;
230
231 // only useful for Linux kernel version check for FGLRX driver.
232 // assumes X client == X server, which is sad.
233 struct utsname unameobj {};
234 if (uname(&unameobj) >= 0) {
235 mOS.Assign(unameobj.sysname);
236 mOSRelease.Assign(unameobj.release);
237 }
238
239 const char* spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
240 if (spoofedVendor) glVendor.Assign(spoofedVendor);
241 const char* spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
242 if (spoofedRenderer) glRenderer.Assign(spoofedRenderer);
243 const char* spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
244 if (spoofedVersion) glVersion.Assign(spoofedVersion);
245 const char* spoofedOS = PR_GetEnv("MOZ_GFX_SPOOF_OS");
246 if (spoofedOS) mOS.Assign(spoofedOS);
247 const char* spoofedOSRelease = PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE");
248 if (spoofedOSRelease) mOSRelease.Assign(spoofedOSRelease);
249
250 // Scan the GL_VERSION string for the GL and driver versions.
251 nsCWhitespaceTokenizer tokenizer(glVersion);
252 while (tokenizer.hasMoreTokens()) {
253 nsCString token(tokenizer.nextToken());
254 unsigned int major = 0, minor = 0, revision = 0, patch = 0;
255 if (sscanf(token.get(), "%u.%u.%u.%u", &major, &minor, &revision, &patch) >=
256 2) {
257 // A survey of GL_VENDOR strings indicates that the first version is
258 // always the GL version, the second is usually the driver version.
259 if (mGLMajorVersion == 0) {
260 mGLMajorVersion = major;
261 mGLMinorVersion = minor;
262 } else if (mDriverVersion.IsEmpty()) { // Not already spoofed.
263 mDriverVersion =
264 nsPrintfCString("%u.%u.%u.%u", major, minor, revision, patch);
265 }
266 }
267 }
268
269 if (mGLMajorVersion == 0) {
270 NS_WARNING("Failed to parse GL version!");
271 }
272
273 mDrmRenderDevice = std::move(drmRenderDevice);
274 mTestType = std::move(testType);
275
276 // Mesa always exposes itself in the GL_VERSION string, but not always the
277 // GL_VENDOR string.
278 mIsMesa = glVersion.Find("Mesa") != -1;
279
280 // We need to use custom driver vendor IDs for mesa so we can treat them
281 // differently than the proprietary drivers.
282 if (mIsMesa) {
283 mIsAccelerated = !mesaAccelerated.Equals("FALSE");
284 // Process software rasterizers before the DRI driver string; we may be
285 // forcing software rasterization on a DRI-accelerated X server by using
286 // LIBGL_ALWAYS_SOFTWARE or a similar restriction.
287 if (strcasestr(glRenderer.get(), "llvmpipe")) {
288 CopyUTF16toUTF8(
289 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaLLVMPipe),
290 mDriverVendor);
291 mIsAccelerated = false;
292 } else if (strcasestr(glRenderer.get(), "softpipe")) {
293 CopyUTF16toUTF8(
294 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSoftPipe),
295 mDriverVendor);
296 mIsAccelerated = false;
297 } else if (strcasestr(glRenderer.get(), "software rasterizer") ||
298 !mIsAccelerated) {
299 // Fallback to reporting swrast if GLX_MESA_query_renderer tells us
300 // we're using an unaccelerated context.
301 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWRast),
302 mDriverVendor);
303 mIsAccelerated = false;
304 } else if (!driDriver.IsEmpty()) {
305 mDriverVendor = nsPrintfCString("mesa/%s", driDriver.get());
306 } else {
307 // Some other mesa configuration where we couldn't get enough info.
308 NS_WARNING("Failed to detect Mesa driver being used!");
309 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaUnknown),
310 mDriverVendor);
311 }
312
313 if (!mesaVendor.IsEmpty()) {
314 mVendorId = mesaVendor;
315 }
316
317 if (!mesaDevice.IsEmpty()) {
318 mDeviceId = mesaDevice;
319 }
320
321 if (!mIsAccelerated && mVendorId.IsEmpty()) {
322 mVendorId.Assign(glVendor.get());
323 }
324
325 if (!mIsAccelerated && mDeviceId.IsEmpty()) {
326 mDeviceId.Assign(glRenderer.get());
327 }
328 } else if (glVendor.EqualsLiteral("NVIDIA Corporation")) {
329 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
330 mVendorId);
331 mDriverVendor.AssignLiteral("nvidia/unknown");
332 // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM.
333 } else if (glVendor.EqualsLiteral("ATI Technologies Inc.")) {
334 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
335 mVendorId);
336 mDriverVendor.AssignLiteral("ati/unknown");
337 // TODO: Look into ways to find the device ID on FGLRX.
338 } else {
339 NS_WARNING("Failed to detect GL vendor!");
340 }
341
342 if (!screenInfo.IsEmpty()) {
343 PRInt32 start = 0;
344 PRInt32 loc = screenInfo.Find(";", PR_FALSE, start);
345 while (loc != kNotFound) {
346 int isDefault = 0;
347 nsCString line(screenInfo.get() + start, loc - start);
348 ScreenInfo info{};
349 if (sscanf(line.get(), "%ux%u:%u", &info.mWidth, &info.mHeight,
350 &isDefault) == 3) {
351 info.mIsDefault = isDefault != 0;
352 mScreenInfo.AppendElement(info);
353 }
354
355 start = loc + 1;
356 loc = screenInfo.Find(";", PR_FALSE, start);
357 }
358 }
359
360 if (!adapterRam.IsEmpty()) {
361 mAdapterRAM = (uint32_t)atoi(adapterRam.get());
362 }
363
364 // If we have the DRI driver, we can derive the vendor ID from that if needed.
365 if (mVendorId.IsEmpty() && !driDriver.IsEmpty()) {
366 const char* nvidiaDrivers[] = {"nouveau", "tegra", nullptr};
367 for (size_t i = 0; nvidiaDrivers[i]; ++i) {
368 if (driDriver.Equals(nvidiaDrivers[i])) {
369 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
370 mVendorId);
371 break;
372 }
373 }
374
375 if (mVendorId.IsEmpty()) {
376 const char* intelDrivers[] = {"iris", "i915", "i965",
377 "i810", "intel", nullptr};
378 for (size_t i = 0; intelDrivers[i]; ++i) {
379 if (driDriver.Equals(intelDrivers[i])) {
380 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel),
381 mVendorId);
382 break;
383 }
384 }
385 }
386
387 if (mVendorId.IsEmpty()) {
388 const char* amdDrivers[] = {"r600", "r200", "r100",
389 "radeon", "radeonsi", nullptr};
390 for (size_t i = 0; amdDrivers[i]; ++i) {
391 if (driDriver.Equals(amdDrivers[i])) {
392 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
393 mVendorId);
394 break;
395 }
396 }
397 }
398
399 if (mVendorId.IsEmpty()) {
400 if (driDriver.EqualsLiteral("freedreno")) {
401 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Qualcomm),
402 mVendorId);
403 }
404 }
405 }
406
407 // If we still don't have a vendor ID, we can try the PCI vendor list.
408 if (mVendorId.IsEmpty()) {
409 if (pciVendors.IsEmpty()) {
410 gfxCriticalNote << "No GPUs detected via PCI";
411 } else {
412 for (size_t i = 0; i < pciVendors.Length(); ++i) {
413 if (mVendorId.IsEmpty()) {
414 mVendorId = pciVendors[i];
415 } else if (mVendorId != pciVendors[i]) {
416 gfxCriticalNote << "More than 1 GPU vendor detected via PCI, cannot "
417 "deduce vendor";
418 mVendorId.Truncate();
419 break;
420 }
421 }
422 }
423 }
424
425 // If we know the vendor ID, but didn't get a device ID, we can guess from the
426 // PCI device list.
427 if (mDeviceId.IsEmpty() && !mVendorId.IsEmpty()) {
428 for (size_t i = 0; i < pciLen; ++i) {
429 if (mVendorId.Equals(pciVendors[i])) {
430 if (mDeviceId.IsEmpty()) {
431 mDeviceId = pciDevices[i];
432 } else if (mDeviceId != pciDevices[i]) {
433 gfxCriticalNote << "More than 1 GPU from same vendor detected via "
434 "PCI, cannot deduce device";
435 mDeviceId.Truncate();
436 break;
437 }
438 }
439 }
440 }
441
442 // Assuming we know the vendor, we should check for a secondary card.
443 if (!mVendorId.IsEmpty()) {
444 if (pciLen > 2) {
445 gfxCriticalNote
446 << "More than 2 GPUs detected via PCI, secondary GPU is arbitrary";
447 }
448 for (size_t i = 0; i < pciLen; ++i) {
449 if (!mVendorId.Equals(pciVendors[i]) ||
450 (!mDeviceId.IsEmpty() && !mDeviceId.Equals(pciDevices[i]))) {
451 mSecondaryVendorId = pciVendors[i];
452 mSecondaryDeviceId = pciDevices[i];
453 break;
454 }
455 }
456 }
457
458 // If we couldn't choose, log them.
459 if (mVendorId.IsEmpty()) {
460 for (size_t i = 0; i < pciLen; ++i) {
461 gfxCriticalNote << "PCI candidate " << pciVendors[i].get() << "/"
462 << pciDevices[i].get();
463 }
464 }
465
466 // Fallback to GL_VENDOR and GL_RENDERER.
467 if (mVendorId.IsEmpty()) {
468 mVendorId.Assign(glVendor.get());
469 }
470 if (mDeviceId.IsEmpty()) {
471 mDeviceId.Assign(glRenderer.get());
472 }
473
474 mAdapterDescription.Assign(glRenderer);
475
476 // Make a best effort guess at whether or not we are using the XWayland compat
477 // layer. For all intents and purposes, we should otherwise believe we are
478 // using X11.
479 mIsWayland = GdkIsWaylandDisplay();
480 const char* waylandDisplay = getenv("WAYLAND_DISPLAY");
481 mIsXWayland = !mIsWayland && waylandDisplay;
482
483 // Make a best effort guess at the desktop environment in use. Sadly there
484 // does not appear to be a standard way to do this, so we check a few
485 // different environment variables and search for relevant keywords.
486 //
487 // Note that some users manually change these values. Some applications check
488 // the environment variable like we are here, and either not work or restrict
489 // functionality. There may be some heroics we could go through to determine
490 // the truth, but for the moment, this is the best we can do. This is
491 // something to keep in mind when updating the blocklist.
492 const char* desktopEnv = getenv("XDG_CURRENT_DESKTOP");
493 if (!desktopEnv) {
494 desktopEnv = getenv("DESKTOP_SESSION");
495 }
496
497 if (desktopEnv) {
498 std::string currentDesktop(desktopEnv);
499 for (auto& c : currentDesktop) {
500 c = std::tolower(c);
501 }
502
503 if (currentDesktop.find("budgie") != std::string::npos) {
504 // We need to check for Budgie first, because it might incorporate GNOME
505 // into the environment variable value.
506 CopyUTF16toUTF8(
507 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Budgie),
508 mDesktopEnvironment);
509 } else if (currentDesktop.find("gnome") != std::string::npos) {
510 CopyUTF16toUTF8(
511 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
512 mDesktopEnvironment);
513 } else if (currentDesktop.find("kde") != std::string::npos) {
514 CopyUTF16toUTF8(
515 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
516 mDesktopEnvironment);
517 } else if (currentDesktop.find("xfce") != std::string::npos) {
518 CopyUTF16toUTF8(
519 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::XFCE),
520 mDesktopEnvironment);
521 } else if (currentDesktop.find("cinnamon") != std::string::npos) {
522 CopyUTF16toUTF8(
523 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Cinnamon),
524 mDesktopEnvironment);
525 } else if (currentDesktop.find("enlightenment") != std::string::npos) {
526 CopyUTF16toUTF8(GfxDriverInfo::GetDesktopEnvironment(
527 DesktopEnvironment::Enlightenment),
528 mDesktopEnvironment);
529 } else if (currentDesktop.find("lxde") != std::string::npos ||
530 currentDesktop.find("lubuntu") != std::string::npos) {
531 CopyUTF16toUTF8(
532 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXDE),
533 mDesktopEnvironment);
534 } else if (currentDesktop.find("openbox") != std::string::npos) {
535 CopyUTF16toUTF8(
536 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Openbox),
537 mDesktopEnvironment);
538 } else if (currentDesktop.find("i3") != std::string::npos) {
539 CopyUTF16toUTF8(
540 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::i3),
541 mDesktopEnvironment);
542 } else if (currentDesktop.find("mate") != std::string::npos) {
543 CopyUTF16toUTF8(
544 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
545 mDesktopEnvironment);
546 } else if (currentDesktop.find("unity") != std::string::npos) {
547 CopyUTF16toUTF8(
548 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unity),
549 mDesktopEnvironment);
550 } else if (currentDesktop.find("pantheon") != std::string::npos) {
551 CopyUTF16toUTF8(
552 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Pantheon),
553 mDesktopEnvironment);
554 } else if (currentDesktop.find("lxqt") != std::string::npos) {
555 CopyUTF16toUTF8(
556 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
557 mDesktopEnvironment);
558 } else if (currentDesktop.find("deepin") != std::string::npos) {
559 CopyUTF16toUTF8(
560 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Deepin),
561 mDesktopEnvironment);
562 } else if (currentDesktop.find("dwm") != std::string::npos) {
563 CopyUTF16toUTF8(
564 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Dwm),
565 mDesktopEnvironment);
566 }
567 }
568
569 if (mDesktopEnvironment.IsEmpty()) {
570 if (getenv("GNOME_DESKTOP_SESSION_ID")) {
571 CopyUTF16toUTF8(
572 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
573 mDesktopEnvironment);
574 } else if (getenv("KDE_FULL_SESSION")) {
575 CopyUTF16toUTF8(
576 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
577 mDesktopEnvironment);
578 } else if (getenv("MATE_DESKTOP_SESSION_ID")) {
579 CopyUTF16toUTF8(
580 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
581 mDesktopEnvironment);
582 } else if (getenv("LXQT_SESSION_CONFIG")) {
583 CopyUTF16toUTF8(
584 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
585 mDesktopEnvironment);
586 } else {
587 CopyUTF16toUTF8(
588 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unknown),
589 mDesktopEnvironment);
590 }
591 }
592
593 if (!ddxDriver.IsEmpty()) {
594 PRInt32 start = 0;
595 PRInt32 loc = ddxDriver.Find(";", PR_FALSE, start);
596 while (loc != kNotFound) {
597 nsCString line(ddxDriver.get() + start, loc - start);
598 mDdxDrivers.AppendElement(std::move(line));
599
600 start = loc + 1;
601 loc = ddxDriver.Find(";", PR_FALSE, start);
602 }
603 }
604
605 if (error || errorLog || mTestType.IsEmpty()) {
606 if (!mAdapterDescription.IsEmpty()) {
607 mAdapterDescription.AppendLiteral(" (See failure log)");
608 } else {
609 mAdapterDescription.AppendLiteral("See failure log");
610 }
611
612 mGlxTestError = true;
613 }
614
615 if (error) {
616 nsAutoCString msg("glxtest: process failed");
617 if (waiting_for_glxtest_process_failed) {
618 msg.AppendPrintf(" (waitpid failed with errno=%d for pid %d)",
619 waitpid_errno, glxtest_pid);
620 }
621
622 if (exited_with_error_code) {
623 if (exit_code == EXIT_STATUS_BUFFER_TOO_SMALL) {
624 msg.AppendLiteral(" (buffer too small)");
625 } else {
626 msg.AppendPrintf(" (exited with status %d)",
627 WEXITSTATUS(glxtest_status));
628 }
629 }
630 if (received_signal) {
631 msg.AppendPrintf(" (received signal %d)", WTERMSIG(glxtest_status));
632 }
633
634 gfxCriticalNote << msg.get();
635 }
636
637 AddCrashReportAnnotations();
638 }
639
GetGfxDriverInfo()640 const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
641 if (!sDriverInfo->Length()) {
642 // Mesa 10.0 provides the GLX_MESA_query_renderer extension, which allows us
643 // to query device IDs backing a GL context for blocklisting.
644 APPEND_TO_DRIVER_BLOCKLIST_EXT(
645 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
646 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
647 DeviceFamily::All, GfxDriverInfo::allFeatures,
648 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
649 V(10, 0, 0, 0), "FEATURE_FAILURE_OLD_MESA", "Mesa 10.0");
650
651 // NVIDIA Mesa baseline (see bug 1714391).
652 APPEND_TO_DRIVER_BLOCKLIST_EXT(
653 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
654 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaNouveau,
655 DeviceFamily::All, GfxDriverInfo::allFeatures,
656 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
657 V(11, 0, 0, 0), "FEATURE_FAILURE_OLD_NV_MESA", "Mesa 11.0");
658
659 // NVIDIA baseline (ported from old blocklist)
660 APPEND_TO_DRIVER_BLOCKLIST_EXT(
661 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
662 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
663 DeviceFamily::NvidiaAll, GfxDriverInfo::allFeatures,
664 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
665 V(257, 21, 0, 0), "FEATURE_FAILURE_OLD_NVIDIA", "NVIDIA 257.21");
666
667 // fglrx baseline (chosen arbitrarily as 2013-07-22 release).
668 APPEND_TO_DRIVER_BLOCKLIST(
669 OperatingSystem::Linux, DeviceFamily::AtiAll,
670 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
671 DRIVER_LESS_THAN, V(13, 15, 100, 1), "FEATURE_FAILURE_OLD_FGLRX",
672 "fglrx 13.15.100.1");
673
674 ////////////////////////////////////
675 // FEATURE_WEBRENDER
676
677 // All Mesa software drivers, see FEATURE_WEBRENDER_SOFTWARE
678 APPEND_TO_DRIVER_BLOCKLIST_EXT(
679 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
680 DesktopEnvironment::All, WindowProtocol::All,
681 DriverVendor::SoftwareMesaAll, DeviceFamily::All,
682 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
683 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_FAILURE_SOFTWARE_GL",
684 "");
685
686 // Intel Mesa baseline, chosen arbitrarily.
687 APPEND_TO_DRIVER_BLOCKLIST(
688 OperatingSystem::Linux, DeviceFamily::IntelAll,
689 nsIGfxInfo::FEATURE_WEBRENDER,
690 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
691 V(17, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 17.0.0.0");
692
693 APPEND_TO_DRIVER_BLOCKLIST2(
694 OperatingSystem::Linux, DeviceFamily::IntelGen7Baytrail,
695 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
696 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0),
697 "FEATURE_FAILURE_BUG_1708682");
698
699 // Nvidia Mesa baseline, see bug 1563859.
700 APPEND_TO_DRIVER_BLOCKLIST_EXT(
701 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
702 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
703 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
704 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
705 V(18, 2, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.2.0.0");
706
707 // Disable on all older Nvidia drivers due to stability issues.
708 APPEND_TO_DRIVER_BLOCKLIST_EXT(
709 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
710 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
711 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
712 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN, V(460, 32, 3, 0),
713 "FEATURE_FAILURE_WEBRENDER_OLD_NVIDIA", "460.32.03");
714
715 // Disable Nvidia proprietary drivers on Wayland.
716 APPEND_TO_DRIVER_BLOCKLIST_EXT(
717 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
718 DesktopEnvironment::All, WindowProtocol::Wayland,
719 DriverVendor::NonMesaAll, DeviceFamily::NvidiaAll,
720 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
721 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0),
722 "FEATURE_FAILURE_WEBRENDER_NVIDIA_WAYLAND",
723 "https://bugzilla.mozilla.org/show_bug.cgi?id=1646135");
724
725 // ATI Mesa baseline, chosen arbitrarily.
726 APPEND_TO_DRIVER_BLOCKLIST_EXT(
727 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
728 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
729 DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_WEBRENDER,
730 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
731 V(17, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 17.0.0.0");
732
733 // Bug 1690568 / Bug 1393793 - Require Mesa 17.3.0+ for devices using the
734 // r600 driver to avoid shader compilation issues.
735 APPEND_TO_DRIVER_BLOCKLIST_EXT(
736 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
737 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaR600,
738 DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
739 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
740 V(17, 3, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA_R600",
741 "Mesa 17.3.0.0");
742
743 // Disable on all ATI devices not using Mesa for now.
744 APPEND_TO_DRIVER_BLOCKLIST_EXT(
745 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
746 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
747 DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_WEBRENDER,
748 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
749 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_ATI", "");
750
751 // Bug 1673939 - Garbled text on RS880 GPUs with Mesa drivers.
752 APPEND_TO_DRIVER_BLOCKLIST_EXT(
753 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
754 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
755 DeviceFamily::AmdR600, nsIGfxInfo::FEATURE_WEBRENDER,
756 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
757 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1673939",
758 "https://gitlab.freedesktop.org/mesa/mesa/-/issues/3720");
759
760 #ifndef EARLY_BETA_OR_EARLIER
761 // Bug 1635186 - Poor performance with video playing in a background window
762 // on XWayland.
763 APPEND_TO_DRIVER_BLOCKLIST_EXT(
764 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
765 DesktopEnvironment::All, WindowProtocol::XWayland, DriverVendor::All,
766 DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
767 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
768 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1635186",
769 "https://bugzilla.mozilla.org/show_bug.cgi?id=1635186");
770 #endif
771
772 ////////////////////////////////////
773 // FEATURE_WEBRENDER - ALLOWLIST
774
775 // Intel Mesa baseline, chosen arbitrarily.
776 APPEND_TO_DRIVER_BLOCKLIST_EXT(
777 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
778 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
779 DeviceFamily::IntelRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
780 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL,
781 V(17, 0, 0, 0), "FEATURE_ROLLOUT_INTEL_MESA", "Mesa 17.0.0.0");
782
783 // Nvidia Mesa baseline, see bug 1563859.
784 APPEND_TO_DRIVER_BLOCKLIST_EXT(
785 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
786 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
787 DeviceFamily::NvidiaRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
788 nsIGfxInfo::FEATURE_ALLOW_QUALIFIED, DRIVER_GREATER_THAN_OR_EQUAL,
789 V(18, 2, 0, 0), "FEATURE_ROLLOUT_NVIDIA_MESA", "Mesa 18.2.0.0");
790
791 // Nvidia proprietary driver baseline, see bug 1673752.
792 APPEND_TO_DRIVER_BLOCKLIST_EXT(
793 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
794 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
795 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
796 nsIGfxInfo::FEATURE_ALLOW_QUALIFIED, DRIVER_GREATER_THAN_OR_EQUAL,
797 V(460, 32, 3, 0), "FEATURE_ROLLOUT_NVIDIA_BINARY", "460.32.03");
798
799 // ATI Mesa baseline, chosen arbitrarily.
800 APPEND_TO_DRIVER_BLOCKLIST_EXT(
801 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
802 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
803 DeviceFamily::AtiRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
804 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL,
805 V(17, 0, 0, 0), "FEATURE_ROLLOUT_ATI_MESA", "Mesa 17.0.0.0");
806
807 ////////////////////////////////////
808 // FEATURE_WEBRENDER_SOFTWARE - ALLOWLIST
809 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
810 defined(__i386) || defined(__amd64__) || EARLY_BETA_OR_EARLIER
811 APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Linux, DeviceFamily::All,
812 nsIGfxInfo::FEATURE_WEBRENDER_SOFTWARE,
813 nsIGfxInfo::FEATURE_ALLOW_ALWAYS,
814 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0),
815 "FEATURE_ROLLOUT_SOFTWARE_WR", "");
816 #endif
817 ////////////////////////////////////
818 // FEATURE_WEBRENDER_COMPOSITOR
819 APPEND_TO_DRIVER_BLOCKLIST(
820 OperatingSystem::Linux, DeviceFamily::All,
821 nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
822 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
823 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_COMPOSITOR_DISABLED", "");
824
825 ////////////////////////////////////
826 // FEATURE_X11_EGL
827 APPEND_TO_DRIVER_BLOCKLIST(
828 OperatingSystem::Linux, DeviceFamily::All, nsIGfxInfo::FEATURE_X11_EGL,
829 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
830 V(0, 0, 0, 0), "FEATURE_FAILURE_X11_EGL_DISABLED", "");
831
832 ////////////////////////////////////
833
834 APPEND_TO_DRIVER_BLOCKLIST_EXT(
835 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
836 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaNouveau,
837 DeviceFamily::All, nsIGfxInfo::FEATURE_THREADSAFE_GL,
838 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
839 V(0, 0, 0, 0), "FEATURE_FAILURE_THREADSAFE_GL", "");
840 }
841 return *sDriverInfo;
842 }
843
DoesWindowProtocolMatch(const nsAString & aBlocklistWindowProtocol,const nsAString & aWindowProtocol)844 bool GfxInfo::DoesWindowProtocolMatch(const nsAString& aBlocklistWindowProtocol,
845 const nsAString& aWindowProtocol) {
846 if (mIsWayland &&
847 aBlocklistWindowProtocol.Equals(
848 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandAll),
849 nsCaseInsensitiveStringComparator)) {
850 return true;
851 }
852 if (!mIsWayland &&
853 aBlocklistWindowProtocol.Equals(
854 GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11All),
855 nsCaseInsensitiveStringComparator)) {
856 return true;
857 }
858 return GfxInfoBase::DoesWindowProtocolMatch(aBlocklistWindowProtocol,
859 aWindowProtocol);
860 }
861
DoesDriverVendorMatch(const nsAString & aBlocklistVendor,const nsAString & aDriverVendor)862 bool GfxInfo::DoesDriverVendorMatch(const nsAString& aBlocklistVendor,
863 const nsAString& aDriverVendor) {
864 if (mIsMesa) {
865 if (aBlocklistVendor.Equals(
866 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaAll),
867 nsCaseInsensitiveStringComparator)) {
868 return true;
869 }
870 if (mIsAccelerated &&
871 aBlocklistVendor.Equals(
872 GfxDriverInfo::GetDriverVendor(DriverVendor::HardwareMesaAll),
873 nsCaseInsensitiveStringComparator)) {
874 return true;
875 }
876 if (!mIsAccelerated &&
877 aBlocklistVendor.Equals(
878 GfxDriverInfo::GetDriverVendor(DriverVendor::SoftwareMesaAll),
879 nsCaseInsensitiveStringComparator)) {
880 return true;
881 }
882 }
883 if (!mIsMesa && aBlocklistVendor.Equals(
884 GfxDriverInfo::GetDriverVendor(DriverVendor::NonMesaAll),
885 nsCaseInsensitiveStringComparator)) {
886 return true;
887 }
888 return GfxInfoBase::DoesDriverVendorMatch(aBlocklistVendor, aDriverVendor);
889 }
890
GetFeatureStatusImpl(int32_t aFeature,int32_t * aStatus,nsAString & aSuggestedDriverVersion,const nsTArray<GfxDriverInfo> & aDriverInfo,nsACString & aFailureId,OperatingSystem * aOS)891 nsresult GfxInfo::GetFeatureStatusImpl(
892 int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion,
893 const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
894 OperatingSystem* aOS /* = nullptr */)
895
896 {
897 NS_ENSURE_ARG_POINTER(aStatus);
898 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
899 aSuggestedDriverVersion.SetIsVoid(true);
900 OperatingSystem os = OperatingSystem::Linux;
901 if (aOS) *aOS = os;
902
903 if (sShutdownOccurred) {
904 return NS_OK;
905 }
906
907 GetData();
908
909 if (mGlxTestError) {
910 // If glxtest failed, block all features by default.
911 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
912 aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
913 return NS_OK;
914 }
915
916 if (mGLMajorVersion == 1) {
917 // We're on OpenGL 1. In most cases that indicates really old hardware.
918 // We better block them, rather than rely on them to fail gracefully,
919 // because they don't! see bug 696636
920 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
921 aFailureId = "FEATURE_FAILURE_OPENGL_1";
922 return NS_OK;
923 }
924
925 // Blocklist software GL implementations from using layers acceleration.
926 // On the test infrastructure, we'll force-enable layers acceleration.
927 if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && !mIsAccelerated &&
928 !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
929 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
930 aFailureId = "FEATURE_FAILURE_SOFTWARE_GL";
931 return NS_OK;
932 }
933
934 if (aFeature == nsIGfxInfo::FEATURE_WEBRENDER) {
935 for (const nsCString& driver : mDdxDrivers) {
936 if (strcasestr(driver.get(), "Intel")) {
937 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
938 aFailureId = "FEATURE_FAILURE_DDX_INTEL";
939 return NS_OK;
940 }
941 }
942 }
943
944 return GfxInfoBase::GetFeatureStatusImpl(
945 aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
946 }
947
948 NS_IMETHODIMP
GetD2DEnabled(bool * aEnabled)949 GfxInfo::GetD2DEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
950
951 NS_IMETHODIMP
GetDWriteEnabled(bool * aEnabled)952 GfxInfo::GetDWriteEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
953
954 NS_IMETHODIMP
GetDWriteVersion(nsAString & aDwriteVersion)955 GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) {
956 return NS_ERROR_FAILURE;
957 }
958
GetHasBattery(bool * aHasBattery)959 NS_IMETHODIMP GfxInfo::GetHasBattery(bool* aHasBattery) {
960 return NS_ERROR_NOT_IMPLEMENTED;
961 }
962
963 NS_IMETHODIMP
GetEmbeddedInFirefoxReality(bool * aEmbeddedInFirefoxReality)964 GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality) {
965 return NS_ERROR_FAILURE;
966 }
967
968 NS_IMETHODIMP
GetCleartypeParameters(nsAString & aCleartypeParams)969 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) {
970 return NS_ERROR_FAILURE;
971 }
972
973 NS_IMETHODIMP
GetWindowProtocol(nsAString & aWindowProtocol)974 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
975 GetData();
976 if (mIsWayland) {
977 aWindowProtocol = GfxDriverInfo::GetWindowProtocol(WindowProtocol::Wayland);
978 } else if (mIsXWayland) {
979 aWindowProtocol =
980 GfxDriverInfo::GetWindowProtocol(WindowProtocol::XWayland);
981 } else {
982 aWindowProtocol = GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11);
983 }
984 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_LINUX_WINDOW_PROTOCOL,
985 aWindowProtocol);
986 return NS_OK;
987 }
988
989 NS_IMETHODIMP
GetDesktopEnvironment(nsAString & aDesktopEnvironment)990 GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
991 GetData();
992 AppendASCIItoUTF16(mDesktopEnvironment, aDesktopEnvironment);
993 return NS_OK;
994 }
995
996 NS_IMETHODIMP
GetTestType(nsAString & aTestType)997 GfxInfo::GetTestType(nsAString& aTestType) {
998 GetData();
999 AppendASCIItoUTF16(mTestType, aTestType);
1000 return NS_OK;
1001 }
1002
1003 NS_IMETHODIMP
GetAdapterDescription(nsAString & aAdapterDescription)1004 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
1005 GetData();
1006 AppendASCIItoUTF16(mAdapterDescription, aAdapterDescription);
1007 return NS_OK;
1008 }
1009
1010 NS_IMETHODIMP
GetAdapterDescription2(nsAString & aAdapterDescription)1011 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
1012 return NS_ERROR_FAILURE;
1013 }
1014
1015 NS_IMETHODIMP
GetAdapterRAM(uint32_t * aAdapterRAM)1016 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM) {
1017 GetData();
1018 *aAdapterRAM = mAdapterRAM;
1019 return NS_OK;
1020 }
1021
1022 NS_IMETHODIMP
GetAdapterRAM2(uint32_t * aAdapterRAM)1023 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM) { return NS_ERROR_FAILURE; }
1024
1025 NS_IMETHODIMP
GetAdapterDriver(nsAString & aAdapterDriver)1026 GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) {
1027 aAdapterDriver.Truncate();
1028 return NS_OK;
1029 }
1030
1031 NS_IMETHODIMP
GetAdapterDriver2(nsAString & aAdapterDriver)1032 GfxInfo::GetAdapterDriver2(nsAString& aAdapterDriver) {
1033 return NS_ERROR_FAILURE;
1034 }
1035
1036 NS_IMETHODIMP
GetAdapterDriverVendor(nsAString & aAdapterDriverVendor)1037 GfxInfo::GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) {
1038 GetData();
1039 CopyASCIItoUTF16(mDriverVendor, aAdapterDriverVendor);
1040 return NS_OK;
1041 }
1042
1043 NS_IMETHODIMP
GetAdapterDriverVendor2(nsAString & aAdapterDriverVendor)1044 GfxInfo::GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor) {
1045 return NS_ERROR_FAILURE;
1046 }
1047
1048 NS_IMETHODIMP
GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)1049 GfxInfo::GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) {
1050 GetData();
1051 CopyASCIItoUTF16(mDriverVersion, aAdapterDriverVersion);
1052 return NS_OK;
1053 }
1054
1055 NS_IMETHODIMP
GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)1056 GfxInfo::GetAdapterDriverVersion2(nsAString& aAdapterDriverVersion) {
1057 return NS_ERROR_FAILURE;
1058 }
1059
1060 NS_IMETHODIMP
GetAdapterDriverDate(nsAString & aAdapterDriverDate)1061 GfxInfo::GetAdapterDriverDate(nsAString& aAdapterDriverDate) {
1062 aAdapterDriverDate.Truncate();
1063 return NS_OK;
1064 }
1065
1066 NS_IMETHODIMP
GetAdapterDriverDate2(nsAString & aAdapterDriverDate)1067 GfxInfo::GetAdapterDriverDate2(nsAString& aAdapterDriverDate) {
1068 return NS_ERROR_FAILURE;
1069 }
1070
1071 NS_IMETHODIMP
GetAdapterVendorID(nsAString & aAdapterVendorID)1072 GfxInfo::GetAdapterVendorID(nsAString& aAdapterVendorID) {
1073 GetData();
1074 CopyUTF8toUTF16(mVendorId, aAdapterVendorID);
1075 return NS_OK;
1076 }
1077
1078 NS_IMETHODIMP
GetAdapterVendorID2(nsAString & aAdapterVendorID)1079 GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) {
1080 GetData();
1081 CopyUTF8toUTF16(mSecondaryVendorId, aAdapterVendorID);
1082 return NS_OK;
1083 }
1084
1085 NS_IMETHODIMP
GetAdapterDeviceID(nsAString & aAdapterDeviceID)1086 GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) {
1087 GetData();
1088 CopyUTF8toUTF16(mDeviceId, aAdapterDeviceID);
1089 return NS_OK;
1090 }
1091
1092 NS_IMETHODIMP
GetAdapterDeviceID2(nsAString & aAdapterDeviceID)1093 GfxInfo::GetAdapterDeviceID2(nsAString& aAdapterDeviceID) {
1094 GetData();
1095 CopyUTF8toUTF16(mSecondaryDeviceId, aAdapterDeviceID);
1096 return NS_OK;
1097 }
1098
1099 NS_IMETHODIMP
GetAdapterSubsysID(nsAString & aAdapterSubsysID)1100 GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) {
1101 return NS_ERROR_FAILURE;
1102 }
1103
1104 NS_IMETHODIMP
GetAdapterSubsysID2(nsAString & aAdapterSubsysID)1105 GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
1106 return NS_ERROR_FAILURE;
1107 }
1108
1109 NS_IMETHODIMP
GetDisplayInfo(nsTArray<nsString> & aDisplayInfo)1110 GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
1111 GetData();
1112
1113 for (auto screenInfo : mScreenInfo) {
1114 nsString infoString;
1115 infoString.AppendPrintf("%dx%d %s", screenInfo.mWidth, screenInfo.mHeight,
1116 screenInfo.mIsDefault ? "default" : "");
1117 aDisplayInfo.AppendElement(infoString);
1118 }
1119
1120 return aDisplayInfo.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
1121 }
1122
1123 NS_IMETHODIMP
GetDisplayWidth(nsTArray<uint32_t> & aDisplayWidth)1124 GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
1125 for (auto screenInfo : mScreenInfo) {
1126 aDisplayWidth.AppendElement((uint32_t)screenInfo.mWidth);
1127 }
1128 return NS_OK;
1129 }
1130
1131 NS_IMETHODIMP
GetDisplayHeight(nsTArray<uint32_t> & aDisplayHeight)1132 GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
1133 for (auto screenInfo : mScreenInfo) {
1134 aDisplayHeight.AppendElement((uint32_t)screenInfo.mHeight);
1135 }
1136 return NS_OK;
1137 }
1138
1139 NS_IMETHODIMP
GetIsGPU2Active(bool * aIsGPU2Active)1140 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
1141 // This is never the case, as the active GPU should be the primary GPU.
1142 *aIsGPU2Active = false;
1143 return NS_OK;
1144 }
1145
1146 NS_IMETHODIMP
GetDrmRenderDevice(nsACString & aDrmRenderDevice)1147 GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
1148 GetData();
1149 aDrmRenderDevice.Assign(mDrmRenderDevice);
1150 return NS_OK;
1151 }
1152
1153 #ifdef DEBUG
1154
1155 // Implement nsIGfxInfoDebug
1156 // We don't support spoofing anything on Linux
1157
SpoofVendorID(const nsAString & aVendorID)1158 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString& aVendorID) {
1159 GetData();
1160 CopyUTF16toUTF8(aVendorID, mVendorId);
1161 mIsAccelerated = true;
1162 return NS_OK;
1163 }
1164
SpoofDeviceID(const nsAString & aDeviceID)1165 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString& aDeviceID) {
1166 GetData();
1167 CopyUTF16toUTF8(aDeviceID, mDeviceId);
1168 return NS_OK;
1169 }
1170
SpoofDriverVersion(const nsAString & aDriverVersion)1171 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString& aDriverVersion) {
1172 GetData();
1173 CopyUTF16toUTF8(aDriverVersion, mDriverVersion);
1174 return NS_OK;
1175 }
1176
SpoofOSVersion(uint32_t aVersion)1177 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
1178 // We don't support OS versioning on Linux. There's just "Linux".
1179 return NS_OK;
1180 }
1181
FireTestProcess()1182 NS_IMETHODIMP GfxInfo::FireTestProcess() {
1183 // If the pid is zero, then we have never run the test process to query for
1184 // driver information. This would normally be run on startup, but we need to
1185 // manually invoke it for XPC shell tests.
1186 if (glxtest_pid == 0) {
1187 fire_glxtest_process();
1188 }
1189 return NS_OK;
1190 }
1191
1192 #endif
1193
1194 } // namespace mozilla::widget
1195