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