1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
12 #include <sys/utsname.h>
15 #include "nsCRTGlue.h"
16 #include "nsExceptionHandler.h"
18 #include "nsPrintfCString.h"
19 #include "nsWhitespaceTokenizer.h"
21 #include "GfxInfoX11.h"
25 # include "mozilla/widget/nsWaylandDisplay.h"
29 bool fire_glxtest_process();
32 namespace mozilla::widget
{
35 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo
, GfxInfoBase
, nsIGfxInfoDebug
)
38 // these global variables will be set when firing the glxtest process
39 int glxtest_pipe
= -1;
40 pid_t glxtest_pid
= 0;
42 nsresult
GfxInfo::Init() {
45 mHasTextureFromPixmap
= false;
47 mIsAccelerated
= true;
49 mIsWaylandDRM
= false;
50 return GfxInfoBase::Init();
53 void GfxInfo::AddCrashReportAnnotations() {
54 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID
,
56 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID
,
58 CrashReporter::AnnotateCrashReport(
59 CrashReporter::Annotation::AdapterDriverVendor
, mDriverVendor
);
60 CrashReporter::AnnotateCrashReport(
61 CrashReporter::Annotation::AdapterDriverVersion
, mDriverVersion
);
62 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWayland
,
64 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWaylandDRM
,
66 CrashReporter::AnnotateCrashReport(
67 CrashReporter::Annotation::DesktopEnvironment
, mDesktopEnvironment
);
70 void GfxInfo::GetData() {
71 GfxInfoBase::GetData();
73 // to understand this function, see bug 639842. We retrieve the OpenGL driver
74 // information in a separate process to protect against bad drivers.
76 // if glxtest_pipe == -1, that means that we already read the information
77 if (glxtest_pipe
== -1) return;
79 enum { buf_size
= 1024 };
81 ssize_t bytesread
= read(glxtest_pipe
, &buf
,
82 buf_size
- 1); // -1 because we'll append a zero
86 // bytesread < 0 would mean that the above read() call failed.
87 // This should never happen. If it did, the outcome would be to blacklist
89 if (bytesread
< 0) bytesread
= 0;
91 // let buf be a zero-terminated string
94 // Wait for the glxtest process to finish. This serves 2 purposes:
95 // * avoid having a zombie glxtest process laying around
96 // * get the glxtest process status info.
97 int glxtest_status
= 0;
98 bool wait_for_glxtest_process
= true;
99 bool waiting_for_glxtest_process_failed
= false;
100 int waitpid_errno
= 0;
101 while (wait_for_glxtest_process
) {
102 wait_for_glxtest_process
= false;
103 if (waitpid(glxtest_pid
, &glxtest_status
, 0) == -1) {
104 waitpid_errno
= errno
;
105 if (waitpid_errno
== EINTR
) {
106 wait_for_glxtest_process
= true;
109 // ECHILD happens when the glxtest process got reaped got reaped after a
110 // PR_CreateProcess as per bug 227246. This shouldn't matter, as we
111 // still seem to get the data from the pipe, and if we didn't, the
112 // outcome would be to blacklist anyway.
113 waiting_for_glxtest_process_failed
= (waitpid_errno
!= ECHILD
);
118 bool exited_with_error_code
= !waiting_for_glxtest_process_failed
&&
119 WIFEXITED(glxtest_status
) &&
120 WEXITSTATUS(glxtest_status
) != EXIT_SUCCESS
;
121 bool received_signal
=
122 !waiting_for_glxtest_process_failed
&& WIFSIGNALED(glxtest_status
);
124 bool error
= waiting_for_glxtest_process_failed
|| exited_with_error_code
||
128 nsCString glRenderer
;
130 nsCString textureFromPixmap
;
132 // Available if GLX_MESA_query_renderer is supported.
133 nsCString mesaVendor
;
134 nsCString mesaDevice
;
135 nsCString mesaAccelerated
;
136 // Available if using a DRI-based libGL stack.
138 nsCString screenInfo
;
139 nsCString adapterRam
;
141 nsCString
* stringToFill
= nullptr;
146 char* line
= NS_strtok("\n", &bufptr
);
149 stringToFill
->Assign(line
);
150 stringToFill
= nullptr;
151 } else if (!strcmp(line
, "VENDOR"))
152 stringToFill
= &glVendor
;
153 else if (!strcmp(line
, "RENDERER"))
154 stringToFill
= &glRenderer
;
155 else if (!strcmp(line
, "VERSION"))
156 stringToFill
= &glVersion
;
157 else if (!strcmp(line
, "TFP"))
158 stringToFill
= &textureFromPixmap
;
159 else if (!strcmp(line
, "MESA_VENDOR_ID"))
160 stringToFill
= &mesaVendor
;
161 else if (!strcmp(line
, "MESA_DEVICE_ID"))
162 stringToFill
= &mesaDevice
;
163 else if (!strcmp(line
, "MESA_ACCELERATED"))
164 stringToFill
= &mesaAccelerated
;
165 else if (!strcmp(line
, "MESA_VRAM"))
166 stringToFill
= &adapterRam
;
167 else if (!strcmp(line
, "DRI_DRIVER"))
168 stringToFill
= &driDriver
;
169 else if (!strcmp(line
, "SCREEN_INFO"))
170 stringToFill
= &screenInfo
;
174 if (!strcmp(textureFromPixmap
.get(), "TRUE")) mHasTextureFromPixmap
= true;
176 // only useful for Linux kernel version check for FGLRX driver.
177 // assumes X client == X server, which is sad.
178 struct utsname unameobj
;
179 if (uname(&unameobj
) >= 0) {
180 mOS
.Assign(unameobj
.sysname
);
181 mOSRelease
.Assign(unameobj
.release
);
184 const char* spoofedVendor
= PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
185 if (spoofedVendor
) glVendor
.Assign(spoofedVendor
);
186 const char* spoofedRenderer
= PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
187 if (spoofedRenderer
) glRenderer
.Assign(spoofedRenderer
);
188 const char* spoofedVersion
= PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
189 if (spoofedVersion
) glVersion
.Assign(spoofedVersion
);
190 const char* spoofedOS
= PR_GetEnv("MOZ_GFX_SPOOF_OS");
191 if (spoofedOS
) mOS
.Assign(spoofedOS
);
192 const char* spoofedOSRelease
= PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE");
193 if (spoofedOSRelease
) mOSRelease
.Assign(spoofedOSRelease
);
195 if (error
|| glVendor
.IsEmpty() || glRenderer
.IsEmpty() ||
196 glVersion
.IsEmpty() || mOS
.IsEmpty() || mOSRelease
.IsEmpty()) {
197 mAdapterDescription
.AppendLiteral("GLXtest process failed");
198 if (waiting_for_glxtest_process_failed
)
199 mAdapterDescription
.AppendPrintf(
200 " (waitpid failed with errno=%d for pid %d)", waitpid_errno
,
202 if (exited_with_error_code
)
203 mAdapterDescription
.AppendPrintf(" (exited with status %d)",
204 WEXITSTATUS(glxtest_status
));
206 mAdapterDescription
.AppendPrintf(" (received signal %d)",
207 WTERMSIG(glxtest_status
));
209 mAdapterDescription
.AppendLiteral(": ");
210 mAdapterDescription
.Append(nsDependentCString(buf
));
211 mAdapterDescription
.Append('\n');
214 CrashReporter::AppendAppNotesToCrashReport(mAdapterDescription
);
218 // Scan the GL_VERSION string for the GL and driver versions.
219 nsCWhitespaceTokenizer
tokenizer(glVersion
);
220 while (tokenizer
.hasMoreTokens()) {
221 nsCString
token(tokenizer
.nextToken());
222 unsigned int major
= 0, minor
= 0, revision
= 0, patch
= 0;
223 if (sscanf(token
.get(), "%u.%u.%u.%u", &major
, &minor
, &revision
, &patch
) >=
225 // A survey of GL_VENDOR strings indicates that the first version is
226 // always the GL version, the second is usually the driver version.
227 if (mGLMajorVersion
== 0) {
228 mGLMajorVersion
= major
;
229 mGLMinorVersion
= minor
;
230 } else if (mDriverVersion
.IsEmpty()) { // Not already spoofed.
232 nsPrintfCString("%u.%u.%u.%u", major
, minor
, revision
, patch
);
237 if (mGLMajorVersion
== 0) {
238 NS_WARNING("Failed to parse GL version!");
242 // Mesa always exposes itself in the GL_VERSION string, but not always the
244 mIsMesa
= glVersion
.Find("Mesa") != -1;
246 // We need to use custom driver vendor IDs for mesa so we can treat them
247 // differently than the proprietary drivers.
249 mIsAccelerated
= !mesaAccelerated
.Equals("FALSE");
250 // Process software rasterizers before the DRI driver string; we may be
251 // forcing software rasterization on a DRI-accelerated X server by using
252 // LIBGL_ALWAYS_SOFTWARE or a similar restriction.
253 if (strcasestr(glRenderer
.get(), "llvmpipe")) {
255 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaLLVMPipe
),
257 mIsAccelerated
= false;
258 } else if (strcasestr(glRenderer
.get(), "softpipe")) {
260 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSoftPipe
),
262 mIsAccelerated
= false;
263 } else if (strcasestr(glRenderer
.get(), "software rasterizer") ||
265 // Fallback to reporting swrast if GLX_MESA_query_renderer tells us
266 // we're using an unaccelerated context.
267 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSWRast
),
269 mIsAccelerated
= false;
270 } else if (!driDriver
.IsEmpty()) {
271 mDriverVendor
= nsPrintfCString("mesa/%s", driDriver
.get());
273 // Some other mesa configuration where we couldn't get enough info.
274 NS_WARNING("Failed to detect Mesa driver being used!");
275 CopyUTF16toUTF8(GfxDriverInfo::GetDriverVendor(DriverVendor::MesaUnknown
),
279 if (!mesaVendor
.IsEmpty()) {
280 mVendorId
= mesaVendor
;
283 "Failed to get Mesa vendor ID! GLX_MESA_query_renderer unsupported?");
286 if (!mesaDevice
.IsEmpty()) {
287 mDeviceId
= mesaDevice
;
290 "Failed to get Mesa device ID! GLX_MESA_query_renderer unsupported?");
292 } else if (glVendor
.EqualsLiteral("NVIDIA Corporation")) {
293 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA
),
295 mDriverVendor
.AssignLiteral("nvidia/unknown");
296 // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM.
297 } else if (glVendor
.EqualsLiteral("ATI Technologies Inc.")) {
298 CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI
),
300 mDriverVendor
.AssignLiteral("ati/unknown");
301 // TODO: Look into ways to find the device ID on FGLRX.
303 NS_WARNING("Failed to detect GL vendor!");
306 if (!screenInfo
.IsEmpty()) {
308 PRInt32 loc
= screenInfo
.Find(";", PR_FALSE
, start
);
309 while (loc
!= kNotFound
) {
311 nsCString
line(screenInfo
.get() + start
, loc
- start
);
313 if (sscanf(line
.get(), "%ux%u:%u", &info
.mWidth
, &info
.mHeight
,
315 info
.mIsDefault
= isDefault
!= 0;
316 mScreenInfo
.AppendElement(info
);
320 loc
= screenInfo
.Find(";", PR_FALSE
, start
);
324 if (!adapterRam
.IsEmpty()) {
325 mAdapterRAM
= (uint32_t)atoi(adapterRam
.get());
328 // Fallback to GL_VENDOR and GL_RENDERER.
329 if (mVendorId
.IsEmpty()) {
330 mVendorId
.Assign(glVendor
.get());
332 if (mDeviceId
.IsEmpty()) {
333 mDeviceId
.Assign(glRenderer
.get());
336 mAdapterDescription
.Assign(glRenderer
);
338 mIsWayland
= !GDK_IS_X11_DISPLAY(gdk_display_get_default());
340 mIsWaylandDRM
= nsWaylandDisplay::IsDMABufEnabled();
344 // Make a best effort guess at the desktop environment in use. Sadly there
345 // does not appear to be a standard way to do this, so we check a few
346 // different environment variables and search for relevant keywords.
347 const char* desktopEnv
= getenv("XDG_CURRENT_DESKTOP");
349 desktopEnv
= getenv("DESKTOP_SESSION");
353 std::string
currentDesktop(desktopEnv
);
354 for (auto& c
: currentDesktop
) {
358 if (currentDesktop
.find("gnome") != std::string::npos
) {
360 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME
),
361 mDesktopEnvironment
);
362 } else if (currentDesktop
.find("kde") != std::string::npos
) {
364 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE
),
365 mDesktopEnvironment
);
366 } else if (currentDesktop
.find("xfce") != std::string::npos
) {
368 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::XFCE
),
369 mDesktopEnvironment
);
370 } else if (currentDesktop
.find("cinnamon") != std::string::npos
) {
372 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Cinnamon
),
373 mDesktopEnvironment
);
374 } else if (currentDesktop
.find("enlightenment") != std::string::npos
) {
375 CopyUTF16toUTF8(GfxDriverInfo::GetDesktopEnvironment(
376 DesktopEnvironment::Enlightenment
),
377 mDesktopEnvironment
);
378 } else if (currentDesktop
.find("lxde") != std::string::npos
||
379 currentDesktop
.find("lubuntu") != std::string::npos
) {
381 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXDE
),
382 mDesktopEnvironment
);
383 } else if (currentDesktop
.find("openbox") != std::string::npos
) {
385 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Openbox
),
386 mDesktopEnvironment
);
387 } else if (currentDesktop
.find("i3") != std::string::npos
) {
389 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::i3
),
390 mDesktopEnvironment
);
391 } else if (currentDesktop
.find("mate") != std::string::npos
) {
393 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate
),
394 mDesktopEnvironment
);
395 } else if (currentDesktop
.find("unity") != std::string::npos
) {
397 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unity
),
398 mDesktopEnvironment
);
399 } else if (currentDesktop
.find("pantheon") != std::string::npos
) {
401 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Pantheon
),
402 mDesktopEnvironment
);
403 } else if (currentDesktop
.find("lxqt") != std::string::npos
) {
405 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT
),
406 mDesktopEnvironment
);
407 } else if (currentDesktop
.find("deepin") != std::string::npos
) {
409 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Deepin
),
410 mDesktopEnvironment
);
414 if (mDesktopEnvironment
.IsEmpty()) {
415 if (getenv("GNOME_DESKTOP_SESSION_ID")) {
417 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME
),
418 mDesktopEnvironment
);
419 } else if (getenv("KDE_FULL_SESSION")) {
421 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE
),
422 mDesktopEnvironment
);
423 } else if (getenv("MATE_DESKTOP_SESSION_ID")) {
425 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate
),
426 mDesktopEnvironment
);
427 } else if (getenv("LXQT_SESSION_CONFIG")) {
429 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT
),
430 mDesktopEnvironment
);
433 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unknown
),
434 mDesktopEnvironment
);
438 AddCrashReportAnnotations();
441 const nsTArray
<GfxDriverInfo
>& GfxInfo::GetGfxDriverInfo() {
442 if (!sDriverInfo
->Length()) {
443 // Mesa 10.0 provides the GLX_MESA_query_renderer extension, which allows us
444 // to query device IDs backing a GL context for blacklisting.
445 APPEND_TO_DRIVER_BLOCKLIST_EXT(
446 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
447 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::MesaAll
,
448 DeviceFamily::All
, GfxDriverInfo::allFeatures
,
449 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
, DRIVER_LESS_THAN
,
450 V(10, 0, 0, 0), "FEATURE_FAILURE_OLD_MESA", "Mesa 10.0");
452 // NVIDIA baseline (ported from old blocklist)
453 APPEND_TO_DRIVER_BLOCKLIST_EXT(
454 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
455 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::NonMesaAll
,
456 DeviceFamily::NvidiaAll
, GfxDriverInfo::allFeatures
,
457 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
, DRIVER_LESS_THAN
,
458 V(257, 21, 0, 0), "FEATURE_FAILURE_OLD_NVIDIA", "NVIDIA 257.21");
460 // fglrx baseline (chosen arbitrarily as 2013-07-22 release).
461 APPEND_TO_DRIVER_BLOCKLIST(
462 OperatingSystem::Linux
, DeviceFamily::AtiAll
,
463 GfxDriverInfo::allFeatures
, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
,
464 DRIVER_LESS_THAN
, V(13, 15, 100, 1), "FEATURE_FAILURE_OLD_FGLRX",
465 "fglrx 13.15.100.1");
467 ////////////////////////////////////
470 // Intel Mesa baseline, chosen arbitrarily.
471 APPEND_TO_DRIVER_BLOCKLIST(
472 OperatingSystem::Linux
, DeviceFamily::IntelAll
,
473 nsIGfxInfo::FEATURE_WEBRENDER
,
474 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
, DRIVER_LESS_THAN
,
475 V(18, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.0.0.0");
477 // Nvidia Mesa baseline, see bug 1563859.
478 APPEND_TO_DRIVER_BLOCKLIST_EXT(
479 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
480 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::MesaAll
,
481 DeviceFamily::NvidiaAll
, nsIGfxInfo::FEATURE_WEBRENDER
,
482 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
, DRIVER_LESS_THAN
,
483 V(18, 2, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.2.0.0");
485 // Disable on all Nvidia devices not using Mesa for now.
486 APPEND_TO_DRIVER_BLOCKLIST_EXT(
487 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
488 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::NonMesaAll
,
489 DeviceFamily::NvidiaAll
, nsIGfxInfo::FEATURE_WEBRENDER
,
490 nsIGfxInfo::FEATURE_BLOCKED_DEVICE
, DRIVER_COMPARISON_IGNORED
,
491 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_NVIDIA", "");
493 // ATI Mesa baseline, chosen arbitrarily.
494 APPEND_TO_DRIVER_BLOCKLIST_EXT(
495 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
496 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::MesaAll
,
497 DeviceFamily::AtiAll
, nsIGfxInfo::FEATURE_WEBRENDER
,
498 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION
, DRIVER_LESS_THAN
,
499 V(18, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_OLD_MESA", "Mesa 18.0.0.0");
501 // Disable on all ATI devices not using Mesa for now.
502 APPEND_TO_DRIVER_BLOCKLIST_EXT(
503 OperatingSystem::Linux
, ScreenSizeStatus::All
, BatteryStatus::All
,
504 DesktopEnvironment::All
, WindowProtocol::All
, DriverVendor::NonMesaAll
,
505 DeviceFamily::AtiAll
, nsIGfxInfo::FEATURE_WEBRENDER
,
506 nsIGfxInfo::FEATURE_BLOCKED_DEVICE
, DRIVER_COMPARISON_IGNORED
,
507 V(0, 0, 0, 0), "FEATURE_FAILURE_WEBRENDER_NO_LINUX_ATI", "");
512 bool GfxInfo::DoesWindowProtocolMatch(const nsAString
& aBlocklistWindowProtocol
,
513 const nsAString
& aWindowProtocol
) {
515 aBlocklistWindowProtocol
.Equals(
516 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandAll
),
517 nsCaseInsensitiveStringComparator())) {
520 return GfxInfoBase::DoesWindowProtocolMatch(aBlocklistWindowProtocol
,
524 bool GfxInfo::DoesDriverVendorMatch(const nsAString
& aBlocklistVendor
,
525 const nsAString
& aDriverVendor
) {
526 if (mIsMesa
&& aBlocklistVendor
.Equals(
527 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaAll
),
528 nsCaseInsensitiveStringComparator())) {
531 if (!mIsMesa
&& aBlocklistVendor
.Equals(
532 GfxDriverInfo::GetDriverVendor(DriverVendor::NonMesaAll
),
533 nsCaseInsensitiveStringComparator())) {
536 return GfxInfoBase::DoesDriverVendorMatch(aBlocklistVendor
, aDriverVendor
);
539 nsresult
GfxInfo::GetFeatureStatusImpl(
540 int32_t aFeature
, int32_t* aStatus
, nsAString
& aSuggestedDriverVersion
,
541 const nsTArray
<GfxDriverInfo
>& aDriverInfo
, nsACString
& aFailureId
,
542 OperatingSystem
* aOS
/* = nullptr */)
545 NS_ENSURE_ARG_POINTER(aStatus
);
546 *aStatus
= nsIGfxInfo::FEATURE_STATUS_UNKNOWN
;
547 aSuggestedDriverVersion
.SetIsVoid(true);
548 OperatingSystem os
= OperatingSystem::Linux
;
551 if (sShutdownOccurred
) {
557 if (mGLMajorVersion
== 0) {
558 // If we failed to get a GL version, glxtest failed.
559 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
560 aFailureId
= "FEATURE_FAILURE_GLXTEST_FAILED";
564 if (mGLMajorVersion
== 1) {
565 // We're on OpenGL 1. In most cases that indicates really old hardware.
566 // We better block them, rather than rely on them to fail gracefully,
567 // because they don't! see bug 696636
568 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
569 aFailureId
= "FEATURE_FAILURE_OPENGL_1";
573 // Blacklist software GL implementations from using layers acceleration.
574 // On the test infrastructure, we'll force-enable layers acceleration.
575 if (aFeature
== nsIGfxInfo::FEATURE_OPENGL_LAYERS
&& !mIsAccelerated
&&
576 !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) {
577 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
578 aFailureId
= "FEATURE_FAILURE_SOFTWARE_GL";
582 return GfxInfoBase::GetFeatureStatusImpl(
583 aFeature
, aStatus
, aSuggestedDriverVersion
, aDriverInfo
, aFailureId
, &os
);
587 GfxInfo::GetD2DEnabled(bool* aEnabled
) { return NS_ERROR_FAILURE
; }
590 GfxInfo::GetDWriteEnabled(bool* aEnabled
) { return NS_ERROR_FAILURE
; }
593 GfxInfo::GetDWriteVersion(nsAString
& aDwriteVersion
) {
594 return NS_ERROR_FAILURE
;
597 NS_IMETHODIMP
GfxInfo::GetHasBattery(bool* aHasBattery
) {
598 return NS_ERROR_NOT_IMPLEMENTED
;
602 GfxInfo::GetCleartypeParameters(nsAString
& aCleartypeParams
) {
603 return NS_ERROR_FAILURE
;
607 GfxInfo::GetWindowProtocol(nsAString
& aWindowProtocol
) {
612 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandDRM
);
615 GfxDriverInfo::GetWindowProtocol(WindowProtocol::Wayland
);
620 aWindowProtocol
= GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11
);
625 GfxInfo::GetDesktopEnvironment(nsAString
& aDesktopEnvironment
) {
627 AppendASCIItoUTF16(mDesktopEnvironment
, aDesktopEnvironment
);
632 GfxInfo::GetAdapterDescription(nsAString
& aAdapterDescription
) {
634 AppendASCIItoUTF16(mAdapterDescription
, aAdapterDescription
);
639 GfxInfo::GetAdapterDescription2(nsAString
& aAdapterDescription
) {
640 return NS_ERROR_FAILURE
;
644 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM
) {
646 *aAdapterRAM
= mAdapterRAM
;
651 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM
) { return NS_ERROR_FAILURE
; }
654 GfxInfo::GetAdapterDriver(nsAString
& aAdapterDriver
) {
655 aAdapterDriver
.Truncate();
660 GfxInfo::GetAdapterDriver2(nsAString
& aAdapterDriver
) {
661 return NS_ERROR_FAILURE
;
665 GfxInfo::GetAdapterDriverVendor(nsAString
& aAdapterDriverVendor
) {
667 CopyASCIItoUTF16(mDriverVendor
, aAdapterDriverVendor
);
672 GfxInfo::GetAdapterDriverVendor2(nsAString
& aAdapterDriverVendor
) {
673 return NS_ERROR_FAILURE
;
677 GfxInfo::GetAdapterDriverVersion(nsAString
& aAdapterDriverVersion
) {
679 CopyASCIItoUTF16(mDriverVersion
, aAdapterDriverVersion
);
684 GfxInfo::GetAdapterDriverVersion2(nsAString
& aAdapterDriverVersion
) {
685 return NS_ERROR_FAILURE
;
689 GfxInfo::GetAdapterDriverDate(nsAString
& aAdapterDriverDate
) {
690 aAdapterDriverDate
.Truncate();
695 GfxInfo::GetAdapterDriverDate2(nsAString
& aAdapterDriverDate
) {
696 return NS_ERROR_FAILURE
;
700 GfxInfo::GetAdapterVendorID(nsAString
& aAdapterVendorID
) {
702 CopyUTF8toUTF16(mVendorId
, aAdapterVendorID
);
707 GfxInfo::GetAdapterVendorID2(nsAString
& aAdapterVendorID
) {
708 return NS_ERROR_FAILURE
;
712 GfxInfo::GetAdapterDeviceID(nsAString
& aAdapterDeviceID
) {
714 CopyUTF8toUTF16(mDeviceId
, aAdapterDeviceID
);
719 GfxInfo::GetAdapterDeviceID2(nsAString
& aAdapterDeviceID
) {
720 return NS_ERROR_FAILURE
;
724 GfxInfo::GetAdapterSubsysID(nsAString
& aAdapterSubsysID
) {
725 return NS_ERROR_FAILURE
;
729 GfxInfo::GetAdapterSubsysID2(nsAString
& aAdapterSubsysID
) {
730 return NS_ERROR_FAILURE
;
734 GfxInfo::GetDisplayInfo(nsTArray
<nsString
>& aDisplayInfo
) {
737 for (auto screenInfo
: mScreenInfo
) {
739 infoString
.AppendPrintf("%dx%d %s", screenInfo
.mWidth
, screenInfo
.mHeight
,
740 screenInfo
.mIsDefault
? "default" : "");
741 aDisplayInfo
.AppendElement(infoString
);
744 return aDisplayInfo
.IsEmpty() ? NS_ERROR_FAILURE
: NS_OK
;
748 GfxInfo::GetDisplayWidth(nsTArray
<uint32_t>& aDisplayWidth
) {
749 for (auto screenInfo
: mScreenInfo
) {
750 aDisplayWidth
.AppendElement((uint32_t)screenInfo
.mWidth
);
756 GfxInfo::GetDisplayHeight(nsTArray
<uint32_t>& aDisplayHeight
) {
757 for (auto screenInfo
: mScreenInfo
) {
758 aDisplayHeight
.AppendElement((uint32_t)screenInfo
.mHeight
);
764 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active
) { return NS_ERROR_FAILURE
; }
768 // Implement nsIGfxInfoDebug
769 // We don't support spoofing anything on Linux
771 NS_IMETHODIMP
GfxInfo::SpoofVendorID(const nsAString
& aVendorID
) {
773 CopyUTF16toUTF8(aVendorID
, mVendorId
);
774 mIsAccelerated
= true;
778 NS_IMETHODIMP
GfxInfo::SpoofDeviceID(const nsAString
& aDeviceID
) {
780 CopyUTF16toUTF8(aDeviceID
, mDeviceId
);
784 NS_IMETHODIMP
GfxInfo::SpoofDriverVersion(const nsAString
& aDriverVersion
) {
786 CopyUTF16toUTF8(aDriverVersion
, mDriverVersion
);
790 NS_IMETHODIMP
GfxInfo::SpoofOSVersion(uint32_t aVersion
) {
791 // We don't support OS versioning on Linux. There's just "Linux".
795 NS_IMETHODIMP
GfxInfo::FireTestProcess() {
796 // If the pid is zero, then we have never run the test process to query for
797 // driver information. This would normally be run on startup, but we need to
798 // manually invoke it for XPC shell tests.
799 if (glxtest_pid
== 0) {
800 fire_glxtest_process();
807 } // namespace mozilla::widget