Bug 1613552 [wpt PR 21618] - Fix timeout vs. task-queue race conditions in promise...
[gecko.git] / widget / GfxInfoX11.cpp
blobeab520a849a9771fbde03e0a6212a125c45ffb17
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 "prenv.h"
18 #include "nsPrintfCString.h"
19 #include "nsWhitespaceTokenizer.h"
21 #include "GfxInfoX11.h"
23 #include <gdk/gdkx.h>
24 #ifdef MOZ_WAYLAND
25 # include "mozilla/widget/nsWaylandDisplay.h"
26 #endif
28 #ifdef DEBUG
29 bool fire_glxtest_process();
30 #endif
32 namespace mozilla::widget {
34 #ifdef DEBUG
35 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
36 #endif
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() {
43 mGLMajorVersion = 0;
44 mGLMinorVersion = 0;
45 mHasTextureFromPixmap = false;
46 mIsMesa = false;
47 mIsAccelerated = true;
48 mIsWayland = false;
49 mIsWaylandDRM = false;
50 return GfxInfoBase::Init();
53 void GfxInfo::AddCrashReportAnnotations() {
54 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID,
55 mVendorId);
56 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID,
57 mDeviceId);
58 CrashReporter::AnnotateCrashReport(
59 CrashReporter::Annotation::AdapterDriverVendor, mDriverVendor);
60 CrashReporter::AnnotateCrashReport(
61 CrashReporter::Annotation::AdapterDriverVersion, mDriverVersion);
62 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWayland,
63 mIsWayland);
64 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::IsWaylandDRM,
65 mIsWaylandDRM);
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 };
80 char buf[buf_size];
81 ssize_t bytesread = read(glxtest_pipe, &buf,
82 buf_size - 1); // -1 because we'll append a zero
83 close(glxtest_pipe);
84 glxtest_pipe = -1;
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
88 // anyway.
89 if (bytesread < 0) bytesread = 0;
91 // let buf be a zero-terminated string
92 buf[bytesread] = 0;
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;
107 } else {
108 // Bug 718629
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 ||
125 received_signal;
127 nsCString glVendor;
128 nsCString glRenderer;
129 nsCString glVersion;
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.
137 nsCString driDriver;
138 nsCString screenInfo;
139 nsCString adapterRam;
141 nsCString* stringToFill = nullptr;
143 char* bufptr = buf;
144 if (!error) {
145 while (true) {
146 char* line = NS_strtok("\n", &bufptr);
147 if (!line) break;
148 if (stringToFill) {
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,
201 glxtest_pid);
202 if (exited_with_error_code)
203 mAdapterDescription.AppendPrintf(" (exited with status %d)",
204 WEXITSTATUS(glxtest_status));
205 if (received_signal)
206 mAdapterDescription.AppendPrintf(" (received signal %d)",
207 WTERMSIG(glxtest_status));
208 if (bytesread) {
209 mAdapterDescription.AppendLiteral(": ");
210 mAdapterDescription.Append(nsDependentCString(buf));
211 mAdapterDescription.Append('\n');
214 CrashReporter::AppendAppNotesToCrashReport(mAdapterDescription);
215 return;
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) >=
224 2) {
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.
231 mDriverVersion =
232 nsPrintfCString("%u.%u.%u.%u", major, minor, revision, patch);
237 if (mGLMajorVersion == 0) {
238 NS_WARNING("Failed to parse GL version!");
239 return;
242 // Mesa always exposes itself in the GL_VERSION string, but not always the
243 // GL_VENDOR string.
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.
248 if (mIsMesa) {
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")) {
254 CopyUTF16toUTF8(
255 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaLLVMPipe),
256 mDriverVendor);
257 mIsAccelerated = false;
258 } else if (strcasestr(glRenderer.get(), "softpipe")) {
259 CopyUTF16toUTF8(
260 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaSoftPipe),
261 mDriverVendor);
262 mIsAccelerated = false;
263 } else if (strcasestr(glRenderer.get(), "software rasterizer") ||
264 !mIsAccelerated) {
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),
268 mDriverVendor);
269 mIsAccelerated = false;
270 } else if (!driDriver.IsEmpty()) {
271 mDriverVendor = nsPrintfCString("mesa/%s", driDriver.get());
272 } else {
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),
276 mDriverVendor);
279 if (!mesaVendor.IsEmpty()) {
280 mVendorId = mesaVendor;
281 } else {
282 NS_WARNING(
283 "Failed to get Mesa vendor ID! GLX_MESA_query_renderer unsupported?");
286 if (!mesaDevice.IsEmpty()) {
287 mDeviceId = mesaDevice;
288 } else {
289 NS_WARNING(
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),
294 mVendorId);
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),
299 mVendorId);
300 mDriverVendor.AssignLiteral("ati/unknown");
301 // TODO: Look into ways to find the device ID on FGLRX.
302 } else {
303 NS_WARNING("Failed to detect GL vendor!");
306 if (!screenInfo.IsEmpty()) {
307 PRInt32 start = 0;
308 PRInt32 loc = screenInfo.Find(";", PR_FALSE, start);
309 while (loc != kNotFound) {
310 int isDefault = 0;
311 nsCString line(screenInfo.get() + start, loc - start);
312 ScreenInfo info;
313 if (sscanf(line.get(), "%ux%u:%u", &info.mWidth, &info.mHeight,
314 &isDefault) == 3) {
315 info.mIsDefault = isDefault != 0;
316 mScreenInfo.AppendElement(info);
319 start = loc + 1;
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);
337 #ifdef MOZ_WAYLAND
338 mIsWayland = !GDK_IS_X11_DISPLAY(gdk_display_get_default());
339 if (mIsWayland) {
340 mIsWaylandDRM = nsWaylandDisplay::IsDMABufEnabled();
342 #endif
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");
348 if (!desktopEnv) {
349 desktopEnv = getenv("DESKTOP_SESSION");
352 if (desktopEnv) {
353 std::string currentDesktop(desktopEnv);
354 for (auto& c : currentDesktop) {
355 c = std::tolower(c);
358 if (currentDesktop.find("gnome") != std::string::npos) {
359 CopyUTF16toUTF8(
360 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
361 mDesktopEnvironment);
362 } else if (currentDesktop.find("kde") != std::string::npos) {
363 CopyUTF16toUTF8(
364 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
365 mDesktopEnvironment);
366 } else if (currentDesktop.find("xfce") != std::string::npos) {
367 CopyUTF16toUTF8(
368 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::XFCE),
369 mDesktopEnvironment);
370 } else if (currentDesktop.find("cinnamon") != std::string::npos) {
371 CopyUTF16toUTF8(
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) {
380 CopyUTF16toUTF8(
381 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXDE),
382 mDesktopEnvironment);
383 } else if (currentDesktop.find("openbox") != std::string::npos) {
384 CopyUTF16toUTF8(
385 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Openbox),
386 mDesktopEnvironment);
387 } else if (currentDesktop.find("i3") != std::string::npos) {
388 CopyUTF16toUTF8(
389 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::i3),
390 mDesktopEnvironment);
391 } else if (currentDesktop.find("mate") != std::string::npos) {
392 CopyUTF16toUTF8(
393 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
394 mDesktopEnvironment);
395 } else if (currentDesktop.find("unity") != std::string::npos) {
396 CopyUTF16toUTF8(
397 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Unity),
398 mDesktopEnvironment);
399 } else if (currentDesktop.find("pantheon") != std::string::npos) {
400 CopyUTF16toUTF8(
401 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Pantheon),
402 mDesktopEnvironment);
403 } else if (currentDesktop.find("lxqt") != std::string::npos) {
404 CopyUTF16toUTF8(
405 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
406 mDesktopEnvironment);
407 } else if (currentDesktop.find("deepin") != std::string::npos) {
408 CopyUTF16toUTF8(
409 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Deepin),
410 mDesktopEnvironment);
414 if (mDesktopEnvironment.IsEmpty()) {
415 if (getenv("GNOME_DESKTOP_SESSION_ID")) {
416 CopyUTF16toUTF8(
417 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::GNOME),
418 mDesktopEnvironment);
419 } else if (getenv("KDE_FULL_SESSION")) {
420 CopyUTF16toUTF8(
421 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::KDE),
422 mDesktopEnvironment);
423 } else if (getenv("MATE_DESKTOP_SESSION_ID")) {
424 CopyUTF16toUTF8(
425 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::Mate),
426 mDesktopEnvironment);
427 } else if (getenv("LXQT_SESSION_CONFIG")) {
428 CopyUTF16toUTF8(
429 GfxDriverInfo::GetDesktopEnvironment(DesktopEnvironment::LXQT),
430 mDesktopEnvironment);
431 } else {
432 CopyUTF16toUTF8(
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 ////////////////////////////////////
468 // FEATURE_WEBRENDER
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", "");
509 return *sDriverInfo;
512 bool GfxInfo::DoesWindowProtocolMatch(const nsAString& aBlocklistWindowProtocol,
513 const nsAString& aWindowProtocol) {
514 if (mIsWayland &&
515 aBlocklistWindowProtocol.Equals(
516 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandAll),
517 nsCaseInsensitiveStringComparator())) {
518 return true;
520 return GfxInfoBase::DoesWindowProtocolMatch(aBlocklistWindowProtocol,
521 aWindowProtocol);
524 bool GfxInfo::DoesDriverVendorMatch(const nsAString& aBlocklistVendor,
525 const nsAString& aDriverVendor) {
526 if (mIsMesa && aBlocklistVendor.Equals(
527 GfxDriverInfo::GetDriverVendor(DriverVendor::MesaAll),
528 nsCaseInsensitiveStringComparator())) {
529 return true;
531 if (!mIsMesa && aBlocklistVendor.Equals(
532 GfxDriverInfo::GetDriverVendor(DriverVendor::NonMesaAll),
533 nsCaseInsensitiveStringComparator())) {
534 return true;
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;
549 if (aOS) *aOS = os;
551 if (sShutdownOccurred) {
552 return NS_OK;
555 GetData();
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";
561 return NS_OK;
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";
570 return NS_OK;
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";
579 return NS_OK;
582 return GfxInfoBase::GetFeatureStatusImpl(
583 aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
586 NS_IMETHODIMP
587 GfxInfo::GetD2DEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
589 NS_IMETHODIMP
590 GfxInfo::GetDWriteEnabled(bool* aEnabled) { return NS_ERROR_FAILURE; }
592 NS_IMETHODIMP
593 GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) {
594 return NS_ERROR_FAILURE;
597 NS_IMETHODIMP GfxInfo::GetHasBattery(bool* aHasBattery) {
598 return NS_ERROR_NOT_IMPLEMENTED;
601 NS_IMETHODIMP
602 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) {
603 return NS_ERROR_FAILURE;
606 NS_IMETHODIMP
607 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
608 GetData();
609 if (mIsWayland) {
610 if (mIsWaylandDRM) {
611 aWindowProtocol =
612 GfxDriverInfo::GetWindowProtocol(WindowProtocol::WaylandDRM);
613 } else {
614 aWindowProtocol =
615 GfxDriverInfo::GetWindowProtocol(WindowProtocol::Wayland);
617 return NS_OK;
620 aWindowProtocol = GfxDriverInfo::GetWindowProtocol(WindowProtocol::X11);
621 return NS_OK;
624 NS_IMETHODIMP
625 GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
626 GetData();
627 AppendASCIItoUTF16(mDesktopEnvironment, aDesktopEnvironment);
628 return NS_OK;
631 NS_IMETHODIMP
632 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
633 GetData();
634 AppendASCIItoUTF16(mAdapterDescription, aAdapterDescription);
635 return NS_OK;
638 NS_IMETHODIMP
639 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
640 return NS_ERROR_FAILURE;
643 NS_IMETHODIMP
644 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM) {
645 GetData();
646 *aAdapterRAM = mAdapterRAM;
647 return NS_OK;
650 NS_IMETHODIMP
651 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM) { return NS_ERROR_FAILURE; }
653 NS_IMETHODIMP
654 GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) {
655 aAdapterDriver.Truncate();
656 return NS_OK;
659 NS_IMETHODIMP
660 GfxInfo::GetAdapterDriver2(nsAString& aAdapterDriver) {
661 return NS_ERROR_FAILURE;
664 NS_IMETHODIMP
665 GfxInfo::GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) {
666 GetData();
667 CopyASCIItoUTF16(mDriverVendor, aAdapterDriverVendor);
668 return NS_OK;
671 NS_IMETHODIMP
672 GfxInfo::GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor) {
673 return NS_ERROR_FAILURE;
676 NS_IMETHODIMP
677 GfxInfo::GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) {
678 GetData();
679 CopyASCIItoUTF16(mDriverVersion, aAdapterDriverVersion);
680 return NS_OK;
683 NS_IMETHODIMP
684 GfxInfo::GetAdapterDriverVersion2(nsAString& aAdapterDriverVersion) {
685 return NS_ERROR_FAILURE;
688 NS_IMETHODIMP
689 GfxInfo::GetAdapterDriverDate(nsAString& aAdapterDriverDate) {
690 aAdapterDriverDate.Truncate();
691 return NS_OK;
694 NS_IMETHODIMP
695 GfxInfo::GetAdapterDriverDate2(nsAString& aAdapterDriverDate) {
696 return NS_ERROR_FAILURE;
699 NS_IMETHODIMP
700 GfxInfo::GetAdapterVendorID(nsAString& aAdapterVendorID) {
701 GetData();
702 CopyUTF8toUTF16(mVendorId, aAdapterVendorID);
703 return NS_OK;
706 NS_IMETHODIMP
707 GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) {
708 return NS_ERROR_FAILURE;
711 NS_IMETHODIMP
712 GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) {
713 GetData();
714 CopyUTF8toUTF16(mDeviceId, aAdapterDeviceID);
715 return NS_OK;
718 NS_IMETHODIMP
719 GfxInfo::GetAdapterDeviceID2(nsAString& aAdapterDeviceID) {
720 return NS_ERROR_FAILURE;
723 NS_IMETHODIMP
724 GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) {
725 return NS_ERROR_FAILURE;
728 NS_IMETHODIMP
729 GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
730 return NS_ERROR_FAILURE;
733 NS_IMETHODIMP
734 GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
735 GetData();
737 for (auto screenInfo : mScreenInfo) {
738 nsString infoString;
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;
747 NS_IMETHODIMP
748 GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
749 for (auto screenInfo : mScreenInfo) {
750 aDisplayWidth.AppendElement((uint32_t)screenInfo.mWidth);
752 return NS_OK;
755 NS_IMETHODIMP
756 GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
757 for (auto screenInfo : mScreenInfo) {
758 aDisplayHeight.AppendElement((uint32_t)screenInfo.mHeight);
760 return NS_OK;
763 NS_IMETHODIMP
764 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) { return NS_ERROR_FAILURE; }
766 #ifdef DEBUG
768 // Implement nsIGfxInfoDebug
769 // We don't support spoofing anything on Linux
771 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString& aVendorID) {
772 GetData();
773 CopyUTF16toUTF8(aVendorID, mVendorId);
774 mIsAccelerated = true;
775 return NS_OK;
778 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString& aDeviceID) {
779 GetData();
780 CopyUTF16toUTF8(aDeviceID, mDeviceId);
781 return NS_OK;
784 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString& aDriverVersion) {
785 GetData();
786 CopyUTF16toUTF8(aDriverVersion, mDriverVersion);
787 return NS_OK;
790 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
791 // We don't support OS versioning on Linux. There's just "Linux".
792 return NS_OK;
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();
802 return NS_OK;
805 #endif
807 } // namespace mozilla::widget