Bug 1751217 Part 3: Make HDR-capable macOS screens report 30 pixelDepth. r=mstange
[gecko.git] / widget / gtk / GfxInfo.cpp
blob889b253ce9a4db05d0b98a9c40cb65d1d3250361
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/. */
8 #include "GfxInfo.h"
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>
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"
29 #define EXIT_STATUS_BUFFER_TOO_SMALL 2
30 #ifdef DEBUG
31 bool fire_glxtest_process();
32 #endif
34 namespace mozilla::widget {
36 #ifdef DEBUG
37 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
38 #endif
40 // these global variables will be set when firing the glxtest process
41 int glxtest_pipe = -1;
42 pid_t glxtest_pid = 0;
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();
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);
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);
80 CrashReporter::AppendAppNotesToCrashReport(note);
84 void GfxInfo::GetData() {
85 GfxInfoBase::GetData();
87 // to understand this function, see bug 639842. We retrieve the OpenGL driver
88 // information in a separate process to protect against bad drivers.
90 // if glxtest_pipe == -1, that means that we already read the information
91 if (glxtest_pipe == -1) return;
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;
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";
109 // let buf be a zero-terminated string
110 buf[bytesread] = 0;
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);
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;
143 bool received_signal =
144 !waiting_for_glxtest_process_failed && WIFSIGNALED(glxtest_status);
146 bool error = waiting_for_glxtest_process_failed || exited_with_error_code ||
147 received_signal;
148 bool errorLog = false;
150 nsCString glVendor;
151 nsCString glRenderer;
152 nsCString glVersion;
153 nsCString textureFromPixmap;
154 nsCString testType;
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;
165 nsCString drmRenderDevice;
167 nsCString ddxDriver;
169 AutoTArray<nsCString, 2> pciVendors;
170 AutoTArray<nsCString, 2> pciDevices;
172 nsCString* stringToFill = nullptr;
173 bool logString = false;
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;
223 MOZ_ASSERT(pciDevices.Length() == pciVendors.Length(),
224 "Missing PCI vendors/devices");
226 size_t pciLen = std::min(pciVendors.Length(), pciDevices.Length());
227 mHasMultipleGPUs = pciLen > 1;
229 if (!strcmp(textureFromPixmap.get(), "TRUE")) mHasTextureFromPixmap = true;
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);
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);
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);
269 if (mGLMajorVersion == 0) {
270 NS_WARNING("Failed to parse GL version!");
273 mDrmRenderDevice = std::move(drmRenderDevice);
274 mTestType = std::move(testType);
276 // Mesa always exposes itself in the GL_VERSION string, but not always the
277 // GL_VENDOR string.
278 mIsMesa = glVersion.Find("Mesa") != -1;
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 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWRast),
299 mDriverVendor);
300 mIsAccelerated = false;
301 } else if (!mIsAccelerated) {
302 CopyUTF16toUTF8(
303 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWUnknown),
304 mDriverVendor);
305 } else if (!driDriver.IsEmpty()) {
306 mDriverVendor = nsPrintfCString("mesa/%s", driDriver.get());
307 } else {
308 // Some other mesa configuration where we couldn't get enough info.
309 NS_WARNING("Failed to detect Mesa driver being used!");
310 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaUnknown),
311 mDriverVendor);
314 if (!mesaVendor.IsEmpty()) {
315 mVendorId = mesaVendor;
318 if (!mesaDevice.IsEmpty()) {
319 mDeviceId = mesaDevice;
322 if (!mIsAccelerated && mVendorId.IsEmpty()) {
323 mVendorId.Assign(glVendor.get());
326 if (!mIsAccelerated && mDeviceId.IsEmpty()) {
327 mDeviceId.Assign(glRenderer.get());
329 } else if (glVendor.EqualsLiteral("NVIDIA Corporation")) {
330 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
331 mVendorId);
332 mDriverVendor.AssignLiteral("nvidia/unknown");
333 // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM.
334 } else if (glVendor.EqualsLiteral("ATI Technologies Inc.")) {
335 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
336 mVendorId);
337 mDriverVendor.AssignLiteral("ati/unknown");
338 // TODO: Look into ways to find the device ID on FGLRX.
339 } else {
340 NS_WARNING("Failed to detect GL vendor!");
343 if (!screenInfo.IsEmpty()) {
344 PRInt32 start = 0;
345 PRInt32 loc = screenInfo.Find(";", PR_FALSE, start);
346 while (loc != kNotFound) {
347 int isDefault = 0;
348 nsCString line(screenInfo.get() + start, loc - start);
349 ScreenInfo info{};
350 if (sscanf(line.get(), "%ux%u:%u", &info.mWidth, &info.mHeight,
351 &isDefault) == 3) {
352 info.mIsDefault = isDefault != 0;
353 mScreenInfo.AppendElement(info);
356 start = loc + 1;
357 loc = screenInfo.Find(";", PR_FALSE, start);
361 if (!adapterRam.IsEmpty()) {
362 mAdapterRAM = (uint32_t)atoi(adapterRam.get());
365 // If we have the DRI driver, we can derive the vendor ID from that if needed.
366 if (mVendorId.IsEmpty() && !driDriver.IsEmpty()) {
367 const char* nvidiaDrivers[] = {"nouveau", "tegra", nullptr};
368 for (size_t i = 0; nvidiaDrivers[i]; ++i) {
369 if (driDriver.Equals(nvidiaDrivers[i])) {
370 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
371 mVendorId);
372 break;
376 if (mVendorId.IsEmpty()) {
377 const char* intelDrivers[] = {"iris", "i915", "i965",
378 "i810", "intel", nullptr};
379 for (size_t i = 0; intelDrivers[i]; ++i) {
380 if (driDriver.Equals(intelDrivers[i])) {
381 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel),
382 mVendorId);
383 break;
388 if (mVendorId.IsEmpty()) {
389 const char* amdDrivers[] = {"r600", "r200", "r100",
390 "radeon", "radeonsi", nullptr};
391 for (size_t i = 0; amdDrivers[i]; ++i) {
392 if (driDriver.Equals(amdDrivers[i])) {
393 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
394 mVendorId);
395 break;
400 if (mVendorId.IsEmpty()) {
401 if (driDriver.EqualsLiteral("freedreno")) {
402 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::Qualcomm),
403 mVendorId);
408 // If we still don't have a vendor ID, we can try the PCI vendor list.
409 if (mVendorId.IsEmpty()) {
410 if (pciVendors.IsEmpty()) {
411 gfxCriticalNote << "No GPUs detected via PCI";
412 } else {
413 for (size_t i = 0; i < pciVendors.Length(); ++i) {
414 if (mVendorId.IsEmpty()) {
415 mVendorId = pciVendors[i];
416 } else if (mVendorId != pciVendors[i]) {
417 gfxCriticalNote << "More than 1 GPU vendor detected via PCI, cannot "
418 "deduce vendor";
419 mVendorId.Truncate();
420 break;
426 // If we know the vendor ID, but didn't get a device ID, we can guess from the
427 // PCI device list.
428 if (mDeviceId.IsEmpty() && !mVendorId.IsEmpty()) {
429 for (size_t i = 0; i < pciLen; ++i) {
430 if (mVendorId.Equals(pciVendors[i])) {
431 if (mDeviceId.IsEmpty()) {
432 mDeviceId = pciDevices[i];
433 } else if (mDeviceId != pciDevices[i]) {
434 gfxCriticalNote << "More than 1 GPU from same vendor detected via "
435 "PCI, cannot deduce device";
436 mDeviceId.Truncate();
437 break;
443 // Assuming we know the vendor, we should check for a secondary card.
444 if (!mVendorId.IsEmpty()) {
445 if (pciLen > 2) {
446 gfxCriticalNote
447 << "More than 2 GPUs detected via PCI, secondary GPU is arbitrary";
449 for (size_t i = 0; i < pciLen; ++i) {
450 if (!mVendorId.Equals(pciVendors[i]) ||
451 (!mDeviceId.IsEmpty() && !mDeviceId.Equals(pciDevices[i]))) {
452 mSecondaryVendorId = pciVendors[i];
453 mSecondaryDeviceId = pciDevices[i];
454 break;
459 // If we couldn't choose, log them.
460 if (mVendorId.IsEmpty()) {
461 for (size_t i = 0; i < pciLen; ++i) {
462 gfxCriticalNote << "PCI candidate " << pciVendors[i].get() << "/"
463 << pciDevices[i].get();
467 // Fallback to GL_VENDOR and GL_RENDERER.
468 if (mVendorId.IsEmpty()) {
469 mVendorId.Assign(glVendor.get());
471 if (mDeviceId.IsEmpty()) {
472 mDeviceId.Assign(glRenderer.get());
475 mAdapterDescription.Assign(glRenderer);
477 // Make a best effort guess at whether or not we are using the XWayland compat
478 // layer. For all intents and purposes, we should otherwise believe we are
479 // using X11.
480 mIsWayland = GdkIsWaylandDisplay();
481 const char* waylandDisplay = getenv("WAYLAND_DISPLAY");
482 mIsXWayland = !mIsWayland && waylandDisplay;
484 // Make a best effort guess at the desktop environment in use. Sadly there
485 // does not appear to be a standard way to do this, so we check a few
486 // different environment variables and search for relevant keywords.
488 // Note that some users manually change these values. Some applications check
489 // the environment variable like we are here, and either not work or restrict
490 // functionality. There may be some heroics we could go through to determine
491 // the truth, but for the moment, this is the best we can do. This is
492 // something to keep in mind when updating the blocklist.
493 const char* desktopEnv = getenv("XDG_CURRENT_DESKTOP");
494 if (!desktopEnv) {
495 desktopEnv = getenv("DESKTOP_SESSION");
498 if (desktopEnv) {
499 std::string currentDesktop(desktopEnv);
500 for (auto& c : currentDesktop) {
501 c = std::tolower(c);
504 if (currentDesktop.find("budgie") != std::string::npos) {
505 // We need to check for Budgie first, because it might incorporate GNOME
506 // into the environment variable value.
507 CopyUTF16toUTF8(
508 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Budgie),
509 mDesktopEnvironment);
510 } else if (currentDesktop.find("gnome") != std::string::npos) {
511 CopyUTF16toUTF8(
512 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
513 mDesktopEnvironment);
514 } else if (currentDesktop.find("kde") != std::string::npos) {
515 CopyUTF16toUTF8(
516 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
517 mDesktopEnvironment);
518 } else if (currentDesktop.find("xfce") != std::string::npos) {
519 CopyUTF16toUTF8(
520 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::XFCE),
521 mDesktopEnvironment);
522 } else if (currentDesktop.find("cinnamon") != std::string::npos) {
523 CopyUTF16toUTF8(
524 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Cinnamon),
525 mDesktopEnvironment);
526 } else if (currentDesktop.find("enlightenment") != std::string::npos) {
527 CopyUTF16toUTF8(GfxDriverInfo::GetDesktopEnvironment(
528 DesktopEnvironment::Enlightenment),
529 mDesktopEnvironment);
530 } else if (currentDesktop.find("lxde") != std::string::npos ||
531 currentDesktop.find("lubuntu") != std::string::npos) {
532 CopyUTF16toUTF8(
533 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXDE),
534 mDesktopEnvironment);
535 } else if (currentDesktop.find("openbox") != std::string::npos) {
536 CopyUTF16toUTF8(
537 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Openbox),
538 mDesktopEnvironment);
539 } else if (currentDesktop.find("i3") != std::string::npos) {
540 CopyUTF16toUTF8(
541 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::i3),
542 mDesktopEnvironment);
543 } else if (currentDesktop.find("sway") != std::string::npos) {
544 CopyUTF16toUTF8(
545 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Sway),
546 mDesktopEnvironment);
547 } else if (currentDesktop.find("mate") != std::string::npos) {
548 CopyUTF16toUTF8(
549 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
550 mDesktopEnvironment);
551 } else if (currentDesktop.find("unity") != std::string::npos) {
552 CopyUTF16toUTF8(
553 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unity),
554 mDesktopEnvironment);
555 } else if (currentDesktop.find("pantheon") != std::string::npos) {
556 CopyUTF16toUTF8(
557 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Pantheon),
558 mDesktopEnvironment);
559 } else if (currentDesktop.find("lxqt") != std::string::npos) {
560 CopyUTF16toUTF8(
561 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
562 mDesktopEnvironment);
563 } else if (currentDesktop.find("deepin") != std::string::npos) {
564 CopyUTF16toUTF8(
565 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Deepin),
566 mDesktopEnvironment);
567 } else if (currentDesktop.find("dwm") != std::string::npos) {
568 CopyUTF16toUTF8(
569 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Dwm),
570 mDesktopEnvironment);
574 if (mDesktopEnvironment.IsEmpty()) {
575 if (getenv("GNOME_DESKTOP_SESSION_ID")) {
576 CopyUTF16toUTF8(
577 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
578 mDesktopEnvironment);
579 } else if (getenv("KDE_FULL_SESSION")) {
580 CopyUTF16toUTF8(
581 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
582 mDesktopEnvironment);
583 } else if (getenv("MATE_DESKTOP_SESSION_ID")) {
584 CopyUTF16toUTF8(
585 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
586 mDesktopEnvironment);
587 } else if (getenv("LXQT_SESSION_CONFIG")) {
588 CopyUTF16toUTF8(
589 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
590 mDesktopEnvironment);
591 } else {
592 CopyUTF16toUTF8(
593 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unknown),
594 mDesktopEnvironment);
598 if (!ddxDriver.IsEmpty()) {
599 PRInt32 start = 0;
600 PRInt32 loc = ddxDriver.Find(";", PR_FALSE, start);
601 while (loc != kNotFound) {
602 nsCString line(ddxDriver.get() + start, loc - start);
603 mDdxDrivers.AppendElement(std::move(line));
605 start = loc + 1;
606 loc = ddxDriver.Find(";", PR_FALSE, start);
610 if (error || errorLog || mTestType.IsEmpty()) {
611 if (!mAdapterDescription.IsEmpty()) {
612 mAdapterDescription.AppendLiteral(" (See failure log)");
613 } else {
614 mAdapterDescription.AppendLiteral("See failure log");
617 mGlxTestError = true;
620 if (error) {
621 nsAutoCString msg("glxtest: process failed");
622 if (waiting_for_glxtest_process_failed) {
623 msg.AppendPrintf(" (waitpid failed with errno=%d for pid %d)",
624 waitpid_errno, glxtest_pid);
627 if (exited_with_error_code) {
628 if (exit_code == EXIT_STATUS_BUFFER_TOO_SMALL) {
629 msg.AppendLiteral(" (buffer too small)");
630 } else {
631 msg.AppendPrintf(" (exited with status %d)",
632 WEXITSTATUS(glxtest_status));
635 if (received_signal) {
636 msg.AppendPrintf(" (received signal %d)", WTERMSIG(glxtest_status));
639 gfxCriticalNote << msg.get();
642 AddCrashReportAnnotations();
645 const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
646 if (!sDriverInfo->Length()) {
647 // Mesa 10.0 provides the GLX_MESA_query_renderer extension, which allows us
648 // to query device IDs backing a GL context for blocklisting.
649 APPEND_TO_DRIVER_BLOCKLIST_EXT(
650 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
651 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
652 DeviceFamily::All, GfxDriverInfo::allFeatures,
653 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
654 V(10, 0, 0, 0), "FEATURE_FAILURE_OLD_MESA", "Mesa 10.0");
656 // NVIDIA Mesa baseline (see bug 1714391).
657 APPEND_TO_DRIVER_BLOCKLIST_EXT(
658 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
659 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaNouveau,
660 DeviceFamily::All, GfxDriverInfo::allFeatures,
661 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
662 V(11, 0, 0, 0), "FEATURE_FAILURE_OLD_NV_MESA", "Mesa 11.0");
664 // NVIDIA baseline (ported from old blocklist)
665 APPEND_TO_DRIVER_BLOCKLIST_EXT(
666 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
667 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
668 DeviceFamily::NvidiaAll, GfxDriverInfo::allFeatures,
669 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
670 V(257, 21, 0, 0), "FEATURE_FAILURE_OLD_NVIDIA", "NVIDIA 257.21");
672 // fglrx baseline (chosen arbitrarily as 2013-07-22 release).
673 APPEND_TO_DRIVER_BLOCKLIST(
674 OperatingSystem::Linux, DeviceFamily::AtiAll,
675 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
676 DRIVER_LESS_THAN, V(13, 15, 100, 1), "FEATURE_FAILURE_OLD_FGLRX",
677 "fglrx 13.15.100.1");
679 ////////////////////////////////////
680 // FEATURE_WEBRENDER
682 // All Mesa software drivers, they should get Software WebRender instead.
683 APPEND_TO_DRIVER_BLOCKLIST_EXT(
684 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
685 DesktopEnvironment::All, WindowProtocol::All,
686 DriverVendor::SoftwareMesaAll, DeviceFamily::All,
687 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
688 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "FEATURE_FAILURE_SOFTWARE_GL",
689 "");
691 APPEND_TO_DRIVER_BLOCKLIST(
692 OperatingSystem::Linux, DeviceFamily::IntelWebRenderBlocked,
693 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
694 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), "INTEL_DEVICE_GEN5_OR_OLDER",
695 "");
697 // Nvidia Mesa baseline, see bug 1563859.
698 APPEND_TO_DRIVER_BLOCKLIST_EXT(
699 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
700 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
701 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
702 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
703 V(18, 2, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.2.0.0");
705 // Disable on all older Nvidia drivers due to stability issues.
706 APPEND_TO_DRIVER_BLOCKLIST_EXT(
707 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
708 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
709 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
710 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN, V(460, 32, 3, 0),
711 "FEATURE_FAILURE_WEBRENDER_OLD_NVIDIA", "460.32.03");
713 // ATI Mesa baseline, chosen arbitrarily.
714 APPEND_TO_DRIVER_BLOCKLIST_EXT(
715 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
716 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
717 DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_WEBRENDER,
718 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
719 V(17, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 17.0.0.0");
721 // Bug 1690568 / Bug 1393793 - Require Mesa 17.3.0+ for devices using the
722 // r600 driver to avoid shader compilation issues.
723 APPEND_TO_DRIVER_BLOCKLIST_EXT(
724 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
725 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaR600,
726 DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
727 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
728 V(17, 3, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA_R600",
729 "Mesa 17.3.0.0");
731 // Disable on all ATI devices not using Mesa for now.
732 APPEND_TO_DRIVER_BLOCKLIST_EXT(
733 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
734 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
735 DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_WEBRENDER,
736 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
737 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_ATI", "");
739 // Bug 1673939 - Garbled text on RS880 GPUs with Mesa drivers.
740 APPEND_TO_DRIVER_BLOCKLIST_EXT(
741 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
742 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
743 DeviceFamily::AmdR600, nsIGfxInfo::FEATURE_WEBRENDER,
744 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
745 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1673939",
746 "https://gitlab.freedesktop.org/mesa/mesa/-/issues/3720");
748 // Bug 1635186 - Poor performance with video playing in a background window
749 // on XWayland. Keep in sync with FEATURE_X11_EGL below to only enable them
750 // together by default. Only Mesa and Nvidia binary drivers are expected
751 // on Wayland rigth now.
752 APPEND_TO_DRIVER_BLOCKLIST_EXT(
753 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
754 DesktopEnvironment::All, WindowProtocol::XWayland,
755 DriverVendor::MesaAll, DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
756 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
757 V(21, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_BUG_1635186",
758 "Mesa 21.0.0.0");
760 ////////////////////////////////////
761 // FEATURE_WEBRENDER - ALLOWLIST
763 #if defined(EARLY_BETA_OR_EARLIER)
764 APPEND_TO_DRIVER_BLOCKLIST_EXT(
765 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
766 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
767 DeviceFamily::All, nsIGfxInfo::FEATURE_WEBRENDER,
768 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL,
769 V(21, 0, 0, 0), "FEATURE_MESA", "Mesa 21.0.0.0");
770 #endif
772 // Intel Mesa baseline, chosen arbitrarily.
773 APPEND_TO_DRIVER_BLOCKLIST_EXT(
774 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
775 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
776 DeviceFamily::IntelAll, nsIGfxInfo::FEATURE_WEBRENDER,
777 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL,
778 V(17, 0, 0, 0), "FEATURE_ROLLOUT_INTEL_MESA", "Mesa 17.0.0.0");
780 // Nvidia Mesa baseline, see bug 1563859.
781 APPEND_TO_DRIVER_BLOCKLIST_EXT(
782 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
783 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
784 DeviceFamily::NvidiaRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
785 nsIGfxInfo::FEATURE_ALLOW_QUALIFIED, DRIVER_GREATER_THAN_OR_EQUAL,
786 V(18, 2, 0, 0), "FEATURE_ROLLOUT_NVIDIA_MESA", "Mesa 18.2.0.0");
788 // Nvidia proprietary driver baseline, see bug 1742994.
789 APPEND_TO_DRIVER_BLOCKLIST_EXT(
790 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
791 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
792 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER,
793 nsIGfxInfo::FEATURE_ALLOW_QUALIFIED, DRIVER_GREATER_THAN_OR_EQUAL,
794 V(470, 82, 0, 0), "FEATURE_ROLLOUT_NVIDIA_BINARY", "470.82.0");
796 // ATI Mesa baseline, chosen arbitrarily.
797 APPEND_TO_DRIVER_BLOCKLIST_EXT(
798 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
799 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
800 DeviceFamily::AtiRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
801 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL,
802 V(17, 0, 0, 0), "FEATURE_ROLLOUT_ATI_MESA", "Mesa 17.0.0.0");
804 ////////////////////////////////////
805 // FEATURE_WEBRENDER_COMPOSITOR
806 APPEND_TO_DRIVER_BLOCKLIST(
807 OperatingSystem::Linux, DeviceFamily::All,
808 nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
809 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
810 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_COMPOSITOR_DISABLED", "");
812 ////////////////////////////////////
813 // FEATURE_X11_EGL
814 APPEND_TO_DRIVER_BLOCKLIST_EXT(
815 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
816 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll,
817 DeviceFamily::All, nsIGfxInfo::FEATURE_X11_EGL,
818 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
819 V(21, 0, 0, 0), "FEATURE_ROLLOUT_X11_EGL_MESA", "Mesa 21.0.0.0");
821 APPEND_TO_DRIVER_BLOCKLIST_EXT(
822 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
823 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
824 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_X11_EGL,
825 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
826 V(470, 82, 0, 0), "FEATURE_ROLLOUT_X11_EGL_NVIDIA_BINARY", "470.82.0");
828 // Disable on all AMD devices not using Mesa.
829 APPEND_TO_DRIVER_BLOCKLIST_EXT(
830 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
831 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
832 DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_X11_EGL,
833 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
834 V(0, 0, 0, 0), "FEATURE_FAILURE_X11_EGL_NO_LINUX_ATI", "");
836 ////////////////////////////////////
837 // FEATURE_DMABUF
838 APPEND_TO_DRIVER_BLOCKLIST_EXT(
839 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
840 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll,
841 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_DMABUF,
842 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
843 V(495, 44, 0, 0), "FEATURE_FAILURE_NO_GBM", "495.44.0");
845 ////////////////////////////////////
846 // FEATURE_WEBRENDER_PARTIAL_PRESENT
847 APPEND_TO_DRIVER_BLOCKLIST_EXT(
848 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
849 DesktopEnvironment::All, WindowProtocol::X11, DriverVendor::NonMesaAll,
850 DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_WEBRENDER_PARTIAL_PRESENT,
851 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
852 V(0, 0, 0, 0), "FEATURE_ROLLOUT_WR_PARTIAL_PRESENT_NVIDIA_BINARY", "");
854 ////////////////////////////////////
856 APPEND_TO_DRIVER_BLOCKLIST_EXT(
857 OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All,
858 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaNouveau,
859 DeviceFamily::All, nsIGfxInfo::FEATURE_THREADSAFE_GL,
860 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
861 V(0, 0, 0, 0), "FEATURE_FAILURE_THREADSAFE_GL", "");
863 return *sDriverInfo;
866 bool GfxInfo::DoesWindowProtocolMatch(const nsAString& aBlocklistWindowProtocol,
867 const nsAString& aWindowProtocol) {
868 if (mIsWayland &&
869 aBlocklistWindowProtocol.Equals(
870 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandAll),
871 nsCaseInsensitiveStringComparator)) {
872 return true;
874 if (!mIsWayland &&
875 aBlocklistWindowProtocol.Equals(
876 GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11All),
877 nsCaseInsensitiveStringComparator)) {
878 return true;
880 return GfxInfoBase::DoesWindowProtocolMatch(aBlocklistWindowProtocol,
881 aWindowProtocol);
884 bool GfxInfo::DoesDriverVendorMatch(const nsAString& aBlocklistVendor,
885 const nsAString& aDriverVendor) {
886 if (mIsMesa) {
887 if (aBlocklistVendor.Equals(
888 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaAll),
889 nsCaseInsensitiveStringComparator)) {
890 return true;
892 if (mIsAccelerated &&
893 aBlocklistVendor.Equals(
894 GfxDriverInfo::GetDriverVendor(DriverVendor::HardwareMesaAll),
895 nsCaseInsensitiveStringComparator)) {
896 return true;
898 if (!mIsAccelerated &&
899 aBlocklistVendor.Equals(
900 GfxDriverInfo::GetDriverVendor(DriverVendor::SoftwareMesaAll),
901 nsCaseInsensitiveStringComparator)) {
902 return true;
905 if (!mIsMesa && aBlocklistVendor.Equals(
906 GfxDriverInfo::GetDriverVendor(DriverVendor::NonMesaAll),
907 nsCaseInsensitiveStringComparator)) {
908 return true;
910 return GfxInfoBase::DoesDriverVendorMatch(aBlocklistVendor, aDriverVendor);
913 nsresult GfxInfo::GetFeatureStatusImpl(
914 int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion,
915 const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
916 OperatingSystem* aOS /* = nullptr */)
919 NS_ENSURE_ARG_POINTER(aStatus);
920 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
921 aSuggestedDriverVersion.SetIsVoid(true);
922 OperatingSystem os = OperatingSystem::Linux;
923 if (aOS) *aOS = os;
925 if (sShutdownOccurred) {
926 return NS_OK;
929 GetData();
931 if (mGlxTestError) {
932 // If glxtest failed, block all features by default.
933 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
934 aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
935 return NS_OK;
938 if (mGLMajorVersion == 1) {
939 // We're on OpenGL 1. In most cases that indicates really old hardware.
940 // We better block them, rather than rely on them to fail gracefully,
941 // because they don't! see bug 696636
942 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
943 aFailureId = "FEATURE_FAILURE_OPENGL_1";
944 return NS_OK;
947 // Blocklist software GL implementations from using layers acceleration.
948 // On the test infrastructure, we'll force-enable layers acceleration.
949 if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && !mIsAccelerated &&
950 !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
951 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
952 aFailureId = "FEATURE_FAILURE_SOFTWARE_GL";
953 return NS_OK;
956 if (aFeature == nsIGfxInfo::FEATURE_WEBRENDER) {
957 // Don't try Webrender on devices where we are guaranteed to fail.
958 if (mGLMajorVersion < 3) {
959 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
960 aFailureId = "FEATURE_FAILURE_OPENGL_LESS_THAN_3";
961 return NS_OK;
964 // Bug 1710400: Disable Webrender on the deprecated Intel DDX driver
965 for (const nsCString& driver : mDdxDrivers) {
966 if (strcasestr(driver.get(), "Intel")) {
967 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
968 aFailureId = "FEATURE_FAILURE_DDX_INTEL";
969 return NS_OK;
974 return GfxInfoBase::GetFeatureStatusImpl(
975 aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
978 NS_IMETHODIMP
979 GfxInfo::GetD2DEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
981 NS_IMETHODIMP
982 GfxInfo::GetDWriteEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
984 NS_IMETHODIMP
985 GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) {
986 return NS_ERROR_FAILURE;
989 NS_IMETHODIMP GfxInfo::GetHasBattery(bool* aHasBattery) {
990 return NS_ERROR_NOT_IMPLEMENTED;
993 NS_IMETHODIMP
994 GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality) {
995 return NS_ERROR_FAILURE;
998 NS_IMETHODIMP
999 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) {
1000 return NS_ERROR_FAILURE;
1003 NS_IMETHODIMP
1004 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
1005 GetData();
1006 if (mIsWayland) {
1007 aWindowProtocol = GfxDriverInfo::GetWindowProtocol(WindowProtocol::Wayland);
1008 } else if (mIsXWayland) {
1009 aWindowProtocol =
1010 GfxDriverInfo::GetWindowProtocol(WindowProtocol::XWayland);
1011 } else {
1012 aWindowProtocol = GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11);
1014 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_LINUX_WINDOW_PROTOCOL,
1015 aWindowProtocol);
1016 return NS_OK;
1019 NS_IMETHODIMP
1020 GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
1021 GetData();
1022 AppendASCIItoUTF16(mDesktopEnvironment, aDesktopEnvironment);
1023 return NS_OK;
1026 NS_IMETHODIMP
1027 GfxInfo::GetTestType(nsAString& aTestType) {
1028 GetData();
1029 AppendASCIItoUTF16(mTestType, aTestType);
1030 return NS_OK;
1033 NS_IMETHODIMP
1034 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
1035 GetData();
1036 AppendASCIItoUTF16(mAdapterDescription, aAdapterDescription);
1037 return NS_OK;
1040 NS_IMETHODIMP
1041 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
1042 return NS_ERROR_FAILURE;
1045 NS_IMETHODIMP
1046 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM) {
1047 GetData();
1048 *aAdapterRAM = mAdapterRAM;
1049 return NS_OK;
1052 NS_IMETHODIMP
1053 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM) { return NS_ERROR_FAILURE; }
1055 NS_IMETHODIMP
1056 GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) {
1057 aAdapterDriver.Truncate();
1058 return NS_OK;
1061 NS_IMETHODIMP
1062 GfxInfo::GetAdapterDriver2(nsAString& aAdapterDriver) {
1063 return NS_ERROR_FAILURE;
1066 NS_IMETHODIMP
1067 GfxInfo::GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) {
1068 GetData();
1069 CopyASCIItoUTF16(mDriverVendor, aAdapterDriverVendor);
1070 return NS_OK;
1073 NS_IMETHODIMP
1074 GfxInfo::GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor) {
1075 return NS_ERROR_FAILURE;
1078 NS_IMETHODIMP
1079 GfxInfo::GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) {
1080 GetData();
1081 CopyASCIItoUTF16(mDriverVersion, aAdapterDriverVersion);
1082 return NS_OK;
1085 NS_IMETHODIMP
1086 GfxInfo::GetAdapterDriverVersion2(nsAString& aAdapterDriverVersion) {
1087 return NS_ERROR_FAILURE;
1090 NS_IMETHODIMP
1091 GfxInfo::GetAdapterDriverDate(nsAString& aAdapterDriverDate) {
1092 aAdapterDriverDate.Truncate();
1093 return NS_OK;
1096 NS_IMETHODIMP
1097 GfxInfo::GetAdapterDriverDate2(nsAString& aAdapterDriverDate) {
1098 return NS_ERROR_FAILURE;
1101 NS_IMETHODIMP
1102 GfxInfo::GetAdapterVendorID(nsAString& aAdapterVendorID) {
1103 GetData();
1104 CopyUTF8toUTF16(mVendorId, aAdapterVendorID);
1105 return NS_OK;
1108 NS_IMETHODIMP
1109 GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) {
1110 GetData();
1111 CopyUTF8toUTF16(mSecondaryVendorId, aAdapterVendorID);
1112 return NS_OK;
1115 NS_IMETHODIMP
1116 GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) {
1117 GetData();
1118 CopyUTF8toUTF16(mDeviceId, aAdapterDeviceID);
1119 return NS_OK;
1122 NS_IMETHODIMP
1123 GfxInfo::GetAdapterDeviceID2(nsAString& aAdapterDeviceID) {
1124 GetData();
1125 CopyUTF8toUTF16(mSecondaryDeviceId, aAdapterDeviceID);
1126 return NS_OK;
1129 NS_IMETHODIMP
1130 GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) {
1131 return NS_ERROR_FAILURE;
1134 NS_IMETHODIMP
1135 GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
1136 return NS_ERROR_FAILURE;
1139 NS_IMETHODIMP
1140 GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
1141 GetData();
1143 for (auto screenInfo : mScreenInfo) {
1144 nsString infoString;
1145 infoString.AppendPrintf("%dx%d %s", screenInfo.mWidth, screenInfo.mHeight,
1146 screenInfo.mIsDefault ? "default" : "");
1147 aDisplayInfo.AppendElement(infoString);
1150 return aDisplayInfo.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
1153 NS_IMETHODIMP
1154 GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
1155 for (auto screenInfo : mScreenInfo) {
1156 aDisplayWidth.AppendElement((uint32_t)screenInfo.mWidth);
1158 return NS_OK;
1161 NS_IMETHODIMP
1162 GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
1163 for (auto screenInfo : mScreenInfo) {
1164 aDisplayHeight.AppendElement((uint32_t)screenInfo.mHeight);
1166 return NS_OK;
1169 NS_IMETHODIMP
1170 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
1171 // This is never the case, as the active GPU should be the primary GPU.
1172 *aIsGPU2Active = false;
1173 return NS_OK;
1176 NS_IMETHODIMP
1177 GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
1178 GetData();
1179 aDrmRenderDevice.Assign(mDrmRenderDevice);
1180 return NS_OK;
1183 #ifdef DEBUG
1185 // Implement nsIGfxInfoDebug
1186 // We don't support spoofing anything on Linux
1188 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString& aVendorID) {
1189 GetData();
1190 CopyUTF16toUTF8(aVendorID, mVendorId);
1191 mIsAccelerated = true;
1192 return NS_OK;
1195 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString& aDeviceID) {
1196 GetData();
1197 CopyUTF16toUTF8(aDeviceID, mDeviceId);
1198 return NS_OK;
1201 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString& aDriverVersion) {
1202 GetData();
1203 CopyUTF16toUTF8(aDriverVersion, mDriverVersion);
1204 return NS_OK;
1207 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
1208 // We don't support OS versioning on Linux. There's just "Linux".
1209 return NS_OK;
1212 NS_IMETHODIMP GfxInfo::FireTestProcess() {
1213 // If the pid is zero, then we have never run the test process to query for
1214 // driver information. This would normally be run on startup, but we need to
1215 // manually invoke it for XPC shell tests.
1216 if (glxtest_pid == 0) {
1217 fire_glxtest_process();
1219 return NS_OK;
1222 #endif
1224 } // namespace mozilla::widget